diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index 0d5ed3309..00c7d9ab3 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -136,6 +136,10 @@ class EE_API UIAbstractTableView : public UIAbstractView { void setRowHeaderWidth( Float rowHeaderWidth ); + bool hasOnUpdateCellCb(); + + void setOnUpdateCellCb( const std::function& onUpdateCellCb ); + protected: friend class EE::UI::UITableHeaderColumn; @@ -167,6 +171,7 @@ class EE_API UIAbstractTableView : public UIAbstractView { std::string mSearchText; size_t mMainColumn{ 0 }; std::unordered_map> mWidgetsClickCbId; + std::function mOnUpdateCellCb; Float mRowHeaderWidth{ 0 }; virtual ~UIAbstractTableView(); diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index c99a74fdf..655cb71d4 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -633,6 +633,9 @@ UIWidget* UIAbstractTableView::updateCell( const Vector2& posIndex, const cell->getIcon()->setVisible( isVisible ); cell->updateCell( getModel() ); + + if ( mOnUpdateCellCb ) + mOnUpdateCellCb( cell, getModel() ); } if ( isCellSelection() ) { @@ -769,6 +772,15 @@ void UIAbstractTableView::setRowHeaderWidth( Float rowHeaderWidth ) { buildRowHeader(); } +bool UIAbstractTableView::hasOnUpdateCellCb() { + return mOnUpdateCellCb != nullptr; +} + +void UIAbstractTableView::setOnUpdateCellCb( + const std::function& onUpdateCellCb ) { + mOnUpdateCellCb = onUpdateCellCb; +} + void UIAbstractTableView::buildRowHeader() { if ( mRowHeaderWidth == 0 ) { if ( mRowHeader ) diff --git a/src/eepp/ui/uicheckbox.cpp b/src/eepp/ui/uicheckbox.cpp index 1f26580aa..556ee327b 100644 --- a/src/eepp/ui/uicheckbox.cpp +++ b/src/eepp/ui/uicheckbox.cpp @@ -146,6 +146,9 @@ void UICheckBox::switchState() { } UICheckBox* UICheckBox::setChecked( const bool& checked ) { + if ( checked == mChecked ) + return this; + if ( !checked ) { mActiveButton->setVisible( false ); mInactiveButton->setVisible( true ); diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index 37a83a837..20a25e391 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -297,6 +297,9 @@ UIWidget* UITreeView::updateCell( const Vector2& posIndex, const ModelInd cell->getIcon()->setVisible( isVisible ); cell->updateCell( getModel() ); + + if ( mOnUpdateCellCb ) + mOnUpdateCellCb( cell, getModel() ); } if ( isCellSelection() ) { diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index bcf4ab3d8..b19f79699 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -1458,6 +1458,9 @@ bool DebuggerPlugin::setBreakpoint( UICodeEditor* editor, Uint32 lineNumber ) { bool DebuggerPlugin::breakpointSetEnabled( const std::string& doc, Uint32 lineNumber, bool enabled ) { + if ( mChangingBreakpoint ) + return false; + BoolScopedOp changing( mChangingBreakpoint, true ); Lock l( mBreakpointsMutex ); auto& breakpoints = mBreakpoints[doc]; SourceBreakpointStateful sb( lineNumber ); diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index 117998746..b372bb7e7 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -83,6 +83,7 @@ class DebuggerPlugin : public PluginBase { bool mInitialized{ false }; bool mFetchRegisters{ false }; bool mFetchGlobals{ false }; + bool mChangingBreakpoint{ false }; std::string mProjectPath; std::vector mDaps; diff --git a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp index 1056594f3..1b5231f98 100644 --- a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp +++ b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp @@ -1,49 +1,53 @@ +#include "statusdebuggercontroller.hpp" #include "../plugincontextprovider.hpp" #include "eepp/ui/uiwidgetcreator.hpp" -#include "statusdebuggercontroller.hpp" #include namespace ecode { -std::function -UIBreakpointsTableView::getCheckBoxFn( const ModelIndex& index, const BreakpointsModel* model ) { - return [index, model, this]( UIPushButton* ) -> UITextView* { - UICheckBox* chk = UICheckBox::New(); - bool enabled = - model->data( model->index( index.row(), BreakpointsModel::Enabled ), ModelRole::Data ) - .asBool(); - chk->setChecked( enabled ); - chk->setCheckMode( UICheckBox::Button ); - chk->on( Event::OnValueChange, [this, index, model, chk]( const Event* ) { - bool checked = chk->isChecked(); - if ( !onBreakpointEnabledChange ) - return; - - std::string filePath( - model - ->data( model->index( index.row(), BreakpointsModel::SourcePath ), - ModelRole::Data ) - .asCStr() ); - int line( - model->data( model->index( index.row(), BreakpointsModel::Line ), ModelRole::Data ) - .asInt() ); - onBreakpointEnabledChange( filePath, line, checked ); - } ); - return chk; - }; -} - class UIBreakpointsTableCell : public UITableCell { public: - static UIBreakpointsTableCell* - New( const std::string& tag, - const std::function& newTextViewCb ) { - return eeNew( UIBreakpointsTableCell, ( tag, newTextViewCb ) ); + static UIBreakpointsTableCell* New( const std::string& tag, const BreakpointsModel* model, + ModelIndex curIndex ) { + return eeNew( UIBreakpointsTableCell, ( tag, model, curIndex ) ); } - UIBreakpointsTableCell( const std::string& tag, - const std::function& newTextViewCb ) : - UITableCell( tag, newTextViewCb ) {} + UIBreakpointsTableCell( const std::string& tag, const BreakpointsModel* model, + ModelIndex curIndex ) : + UITableCell( tag, getCheckBoxFn( model, curIndex ) ) {} + + std::function getCheckBoxFn( const BreakpointsModel* model, + ModelIndex index ) { + return [index, model, this]( UIPushButton* ) -> UITextView* { + UICheckBox* chk = UICheckBox::New(); + bool enabled = model + ->data( model->index( index.row(), BreakpointsModel::Enabled ), + ModelRole::Data ) + .asBool(); + chk->setChecked( enabled ); + chk->setCheckMode( UICheckBox::Button ); + chk->on( Event::OnValueChange, [this, chk]( const Event* ) { + auto parent = static_cast( getParent()->getParent() ); + auto model = parent->getModel(); + auto index = getCurIndex(); + bool checked = chk->isChecked(); + if ( !parent->onBreakpointEnabledChange ) + return; + + std::string filePath( + model + ->data( model->index( index.row(), BreakpointsModel::SourcePath ), + ModelRole::Data ) + .asCStr() ); + int line( model + ->data( model->index( index.row(), BreakpointsModel::Line ), + ModelRole::Data ) + .asInt() ); + parent->onBreakpointEnabledChange( filePath, line, checked ); + } ); + return chk; + }; + } virtual void updateCell( Model* model ) { if ( !mTextBox->isType( UI_TYPE_CHECKBOX ) ) @@ -59,7 +63,7 @@ class UIBreakpointsTableCell : public UITableCell { UIWidget* UIBreakpointsTableView::createCell( UIWidget* rowWidget, const ModelIndex& index ) { if ( index.column() == BreakpointsModel::Enabled ) { UIBreakpointsTableCell* widget = UIBreakpointsTableCell::New( - mTag + "::cell", getCheckBoxFn( index, (const BreakpointsModel*)getModel() ) ); + mTag + "::cell", (const BreakpointsModel*)getModel(), index ); widget->getTextBox()->setEnabled( true ); widget->setDontAutoHideEmptyTextBox( true ); return setupCell( widget, rowWidget, index ); diff --git a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.hpp b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.hpp index 1f305c6ad..d50a591b3 100644 --- a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.hpp +++ b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.hpp @@ -29,9 +29,6 @@ class UIBreakpointsTableView : public UITableView { std::function onBreakpointRemove; - std::function getCheckBoxFn( const ModelIndex& index, - const BreakpointsModel* model ); - UIWidget* createCell( UIWidget* rowWidget, const ModelIndex& index ); }; diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index b614c0e8d..22ea95057 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -3,6 +3,7 @@ #include "plugin.hpp" #include #include +#include #include #include #include @@ -395,8 +396,25 @@ PluginManager* PluginsModel::getManager() const { class UIPluginManagerTable : public UITableView { public: std::map readyCbs; + bool mUpdatingEnabled{ false }; - UIPluginManagerTable() : UITableView() {} + UIPluginManagerTable() : UITableView() { + setOnUpdateCellCb( [this]( UITableCell* cell, Model* model ) { + if ( mUpdatingEnabled ) + return; + if ( !cell->getTextBox()->isType( UI_TYPE_CHECKBOX ) ) + return; + UICheckBox* chk = cell->getTextBox()->asType(); + PluginsModel* pModel = static_cast( model ); + bool enabled = pModel + ->data( model->index( cell->getCurIndex().row(), + PluginsModel::Columns::Enabled ), + ModelRole::Display ) + .asBool(); + if ( enabled != chk->isChecked() ) + chk->setChecked( enabled ); + } ); + } std::function onModelEnabledChange; @@ -407,7 +425,15 @@ class UIPluginManagerTable : public UITableView { chk->setChecked( model->data( model->index( index.row(), PluginsModel::Enabled ) ).asBool() ); chk->setCheckMode( UICheckBox::Button ); - chk->on( Event::OnValueChange, [this, index, model, chk]( const Event* ) { + chk->on( Event::OnValueChange, [this, chk]( const Event* ) { + if ( mUpdatingEnabled ) + return; + BoolScopedOp op( mUpdatingEnabled, true ); + UITableCell* parent = chk->getParent()->asType(); + auto index = parent->getCurIndex(); + UIPluginManagerTable* tableView = + parent->getParent()->getParent()->asType(); + auto model = static_cast( tableView->getModel() ); bool checked = chk->isChecked(); std::string id( model->data( model->index( index.row(), PluginsModel::Id ) ).asCStr() ); @@ -440,11 +466,11 @@ UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager, ->loadLayoutFromString( R"xml( + window-min-size="300dp 50dp">