diff --git a/include/eepp/system/translator.hpp b/include/eepp/system/translator.hpp index c16c7acf6..67c119e94 100644 --- a/include/eepp/system/translator.hpp +++ b/include/eepp/system/translator.hpp @@ -43,8 +43,8 @@ class EE_API Translator { void setCurrentLanguage( const std::string& currentLanguage ); protected: - typedef std::map StringDictionary; - typedef std::map StringLocaleDictionary; + typedef std::unordered_map StringDictionary; + typedef std::unordered_map StringLocaleDictionary; std::string mDefaultLanguage; std::string mCurrentLanguage; diff --git a/include/eepp/ui/tools/uicodeeditorsplitter.hpp b/include/eepp/ui/tools/uicodeeditorsplitter.hpp index 74004f1cb..c8076ab4e 100644 --- a/include/eepp/ui/tools/uicodeeditorsplitter.hpp +++ b/include/eepp/ui/tools/uicodeeditorsplitter.hpp @@ -85,6 +85,9 @@ class EE_API UICodeEditorSplitter { const std::string& tabName, bool focus = true ); + std::pair createWidget( UIWidget* widget, const std::string& tabName, + bool focus = true ); + std::vector> getTabFromOwnedWidgetId( const std::string& id ); bool removeTabWithOwnedWidgetId( const std::string& id, bool destroyOwnedNode = true, diff --git a/include/eepp/ui/uidatabind.hpp b/include/eepp/ui/uidatabind.hpp index 9ca532172..8c3e2205e 100644 --- a/include/eepp/ui/uidatabind.hpp +++ b/include/eepp/ui/uidatabind.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace EE { namespace UI { @@ -29,6 +30,18 @@ template class UIDataBind { } ); } + static Converter converterString() { + return Converter( + []( const UIDataBind*, T& val, const std::string& str ) { + val = str; + return true; + }, + []( const UIDataBind*, std::string& str, const T& val ) { + str = val; + return true; + } ); + } + static Converter converterBool() { return Converter( []( const UIDataBind* databind, T& val, const std::string& str ) -> bool { @@ -44,39 +57,45 @@ template class UIDataBind { static std::unique_ptr> New( T* t, const std::set& widgets, const Converter& converter = UIDataBind::converterDefault(), - const std::string& valueKey = "value" ) { + const std::string& valueKey = "value", + const Event::EventType& eventType = Event::OnValueChange ) { return std::unique_ptr>( - new UIDataBind( t, widgets, converter, valueKey ) ); + new UIDataBind( t, widgets, converter, valueKey, eventType ) ); } static std::unique_ptr> New( T* t, UIWidget* widget, const Converter& converter = UIDataBind::converterDefault(), - const std::string& valueKey = "value" ) { + const std::string& valueKey = "value", + const Event::EventType& eventType = Event::OnValueChange ) { return std::unique_ptr>( - new UIDataBind( t, widget, converter, valueKey ) ); + new UIDataBind( t, widget, converter, valueKey, eventType ) ); } UIDataBind() {} UIDataBind( T* t, const std::set& widgets, const Converter& converter = UIDataBind::converterDefault(), - const std::string& valueKey = "value" ) { - init( t, widgets, converter, valueKey ); + const std::string& valueKey = "value", + const Event::EventType& eventType = Event::OnValueChange ) { + init( t, widgets, converter, valueKey, eventType ); } UIDataBind( T* t, UIWidget* widget, const Converter& converter = UIDataBind::converterDefault(), - const std::string& valueKey = "value" ) { - init( t, { widget }, converter, valueKey ); + const std::string& valueKey = "value", + const Event::EventType& eventType = Event::OnValueChange ) { + init( t, { widget }, converter, valueKey, eventType ); } void init( T* t, const std::set& widgets, const Converter& converter = UIDataBind::converterDefault(), - const std::string& valueKey = "value" ) { + const std::string& valueKey = "value", + const Event::EventType& eventType = Event::OnValueChange ) { data = t; this->widgets = widgets; this->property = StyleSheetSpecification::instance()->getProperty( valueKey ); this->converter = converter; + this->eventType = eventType; for ( auto widget : widgets ) bindListeners( widget ); set( *data ); @@ -134,17 +153,17 @@ template class UIDataBind { protected: T* data{ nullptr }; std::set widgets; - std::map valueCbs; - std::map closeCbs; + std::unordered_map valueCbs; + std::unordered_map closeCbs; bool inSetValue{ false }; const PropertyDefinition* property{ nullptr }; Converter converter; + Event::EventType eventType{ Event::OnValueChange }; void bindListeners( UIWidget* widget ) { - valueCbs[widget] = - widget->addEventListener( Event::OnValueChange, [this]( const Event* event ) { - processValueChange( event->getNode()->asType() ); - } ); + valueCbs[widget] = widget->addEventListener( eventType, [this]( const Event* event ) { + processValueChange( event->getNode()->asType() ); + } ); closeCbs[widget] = widget->addEventListener( Event::OnClose, [this]( const Event* event ) { closeCbs.erase( event->getNode()->asType() ); this->widgets.erase( event->getNode()->asType() ); @@ -190,14 +209,16 @@ template class UIDataBind { class UIDataBindBool { public: - static std::unique_ptr> + using Ptr = std::unique_ptr>; + + static Ptr New( bool* t, const std::set& widgets, const UIDataBind::Converter& converter = UIDataBind::converterBool(), const std::string& valueKey = "value" ) { return UIDataBind::New( t, widgets, converter, valueKey ); } - static std::unique_ptr> + static Ptr New( bool* t, UIWidget* widget, const UIDataBind::Converter& converter = UIDataBind::converterBool(), const std::string& valueKey = "value" ) { @@ -205,6 +226,51 @@ class UIDataBindBool { } }; +class UIDataBindString { + public: + using Ptr = std::unique_ptr>; + + static Ptr New( std::string* t, const std::set& widgets, + const UIDataBind::Converter& converter = + UIDataBind::converterString(), + const std::string& valueKey = "text", + const Event::EventType& eventType = Event::OnTextChanged ) { + return UIDataBind::New( t, widgets, converter, valueKey, eventType ); + } + + static Ptr New( std::string* t, UIWidget* widget, + const UIDataBind::Converter& converter = + UIDataBind::converterString(), + const std::string& valueKey = "text", + const Event::EventType& eventType = Event::OnTextChanged ) { + return UIDataBind::New( t, widget, converter, valueKey, eventType ); + } +}; + +class UIDataBindHolder { + public: + using UIDataBindVariant = + std::variant, + UIDataBind, UIDataBind, UIDataBind, UIDataBind, + UIDataBind, UIDataBind, UIDataBind, UIDataBind, + UIDataBind>; + + UIDataBindHolder& hold( UIDataBindVariant&& ptr ) { + mHolder.emplace_back( std::move( ptr ) ); + return *this; + } + + UIDataBindHolder& operator+=( UIDataBindVariant&& ptr ) { + mHolder.emplace_back( std::move( ptr ) ); + return *this; + } + + void clear() { mHolder.clear(); } + + protected: + std::vector mHolder; +}; + }} // namespace EE::UI #endif // EE_UI_UIDATABIND_HPP diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 9152ddbb6..1da1fdb14 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1214,6 +1214,8 @@ ../../src/tools/ecode/statusterminalcontroller.hpp ../../src/tools/ecode/terminalmanager.cpp ../../src/tools/ecode/terminalmanager.hpp +../../src/tools/ecode/uibuildsettings.cpp +../../src/tools/ecode/uibuildsettings.hpp ../../src/tools/ecode/uicodeeditorsplitter.cpp ../../src/tools/ecode/uicodeeditorsplitter.hpp ../../src/tools/ecode/uistatusbar.cpp diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 54d664ecd..5c5f111d4 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -199,7 +199,10 @@ void UIAbstractTableView::createOrUpdateColumns( bool resetColumnData ) { } mHeader->setPixelsSize( totalWidth, getHeaderHeight() ); + bool visible = mHeader->isVisible(); + mHeader->setVisible( true ); mHeader->updateLayout(); + mHeader->setVisible( visible ); updateColumnsWidth(); } diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index 3896d20b5..1cc6ff127 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -465,6 +465,26 @@ UICodeEditorSplitter::createCodeEditorInTabWidget( UITabWidget* tabWidget ) { return std::make_pair( tab, editor ); } +std::pair +UICodeEditorSplitter::createWidget( UIWidget* widget, const std::string& tabName, bool focus ) { + UITabWidget* tabWidget = nullptr; + + UIWidget* curWidget = getCurWidget(); + if ( !curWidget ) + return std::make_pair( (UITab*)nullptr, (UIWidget*)nullptr ); + tabWidget = tabWidgetFromWidget( curWidget ); + + if ( !tabWidget ) { + if ( !getTabWidgets().empty() ) { + tabWidget = getTabWidgets()[0]; + } else { + return std::make_pair( (UITab*)nullptr, (UIWidget*)nullptr ); + } + } + + return createWidgetInTabWidget( tabWidget, widget, tabName, focus ); +} + std::pair UICodeEditorSplitter::createWidgetInTabWidget( UITabWidget* tabWidget, UIWidget* widget, const std::string& tabName, bool focus ) { diff --git a/src/eepp/ui/uigridlayout.cpp b/src/eepp/ui/uigridlayout.cpp index b600a3ac6..e1340d2c4 100644 --- a/src/eepp/ui/uigridlayout.cpp +++ b/src/eepp/ui/uigridlayout.cpp @@ -110,6 +110,15 @@ void UIGridLayout::updateLayout() { if ( mPacking ) return; mPacking = true; + + if ( !mVisible ) { + setInternalPixelsSize( Sizef::Zero ); + notifyLayoutAttrChangeParent(); + mPacking = false; + mDirtyLayout = false; + return; + } + Sizef oldSize( getSize() ); if ( getParent()->isUINode() && diff --git a/src/eepp/ui/uilinearlayout.cpp b/src/eepp/ui/uilinearlayout.cpp index c844847ea..fc6325c6d 100644 --- a/src/eepp/ui/uilinearlayout.cpp +++ b/src/eepp/ui/uilinearlayout.cpp @@ -51,10 +51,19 @@ UILinearLayout* UILinearLayout::setOrientation( const UIOrientation& orientation } void UILinearLayout::updateLayout() { - if ( mOrientation == UIOrientation::Vertical ) - packVertical(); - else - packHorizontal(); + if ( !mVisible ) { + if ( mPacking ) + return; + mPacking = true; + setInternalPixelsSize( Sizef::Zero ); + notifyLayoutAttrChangeParent(); + mPacking = false; + } else { + if ( mOrientation == UIOrientation::Vertical ) + packVertical(); + else + packHorizontal(); + } mDirtyLayout = false; } @@ -206,9 +215,10 @@ void UILinearLayout::packVertical() { ? getPixelsSize().getHeight() - mPaddingPx.Top - mPaddingPx.Bottom : getParent()->getPixelsSize().getHeight() - mLayoutMarginPx.Bottom - mLayoutMarginPx.Top - mPaddingPx.Top - mPaddingPx.Bottom; - Float size = (Float)( totSize - freeSize.getHeight() ) * widget->getLayoutWeight(); + Float newSize = + eeceil( totSize - freeSize.getHeight() ) * widget->getLayoutWeight(); - widget->setPixelsSize( widget->getPixelsSize().getWidth(), (Int32)size ); + widget->setPixelsSize( widget->getPixelsSize().getWidth(), newSize ); } switch ( Font::getHorizontalAlign( widget->getLayoutGravity() ) ) { @@ -333,9 +343,9 @@ void UILinearLayout::packHorizontal() { ? getPixelsSize().getWidth() - mPaddingPx.Left - mPaddingPx.Right : getParent()->getPixelsSize().getWidth() - mLayoutMarginPx.Right - mLayoutMarginPx.Left - mPaddingPx.Left - mPaddingPx.Right; - Float size = (Float)( totSize - freeSize.getWidth() ) * widget->getLayoutWeight(); + Float newSize = eeceil( totSize - freeSize.getWidth() ) * widget->getLayoutWeight(); - widget->setPixelsSize( (Int32)size, widget->getPixelsSize().getHeight() ); + widget->setPixelsSize( newSize, widget->getPixelsSize().getHeight() ); } switch ( Font::getVerticalAlign( widget->getLayoutGravity() ) ) { diff --git a/src/eepp/ui/uirelativelayout.cpp b/src/eepp/ui/uirelativelayout.cpp index 6f944a898..6e839361f 100644 --- a/src/eepp/ui/uirelativelayout.cpp +++ b/src/eepp/ui/uirelativelayout.cpp @@ -33,28 +33,34 @@ void UIRelativeLayout::updateLayout() { return; mPacking = true; - if ( getParent()->isUINode() && - ( !getParent()->asType()->ownsChildPosition() || isGravityOwner() ) ) { - setInternalPosition( Vector2f( mLayoutMargin.Left, mLayoutMargin.Top ) ); - } + if ( !mVisible ) { + setInternalPixelsSize( Sizef::Zero ); + notifyLayoutAttrChangeParent(); + } else { - Sizef s( getSizeFromLayoutPolicy() ); - - if ( s != getPixelsSize() ) - setInternalPixelsSize( s ); - - Node* child = mChild; - - while ( NULL != child ) { - if ( child->isWidget() ) { - UIWidget* widget = static_cast( child ); - - fixChildSize( widget ); - - fixChildPos( widget ); + if ( getParent()->isUINode() && + ( !getParent()->asType()->ownsChildPosition() || isGravityOwner() ) ) { + setInternalPosition( Vector2f( mLayoutMargin.Left, mLayoutMargin.Top ) ); } - child = child->getNextNode(); + Sizef s( getSizeFromLayoutPolicy() ); + + if ( s != getPixelsSize() ) + setInternalPixelsSize( s ); + + Node* child = mChild; + + while ( NULL != child ) { + if ( child->isWidget() ) { + UIWidget* widget = static_cast( child ); + + fixChildSize( widget ); + + fixChildPos( widget ); + } + + child = child->getNextNode(); + } } mDirtyLayout = false; diff --git a/src/eepp/ui/uistacklayout.cpp b/src/eepp/ui/uistacklayout.cpp index a381f8534..c8a0e71ac 100644 --- a/src/eepp/ui/uistacklayout.cpp +++ b/src/eepp/ui/uistacklayout.cpp @@ -199,6 +199,14 @@ void UIStackLayout::updateLayout() { return; mPacking = true; + if ( !mVisible ) { + setInternalPixelsSize( Sizef::Zero ); + notifyLayoutAttrChangeParent(); + mPacking = false; + mDirtyLayout = false; + return; + } + Sizef size( getSizeFromLayoutPolicy() ); if ( getLayoutWidthPolicy() == SizePolicy::WrapContent ) diff --git a/src/eepp/ui/uitouchdraggablewidget.cpp b/src/eepp/ui/uitouchdraggablewidget.cpp index 4615f4852..6e9b3d2fc 100644 --- a/src/eepp/ui/uitouchdraggablewidget.cpp +++ b/src/eepp/ui/uitouchdraggablewidget.cpp @@ -131,13 +131,14 @@ void UITouchDraggableWidget::scheduledUpdate( const Time& time ) { Uint32 UITouchDraggableWidget::onMessage( const NodeMessage* msg ) { if ( msg->getMsg() == NodeMessage::MouseDown && ( msg->getFlags() & EE_BUTTON_LMASK ) && !isTouchDragging() && isTouchOverAllowedChilds() && - !getEventDispatcher()->isNodeDragging() ) { + !getEventDispatcher()->isNodeDragging() && isTouchDragEnabled() ) { setTouchDragging( true ); getEventDispatcher()->setNodeDragging( this ); mTouchDragPoint = getEventDispatcher()->getMousePosf(); mTouchDragAcceleration = Vector2f( 0, 0 ); return 1; - } else if ( msg->getMsg() == NodeMessage::MouseUp && ( msg->getFlags() & EE_BUTTON_LMASK ) && isTouchDragging() && isTouchOverAllowedChilds() ) { + } else if ( msg->getMsg() == NodeMessage::MouseUp && ( msg->getFlags() & EE_BUTTON_LMASK ) && + isTouchDragging() && isTouchOverAllowedChilds() ) { setTouchDragging( false ); getEventDispatcher()->setNodeDragging( nullptr ); return 1; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 6b804b42d..1d79d694d 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -3278,6 +3278,142 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe #status_bar > TextView.selected { background-color: var(--primary); } + .settings_panel { + padding: 4dp; + } + .settings_panel .title { + font-size:17dp; + } + .settings_panel .subtitle { + font-size:15dp; + margin-top: 12dp; + } + .settings_panel > .subtitle { + margin-top: 4dp; + } + .settings_panel .advance_opt { + font-size:15dp; + } + .settings_panel .separator { + margin-top: 4dp; + background-color: var(--font-hint); + } + .settings_panel PushButton { + padding-top: 2dp; + padding-bottom: 2dp; + } + .settings_panel .build_step, + .settings_panel .os_select { + background-color: var(--list-back); + border-width: 1dp; + border-color: var(--button-border); + padding: 4dp; + margin-top: 4dp; + } + .settings_panel .build_step > LinearLayout > LinearLayout { + margin-bottom: 3dp; + } + .settings_panel .build_step TextInput { + padding: 2dp 4dp 2dp 4dp; + } + .settings_panel .add_build_step { + margin-top: 4dp; + } + .settings_panel .build_steps { + margin-bottom: 4dp; + } + .settings_panel .build_step:first-child .move_up, + .settings_panel .build_step:first-child .remove_item { + enabled: false; + } + .settings_panel .build_step:last-child .move_down { + enabled: false; + } + .settings_panel .build_step > .details { + margin-top: 2dp; + } + .settings_panel .build_step > .header > PushButton { + margin-left: 2dp; + } + .settings_panel .build_step > .header > .remove_item:disabled, + .settings_panel .build_step > .header > .move_up:disabled, + .settings_panel .build_step > .header > .move_down:disabled { + tint: var(--icon); + } + .settings_panel .os_select > CheckBox { + margin-right: 8dp; + } + .settings_panel .save_cont > PushButton { + margin: 8dp 0dp 0dp 4dp; + padding: 4dp 16dp 4dp 16dp; + } + .settings_panel .build_types > DropDownList, + .settings_panel .output_parser > DropDownList, + .settings_panel .span { + margin-top: 4dp; + } + .settings_panel #build_type_list { + margin-right: 4dp; + } + .settings_panel .build_types_cont { + row-valign: center; + } + .settings_panel .inner_box { + padding-top: 8dp; + visible: false; + } + .settings_panel .inner_box .build_environment > .subtitle { + margin-top: 0dp; + } + .settings_panel .advanced_options { + margin-top: 12dp; + border-radius: 4dp; + padding: 4dp; + background-color: rgba(0,0,0, 0.1); + } + .settings_panel .advanced_options .title { + padding-bottom: 4dp; + border-radius: 4dp; + background-color: transparent; + transition: background-color 100ms; + } + .settings_panel .advanced_options .title:hover { + background-color: var(--primary); + } + .settings_panel .output_parser .output_parser_rules { + background-color: var(--list-back); + } + .settings_panel .output_parser .output_parser_rules { + margin-top: 4dp; + } + .settings_panel .output_parser .output_parser_rules > TextView { + padding-left: 4dp; + min-height: 24dp; + layout-gravity: center; + } + .settings_panel .output_parser .output_parser_rules > TextView:first-child { + border-width: 1dp; + border-right-color: var(--button-border); + } + .settings_panel .output_parser .output_parser_rules > PushButton { + layout-gravity: center; + } + .settings_panel .details_but { + icon: icon(arrow-up-s, 10dp); + inner-widget-orientation: widgettextboxicon; + } + .settings_panel .details_but.contracted { + icon: icon(arrow-down-s, 10dp); + } + .settings_panel > .advanced_options > .title > Image { + icon: icon(arrow-down-s, 24dp); + } + .settings_panel > .advanced_options > .title > Image.expanded { + icon: icon(arrow-up-s, 24dp); + } + .settings_panel > .advanced_options > LinearLayout.inner_box.visible { + visible: true; + } @@ -3440,6 +3576,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe { "arrow-down", 0xea4c }, { "arrow-up", 0xea76 }, { "arrow-down-s", 0xea4e }, + { "arrow-up-s", 0xea78 }, { "arrow-right-s", 0xea6e }, { "match-case", 0xed8d }, { "palette", 0xefc5 }, diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index 373c4a78d..268879c73 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -1276,7 +1276,7 @@ LSPClientServer::LSPRequestHandle LSPClientServer::write( const json& msg, std::string sjson = ob.dump(); sjson = String::format( "Content-Length: %lu\r\n\r\n%s", sjson.length(), sjson.c_str() ); - if ( mReady || msg[MEMBER_METHOD] == "initialize" ) { + if ( mReady || ( msg.contains( MEMBER_METHOD ) && msg[MEMBER_METHOD] == "initialize" ) ) { std::string method; if ( msg.contains( MEMBER_METHOD ) ) method = msg[MEMBER_METHOD].get(); diff --git a/src/tools/ecode/projectbuild.cpp b/src/tools/ecode/projectbuild.cpp index 4f3ce0118..8b0dff933 100644 --- a/src/tools/ecode/projectbuild.cpp +++ b/src/tools/ecode/projectbuild.cpp @@ -2,6 +2,7 @@ #include "ecode.hpp" #include "scopedop.hpp" #include "statusbuildoutputcontroller.hpp" +#include "uibuildsettings.hpp" #include #include #include @@ -81,7 +82,11 @@ bool ProjectBuild::isOSSupported( const std::string& os ) const { ProjectBuildManager::ProjectBuildManager( const std::string& projectRoot, std::shared_ptr pool, UITabWidget* sidePanel, App* app ) : - mProjectRoot( projectRoot ), mThreadPool( pool ), mSidePanel( sidePanel ), mApp( app ) { + mProjectRoot( projectRoot ), + mThreadPool( pool ), + mSidePanel( sidePanel ), + mApp( app ), + mNewBuild( mApp->i18n( "new_name", "new_name" ), mProjectRoot ) { FileSystem::dirAddSlashAtEnd( mProjectRoot ); if ( mThreadPool ) { @@ -583,17 +588,15 @@ void ProjectBuildManager::buildSidePanelTab() { - - - + @@ -612,6 +615,8 @@ void ProjectBuildManager::updateSidePanelTab() { UIDropDownList* buildList = buildTab->find( "build_list" ); UIPushButton* buildButton = buildTab->find( "build_button" ); UIPushButton* cleanButton = buildTab->find( "clean_button" ); + UIPushButton* buildAdd = buildTab->find( "build_add" ); + UIPushButton* buildEdit = buildTab->find( "build_edit" ); buildList->getListBox()->clear(); @@ -634,13 +639,15 @@ void ProjectBuildManager::updateSidePanelTab() { } buildList->setEnabled( !buildList->getListBox()->isEmpty() ); + buildEdit->setEnabled( !buildList->getListBox()->isEmpty() ); updateBuildType(); buildList->removeEventsOfType( Event::OnItemSelected ); - buildList->addEventListener( Event::OnItemSelected, [this, buildList]( const Event* ) { + buildList->addEventListener( Event::OnItemSelected, [this, buildEdit, buildList]( const Event* ) { mConfig.buildName = buildList->getListBox()->getItemSelectedText(); mConfig.buildType = ""; + buildEdit->setEnabled( true ); updateBuildType(); } ); @@ -669,12 +676,37 @@ void ProjectBuildManager::updateSidePanelTab() { } }, MouseButton::EE_BUTTON_LEFT ); + + buildAdd->addMouseClickListener( + [this]( const Event* ) { + mNewBuild = ProjectBuild( mApp->i18n( "new_name", "new_name" ), mProjectRoot ); + auto ret = mApp->getSplitter()->createWidget( + UIBuildSettings::New( mNewBuild ), + mApp->i18n( "build_settings", "Build Settings" ) ); + ret.first->setIcon( mApp->findIcon( "hammer" ) ); + }, + MouseButton::EE_BUTTON_LEFT ); + + buildEdit->addMouseClickListener( + [this]( const Event* ) { + if ( !mConfig.buildName.empty() ) { + auto build = mBuilds.find( mConfig.buildName ); + if ( build != mBuilds.end() ) { + auto ret = mApp->getSplitter()->createWidget( + UIBuildSettings::New( build->second ), + mApp->i18n( "build_settings", "Build Settings" ) ); + ret.first->setIcon( mApp->findIcon( "hammer" ) ); + } + } + }, + MouseButton::EE_BUTTON_LEFT ); } void ProjectBuildManager::updateBuildType() { UIWidget* buildTab = mTab->getOwnedWidget()->find( "build_tab" ); UIDropDownList* buildList = buildTab->find( "build_list" ); UIDropDownList* buildTypeList = buildTab->find( "build_type_list" ); + UIPushButton* buildTypeAdd = buildTab->find( "build_type_add" ); buildTypeList->getListBox()->clear(); @@ -697,6 +729,7 @@ void ProjectBuildManager::updateBuildType() { } } buildTypeList->setEnabled( !buildTypeList->getListBox()->isEmpty() ); + buildTypeAdd->setEnabled( !mConfig.buildName.empty() ); buildTypeList->removeEventsOfType( Event::OnItemSelected ); buildTypeList->addEventListener( Event::OnItemSelected, [this, buildTypeList]( const Event* ) { diff --git a/src/tools/ecode/projectbuild.hpp b/src/tools/ecode/projectbuild.hpp index f4c89cd0f..b66072812 100644 --- a/src/tools/ecode/projectbuild.hpp +++ b/src/tools/ecode/projectbuild.hpp @@ -48,8 +48,7 @@ class StatusBuildOutputController; } ], "config": { - "clear_sys_env": false, - "enabled": true + "clear_sys_env": false }, "env": { "SHELL": "fish" @@ -91,7 +90,6 @@ using ProjectBuildSteps = std::vector; using ProjectBuildKeyVal = std::unordered_map; struct ProjectBuildConfig { - bool enabled{ true }; bool clearSysEnv{ false }; }; @@ -146,6 +144,7 @@ class ProjectBuild { protected: friend class ProjectBuildManager; + friend class UIBuildSettings; std::string mName; std::string mProjectRoot; @@ -257,6 +256,7 @@ class ProjectBuildManager { UITab* mTab{ nullptr }; App* mApp{ nullptr }; std::unique_ptr mProcess; + ProjectBuild mNewBuild; bool mLoaded{ false }; bool mLoading{ false }; bool mBuilding{ false }; diff --git a/src/tools/ecode/uibuildsettings.cpp b/src/tools/ecode/uibuildsettings.cpp new file mode 100644 index 000000000..ed3fbbb56 --- /dev/null +++ b/src/tools/ecode/uibuildsettings.cpp @@ -0,0 +1,226 @@ +#include "uibuildsettings.hpp" +#include +#include +#include + +namespace ecode { + +class UIBuildStep : public UILinearLayout { + public: + static UIBuildStep* New( bool isBuildStep, UIBuildSettings* buildSettings, size_t stepNum, + ProjectBuildStep& buildStep ) { + return eeNew( UIBuildStep, ( isBuildStep, buildSettings, stepNum, buildStep ) ); + } + + protected: + UIBuildStep( bool isBuildStep, UIBuildSettings* buildSettings, size_t stepNum, + ProjectBuildStep& buildStep ) : + UILinearLayout( "buildstep", UIOrientation::Vertical ), + mIsBuildStep( isBuildStep ), + mBuildSettings( buildSettings ), + mStepNum( stepNum ), + mStep( buildStep ) { + setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + addClass( "build_step" ); + + static const auto BUILD_STEP_XML = R"xml( + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + + getUISceneNode()->loadLayoutFromString( BUILD_STEP_XML, this ); + findByClass( "step_name" ) + ->setText( String::format( mBuildSettings->getUISceneNode() + ->i18n( "build_step_num", "Step %u" ) + .toUtf8() + .c_str(), + stepNum + 1 ) ); + mDataBindHolder += UIDataBindBool::New( &mStep.enabled, findByClass( "enabled_checkbox" ) ); + mDataBindHolder += UIDataBindString::New( &mStep.cmd, findByClass( "input_cmd" ) ); + mDataBindHolder += UIDataBindString::New( &mStep.args, findByClass( "input_args" ) ); + mDataBindHolder += + UIDataBindString::New( &mStep.workingDir, findByClass( "input_working_dir" ) ); + findByClass( "details_but" ) + ->addMouseClickListener( + [this]( const MouseEvent* event ) { + auto me = event->getNode()->asType(); + findByClass( "details" )->setVisible( me->hasClass( "contracted" ) ); + me->toggleClass( "contracted" ); + }, + MouseButton::EE_BUTTON_LEFT ); + } + + bool mIsBuildStep{ true }; + UIBuildSettings* mBuildSettings{ nullptr }; + size_t mStepNum{ 0 }; + ProjectBuildStep& mStep; + UIDataBindHolder mDataBindHolder; +}; + +static const auto SETTINGS_PANEL_XML = R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + generic + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + +UIBuildSettings* UIBuildSettings::New( ProjectBuild& build ) { + return eeNew( UIBuildSettings, ( build ) ); +} + +UIBuildSettings::UIBuildSettings( ProjectBuild& build ) : mBuild( build ) { + mUISceneNode->loadLayoutFromString( SETTINGS_PANEL_XML, this, + String::hash( "build_settings" ) ); + mDataBindHolder += UIDataBindString::New( &mBuild.mName, find( "build_name" ) ); + + auto oses = find( "os_select" )->querySelectorAll( "CheckBox" ); + for ( const auto os : oses ) { + if ( mBuild.mOS.find( os->getId() ) != mBuild.mOS.end() ) + os->asType()->setChecked( true ); + os->on( Event::OnValueChange, [this]( const Event* ) { updateOS(); } ); + } + + if ( mBuild.mBuild.empty() ) + mBuild.mBuild.push_back( {} ); + + if ( mBuild.mClean.empty() ) + mBuild.mClean.push_back( {} ); + + auto buildStepsParent = find( "build_steps_cont" ); + for ( size_t step = 0; step < mBuild.mBuild.size(); ++step ) { + auto bs = UIBuildStep::New( true, this, step, mBuild.mBuild[step] ); + bs->setParent( buildStepsParent ); + } + + auto buildCleanStepsParent = find( "build_clean_steps_cont" ); + for ( size_t step = 0; step < mBuild.mClean.size(); ++step ) { + auto bs = UIBuildStep::New( false, this, step, mBuild.mClean[step] ); + bs->setParent( buildCleanStepsParent ); + } + + auto buildTypeDropDown = find( "build_type_list" ); + std::vector buildTypes; + for ( const auto& type : mBuild.mBuildTypes ) + buildTypes.push_back( type ); + buildTypeDropDown->getListBox()->addListBoxItems( buildTypes ); + buildTypeDropDown->getListBox()->setSelected( 0 ); + + auto advTitle = querySelector( ".settings_panel > .advanced_options > .title" ); + advTitle->addMouseClickListener( + [this]( const MouseEvent* event ) { + auto img = event->getNode()->findByType( UI_TYPE_IMAGE )->asType(); + findByClass( "inner_box" )->toggleClass( "visible" ); + img->toggleClass( "expanded" ); + }, + MouseButton::EE_BUTTON_LEFT ); +} + +void UIBuildSettings::updateOS() { + mBuild.mOS.clear(); + auto oses = find( "os_select" )->querySelectorAll( "CheckBox" ); + for ( const auto os : oses ) { + if ( os->asType()->isChecked() ) + mBuild.mOS.insert( os->getId() ); + } +} + +} // namespace ecode diff --git a/src/tools/ecode/uibuildsettings.hpp b/src/tools/ecode/uibuildsettings.hpp new file mode 100644 index 000000000..332297459 --- /dev/null +++ b/src/tools/ecode/uibuildsettings.hpp @@ -0,0 +1,27 @@ +#ifndef EE_UI_UIBUILDSETTINGS_HPP +#define EE_UI_UIBUILDSETTINGS_HPP + +#include "projectbuild.hpp" +#include +#include + +using namespace EE::UI; + +namespace ecode { + +class UIBuildSettings : public UIRelativeLayout { + public: + static UIBuildSettings* New( ProjectBuild& build ); + + protected: + ProjectBuild& mBuild; + UIDataBindHolder mDataBindHolder; + + explicit UIBuildSettings( ProjectBuild& build ); + + void updateOS(); +}; + +} // namespace ecode + +#endif // EE_UI_UIBUILDSETTINGS_HPP