From 1399d23770a0b7f2f25403e65cf72dbac15108ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 28 Jan 2024 02:15:58 -0300 Subject: [PATCH] Improved UICheckBox. Fixed a bug and simplified UIPluginManager. --- docs/articles/cssspecification.md | 23 ++++++++++++ include/eepp/ui/css/propertydefinition.hpp | 1 + include/eepp/ui/css/stylesheetproperty.hpp | 1 - include/eepp/ui/uicheckbox.hpp | 7 ++++ src/eepp/ui/css/stylesheetspecification.cpp | 2 + src/eepp/ui/uicheckbox.cpp | 28 +++++++++++--- src/tools/ecode/plugins/git/gitplugin.cpp | 31 +++++++++------- src/tools/ecode/plugins/git/gitplugin.hpp | 2 +- src/tools/ecode/plugins/pluginmanager.cpp | 41 ++++++++------------- 9 files changed, 89 insertions(+), 47 deletions(-) diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 4db92d92c..d113a78a9 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -431,6 +431,29 @@ Sets the percentage of scroll of a page that triggers a page change in a ViewPag --- +### checked + +Sets as checkbox as checked + +* Applicable to: EE::UI::UICheckBox (CheckBox). +* Data Type: [boolean](#boolean-data-type) +* Default value: `false` + +--- + +### check-mode + +Checkboxs have two possible interaction modes for changing its checked state. + +* Applicable to: EE::UI::UICheckBox (CheckBox). +* Data Type: [string-list](#string-list-data-type) +* Value List: + * `element`: Checked state will change by clicking anywhere in the widget (clicking over text or icon) + * `button`: Checked state will only change by clicking over the icon +* Default value: `element` + +--- + ### click-step For any element that has a stepped value change, this sets the step variation for a click to the diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp index 8e9b18b6e..ed13d3080 100644 --- a/include/eepp/ui/css/propertydefinition.hpp +++ b/include/eepp/ui/css/propertydefinition.hpp @@ -217,6 +217,7 @@ enum class PropertyId : Uint32 { Name = String::hash( "name" ), RowValign = String::hash( "row-valign" ), TextOverflow = String::hash( "text-overflow" ), + CheckMode = String::hash( "check-mode" ), }; enum class PropertyType : Uint32 { diff --git a/include/eepp/ui/css/stylesheetproperty.hpp b/include/eepp/ui/css/stylesheetproperty.hpp index e30e0fe5a..7ad34805e 100644 --- a/include/eepp/ui/css/stylesheetproperty.hpp +++ b/include/eepp/ui/css/stylesheetproperty.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include using namespace EE::System; diff --git a/include/eepp/ui/uicheckbox.hpp b/include/eepp/ui/uicheckbox.hpp index 39264aae5..2cde649aa 100644 --- a/include/eepp/ui/uicheckbox.hpp +++ b/include/eepp/ui/uicheckbox.hpp @@ -8,6 +8,8 @@ namespace EE { namespace UI { class EE_API UICheckBox : public UITextView { public: + enum CheckMode { TextAndButton, Button }; + static UICheckBox* New(); static UICheckBox* NewWithTag( const std::string& tag ); @@ -41,10 +43,15 @@ class EE_API UICheckBox : public UITextView { virtual std::vector getPropertiesImplemented() const; + bool getCheckMode() const; + + void setCheckMode( CheckMode mode ); + protected: UIWidget* mActiveButton; UIWidget* mInactiveButton; bool mChecked; + CheckMode mCheckMode{ CheckMode::TextAndButton }; Uint32 mLastTick; Int32 mTextSeparation; diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index d4879ff72..f8fa4f6e6 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -409,6 +409,8 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "text-overflow", "clip" ).setType( PropertyType::String ); + registerProperty( "check-mode", "element" ).setType( PropertyType::String ); + // Shorthands registerShorthand( "margin", { "margin-top", "margin-right", "margin-bottom", "margin-left" }, "box" ); diff --git a/src/eepp/ui/uicheckbox.cpp b/src/eepp/ui/uicheckbox.cpp index 64a272b06..b6b2472dc 100644 --- a/src/eepp/ui/uicheckbox.cpp +++ b/src/eepp/ui/uicheckbox.cpp @@ -112,15 +112,17 @@ void UICheckBox::onSizeChange() { UITextView::onSizeChange(); } -Uint32 UICheckBox::onMessage( const NodeMessage* Msg ) { - switch ( Msg->getMsg() ) { +Uint32 UICheckBox::onMessage( const NodeMessage* msg ) { + switch ( msg->getMsg() ) { case NodeMessage::MouseClick: { - if ( Msg->getFlags() & EE_BUTTON_LMASK ) { - switchState(); + if ( msg->getFlags() & EE_BUTTON_LMASK ) { + if ( CheckMode::TextAndButton == mCheckMode || + ( msg->getSender() == mActiveButton || msg->getSender() == mInactiveButton ) ) + switchState(); } if ( NULL != getEventDispatcher() && - ( Msg->getSender() == mActiveButton || Msg->getSender() == mInactiveButton ) ) { + ( msg->getSender() == mActiveButton || msg->getSender() == mInactiveButton ) ) { sendMouseEvent( Event::MouseClick, getEventDispatcher()->getMousePos(), getEventDispatcher()->getPressTrigger() ); } @@ -230,6 +232,8 @@ std::string UICheckBox::getPropertyString( const PropertyDefinition* propertyDef case PropertyId::Checked: case PropertyId::Value: return isChecked() ? "true" : "false"; + case PropertyId::CheckMode: + return mCheckMode == CheckMode::TextAndButton ? "element" : "button"; default: return UITextView::getPropertyString( propertyDef, propertyIndex ); } @@ -238,9 +242,18 @@ std::string UICheckBox::getPropertyString( const PropertyDefinition* propertyDef std::vector UICheckBox::getPropertiesImplemented() const { auto props = UITextView::getPropertiesImplemented(); props.push_back( PropertyId::Checked ); + props.push_back( PropertyId::CheckMode ); return props; } +bool UICheckBox::getCheckMode() const { + return mCheckMode; +} + +void UICheckBox::setCheckMode( UICheckBox::CheckMode mode ) { + mCheckMode = mode; +} + bool UICheckBox::applyProperty( const StyleSheetProperty& attribute ) { if ( !checkPropertyDefinition( attribute ) ) return false; @@ -251,6 +264,11 @@ bool UICheckBox::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::Value: setChecked( attribute.asBool() ); break; + case PropertyId::CheckMode: + setCheckMode( String::toLower( attribute.value() ) == "button" + ? CheckMode::Button + : CheckMode::TextAndButton ); + break; case PropertyId::Tooltip: if ( mActiveButton ) mActiveButton->applyProperty( attribute ); diff --git a/src/tools/ecode/plugins/git/gitplugin.cpp b/src/tools/ecode/plugins/git/gitplugin.cpp index 19b5cb2c4..eb5bcc7a5 100644 --- a/src/tools/ecode/plugins/git/gitplugin.cpp +++ b/src/tools/ecode/plugins/git/gitplugin.cpp @@ -608,7 +608,7 @@ void GitPlugin::push() { "Are you sure you want to push the local changes to the remote server?" ) ); msgBox->on( Event::OnConfirm, [this]( auto ) { - runAsync( [this]() { return mGit->push( repoSelected() ); }, true, true, true ); + runAsync( [this]() { return mGit->push( repoSelected() ); }, true, true, true, true ); } ); msgBox->setCloseShortcut( { KEY_ESCAPE, KEYMOD_NONE } ); msgBox->setTitle( i18n( "git_confirm", "Confirm" ) ); @@ -1312,23 +1312,26 @@ void GitPlugin::openFileStatusMenu( const Git::DiffFile& file ) { } void GitPlugin::runAsync( std::function fn, bool _updateStatus, bool _updateBranches, - bool displaySuccessMsg ) { + bool displaySuccessMsg, bool updateBranchesOnError ) { if ( !mGit ) return; mLoader->setVisible( true ); - mThreadPool->run( [this, fn, _updateStatus, _updateBranches, displaySuccessMsg] { - auto res = fn(); - mLoader->runOnMainThread( [this] { mLoader->setVisible( false ); } ); - if ( res.fail() || displaySuccessMsg ) { - showMessage( LSPMessageType::Warning, res.result ); - return; - } - if ( _updateBranches ) - updateBranches( true ); + mThreadPool->run( + [this, fn, _updateStatus, _updateBranches, displaySuccessMsg, updateBranchesOnError] { + auto res = fn(); + mLoader->runOnMainThread( [this] { mLoader->setVisible( false ); } ); + if ( res.fail() || displaySuccessMsg ) { + showMessage( LSPMessageType::Warning, res.result ); + if ( _updateBranches && updateBranchesOnError ) + updateBranches(); + return; + } + if ( _updateBranches ) + updateBranches(); - if ( _updateStatus ) - updateStatus( true ); - } ); + if ( _updateStatus ) + updateStatus( true ); + } ); } void GitPlugin::addMenuItem( UIMenu* menu, const std::string& txtKey, const std::string& txtVal, diff --git a/src/tools/ecode/plugins/git/gitplugin.hpp b/src/tools/ecode/plugins/git/gitplugin.hpp index fe73a53b3..ea2d04fb5 100644 --- a/src/tools/ecode/plugins/git/gitplugin.hpp +++ b/src/tools/ecode/plugins/git/gitplugin.hpp @@ -189,7 +189,7 @@ class GitPlugin : public PluginBase { void openFileStatusMenu( const Git::DiffFile& file ); void runAsync( std::function fn, bool updateStatus, bool updateBranches, - bool displaySuccessMsg = false ); + bool displaySuccessMsg = false, bool updateBranchesOnError = false ); void addMenuItem( UIMenu* menu, const std::string& txtKey, const std::string& txtVal, const std::string& icon = "", diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index 8cb0e775d..216179945 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -51,8 +51,8 @@ bool PluginManager::setEnabled( const std::string& id, bool enable, bool sync ) if ( enable && plugin == nullptr && hasDefinition( id ) ) { Log::debug( "PluginManager: loading plugin %s", mDefinitions[id].name ); Plugin* newPlugin = sync && mDefinitions[id].creatorSyncFn - ? mDefinitions[id].creatorSyncFn( this ) - : mDefinitions[id].creatorFn( this ); + ? mDefinitions[id].creatorSyncFn( this ) + : mDefinitions[id].creatorFn( this ); mPlugins.insert( std::pair( id, newPlugin ) ); if ( onPluginEnabled ) onPluginEnabled( newPlugin ); @@ -170,9 +170,8 @@ PluginRequestHandle PluginManager::sendRequest( PluginMessageType type, PluginMe return PluginRequestHandle::empty(); } -PluginRequestHandle PluginManager::sendRequest( Plugin* pluginWho, - PluginMessageType type, PluginMessageFormat format, - const void* data ) { +PluginRequestHandle PluginManager::sendRequest( Plugin* pluginWho, PluginMessageType type, + PluginMessageFormat format, const void* data ) { if ( mClosing ) return PluginRequestHandle::empty(); SubscribedPlugins subscribedPlugins; @@ -365,26 +364,18 @@ class UIPluginManagerTable : public UITableView { std::function getCheckBoxFn( const ModelIndex& index, const PluginsModel* model ) { - return [index, model, this]( UIPushButton* but ) -> UITextView* { + return [index, model, this]( UIPushButton* ) -> UITextView* { UICheckBox* chk = UICheckBox::New(); chk->setChecked( model->data( model->index( index.row(), PluginsModel::Enabled ) ).asBool() ); - but->addEventListener( Event::MouseClick, [&, index, model, chk]( const Event* event ) { - if ( !( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) ) - return 1; - UIWidget* chkBut = chk->getCurrentButton(); - auto mousePos = - chkBut->convertToNodeSpace( event->asMouseEvent()->getPosition().asFloat() ); - if ( chkBut->getLocalBounds().contains( mousePos ) ) { - bool checked = !chk->isChecked(); - chk->setChecked( checked ); - std::string id( - model->data( model->index( index.row(), PluginsModel::Id ) ).asCStr() ); - model->getManager()->setEnabled( id, checked ); - if ( onModelEnabledChange ) - onModelEnabledChange( id, checked ); - } - return 1; + chk->setCheckMode( UICheckBox::Button ); + chk->on( Event::OnValueChange, [&, index, model, chk]( const Event* ) { + bool checked = chk->isChecked(); + std::string id( + model->data( model->index( index.row(), PluginsModel::Id ) ).asCStr() ); + model->getManager()->setEnabled( id, checked ); + if ( onModelEnabledChange ) + onModelEnabledChange( id, checked ); } ); return chk; }; @@ -394,6 +385,7 @@ class UIPluginManagerTable : public UITableView { if ( index.column() == PluginsModel::Title ) { UITableCell* widget = UITableCell::NewWithOpt( mTag + "::cell", getCheckBoxFn( index, (const PluginsModel*)getModel() ) ); + widget->getTextBox()->setEnabled( true ); return setupCell( widget, rowWidget, index ); } return UITableView::createCell( rowWidget, index ); @@ -432,10 +424,7 @@ UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager, UIPushButton* prefs = cont->find( "plugin-manager-preferences" ); UIPluginManagerTable* tv = win->getContainer()->find( "plugin-manager-table" ); - close->addEventListener( Event::MouseClick, [win]( const Event* event ) { - if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) - win->closeWindow(); - } ); + close->onClick( [win]( const MouseEvent* ) { win->closeWindow(); } ); tv->setModel( PluginsModel::New( manager ) ); tv->setColumnsVisible( { PluginsModel::Title, PluginsModel::Description, PluginsModel::Version } );