diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 46715cfb9..58142c589 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -40,6 +40,7 @@ --floating-icon: #eff0f188; --term-back-color: #1e2127; --term-font-color: #abb2bf; + --highlight-primary: #FFFFFF7A; droppable-hovering-color: #FFFFFF20; } @@ -195,6 +196,13 @@ CheckBox::active { background-position: center; } +tableview::row:selected CheckBox::active, +treeview::row:selected CheckBox::active, +listview::row:selected CheckBox::active { + border-color: var(--highlight-primary); + background-image: rectangle(solid, var(--highlight-primary)); +} + RadioButton::active, RadioButton::inactive { width: 12dp; diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index 46c62fd1d..10ad7b921 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -7,6 +7,11 @@ namespace EE { namespace Scene { class Node; +class MouseEvent; +class KeyEvent; +class DropEvent; +class TextEvent; +class TextInputEvent; class EE_API Event { public: @@ -100,6 +105,16 @@ class EE_API Event { const Uint32& getCallbackId() const; + const MouseEvent* asMouseEvent() const; + + const KeyEvent* asKeyEvent() const; + + const DropEvent* asDropEvent() const; + + const TextEvent* asTextEvent() const; + + const TextInputEvent* asTextInputEvent() const; + protected: friend class Node; Node* mNode; diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index 9f3128724..0e4b41c49 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -163,6 +163,9 @@ class EE_API UIAbstractTableView : public UIAbstractView { virtual UIWidget* createCell( UIWidget* rowWidget, const ModelIndex& index ); + virtual UIWidget* setupCell( UITableCell* widget, UIWidget* rowWidget, + const ModelIndex& index ); + virtual void onScrollChange(); virtual void onOpenModelIndex( const ModelIndex& index, const Event* triggerEvent = nullptr ); diff --git a/include/eepp/ui/uipushbutton.hpp b/include/eepp/ui/uipushbutton.hpp index e423f966d..b11b2ee35 100644 --- a/include/eepp/ui/uipushbutton.hpp +++ b/include/eepp/ui/uipushbutton.hpp @@ -15,10 +15,9 @@ class EE_API UIPushButton : public UIWidget { static UIPushButton* NewWithTag( const std::string& tag ); - static UIPushButton* NewWithOpt( const std::string& tag, - const std::function& newTextViewCb ); - - UIPushButton(); + static UIPushButton* + NewWithOpt( const std::string& tag, + const std::function& newTextViewCb ); virtual ~UIPushButton(); @@ -72,9 +71,12 @@ class EE_API UIPushButton : public UIWidget { InnerWidgetOrientation mInnerWidgetOrientation{ InnerWidgetOrientation::Right }; bool mTextAsFallback{ false }; + UIPushButton(); + explicit UIPushButton( const std::string& tag ); - explicit UIPushButton( const std::string& tag, const std::function& cb ); + explicit UIPushButton( const std::string& tag, + const std::function& cb ); virtual Rectf calculatePadding() const; diff --git a/include/eepp/ui/uitablecell.hpp b/include/eepp/ui/uitablecell.hpp index cf37455c3..21258db98 100644 --- a/include/eepp/ui/uitablecell.hpp +++ b/include/eepp/ui/uitablecell.hpp @@ -14,6 +14,12 @@ class EE_API UITableCell : public UIPushButton { static UITableCell* New( const std::string& tag ) { return eeNew( UITableCell, ( tag ) ); } + static UITableCell* + NewWithOpt( const std::string& tag, + const std::function& newTextViewCb ) { + return eeNew( UITableCell, ( tag, newTextViewCb ) ); + } + Uint32 getType() const { return UI_TYPE_TABLECELL; } bool isType( const Uint32& type ) const { @@ -43,7 +49,7 @@ class EE_API UITableCell : public UIPushButton { UITableCell() : UITableCell( "table::cell" ) {} UITableCell( const std::string& tag, - const std::function& newTextViewCb = nullptr ) : + const std::function& newTextViewCb = nullptr ) : UIPushButton( tag, newTextViewCb ) { applyDefaultTheme(); } diff --git a/include/eepp/ui/uitreeview.hpp b/include/eepp/ui/uitreeview.hpp index d5e835ee5..853e20631 100644 --- a/include/eepp/ui/uitreeview.hpp +++ b/include/eepp/ui/uitreeview.hpp @@ -58,7 +58,7 @@ class EE_API UITreeViewCell : public UITableCell { mutable UIImage* mImage{ nullptr }; Float mIndent{ 0 }; - UITreeViewCell( const std::function& newTextViewCb = nullptr ) : + UITreeViewCell( const std::function& newTextViewCb = nullptr ) : UITableCell( "treeview::cell", newTextViewCb ) { mTextBox->setElementTag( mTag + "::text" ); mIcon->setElementTag( mTag + "::icon" ); diff --git a/src/eepp/scene/event.cpp b/src/eepp/scene/event.cpp index 4ff60271b..e466d35ab 100644 --- a/src/eepp/scene/event.cpp +++ b/src/eepp/scene/event.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include namespace EE { namespace Scene { @@ -19,4 +21,24 @@ const Uint32& Event::getCallbackId() const { return mCallbackId; } +const MouseEvent* Event::asMouseEvent() const { + return static_cast( this ); +} + +const KeyEvent* Event::asKeyEvent() const { + return static_cast( this ); +} + +const DropEvent* Event::asDropEvent() const { + return static_cast( this ); +} + +const TextEvent* Event::asTextEvent() const { + return static_cast( this ); +} + +const TextInputEvent* Event::asTextInputEvent() const { + return static_cast( this ); +} + }} // namespace EE::Scene diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 825c9a64a..4bc414ebc 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -415,6 +415,11 @@ void UIAbstractTableView::bindNavigationClick( UIWidget* widget ) { UIWidget* UIAbstractTableView::createCell( UIWidget* rowWidget, const ModelIndex& index ) { UITableCell* widget = UITableCell::New( mTag + "::cell" ); + return setupCell( widget, rowWidget, index ); +} + +UIWidget* UIAbstractTableView::setupCell( UITableCell* widget, UIWidget* rowWidget, + const ModelIndex& index ) { widget->setParent( rowWidget ); widget->unsetFlags( UI_AUTO_SIZE ); widget->setClipType( ClipType::ContentBox ); @@ -450,6 +455,10 @@ UIWidget* UIAbstractTableView::updateCell( const int& rowIndex, const ModelIndex cell->setText( txt.asString() ); else if ( txt.is( Variant::Type::cstr ) ) cell->setText( txt.asCStr() ); + else if ( txt.is( Variant::Type::Bool ) || txt.is( Variant::Type::Float ) || + txt.is( Variant::Type::Int ) || txt.is( Variant::Type::Uint ) || + txt.is( Variant::Type::Int64 ) || txt.is( Variant::Type::Uint64 ) ) + cell->setText( txt.toString() ); } bool isVisible = false; diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 9b1fb7dc6..e788277e5 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -187,7 +187,7 @@ void TextDocument::guessIndentType() { int guessSpaces = 0; int guessTabs = 0; std::map guessWidth; - int guessCoundown = 10; + int guessCountdown = 10; size_t linesCount = eemin( 100, mLines.size() ); for ( size_t i = 0; i < linesCount; i++ ) { const String& text = mLines[i].getText(); @@ -196,16 +196,16 @@ void TextDocument::guessIndentType() { if ( !match.empty() ) { guessSpaces++; guessWidth[match.size()]++; - guessCoundown--; + guessCountdown--; } else { match = LuaPattern::match( mLines[i].getText(), "^\t+" ); if ( !match.empty() ) { guessTabs++; - guessCoundown--; + guessCountdown--; break; // if tab found asume tabs } } - if ( guessCoundown == 0 ) + if ( guessCountdown == 0 ) break; } if ( !guessTabs && !guessSpaces ) { diff --git a/src/eepp/ui/uipushbutton.cpp b/src/eepp/ui/uipushbutton.cpp index 11ab91592..9b9f48b60 100644 --- a/src/eepp/ui/uipushbutton.cpp +++ b/src/eepp/ui/uipushbutton.cpp @@ -17,14 +17,14 @@ UIPushButton* UIPushButton::NewWithTag( const std::string& tag ) { } UIPushButton* UIPushButton::NewWithOpt( const std::string& tag, - const std::function& newTextViewCb ) { + const std::function& newTextViewCb ) { return eeNew( UIPushButton, ( tag, newTextViewCb ) ); } UIPushButton::UIPushButton( const std::string& tag ) : UIPushButton( tag, nullptr ) {} UIPushButton::UIPushButton( const std::string& tag, - const std::function& newTextViewCb ) : + const std::function& newTextViewCb ) : UIWidget( tag ), mIcon( NULL ), mTextBox( NULL ) { mFlags |= ( UI_AUTO_SIZE | UI_VALIGN_CENTER | UI_HALIGN_CENTER ); @@ -43,7 +43,7 @@ UIPushButton::UIPushButton( const std::string& tag, mIcon->addEventListener( Event::OnSizeChange, cb ); mIcon->addEventListener( Event::OnVisibleChange, cb ); - mTextBox = newTextViewCb ? newTextViewCb() : UITextView::NewWithTag( tag + "::text" ); + mTextBox = newTextViewCb ? newTextViewCb( this ) : UITextView::NewWithTag( tag + "::text" ); mTextBox->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent ) ->setFlags( UI_VALIGN_CENTER | UI_HALIGN_CENTER ) ->setParent( this ) diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index 897ea504b..58209e8b4 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -207,6 +207,10 @@ UIWidget* UITreeView::updateCell( const int& rowIndex, const ModelIndex& index, cell->setText( txt.asString() ); else if ( txt.is( Variant::Type::cstr ) ) cell->setText( txt.asCStr() ); + else if ( txt.is( Variant::Type::Bool ) || txt.is( Variant::Type::Float ) || + txt.is( Variant::Type::Int ) || txt.is( Variant::Type::Uint ) || + txt.is( Variant::Type::Int64 ) || txt.is( Variant::Type::Uint64 ) ) + cell->setText( txt.toString() ); } bool hasChilds = false; diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index 49cd494e1..2382d1076 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -21,7 +21,7 @@ class AutoCompletePlugin : public UICodeEditorPlugin { static PluginDefinition Definition() { return { "autocomplete", "Auto Complete", - "Auto complete shows the completion popup as you type, so you can fill\n" + "Auto complete shows the completion popup as you type, so you can fill " "in long words by typing only a few characters.", AutoCompletePlugin::New }; } diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index 181469b52..1911c7cae 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -46,7 +46,7 @@ class LinterPlugin : public UICodeEditorPlugin { public: static PluginDefinition Definition() { return { "linter", "Linter", - "Use static code analysis tool used to flag programming errors, bugs,\n" + "Use static code analysis tool used to flag programming errors, bugs, " "stylistic errors, and suspicious constructs.", LinterPlugin::New }; } diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index 3017250c8..37a11e191 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -1,5 +1,7 @@ #include "pluginmanager.hpp" +#include #include +#include namespace ecode { @@ -92,7 +94,7 @@ bool PluginManager::hasDefinition( const std::string& id ) { return mDefinitions.find( id ) != mDefinitions.end(); } -std::shared_ptr PluginsModel::create( PluginManager* manager ) { +std::shared_ptr PluginsModel::New( PluginManager* manager ) { return std::make_shared( manager ); } @@ -117,6 +119,8 @@ Variant PluginsModel::data( const ModelIndex& index, ModelRole role ) const { return Variant( def->description.c_str() ); case Columns::Title: return Variant( def->name.c_str() ); + case Columns::Enabled: + return Variant( mManager->isEnabled( def->id ) ); case Columns::Id: return Variant( def->id.c_str() ); } @@ -124,7 +128,54 @@ Variant PluginsModel::data( const ModelIndex& index, ModelRole role ) const { return {}; } +PluginManager* PluginsModel::getManager() const { + return mManager; +} + +class UIPluginManagerTable : public UITableView { + public: + UIPluginManagerTable() : UITableView() {} + + std::function getCheckBoxFn( const ModelIndex& index, + const PluginsModel* model ) { + return [index, model]( UIPushButton* but ) -> 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 ); + } + return 1; + } ); + return chk; + }; + } + + UIWidget* createCell( UIWidget* rowWidget, const ModelIndex& index ) { + if ( index.column() == PluginsModel::Title ) { + UITableCell* widget = UITableCell::NewWithOpt( + mTag + "::cell", getCheckBoxFn( index, (const PluginsModel*)getModel() ) ); + return setupCell( widget, rowWidget, index ); + } + return UITableView::createCell( rowWidget, index ); + } +}; + UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager ) { + if ( !UIWidgetCreator::isWidgetRegistered( "UIPluginManagerTable" ) ) + UIWidgetCreator::registerWidget( "UIPluginManagerTable", + [] { return eeNew( UIPluginManagerTable, () ); } ); + UIWindow* win = sceneNode ->loadLayoutFromString( R"xml( - - + - @@ -149,44 +198,19 @@ UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager ) )xml" ) ->asType(); UIWidget* cont = win->getContainer(); - UIPushButton* enable = cont->find( "plugin-manager-enabled" ); UIPushButton* close = cont->find( "plugin-manager-close" ); - UITableView* tv = win->getContainer()->find( "plugin-manager-table" ); + UIPluginManagerTable* tv = + win->getContainer()->find( "plugin-manager-table" ); close->addEventListener( Event::MouseClick, [win]( const Event* event ) { const MouseEvent* mevent = static_cast( event ); if ( mevent->getFlags() & EE_BUTTON_LMASK ) win->closeWindow(); } ); - win->setTitle( sceneNode->i18n( "plugin_manager", "Plugin Manager" ) ); - enable->setText( sceneNode->i18n( "enable", "Select a Plugin" ) ); - - auto updateButtonsState = [sceneNode, enable, manager]( const ModelIndex& index ) { - const PluginDefinition* def = manager->getDefinitionIndex( index.row() ); - if ( def == nullptr ) - return; - enable->setEnabled( true ); - enable->setText( manager->isEnabled( def->id ) ? sceneNode->i18n( "disable", "Disable" ) - : sceneNode->i18n( "enable", "Enable" ) ); - }; - enable->addEventListener( - Event::MouseClick, [updateButtonsState, tv, manager]( const Event* event ) { - const MouseEvent* mevent = static_cast( event ); - if ( mevent->getFlags() & EE_BUTTON_LMASK && !tv->getSelection().isEmpty() ) { - const PluginDefinition* def = - manager->getDefinitionIndex( tv->getSelection().first().row() ); - if ( def == nullptr ) - return; - manager->setEnabled( def->id, !manager->isEnabled( def->id ) ); - updateButtonsState( tv->getSelection().first() ); - } - } ); - tv->setOnSelection( updateButtonsState ); - tv->setModel( PluginsModel::create( manager ) ); + tv->setModel( PluginsModel::New( manager ) ); tv->setColumnsVisible( { PluginsModel::Title, PluginsModel::Description, PluginsModel::Version } ); tv->setAutoColumnsWidth( true ); - tv->setRowHeight( PixelDensity::dpToPx( 64 ) ); win->center(); return win; } diff --git a/src/tools/ecode/plugins/pluginmanager.hpp b/src/tools/ecode/plugins/pluginmanager.hpp index 41a289679..356603fde 100644 --- a/src/tools/ecode/plugins/pluginmanager.hpp +++ b/src/tools/ecode/plugins/pluginmanager.hpp @@ -74,9 +74,9 @@ class PluginManager { class PluginsModel : public Model { public: - enum Columns { Id, Enabled, Title, Description, Version }; + enum Columns { Id, Title, Enabled, Description, Version }; - static std::shared_ptr create( PluginManager* manager ); + static std::shared_ptr New( PluginManager* manager ); PluginsModel( PluginManager* manager ) : mManager( manager ) {} @@ -97,9 +97,11 @@ class PluginsModel : public Model { virtual void update() { onModelUpdate(); } - protected: + PluginManager* getManager() const; + + protected: PluginManager* mManager; - std::vector mColumnNames{ "Id", "Enabled", "Title", "Description", "Version" }; + std::vector mColumnNames{ "Id", "Title", "Enabled", "Description", "Version" }; }; class UIPluginManager { diff --git a/src/tools/ecode/uitreeviewglobalsearch.cpp b/src/tools/ecode/uitreeviewglobalsearch.cpp index 82739b2ab..3f548627f 100644 --- a/src/tools/ecode/uitreeviewglobalsearch.cpp +++ b/src/tools/ecode/uitreeviewglobalsearch.cpp @@ -58,11 +58,13 @@ void UITreeViewCellGlobalSearch::toggleSelected() { } } -std::function UITreeViewCellGlobalSearch::getCheckBoxFn() { - return [&]() -> UITextView* { +std::function UITreeViewCellGlobalSearch::getCheckBoxFn() { + return [&]( UIPushButton* ) -> UITextView* { UICheckBox* chk = UICheckBox::New(); addEventListener( Event::MouseClick, [&, chk]( const Event* event ) { const MouseEvent* mouseEvent = static_cast( event ); + if ( !( mouseEvent->getFlags() & EE_BUTTON_LMASK ) ) + return 1; Vector2f pos = convertToNodeSpace( mouseEvent->getPosition().asFloat() ); Rectf box( { convertToNodeSpace( chk->getCurrentButton()->convertToWorldSpace( chk->getCurrentButton()->getPixelsPosition() ) ), diff --git a/src/tools/ecode/uitreeviewglobalsearch.hpp b/src/tools/ecode/uitreeviewglobalsearch.hpp index 1c2672d3e..886a20316 100644 --- a/src/tools/ecode/uitreeviewglobalsearch.hpp +++ b/src/tools/ecode/uitreeviewglobalsearch.hpp @@ -32,7 +32,7 @@ class UITreeViewCellGlobalSearch : public UITreeViewCell { std::pair mSearchStrPos; String mResultStr; - std::function getCheckBoxFn(); + std::function getCheckBoxFn(); void* getDataPtr( const ModelIndex& modelIndex );