diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 08c98dcf7..c99a74fdf 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -1009,6 +1009,8 @@ void UIAbstractTableView::recalculateColumnsWidth() { } UITableCell* UIAbstractTableView::getCellFromIndex( const ModelIndex& index ) const { + if ( !index.isValid() ) + return nullptr; for ( const auto& row : mWidgets ) { for ( const auto& widget : row ) { if ( widget.second->isType( UI_TYPE_TABLECELL ) && diff --git a/src/tools/ecode/plugins/debugger/dap/protocol.hpp b/src/tools/ecode/plugins/debugger/dap/protocol.hpp index 2b8553282..735b44258 100644 --- a/src/tools/ecode/plugins/debugger/dap/protocol.hpp +++ b/src/tools/ecode/plugins/debugger/dap/protocol.hpp @@ -509,7 +509,7 @@ template <> struct std::hash { size_t h4 = breakpoint.hitCondition ? std::hash()( *breakpoint.hitCondition ) : 0; size_t h5 = breakpoint.logMessage ? std::hash()( *breakpoint.logMessage ) : 0; - size_t h6 = std::hash()( breakpoint.enabled ); - return hashCombine( h1, h2, h3, h4, h5, h6 ); + // size_t h6 = std::hash()( breakpoint.enabled ); + return hashCombine( h1, h2, h3, h4, h5/*, h6*/ ); } }; diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp index 4b178ddbe..38c524200 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp @@ -13,7 +13,7 @@ namespace ecode { std::vector -DebuggerClientListener::fromSet( const EE::UnorderedSet& set ) { +DebuggerClientListener::fromSet( const UnorderedSet& set ) { std::vector bps; bps.reserve( set.size() ); for ( const auto& bp : set ) @@ -326,7 +326,7 @@ void DebuggerClientListener::changeScope( const StackFrame& f ) { if ( !f.source ) return; - TextRange range{ { f.line - 1, f.column }, { f.line - 1, f.column } }; + TextRange range{ { f.line - 1, f.column - 1 }, { f.line - 1, f.column - 1 } }; std::string path( f.source->path ); mPlugin->getUISceneNode()->runOnMainThread( diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp index c93348c9d..aaf382f03 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp @@ -14,7 +14,7 @@ struct ModelVariableNode; class DebuggerClientListener : public DebuggerClient::Listener { public: static std::vector - fromSet( const EE::UnorderedSet& set ); + fromSet( const UnorderedSet& set ); DebuggerClientListener( DebuggerClient* client, DebuggerPlugin* plugin ); diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index b46b70333..bcf4ab3d8 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -1,3 +1,4 @@ +#include "debuggerplugin.hpp" #include "../../notificationcenter.hpp" #include "../../projectbuild.hpp" #include "../../terminalmanager.hpp" @@ -7,7 +8,6 @@ #include "bussocket.hpp" #include "bussocketprocess.hpp" #include "dap/debuggerclientdap.hpp" -#include "debuggerplugin.hpp" #include "models/breakpointsmodel.hpp" #include "models/processesmodel.hpp" #include "models/variablesmodel.hpp" @@ -1460,12 +1460,15 @@ bool DebuggerPlugin::breakpointSetEnabled( const std::string& doc, Uint32 lineNu bool enabled ) { Lock l( mBreakpointsMutex ); auto& breakpoints = mBreakpoints[doc]; - auto breakpointIt = breakpoints.find( SourceBreakpointStateful( lineNumber ) ); + SourceBreakpointStateful sb( lineNumber ); + auto breakpointIt = breakpoints.find( sb ); if ( breakpointIt != breakpoints.end() ) { - breakpointIt->enabled = enabled; - mBreakpointsModel->enable( doc, lineNumber, breakpointIt->enabled ); - mThreadPool->run( [this, doc] { sendFileBreakpoints( doc ); } ); - getUISceneNode()->getRoot()->invalidateDraw(); + if ( enabled != breakpointIt->enabled ) { + breakpointIt->enabled = enabled; + mBreakpointsModel->enable( doc, lineNumber, enabled ); + mThreadPool->run( [this, doc] { sendFileBreakpoints( doc ); } ); + getUISceneNode()->getRoot()->invalidateDraw(); + } return true; } return false; @@ -1488,9 +1491,16 @@ bool DebuggerPlugin::breakpointToggleEnabled( TextDocument* doc, Uint32 lineNumb return breakpointToggleEnabled( doc->getFilePath(), lineNumber ); } +bool DebuggerPlugin::hasBreakpoint( const std::string& doc, Uint32 lineNumber ) { + Lock l( mBreakpointsMutex ); + auto& breakpoints = mBreakpoints[doc]; + auto breakpointIt = breakpoints.find( SourceBreakpointStateful( lineNumber ) ); + return breakpointIt != breakpoints.end(); +} + bool DebuggerPlugin::onMouseDown( UICodeEditor* editor, const Vector2i& position, const Uint32& flags ) { - if ( !( flags & EE_BUTTON_LMASK ) ) + if ( !( flags & ( EE_BUTTON_LMASK | EE_BUTTON_RMASK ) ) ) return false; Float offset = editor->getGutterLocalStartOffset( this ); Vector2f localPos( editor->convertToNodeSpace( position.asFloat() ) ); @@ -1500,7 +1510,12 @@ bool DebuggerPlugin::onMouseDown( UICodeEditor* editor, const Vector2i& position localPos.y > editor->getPluginsTopSpace() ) { if ( editor->getUISceneNode()->getEventDispatcher()->isFirstPress() ) { auto cursorPos( editor->resolveScreenPosition( position.asFloat() ) ); - setBreakpoint( editor, cursorPos.line() + 1 ); + if ( ( flags & EE_BUTTON_RMASK ) && + hasBreakpoint( editor->getDocument().getFilePath(), cursorPos.line() + 1 ) ) { + breakpointToggleEnabled( &editor->getDocument(), cursorPos.line() + 1 ); + } else { + setBreakpoint( editor, cursorPos.line() + 1 ); + } } return true; } diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index 66943a249..117998746 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -187,6 +187,8 @@ class DebuggerPlugin : public PluginBase { bool breakpointSetEnabled( const std::string& doc, Uint32 lineNumber, bool enabled ); + bool hasBreakpoint( const std::string& doc, Uint32 lineNumber ); + bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& flags ) override; bool isSupportedByAnyDebugger( const std::string& language ); diff --git a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp index 00c170798..1d5e7c2b5 100644 --- a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp +++ b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp @@ -106,4 +106,11 @@ void BreakpointsModel::enable( const std::string& filePath, } } +const std::pair& BreakpointsModel::get( ModelIndex index ) { + static std::pair EMPTY = {}; + if ( !index.isValid() || index.row() >= static_cast( mBreakpoints.size() ) ) + return EMPTY; + return mBreakpoints[index.row()]; +} + } // namespace ecode diff --git a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp index 1cf3653a8..3d4cbbc07 100644 --- a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp +++ b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp @@ -38,6 +38,7 @@ class BreakpointsModel : public Model { void enable( const std::string& filePath, const SourceBreakpointStateful& breakpoint, bool enable ); + const std::pair& get( ModelIndex index ); protected: std::vector> mBreakpoints; UISceneNode* mSceneNode{ nullptr }; diff --git a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp index 10e4e68d0..1056594f3 100644 --- a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp +++ b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp @@ -1,6 +1,6 @@ -#include "statusdebuggercontroller.hpp" #include "../plugincontextprovider.hpp" #include "eepp/ui/uiwidgetcreator.hpp" +#include "statusdebuggercontroller.hpp" #include namespace ecode { @@ -33,9 +33,32 @@ UIBreakpointsTableView::getCheckBoxFn( const ModelIndex& index, const Breakpoint }; } +class UIBreakpointsTableCell : public UITableCell { + public: + static UIBreakpointsTableCell* + New( const std::string& tag, + const std::function& newTextViewCb ) { + return eeNew( UIBreakpointsTableCell, ( tag, newTextViewCb ) ); + } + + UIBreakpointsTableCell( const std::string& tag, + const std::function& newTextViewCb ) : + UITableCell( tag, newTextViewCb ) {} + + virtual void updateCell( Model* model ) { + if ( !mTextBox->isType( UI_TYPE_CHECKBOX ) ) + return; + auto bpModel = static_cast( model ); + auto cur = bpModel->get( getCurIndex() ); + if ( cur.first.empty() ) + return; + mTextBox->asType()->setChecked( cur.second.enabled ); + } +}; + UIWidget* UIBreakpointsTableView::createCell( UIWidget* rowWidget, const ModelIndex& index ) { if ( index.column() == BreakpointsModel::Enabled ) { - UITableCell* widget = UITableCell::NewWithOpt( + UIBreakpointsTableCell* widget = UIBreakpointsTableCell::New( mTag + "::cell", getCheckBoxFn( index, (const BreakpointsModel*)getModel() ) ); widget->getTextBox()->setEnabled( true ); widget->setDontAutoHideEmptyTextBox( true );