From 72a0cdbc69620a7e068646af97f00be098af6aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 17 Aug 2024 20:16:32 -0300 Subject: [PATCH] Add support for DropDownList and ComboBox on UIMessageBox. Improve displayed indent tab character settings. --- include/eepp/scene/event.hpp | 1 + include/eepp/ui/uimessagebox.hpp | 10 ++- include/eepp/ui/uiwindow.hpp | 2 + src/eepp/ui/uimessagebox.cpp | 44 ++++++++++++ src/eepp/ui/uiwindow.cpp | 11 ++- src/tools/ecode/appconfig.cpp | 1 + src/tools/ecode/applayout.xml.hpp | 5 ++ src/tools/ecode/ecode.cpp | 107 +++++++++++++++--------------- src/tools/ecode/ecode.hpp | 1 + 9 files changed, 126 insertions(+), 56 deletions(-) diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index 8b6782550..37a27e4ac 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -115,6 +115,7 @@ class EE_API Event { OnRowCreated, OnScrollChange, OnModelChanged, + OnWindowToFront, NoEvent = eeINDEX_NOT_FOUND }; diff --git a/include/eepp/ui/uimessagebox.hpp b/include/eepp/ui/uimessagebox.hpp index fc02d7a7a..244384712 100644 --- a/include/eepp/ui/uimessagebox.hpp +++ b/include/eepp/ui/uimessagebox.hpp @@ -9,6 +9,8 @@ class UITextEdit; class UITextInput; class UILayout; class UIPushButton; +class UIDropDownList; +class UIComboBox; #define UI_MESSAGE_BOX_DEFAULT_FLAGS \ UI_WIN_CLOSE_BUTTON | UI_WIN_USE_DEFAULT_BUTTONS_ACTIONS | UI_WIN_MODAL | \ @@ -16,7 +18,7 @@ class UIPushButton; class EE_API UIMessageBox : public UIWindow { public: - enum Type { OK_CANCEL, YES_NO, RETRY_CANCEL, OK, INPUT, TEXT_EDIT }; + enum Type { OK_CANCEL, YES_NO, RETRY_CANCEL, OK, INPUT, TEXT_EDIT, DROPDOWNLIST, COMBOBOX }; static UIMessageBox* New( const Type& type, const String& message, const Uint32& windowFlags = UI_MESSAGE_BOX_DEFAULT_FLAGS ); @@ -43,6 +45,10 @@ class EE_API UIMessageBox : public UIWindow { UILayout* getLayoutCont() const; + UIDropDownList* getDropDownList() const; + + UIComboBox* getComboBox() const; + protected: Type mMsgBoxType; UITextView* mTextBox{ nullptr }; @@ -50,6 +56,8 @@ class EE_API UIMessageBox : public UIWindow { UIPushButton* mButtonCancel{ nullptr }; UITextInput* mTextInput{ nullptr }; UITextEdit* mTextEdit{ nullptr }; + UIDropDownList* mDropDownList{ nullptr }; + UIComboBox* mComboBox{ nullptr }; KeyBindings::Shortcut mCloseShortcut; UILayout* mLayoutCont{ nullptr }; diff --git a/include/eepp/ui/uiwindow.hpp b/include/eepp/ui/uiwindow.hpp index 245e4a3b4..6be5ba361 100644 --- a/include/eepp/ui/uiwindow.hpp +++ b/include/eepp/ui/uiwindow.hpp @@ -295,6 +295,8 @@ class EE_API UIWindow : public UIWidget { void setupModal(); void forcedApplyStyle(); + + void sendWindowToFront(); }; }} // namespace EE::UI diff --git a/src/eepp/ui/uimessagebox.cpp b/src/eepp/ui/uimessagebox.cpp index 8550d5453..d1ff598db 100644 --- a/src/eepp/ui/uimessagebox.cpp +++ b/src/eepp/ui/uimessagebox.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -56,6 +58,38 @@ UIMessageBox::UIMessageBox( const Type& type, const String& message, const Uint3 [this] { sendCommonEvent( Event::OnConfirm ); } ); mTextEdit->getKeyBindings().addKeybind( { KEY_RETURN, KeyMod::getDefaultModifier() }, "complete-edit" ); + } else if ( mMsgBoxType == DROPDOWNLIST ) { + mDropDownList = UIDropDownList::New(); + mDropDownList->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ) + ->setLayoutMargin( Rectf( 0, 4, 0, 4 ) ) + ->setSize( PixelDensity::dpToPx( Vector2f{ 200, 18 } ) ) + ->setParent( vlay ); + mDropDownList->setPopUpToRoot( true ); + } else if ( mMsgBoxType == COMBOBOX ) { + mComboBox = UIComboBox::New(); + mComboBox->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ) + ->setLayoutMargin( Rectf( 0, 4, 0, 4 ) ) + ->setSize( PixelDensity::dpToPx( Vector2f{ 200, 18 } ) ) + ->setParent( vlay ); + mComboBox->getDropDownList()->setPopUpToRoot( true ); + mComboBox->getDropDownList()->getDocument().setCommand( + "complete-edit", [this] { sendCommonEvent( Event::OnConfirm ); } ); + mComboBox->getDropDownList()->getKeyBindings().addKeybind( + { KEY_RETURN, KeyMod::getDefaultModifier() }, "complete-edit" ); + } + + if ( mMsgBoxType == DROPDOWNLIST || mMsgBoxType == COMBOBOX ) { + on( Event::OnWindowToFront, [this]( auto ) { + UIListBox* listBox = nullptr; + if ( mMsgBoxType == DROPDOWNLIST ) { + listBox = mDropDownList->getListBox(); + } else if ( mMsgBoxType == COMBOBOX ) { + listBox = mComboBox->getDropDownList()->getListBox(); + } + + if ( listBox && listBox->isVisible() ) + listBox->toFront(); + } ); } UILinearLayout* hlay = UILinearLayout::NewHorizontal(); @@ -74,6 +108,8 @@ UIMessageBox::UIMessageBox( const Type& type, const String& message, const Uint3 switch ( mMsgBoxType ) { case UIMessageBox::INPUT: case UIMessageBox::TEXT_EDIT: + case DROPDOWNLIST: + case COMBOBOX: case UIMessageBox::OK_CANCEL: { mButtonOK->setText( i18n( "msg_box_ok", "Ok" ) ); mButtonCancel->setText( i18n( "msg_box_cancel", "Cancel" ) ); @@ -207,6 +243,14 @@ UILayout* UIMessageBox::getLayoutCont() const { return mLayoutCont; } +UIDropDownList* UIMessageBox::getDropDownList() const { + return mDropDownList; +} + +UIComboBox* UIMessageBox::getComboBox() const { + return mComboBox; +} + void UIMessageBox::onWindowReady() { forcedApplyStyle(); diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index c0567f6bf..7d30838a0 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -785,7 +785,7 @@ void UIWindow::fixChildsSize() { Uint32 UIWindow::onMessage( const NodeMessage* Msg ) { switch ( Msg->getMsg() ) { case NodeMessage::Focus: { - toFront(); + sendWindowToFront(); break; } case NodeMessage::MouseDown: { @@ -808,7 +808,7 @@ Uint32 UIWindow::onMessage( const NodeMessage* Msg ) { if ( getUISceneNode() != NULL ) getUISceneNode()->setCursor( Cursor::Hand ); - toFront(); + sendWindowToFront(); break; } @@ -1071,7 +1071,7 @@ void UIWindow::setupModal() { mModalNode->setVisible( true ); mModalNode->toFront(); - toFront(); + sendWindowToFront(); } } @@ -1803,4 +1803,9 @@ void UIWindow::executeKeyBindingCommand( const std::string& command ) { } } +void UIWindow::sendWindowToFront() { + toFront(); + sendCommonEvent( Event::OnWindowToFront ); +} + }} // namespace EE::UI diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 58b4c1881..8a4f7f43b 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -27,6 +27,7 @@ std::string characterAlignmentToString( CharacterAlignment alignment ) { return "right"; break; } + return "left"; } CharacterAlignment characterAlignmentFromString( const std::string_view& str ) { diff --git a/src/tools/ecode/applayout.xml.hpp b/src/tools/ecode/applayout.xml.hpp index ec69d00d0..cd6b4ae3c 100644 --- a/src/tools/ecode/applayout.xml.hpp +++ b/src/tools/ecode/applayout.xml.hpp @@ -478,6 +478,11 @@ Anchor.error:hover { margin-right: 2dp; font-style: shadow; } +#indent_tab_window ComboBox, +#indent_tab_window ListBox::item, +.indent_tab_listbox_item combobox::dropdownlist::listbox::item { + font-family: monospace; +} ]]> )html" diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 8340e21a8..b7c7cdf1d 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1336,16 +1336,19 @@ void App::setCursorBlinkingTime() { void App::setIndentTabCharacter() { UIMessageBox* msgBox = UIMessageBox::New( - UIMessageBox::INPUT, + UIMessageBox::COMBOBOX, i18n( "set_indent_tab_character", "Set the tab indentation guide character displayed." ) ); + msgBox->setId( "indent_tab_window" ); msgBox->setTitle( mWindowTitle ); msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); - msgBox->getTextInput()->setFont( mFontMono ); - msgBox->getTextInput()->setText( String::fromUtf8( + msgBox->getComboBox()->getDropDownList()->getListBox()->addClass( "indent_tab_listbox_item" ); + msgBox->getComboBox()->getDropDownList()->getListBox()->addListBoxItems( + { u8"»", u8"→", u8"⇒", u8"↪", u8"⇢", u8"↣" } ); + msgBox->getComboBox()->setText( String::fromUtf8( mConfig.editor.tabIndentCharacter.empty() ? u8"»" : mConfig.editor.tabIndentCharacter ) ); msgBox->showWhenReady(); msgBox->on( Event::OnConfirm, [this, msgBox]( const Event* ) { - auto txt( msgBox->getTextInput()->getText() ); + auto txt( msgBox->getComboBox()->getText() ); if ( txt.size() == 1 ) { mConfig.editor.tabIndentCharacter = txt.toUtf8(); mSplitter->forEachEditor( @@ -2107,51 +2110,50 @@ std::map App::getDefaultKeybindings() { std::map App::getLocalKeybindings() { return { { { KEY_RETURN, KEYMOD_LALT | KEYMOD_LCTRL }, "fullscreen-toggle" }, - { { KEY_F3, KEYMOD_NONE }, "repeat-find" }, { { KEY_F3, KEYMOD_SHIFT }, "find-prev" }, - { { KEY_F12, KEYMOD_NONE }, "console-toggle" }, - { { KEY_F, KeyMod::getDefaultModifier() }, "find-replace" }, - { { KEY_Q, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "close-app" }, - { { KEY_O, KeyMod::getDefaultModifier() }, "open-file" }, - { { KEY_W, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "download-file-web" }, - { { KEY_O, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-folder" }, - { { KEY_F11, KEYMOD_NONE }, "debug-widget-tree-view" }, - { { KEY_K, KeyMod::getDefaultModifier() }, "open-locatebar" }, - { { KEY_P, KeyMod::getDefaultModifier() }, "open-command-palette" }, - { { KEY_F, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-global-search" }, - { { KEY_L, KeyMod::getDefaultModifier() }, "go-to-line" }, + { { KEY_F3, KEYMOD_NONE }, "repeat-find" }, + { { KEY_F3, KEYMOD_SHIFT }, "find-prev" }, + { { KEY_F12, KEYMOD_NONE }, "console-toggle" }, + { { KEY_F, KeyMod::getDefaultModifier() }, "find-replace" }, + { { KEY_Q, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "close-app" }, + { { KEY_O, KeyMod::getDefaultModifier() }, "open-file" }, + { { KEY_W, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "download-file-web" }, + { { KEY_O, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-folder" }, + { { KEY_F11, KEYMOD_NONE }, "debug-widget-tree-view" }, + { { KEY_K, KeyMod::getDefaultModifier() }, "open-locatebar" }, + { { KEY_P, KeyMod::getDefaultModifier() }, "open-command-palette" }, + { { KEY_F, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-global-search" }, + { { KEY_L, KeyMod::getDefaultModifier() }, "go-to-line" }, #if EE_PLATFORM == EE_PLATFORM_MACOS - { { KEY_M, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "menu-toggle" }, + { { KEY_M, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "menu-toggle" }, #else - { { KEY_M, KeyMod::getDefaultModifier() }, "menu-toggle" }, + { { KEY_M, KeyMod::getDefaultModifier() }, "menu-toggle" }, #endif - { { KEY_S, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "save-all" }, - { { KEY_F9, KEYMOD_LALT }, "switch-side-panel" }, - { { KEY_J, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "terminal-split-left" }, - { { KEY_L, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "terminal-split-right" }, - { { KEY_I, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "terminal-split-top" }, - { { KEY_K, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "terminal-split-bottom" }, - { { KEY_S, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "terminal-split-swap" }, - { { KEY_T, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, - "reopen-closed-tab" }, - { { KEY_1, KEYMOD_LALT }, "toggle-status-locate-bar" }, - { { KEY_2, KEYMOD_LALT }, "toggle-status-global-search-bar" }, - { { KEY_3, KEYMOD_LALT }, "toggle-status-terminal" }, - { { KEY_4, KEYMOD_LALT }, "toggle-status-build-output" }, - { { KEY_5, KEYMOD_LALT }, "toggle-status-app-output" }, - { { KEY_B, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-start" }, - { { KEY_C, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-cancel" }, - { { KEY_F5, KEYMOD_NONE }, "project-build-and-run" }, - { { KEY_O, KEYMOD_LALT | KEYMOD_SHIFT }, "show-open-documents" }, - { { KEY_K, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, - "open-workspace-symbol-search" }, - { { KEY_P, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, - "open-document-symbol-search" }, - { { KEY_N, KEYMOD_SHIFT | KEYMOD_LALT }, "create-new-window" }, + { { KEY_S, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "save-all" }, + { { KEY_F9, KEYMOD_LALT }, "switch-side-panel" }, + { { KEY_J, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "terminal-split-left" }, + { { KEY_L, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "terminal-split-right" }, + { { KEY_I, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "terminal-split-top" }, + { { KEY_K, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "terminal-split-bottom" }, + { { KEY_S, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "terminal-split-swap" }, + { { KEY_T, KeyMod::getDefaultModifier() | KEYMOD_LALT | KEYMOD_SHIFT }, + "reopen-closed-tab" }, + { { KEY_1, KEYMOD_LALT }, "toggle-status-locate-bar" }, + { { KEY_2, KEYMOD_LALT }, "toggle-status-global-search-bar" }, + { { KEY_3, KEYMOD_LALT }, "toggle-status-terminal" }, + { { KEY_4, KEYMOD_LALT }, "toggle-status-build-output" }, + { { KEY_5, KEYMOD_LALT }, "toggle-status-app-output" }, + { { KEY_B, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-start" }, + { { KEY_C, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-cancel" }, + { { KEY_F5, KEYMOD_NONE }, "project-build-and-run" }, + { { KEY_O, KEYMOD_LALT | KEYMOD_SHIFT }, "show-open-documents" }, + { { KEY_K, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-workspace-symbol-search" }, + { { KEY_P, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-document-symbol-search" }, + { { KEY_N, KEYMOD_SHIFT | KEYMOD_LALT }, "create-new-window" }, }; } @@ -2160,13 +2162,13 @@ std::map App::getLocalKeybindings() { std::map App::getMigrateKeybindings() { return { { "fullscreen-toggle", "alt+return" }, { "switch-to-tab-1", "alt+1" }, - { "switch-to-tab-2", "alt+2" }, { "switch-to-tab-3", "alt+3" }, - { "switch-to-tab-4", "alt+4" }, { "switch-to-tab-5", "alt+5" }, - { "switch-to-tab-6", "alt+6" }, { "switch-to-tab-7", "alt+7" }, - { "switch-to-tab-8", "alt+8" }, { "switch-to-tab-9", "alt+9" }, - { "switch-to-last-tab", "alt+0" }, + { "switch-to-tab-2", "alt+2" }, { "switch-to-tab-3", "alt+3" }, + { "switch-to-tab-4", "alt+4" }, { "switch-to-tab-5", "alt+5" }, + { "switch-to-tab-6", "alt+6" }, { "switch-to-tab-7", "alt+7" }, + { "switch-to-tab-8", "alt+8" }, { "switch-to-tab-9", "alt+9" }, + { "switch-to-last-tab", "alt+0" }, #if EE_PLATFORM == EE_PLATFORM_MACOS - { "menu-toggle", "mod+shift+m" }, + { "menu-toggle", "mod+shift+m" }, #endif }; } @@ -2211,6 +2213,7 @@ std::vector App::getUnlockedCommands() { "editor-set-line-breaking-column", "editor-set-line-spacing", "editor-set-cursor-blinking-time", + "editor-set-indent-tab-character", "check-for-updates", "keybindings", "about-ecode", diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index f1566c280..755a2d3f3 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -282,6 +282,7 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "editor-set-line-breaking-column", [this] { setLineBreakingColumn(); } ); t.setCommand( "editor-set-line-spacing", [this] { setLineSpacing(); } ); t.setCommand( "editor-set-cursor-blinking-time", [this] { setCursorBlinkingTime(); } ); + t.setCommand( "editor-set-indent-tab-character", [this] { setIndentTabCharacter(); } ); t.setCommand( "check-for-updates", [this] { checkForUpdates(); } ); t.setCommand( "about-ecode", [this] { aboutEcode(); } ); t.setCommand( "ecode-source", [this] { ecodeSource(); } );