diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 51be4828f..57e5c3b41 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -904,6 +904,26 @@ treeview::row:selected { background-color: var(--primary); } +tableview.selection_type_cell tableview::row:hover, +treeview.selection_type_cell treeview::row:hover { + background-color: transparent; +} + +tableview.selection_type_cell tableview::row:selected, +treeview.selection_type_cell treeview::row:selected { + background-color: transparent; +} + +tableview.selection_type_cell tableview::cell:hover, +treeview.selection_type_cell treeview::cell:hover { + background-color: var(--tab-hover); +} + +tableview.selection_type_cell tableview::cell:selected, +treeview.selection_type_cell tableview::cell:selected { + background-color: var(--primary); +} + tableview::cell, treeview::cell { padding-left: 6dp; diff --git a/include/eepp/ui/abstract/uiabstractview.hpp b/include/eepp/ui/abstract/uiabstractview.hpp index 766dff355..cb2074760 100644 --- a/include/eepp/ui/abstract/uiabstractview.hpp +++ b/include/eepp/ui/abstract/uiabstractview.hpp @@ -49,6 +49,12 @@ class EE_API UIAbstractView : public UIScrollableWidget { AnyKeyPressed = 1 << 2, }; + enum SelectionType { Row, Cell }; + + bool isCellSelection() const; + + bool isRowSelection() const; + Uint32 getType() const; bool isType( const Uint32& type ) const; @@ -98,6 +104,9 @@ class EE_API UIAbstractView : public UIScrollableWidget { std::function onCreateEditingDelegate; + SelectionType getSelectionType() const; + void setSelectionType( SelectionType selectionType ); + protected: friend class EE::UI::Models::Model; @@ -124,6 +133,7 @@ class EE_API UIAbstractView : public UIScrollableWidget { Uint32 mEditTriggers{ EditTrigger::None }; KeyBindings::Shortcut mEditShortcut{ KEY_F2 }; + SelectionType mSelectionType{ SelectionType::Row }; virtual void editingWidgetDidChange( const ModelIndex& ) {} }; diff --git a/include/eepp/ui/models/itemlistmodel.hpp b/include/eepp/ui/models/itemlistmodel.hpp index 7157ce2fc..33c654b9b 100644 --- a/include/eepp/ui/models/itemlistmodel.hpp +++ b/include/eepp/ui/models/itemlistmodel.hpp @@ -23,8 +23,7 @@ template class ItemListModel final : public Model { virtual std::string columnName( const size_t& ) const { return "Data"; } - virtual ModelIndex index( int row, int column, - const ModelIndex& parent = ModelIndex() ) const override { + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) return {}; return Model::index( row, column, parent ); @@ -66,8 +65,7 @@ template class ItemPairListModel final : public Model { mColumnNames[index] = name; } - virtual ModelIndex index( int row, int column, - const ModelIndex& parent = ModelIndex() ) const override { + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) return {}; return Model::index( row, column, parent ); @@ -125,8 +123,7 @@ template class ItemListOwnerModel final : public Model { virtual std::string columnName( const size_t& ) const { return "Data"; } - virtual ModelIndex index( int row, int column, - const ModelIndex& parent = ModelIndex() ) const override { + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) return {}; return Model::index( row, column, parent ); @@ -180,8 +177,7 @@ template class ItemPairListOwnerModel final : public Mo mColumnNames[index] = name; } - virtual ModelIndex index( int row, int column, - const ModelIndex& parent = ModelIndex() ) const override { + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) return {}; return Model::index( row, column, parent ); @@ -252,8 +248,7 @@ template class ItemVectorListOwnerModel final : public Model { mColumnNames[index] = name; } - virtual ModelIndex index( int row, int column, - const ModelIndex& parent = ModelIndex() ) const override { + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) return {}; return Model::index( row, column, parent ); diff --git a/include/eepp/ui/models/modeleditingdelegate.hpp b/include/eepp/ui/models/modeleditingdelegate.hpp index 39c3b27d1..faf35e3de 100644 --- a/include/eepp/ui/models/modeleditingdelegate.hpp +++ b/include/eepp/ui/models/modeleditingdelegate.hpp @@ -31,12 +31,16 @@ class EE_API ModelEditingDelegate { std::function onCommit; std::function onRollback; std::function onChange; + std::function onWillBeginEditing; virtual Variant getValue() const = 0; virtual void setValue( const Variant& ) = 0; - virtual void willBeginEditing() {} + virtual void willBeginEditing() { + if ( onWillBeginEditing ) + onWillBeginEditing(); + } ModelIndex const& index() const { return mIndex; } @@ -95,6 +99,8 @@ class EE_API StringModelEditingDelegate : public ModelEditingDelegate { void willBeginEditing() override { if ( mSelectionBehavior == SelectionBehavior::SelectAll ) getWidget()->asType()->getDocument().selectAll(); + + ModelEditingDelegate::willBeginEditing(); } protected: diff --git a/include/eepp/ui/uidatabind.hpp b/include/eepp/ui/uidatabind.hpp index 8c3e2205e..2f26d368c 100644 --- a/include/eepp/ui/uidatabind.hpp +++ b/include/eepp/ui/uidatabind.hpp @@ -250,10 +250,12 @@ class UIDataBindString { class UIDataBindHolder { public: using UIDataBindVariant = - std::variant, - UIDataBind, UIDataBind, UIDataBind, UIDataBind, - UIDataBind, UIDataBind, UIDataBind, UIDataBind, - UIDataBind>; + std::variant>, std::unique_ptr>, + std::unique_ptr>, std::unique_ptr>, + std::unique_ptr>, std::unique_ptr>, + std::unique_ptr>, std::unique_ptr>, + std::unique_ptr>, std::unique_ptr>>; UIDataBindHolder& hold( UIDataBindVariant&& ptr ) { mHolder.emplace_back( std::move( ptr ) ); diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index bbf72cb27..91225aca3 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -110,7 +110,7 @@ {388e5431-b31b-42b3-b9ad-9002d279d75d} 10 0 - 15 + 19 ../../make/linux @@ -1107,7 +1107,7 @@ eepp-UIEditor-debug ProjectExplorer.CustomExecutableRunConfiguration - -u --xml=/home/downloads/build_settings.xml + -u true false false diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 4fa97c6be..6957dc11d 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -262,7 +262,7 @@ void UIAbstractTableView::updateHeaderSize() { size_t count = getModel()->columnCount(); Float totalWidth = 0; for ( size_t i = 0; i < count; i++ ) { - ColumnData& col = columnData( i ); + const ColumnData& col = columnData( i ); totalWidth += col.width; } mHeader->setPixelsSize( totalWidth, getHeaderHeight() ); @@ -419,7 +419,7 @@ UITableRow* UIAbstractTableView::createRow() { rowWidget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed ); rowWidget->reloadStyle( true, true, true ); rowWidget->addEventListener( Event::MouseDown, [&]( const Event* event ) { - if ( !( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) ) + if ( !( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) || !isRowSelection() ) return; getSelection().set( event->getNode()->asType()->getCurIndex() ); } ); @@ -440,10 +440,12 @@ UITableRow* UIAbstractTableView::updateRow( const int& rowIndex, const ModelInde rowWidget->setCurIndex( index ); rowWidget->setPixelsSize( getContentSize().getWidth(), getRowHeight() ); rowWidget->setPixelsPosition( { -mScrollOffset.x, yOffset - mScrollOffset.y } ); - if ( getSelection().contains( index ) ) { - rowWidget->pushState( UIState::StateSelected ); - } else { - rowWidget->popState( UIState::StateSelected ); + if ( isRowSelection() ) { + if ( getSelection().contains( index ) ) { + rowWidget->pushState( UIState::StateSelected ); + } else { + rowWidget->popState( UIState::StateSelected ); + } } return rowWidget; } @@ -474,6 +476,9 @@ void UIAbstractTableView::bindNavigationClick( UIWidget* widget ) { onOpenMenuModelIndex( idx, event ); } else if ( ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) && mSingleClickNavigation ) { onOpenModelIndex( idx, event ); + } else if ( isCellSelection() && ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) ) { + auto cellIdx = mouseEvent->getNode()->asType()->getCurIndex(); + getSelection().set( cellIdx ); } } ) ); } @@ -545,6 +550,14 @@ UIWidget* UIAbstractTableView::updateCell( const int& rowIndex, const ModelIndex cell->updateCell( getModel() ); } + if ( isCellSelection() ) { + if ( getSelection().contains( index ) ) { + widget->pushState( UIState::StateSelected ); + } else { + widget->popState( UIState::StateSelected ); + } + } + return widget; } @@ -672,14 +685,14 @@ Uint32 UIAbstractTableView::onTextInput( const TextInputEvent& event ) { String::startsWith( String::toLower( var.toString() ), mSearchText ) ) { setSelection( model->index( next.row(), 0, next.parent() ) ); } else { - ModelIndex index = findRowWithText( mSearchText ); - if ( index.isValid() ) - setSelection( index ); + ModelIndex fIndex = findRowWithText( mSearchText ); + if ( fIndex.isValid() ) + setSelection( fIndex ); } } else { - ModelIndex index = findRowWithText( mSearchText ); - if ( index.isValid() ) - setSelection( index ); + ModelIndex fIndex = findRowWithText( mSearchText ); + if ( fIndex.isValid() ) + setSelection( fIndex ); } } } diff --git a/src/eepp/ui/abstract/uiabstractview.cpp b/src/eepp/ui/abstract/uiabstractview.cpp index b486e787a..0bad4957d 100644 --- a/src/eepp/ui/abstract/uiabstractview.cpp +++ b/src/eepp/ui/abstract/uiabstractview.cpp @@ -11,6 +11,20 @@ UIAbstractView::~UIAbstractView() { eeSAFE_DELETE( mEditingDelegate ); } +UIAbstractView::SelectionType UIAbstractView::getSelectionType() const { + return mSelectionType; +} + +void UIAbstractView::setSelectionType( SelectionType selectionType ) { + mSelectionType = selectionType; + + if ( selectionType == UIAbstractView::SelectionType::Cell ) { + addClass( "selection_type_cell" ); + } else { + removeClass( "selection_type_cell" ); + } +} + KeyBindings::Shortcut UIAbstractView::getEditShortcut() const { return mEditShortcut; } @@ -33,6 +47,12 @@ bool UIAbstractView::isEditable() const { void UIAbstractView::setEditable( bool editable ) { mEditable = editable; + + if ( editable ) { + addClass( "editable_cells" ); + } else { + removeClass( "editable_cells" ); + } } std::function UIAbstractView::getOnSelection() const { @@ -51,6 +71,14 @@ void UIAbstractView::setOnSelectionChange( const std::function& onSelect mOnSelectionChange = onSelectionChange; } +bool UIAbstractView::isCellSelection() const { + return mSelectionType == UIAbstractView::SelectionType::Cell; +} + +bool UIAbstractView::isRowSelection() const { + return mSelectionType == UIAbstractView::SelectionType::Row; +} + Uint32 UIAbstractView::getType() const { return UI_TYPE_ABSTRACTVIEW; } @@ -131,7 +159,6 @@ void UIAbstractView::beginEditing( const ModelIndex& index, UIWidget* editedWidg }; mEditingDelegate->onRollback = [this]() { stopEditing(); }; mEditingDelegate->onChange = [this, index]() { editingWidgetDidChange( index ); }; - // mEditWidget->on( Event::OnFocusLoss, [this]( auto ) { mEditingDelegate->onRollback(); } ); } void UIAbstractView::stopEditing() { diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index a46966cb2..936359adc 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -906,7 +906,7 @@ void StyleSheetSpecification::registerDefaultShorthandParsers() { // boder-style is not implemented yet if ( pos != -1 ) continue; - } else if ( Color::isColorString( tok ) ) { + } else if ( Color::isColorString( tok ) || String::startsWith( tok, "var(" ) ) { int pos = getIndexEndingWith( propNames, "-color" ); if ( pos != -1 ) { const ShorthandDefinition* shorthand = getShorthand( propNames[pos] ); diff --git a/src/eepp/ui/uispinbox.cpp b/src/eepp/ui/uispinbox.cpp index 15d5b2cdb..160ab67f5 100644 --- a/src/eepp/ui/uispinbox.cpp +++ b/src/eepp/ui/uispinbox.cpp @@ -17,7 +17,7 @@ UISpinBox::UISpinBox() : mValue( 0 ), mClickStep( 1.f ), mModifyingVal( false ) { - mFlags |= UI_SCROLLABLE; + mFlags |= UI_SCROLLABLE; mInput = UITextInput::NewWithTag( "spinbox::input" ); mInput->setVisible( true ); mInput->setEnabled( true ); @@ -159,24 +159,23 @@ void UISpinBox::addValue( const double& value ) { } UISpinBox* UISpinBox::setValue( const double& val ) { - if ( val != mValue ) { - if ( val >= mMinValue && val <= mMaxValue ) { - double iValN = (double)(Int64)val; - double fValN = (double)iValN; + double newVal = eeclamp( val, mMinValue, mMaxValue ); + double iValN = (double)(Int64)newVal; + double fValN = (double)iValN; + bool valueChanged = mValue != newVal; - mValue = val; + mValue = newVal; - mModifyingVal = true; - if ( fValN == val ) { - mInput->setText( String::toString( (Int64)iValN ) ); - } else { - mInput->setText( String::toString( val ) ); - } - mModifyingVal = false; - - onValueChange(); - } + mModifyingVal = true; + if ( fValN == newVal ) { + mInput->setText( String::toString( (Int64)iValN ) ); + } else { + mInput->setText( String::toString( newVal ) ); } + mModifyingVal = false; + + if ( valueChanged ) + onValueChange(); return this; } @@ -196,12 +195,8 @@ void UISpinBox::onBufferChange( const Event* ) { mInput->setText( mInput->getText().substr( 0, mInput->getText().size() - 1 ) ); } else { bool res = String::fromString( val, mInput->getText() ); - - if ( res && val != mValue && val >= mMinValue && val <= mMaxValue ) { - mValue = val; - - onValueChange(); - } + if ( res && val != mValue ) + setValue( val ); } } } @@ -226,7 +221,7 @@ UISpinBox* UISpinBox::setMinValue( const double& minVal ) { mMinValue = minVal; if ( mValue < mMinValue ) - mValue = mMinValue; + setValue( mMinValue ); return this; } @@ -239,7 +234,7 @@ UISpinBox* UISpinBox::setMaxValue( const double& maxVal ) { mMaxValue = maxVal; if ( mValue > mMaxValue ) - mValue = mMaxValue; + setValue( mMaxValue ); return this; } diff --git a/src/eepp/ui/uitableheadercolumn.cpp b/src/eepp/ui/uitableheadercolumn.cpp index 74b5c98ef..77021f33e 100644 --- a/src/eepp/ui/uitableheadercolumn.cpp +++ b/src/eepp/ui/uitableheadercolumn.cpp @@ -60,6 +60,7 @@ Uint32 UITableHeaderColumn::onMouseDown( const Vector2i& position, const Uint32& !( getEventDispatcher()->getLastPressTrigger() & mDragButton ) && ( flags & mDragButton ) && isDragEnabled() && !isDragging() && localPos.x >= mSize.getWidth() - mView->getDragBorderDistance() ) { + setFocus(); startDragging( position.asFloat() ); } pushState( UIState::StatePressed ); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 37dfa910d..5cfb3c938 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -3367,12 +3367,8 @@ TableView#locate_bar_table > tableview::row:selected > tableview::cell:nth-child 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; @@ -3422,6 +3418,27 @@ TableView#locate_bar_table > tableview::row:selected > tableview::cell:nth-child .settings_panel > .advanced_options > LinearLayout.inner_box.visible { visible: true; } +.settings_panel .buttons_box { + margin-left:4dp; + layout-gravity: center_horizontal|top; +} +.settings_panel .buttons_box > * { + margin-bottom: 4dp; +} +.settings_panel TableView { + margin-top: 4dp; +} +.custom_output_parser_cont > * { + margin-bottom: 4dp; + padding-top: 4dp; +} +.custom_output_parser_cont > .capture_positions_cont { + border: 1dp solid var(--tab-line); + padding: 4dp; +} +.custom_output_parser_cont > .capture_positions_cont > * { + padding: 2dp; +} diff --git a/src/tools/ecode/projectbuild.hpp b/src/tools/ecode/projectbuild.hpp index c9e6ad6d2..f3736d146 100644 --- a/src/tools/ecode/projectbuild.hpp +++ b/src/tools/ecode/projectbuild.hpp @@ -93,9 +93,21 @@ struct ProjectBuildConfig { bool clearSysEnv{ false }; }; -enum class ProjectOutputParserTypes { Error, Warning, Notice }; +enum class ProjectOutputParserTypes { Error = 0, Warning = 1, Notice = 2 }; struct ProjectBuildOutputParserConfig { + static std::string typeToString( ProjectOutputParserTypes type ) { + switch ( type ) { + case ProjectOutputParserTypes::Notice: + return "notice"; + case ProjectOutputParserTypes::Warning: + return "warning"; + case ProjectOutputParserTypes::Error: + default: + return "error"; + } + } + ProjectOutputParserTypes type; std::string pattern; struct { diff --git a/src/tools/ecode/uibuildsettings.cpp b/src/tools/ecode/uibuildsettings.cpp index b402745af..80a57ff66 100644 --- a/src/tools/ecode/uibuildsettings.cpp +++ b/src/tools/ecode/uibuildsettings.cpp @@ -10,6 +10,196 @@ using namespace EE::UI::Models; namespace ecode { +class OutputParserModel final : public Model { + public: + static std::shared_ptr + create( std::vector& data, + std::function i18n ) { + return std::make_shared( data, i18n ); + } + + explicit OutputParserModel( std::vector& data, + std::function i18n ) : + mData( data ), i18n( i18n ) { + mColumnNames.push_back( i18n( "type", "Type" ) ); + mColumnNames.push_back( i18n( "pattern", "Pattern" ) ); + } + + virtual ~OutputParserModel() {} + + virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } + + virtual size_t columnCount( const ModelIndex& ) const { return 2; } + + virtual std::string columnName( const size_t& index ) const { + eeASSERT( index < 2 ); + return mColumnNames[index]; + } + + virtual void setColumnName( const size_t& index, const std::string& name ) { + eeASSERT( index < 2 ); + mColumnNames[index] = name; + } + + virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const { + if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) ) + return {}; + return Model::index( row, column, parent ); + } + + virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const { + if ( role == ModelRole::Display ) { + switch ( index.column() ) { + case 0: { + std::string val = + ProjectBuildOutputParserConfig::typeToString( mData[index.row()].type ); + return Variant( i18n( val, String::capitalize( val ) ) ); + } + case 1: + default: + return Variant( mData[index.row()].pattern ); + } + } + return {}; + } + + virtual void update() { onModelUpdate(); } + + private: + std::vector& mData; + std::function i18n; + std::vector mColumnNames; +}; + +class UICustomOutputParserWindow : public UIWindow { + public: + static UICustomOutputParserWindow* New( ProjectBuildOutputParserConfig& cfg ) { + return eeNew( UICustomOutputParserWindow, ( cfg ) ); + } + + explicit UICustomOutputParserWindow( ProjectBuildOutputParserConfig& cfg ) : + UIWindow( SIMPLE_LAYOUT, { UI_WIN_CLOSE_BUTTON | UI_WIN_USE_DEFAULT_BUTTONS_ACTIONS | + UI_WIN_SHARE_ALPHA_WITH_CHILDS | UI_WIN_MODAL } ), + mTmpCfg( cfg ), + mCfg( cfg ) { + static const auto CUSTOM_OUTPUT_PARSER_XML = R"xml( + + + + @string("error", "Error") + @string("warning", "Warning") + @string("notice", "Notice") + + + + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + + mLayoutCont = + getUISceneNode()->loadLayoutFromString( CUSTOM_OUTPUT_PARSER_XML, mContainer ); + + setTitle( i18n( "custom_output_parser", "Custom Output Parser" ) ); + + auto patternInput = find( "custom_parser_pattern" ); + + mDataBindHolder += UIDataBindString::New( &mTmpCfg.pattern, patternInput ); + + UIDropDownList* cpTypeddl = find( "custom_parser_type" ); + UIDataBind::Converter projectOutputParserTypesConverter( + []( const UIDataBind* databind, ProjectOutputParserTypes& val, + const std::string& str ) -> bool { + auto v = StyleSheetProperty( databind->getPropertyDefinition(), str ).asString(); + Uint32 idx; + if ( String::fromString( idx, v ) && idx >= 0 && idx <= 2 ) { + val = (ProjectOutputParserTypes)idx; + return true; + } + return false; + }, + [cpTypeddl]( const UIDataBind*, std::string& str, + const ProjectOutputParserTypes& val ) -> bool { + str = cpTypeddl->getListBox()->getItem( (Uint32)val )->getText(); + return true; + } ); + + mOptDb = UIDataBind::New( + &mTmpCfg.type, cpTypeddl, projectOutputParserTypesConverter, "selected-index" ); + + mDataBindHolder += + UIDataBind::New( &mTmpCfg.patternOrder.file, find( "file_name_pos" ) ); + mDataBindHolder += + UIDataBind::New( &mTmpCfg.patternOrder.line, find( "line_number_pos" ) ); + mDataBindHolder += + UIDataBind::New( &mTmpCfg.patternOrder.col, find( "column_pos" ) ); + mDataBindHolder += + UIDataBind::New( &mTmpCfg.patternOrder.message, find( "message_pos" ) ); + + auto butOK = find( "but_ok" ); + butOK->setEnabled( !patternInput->getText().empty() ); + + patternInput->on( Event::OnTextChanged, [butOK, patternInput]( auto ) { + butOK->setEnabled( !patternInput->getText().empty() ); + } ); + + butOK->onClick( [this]( auto ) { + mCfg.pattern = mTmpCfg.pattern; + mCfg.patternOrder = mTmpCfg.patternOrder; + mCfg.type = mTmpCfg.type; + sendCommonEvent( Event::OnConfirm ); + closeWindow(); + } ); + + find( "but_cancel" )->onClick( [this]( auto ) { closeWindow(); } ); + } + + virtual ~UICustomOutputParserWindow() {} + + protected: + UIWidget* mLayoutCont{ nullptr }; + ProjectBuildOutputParserConfig mTmpCfg; + ProjectBuildOutputParserConfig& mCfg; + UIDataBindHolder mDataBindHolder; + std::unique_ptr> mOptDb; + + virtual void onWindowReady() { + forcedApplyStyle(); + + Sizef size( mLayoutCont->getSize() ); + setMinWindowSize( size ); + center(); + + if ( mShowWhenReady ) { + mShowWhenReady = false; + show(); + } + + sendCommonEvent( Event::OnWindowReady ); + } +}; + class UIBuildStep : public UILinearLayout { public: static UIBuildStep* New( bool isBuildStep, UIBuildSettings* buildSettings, size_t stepNum, @@ -113,91 +303,106 @@ class UIBuildStep : public UILinearLayout { static const auto SETTINGS_PANEL_XML = R"xml( - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - generic - - - - - - - - - - - - - - - - + + + + + + + generic + + + + + + + + + - - + + + + )xml"; UIBuildSettings* UIBuildSettings::New( ProjectBuild& build, ProjectBuildConfiguration& config ) { @@ -303,40 +508,19 @@ UIBuildSettings::UIBuildSettings( ProjectBuild& build, ProjectBuildConfiguration } auto advTitle = querySelector( ".settings_panel > .advanced_options > .title" ); - advTitle->onClick( [this]( const MouseEvent* event ) { - auto img = event->getNode()->findByType( UI_TYPE_IMAGE )->asType(); - findByClass( "inner_box" )->toggleClass( "visible" ); - img->toggleClass( "expanded" ); + advTitle->onClick( [this, advTitle]( const MouseEvent* event ) { + if ( getEventDispatcher()->getMouseDownNode() == advTitle ) { + auto img = event->getNode()->findByType( UI_TYPE_IMAGE )->asType(); + findByClass( "inner_box" )->toggleClass( "visible" ); + img->toggleClass( "expanded" ); + } } ); mDataBindHolder += UIDataBindBool::New( &mBuild.mConfig.clearSysEnv, find( "clear_sys_env" ) ); - UITableView* tableEnvs = find( "table_vars" ); - auto modelEnvs = ItemPairListModel::create( mBuild.mEnvs ); - modelEnvs->setIsEditable( true ); - modelEnvs->setColumnName( 0, getTranslatorString( "env_name", "Name" ) ); - modelEnvs->setColumnName( 1, getTranslatorString( "env_value", "Value" ) ); - tableEnvs->setAutoColumnsWidth( true ); - tableEnvs->setModel( modelEnvs ); - tableEnvs->setEditable( true ); - tableEnvs->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked ); - tableEnvs->onCreateEditingDelegate = []( const ModelIndex& ) { - return StringModelEditingDelegate::New(); - }; - - UITableView* tableVars = find( "table_vars" ); - auto modelVars = ItemPairListModel::create( mBuild.mVars ); - modelVars->setColumnName( 0, getTranslatorString( "var_name", "Name" ) ); - modelVars->setColumnName( 1, getTranslatorString( "var_value", "Value" ) ); - modelVars->setIsEditable( true ); - tableVars->setAutoColumnsWidth( true ); - tableVars->setModel( modelVars ); - tableVars->setEditable( true ); - tableVars->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked ); - tableVars->onCreateEditingDelegate = []( const ModelIndex& ) { - return StringModelEditingDelegate::New(); - }; + bindTable( "table_envs", "env", mBuild.mEnvs ); + bindTable( "table_vars", "var", mBuild.mVars ); find( "build_type_add" )->onClick( [this, buildTypeDropDown, panelBuildTypeDDL]( auto ) { UIMessageBox* msgBox = @@ -393,6 +577,42 @@ UIBuildSettings::UIBuildSettings( ProjectBuild& build, ProjectBuildConfiguration ProjectBuildOutputParser::getPresets()[mBuild.mOutputParser.mPreset].mConfig; } } ); + + UITableView* tableOP = find( "table_output_parsers" ); + tableOP->setAutoColumnsWidth( true ); + tableOP->setFitAllColumnsToWidget( true ); + auto modelOP = OutputParserModel::create( mBuild.mOutputParser.mConfig, + [this]( auto s, auto s2 ) { return i18n( s, s2 ); } ); + tableOP->setModel( modelOP ); + + find( "custom_op_add" )->onClick( [this, modelOP]( auto ) { + mTmpOpCfg = {}; + auto ret = UICustomOutputParserWindow::New( mTmpOpCfg ); + ret->showWhenReady(); + ret->on( Event::OnConfirm, [this, modelOP]( auto ) { + mBuild.mOutputParser.mConfig.push_back( mTmpOpCfg ); + modelOP->invalidate(); + } ); + } ); + + find( "custom_op_edit" )->onClick( [this, tableOP, modelOP]( auto ) { + if ( !tableOP->getSelection().isEmpty() && tableOP->getSelection().first().row() >= 0 && + tableOP->getSelection().first().row() < (int)mBuild.mOutputParser.mConfig.size() ) { + auto ret = UICustomOutputParserWindow::New( + mBuild.mOutputParser.mConfig[tableOP->getSelection().first().row()] ); + ret->showWhenReady(); + ret->on( Event::OnConfirm, [modelOP]( auto ) { modelOP->invalidate(); } ); + } + } ); + + find( "custom_op_del" )->onClick( [this, tableOP, modelOP]( auto ) { + if ( !tableOP->getSelection().isEmpty() && tableOP->getSelection().first().row() >= 0 && + tableOP->getSelection().first().row() < (int)mBuild.mOutputParser.mConfig.size() ) { + mBuild.mOutputParser.mConfig.erase( mBuild.mOutputParser.mConfig.begin() + + tableOP->getSelection().first().row() ); + modelOP->invalidate(); + } + } ); } void UIBuildSettings::updateOS() { @@ -424,6 +644,45 @@ void UIBuildSettings::refreshTab() { mTab->setId( "build_settings_" + mBuild.mName ); } +void UIBuildSettings::bindTable( const std::string& name, const std::string& key, + ProjectBuildKeyVal& data ) { + + const auto createInputDelegate = []( const ModelIndex& ) -> ModelEditingDelegate* { + auto delegate = StringModelEditingDelegate::New(); + delegate->onWillBeginEditing = [delegate]() { + delegate->getWidget()->asType()->on( + Event::OnFocusLoss, [delegate]( auto ) { delegate->onCommit(); } ); + }; + return delegate; + }; + + UITableView* table = find( name ); + auto model = ItemPairListModel::create( data ); + model->setColumnName( 0, getTranslatorString( key + "_name", "Name" ) ); + model->setColumnName( 1, getTranslatorString( key + "_value", "Value" ) ); + model->setIsEditable( true ); + table->setAutoColumnsWidth( true ); + table->setFitAllColumnsToWidget( true ); + table->setModel( model ); + table->setEditable( true ); + table->setSelectionType( UIAbstractView::SelectionType::Cell ); + table->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked | + UIAbstractTableView::EditTrigger::EditKeyPressed ); + table->onCreateEditingDelegate = createInputDelegate; + + find( "custom_" + key + "_add" )->onClick( [this, model, &data]( auto ) { + data.push_back( { i18n( "new_name", "New Name" ), i18n( "new_value", "New Value" ) } ); + model->invalidate(); + } ); + + find( "custom_" + key + "_del" )->onClick( [model, table, &data]( auto ) { + if ( !table->getSelection().isEmpty() ) { + data.erase( data.begin() + table->getSelection().first().row() ); + model->invalidate(); + } + } ); +} + void UIBuildSettings::moveStepUp( size_t stepNum, bool isClean ) { moveStepDir( stepNum, isClean, -1 ); } diff --git a/src/tools/ecode/uibuildsettings.hpp b/src/tools/ecode/uibuildsettings.hpp index f526a8da9..0afb5c543 100644 --- a/src/tools/ecode/uibuildsettings.hpp +++ b/src/tools/ecode/uibuildsettings.hpp @@ -28,6 +28,7 @@ class UIBuildSettings : public UIRelativeLayout { UITab* mTab{ nullptr }; String mOldName; std::unordered_map> mCbs; + ProjectBuildOutputParserConfig mTmpOpCfg; explicit UIBuildSettings( ProjectBuild& build, ProjectBuildConfiguration& config ); @@ -42,6 +43,8 @@ class UIBuildSettings : public UIRelativeLayout { void updateOS(); void refreshTab(); + + void bindTable( const std::string& name, const std::string& key, ProjectBuildKeyVal& data ); }; } // namespace ecode