Improved UICheckBox. Fixed a bug and simplified UIPluginManager.

This commit is contained in:
Martín Lucas Golini
2024-01-28 02:15:58 -03:00
parent 2ae84f7c9d
commit 1399d23770
9 changed files with 89 additions and 47 deletions

View File

@@ -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

View File

@@ -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 {

View File

@@ -10,7 +10,6 @@
#include <eepp/system/color.hpp>
#include <eepp/system/time.hpp>
#include <eepp/ui/css/stylesheetlength.hpp>
#include <unordered_map>
#include <string>
using namespace EE::System;

View File

@@ -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<PropertyId> getPropertiesImplemented() const;
bool getCheckMode() const;
void setCheckMode( CheckMode mode );
protected:
UIWidget* mActiveButton;
UIWidget* mInactiveButton;
bool mChecked;
CheckMode mCheckMode{ CheckMode::TextAndButton };
Uint32 mLastTick;
Int32 mTextSeparation;

View File

@@ -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" );

View File

@@ -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<PropertyId> 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 );

View File

@@ -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<Git::Result()> 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,

View File

@@ -189,7 +189,7 @@ class GitPlugin : public PluginBase {
void openFileStatusMenu( const Git::DiffFile& file );
void runAsync( std::function<Git::Result()> 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 = "",

View File

@@ -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<std::string, Plugin*>( 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<UITextView*( UIPushButton* )> 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<UIPushButton>( "plugin-manager-preferences" );
UIPluginManagerTable* tv =
win->getContainer()->find<UIPluginManagerTable>( "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 } );