diff --git a/TODO.md b/TODO.md index d3f9641d5..0841a7fbd 100644 --- a/TODO.md +++ b/TODO.md @@ -1,25 +1,17 @@ # TODO - Short and mid term plans. -## UIMenuRadioButton - -Implement support for radio buttons in menues. - -## UIMenuItem - -* Support displaying the keyboard shortcuts for the menu items. - ## UIWidget -* Add onDrop( UIWidget* ) API. In order to be able to drop widgets onto other widgets. +* Add `onDrop( UIWidget* )` API. In order to be able to drop widgets onto other widgets. ## UITabWidget -* Add support to move Tabs from one UITabWidget to another using the onDrop API. +* Add support to move Tabs from one `UITabWidget` to another using the onDrop API. ## UIIconTheme and UIIconThemeManager -Implement icon themes separated from the UITheme and customizable from a CSS file. +Implement icon themes separated from the `UITheme` and customizable from a CSS file. ## UICodeEditor @@ -58,4 +50,20 @@ Keep improving it: * Add more menues ( Edit, Window ). -* Save user configuration. \ No newline at end of file +* Save user configuration. + +* Support single instance (when a new file is opened while a previous instance exists, open it in the first instance). + +## UI Editor + +* Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app. + +* Once `UITreeView` is finished add a tree view inspecto of the node tree. + +# StyleSheetParser + +Detect errors and log them. + +# UISceneNode and UIWindow + +Redesign the shortcut API to use the new keybinding class. diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 8575a0d3f..e4eed3fce 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -45,7 +45,8 @@ ComboBox::DropDownList::ListBox::item, DropDownList, DropDownList::ListBox::item, ListBox::item, -Menu::item, +Menu::item::text, +Menu::item::shortcut, Menu::SubMenu, PushButton, RadioButton, @@ -605,7 +606,8 @@ MenuBar::Button:hover { Menu::Item, Menu::CheckBox, Menu::Separator, -Menu::SubMenu { +Menu::SubMenu, +Menu::RadioButton { padding-left: 4dp; padding-top: 2dp; padding-bottom: 2dp; @@ -614,20 +616,33 @@ Menu::SubMenu { Menu::Item:hover, Menu::CheckBox:hover, -Menu::SubMenu:hover { +Menu::SubMenu:hover, +Menu::RadioButton:hover { background-color: var(--primary); } Menu::Item::text, Menu::CheckBox::text, -Menu::SubMenu::text { +Menu::SubMenu::text, +Menu::RadioButton::text { padding-right: 8dp; color: var(--menu-font); } +Menu::Item::shortcut, +Menu::CheckBox::shortcut, +Menu::RadioButton::shortcut { + padding-left: 8dp; + padding-right: 8dp; + color: var(--menu-font); +} Menu::Item:disabled > Menu::Item::text, +Menu::Item:disabled > Menu::Item::shortcut, Menu::CheckBox:disabled > Menu::CheckBox::text, +Menu::CheckBox:disabled > Menu::CheckBox::shortcut, +Menu::RadioButton:disabled > Menu::RadioButton::text, +Menu::RadioButton:disabled > Menu::RadioButton::shortcut, Menu::SubMenu:disabled > Menu::SubMenu::text { color: var(--menu-font-disabled); } @@ -636,11 +651,10 @@ Menu::SubMenu::arrow { margin-right: 1dp; } -Menu:hover, -PopUpMenu:hover, -Menu::Item:hover, -Menu::CheckBox:hover, -Menu::SubMenu:hover, +Menu::Item:hover > Menu::Item::text, +Menu::CheckBox:hover > Menu::Item::text, +Menu::RadioButton:hover > Menu::Item::text, +Menu::SubMenu:hover > Menu::Item::text, ListBox::item:hover, Tab:selected, Tab:hover, @@ -664,7 +678,8 @@ Menu::SubMenu::Arrow { Menu::Item::icon, Menu::SubMenu::icon, -Menu::CheckBox::icon { +Menu::CheckBox::icon, +Menu::RadioButton::icon { margin-right: 4dp; } @@ -685,6 +700,23 @@ Menu::CheckBox::icon:selected { background-position: center; } +Menu::RadioButton::icon { + max-width: 12dp; + max-height: 12dp; + border-width: 1dp; + border-color: var(--button-border); + border-radius: 100%; + background-image: none; + background-color: var(--menu-back); +} + +Menu::RadioButton::icon:selected { + border-color: var(--primary); + background-image: circle(solid, var(--primary)); + background-size: 8dp 8dp; + background-position: 6dp 6dp; +} + ListBox > ScrollBar, TextEdit > ScrollBar, Table > ScrollBar { diff --git a/bin/assets/ui/uitheme.eta b/bin/assets/ui/uitheme.eta index 6513e854b..61f5f35b7 100644 Binary files a/bin/assets/ui/uitheme.eta and b/bin/assets/ui/uitheme.eta differ diff --git a/bin/assets/ui/uitheme.png b/bin/assets/ui/uitheme.png index cd7bb8f38..a3de374ce 100644 Binary files a/bin/assets/ui/uitheme.png and b/bin/assets/ui/uitheme.png differ diff --git a/bin/assets/ui/uitheme/uitheme_menuradiobutton_active_normal.png b/bin/assets/ui/uitheme/uitheme_menuradiobutton_active_normal.png new file mode 100644 index 000000000..0069994a4 Binary files /dev/null and b/bin/assets/ui/uitheme/uitheme_menuradiobutton_active_normal.png differ diff --git a/bin/assets/ui/uitheme/uitheme_menuradiobutton_inactive_normal.png b/bin/assets/ui/uitheme/uitheme_menuradiobutton_inactive_normal.png new file mode 100644 index 000000000..13a32e261 Binary files /dev/null and b/bin/assets/ui/uitheme/uitheme_menuradiobutton_inactive_normal.png differ diff --git a/bin/assets/ui/uitheme1.5x.eta b/bin/assets/ui/uitheme1.5x.eta index a9b028c5b..fe8b8cf1a 100644 Binary files a/bin/assets/ui/uitheme1.5x.eta and b/bin/assets/ui/uitheme1.5x.eta differ diff --git a/bin/assets/ui/uitheme1.5x.png b/bin/assets/ui/uitheme1.5x.png index 96706fcfd..3f759c97a 100644 Binary files a/bin/assets/ui/uitheme1.5x.png and b/bin/assets/ui/uitheme1.5x.png differ diff --git a/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_active_normal.png b/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_active_normal.png new file mode 100644 index 000000000..7777e2cdd Binary files /dev/null and b/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_active_normal.png differ diff --git a/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_inactive_normal.png b/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_inactive_normal.png new file mode 100644 index 000000000..4700450ed Binary files /dev/null and b/bin/assets/ui/uitheme1.5x/uitheme1.5x_menuradiobutton_inactive_normal.png differ diff --git a/bin/assets/ui/uitheme2x.eta b/bin/assets/ui/uitheme2x.eta index 125b16552..f721df64a 100644 Binary files a/bin/assets/ui/uitheme2x.eta and b/bin/assets/ui/uitheme2x.eta differ diff --git a/bin/assets/ui/uitheme2x.png b/bin/assets/ui/uitheme2x.png index affba9d97..c7a5f0963 100644 Binary files a/bin/assets/ui/uitheme2x.png and b/bin/assets/ui/uitheme2x.png differ diff --git a/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_active_normal.png b/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_active_normal.png new file mode 100644 index 000000000..aa4b75c90 Binary files /dev/null and b/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_active_normal.png differ diff --git a/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_inactive_normal.png b/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_inactive_normal.png new file mode 100644 index 000000000..8f9574a8d Binary files /dev/null and b/bin/assets/ui/uitheme2x/uitheme2x_menuradiobutton_inactive_normal.png differ diff --git a/include/eepp/scene/eventdispatcher.hpp b/include/eepp/scene/eventdispatcher.hpp index ec82704d2..9842d6768 100644 --- a/include/eepp/scene/eventdispatcher.hpp +++ b/include/eepp/scene/eventdispatcher.hpp @@ -36,17 +36,17 @@ class EE_API EventDispatcher { Node* getFocusNode() const; - void setFocusNode( Node* Ctrl ); + void setFocusNode( Node* node ); Node* getMouseOverNode() const; - void setMouseOverNode( Node* Ctrl ); + void setMouseOverNode( Node* node ); Node* getMouseDownNode() const; Node* getLossFocusNode() const; - void sendMsg( Node* Ctrl, const Uint32& Msg, const Uint32& Flags = 0 ); + void sendMsg( Node* node, const Uint32& Msg, const Uint32& Flags = 0 ); void sendTextInput( const Uint32& textChar, const Uint32& timestamp ); @@ -54,11 +54,11 @@ class EE_API EventDispatcher { void sendKeyDown( const Keycode& KeyCode, const Uint32& Char, const Uint32& Mod ); - void sendMouseClick( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ); + void sendMouseClick( Node* toNode, const Vector2i& pos, const Uint32 flags ); - void sendMouseUp( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ); + void sendMouseUp( Node* toNode, const Vector2i& pos, const Uint32 flags ); - void sendMouseDown( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ); + void sendMouseDown( Node* toNode, const Vector2i& pos, const Uint32 flags ); const Uint32& getPressTrigger() const; diff --git a/include/eepp/ui.hpp b/include/eepp/ui.hpp index f937cd843..9314bf741 100644 --- a/include/eepp/ui.hpp +++ b/include/eepp/ui.hpp @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include #include diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp index 4490f606d..eb2d77298 100644 --- a/include/eepp/ui/uihelper.hpp +++ b/include/eepp/ui/uihelper.hpp @@ -67,6 +67,7 @@ enum UINodeType { UI_TYPE_MENU, UI_TYPE_MENUITEM, UI_TYPE_MENUCHECKBOX, + UI_TYPE_MENURADIOBUTTON, UI_TYPE_MENUSUBMENU, UI_TYPE_TEXTEDIT, UI_TYPE_TOOLTIP, diff --git a/include/eepp/ui/uimenu.hpp b/include/eepp/ui/uimenu.hpp index 8af32227f..687de6f2d 100644 --- a/include/eepp/ui/uimenu.hpp +++ b/include/eepp/ui/uimenu.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,8 +15,8 @@ class EE_API UIMenu : public UIWidget { public: static UIMenu* New(); - static void fixMenuPos( Vector2f& position, UIMenu* Menu, UIMenu* parent = NULL, - UIMenuSubMenu* SubMenu = NULL ); + static void fixMenuPos( Vector2f& position, UIMenu* menu, UIMenu* parent = NULL, + UIMenuSubMenu* subMenu = NULL ); UIMenu(); @@ -25,35 +26,37 @@ class EE_API UIMenu : public UIWidget { virtual bool isType( const Uint32& type ) const; - UIMenuItem* add( const String& Text, Drawable* Icon = NULL ); + UIMenuItem* add( const String& text, Drawable* icon = NULL, const String& shortcutText = "" ); UIWidget* add( UIWidget* widget ); UIMenuSeparator* addSeparator(); - UIMenuCheckBox* addCheckBox( const String& Text, const bool& Active = false ); + UIMenuCheckBox* addCheckBox( const String& text, const bool& active = false ); - UIMenuSubMenu* addSubMenu( const String& Text, Drawable* Icon = NULL, UIMenu* SubMenu = NULL ); + UIMenuRadioButton* addRadioButton( const String& text, const bool& active = false ); - UIWidget* getItem( const Uint32& Index ); + UIMenuSubMenu* addSubMenu( const String& text, Drawable* icon = NULL, UIMenu* subMenu = NULL ); - UIWidget* getItem( const String& Text ); + UIWidget* getItem( const Uint32& index ); - Uint32 getItemIndex( UIWidget* Item ); + UIWidget* getItem( const String& text ); + + Uint32 getItemIndex( UIWidget* item ); Uint32 getCount() const; - void remove( const Uint32& Index ); + void remove( const Uint32& index ); - void remove( UIWidget* Ctrl ); + void remove( UIWidget* widget ); void removeAll(); - void insert( const String& Text, Drawable* Icon, const Uint32& Index ); + void insert( const String& text, Drawable* icon, const Uint32& index ); - void insert( UIWidget* Control, const Uint32& Index ); + void insert( UIWidget* widget, const Uint32& index ); - virtual void setTheme( UITheme* Theme ); + virtual void setTheme( UITheme* theme ); virtual bool show(); @@ -78,6 +81,7 @@ class EE_API UIMenu : public UIWidget { protected: friend class UIMenuItem; friend class UIMenuCheckBox; + friend class UIMenuRadioButton; friend class UIMenuSubMenu; std::deque mItems; @@ -106,17 +110,20 @@ class EE_API UIMenu : public UIWidget { void resizeMe(); - UIMenuItem* createMenuItem( const String& Text, Drawable* Icon ); + UIMenuItem* createMenuItem( const String& text, Drawable* icon, + const String& shortcutText = "" ); - UIMenuCheckBox* createMenuCheckBox( const String& Text, const bool& Active ); + UIMenuCheckBox* createMenuCheckBox( const String& text, const bool& active ); - UIMenuSubMenu* createSubMenu( const String& Text, Drawable* Icon, UIMenu* SubMenu ); + UIMenuRadioButton* createMenuRadioButton( const String& text, const bool& active ); + + UIMenuSubMenu* createSubMenu( const String& text, Drawable* icon, UIMenu* subMenu ); void onThemeLoaded(); virtual void onPaddingChange(); - bool widgetCheckSize( UIWidget* widget, const bool& Resize = true ); + bool widgetCheckSize( UIWidget* widget, const bool& resize = true ); bool isSubMenu( Node* Ctrl ); diff --git a/include/eepp/ui/uimenubar.hpp b/include/eepp/ui/uimenubar.hpp index 6a5b66247..2e135ce7d 100644 --- a/include/eepp/ui/uimenubar.hpp +++ b/include/eepp/ui/uimenubar.hpp @@ -44,6 +44,7 @@ class EE_API UIMenuBar : public UIWidget { Uint32 mMenuHeight; UIPopUpMenu* mCurrentMenu; MenuBarList mButtons; + UIPopUpMenu* mWaitingUp; void refreshButtons(); diff --git a/include/eepp/ui/uimenuitem.hpp b/include/eepp/ui/uimenuitem.hpp index 07c454193..41530e11e 100644 --- a/include/eepp/ui/uimenuitem.hpp +++ b/include/eepp/ui/uimenuitem.hpp @@ -19,10 +19,22 @@ class EE_API UIMenuItem : public UIPushButton { virtual void setTheme( UITheme* Theme ); + virtual void setShortcutText( const String& text ); + + UITextView* getShortcutView() const; + protected: + UITextView* mShortcutView; + explicit UIMenuItem( const std::string& tag ); + virtual void onSizeChange(); + virtual Uint32 onMouseOver( const Vector2i& position, const Uint32& flags ); + + virtual UIWidget* getExtraInnerWidget(); + + void createShortcutView(); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uimenuradiobutton.hpp b/include/eepp/ui/uimenuradiobutton.hpp new file mode 100644 index 000000000..c97e1c254 --- /dev/null +++ b/include/eepp/ui/uimenuradiobutton.hpp @@ -0,0 +1,40 @@ +#ifndef EE_UI_UIMENURADIOBUTTON_HPP +#define EE_UI_UIMENURADIOBUTTON_HPP + +#include + +namespace EE { namespace UI { + +class EE_API UIMenuRadioButton : public UIMenuItem { + public: + static UIMenuRadioButton* New(); + + UIMenuRadioButton(); + + virtual ~UIMenuRadioButton(); + + virtual Uint32 getType() const; + + virtual bool isType( const Uint32& type ) const; + + virtual void setTheme( UITheme* Theme ); + + const bool& isActive() const; + + void setActive( const bool& active ); + + void switchActive(); + + protected: + bool mActive; + UISkin* mSkinActive; + UISkin* mSkinInactive; + + virtual Uint32 onMouseUp( const Vector2i& position, const Uint32& flags ); + + virtual void onStateChange(); +}; + +}} // namespace EE::UI + +#endif // EE_UI_UIMENURADIOBUTTON_HPP diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 4ed3e8187..d1883ad9b 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -353,6 +353,7 @@ ../../include/eepp/ui/uimenucheckbox.hpp ../../include/eepp/ui/uimenu.hpp ../../include/eepp/ui/uimenuitem.hpp +../../include/eepp/ui/uimenuradiobutton.hpp ../../include/eepp/ui/uimenuseparator.hpp ../../include/eepp/ui/uimenusubmenu.hpp ../../include/eepp/ui/uimessagebox.hpp @@ -802,6 +803,7 @@ ../../src/eepp/ui/uimenucheckbox.cpp ../../src/eepp/ui/uimenu.cpp ../../src/eepp/ui/uimenuitem.cpp +../../src/eepp/ui/uimenuradiobutton.cpp ../../src/eepp/ui/uimenuseparator.cpp ../../src/eepp/ui/uimenusubmenu.cpp ../../src/eepp/ui/uimessagebox.cpp diff --git a/src/eepp/scene/eventdispatcher.cpp b/src/eepp/scene/eventdispatcher.cpp index 0ee1b2c94..ea056e0c4 100644 --- a/src/eepp/scene/eventdispatcher.cpp +++ b/src/eepp/scene/eventdispatcher.cpp @@ -111,8 +111,8 @@ void EventDispatcher::update( const Time& time ) { if ( mInput->getReleaseTrigger() ) { if ( NULL != mFocusNode ) { if ( !nodeWasDragging || mMousePos == mLastMousePos ) { - if ( mOverNode != mFocusNode && - mInput->getReleaseTrigger() & ( EE_BUTTON_LMASK | EE_BUTTON_RMASK ) ) + if ( mDownNode == mOverNode && + ( mInput->getReleaseTrigger() & ( EE_BUTTON_LMASK | EE_BUTTON_RMASK ) ) ) setFocusNode( mOverNode ); // The focused node can change after the MouseUp ( since the node can call @@ -123,9 +123,8 @@ void EventDispatcher::update( const Time& time ) { if ( NULL != mOverNode ) { getMouseOverNode()->onMouseUp( mMousePosi, mInput->getReleaseTrigger() ); - if ( NULL != getMouseOverNode() ) - sendMsg( getMouseOverNode(), NodeMessage::MouseUp, - mInput->getReleaseTrigger() ); + if ( NULL != mOverNode ) + sendMsg( mOverNode, NodeMessage::MouseUp, mInput->getReleaseTrigger() ); } if ( mInput->getClickTrigger() ) { @@ -166,66 +165,59 @@ Input* EventDispatcher::getInput() const { void EventDispatcher::sendTextInput( const Uint32& textChar, const Uint32& timestamp ) { TextInputEvent textInputEvent = TextInputEvent( mFocusNode, Event::TextInput, textChar, timestamp ); - Node* CtrlLoop = mFocusNode; - - while ( NULL != CtrlLoop ) { - if ( CtrlLoop->isEnabled() && CtrlLoop->onTextInput( textInputEvent ) ) + Node* node = mFocusNode; + while ( NULL != node ) { + if ( node->isEnabled() && node->onTextInput( textInputEvent ) ) break; - - CtrlLoop = CtrlLoop->getParent(); + node = node->getParent(); } } void EventDispatcher::sendKeyUp( const Keycode& KeyCode, const Uint32& Char, const Uint32& Mod ) { KeyEvent keyEvent = KeyEvent( mFocusNode, Event::KeyUp, KeyCode, Char, Mod ); - Node* CtrlLoop = mFocusNode; - - while ( NULL != CtrlLoop ) { - if ( CtrlLoop->isEnabled() && CtrlLoop->onKeyUp( keyEvent ) ) + Node* node = mFocusNode; + while ( NULL != node ) { + if ( node->isEnabled() && node->onKeyUp( keyEvent ) ) break; - - CtrlLoop = CtrlLoop->getParent(); + node = node->getParent(); } } void EventDispatcher::sendKeyDown( const Keycode& KeyCode, const Uint32& Char, const Uint32& Mod ) { KeyEvent keyEvent = KeyEvent( mFocusNode, Event::KeyDown, KeyCode, Char, Mod ); - Node* CtrlLoop = mFocusNode; - - while ( NULL != CtrlLoop ) { - if ( CtrlLoop->isEnabled() && CtrlLoop->onKeyDown( keyEvent ) ) + Node* node = mFocusNode; + while ( NULL != node ) { + if ( node->isEnabled() && node->onKeyDown( keyEvent ) ) break; - - CtrlLoop = CtrlLoop->getParent(); + node = node->getParent(); } } -void EventDispatcher::sendMsg( Node* Ctrl, const Uint32& Msg, const Uint32& Flags ) { - NodeMessage tMsg( Ctrl, Msg, Flags ); - - Ctrl->messagePost( &tMsg ); +void EventDispatcher::sendMsg( Node* node, const Uint32& Msg, const Uint32& Flags ) { + NodeMessage tMsg( node, Msg, Flags ); + node->messagePost( &tMsg ); } -void EventDispatcher::sendMouseClick( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ) { - sendMsg( ToCtrl, NodeMessage::Click, Flags ); - ToCtrl->onMouseClick( Pos, Flags ); +void EventDispatcher::sendMouseClick( Node* toNode, const Vector2i& Pos, const Uint32 flags ) { + sendMsg( toNode, NodeMessage::Click, flags ); + toNode->onMouseClick( Pos, flags ); } -void EventDispatcher::sendMouseUp( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ) { - sendMsg( ToCtrl, NodeMessage::MouseUp, Flags ); - ToCtrl->onMouseUp( Pos, Flags ); +void EventDispatcher::sendMouseUp( Node* toNode, const Vector2i& Pos, const Uint32 flags ) { + sendMsg( toNode, NodeMessage::MouseUp, flags ); + toNode->onMouseUp( Pos, flags ); } -void EventDispatcher::sendMouseDown( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags ) { - sendMsg( ToCtrl, NodeMessage::MouseDown, Flags ); - ToCtrl->onMouseDown( Pos, Flags ); +void EventDispatcher::sendMouseDown( Node* toNode, const Vector2i& pos, const Uint32 flags ) { + sendMsg( toNode, NodeMessage::MouseDown, flags ); + toNode->onMouseDown( pos, flags ); } -void EventDispatcher::setFocusNode( Node* Ctrl ) { - if ( NULL != mFocusNode && NULL != Ctrl && Ctrl != mFocusNode ) { +void EventDispatcher::setFocusNode( Node* node ) { + if ( NULL != mFocusNode && NULL != node && node != mFocusNode ) { mLossFocusNode = mFocusNode; - mFocusNode = Ctrl; + mFocusNode = node; mLossFocusNode->onFocusLoss(); sendMsg( mLossFocusNode, NodeMessage::FocusLoss ); @@ -243,8 +235,8 @@ Node* EventDispatcher::getMouseOverNode() const { return mOverNode; } -void EventDispatcher::setMouseOverNode( Node* Ctrl ) { - mOverNode = Ctrl; +void EventDispatcher::setMouseOverNode( Node* node ) { + mOverNode = node; } Node* EventDispatcher::getFocusNode() const { diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 3fbb83b35..200e7ffad 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -858,7 +858,7 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() { // ini / conf add( {"Config File", - {"%.ini$", "%.conf$", "%.desktop$", "Doxyfile"}, + {"%.ini$", "%.conf$", "%.desktop$", "%.service$", "Doxyfile"}, { {{"#[%da-fA-F]+"}, "literal"}, {{"#.-\n"}, "comment"}, @@ -866,7 +866,7 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() { {{"'", "'", "\\"}, "string"}, {{"%[", "%]"}, "keyword2"}, {{"[%a][%w_-]*%s*%f[=]"}, "keyword"}, - {{"[=]"}, "operator"}, + {{"="}, "operator"}, {{"https?://%S+"}, "function"}, }} ); @@ -1673,6 +1673,19 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() { }, prepareBatchSymbols( batchSymTable ), "rem"} ); + + // diff - patch + add( {"Diff File", + {"%.diff$", "%.patch$"}, + { + {{"^%+%+%+%s.-\n"}, "keyword"}, + {{"^%-%-%-%s.-\n"}, "keyword"}, + {{"^diff%s.-\n"}, "string"}, + {{"^index%s.-\n"}, "comment"}, + {{"^@@.-\n"}, "number"}, + {{"^%+.-\n"}, "function"}, + {{"^%-.-\n"}, "keyword2"}, + }} ); } SyntaxDefinition& SyntaxDefinitionManager::add( SyntaxDefinition&& syntaxStyle ) { diff --git a/src/eepp/ui/doc/syntaxtokenizer.cpp b/src/eepp/ui/doc/syntaxtokenizer.cpp index ee285fd17..03912d1d4 100644 --- a/src/eepp/ui/doc/syntaxtokenizer.cpp +++ b/src/eepp/ui/doc/syntaxtokenizer.cpp @@ -89,7 +89,10 @@ std::pair, int> SyntaxTokenizer::tokenize( const Syntax for ( size_t patternIndex = 0; patternIndex < syntax.getPatterns().size(); patternIndex++ ) { const SyntaxPattern& pattern = syntax.getPatterns()[patternIndex]; - const std::string& patternStr( "^" + pattern.patterns.at( 0 ) ); + if ( i != 0 && pattern.patterns[0][0] == '^' ) + continue; + const std::string& patternStr( + pattern.patterns[0][0] == '^' ? pattern.patterns[0] : "^" + pattern.patterns[0] ); LuaPatternMatcher words( patternStr ); int start, end = 0; if ( words.find( text, i, start, end ) ) { diff --git a/src/eepp/ui/uimenu.cpp b/src/eepp/ui/uimenu.cpp index 0524ab479..aa56a6e46 100644 --- a/src/eepp/ui/uimenu.cpp +++ b/src/eepp/ui/uimenu.cpp @@ -41,10 +41,10 @@ bool UIMenu::isType( const Uint32& type ) const { return UIMenu::getType() == type ? true : UIWidget::isType( type ); } -void UIMenu::setTheme( UITheme* Theme ) { - UIWidget::setTheme( Theme ); +void UIMenu::setTheme( UITheme* theme ) { + UIWidget::setTheme( theme ); - setThemeSkin( Theme, "menu" ); + setThemeSkin( theme, "menu" ); onThemeLoaded(); } @@ -60,61 +60,79 @@ void UIMenu::onPaddingChange() { widgetsSetPos(); } -UIMenuItem* UIMenu::createMenuItem( const String& Text, Drawable* Icon ) { - UIMenuItem* tCtrl = UIMenuItem::New(); - tCtrl->setHorizontalAlign( UI_HALIGN_LEFT ); - tCtrl->setParent( this ); - tCtrl->setIconMinimumSize( mIconMinSize ); - tCtrl->setIcon( Icon ); - tCtrl->setText( Text ); - - return tCtrl; +UIMenuItem* UIMenu::createMenuItem( const String& text, Drawable* icon, + const String& shortcutText ) { + UIMenuItem* widget = UIMenuItem::New(); + widget->setHorizontalAlign( UI_HALIGN_LEFT ); + widget->setParent( this ); + widget->setIconMinimumSize( mIconMinSize ); + widget->setIcon( icon ); + widget->setText( text ); + widget->setShortcutText( shortcutText ); + return widget; } -UIMenuItem* UIMenu::add( const String& Text, Drawable* Icon ) { - UIMenuItem* menuItem = createMenuItem( Text, Icon ); +UIMenuItem* UIMenu::add( const String& text, Drawable* icon, const String& shortcutText ) { + UIMenuItem* menuItem = createMenuItem( text, icon, shortcutText ); add( menuItem ); return menuItem; } -UIMenuCheckBox* UIMenu::createMenuCheckBox( const String& Text, const bool& Active ) { - UIMenuCheckBox* tCtrl = UIMenuCheckBox::New(); - tCtrl->setHorizontalAlign( UI_HALIGN_LEFT ); - tCtrl->setParent( this ); - tCtrl->setIconMinimumSize( mIconMinSize ); - tCtrl->setText( Text ); - - if ( Active ) - tCtrl->setActive( Active ); - - return tCtrl; +UIMenuCheckBox* UIMenu::createMenuCheckBox( const String& text, const bool& active ) { + UIMenuCheckBox* widget = UIMenuCheckBox::New(); + widget->setHorizontalAlign( UI_HALIGN_LEFT ); + widget->setParent( this ); + widget->setIconMinimumSize( mIconMinSize ); + widget->setText( text ); + if ( active ) + widget->setActive( active ); + return widget; } -UIMenuCheckBox* UIMenu::addCheckBox( const String& Text, const bool& Active ) { - UIMenuCheckBox* chkBox = createMenuCheckBox( Text, Active ); +UIMenuCheckBox* UIMenu::addCheckBox( const String& text, const bool& active ) { + UIMenuCheckBox* chkBox = createMenuCheckBox( text, active ); add( chkBox ); return chkBox; } -UIMenuSubMenu* UIMenu::createSubMenu( const String& Text, Drawable* Icon, UIMenu* SubMenu ) { +UIMenuRadioButton* UIMenu::createMenuRadioButton( const String& text, const bool& active ) { + UIMenuRadioButton* widget = UIMenuRadioButton::New(); + widget->setHorizontalAlign( UI_HALIGN_LEFT ); + widget->setParent( this ); + widget->setIconMinimumSize( mIconMinSize ); + widget->setText( text ); + + if ( active ) + widget->setActive( active ); + + return widget; +} + +UIMenuRadioButton* UIMenu::addRadioButton( const String& text, const bool& active ) { + UIMenuRadioButton* radioButton = createMenuRadioButton( text, active ); + add( radioButton ); + return radioButton; +} + +UIMenuSubMenu* UIMenu::createSubMenu( const String& text, Drawable* icon, UIMenu* subMenu ) { UIMenuSubMenu* tCtrl = UIMenuSubMenu::New(); tCtrl->setHorizontalAlign( UI_HALIGN_LEFT ); tCtrl->setParent( this ); tCtrl->setIconMinimumSize( mIconMinSize ); - tCtrl->setIcon( Icon ); - tCtrl->setText( Text ); - tCtrl->setSubMenu( SubMenu ); + tCtrl->setIcon( icon ); + tCtrl->setText( text ); + tCtrl->setSubMenu( subMenu ); return tCtrl; } -UIMenuSubMenu* UIMenu::addSubMenu( const String& Text, Drawable* Icon, UIMenu* SubMenu ) { - UIMenuSubMenu* subMenu = createSubMenu( Text, Icon, SubMenu ); - add( subMenu ); - return subMenu; +UIMenuSubMenu* UIMenu::addSubMenu( const String& text, Drawable* icon, UIMenu* subMenu ) { + UIMenuSubMenu* menu = createSubMenu( text, icon, subMenu ); + add( menu ); + return menu; } -bool UIMenu::widgetCheckSize( UIWidget* widget, const bool& Resize ) { +bool UIMenu::widgetCheckSize( UIWidget* widget, const bool& resize ) { if ( widget->isType( UI_TYPE_MENUITEM ) ) { UIMenuItem* tItem = widget->asType(); @@ -131,7 +149,7 @@ bool UIMenu::widgetCheckSize( UIWidget* widget, const bool& Resize ) { if ( widget->getPixelsSize().getWidth() > (Int32)mMaxWidth ) { mMaxWidth = widget->getPixelsSize().getWidth(); - if ( Resize ) { + if ( resize ) { widgetsResize(); return true; @@ -198,17 +216,17 @@ UIMenuSeparator* UIMenu::addSeparator() { return separator; } -UIWidget* UIMenu::getItem( const Uint32& Index ) { - eeASSERT( Index < mItems.size() ); - return mItems[Index]; +UIWidget* UIMenu::getItem( const Uint32& index ) { + eeASSERT( index < mItems.size() ); + return mItems[index]; } -UIWidget* UIMenu::getItem( const String& Text ) { +UIWidget* UIMenu::getItem( const String& text ) { for ( Uint32 i = 0; i < mItems.size(); i++ ) { if ( mItems[i]->isType( UI_TYPE_MENUITEM ) ) { UIMenuItem* tMenuItem = mItems[i]->asType(); - if ( tMenuItem->getText() == Text ) + if ( tMenuItem->getText() == text ) return tMenuItem; } } @@ -216,9 +234,9 @@ UIWidget* UIMenu::getItem( const String& Text ) { return NULL; } -Uint32 UIMenu::getItemIndex( UIWidget* Item ) { +Uint32 UIMenu::getItemIndex( UIWidget* item ) { for ( Uint32 i = 0; i < mItems.size(); i++ ) { - if ( mItems[i] == Item ) + if ( mItems[i] == item ) return i; } @@ -229,20 +247,20 @@ Uint32 UIMenu::getCount() const { return mItems.size(); } -void UIMenu::remove( const Uint32& Index ) { - eeASSERT( Index < mItems.size() ); +void UIMenu::remove( const Uint32& index ) { + eeASSERT( index < mItems.size() ); - mItems[Index]->close(); + mItems[index]->close(); - mItems.erase( mItems.begin() + Index ); + mItems.erase( mItems.begin() + index ); widgetsSetPos(); widgetsResize(); } -void UIMenu::remove( UIWidget* Ctrl ) { +void UIMenu::remove( UIWidget* widget ) { for ( Uint32 i = 0; i < mItems.size(); i++ ) { - if ( mItems[i] == Ctrl ) { + if ( mItems[i] == widget ) { remove( i ); break; } @@ -261,14 +279,14 @@ void UIMenu::removeAll() { resizeMe(); } -void UIMenu::insert( const String& Text, Drawable* Icon, const Uint32& Index ) { - insert( createMenuItem( Text, Icon ), Index ); +void UIMenu::insert( const String& text, Drawable* icon, const Uint32& index ) { + insert( createMenuItem( text, icon ), index ); } -void UIMenu::insert( UIWidget* Control, const Uint32& Index ) { - mItems.insert( mItems.begin() + Index, Control ); +void UIMenu::insert( UIWidget* widget, const Uint32& index ) { + mItems.insert( mItems.begin() + index, widget ); - childAddAt( Control, Index ); + childAddAt( widget, index ); widgetsSetPos(); widgetsResize(); @@ -642,20 +660,20 @@ const Sizei& UIMenu::getIconMinimumSize() const { return mIconMinSize; } -void UIMenu::fixMenuPos( Vector2f& Pos, UIMenu* Menu, UIMenu* Parent, UIMenuSubMenu* SubMenu ) { - SceneNode* sceneNode = Menu->getSceneNode(); +void UIMenu::fixMenuPos( Vector2f& Pos, UIMenu* menu, UIMenu* Parent, UIMenuSubMenu* subMenu ) { + SceneNode* sceneNode = menu->getSceneNode(); if ( NULL == sceneNode ) return; Rectf qScreen( 0.f, 0.f, sceneNode->getPixelsSize().getWidth(), sceneNode->getPixelsSize().getHeight() ); - Rectf qPos( Pos.x, Pos.y, Pos.x + Menu->getPixelsSize().getWidth(), - Pos.y + Menu->getPixelsSize().getHeight() ); + Rectf qPos( Pos.x, Pos.y, Pos.x + menu->getPixelsSize().getWidth(), + Pos.y + menu->getPixelsSize().getHeight() ); - if ( NULL != Parent && NULL != SubMenu ) { - Vector2f sPos = SubMenu->getPixelsPosition(); - SubMenu->nodeToWorldTranslation( sPos ); + if ( NULL != Parent && NULL != subMenu ) { + Vector2f sPos = subMenu->getPixelsPosition(); + subMenu->nodeToWorldTranslation( sPos ); Vector2f pPos = Parent->getPixelsPosition(); Parent->nodeToWorldTranslation( pPos ); @@ -666,30 +684,30 @@ void UIMenu::fixMenuPos( Vector2f& Pos, UIMenu* Menu, UIMenu* Parent, UIMenuSubM Pos.x = qParent.Right; Pos.y = sPos.y; qPos.Left = Pos.x; - qPos.Right = qPos.Left + Menu->getPixelsSize().getWidth(); + qPos.Right = qPos.Left + menu->getPixelsSize().getWidth(); qPos.Top = Pos.y; - qPos.Bottom = qPos.Top + Menu->getPixelsSize().getHeight(); + qPos.Bottom = qPos.Top + menu->getPixelsSize().getHeight(); Vector2f oriPos( Pos ); if ( !qScreen.contains( qPos ) ) { Pos.y = - sPos.y + SubMenu->getPixelsSize().getHeight() - Menu->getPixelsSize().getHeight(); + sPos.y + subMenu->getPixelsSize().getHeight() - menu->getPixelsSize().getHeight(); qPos.Top = Pos.y; - qPos.Bottom = qPos.Top + Menu->getPixelsSize().getHeight(); + qPos.Bottom = qPos.Top + menu->getPixelsSize().getHeight(); if ( !qScreen.contains( qPos ) ) { - Pos.x = qParent.Left - Menu->getPixelsSize().getWidth(); + Pos.x = qParent.Left - menu->getPixelsSize().getWidth(); Pos.y = sPos.y; qPos.Left = Pos.x; - qPos.Right = qPos.Left + Menu->getPixelsSize().getWidth(); + qPos.Right = qPos.Left + menu->getPixelsSize().getWidth(); qPos.Top = Pos.y; - qPos.Bottom = qPos.Top + Menu->getPixelsSize().getHeight(); + qPos.Bottom = qPos.Top + menu->getPixelsSize().getHeight(); if ( !qScreen.contains( qPos ) ) { - Pos.y = sPos.y + SubMenu->getPixelsSize().getHeight() - - Menu->getPixelsSize().getHeight(); + Pos.y = sPos.y + subMenu->getPixelsSize().getHeight() - + menu->getPixelsSize().getHeight(); qPos.Top = Pos.y; - qPos.Bottom = qPos.Top + Menu->getPixelsSize().getHeight(); + qPos.Bottom = qPos.Top + menu->getPixelsSize().getHeight(); if ( !qScreen.contains( qPos ) ) { Pos = oriPos; @@ -699,19 +717,19 @@ void UIMenu::fixMenuPos( Vector2f& Pos, UIMenu* Menu, UIMenu* Parent, UIMenuSubM } } else { if ( !qScreen.contains( qPos ) ) { - Pos.y -= Menu->getPixelsSize().getHeight(); - qPos.Top -= Menu->getPixelsSize().getHeight(); - qPos.Bottom -= Menu->getPixelsSize().getHeight(); + Pos.y -= menu->getPixelsSize().getHeight(); + qPos.Top -= menu->getPixelsSize().getHeight(); + qPos.Bottom -= menu->getPixelsSize().getHeight(); if ( !qScreen.contains( qPos ) ) { - Pos.x -= Menu->getPixelsSize().getWidth(); - qPos.Left -= Menu->getPixelsSize().getWidth(); - qPos.Right -= Menu->getPixelsSize().getWidth(); + Pos.x -= menu->getPixelsSize().getWidth(); + qPos.Left -= menu->getPixelsSize().getWidth(); + qPos.Right -= menu->getPixelsSize().getWidth(); if ( !qScreen.contains( qPos ) ) { - Pos.y += Menu->getPixelsSize().getHeight(); - qPos.Top += Menu->getPixelsSize().getHeight(); - qPos.Bottom += Menu->getPixelsSize().getHeight(); + Pos.y += menu->getPixelsSize().getHeight(); + qPos.Top += menu->getPixelsSize().getHeight(); + qPos.Bottom += menu->getPixelsSize().getHeight(); } } } diff --git a/src/eepp/ui/uimenubar.cpp b/src/eepp/ui/uimenubar.cpp index 5972d43b8..a8e5b495d 100644 --- a/src/eepp/ui/uimenubar.cpp +++ b/src/eepp/ui/uimenubar.cpp @@ -1,9 +1,9 @@ #include #include #include +#include #include #include -#include #include namespace EE { namespace UI { @@ -12,7 +12,8 @@ UIMenuBar* UIMenuBar::New() { return eeNew( UIMenuBar, () ); } -UIMenuBar::UIMenuBar() : UIWidget( "menubar" ), mMenuHeight( 0 ), mCurrentMenu( NULL ) { +UIMenuBar::UIMenuBar() : + UIWidget( "menubar" ), mMenuHeight( 0 ), mCurrentMenu( NULL ), mWaitingUp( NULL ) { if ( !( mFlags & UI_ANCHOR_RIGHT ) ) mFlags |= UI_ANCHOR_RIGHT; @@ -57,6 +58,7 @@ void UIMenuBar::addMenuButton( const String& ButtonText, UIPopUpMenu* Menu ) { Menu->setVisible( false ); Menu->setEnabled( false ); + Menu->setOwnerNode( Button ); // This will force to change the parent when shown, and force the CSS style reload. Menu->setParent( this ); Menu->addEventListener( Event::OnWidgetFocusLoss, @@ -105,7 +107,6 @@ UISelectButton* UIMenuBar::getButton( const String& ButtonText ) { return it->first; } } - return NULL; } @@ -115,7 +116,6 @@ UIPopUpMenu* UIMenuBar::getPopUpMenu( const String& ButtonText ) { return it->second; } } - return NULL; } @@ -179,37 +179,38 @@ bool UIMenuBar::applyProperty( const StyleSheetProperty& attribute ) { return true; } -Uint32 UIMenuBar::onMessage( const NodeMessage* Msg ) { - switch ( Msg->getMsg() ) { +Uint32 UIMenuBar::onMessage( const NodeMessage* msg ) { + switch ( msg->getMsg() ) { case NodeMessage::MouseUp: + mWaitingUp = NULL; + case NodeMessage::MouseDown: case NodeMessage::MouseOver: { - if ( Msg->getSender()->isType( UI_TYPE_SELECTBUTTON ) ) { - UISelectButton* tbut = Msg->getSender()->asType(); + if ( msg->getSender()->isType( UI_TYPE_SELECTBUTTON ) ) { + UISelectButton* tbut = msg->getSender()->asType(); UIPopUpMenu* tpop = getMenuFromButton( tbut ); Vector2f pos( tbut->getPosition().x, tbut->getPosition().y + tbut->getSize().getHeight() ); tpop->setPosition( pos ); - if ( Msg->getMsg() == NodeMessage::MouseOver ) { - if ( NULL != mCurrentMenu ) { + if ( msg->getMsg() == NodeMessage::MouseOver ) { + if ( NULL != mCurrentMenu && mCurrentMenu != tpop ) { mCurrentMenu = tpop; - tbut->select(); tpop->setParent( getWindowContainer() ); tpop->show(); } } else { - if ( Msg->getFlags() & EE_BUTTON_LMASK ) { - if ( mCurrentMenu != tpop ) { + if ( msg->getMsg() == NodeMessage::MouseDown && + msg->getFlags() & EE_BUTTON_LMASK ) { + if ( !tpop->isVisible() ) { mCurrentMenu = tpop; - tbut->select(); tpop->setParent( getWindowContainer() ); tpop->show(); - } else { + mWaitingUp = tpop; + } else if ( mCurrentMenu != tpop || mWaitingUp == NULL ) { mCurrentMenu = NULL; - tbut->unselect(); tpop->hide(); } @@ -223,34 +224,31 @@ Uint32 UIMenuBar::onMessage( const NodeMessage* Msg ) { } case NodeMessage::Selected: { for ( MenuBarList::iterator it = mButtons.begin(); it != mButtons.end(); ++it ) { - if ( it->first != Msg->getSender() ) { + if ( it->first != msg->getSender() ) { it->first->unselect(); + it->second->hide(); } } - return 1; } case NodeMessage::FocusLoss: { + mWaitingUp = NULL; if ( NULL != getEventDispatcher() ) { - Node* FocusCtrl = getEventDispatcher()->getFocusNode(); + Node* focusNode = getEventDispatcher()->getFocusNode(); - if ( !isParentOf( FocusCtrl ) && !isPopUpMenuChild( FocusCtrl ) ) { + if ( !isParentOf( focusNode ) && !isPopUpMenuChild( focusNode ) ) { onWidgetFocusLoss(); } - return 1; } } } - return 0; } void UIMenuBar::onParentChange() { setSize( getParent()->getSize().getWidth(), mMenuHeight ); - updateAnchorsDistances(); - UIWidget::onParentChange(); } @@ -274,20 +272,18 @@ UIPopUpMenu* UIMenuBar::getMenuFromButton( UISelectButton* Button ) { return NULL; } -bool UIMenuBar::isPopUpMenuChild( Node* Ctrl ) { +bool UIMenuBar::isPopUpMenuChild( Node* node ) { for ( MenuBarList::iterator it = mButtons.begin(); it != mButtons.end(); ++it ) { - if ( it->second == Ctrl || it->second->isParentOf( Ctrl ) ) { + if ( it->second == node || it->second->isParentOf( node ) ) { return true; } } - return false; } void UIMenuBar::onMenuFocusLoss( const Event* ) { - Node* FocusCtrl = getEventDispatcher()->getFocusNode(); - - if ( !isParentOf( FocusCtrl ) && !isPopUpMenuChild( FocusCtrl ) ) { + Node* focusNode = getEventDispatcher()->getFocusNode(); + if ( !isParentOf( focusNode ) && !isPopUpMenuChild( focusNode ) ) { onWidgetFocusLoss(); } } diff --git a/src/eepp/ui/uimenuitem.cpp b/src/eepp/ui/uimenuitem.cpp index 12ca5a5cb..c1e5a5465 100644 --- a/src/eepp/ui/uimenuitem.cpp +++ b/src/eepp/ui/uimenuitem.cpp @@ -7,7 +7,7 @@ UIMenuItem* UIMenuItem::New() { return eeNew( UIMenuItem, () ); } -UIMenuItem::UIMenuItem( const std::string& tag ) : UIPushButton( tag ) { +UIMenuItem::UIMenuItem( const std::string& tag ) : UIPushButton( tag ), mShortcutView( NULL ) { mIcon->setElementTag( mTag + "::icon" ); mTextBox->setElementTag( mTag + "::text" ); applyDefaultTheme(); @@ -31,12 +31,47 @@ void UIMenuItem::setTheme( UITheme* Theme ) { onThemeLoaded(); } +void UIMenuItem::setShortcutText( const String& text ) { + if ( !text.empty() ) + createShortcutView(); + if ( mShortcutView ) + mShortcutView->setText( text ); +} + +UITextView* UIMenuItem::getShortcutView() const { + return mShortcutView; +} + +void UIMenuItem::onSizeChange() { + UIPushButton::onSizeChange(); + if ( mShortcutView ) { + mShortcutView->setPosition( getSize().getWidth() - mShortcutView->getSize().getWidth() - + mShortcutView->getLayoutMargin().Right, + 0 ); + mShortcutView->centerVertical(); + } +} + Uint32 UIMenuItem::onMouseOver( const Vector2i& Pos, const Uint32& Flags ) { UIPushButton::onMouseOver( Pos, Flags ); - getParent()->asType()->setItemSelected( this ); - return 1; } +UIWidget* UIMenuItem::getExtraInnerWidget() { + return mShortcutView; +} + +void UIMenuItem::createShortcutView() { + if ( mShortcutView ) + return; + mShortcutView = UITextView::NewWithTag( mTag + "::shortcut" ); + mShortcutView->setParent( this )->setVisible( true )->setEnabled( false ); + mShortcutView->setFlags( UI_AUTO_SIZE | UI_HALIGN_RIGHT ); + auto cb = [&]( const Event* ) { onSizeChange(); }; + mShortcutView->addEventListener( Event::OnPaddingChange, cb ); + mShortcutView->addEventListener( Event::OnMarginChange, cb ); + mShortcutView->addEventListener( Event::OnSizeChange, cb ); +} + }} // namespace EE::UI diff --git a/src/eepp/ui/uimenuradiobutton.cpp b/src/eepp/ui/uimenuradiobutton.cpp new file mode 100644 index 000000000..0379aa59e --- /dev/null +++ b/src/eepp/ui/uimenuradiobutton.cpp @@ -0,0 +1,135 @@ +#include +#include +#include + +namespace EE { namespace UI { + +UIMenuRadioButton* UIMenuRadioButton::New() { + return eeNew( UIMenuRadioButton, () ); +} + +UIMenuRadioButton::UIMenuRadioButton() : + UIMenuItem( "menu::radiobutton" ), + mActive( false ), + mSkinActive( NULL ), + mSkinInactive( NULL ) { + mIcon->setElementTag( mTag + "::icon" ); + mTextBox->setElementTag( mTag + "::text" ); + applyDefaultTheme(); + mIcon->setFlags( UI_SKIN_KEEP_SIZE_ON_DRAW ); +} + +UIMenuRadioButton::~UIMenuRadioButton() {} + +Uint32 UIMenuRadioButton::getType() const { + return UI_TYPE_MENURADIOBUTTON; +} + +bool UIMenuRadioButton::isType( const Uint32& type ) const { + return UIMenuRadioButton::getType() == type ? true : UIMenuItem::isType( type ); +} + +void UIMenuRadioButton::setTheme( UITheme* Theme ) { + UIWidget::setTheme( Theme ); + + setThemeSkin( Theme, "menuitem" ); + + mSkinActive = Theme->getSkin( "menuradiobutton_active" ); + mSkinInactive = Theme->getSkin( "menuradiobutton_inactive" ); + + mActive = !mActive; + setActive( !mActive ); + + onThemeLoaded(); +} + +const bool& UIMenuRadioButton::isActive() const { + return mActive; +} + +void UIMenuRadioButton::setActive( const bool& active ) { + if ( mActive == active ) + return; + + mActive = active; + + if ( mActive ) { + mIcon->pushState( UIState::StateSelected ); + } else { + mIcon->popState( UIState::StateSelected ); + } + + if ( mActive ) { + if ( NULL != mSkinActive ) { + if ( NULL == mIcon->getSkin() || mIcon->getSkin()->getName() != mSkinActive->getName() ) + mIcon->setSkin( mSkinActive ); + + if ( NULL != mSkinState ) { + if ( mSkinState->getState() & UIState::StateFlagSelected ) { + mIcon->pushState( UIState::StateHover ); + } else { + mIcon->popState( UIState::StateHover ); + } + } + } else { + mIcon->removeSkin(); + } + } else { + if ( NULL != mSkinInactive ) { + if ( NULL == mIcon->getSkin() || + mIcon->getSkin()->getName() != mSkinInactive->getName() ) + mIcon->setSkin( mSkinInactive ); + + if ( NULL != mSkinState ) { + if ( mSkinState->getState() & UIState::StateFlagSelected ) { + mIcon->pushState( UIState::StateHover ); + } else { + mIcon->popState( UIState::StateHover ); + } + } + } else { + mIcon->removeSkin(); + } + } + + UIMenu* Menu = getParent()->asType(); + + if ( !Menu->widgetCheckSize( this ) ) { + if ( NULL != getIcon()->getDrawable() ) { + setPadding( Rectf( 0, 0, 0, 0 ) ); + } + } + + if ( mActive ) { + Node* child = Menu->getFirstChild(); + while ( child ) { + if ( child->isType( UI_TYPE_MENURADIOBUTTON ) && child != this ) { + child->asType()->setActive( false ); + } + child = child->getNextNode(); + } + } + + onValueChange(); +} + +void UIMenuRadioButton::switchActive() { + setActive( !mActive ); +} + +Uint32 UIMenuRadioButton::onMouseUp( const Vector2i& Pos, const Uint32& Flags ) { + UIMenuItem::onMouseUp( Pos, Flags ); + + if ( getParent()->isVisible() && ( Flags & EE_BUTTONS_LRM ) ) + switchActive(); + + return 1; +} + +void UIMenuRadioButton::onStateChange() { + UIMenuItem::onStateChange(); + + setActive( mActive ); +} + +}} // namespace EE::UI diff --git a/src/eepp/ui/uimenusubmenu.cpp b/src/eepp/ui/uimenusubmenu.cpp index 7a0e8dbd2..3116bc45d 100644 --- a/src/eepp/ui/uimenusubmenu.cpp +++ b/src/eepp/ui/uimenusubmenu.cpp @@ -53,9 +53,8 @@ void UIMenuSubMenu::setTheme( UITheme* Theme ) { void UIMenuSubMenu::onSizeChange() { UIMenuItem::onSizeChange(); - mArrow->setPosition( getSize().getWidth() - mArrow->getSize().getWidth() - - PixelDensity::dpToPx( mArrow->getLayoutMargin().Right ), - 0 ); + mArrow->setPosition( + getSize().getWidth() - mArrow->getSize().getWidth() - mArrow->getLayoutMargin().Right, 0 ); mArrow->centerVertical(); } diff --git a/src/eepp/ui/uipushbutton.cpp b/src/eepp/ui/uipushbutton.cpp index 0ee67d8a5..163a1337f 100644 --- a/src/eepp/ui/uipushbutton.cpp +++ b/src/eepp/ui/uipushbutton.cpp @@ -25,7 +25,6 @@ UIPushButton::UIPushButton( const std::string& tag ) : auto cb = [&]( const Event* ) { onSizeChange(); - notifyLayoutAttrChange(); }; mIcon->addEventListener( Event::OnPaddingChange, cb ); diff --git a/src/eepp/ui/uitouchdraggablewidget.cpp b/src/eepp/ui/uitouchdraggablewidget.cpp index 84e7bb055..1405fae9f 100644 --- a/src/eepp/ui/uitouchdraggablewidget.cpp +++ b/src/eepp/ui/uitouchdraggablewidget.cpp @@ -86,7 +86,7 @@ void UITouchDraggableWidget::scheduledUpdate( const Time& time ) { mTouchDragPoint = Pos; getEventDispatcher()->setNodeDragging( this ); - } else { + } else if ( mTouchDragAcceleration != Vector2f::Zero ) { mTouchDragAcceleration -= elapsed * mTouchDragDeceleration; } } else { @@ -134,8 +134,7 @@ Uint32 UITouchDraggableWidget::onMessage( const NodeMessage* msg ) { !getEventDispatcher()->isNodeDragging() ) { setTouchDragging( true ); getEventDispatcher()->setNodeDragging( this ); - mTouchDragPoint = Vector2f( getEventDispatcher()->getMousePos().x, - getEventDispatcher()->getMousePos().y ); + mTouchDragPoint = getEventDispatcher()->getMousePosf(); mTouchDragAcceleration = Vector2f( 0, 0 ); return 1; } diff --git a/src/tests/test_all/test.cpp b/src/tests/test_all/test.cpp index 7afbb670b..761638ef0 100644 --- a/src/tests/test_all/test.cpp +++ b/src/tests/test_all/test.cpp @@ -546,6 +546,8 @@ void EETest::createBaseUI() { Menu2->add( "Test 2" ); Menu2->add( "Test 3" ); Menu2->add( "Test 4" ); + Menu2->addRadioButton( "Test Radio Button" ); + Menu2->addRadioButton( "Test Radio Button Active" )->setActive( true ); Menu2->addSubMenu( "Hello World", NULL, Menu3 ); Menu->addSeparator(); diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 3e053f5bd..fe3657f1a 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -802,18 +802,18 @@ App::~App() { void App::createSettingsMenu() { mSettingsMenu = UIPopUpMenu::New(); - mSettingsMenu->add( "New" ); - mSettingsMenu->add( "Open..." ); + mSettingsMenu->add( "New", NULL, "Ctrl+T" ); + mSettingsMenu->add( "Open...", NULL, "Ctrl+O" ); mSettingsMenu->addSeparator(); - mSettingsMenu->add( "Save" ); + mSettingsMenu->add( "Save", NULL, "Ctrl+S" ); mSettingsMenu->add( "Save as..." ); mSettingsMenu->addSeparator(); mSettingsMenu->addSubMenu( "Filetype", NULL, createFiletypeMenu() ); mSettingsMenu->addSubMenu( "Color Scheme", NULL, createColorSchemeMenu() ); mSettingsMenu->addSeparator(); - mSettingsMenu->add( "Close" ); + mSettingsMenu->add( "Close", NULL, "Ctrl+W" ); mSettingsMenu->addSeparator(); - mSettingsMenu->add( "Quit" ); + mSettingsMenu->add( "Quit", NULL, "Ctrl+Q" ); mSettingsButton = mUISceneNode->find( "settings" ); mSettingsButton->addEventListener( Event::MouseClick, [&]( const Event* ) { Vector2f pos( mSettingsButton->getPixelsPosition() ); @@ -849,7 +849,7 @@ void App::setColorScheme( const std::string& name ) { void App::updateColorSchemeMenu() { for ( size_t i = 0; i < mColorSchemeMenu->getCount(); i++ ) { - UIMenuCheckBox* menuItem = mColorSchemeMenu->getItem( i )->asType(); + UIMenuRadioButton* menuItem = mColorSchemeMenu->getItem( i )->asType(); menuItem->setActive( mCurrentColorScheme == menuItem->getText() ); } } @@ -857,8 +857,8 @@ void App::updateColorSchemeMenu() { UIMenu* App::createColorSchemeMenu() { mColorSchemeMenu = UIPopUpMenu::New(); for ( auto& colorScheme : mColorSchemes ) { - mColorSchemeMenu->addCheckBox( colorScheme.first, - mCurrentColorScheme == colorScheme.first ); + mColorSchemeMenu->addRadioButton( colorScheme.first, + mCurrentColorScheme == colorScheme.first ); } mColorSchemeMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { UIMenuItem* item = event->getNode()->asType(); @@ -873,7 +873,7 @@ UIMenu* App::createFiletypeMenu() { mFiletypeMenu = UIPopUpMenu::New(); auto names = dM->getLanguageNames(); for ( auto& name : names ) { - mFiletypeMenu->addCheckBox( + mFiletypeMenu->addRadioButton( name, mCurEditor && mCurEditor->getSyntaxDefinition().getLanguageName() == name ); } mFiletypeMenu->addEventListener( Event::OnItemClicked, [&, dM]( const Event* event ) { @@ -892,7 +892,7 @@ void App::updateCurrentFiletype() { return; std::string curLang( mCurEditor->getSyntaxDefinition().getLanguageName() ); for ( size_t i = 0; i < mFiletypeMenu->getCount(); i++ ) { - UIMenuCheckBox* menuItem = mFiletypeMenu->getItem( i )->asType(); + UIMenuRadioButton* menuItem = mFiletypeMenu->getItem( i )->asType(); std::string itemLang( menuItem->getText() ); menuItem->setActive( curLang == itemLang ); } diff --git a/src/tools/uieditor/uieditor.cpp b/src/tools/uieditor/uieditor.cpp index 1b8a329eb..9a84d7024 100644 --- a/src/tools/uieditor/uieditor.cpp +++ b/src/tools/uieditor/uieditor.cpp @@ -1064,10 +1064,9 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { } #if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN - setUserDefaultTheme(); if ( !xmlFile && !cssFile ) - loadStyleSheet( "assets/layouts/test.css" ); - loadLayoutFile( "assets/layouts/test.xml" ); + loadStyleSheet( "assets/ui/breeze.css" ); + loadLayoutFile( "assets/layouts/test_widgets.xml" ); #endif window->runMainLoop( &mainLoop );