Minor fixes in UITreeView.

Minor fixes in debugger and some new menues.
This commit is contained in:
Martín Lucas Golini
2025-01-22 00:59:52 -03:00
parent 40d21de8dd
commit c945b0b659
10 changed files with 154 additions and 70 deletions

View File

@@ -333,6 +333,11 @@ void UIAbstractTableView::updateColumnsWidth() {
if ( columnData( col ).width != width ) {
columnData( col ).width = width;
updateHeaderSize();
ColumnData& colData = columnData( col );
if ( colData.widget )
colData.widget->setPixelsSize( colData.width, getHeaderHeight() );
onColumnSizeChange( col );
}
}

View File

@@ -1573,7 +1573,9 @@ Uint32 UICodeEditor::onMouseUp( const Vector2i& position, const Uint32& flags )
} else if ( flags & EE_BUTTON_WLMASK ) {
setScrollX( mScroll.x - mMouseWheelScroll );
} else if ( !minimapHover && ( flags & EE_BUTTON_RMASK ) ) {
onCreateContextMenu( position, flags );
Vector2f localPos( convertToNodeSpace( position.asFloat() ) );
if ( localPos.x >= mPaddingPx.Left + getGutterWidth() && localPos.y >= mPluginsTopSpace )
onCreateContextMenu( position, flags );
}
return UIWidget::onMouseUp( position, flags );

View File

