diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 4186e44ac..82750d510 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -34,6 +34,8 @@ --icon-line-hover: #3d4246; --icon-back-alert: #e49aa2; --win-icon: #dbdbdd; + --tab-close: #909396; + --tab-close-hover: #863d47; } CheckBox, @@ -445,6 +447,21 @@ Tab:selectedhover { background-color: var(--tab-active); } +Tab::close { + width: 10dp; + height: 10dp; + border-radius: 5dp; + background-color: var(--tab-close); + foreground-image: poly(line, var(--tab-hover), "0dp 0dp, 5dp 5dp"), poly(line, var(--icon-line-hover), "5dp 0dp, 0dp 5dp"); + foreground-position: 2.5dp 2.5dp, 2.5dp 2.5dp; + margin-right: 4dp; + transition: all 0.15s; +} + +Tab::close:hover { + background-color: var(--tab-close-hover); +} + Loader { fill-color: var(--primary); } diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 22a7d9741..933a4ac7b 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -1554,10 +1554,30 @@ src: drawable_resource_name; /** same as doing: @drawable/drawable_resource_name --- +### tabbar-hide-on-single-tab + +Enables/disables the tab bar hiding when only one tab is contained in the tab widget. + +* Applicable to: EE::UI::UITabWidget (TabWidget) +* Data Type: [boolean](#boolean-data-type) +* Default value: `false` + +--- + +### tabbar-allow-rearrange + +Enables/disables manually rearraging the tabs in the tab bar. + +* Applicable to: EE::UI::UITabWidget (TabWidget) +* Data Type: [boolean](#boolean-data-type) +* Default value: `false` + +--- + ### tab-closable -Enables/disables tabs to be closable with the middle mouse button click (pending implementation of a close -button inside a tab). +Enables/disables tabs to be closable with the middle mouse button click or by clicking on the close +button. * Applicable to: EE::UI::UITabWidget (TabWidget) * Data Type: [boolean](#boolean-data-type) diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp index d2f1d7138..e5f6c11e7 100644 --- a/include/eepp/ui/css/propertydefinition.hpp +++ b/include/eepp/ui/css/propertydefinition.hpp @@ -189,6 +189,8 @@ enum class PropertyId : Uint32 { BorderTopRightRadius = String::hash( "border-top-right-radius" ), BorderBottomLeftRadius = String::hash( "border-bottom-left-radius" ), BorderBottomRightRadius = String::hash( "border-bottom-right-radius" ), + TabBarHideOnSingleTab = String::hash( "tabbar-hide-on-single-tab" ), + TabBarAllowRearrange = String::hash( "tabbar-allow-rearrange" ), }; enum class PropertyType : Uint32 { diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp index 290ba99d9..b09741634 100644 --- a/include/eepp/ui/uihelper.hpp +++ b/include/eepp/ui/uihelper.hpp @@ -37,6 +37,8 @@ enum UIFlag { UI_ATTRIBUTE_CHANGED = ( 1 << 20 ), UI_CHECKED = ( 1 << 21 ), UI_OWNS_CHILDS_POSITION = ( 1 << 22 ), + UI_DRAG_VERTICAL = ( 1 << 23 ), + UI_DRAG_HORIZONTAL = ( 1 << 24 ) }; enum UINodeType { @@ -98,15 +100,18 @@ enum class PositionPolicy : Uint32 { None, LeftOf, RightOf, TopOf, BottomOf }; enum class UIScaleType : Uint32 { None, Expand, FitInside }; -static const Uint32 UI_CONTROL_DEFAULT_ALIGN = UI_HALIGN_LEFT | UI_VALIGN_CENTER; +static const Uint32 UI_NODE_DEFAULT_ALIGN = UI_HALIGN_LEFT | UI_VALIGN_CENTER; -static const Uint32 UI_CONTROL_ALIGN_CENTER = UI_HALIGN_CENTER | UI_VALIGN_CENTER; +static const Uint32 UI_NODE_ALIGN_CENTER = UI_HALIGN_CENTER | UI_VALIGN_CENTER; -static const Uint32 UI_CONTROL_DEFAULT_ANCHOR = UI_ANCHOR_LEFT | UI_ANCHOR_TOP; +static const Uint32 UI_NODE_DEFAULT_ANCHOR = UI_ANCHOR_LEFT | UI_ANCHOR_TOP; -static const Uint32 UI_CONTROL_DEFAULT_FLAGS = UI_CONTROL_DEFAULT_ANCHOR | UI_CONTROL_DEFAULT_ALIGN; +static const Uint32 UI_NODE_DEFAULT_DRAG = UI_DRAG_VERTICAL | UI_DRAG_HORIZONTAL; -static const Uint32 UI_CONTROL_DEFAULT_FLAGS_CENTERED = +static const Uint32 UI_NODE_DEFAULT_FLAGS = + UI_NODE_DEFAULT_ANCHOR | UI_NODE_DEFAULT_ALIGN | UI_NODE_DEFAULT_DRAG; + +static const Uint32 UI_NODE_DEFAULT_FLAGS_CENTERED = UI_ANCHOR_LEFT | UI_ANCHOR_TOP | UI_HALIGN_CENTER | UI_VALIGN_CENTER; }} // namespace EE::UI diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp index 1e7f232d5..063d1ba03 100644 --- a/include/eepp/ui/uinode.hpp +++ b/include/eepp/ui/uinode.hpp @@ -303,7 +303,7 @@ class EE_API UINode : public Node { virtual Uint32 onCalculateDrag( const Vector2f& position, const Uint32& flags ); - virtual Uint32 onDrag( const Vector2f& position, const Uint32& flags ); + virtual Uint32 onDrag( const Vector2f& position, const Uint32& flags, const Sizef& dragDiff ); virtual Uint32 onDragStart( const Vector2i& position, const Uint32& flags ); diff --git a/include/eepp/ui/uisplitter.hpp b/include/eepp/ui/uisplitter.hpp index 321c6d638..74451a441 100644 --- a/include/eepp/ui/uisplitter.hpp +++ b/include/eepp/ui/uisplitter.hpp @@ -55,6 +55,8 @@ class EE_API UISplitter : public UILayout { virtual Uint32 onMessage( const NodeMessage* Msg ); void updateFromDrag(); + + void updateSplitterDragFlags(); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uitab.hpp b/include/eepp/ui/uitab.hpp index ac8e41a7d..6fdf941df 100644 --- a/include/eepp/ui/uitab.hpp +++ b/include/eepp/ui/uitab.hpp @@ -42,10 +42,13 @@ class EE_API UITab : public UISelectButton { Node* mOwnedWidget; String mText; std::string mOwnedName; + UIWidget* mCloseButton; - virtual Uint32 onMouseUp( const Vector2i& position, const Uint32& flags ); + Uint32 onDrag( const Vector2f& position, const Uint32& flags, const Sizef& dragDiff ); - virtual Uint32 onMouseClick( const Vector2i& position, const Uint32& flags ); + Uint32 onDragStop( const Vector2i& position, const Uint32& flags ); + + virtual Uint32 onMessage( const NodeMessage* message ); virtual void onStateChange(); @@ -55,6 +58,8 @@ class EE_API UITab : public UISelectButton { virtual void onSizeChange(); + virtual UIWidget* getExtraInnerWidget(); + void setOwnedControl(); void updateTab(); diff --git a/include/eepp/ui/uitabwidget.hpp b/include/eepp/ui/uitabwidget.hpp index aff994196..a05f243df 100644 --- a/include/eepp/ui/uitabwidget.hpp +++ b/include/eepp/ui/uitabwidget.hpp @@ -1,4 +1,4 @@ -#ifndef EE_UICUITABWIDGET_HPP +#ifndef EE_UICUITABWIDGET_HPP #define EE_UICUITABWIDGET_HPP #include @@ -33,6 +33,8 @@ class EE_API UITabWidget : public UIWidget { //! border tab ) are different from the central tabs. }; + typedef std::function TabTryCloseCallback; + static UITabWidget* New(); UITabWidget(); @@ -124,9 +126,17 @@ class EE_API UITabWidget : public UIWidget { UITab* setTabSelected( const Uint32& tabIndex ); - const bool& getHideWhenNotNeeded() const; + const bool& getHideTabBarOnSingleTab() const; - void setHideWhenNotNeeded( const bool& hideWhenNotNeeded ); + void setHideTabBarOnSingleTab( const bool& hideTabBarOnSingleTab ); + + const TabTryCloseCallback& getTabTryCloseCallback() const; + + void setTabTryCloseCallback( const TabTryCloseCallback& tabTryCloseCallback ); + + const bool& getAllowRearrangeTabs() const; + + void setAllowRearrangeTabs( bool allowRearrangeTabs ); protected: friend class UITab; @@ -137,7 +147,9 @@ class EE_API UITabWidget : public UIWidget { std::deque mTabs; UITab* mTabSelected; Uint32 mTabSelectedIndex; - bool mHideWhenNotNeeded; + TabTryCloseCallback mTabTryCloseCallback; + bool mHideTabBarOnSingleTab; + bool mAllowRearrangeTabs; void onThemeLoaded(); @@ -162,6 +174,10 @@ class EE_API UITabWidget : public UIWidget { void applyThemeToTabs(); void refreshOwnedWidget( UITab* tab ); + + void tryCloseTab( UITab* tab ); + + void swapTabs( UITab* left, UITab* right ); }; }} // namespace EE::UI diff --git a/premake5.lua b/premake5.lua index c0fe237f0..cc7cec7b8 100644 --- a/premake5.lua +++ b/premake5.lua @@ -214,6 +214,7 @@ function build_link_configuration( package_name, use_ee_icon ) targetname ( package_name .. "-debug" .. extension ) filter "configurations:release*" + defines { "NDEBUG" } targetname ( package_name .. extension ) filter { "system:windows", "action:not vs*" } diff --git a/src/eepp/maps/mapeditor/mapeditor.cpp b/src/eepp/maps/mapeditor/mapeditor.cpp index 32defe1cd..1abd0aab7 100644 --- a/src/eepp/maps/mapeditor/mapeditor.cpp +++ b/src/eepp/maps/mapeditor/mapeditor.cpp @@ -31,7 +31,7 @@ namespace EE { namespace Maps { static UITextView* createTextBox( const String& Text = "", Node* Parent = NULL, const Sizef& Size = Sizef(), const Vector2f& Pos = Vector2f(), - const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, + const Uint32& Flags = UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, const Uint32& fontStyle = Text::Regular ) { UITextView* Ctrl = UITextView::New(); Ctrl->setFontStyle( fontStyle ); @@ -292,7 +292,7 @@ void MapEditor::fillGotyList() { void MapEditor::createTextureRegionContainer( Int32 Width ) { UITextView* Txt; - Uint32 TxtFlags = UI_CONTROL_DEFAULT_ALIGN | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; + Uint32 TxtFlags = UI_NODE_DEFAULT_ALIGN | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; Txt = createTextBox( "Add Game Object as...", mTextureRegionCont, Sizef( Width, 16 ), Vector2f( TAB_CONT_X_DIST, 4 ), TxtFlags, Text::Shadow ); @@ -340,7 +340,7 @@ void MapEditor::createTextureRegionContainer( Int32 Width ) { mLayerList->getSize().getHeight() + 4 ), TxtFlags, Text::Shadow ); - Uint32 ChkFlags = UI_CONTROL_DEFAULT_ALIGN | UI_AUTO_SIZE | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; + Uint32 ChkFlags = UI_NODE_DEFAULT_ALIGN | UI_AUTO_SIZE | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; mChkMirrored = UICheckBox::New(); mChkMirrored->setFontStyle( Text::Shadow ) @@ -503,7 +503,7 @@ void MapEditor::createLighContainer() { UITextView* Txt = createTextBox( "Light Color:", mLightCont, Sizef(), Vector2f( TAB_CONT_X_DIST, 32 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE ); Txt->setFontStyle( Text::Shadow ); mUIBaseColor = UIWidget::New(); @@ -519,7 +519,7 @@ void MapEditor::createLighContainer() { "R:", mLightCont, Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIBaseColor->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIRedSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIRedSlider->setParent( mLightCont ) @@ -534,13 +534,13 @@ void MapEditor::createLighContainer() { String::toStr( (Uint32)255 ), mLightCont, Sizef(), Vector2f( mUIRedSlider->getPosition().x + mUIRedSlider->getSize().getWidth() + 4, mUIRedSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "G:", mLightCont, Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIRedSlider->getPosition().y + mUIRedSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIGreenSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIGreenSlider->setParent( mLightCont ) ->setSize( 100, 20 ) @@ -554,13 +554,13 @@ void MapEditor::createLighContainer() { String::toStr( (Uint32)255 ), mLightCont, Sizef(), Vector2f( mUIGreenSlider->getPosition().x + mUIGreenSlider->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "B:", mLightCont, Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y + mUIGreenSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIBlueSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIBlueSlider->setParent( mLightCont ) ->setSize( 100, 20 ) @@ -574,12 +574,12 @@ void MapEditor::createLighContainer() { String::toStr( (Uint32)255 ), mLightCont, Sizef(), Vector2f( mUIBlueSlider->getPosition().x + mUIBlueSlider->getSize().getWidth() + 4, mUIBlueSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "Light Radius:", mLightCont, Sizef(), Vector2f( TAB_CONT_X_DIST, mUIBlueTxt->getPosition().y + mUIBlueTxt->getSize().getHeight() + 16 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mLightRadius = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); mLightRadius->setParent( mLightCont ) @@ -627,7 +627,7 @@ void MapEditor::createObjectsContainer() { Int32 nextY = Button->getPosition().y + Button->getSize().getHeight() + 4; - Uint32 ChkFlags = UI_CONTROL_DEFAULT_ALIGN | UI_AUTO_SIZE | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; + Uint32 ChkFlags = UI_NODE_DEFAULT_ALIGN | UI_AUTO_SIZE | UI_ANCHOR_RIGHT | UI_ANCHOR_TOP; mChkClampToTile = UICheckBox::New(); mChkClampToTile->resetFlags( ChkFlags )->setParent( mObjectCont )->setPosition( 12, nextY ); diff --git a/src/eepp/maps/mapeditor/mapobjectproperties.cpp b/src/eepp/maps/mapeditor/mapobjectproperties.cpp index c92cc78b0..d76c0e86b 100644 --- a/src/eepp/maps/mapeditor/mapobjectproperties.cpp +++ b/src/eepp/maps/mapeditor/mapobjectproperties.cpp @@ -7,7 +7,7 @@ namespace EE { namespace Maps { namespace Private { static UITextView* createTextBox( const String& Text = "", Node* Parent = NULL, const Sizef& Size = Sizef(), const Vector2f& Pos = Vector2f(), - const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, + const Uint32& Flags = UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, const Uint32& fontStyle = Text::Regular ) { UITextView* Ctrl = UITextView::New(); Ctrl->setFontStyle( fontStyle ); @@ -50,7 +50,7 @@ MapObjectProperties::MapObjectProperties( GameObjectObject* Obj ) : UITextView* Txt = createTextBox( "Object name:", mUIWindow->getContainer(), Sizef(), Vector2f( 50, InitialY ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIInput = UITextInput::New(); mUIInput->setParent( mUIWindow->getContainer() ) ->setSize( 120, 0 ) @@ -62,7 +62,7 @@ MapObjectProperties::MapObjectProperties( GameObjectObject* Obj ) : UITextView* Txt2 = createTextBox( "Object type:", mUIWindow->getContainer(), Sizef(), Vector2f( 50 + 192, InitialY ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIInput2 = UITextInput::New(); mUIInput2->setParent( mUIWindow->getContainer() ) ->setSize( 120, 0 ) @@ -73,7 +73,7 @@ MapObjectProperties::MapObjectProperties( GameObjectObject* Obj ) : mUIInput2->addEventListener( Event::OnPressEnter, cb::Make1( this, &MapObjectProperties::onOKClick ) ); - Uint32 TxtBoxFlags = UI_CONTROL_DEFAULT_FLAGS | UI_HALIGN_CENTER | UI_VALIGN_CENTER; + Uint32 TxtBoxFlags = UI_NODE_DEFAULT_FLAGS | UI_HALIGN_CENTER | UI_VALIGN_CENTER; createTextBox( "Property Name", mUIWindow->getContainer(), Sizef( 192, 24 ), Vector2f( 50, mUIInput->getPosition().y + mUIInput->getSize().getHeight() + 12 ), TxtBoxFlags, Text::Shadow ); diff --git a/src/eepp/maps/mapeditor/tilemapproperties.cpp b/src/eepp/maps/mapeditor/tilemapproperties.cpp index c33be5be8..4b91e5ac5 100644 --- a/src/eepp/maps/mapeditor/tilemapproperties.cpp +++ b/src/eepp/maps/mapeditor/tilemapproperties.cpp @@ -7,7 +7,7 @@ namespace EE { namespace Maps { namespace Private { static UITextView* createTextBox( const String& Text = "", Node* Parent = NULL, const Sizef& Size = Sizef(), const Vector2f& Pos = Vector2f(), - const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, + const Uint32& Flags = UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, const Uint32& fontStyle = Text::Regular ) { UITextView* Ctrl = UITextView::New(); Ctrl->setFontStyle( fontStyle ); @@ -52,7 +52,7 @@ TileMapProperties::TileMapProperties( TileMap* Map ) : UITextView* Txt = createTextBox( "Map Base Color:", mUIWindow->getContainer(), Sizef(), Vector2f( 50, 16 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIBaseColor = UIWidget::New(); mUIBaseColor->setFlags( UI_FILL_BACKGROUND | UI_BORDER ); @@ -67,7 +67,7 @@ TileMapProperties::TileMapProperties( TileMap* Map ) : "Red Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIBaseColor->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIRedSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIRedSlider->setParent( mUIWindow->getContainer() ) ->setSize( 255, 20 ) @@ -82,13 +82,13 @@ TileMapProperties::TileMapProperties( TileMap* Map ) : String::toStr( (Uint32)mMap->getBaseColor().r ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIRedSlider->getPosition().x + mUIRedSlider->getSize().getWidth() + 4, mUIRedSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "Green Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIRedSlider->getPosition().y + mUIRedSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIGreenSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIGreenSlider->setParent( mUIWindow->getContainer() ) @@ -103,13 +103,13 @@ TileMapProperties::TileMapProperties( TileMap* Map ) : String::toStr( (Uint32)mMap->getBaseColor().g ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIGreenSlider->getPosition().x + mUIGreenSlider->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "Blue Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y + mUIGreenSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIBlueSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIBlueSlider->setParent( mUIWindow->getContainer() ) ->setSize( 255, 20 ) @@ -123,10 +123,10 @@ TileMapProperties::TileMapProperties( TileMap* Map ) : String::toStr( (Uint32)mMap->getBaseColor().b ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIBlueSlider->getPosition().x + mUIBlueSlider->getSize().getWidth() + 4, mUIBlueSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); } - Uint32 TxtBoxFlags = UI_CONTROL_DEFAULT_FLAGS | UI_HALIGN_CENTER | UI_VALIGN_CENTER; + Uint32 TxtBoxFlags = UI_NODE_DEFAULT_FLAGS | UI_HALIGN_CENTER | UI_VALIGN_CENTER; UITextView* TxtBox = createTextBox( "Property Name", mUIWindow->getContainer(), Sizef( 192, 24 ), Vector2f( 50, 10 + DiffIfLights ), TxtBoxFlags, Text::Shadow ); diff --git a/src/eepp/maps/mapeditor/uimap.cpp b/src/eepp/maps/mapeditor/uimap.cpp index 90d458cf2..0639fba97 100644 --- a/src/eepp/maps/mapeditor/uimap.cpp +++ b/src/eepp/maps/mapeditor/uimap.cpp @@ -59,7 +59,7 @@ UIMap::~UIMap() { eeSAFE_DELETE( mMap ); } -Uint32 UIMap::onDrag( const Vector2f& Pos, const Uint32& ) { +Uint32 UIMap::onDrag( const Vector2f& Pos, const Uint32&, const Sizef& ) { if ( ( EDITING_OBJECT == mEditingMode && NULL != mSelObj ) || ( EDITING_LIGHT == mEditingMode && NULL != mSelLight ) ) { diff --git a/src/eepp/maps/mapeditor/uimap.hpp b/src/eepp/maps/mapeditor/uimap.hpp index 08a059f05..7115cc0dc 100644 --- a/src/eepp/maps/mapeditor/uimap.hpp +++ b/src/eepp/maps/mapeditor/uimap.hpp @@ -141,7 +141,7 @@ class EE_API UIMap : public UIWindow { virtual void onAlphaChange(); - virtual Uint32 onDrag( const Vector2f& Pos, const Uint32& flags ); + virtual Uint32 onDrag( const Vector2f& Pos, const Uint32& flags, const Sizef& dragDiff ); void objItemClick( const Event* Event ); diff --git a/src/eepp/maps/mapeditor/uimapnew.cpp b/src/eepp/maps/mapeditor/uimapnew.cpp index 54de93d4d..8a04af74b 100644 --- a/src/eepp/maps/mapeditor/uimapnew.cpp +++ b/src/eepp/maps/mapeditor/uimapnew.cpp @@ -7,7 +7,7 @@ namespace EE { namespace Maps { namespace Private { static UITextView* createTextBox( const String& Text = "", Node* Parent = NULL, const Sizef& Size = Sizef(), const Vector2f& Pos = Vector2f(), - const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, + const Uint32& Flags = UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, const Uint32& fontStyle = Text::Regular ) { UITextView* Ctrl = UITextView::New(); Ctrl->setFontStyle( fontStyle ); @@ -55,12 +55,12 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) UITextView* Txt = createTextBox( "Map Size", mUIWindow->getContainer(), Sizef(), Vector2f( 16, InitialY ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "Width:", mUIWindow->getContainer(), Sizef( 46, 24 ), Vector2f( Txt->getPosition().x + DistFromTitle, Txt->getPosition().y + DistFromTitle ), - UI_CONTROL_DEFAULT_FLAGS, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS, Text::Shadow ); mUIMapWidth = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); mUIMapWidth->setParent( mUIWindow->getContainer() ) @@ -75,7 +75,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Txt = createTextBox( "Height:", mUIWindow->getContainer(), Sizef( 46, 24 ), Vector2f( Txt->getPosition().x, Txt->getPosition().y + Txt->getSize().getHeight() + 8 ), - UI_CONTROL_DEFAULT_FLAGS, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS, Text::Shadow ); mUIMapHeight = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); mUIMapHeight->setParent( mUIWindow->getContainer() ) @@ -89,12 +89,12 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Txt = createTextBox( "Tile Size", mUIWindow->getContainer(), Sizef(), Vector2f( mUIWindow->getContainer()->getSize().getWidth() / 2, InitialY ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); Txt = createTextBox( "Width:", mUIWindow->getContainer(), Sizef( 46, 24 ), Vector2f( Txt->getPosition().x + DistFromTitle, Txt->getPosition().y + DistFromTitle ), - UI_CONTROL_DEFAULT_FLAGS, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS, Text::Shadow ); mUIMapTWidth = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 32 ); mUIMapTWidth->setParent( mUIWindow->getContainer() ) @@ -109,7 +109,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Txt = createTextBox( "Height:", mUIWindow->getContainer(), Sizef( 46, 24 ), Vector2f( Txt->getPosition().x, Txt->getPosition().y + Txt->getSize().getHeight() + 8 ), - UI_CONTROL_DEFAULT_FLAGS, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS, Text::Shadow ); mUIMapTHeight = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 32 ); mUIMapTHeight->setParent( mUIWindow->getContainer() ) @@ -124,7 +124,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Txt = createTextBox( "Max Layers", mUIWindow->getContainer(), Sizef(), Vector2f( 16, mUIMapTHeight->getPosition().y + mUIMapTHeight->getSize().getHeight() + 8 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIMapMaxLayers = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 8 ); mUIMapMaxLayers->setParent( mUIWindow->getContainer() ) @@ -136,7 +136,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) "Map Flags:", mUIWindow->getContainer(), Sizef(), Vector2f( Txt->getPosition().x, mUIMapMaxLayers->getPosition().y + mUIMapMaxLayers->getSize().getHeight() + 8 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUILightsEnabled = UICheckBox::New(); mUILightsEnabled->setFlags( UI_AUTO_SIZE ) @@ -191,7 +191,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) createTextBox( "Map Base Color:", mUIWindow->getContainer(), Sizef(), Vector2f( Txt->getPosition().x, mUIClipArea->getPosition().y + mUIClipArea->getSize().getHeight() + 8 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIBaseColor = UIWidget::New(); mUIBaseColor->setFlags( UI_FILL_BACKGROUND | UI_BORDER ); @@ -206,7 +206,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) "Red Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIBaseColor->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIRedSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIRedSlider->setParent( mUIWindow->getContainer() ) @@ -222,7 +222,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) String::toStr( 255 ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIRedSlider->getPosition().x + mUIRedSlider->getSize().getWidth() + 4, mUIRedSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); if ( ResizeMap ) { mUIRedSlider->setValue( mUIMap->Map()->getBaseColor().r ); @@ -232,7 +232,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) "Green Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIRedSlider->getPosition().y + mUIRedSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIGreenSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIGreenSlider->setParent( mUIWindow->getContainer() ) @@ -247,7 +247,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) String::toStr( 255 ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIGreenSlider->getPosition().x + mUIGreenSlider->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); if ( ResizeMap ) { mUIGreenSlider->setValue( mUIMap->Map()->getBaseColor().g ); @@ -257,7 +257,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) "Blue Color:", mUIWindow->getContainer(), Sizef(), Vector2f( mUIBaseColor->getPosition().x + mUIBaseColor->getSize().getWidth() + 4, mUIGreenSlider->getPosition().y + mUIGreenSlider->getSize().getHeight() + 4 ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); mUIBlueSlider = UISlider::New()->setOrientation( UIOrientation::Horizontal ); mUIBlueSlider->setParent( mUIWindow->getContainer() ) @@ -272,7 +272,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) String::toStr( 255 ), mUIWindow->getContainer(), Sizef(), Vector2f( mUIBlueSlider->getPosition().x + mUIBlueSlider->getSize().getWidth() + 4, mUIBlueSlider->getPosition().y ), - UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); + UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); if ( ResizeMap ) { mUIBlueSlider->setValue( mUIMap->Map()->getBaseColor().b ); diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index e1359b38d..7c3a74b2a 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -361,6 +361,9 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "border-bottom-left-radius", "0" ).setType( PropertyType::RadiusLength ); registerProperty( "border-bottom-right-radius", "0" ).setType( PropertyType::RadiusLength ); + registerProperty( "tabbar-hide-on-single-tab", "false" ); + registerProperty( "tabbar-allow-rearrange", "false" ); + // Shorthands registerShorthand( "margin", {"margin-top", "margin-right", "margin-bottom", "margin-left"}, "box" ); diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp index e346152df..fe3337c6a 100644 --- a/src/eepp/ui/uinode.cpp +++ b/src/eepp/ui/uinode.cpp @@ -32,7 +32,7 @@ UINode* UINode::New() { UINode::UINode() : Node(), - mFlags( UI_CONTROL_DEFAULT_FLAGS ), + mFlags( UI_NODE_DEFAULT_FLAGS ), mState( UIState::StateFlagNormal ), mSkinState( NULL ), mBackground( NULL ), @@ -437,19 +437,17 @@ Uint32 UINode::onCalculateDrag( const Vector2f& position, const Uint32& flags ) return 1; } - Vector2f Pos( eefloor( position.x ), eefloor( position.y ) ); - - if ( mDragPoint != Pos && ( std::abs( mDragPoint.x - Pos.x ) > 1.f || - std::abs( mDragPoint.y - Pos.y ) > 1.f ) ) { - if ( onDrag( Pos, flags ) ) { - Sizef dragDiff; - - dragDiff.x = ( Float )( mDragPoint.x - Pos.x ); - dragDiff.y = ( Float )( mDragPoint.y - Pos.y ); + Vector2f pos( eefloor( position.x ), eefloor( position.y ) ); + if ( mDragPoint != pos && ( std::abs( mDragPoint.x - pos.x ) > 1.f || + std::abs( mDragPoint.y - pos.y ) > 1.f ) ) { + Sizef dragDiff; + dragDiff.x = ( mFlags & UI_DRAG_HORIZONTAL ) ? ( Float )( mDragPoint.x - pos.x ) : 0; + dragDiff.y = ( mFlags & UI_DRAG_VERTICAL ) ? ( Float )( mDragPoint.y - pos.y ) : 0; + if ( onDrag( pos, flags, dragDiff ) ) { setPixelsPosition( mPosition - dragDiff ); - mDragPoint = Pos; + mDragPoint = pos; onPositionChange(); @@ -1016,7 +1014,7 @@ void UINode::onThemeLoaded() { invalidateDraw(); } -void UINode::onChildCountChange( Node* child, const bool& removed ) { +void UINode::onChildCountChange( Node*, const bool& ) { invalidateDraw(); } @@ -1072,7 +1070,7 @@ void UINode::setDragPoint( const Vector2f& Point ) { mDragPoint = Point; } -Uint32 UINode::onDrag( const Vector2f&, const Uint32& ) { +Uint32 UINode::onDrag( const Vector2f&, const Uint32&, const Sizef& ) { return 1; } diff --git a/src/eepp/ui/uipushbutton.cpp b/src/eepp/ui/uipushbutton.cpp index b96d69206..0ee67d8a5 100644 --- a/src/eepp/ui/uipushbutton.cpp +++ b/src/eepp/ui/uipushbutton.cpp @@ -23,7 +23,7 @@ UIPushButton::UIPushButton( const std::string& tag ) : ->setVisible( true ) ->setEnabled( false ); - auto cb = [&]( const Event* event ) { + auto cb = [&]( const Event* ) { onSizeChange(); notifyLayoutAttrChange(); }; @@ -41,6 +41,7 @@ UIPushButton::UIPushButton( const std::string& tag ) : mTextBox->addEventListener( Event::OnFontChanged, cb ); mTextBox->addEventListener( Event::OnFontStyleChanged, cb ); mTextBox->addEventListener( Event::OnTextChanged, cb ); + mTextBox->addEventListener( Event::OnVisibleChange, cb ); if ( NULL != getExtraInnerWidget() ) { getExtraInnerWidget()->addEventListener( Event::OnPaddingChange, cb ); @@ -140,11 +141,12 @@ void UIPushButton::onSizeChange() { PixelDensity::dpToPxI( mIcon->getLayoutMargin().Left + mIcon->getLayoutMargin().Right ) : 0; - Float eWidth = NULL != eWidget && eWidget->getPixelsSize().getWidth() > 0 - ? eWidget->getPixelsSize().getWidth() + - PixelDensity::dpToPxI( eWidget->getLayoutMargin().Left + - eWidget->getLayoutMargin().Right ) - : 0; + Float eWidth = + NULL != eWidget && eWidget->isVisible() && eWidget->getPixelsSize().getWidth() > 0 + ? eWidget->getPixelsSize().getWidth() + + PixelDensity::dpToPxI( eWidget->getLayoutMargin().Left + + eWidget->getLayoutMargin().Right ) + : 0; Float textBoxWidth = mTextBox->getPixelsSize().getWidth(); Float totalWidth = textBoxWidth + iconWidth + eWidth; @@ -155,14 +157,14 @@ void UIPushButton::onSizeChange() { position.y = eefloor( ( mSize.getHeight() - mTextBox->getPixelsSize().getHeight() ) * 0.5f ); ePos.y = - NULL != eWidget + NULL != eWidget && eWidget->isVisible() ? eefloor( ( mSize.getHeight() - eWidget->getPixelsSize().getHeight() ) * 0.5f ) : 0; break; case UI_VALIGN_BOTTOM: iconPos.y = mSize.y - mIcon->getPixelsSize().getHeight() - autoPadding.Bottom; position.y = mSize.y - mTextBox->getPixelsSize().getHeight() - autoPadding.Bottom; - ePos.y = NULL != eWidget + ePos.y = NULL != eWidget && eWidget->isVisible() ? mSize.y - eWidget->getPixelsSize().getHeight() - autoPadding.Bottom : 0; break; @@ -178,7 +180,7 @@ void UIPushButton::onSizeChange() { position.x = mSize.getWidth() - autoPadding.Right; ePos.x = position.x; - if ( NULL != eWidget ) { + if ( NULL != eWidget && eWidget->isVisible() ) { ePos.x = position.x - PixelDensity::dpToPx( eWidget->getLayoutMargin().Right ) - eWidget->getPixelsSize().getWidth(); position.x = ePos.x - PixelDensity::dpToPx( eWidget->getLayoutMargin().Left ); @@ -194,7 +196,7 @@ void UIPushButton::onSizeChange() { iconPos.x = ( mSize.getWidth() - totalWidth ) / 2 + PixelDensity::dpToPxI( mIcon->getLayoutMargin().Left ); - if ( NULL != eWidget ) { + if ( NULL != eWidget && eWidget->isVisible() ) { ePos.x = position.x + textBoxWidth + PixelDensity::dpToPx( eWidget->getLayoutMargin().Left ); } @@ -203,7 +205,7 @@ void UIPushButton::onSizeChange() { position.x = autoPadding.Left + iconWidth; iconPos.x = autoPadding.Left + PixelDensity::dpToPxI( mIcon->getLayoutMargin().Left ); - if ( NULL != eWidget ) { + if ( NULL != eWidget && eWidget->isVisible() ) { ePos.x = position.x + textBoxWidth + PixelDensity::dpToPx( eWidget->getLayoutMargin().Left ); } @@ -212,7 +214,7 @@ void UIPushButton::onSizeChange() { mTextBox->setPixelsPosition( position ); mIcon->setPixelsPosition( iconPos ); - if ( NULL != eWidget ) { + if ( NULL != eWidget && eWidget->isVisible() ) { eWidget->setPixelsPosition( ePos ); } } diff --git a/src/eepp/ui/uisplitter.cpp b/src/eepp/ui/uisplitter.cpp index 85787274f..efb90e08a 100644 --- a/src/eepp/ui/uisplitter.cpp +++ b/src/eepp/ui/uisplitter.cpp @@ -4,57 +4,6 @@ namespace EE { namespace UI { -class UISplitterSeparator : public UIWidget { - public: - static UISplitterSeparator* NewWithTag( const std::string& tag, UISplitter* parent ) { - return eeNew( UISplitterSeparator, ( tag, parent ) ); - } - - UISplitterSeparator( const std::string& tagname, UISplitter* parent ) : - UIWidget( tagname ), mContainer( parent ) { - setDragEnabled( true ); - } - - protected: - UISplitter* mContainer; - - Uint32 onCalculateDrag( const Vector2f& position, const Uint32& flags ) { - if ( isDragging() && !( flags /*press trigger*/ & EE_BUTTON_LMASK ) ) { - setDragging( false ); - getUISceneNode()->getEventDispatcher()->setNodeDragging( NULL ); - return 1; - } - Vector2f pos( eefloor( position.x ), eefloor( position.y ) ); - if ( mDragPoint != pos && ( std::abs( mDragPoint.x - pos.x ) > 1.f || - std::abs( mDragPoint.y - pos.y ) > 1.f ) ) { - if ( onDrag( pos, flags ) ) { - Sizef dragDiff; - dragDiff.x = ( Float )( mDragPoint.x - pos.x ); - dragDiff.y = ( Float )( mDragPoint.y - pos.y ); - if ( mContainer->getOrientation() == UIOrientation::Horizontal ) { - setPixelsPosition( mPosition.x - dragDiff.x, mPosition.y ); - } else { - setPixelsPosition( mPosition.x, mPosition.y - dragDiff.y ); - } - mDragPoint = pos; - onPositionChange(); - getUISceneNode()->getEventDispatcher()->setNodeDragging( this ); - } - } - return 1; - } - - Uint32 onDragStart( const Vector2i& pos, const Uint32& flags ) { - pushState( UIState::StateSelected ); - return UIWidget::onDragStart( pos, flags ); - } - - Uint32 onDragStop( const Vector2i& pos, const Uint32& flags ) { - popState( UIState::StateSelected ); - return UIWidget::onDragStop( pos, flags ); - } -}; - UISplitter* UISplitter::New() { return eeNew( UISplitter, () ); } @@ -68,7 +17,13 @@ UISplitter::UISplitter() : mFirstWidget( NULL ), mLastWidget( NULL ) { mFlags |= UI_OWNS_CHILDS_POSITION; - mSplitter = UISplitterSeparator::NewWithTag( "splitter::separator", this ); + mSplitter = UIWidget::NewWithTag( "splitter::separator" ); + mSplitter->setDragEnabled( true ); + mSplitter->addEventListener( Event::OnDragStart, [&]( const Event* ) { + mSplitter->pushState( UIState::StateSelected ); + } ); + mSplitter->addEventListener( + Event::OnDragStop, [&]( const Event* ) { mSplitter->popState( UIState::StateSelected ); } ); mSplitter->setParent( this ); mSplitter->setMinWidth( 4 ); mSplitter->setMinHeight( 4 ); @@ -83,6 +38,9 @@ UISplitter::UISplitter() : if ( mSplitter->isDragging() && !mDirtyLayout ) updateFromDrag(); } ); + + updateSplitterDragFlags(); + applyDefaultTheme(); } @@ -103,6 +61,7 @@ const UIOrientation& UISplitter::getOrientation() const { void UISplitter::setOrientation( const UIOrientation& orientation ) { if ( orientation != mOrientation ) { mOrientation = orientation; + updateSplitterDragFlags(); setLayoutDirty(); } } @@ -231,10 +190,11 @@ void UISplitter::updateFromDrag() { Float lMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getHeight() : 0.f; - if ( mSplitter->getPosition().y > mDpSize.getHeight() - mPadding.Bottom - lMinSize ) { + if ( mSplitter->getPosition().y + mSplitter->getSize().getHeight() > + mDpSize.getHeight() - mPadding.Bottom - lMinSize ) { mSplitter->setPosition( mSplitter->getPosition().x, mDpSize.getHeight() - mPadding.Bottom - lMinSize - - +mSplitter->getSize().getHeight() ); + mSplitter->getSize().getHeight() ); } mSplitter->setPixelsSize( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, @@ -408,6 +368,13 @@ void UISplitter::updateLayout() { mDirtyLayout = false; } +void UISplitter::updateSplitterDragFlags() { + mSplitter->setFlags( getOrientation() == UIOrientation::Horizontal ? UI_DRAG_HORIZONTAL + : UI_DRAG_VERTICAL ); + mSplitter->unsetFlags( getOrientation() == UIOrientation::Horizontal ? UI_DRAG_VERTICAL + : UI_DRAG_HORIZONTAL ); +} + Uint32 UISplitter::onMessage( const NodeMessage* Msg ) { switch ( Msg->getMsg() ) { case NodeMessage::LayoutAttributeChange: { diff --git a/src/eepp/ui/uitab.cpp b/src/eepp/ui/uitab.cpp index 14402f1de..91f29b881 100644 --- a/src/eepp/ui/uitab.cpp +++ b/src/eepp/ui/uitab.cpp @@ -12,10 +12,15 @@ UITab* UITab::New() { UITab::UITab() : UISelectButton( "tab" ), mOwnedWidget( NULL ) { mTextBox->setElementTag( mTag + "::text" ); mIcon->setElementTag( mTag + "::icon" ); - applyDefaultTheme(); auto cb = [&]( const Event* ) { onSizeChange(); }; mTextBox->addEventListener( Event::OnSizeChange, cb ); mIcon->addEventListener( Event::OnSizeChange, cb ); + mCloseButton = UIWidget::NewWithTag( mTag + "::close" ); + mCloseButton->setParent( this ); + mCloseButton->setEnabled( false ); + mCloseButton->setVisible( false ); + applyDefaultTheme(); + unsetFlags( UI_DRAG_VERTICAL ); } UITab::~UITab() {} @@ -37,6 +42,44 @@ UITabWidget* UITab::getTabWidget() { return NULL; } +Uint32 UITab::onDrag( const Vector2f&, const Uint32&, const Sizef& dragDiff ) { + UITabWidget* tabW = getTabWidget(); + if ( !tabW ) + return 0; + Vector2f newPos( mPosition - dragDiff ); + if ( newPos.x < 0 || newPos.x + mSize.getWidth() > getParent()->getPixelsSize().getWidth() ) { + getUISceneNode()->getEventDispatcher()->setNodeDragging( this ); + return 0; + } + Uint32 index = tabW->getTabIndex( this ); + if ( index > 0 ) { + UITab* tab = tabW->getTab( index - 1 ); + if ( tab ) { + if ( newPos.x < tab->getPixelsPosition().x + tab->getPixelsSize().getWidth() * 0.5f ) { + tabW->swapTabs( this, tab ); + } + } + } + if ( index + 1 < tabW->getTabCount() ) { + UITab* tab = tabW->getTab( index + 1 ); + + if ( tab ) { + if ( newPos.x + mSize.getWidth() > + tab->getPixelsPosition().x + tab->getPixelsSize().getWidth() * 0.5f ) { + tabW->swapTabs( tab, this ); + } + } + } + return 1; +} + +Uint32 UITab::onDragStop( const Vector2i& position, const Uint32& flags ) { + UITabWidget* tabW = getTabWidget(); + if ( tabW ) + tabW->posTabs(); + return UISelectButton::onDragStop( position, flags ); +} + void UITab::onParentChange() { applyDefaultTheme(); UISelectButton::onParentChange(); @@ -49,6 +92,10 @@ void UITab::onSizeChange() { UISelectButton::onSizeChange(); } +UIWidget* UITab::getExtraInnerWidget() { + return mCloseButton; +} + void UITab::setTheme( UITheme* Theme ) { UIWidget::setTheme( Theme ); @@ -73,20 +120,6 @@ void UITab::setTheme( UITheme* Theme ) { onStateChange(); } -Uint32 UITab::onMouseClick( const Vector2i& Pos, const Uint32& Flags ) { - UISelectButton::onMouseClick( Pos, Flags ); - - UITabWidget* tTabW = getTabWidget(); - - if ( NULL != tTabW ) { - if ( Flags & EE_BUTTON_LMASK ) { - tTabW->setTabSelected( this ); - } - } - - return UISelectButton::onMouseClick( Pos, Flags ); -} - void UITab::onStateChange() { UISelectButton::onStateChange(); @@ -125,14 +158,24 @@ UIPushButton* UITab::setText( const String& text ) { } void UITab::onAutoSize() { - if ( mFlags & UI_AUTO_SIZE ) { - Float w = mTextBox->getSize().getWidth() + - ( NULL != mIcon ? mIcon->getSize().getWidth() + mIcon->getLayoutMargin().Left + - mIcon->getLayoutMargin().Right - : 0 ) + - getSkinSize().getWidth(); + UITabWidget* tTabW = getTabWidget(); - UITabWidget* tTabW = getTabWidget(); + if ( NULL != tTabW ) { + mCloseButton->setVisible( tTabW->getTabsClosable() ); + mCloseButton->setEnabled( tTabW->getTabsClosable() ); + } + + if ( mFlags & UI_AUTO_SIZE ) { + Float w = + mTextBox->getSize().getWidth() + + ( NULL != mIcon ? mIcon->getSize().getWidth() + mIcon->getLayoutMargin().Left + + mIcon->getLayoutMargin().Right + : 0 ) + + ( NULL != mCloseButton && mCloseButton->isVisible() + ? mCloseButton->getSize().getWidth() + mCloseButton->getLayoutMargin().Left + + mCloseButton->getLayoutMargin().Right + : 0 ) + + getSkinSize().getWidth(); if ( NULL != tTabW ) { w = eemax( w, tTabW->getMinTabWidth() ); @@ -184,28 +227,45 @@ bool UITab::applyProperty( const StyleSheetProperty& attribute ) { return true; } -Uint32 UITab::onMouseUp( const Vector2i& Pos, const Uint32& Flags ) { - if ( mEnabled && mVisible ) { - if ( NULL == mOwnedWidget && !mOwnedName.empty() ) { - setOwnedControl(); +Uint32 UITab::onMessage( const NodeMessage* message ) { + UITabWidget* tTabW = getTabWidget(); + if ( !tTabW || !mEnabled || !mVisible ) + return 1; + + if ( NULL == mOwnedWidget && !mOwnedName.empty() ) { + setOwnedControl(); + } + + Uint32 flags = message->getFlags(); + + switch ( message->getMsg() ) { + case NodeMessage::MouseDown: { + if ( flags & EE_BUTTON_LMASK && message->getSender() != mCloseButton ) { + tTabW->setTabSelected( this ); + } + break; } - - UITabWidget* tTabW = getTabWidget(); - - if ( NULL != tTabW ) { - if ( Flags & EE_BUTTONS_WUWD ) { - if ( Flags & EE_BUTTON_WUMASK ) { + case NodeMessage::MouseUp: { + if ( tTabW->getTabsClosable() && ( flags & EE_BUTTON_MMASK ) ) { + tTabW->tryCloseTab( this ); + } else if ( flags & EE_BUTTONS_WUWD ) { + if ( flags & EE_BUTTON_WUMASK ) { tTabW->selectPreviousTab(); - } else if ( Flags & EE_BUTTON_WDMASK ) { + } else if ( flags & EE_BUTTON_WDMASK ) { tTabW->selectNextTab(); } - } else if ( tTabW->getTabsClosable() && ( Flags & EE_BUTTON_MMASK ) ) { - tTabW->removeTab( this ); } + break; + } + case NodeMessage::Click: { + if ( flags & EE_BUTTON_LMASK && message->getSender() == mCloseButton ) { + tTabW->tryCloseTab( this ); + } + break; } } - return UISelectButton::onMouseUp( Pos, Flags ); + return 0; } void UITab::setOwnedControl() { @@ -225,7 +285,7 @@ void UITab::updateTab() { } else { UIPushButton::setText( mText ); } - + setDragEnabled( tTabW->getAllowRearrangeTabs() ); onAutoSize(); } } diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index 7cda247c2..8b978da47 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -19,7 +19,8 @@ UITabWidget::UITabWidget() : mTabBar( NULL ), mTabSelected( NULL ), mTabSelectedIndex( eeINDEX_NOT_FOUND ), - mHideWhenNotNeeded( false ) { + mHideTabBarOnSingleTab( false ), + mAllowRearrangeTabs( false ) { setHorizontalAlign( UI_HALIGN_CENTER ); mTabBar = UIWidget::NewWithTag( "tabwidget::tabbar" ); @@ -82,7 +83,7 @@ void UITabWidget::onThemeLoaded() { } void UITabWidget::setContainerSize() { - if ( getTabCount() < 2 && mHideWhenNotNeeded ) { + if ( getTabCount() < 2 && mHideTabBarOnSingleTab ) { mTabBar->setVisible( false ); mTabBar->setEnabled( false ); mCtrlContainer->setPosition( mPadding.Left, mPadding.Top ); @@ -146,6 +147,10 @@ std::string UITabWidget::getPropertyString( const PropertyDefinition* propertyDe return String::fromFloat( getTabSeparation(), "dp" ); case PropertyId::TabHeight: return String::fromFloat( getTabsHeight(), "dp" ); + case PropertyId::TabBarHideOnSingleTab: + return getHideTabBarOnSingleTab() ? "true" : "false"; + case PropertyId::TabBarAllowRearrange: + return getAllowRearrangeTabs() ? "true" : "false"; default: return UIWidget::getPropertyString( propertyDef, propertyIndex ); } @@ -159,7 +164,7 @@ void UITabWidget::invalidate( Node* invalidator ) { // Only invalidate if the invalidator is actually visible in the current active tab. if ( NULL != invalidator ) { if ( invalidator == mCtrlContainer || invalidator == mTabBar || - mTabBar->isChild( invalidator ) ) { + mTabBar->inParentTreeOf( invalidator ) ) { mNodeDrawInvalidator->invalidate( mCtrlContainer ); } else if ( invalidator->getParent() == mCtrlContainer ) { if ( invalidator->isVisible() ) { @@ -207,6 +212,12 @@ bool UITabWidget::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::TabHeight: setTabsHeight( attribute.asDpDimension( this ) ); break; + case PropertyId::TabBarHideOnSingleTab: + setHideTabBarOnSingleTab( attribute.asBool() ); + break; + case PropertyId::TabBarAllowRearrange: + setAllowRearrangeTabs( attribute.asBool() ); + break; default: return UIWidget::applyProperty( attribute ); } @@ -268,6 +279,7 @@ bool UITabWidget::getTabsClosable() const { void UITabWidget::setTabsClosable( bool tabsClosable ) { if ( mStyleConfig.TabsClosable != tabsClosable ) { mStyleConfig.TabsClosable = tabsClosable; + updateTabs(); invalidateDraw(); } } @@ -337,7 +349,9 @@ void UITabWidget::posTabs() { break; } - mTabs[i]->setPixelsPosition( alignOffset + x, y ); + if ( !mTabs[i]->isDragging() ) { + mTabs[i]->setPixelsPosition( alignOffset + x, y ); + } x += mTabs[i]->getPixelsSize().getWidth() + mStyleConfig.TabSeparation; } @@ -577,17 +591,36 @@ UITab* UITabWidget::setTabSelected( const Uint32& tabIndex ) { return NULL; } -const bool& UITabWidget::getHideWhenNotNeeded() const { - return mHideWhenNotNeeded; +const bool& UITabWidget::getHideTabBarOnSingleTab() const { + return mHideTabBarOnSingleTab; } -void UITabWidget::setHideWhenNotNeeded( const bool& hideWhenNotNeeded ) { - if ( mHideWhenNotNeeded != hideWhenNotNeeded ) { - mHideWhenNotNeeded = hideWhenNotNeeded; +void UITabWidget::setHideTabBarOnSingleTab( const bool& hideTabBarOnSingleTab ) { + if ( mHideTabBarOnSingleTab != hideTabBarOnSingleTab ) { + mHideTabBarOnSingleTab = hideTabBarOnSingleTab; setContainerSize(); } } +const UITabWidget::TabTryCloseCallback& UITabWidget::getTabTryCloseCallback() const { + return mTabTryCloseCallback; +} + +void UITabWidget::setTabTryCloseCallback( const TabTryCloseCallback& tabTryCloseCallback ) { + mTabTryCloseCallback = tabTryCloseCallback; +} + +const bool& UITabWidget::getAllowRearrangeTabs() const { + return mAllowRearrangeTabs; +} + +void UITabWidget::setAllowRearrangeTabs( bool allowRearrangeTabs ) { + if ( allowRearrangeTabs != mAllowRearrangeTabs ) { + mAllowRearrangeTabs = allowRearrangeTabs; + updateTabs(); + } +} + void UITabWidget::refreshOwnedWidget( UITab* tab ) { if ( NULL != tab && NULL != tab->getOwnedWidget() ) { tab->getOwnedWidget()->setParent( mCtrlContainer ); @@ -605,6 +638,22 @@ void UITabWidget::refreshOwnedWidget( UITab* tab ) { } } +void UITabWidget::tryCloseTab( UITab* tab ) { + if ( mTabTryCloseCallback && !mTabTryCloseCallback( tab ) ) + return; + removeTab( tab ); +} + +void UITabWidget::swapTabs( UITab* left, UITab* right ) { + Uint32 leftIndex = getTabIndex( left ); + Uint32 rightIndex = getTabIndex( right ); + if ( leftIndex != eeINDEX_NOT_FOUND && rightIndex != eeINDEX_NOT_FOUND ) { + mTabs[leftIndex] = right; + mTabs[rightIndex] = left; + posTabs(); + } +} + void UITabWidget::selectPreviousTab() { if ( eeINDEX_NOT_FOUND != mTabSelectedIndex && mTabSelectedIndex > 0 ) { setTabSelected( getTab( mTabSelectedIndex - 1 ) ); diff --git a/src/eepp/ui/uitooltip.cpp b/src/eepp/ui/uitooltip.cpp index 4e0694755..a41a6bca9 100644 --- a/src/eepp/ui/uitooltip.cpp +++ b/src/eepp/ui/uitooltip.cpp @@ -15,7 +15,7 @@ UITooltip* UITooltip::New() { UITooltip::UITooltip() : UIWidget( "tooltip" ), mAlignOffset( 0.f, 0.f ), mTooltipTime( Time::Zero ), mTooltipOf() { - setFlags( UI_CONTROL_DEFAULT_FLAGS_CENTERED | UI_AUTO_PADDING | UI_AUTO_SIZE ); + setFlags( UI_NODE_DEFAULT_FLAGS_CENTERED | UI_AUTO_PADDING | UI_AUTO_SIZE ); mTextCache = Text::New(); mEnabled = false; diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index 578afceff..c1610b93d 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -155,7 +155,7 @@ void UIWindow::updateWinFlags() { mWindowDecoration->writeNodeFlag( NODE_FLAG_OWNED_BY_NODE, 1 ); } - auto cb = [&]( const Event* event ) { onSizeChange(); }; + auto cb = [&]( const Event* ) { onSizeChange(); }; mWindowDecoration->setParent( this ); mWindowDecoration->setVisible( true ); diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 5bc6c45fc..293cb4050 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -24,13 +24,13 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) { } } -bool App::onTabCloseRequestCallback( EE::Window::Window* ) { - if ( NULL != mCurEditor && mCurEditor->isDirty() ) { +bool App::tryTabClose( UICodeEditor* editor ) { + if ( NULL != editor && editor->isDirty() ) { mMsgBox = UIMessageBox::New( UIMessageBox::OK_CANCEL, "Do you really want to close this tab?\nAll changes will be lost." ); mMsgBox->addEventListener( Event::MsgBoxConfirmClick, - [&]( const Event* ) { closeCurrrentTab(); } ); + [&, editor]( const Event* ) { closeEditorTab( editor ); } ); mMsgBox->addEventListener( Event::OnClose, [&]( const Event* ) { mMsgBox = NULL; if ( mCurEditor ) @@ -41,17 +41,19 @@ bool App::onTabCloseRequestCallback( EE::Window::Window* ) { mMsgBox->show(); return false; } else { + closeEditorTab( editor ); return true; } } -void App::closeCurrrentTab() { - if ( mCurEditor ) { - UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); +void App::closeEditorTab( UICodeEditor* editor ) { + if ( editor ) { + UITabWidget* tabWidget = tabWidgetFromEditor( editor ); if ( tabWidget ) { - if ( !( mCurEditor->getDocument().isEmpty() && - !tabWidget->getParent()->isType( UI_TYPE_SPLITTER ) ) ) { - tabWidget->removeTab( (UITab*)mCurEditor->getData() ); + if ( !( editor->getDocument().isEmpty() && + !tabWidget->getParent()->isType( UI_TYPE_SPLITTER ) && + tabWidget->getTabCount() == 1 ) ) { + tabWidget->removeTab( (UITab*)editor->getData() ); } } } @@ -117,11 +119,7 @@ UICodeEditor* App::createCodeEditor() { [&]() { mWindow->toggleFullscreen(); } ); codeEditor->getDocument().setCommand( "open-file", [&] { openFileDialog(); } ); codeEditor->getDocument().setCommand( "console-toggle", [&] { mConsole->toggle(); } ); - codeEditor->getDocument().setCommand( "close-doc", [&] { - if ( onTabCloseRequestCallback( mWindow ) ) { - closeCurrrentTab(); - } - } ); + codeEditor->getDocument().setCommand( "close-doc", [&] { tryTabClose( mCurEditor ); } ); codeEditor->getDocument().setCommand( "create-new", [&] { auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) ); d.first->getTabWidget()->setTabSelected( d.first ); @@ -303,13 +301,18 @@ UITabWidget* App::createEditorWithTabWidget( Node* parent ) { tabWidget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); tabWidget->setParent( parent ); tabWidget->setTabsClosable( true ); - tabWidget->setHideWhenNotNeeded( true ); + tabWidget->setHideTabBarOnSingleTab( true ); + tabWidget->setAllowRearrangeTabs( true ); tabWidget->addEventListener( Event::OnTabSelected, [&]( const Event* event ) { UITabWidget* tabWidget = event->getNode()->asType(); mCurEditor = tabWidget->getSelectedTab()->getOwnedWidget()->asType(); updateEditorTitle( mCurEditor ); mCurEditor->setFocus(); } ); + tabWidget->setTabTryCloseCallback( [&]( UITab* tab ) -> bool { + tryTabClose( tab->getOwnedWidget()->asType() ); + return false; + } ); createCodeEditorInTabWidget( tabWidget ); return tabWidget; } @@ -502,12 +505,14 @@ void App::init( const std::string& file ) { mUISceneNode = UISceneNode::New(); - mUISceneNode->getUIThemeManager()->setDefaultFont( FontTrueType::New( - "NotoSans-Regular", resPath + "assets/fonts/NotoSans-Regular.ttf" ) ); + Font* font = + FontTrueType::New( "NotoSans-Regular", resPath + "assets/fonts/NotoSans-Regular.ttf" ); Font* fontMono = FontTrueType::New( "monospace", resPath + "assets/fonts/DejaVuSansMono.ttf" ); + mUISceneNode->getUIThemeManager()->setDefaultFont( font ); + SceneManager::instance()->add( mUISceneNode ); StyleSheetParser cssParser; diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp index f2ee2ac75..a3ca6e3c9 100644 --- a/src/tools/codeeditor/codeeditor.hpp +++ b/src/tools/codeeditor/codeeditor.hpp @@ -57,11 +57,11 @@ class App { std::string titleFromEditor( UICodeEditor* editor ); - bool onTabCloseRequestCallback( EE::Window::Window* ); + bool tryTabClose( UICodeEditor* editor ); bool onCloseRequestCallback( EE::Window::Window* ); - void closeCurrrentTab(); + void closeEditorTab( UICodeEditor* editor ); void onTabClosed( const TabEvent* tabEvent ); }; diff --git a/src/tools/uieditor/uieditor.cpp b/src/tools/uieditor/uieditor.cpp index 4b11baf64..6d036d785 100644 --- a/src/tools/uieditor/uieditor.cpp +++ b/src/tools/uieditor/uieditor.cpp @@ -1038,7 +1038,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { createAppMenu(); - UIWindow::StyleConfig winStyle( UI_CONTROL_DEFAULT_FLAGS | UI_WIN_NO_DECORATION ); + UIWindow::StyleConfig winStyle( UI_NODE_DEFAULT_FLAGS | UI_WIN_NO_DECORATION ); uiContainer = UIWindow::NewOpt( UIWindow::SIMPLE_LAYOUT, winStyle ); uiContainer->setId( "appContainer" )->setSize( uiSceneNode->getSize() );