@@ -88,10 +88,10 @@ void UITreeView::traverseTree( TreeViewCallback callback ) const {
}
void UITreeView::createOrUpdateColumns( bool resetColumnData ) {
updateContentSize();
if ( !getModel() )
return;
UIAbstractTableView::createOrUpdateColumns( resetColumnData );
updateContentSize();
}
size_t UITreeView::getItemCount() const {
@@ -184,8 +184,8 @@ UIWidget* UITreeView::setupCell( UITableCell* widget, UIWidget* rowWidget,
widget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
widget->setTextAlign( UI_HALIGN_LEFT );
widget->setCurIndex( index );
bindNavigationClick( widget );
if ( index.column() == (Int64)getModel()->treeColumn() ) {
bindNavigationClick( widget );
widget->onClick( [this]( const MouseEvent* mouseEvent ) {
if ( mSingleClickNavigation )
return;
@@ -740,6 +740,10 @@ void UITreeView::setDisableCellClipping( bool disableCellClipping ) {
mDisableCellClipping = disableCellClipping;
}
void UITreeView::clearViewMetadata() {
mViewMetadata.clear();
}
void UITreeView::onSortColumn( const size_t& ) {
// Do nothing.
return;

View File

@@ -1,7 +1,8 @@
#include "debuggerclientlistener.hpp"
#include "../../notificationcenter.hpp"
#include "../../statusappoutputcontroller.hpp"
#include "debuggerclientlistener.hpp"
#include "debuggerplugin.hpp"
#include "eepp/window/clipboard.hpp"
#include "models/stackmodel.hpp"
#include "models/threadsmodel.hpp"
#include "models/variablesmodel.hpp"
@@ -87,13 +88,73 @@ void DebuggerClientListener::initUI() {
uiVariables->setModel( mVariablesHolder->getModel() );
uiVariables->removeEventsOfType( Event::OnModelEvent );
uiVariables->onModelEvent( [this]( const ModelEvent* modelEvent ) {
auto idx( modelEvent->getModelIndex() );
if ( modelEvent->getModelEventType() == Abstract::ModelEventType::OpenTree ) {
ModelVariableNode* node =
static_cast<ModelVariableNode*>( modelEvent->getModelIndex().internalData() );
ModelVariableNode* node = static_cast<ModelVariableNode*>( idx.internalData() );
mClient->variables( node->var.variablesReference );
mVariablesHolder->saveExpandedState( modelEvent->getModelIndex() );
mVariablesHolder->saveExpandedState( idx );
} else if ( modelEvent->getModelEventType() == Abstract::ModelEventType::CloseTree ) {
mVariablesHolder->removeExpandedState( modelEvent->getModelIndex() );
mVariablesHolder->removeExpandedState( idx );
} else if ( modelEvent->getModelEventType() == Abstract::ModelEventType::OpenMenu &&
idx.isValid() ) {
auto context = mPlugin->getPluginContext();
UIPopUpMenu* menu = UIPopUpMenu::New();
ModelVariableNode* node = static_cast<ModelVariableNode*>( idx.internalData() );
Variable var( node->var );
menu->add( context->i18n( "debugger_copy_variable_value", "Copy Value" ),
context->findIcon( "copy" ) )
->setId( "debugger_copy_variable_value" );
menu->add( context->i18n( "debugger_copy_variable_name", "Copy Name" ),
context->findIcon( "copy" ) )
->setId( "debugger_copy_variable_name" );
if ( var.type ) {
menu->add( context->i18n( "debugger_copy_variable_type", "Copy Type" ),
context->findIcon( "copy" ) )
->setId( "debugger_copy_variable_type" );
}
if ( var.evaluateName ) {
menu->add( context->i18n( "debugger_copy_variable_evaluate_name",
"Copy Evaluate Name" ),
context->findIcon( "copy" ) )
->setId( "debugger_copy_variable_evaluate_name" );
}
if ( var.memoryReference ) {
menu->add( context->i18n( "debugger_copy_variable_memory_reference",
"Copy Memory Reference" ),
context->findIcon( "copy" ) )
->setId( "debugger_copy_variable_memory_reference" );
}
menu->on( Event::OnItemClicked, [this, var = std::move( var )]( const Event* event ) {
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
std::string id( item->getId() );
if ( id == "debugger_copy_variable_value" ) {
mPlugin->getUISceneNode()->getWindow()->getClipboard()->setText( var.value );
} else if ( id == "debugger_copy_variable_name" ) {
mPlugin->getUISceneNode()->getWindow()->getClipboard()->setText( var.name );
} else if ( id == "debugger_copy_variable_type" ) {
mPlugin->getUISceneNode()->getWindow()->getClipboard()->setText( *var.type );
} else if ( id == "debugger_copy_variable_evaluate_name" ) {
mPlugin->getUISceneNode()->getWindow()->getClipboard()->setText(
*var.evaluateName );
} else if ( id == "debugger_copy_variable_memory_reference" ) {
mPlugin->getUISceneNode()->getWindow()->getClipboard()->setText(
*var.memoryReference );
}
} );
Vector2f pos( context->getWindow()->getInput()->getMousePos().asFloat() );
menu->nodeToWorldTranslation( pos );
UIMenu::findBestMenuPos( pos, menu );
menu->setPixelsPosition( pos );
menu->show();
}
} );

View File

@@ -178,6 +178,8 @@ void DebuggerPlugin::onLoadProject( const std::string& projectFolder,
if ( !FileSystem::fileGet( debuggerStatePath, data ) )
return;
auto sdc = getStatusDebuggerController();
json j;
try {
j = json::parse( data, nullptr, true, true );
@@ -199,6 +201,9 @@ void DebuggerPlugin::onLoadProject( const std::string& projectFolder,
}
}
}
if ( sdc && sdc->getWidget() && sdc->getUIExpressions() )
sdc->getUIExpressions()->setModel( mExpressionsHolder->getModel() );
}
if ( config.contains( "breakpoints" ) && config["breakpoints"].is_object() ) {
@@ -221,13 +226,16 @@ void DebuggerPlugin::onLoadProject( const std::string& projectFolder,
mBreakpointsModel =
std::make_shared<BreakpointsModel>( mBreakpoints, getUISceneNode() );
}
if ( sdc && sdc->getWidget() && sdc->getUIBreakpoints() )
sdc->getUIBreakpoints()->setModel( mBreakpointsModel );
}
}
} catch ( const json::exception& e ) {
Log::error(
"DebuggerPlugin::onLoadProject - Error parsing config from path %s, error: %s, config "
"file content:\n%s",
debuggerStatePath.c_str(), e.what(), data.c_str() );
debuggerStatePath, e.what(), data );
}
}
@@ -246,8 +254,11 @@ void DebuggerPlugin::resetExpressions() {
if ( !mExpressionsHolder )
return;
mExpressionsHolder->clear( true );
std::vector<ModelVariableNode::NodePtr> childs;
childs.reserve( mExpressions.size() );
for ( const auto& expression : mExpressions )
mExpressionsHolder->addChild( std::make_shared<ModelVariableNode>( expression, 0 ) );
childs.emplace_back( std::make_shared<ModelVariableNode>( expression, 0 ) );
mExpressionsHolder->addChilds( childs );
}
void DebuggerPlugin::closeProject() {
@@ -760,8 +771,7 @@ void DebuggerPlugin::removeExpression( const std::string& name ) {
resetExpressions();
}
void DebuggerPlugin::openExpressionMenu( UITreeView* uiExpressions, ModelIndex idx,
bool fromMouseClick ) {
void DebuggerPlugin::openExpressionMenu( ModelIndex idx ) {
UIPopUpMenu* menu = UIPopUpMenu::New();
auto context = getPluginContext();
@@ -801,19 +811,10 @@ void DebuggerPlugin::openExpressionMenu( UITreeView* uiExpressions, ModelIndex i
}
} );
UITableCell* cell = uiExpressions->getCellFromIndex( idx );
if ( fromMouseClick || cell == nullptr ) {
Vector2f pos( context->getWindow()->getInput()->getMousePos().asFloat() );
menu->nodeToWorldTranslation( pos );
UIMenu::findBestMenuPos( pos, menu );
menu->setPixelsPosition( pos );
} else {
Vector2f pos( 0, cell->getPixelsSize().getHeight() );
cell->nodeToWorldTranslation( pos );
UIMenu::findBestMenuPos( pos, menu );
menu->setPixelsPosition( pos );
}
Vector2f pos( context->getWindow()->getInput()->getMousePos().asFloat() );
menu->nodeToWorldTranslation( pos );
UIMenu::findBestMenuPos( pos, menu );
menu->setPixelsPosition( pos );
menu->show();
}
void DebuggerPlugin::buildStatusBar() {
@@ -842,9 +843,9 @@ void DebuggerPlugin::buildStatusBar() {
UITreeView* uiExpressions = sdc->getUIExpressions();
uiExpressions->setModel( mExpressionsHolder->getModel() );
uiExpressions->removeEventsOfType( Event::OnModelEvent );
uiExpressions->onModelEvent( [this, uiExpressions]( const ModelEvent* modelEvent ) {
uiExpressions->onModelEvent( [this]( const ModelEvent* modelEvent ) {
if ( modelEvent->getModelEventType() == Abstract::ModelEventType::OpenMenu ) {
openExpressionMenu( uiExpressions, modelEvent->getModelIndex(), true );
openExpressionMenu( modelEvent->getModelIndex() );
} else if ( mDebugger && mListener &&
modelEvent->getModelEventType() == Abstract::ModelEventType::OpenTree ) {
ModelVariableNode* node =
@@ -861,11 +862,8 @@ void DebuggerPlugin::buildStatusBar() {
}
} );
uiExpressions->removeEventsOfType( Event::MouseClick );
uiExpressions->onClick(
[this, uiExpressions]( const MouseEvent* ) {
openExpressionMenu( uiExpressions, {}, true );
},
MouseButton::EE_BUTTON_RIGHT );
uiExpressions->onClick( [this]( const MouseEvent* ) { openExpressionMenu( {} ); },
MouseButton::EE_BUTTON_RIGHT );
auto uiBreakpoints = sdc->getUIBreakpoints();
if ( nullptr == uiBreakpoints->onBreakpointEnabledChange ) {
@@ -947,8 +945,7 @@ void DebuggerPlugin::sendPendingBreakpoints() {
for ( const auto& pbp : mPendingBreakpoints )
sendFileBreakpoints( pbp );
mPendingBreakpoints.clear();
if ( mDebugger )
mDebugger->resume( mListener->getCurrentThreadId() );
resume( mListener->getCurrentThreadId() );
}
void DebuggerPlugin::sendFileBreakpoints( const std::string& filePath ) {
@@ -1227,7 +1224,7 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) {
doc->setCommand( "debugger-continue-interrupt", [this] {
if ( mDebugger && mListener ) {
if ( mListener->isStopped() ) {
mDebugger->resume( mListener->getCurrentThreadId() );
resume( mListener->getCurrentThreadId() );
} else {
mDebugger->pause( 1 );
}
@@ -1763,6 +1760,18 @@ UIWindow* DebuggerPlugin::processPicker() {
return win;
}
bool DebuggerPlugin::resume( int threadId, bool singleThread ) {
mHoverExpressionsHolder->clear( true );
if ( mHoverTooltip && mHoverTooltip->isVisible() )
mHoverTooltip->hide();
if ( !mDebugger )
return false;
return mDebugger->resume( threadId, singleThread );
}
std::optional<Command>
DebuggerPlugin::debuggerBinaryExists( const std::string& debugger,
std::optional<DapRunConfig> optRunConfig ) {
@@ -2025,17 +2034,11 @@ static Action::UniqueID getMouseMoveHash( UICodeEditor* editor ) {
reinterpret_cast<Action::UniqueID>( editor ) );
}
void DebuggerPlugin::hideTooltip( UICodeEditor* ) {
// if ( mHoverTooltip ) {
// mHoverTooltip->hide();
// }
}
void DebuggerPlugin::displayTooltip( UICodeEditor* editor, const std::string& expression,
const EvaluateInfo& info, const Vector2f& position ) {
if ( mHoverTooltip == nullptr ) {
UIWindow* win =
UIWindow::NewOpt( UIMessageBox::WindowBaseContainerType::VERTICAL_LINEAR_LAYOUT );
UIWindow* win = UIWindow::New();
win->setId( "debugger_hover_window" );
win->setMinWindowSize( 400, 250 );
win->setKeyBindingCommand( "closeWindow", [this, win, editor] {
win->closeWindow();
@@ -2044,20 +2047,26 @@ void DebuggerPlugin::displayTooltip( UICodeEditor* editor, const std::string& ex
editor->setFocus();
} );
win->getKeyBindings().addKeybind( { KEY_ESCAPE }, "closeWindow" );
win->setWindowFlags( UI_WIN_NO_DECORATION | UI_WIN_SHADOW | UI_WIN_EPHEMERAL );
win->setWindowFlags( UI_WIN_CLOSE_BUTTON | UI_WIN_USE_DEFAULT_BUTTONS_ACTIONS |
UI_WIN_SHADOW | UI_WIN_EPHEMERAL | UI_WIN_RESIZEABLE |
UI_WIN_DRAGABLE_CONTAINER | UI_WIN_SHARE_ALPHA_WITH_CHILDS );
win->center();
win->on( Event::OnWindowClose, [this]( auto ) { mHoverTooltip = nullptr; } );
win->on( Event::OnWindowReady, [win]( auto ) { win->setFocus(); } );
UILinearLayout* vbox = UILinearLayout::NewVertical();
vbox->setParent( win->getContainer() );
vbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
UITreeView* tv = UITreeView::New();
tv->setId( "debugger_hover_treeview" );
tv->setHeadersVisible( false );
tv->setAutoExpandOnSingleColumn( true );
tv->setAutoColumnsWidth( true );
tv->setFitAllColumnsToWidget( true );
tv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed );
tv->setLayoutWeight( 1 );
tv->setParent( win->getContainer() );
tv->setParent( vbox );
tv->setModel( mHoverExpressionsHolder->getModel() );
tv->expandAll();
tv->setFocusOnSelection( false );
tv->on( Event::OnModelEvent, [this]( const Event* event ) {
@@ -2078,6 +2087,10 @@ void DebuggerPlugin::displayTooltip( UICodeEditor* editor, const std::string& ex
mHoverTooltip = win;
}
if ( editor->getTooltip() )
editor->getTooltip()->hide();
mHoverTooltip->find( "debugger_hover_treeview" )->asType<UITreeView>()->clearViewMetadata();
mHoverExpressionsHolder->clear( true );
Variable var;
@@ -2098,25 +2111,11 @@ void DebuggerPlugin::displayTooltip( UICodeEditor* editor, const std::string& ex
mHoverTooltip->showWhenReady();
}
void DebuggerPlugin::tryHideTooltip( UICodeEditor* editor, const Vector2i& position ) {
if ( ( editor->hasDocument() && editor->getDocument().isLoading() ) ||
!mCurrentHover.isValid() ||
( mCurrentHover.isValid() &&
!mCurrentHover.contains( editor->resolveScreenPosition( position.asFloat() ) ) ) )
hideTooltip( editor );
}
bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position,
const Uint32& flags ) {
if ( !mDebugger || !mListener || !mDebugger->isServerConnected() ||
mDebuggingState != StatusDebuggerController::State::Paused ) {
tryHideTooltip( editor, position );
return false;
}
if ( flags != 0 ) {
tryHideTooltip( editor, position );
mDebuggingState != StatusDebuggerController::State::Paused || flags != 0 ) {
return false;
}
@@ -2167,7 +2166,6 @@ bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position
} );
},
mHoverDelay, getMouseMoveHash( editor ) );
tryHideTooltip( editor, position );
editor->updateMouseCursor( position.asFloat() );
return true;
}

View File

@@ -203,13 +203,9 @@ class DebuggerPlugin : public PluginBase {
void updatePanelUIState( StatusDebuggerController::State state );
void hideTooltip( UICodeEditor* editor );
void displayTooltip( UICodeEditor* editor, const std::string& expression,
const EvaluateInfo& info, const Vector2f& position );
void tryHideTooltip( UICodeEditor* editor, const Vector2i& position );
bool onMouseMove( UICodeEditor* editor, const Vector2i& position,
const Uint32& flags ) override;
@@ -217,7 +213,7 @@ class DebuggerPlugin : public PluginBase {
void loadProjectConfigurations();
void openExpressionMenu( UITreeView* uiExpressions, ModelIndex idx, bool fromMouseClick );
void openExpressionMenu( ModelIndex idx );
void updateSelectedDebugConfig();
@@ -238,6 +234,8 @@ class DebuggerPlugin : public PluginBase {
std::unordered_map<std::string, std::string> solvedInputs );
UIWindow* processPicker();
bool resume( int threadId, bool singleThread = false );
};
} // namespace ecode

View File

@@ -213,6 +213,15 @@ void VariablesHolder::addChild( ModelVariableNode::NodePtr child ) {
mModel->invalidate( Model::UpdateFlag::InvalidateAllIndexes );
}
void VariablesHolder::addChilds( const std::vector<ModelVariableNode::NodePtr>& childs ) {
Lock l( mMutex );
for ( auto& child : childs) {
mRootNode->addChild( child );
mNodeMap[child->var.variablesReference] = child;
}
mModel->invalidate( Model::UpdateFlag::InvalidateAllIndexes );
}
void VariablesHolder::upsertRootChild( Variable&& var ) {
Lock l( mMutex );
for ( size_t i = 0; i < mRootNode->children.size(); i++ ) {

View File

@@ -131,6 +131,8 @@ class VariablesHolder {
void addChild( ModelVariableNode::NodePtr child );
void addChilds( const std::vector<ModelVariableNode::NodePtr>& childs );
void upsertRootChild( Variable&& );
void clear( bool all = false );

View File

@@ -159,8 +159,11 @@ void StatusDebuggerController::createContainer() {
#app_debugger_buttons > PushButton:disabled {
tint: var(--disabled-color);
}
#app_debugger.vertical_bar {
background-color: none;
}
</style>
<hbox id="app_debugger" class="vertical_bar" lw="mp" lh="mp" visible="false">
<hbox id="app_debugger" lw="mp" lh="mp" visible="false">
<TabWidget id="app_debugger_tab_widget" lw="0" lw8="1" lh="mp">
<Splitter id="debugger_threads_and_stack" layout_width="mp" lh="mp" splitter-partition="15%">
<TableView id="debugger_threads" layout_width="mp" layout_height="mp" />
@@ -176,7 +179,7 @@ void StatusDebuggerController::createContainer() {
<Tab id="debugger_tab_breakpoints" text="@string(breakpoints, Breakpoints)" owns="debugger_breakpoints" />
<Tab id="debugger_tab_console" text="@string(console_output, Console Output)" owns="debugger_console" />
</TabWidget>
<vbox id="app_debugger_buttons" lw="16dp" lh="mp">
<vbox id="app_debugger_buttons" class="vertical_bar" lw="16dp" lh="mp">
<PushButton id="app_debugger_start" class="debugger_start" lw="mp" icon="icon(debug-start, 12dp)" tooltip="@string(start, Start)" />
<PushButton id="app_debugger_stop" class="debugger_stop" lw="mp" icon="icon(debug-stop, 12dp)" tooltip="@string(stop, Stop)" />
<PushButton id="app_debugger_continue" class="debugger_continue" lw="mp" icon="icon(debug-continue, 12dp)" tooltip="@string(continue, Continue)" />