diff --git a/bin/assets/layouts/test.css b/bin/assets/layouts/test.css index 64e1ce6bd..610790858 100644 --- a/bin/assets/layouts/test.css +++ b/bin/assets/layouts/test.css @@ -75,8 +75,7 @@ Tooltip { margin-top: 0dp; border-width: 2dp; border-color: #66666666; - background-color: #33FF3333; - background-image: linear-gradient( #8c8886, #585857 ); + background-color: #33FF3310; border-radius: 12; font-size: 24dp; padding: 12dp; @@ -86,7 +85,7 @@ Tooltip { #lvbox > #tpad:hover { scale: 1.1; rotation: -3; - background-color: #FF333333; + background-color: #FF333310; border-color: #99999999; border-radius: 4; } diff --git a/include/eepp/graphics/drawable.hpp b/include/eepp/graphics/drawable.hpp index a7c39c6e1..3bfa1b743 100644 --- a/include/eepp/graphics/drawable.hpp +++ b/include/eepp/graphics/drawable.hpp @@ -25,6 +25,8 @@ class EE_API Drawable { NINEPATCH, STATELIST, SKIN, + UINODEDRAWABLE, + UINODEDRAWABLE_LAYERDRAWABLE, CUSTOM }; diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp index eebdd7634..d079388c1 100644 --- a/include/eepp/ui/uinode.hpp +++ b/include/eepp/ui/uinode.hpp @@ -22,6 +22,7 @@ using namespace EE::Scene; namespace EE { namespace UI { class UITheme; +class UINodeDrawable; class EE_API UINode : public Node { public: @@ -85,24 +86,32 @@ class EE_API UINode : public Node { UINode * setGravity( Uint32 hvalign ); - UISkin * setBackgroundFillEnabled( bool enabled ); + UINodeDrawable * setBackgroundFillEnabled( bool enabled ); - UINode * setBackgroundDrawable( Drawable * drawable , bool ownIt = false ); + UINode * setBackgroundDrawable( Drawable * drawable, bool ownIt = false, int index = 0 ); UINode * setBackgroundColor( const Color& color ); + UINode * setBackgroundPosition( const std::string& positionEq, int index = 0 ); + + UINode * setBackgroundRepeat( const std::string& repeatRule, int index = 0 ); + Color getBackgroundColor() const; UINode * setBorderRadius( const unsigned int& corners ); Uint32 getBorderRadius() const; - UISkin * setForegroundFillEnabled( bool enabled ); + UINodeDrawable * setForegroundFillEnabled( bool enabled ); - UINode * setForegroundDrawable( Drawable * drawable , bool ownIt = false ); + UINode * setForegroundDrawable( Drawable * drawable , bool ownIt = false, int index = 0 ); UINode * setForegroundColor( const Color& color ); + UINode * setForegroundPosition( const std::string& positionEq, int index = 0 ); + + UINode * setForegroundRepeat( const std::string& repeatRule, int index = 0 ) ; + Color getForegroundColor() const; UINode * setForegroundRadius( const unsigned int& corners ); @@ -127,9 +136,9 @@ class EE_API UINode : public Node { virtual UINode * resetFlags( Uint32 newFlags = 0 ); - UISkin * getBackground(); + UINodeDrawable * getBackground(); - UISkin * getForeground(); + UINodeDrawable* getForeground(); RectangleDrawable * getBorder(); @@ -188,8 +197,8 @@ class EE_API UINode : public Node { Uint32 mFlags; Uint32 mState; UISkinState * mSkinState; - UISkinState * mBackgroundState; - UISkinState * mForegroundState; + UINodeDrawable * mBackground; + UINodeDrawable * mForegroundState; RectangleDrawable * mBorder; Vector2f mDragPoint; Uint32 mDragButton; diff --git a/include/eepp/ui/uinodedrawable.hpp b/include/eepp/ui/uinodedrawable.hpp new file mode 100644 index 000000000..5cb4eddba --- /dev/null +++ b/include/eepp/ui/uinodedrawable.hpp @@ -0,0 +1,130 @@ +#ifndef EE_UI_UINODEDRAWABLE_HPP +#define EE_UI_UINODEDRAWABLE_HPP + +#include +#include +#include +#include + +using namespace EE::Graphics; + +namespace EE { namespace UI { + +class EE_API UINodeDrawable : public Drawable { + public: + enum Repeat { + RepeatXY, + RepeatX, + RepeatY, + NoRepeat + }; + + static Repeat repeatFromText( const std::string& text ); + + class EE_API LayerDrawable : public Drawable { + public: + static LayerDrawable * New( UINodeDrawable * container ); + + LayerDrawable( UINodeDrawable * container ); + + virtual ~LayerDrawable(); + + bool isStateful() { return false; } + + virtual void draw(); + + virtual void draw( const Vector2f& position ); + + virtual void draw( const Vector2f& position, const Sizef& size ); + + virtual Sizef getSize(); + + virtual void setSize( const Sizef& size ); + + Drawable* getDrawable() const; + + void setDrawable( Drawable* drawable, const bool& ownIt ); + + const Vector2f& getOffset() const; + + void setPositionEq( const std::string& offset ); + + const Repeat& getRepeat() const; + + void setRepeat( const Repeat& repeat ); + protected: + UINodeDrawable * mContainer; + Sizef mSize; + Vector2f mOffset; + std::string mPositionEq; + bool mNeedsUpdate; + bool mUpdatePosEq; + bool mOwnsDrawable; + Drawable * mDrawable; + Uint32 mResourceChangeCbId; + Repeat mRepeat; + + virtual void onPositionChange(); + + void update(); + }; + + static UINodeDrawable * New(); + + UINodeDrawable(); + + virtual ~UINodeDrawable(); + + virtual Sizef getSize(); + + virtual void setSize( const Sizef& size ); + + virtual void draw(); + + virtual void draw( const Vector2f& position ); + + virtual void draw( const Vector2f& position, const Sizef& size ); + + void draw( const Vector2f& position, const Sizef& size, const Uint32& alpha ); + + virtual bool isStateful() { return false; } + + void clearDrawables(); + + void setBorderRadius( const Uint32& corners ); + + Uint32 getBorderRadius() const; + + LayerDrawable * getLayer( int index ); + + void setDrawable( int index, Drawable * drawable, bool ownIt ); + + void setDrawablePosition( int index, const std::string& positionEq ); + + void setDrawableRepeat( int index, const std::string& repeatRule ); + + void setBackgroundColor( const Color& color ); + + Color getBackgroundColor() const; + + bool getClipEnabled() const; + + void setClipEnabled(bool clipEnabled); + protected: + RectangleDrawable mBackgroundColor; + std::map mGroup; + std::map mPosEq; + Sizef mSize; + bool mNeedsUpdate; + bool mClipEnabled; + + virtual void onPositionChange(); + + virtual void onSizeChange(); + + void update(); +}; + +}} + +#endif diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp index 977a4cbbe..6aceb8fe8 100644 --- a/include/eepp/ui/uiwidget.hpp +++ b/include/eepp/ui/uiwidget.hpp @@ -239,7 +239,7 @@ class EE_API UIWidget : public UINode, public CSS::StyleSheetElement { std::string getFlagsString() const; - bool drawablePropertySet( const std::string& propertyName, const std::string& value, std::function funcSet); + bool drawablePropertySet( const std::string& propertyName, const std::string& value, std::function funcSet); UIWidget * querySelector( const CSS::StyleSheetSelector& selector ); diff --git a/projects/linux/ee.files b/projects/linux/ee.files index d9df990f4..c8ce0036a 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -324,6 +324,7 @@ ../../include/eepp/ui/uimenusubmenu.hpp ../../include/eepp/ui/uimessagebox.hpp ../../include/eepp/ui/uinode.hpp +../../include/eepp/ui/uinodedrawable.hpp ../../include/eepp/ui/uipopupmenu.hpp ../../include/eepp/ui/uiprogressbar.hpp ../../include/eepp/ui/uipushbutton.hpp @@ -742,6 +743,7 @@ ../../src/eepp/ui/uimenusubmenu.cpp ../../src/eepp/ui/uimessagebox.cpp ../../src/eepp/ui/uinode.cpp +../../src/eepp/ui/uinodedrawable.cpp ../../src/eepp/ui/uipopupmenu.cpp ../../src/eepp/ui/uiprogressbar.cpp ../../src/eepp/ui/uipushbutton.cpp diff --git a/src/eepp/maps/mapeditor/mapeditor.cpp b/src/eepp/maps/mapeditor/mapeditor.cpp index ee5fb5a30..648763a1e 100644 --- a/src/eepp/maps/mapeditor/mapeditor.cpp +++ b/src/eepp/maps/mapeditor/mapeditor.cpp @@ -595,12 +595,12 @@ void MapEditor::onNewLight( const Event * Event ) { if ( MEvent->getFlags() & EE_BUTTON_LMASK ) { Vector2f Pos = mUIMap->Map()->getMouseMapPosf(); - mUIMap->addLight( eeNew( MapLight, ( mLightRadius->getValue(), Pos.x, Pos.y, mUIBaseColor->getBackground()->getColor().toRGB(), mLightTypeChk->isActive() ? LIGHT_ISOMETRIC : LIGHT_NORMAL ) ) ); + mUIMap->addLight( eeNew( MapLight, ( mLightRadius->getValue(), Pos.x, Pos.y, mUIBaseColor->getBackgroundColor().toRGB(), mLightTypeChk->isActive() ? LIGHT_ISOMETRIC : LIGHT_NORMAL ) ) ); } } void MapEditor::onRedChange( const Event * Event ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.r = (Uint8)mUIRedSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIRedTxt->setText( String::toStr( (Int32)mUIRedSlider->getValue() ) ); @@ -613,7 +613,7 @@ void MapEditor::onRedChange( const Event * Event ) { } void MapEditor::onGreenChange( const Event * Event ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.g = (Uint8)mUIGreenSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIGreenTxt->setText( String::toStr( (Uint32)mUIGreenSlider->getValue() ) ); @@ -626,7 +626,7 @@ void MapEditor::onGreenChange( const Event * Event ) { } void MapEditor::onBlueChange( const Event * Event ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.b = (Uint8)mUIBlueSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIBlueTxt->setText( String::toStr( (Uint32)mUIBlueSlider->getValue() ) ); diff --git a/src/eepp/maps/mapeditor/tilemapproperties.cpp b/src/eepp/maps/mapeditor/tilemapproperties.cpp index f582c76bf..ee4f55faa 100644 --- a/src/eepp/maps/mapeditor/tilemapproperties.cpp +++ b/src/eepp/maps/mapeditor/tilemapproperties.cpp @@ -140,7 +140,7 @@ TileMapProperties::~TileMapProperties() { } void TileMapProperties::onRedChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.r = (Uint8)mUIRedSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIRedTxt->setText( String::toStr( (Int32)mUIRedSlider->getValue() ) ); @@ -151,7 +151,7 @@ void TileMapProperties::onRedChange( const Event * ) { } void TileMapProperties::onGreenChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.g = (Uint8)mUIGreenSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIGreenTxt->setText( String::toStr( (Uint32)mUIGreenSlider->getValue() ) ); @@ -162,7 +162,7 @@ void TileMapProperties::onGreenChange( const Event * ) { } void TileMapProperties::onBlueChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.b = (Uint8)mUIBlueSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIBlueTxt->setText( String::toStr( (Uint32)mUIBlueSlider->getValue() ) ); diff --git a/src/eepp/maps/mapeditor/uimapnew.cpp b/src/eepp/maps/mapeditor/uimapnew.cpp index e1711bf2c..5480283b3 100644 --- a/src/eepp/maps/mapeditor/uimapnew.cpp +++ b/src/eepp/maps/mapeditor/uimapnew.cpp @@ -202,21 +202,21 @@ UIMapNew::~UIMapNew() { } void UIMapNew::onRedChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.r = (Uint8)mUIRedSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIRedTxt->setText( String::toStr( (Int32)mUIRedSlider->getValue() ) ); } void UIMapNew::onGreenChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.g = (Uint8)mUIGreenSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIGreenTxt->setText( String::toStr( (Uint32)mUIGreenSlider->getValue() ) ); } void UIMapNew::onBlueChange( const Event * ) { - Color Col = mUIBaseColor->getBackground()->getColor(); + Color Col = mUIBaseColor->getBackgroundColor(); Col.b = (Uint8)mUIBlueSlider->getValue(); mUIBaseColor->setBackgroundColor( Col ); mUIBlueTxt->setText( String::toStr( (Uint32)mUIBlueSlider->getValue() ) ); @@ -246,7 +246,7 @@ void UIMapNew::onOKClick( const Event * ) { if ( w > 0 && h > 0 && tw > 0 && th > 0 && ml > 0 ) { if ( !mResizeMap ) { mUIMap->Map()->create( Sizei( w, h ), ml, Sizei( tw, th ), Flags, mUIMap->Map()->getViewSize() ); - mUIMap->Map()->setBaseColor( mUIBaseColor->getBackground()->getColor() ); + mUIMap->Map()->setBaseColor( mUIBaseColor->getBackgroundColor() ); } else { std::string oldPath( mUIMap->Map()->getPath() ); std::string mapPath( Sys::getTempPath() + "temp.eepp.map.eem" ); diff --git a/src/eepp/ui/css/stylesheetselectorrule.cpp b/src/eepp/ui/css/stylesheetselectorrule.cpp index b4585a8e2..70ea582ed 100644 --- a/src/eepp/ui/css/stylesheetselectorrule.cpp +++ b/src/eepp/ui/css/stylesheetselectorrule.cpp @@ -248,8 +248,10 @@ bool StyleSheetSelectorRule::matches( StyleSheetElement * element, const bool& a if ( !mClasses.empty() && !element->getStyleSheetClasses().empty() ) { bool hasClasses = true; - for ( const auto& cls : element->getStyleSheetClasses() ) { - if ( !hasClass( cls ) ) { + const std::vector& elClasses = element->getStyleSheetClasses(); + + for ( const auto& cls : mClasses ) { + if ( std::find(elClasses.begin(), elClasses.end(), cls) == elClasses.end() ) { hasClasses = false; break; } diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp index a00a28e37..d41a917ff 100644 --- a/src/eepp/ui/uinode.cpp +++ b/src/eepp/ui/uinode.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace EE { namespace UI { @@ -33,7 +34,7 @@ UINode::UINode() : mFlags( UI_CONTROL_DEFAULT_FLAGS ), mState(UIState::StateFlagNormal), mSkinState( NULL ), - mBackgroundState( NULL ), + mBackground( NULL ), mForegroundState( NULL ), mBorder( NULL ), mDragButton( EE_BUTTON_LMASK ), @@ -48,13 +49,7 @@ UINode::UINode() : UINode::~UINode() { removeSkin(); - if ( NULL != mBackgroundState && NULL != mBackgroundState->getSkin() ) - eeDelete( mBackgroundState->getSkin() ); - - if ( NULL != mForegroundState && NULL != mForegroundState->getSkin() ) - eeDelete( mForegroundState->getSkin() ); - - eeSAFE_DELETE( mBackgroundState ); + eeSAFE_DELETE( mBackground ); eeSAFE_DELETE( mForegroundState ); eeSAFE_DELETE( mBorder ); @@ -384,72 +379,53 @@ UINode * UINode::setGravity( Uint32 hvalign ) { return this; } -UISkin * UINode::setBackgroundFillEnabled( bool enabled ) { +UINodeDrawable * UINode::setBackgroundFillEnabled( bool enabled ) { writeFlag( UI_FILL_BACKGROUND, enabled ? 1 : 0 ); - if ( enabled && NULL == mBackgroundState ) { + if ( enabled && NULL == mBackground ) { getBackground(); } invalidateDraw(); - return NULL != mBackgroundState ? mBackgroundState->getSkin() : NULL; + return mBackground; } -UINode * UINode::setBackgroundDrawable( Drawable * drawable, bool ownIt ) { - setBackgroundFillEnabled( true )->setStateDrawable( UIState::StateFlagNormal, drawable, ownIt ); +UINode * UINode::setBackgroundDrawable( Drawable * drawable, bool ownIt, int index ) { + setBackgroundFillEnabled( true )->setDrawable( index, drawable, ownIt ); return this; } UINode * UINode::setBackgroundColor( const Color& color ) { - UISkin * background = setBackgroundFillEnabled( true ); + setBackgroundFillEnabled( true )->setBackgroundColor( color ); + return this; +} - Drawable * stateDrawable = background->getStateDrawable( UIState::StateFlagNormal ); - - if ( NULL == stateDrawable ) - setBackgroundDrawable( RectangleDrawable::New(), true ); - - if ( NULL != mBackgroundState ) - mBackgroundState->setStateColor( UIState::StateFlagNormal, color ); +UINode* UINode::setBackgroundPosition( const std::string& positionEq, int index ) { + setBackgroundFillEnabled( true )->setDrawablePosition( index, positionEq ); + return this; +} +UINode* UINode::setBackgroundRepeat( const std::string& repeatRule, int index ) { + setBackgroundFillEnabled( true )->setDrawableRepeat( index, repeatRule ); return this; } Color UINode::getBackgroundColor() const { - if ( NULL != mBackgroundState ) - return mBackgroundState->getStateColor( UIState::StateFlagNormal ); - - return Color::Transparent; + return NULL != mBackground ? mBackground->getBackgroundColor() : Color::Transparent; } UINode * UINode::setBorderRadius( const unsigned int& corners ) { setBorderEnabled( true )->setCorners( corners ); - - UISkin * background = setBackgroundFillEnabled( true ); - - Drawable * stateDrawable = background->getStateDrawable( UIState::StateFlagNormal ); - - if ( NULL == stateDrawable ) { - setBackgroundColor( Color::Transparent ); - - stateDrawable = background->getStateDrawable( UIState::StateFlagNormal ); - } - - if ( stateDrawable->getDrawableType() == Drawable::RECTANGLE ) { - static_cast( stateDrawable )->setCorners( corners ); - } - + setBackgroundFillEnabled( true )->setBorderRadius( corners ); return this; } Uint32 UINode::getBorderRadius() const { - if ( NULL != mBorder ) - return mBorder->getCorners(); - - return 0; + return NULL != mBorder ? mBorder->getCorners() : 0; } -UISkin * UINode::setForegroundFillEnabled( bool enabled ) { +UINodeDrawable * UINode::setForegroundFillEnabled( bool enabled ) { writeFlag( UI_FILL_FOREGROUND, enabled ? 1 : 0 ); if ( enabled && NULL == mForegroundState ) { @@ -458,67 +434,40 @@ UISkin * UINode::setForegroundFillEnabled( bool enabled ) { invalidateDraw(); - return NULL != mForegroundState ? mForegroundState->getSkin() : NULL; + return mForegroundState; } -UINode * UINode::setForegroundDrawable( Drawable * drawable, bool ownIt ) { - setForegroundFillEnabled( true )->setStateDrawable( UIState::StateFlagNormal, drawable, ownIt ); +UINode * UINode::setForegroundDrawable( Drawable * drawable, bool ownIt, int index ) { + setForegroundFillEnabled( true )->setDrawable( index, drawable, ownIt ); return this; } Color UINode::getForegroundColor() const { - if ( NULL != mForegroundState ) - return mForegroundState->getStateColor( UIState::StateFlagNormal ); - - return Color::Transparent; + return NULL != mForegroundState ? mForegroundState->getBackgroundColor() : Color::Transparent; } UINode * UINode::setForegroundColor( const Color& color ) { - UISkin * foreground = setForegroundFillEnabled( true ); + setForegroundFillEnabled( true )->setBackgroundColor(color ); + return this; +} - Drawable * stateDrawable = foreground->getStateDrawable( UIState::StateFlagNormal ); - - if ( NULL == stateDrawable ) - setForegroundDrawable( RectangleDrawable::New(), true ); - - if ( NULL != mForegroundState ) - mForegroundState->setStateColor( UIState::StateFlagNormal, color ); +UINode* UINode::setForegroundPosition( const std::string& positionEq, int index ) { + setForegroundFillEnabled( true )->setDrawablePosition( index, positionEq ); + return this; +} +UINode* UINode::setForegroundRepeat( const std::string& repeatRule, int index ) { + setBackgroundFillEnabled( true )->setDrawableRepeat( index, repeatRule ); return this; } UINode * UINode::setForegroundRadius( const unsigned int& corners ) { - UISkin * foreground = setForegroundFillEnabled( true ); - - Drawable * stateDrawable = foreground->getStateDrawable( UIState::StateFlagNormal ); - - if ( NULL == stateDrawable ) { - setForegroundColor( Color::Black ); - - stateDrawable = foreground->getStateDrawable( UIState::StateFlagNormal ); - } - - if ( stateDrawable->getDrawableType() == Drawable::RECTANGLE ) { - RectangleDrawable * rectangleDrawable = static_cast( stateDrawable ); - - rectangleDrawable->setCorners( corners ); - } - + setForegroundFillEnabled( true )->setBorderRadius( corners ); return this; } Uint32 UINode::getForegroundRadius() const { - if ( NULL != mForegroundState && NULL != mForegroundState->getSkin() ) { - Drawable * stateDrawable = mForegroundState->getSkin()->getStateDrawable( UIState::StateFlagNormal ); - - if ( stateDrawable->getDrawableType() == Drawable::RECTANGLE ) { - RectangleDrawable * rectangleDrawable = static_cast( stateDrawable ); - - return rectangleDrawable->getCorners(); - } - } - - return 0; + return NULL != mForegroundState ? mForegroundState->getBorderRadius() : 0; } RectangleDrawable * UINode::setBorderEnabled( bool enabled ) { @@ -527,7 +476,7 @@ RectangleDrawable * UINode::setBorderEnabled( bool enabled ) { if ( enabled && NULL == mBorder ) { getBorder(); - if ( NULL == mBackgroundState ) { + if ( NULL == mBackground ) { getBackground(); } } @@ -560,7 +509,7 @@ const Uint32& UINode::getFlags() const { } UINode * UINode::setFlags( const Uint32& flags ) { - if ( NULL == mBackgroundState && ( flags & UI_FILL_BACKGROUND ) ) + if ( NULL == mBackground && ( flags & UI_FILL_BACKGROUND ) ) setBackgroundFillEnabled( true ); if ( NULL == mForegroundState && ( flags & UI_FILL_FOREGROUND ) ) @@ -595,14 +544,14 @@ UINode * UINode::resetFlags( Uint32 newFlags ) { } void UINode::drawBackground() { - if ( ( mFlags & UI_FILL_BACKGROUND ) && NULL != mBackgroundState ) { - mBackgroundState->draw( mScreenPosi.x, mScreenPosi.y, eefloor(mSize.getWidth()), eefloor(mSize.getHeight()), (Uint32)mAlpha ); + if ( ( mFlags & UI_FILL_BACKGROUND ) && NULL != mBackground ) { + mBackground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), Sizef( eefloor(mSize.getWidth()), eefloor(mSize.getHeight()) ), mAlpha ); } } void UINode::drawForeground() { if ( ( mFlags & UI_FILL_FOREGROUND ) && NULL != mForegroundState ) { - mForegroundState->draw( mScreenPosi.x, mScreenPosi.y, eefloor(mSize.getWidth()), eefloor(mSize.getHeight()), (Uint32)mAlpha ); + mForegroundState->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), Sizef( eefloor(mSize.getWidth()), eefloor(mSize.getHeight()) ), (Uint32)mAlpha ); } } @@ -651,20 +600,20 @@ void UINode::internalDraw() { } } -UISkin * UINode::getBackground() { - if ( NULL == mBackgroundState ) { - mBackgroundState = UISkinState::New( UISkin::New() ); +UINodeDrawable * UINode::getBackground() { + if ( NULL == mBackground ) { + mBackground = UINodeDrawable::New(); } - return mBackgroundState->getSkin(); + return mBackground; } -UISkin * UINode::getForeground() { +UINodeDrawable * UINode::getForeground() { if ( NULL == mForegroundState ) { - mForegroundState = UISkinState::New( UISkin::New() ); + mForegroundState = UINodeDrawable::New(); } - return mForegroundState->getSkin(); + return mForegroundState; } RectangleDrawable * UINode::getBorder() { @@ -781,12 +730,6 @@ void UINode::pushState(const Uint32& State , bool emitEvent) { if ( NULL != mSkinState ) mSkinState->pushState( State ); - if ( NULL != mBackgroundState ) - mBackgroundState->pushState( State ); - - if ( NULL != mForegroundState ) - mForegroundState->pushState( State ); - if ( emitEvent ) { onStateChange(); } else { @@ -802,12 +745,6 @@ void UINode::popState(const Uint32& State , bool emitEvent) { if ( NULL != mSkinState ) mSkinState->popState( State ); - if ( NULL != mBackgroundState ) - mBackgroundState->popState( State ); - - if ( NULL != mForegroundState ) - mForegroundState->popState( State ); - if ( emitEvent ) { onStateChange(); } else { diff --git a/src/eepp/ui/uinodedrawable.cpp b/src/eepp/ui/uinodedrawable.cpp new file mode 100644 index 000000000..5c2c284d9 --- /dev/null +++ b/src/eepp/ui/uinodedrawable.cpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include + +namespace EE { namespace UI { + +UINodeDrawable::Repeat UINodeDrawable::repeatFromText( const std::string& text ) { + if ( "repeat" == text ) return UINodeDrawable::Repeat::RepeatXY; + if ( "repeat-x" == text ) return UINodeDrawable::Repeat::RepeatX; + if ( "repeat-y" == text ) return UINodeDrawable::Repeat::RepeatY; + return UINodeDrawable::Repeat::NoRepeat; +} + +UINodeDrawable * UINodeDrawable::New() { + return eeNew( UINodeDrawable, () ); +} + +UINodeDrawable::UINodeDrawable() : + Drawable( Drawable::UINODEDRAWABLE ), + mNeedsUpdate(true), + mClipEnabled(false) +{ + mBackgroundColor.setColor(Color::Transparent); +} + +UINodeDrawable::~UINodeDrawable() { + clearDrawables(); +} + +void UINodeDrawable::clearDrawables() { + for ( auto& drawable : mGroup ) { + eeDelete( drawable.second ); + } + + mGroup.clear(); + mBackgroundColor.setColor(Color::Transparent); +} + +void UINodeDrawable::setBorderRadius( const Uint32& corners ) { + mBackgroundColor.setCorners( corners ); +} + +Uint32 UINodeDrawable::getBorderRadius() const { + return mBackgroundColor.getCorners(); +} + +UINodeDrawable::LayerDrawable* UINodeDrawable::getLayer( int index ) { + auto it = mGroup.find(index); + + if ( it == mGroup.end() ) + mGroup[ index ] = UINodeDrawable::LayerDrawable::New( this ); + + return mGroup[ index ]; +} + +void UINodeDrawable::setDrawable( int index, Drawable* drawable, bool ownIt ) { + if ( drawable != getLayer( index )->getDrawable() ) { + getLayer( index )->setDrawable( drawable, ownIt ); + mNeedsUpdate = true; + } +} + +void UINodeDrawable::setDrawablePosition( int index, const std::string& positionEq ) { + if ( mPosEq[index] != positionEq ) { + mPosEq[index] = positionEq; + mNeedsUpdate = true; + } +} + +void UINodeDrawable::setDrawableRepeat( int index, const std::string& repeatRule ) { + getLayer( index )->setRepeat( repeatFromText( repeatRule ) ); +} + +void UINodeDrawable::setBackgroundColor(const Color& color) { + mBackgroundColor.setColor( color ); +} + +Color UINodeDrawable::getBackgroundColor() const { + return mBackgroundColor.getColor(); +} + +bool UINodeDrawable::getClipEnabled() const { + return mClipEnabled; +} + +void UINodeDrawable::setClipEnabled(bool clipEnabled) { + mClipEnabled = clipEnabled; +} + +Sizef UINodeDrawable::getSize() { + return mSize; +} + +void UINodeDrawable::setSize( const Sizef& size ) { + if ( size != mSize ) { + mSize = size; + onSizeChange(); + } +} + +void UINodeDrawable::draw( const Vector2f& position, const Sizef& size ) { + draw( position, size, 255 ); +} + +void UINodeDrawable::draw( const Vector2f& position, const Sizef& size, const Uint32& alpha ) { + if ( position != mPosition ) { + mPosition = position; + mNeedsUpdate = true; + } + + if ( size != mSize ) { + mSize = size; + mNeedsUpdate = true; + } + + if ( mNeedsUpdate ) + update(); + + if ( mClipEnabled ) + GLi->getClippingMask()->clipPlaneEnable( mPosition.x, mPosition.y, mSize.x, mSize.y ); + + if ( mBackgroundColor.getColor().a != 0 ) { + if ( alpha != 255 ) { + Color color = mBackgroundColor.getColor(); + mBackgroundColor.setAlpha( alpha * color.a / 255 ); + mBackgroundColor.draw( position, size ); + mBackgroundColor.setAlpha( color.a ); + + } else { + mBackgroundColor.draw( position, size ); + } + } + + for ( auto& drawableIt : mGroup ) { + UINodeDrawable::LayerDrawable * drawable = drawableIt.second; + + if ( alpha != 255 ) { + Color color = drawable->getColor(); + drawable->setAlpha( alpha * color.a / 255 ); + drawable->draw( position, size ); + drawable->setAlpha( color.a ); + } else { + drawable->draw( position, size ); + } + } + + if ( mClipEnabled ) + GLi->getClippingMask()->clipPlaneDisable(); +} + +void UINodeDrawable::draw(const Vector2f & position) { + draw( position, mSize ); +} + +void UINodeDrawable::draw() { + draw( mPosition, mSize ); +} + +void UINodeDrawable::onPositionChange() { + mNeedsUpdate = true; +} + +void UINodeDrawable::onSizeChange() { + mNeedsUpdate = true; +} + +void UINodeDrawable::update() { + mBackgroundColor.setPosition( mPosition ); + mBackgroundColor.setSize( mSize ); + + for ( size_t i = 0; i < mGroup.size(); i++ ) { + UINodeDrawable::LayerDrawable * drawable = mGroup[i]; + drawable->setPosition( mPosition ); + drawable->setPositionEq( mPosEq[i] ); + drawable->setSize( mSize ); + } + + mNeedsUpdate = false; +} + +UINodeDrawable::LayerDrawable * UINodeDrawable::LayerDrawable::New( UINodeDrawable * container ) { + return eeNew( UINodeDrawable::LayerDrawable, ( container ) ); +} + +UINodeDrawable::LayerDrawable::LayerDrawable( UINodeDrawable * container ) : + Drawable(UINODEDRAWABLE_LAYERDRAWABLE), + mContainer(container), + mNeedsUpdate(false), + mUpdatePosEq(false), + mOwnsDrawable(false), + mDrawable(NULL), + mResourceChangeCbId(0) +{} + +UINodeDrawable::LayerDrawable::~LayerDrawable() { + if ( mOwnsDrawable ) + eeSAFE_DELETE( mDrawable ); +} + +void UINodeDrawable::LayerDrawable::draw() { + draw( mPosition, mSize ); +} + +void UINodeDrawable::LayerDrawable::draw( const Vector2f& position ) { + draw( position, mSize ); +} + +void UINodeDrawable::LayerDrawable::draw( const Vector2f& position, const Sizef& size ) { + if ( position != mPosition ) { + mPosition = position; + mNeedsUpdate = true; + } + + if ( size != mSize ) { + mSize = size; + mNeedsUpdate = true; + } + + if ( mDrawable == NULL ) + return; + + if ( mNeedsUpdate ) + update(); + + mDrawable->draw( mPosition + mOffset, mSize ); +} + +Sizef UINodeDrawable::LayerDrawable::getSize() { + return mSize; +} + +void UINodeDrawable::LayerDrawable::setSize(const Sizef& size) { + if ( size != mSize ) { + mSize = size; + mNeedsUpdate = true; + mUpdatePosEq = true; + } +} + +Drawable* UINodeDrawable::LayerDrawable::getDrawable() const { + return mDrawable; +} + +void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& ownIt ) { + if ( drawable == mDrawable ) + return; + + if ( NULL != mDrawable ) { + if ( mDrawable->isDrawableResource() ) { + reinterpret_cast( mDrawable )->popResourceChangeCallback( mResourceChangeCbId ); + } + + if ( mOwnsDrawable ) { + eeSAFE_DELETE( mDrawable ); + } + } + + mDrawable = drawable; + mOwnsDrawable = ownIt; + + if ( mDrawable->isDrawableResource() ) { + mResourceChangeCbId = reinterpret_cast( mDrawable )->pushResourceChangeCallback( [&] ( DrawableResource::Event, DrawableResource* ) { + mNeedsUpdate = true; + } ); + } +} + +const Vector2f& UINodeDrawable::LayerDrawable::getOffset() const { + return mOffset; +} + +void UINodeDrawable::LayerDrawable::setPositionEq( const std::string& positionEq ) { + if ( mPositionEq != positionEq ) { + mPositionEq = positionEq; + mUpdatePosEq = true; + mNeedsUpdate = true; + } +} + +const UINodeDrawable::Repeat& UINodeDrawable::LayerDrawable::getRepeat() const { + return mRepeat; +} + +void UINodeDrawable::LayerDrawable::setRepeat( const UINodeDrawable::Repeat& repeat ) { + mRepeat = repeat; + mNeedsUpdate = true; + mUpdatePosEq = true; +} + +void UINodeDrawable::LayerDrawable::onPositionChange() { + mNeedsUpdate = true; + mUpdatePosEq = true; +} + +void UINodeDrawable::LayerDrawable::update() { + // TODO: Implement background-position and background-repeat + if ( mUpdatePosEq ) { + + mUpdatePosEq = false; + } +} + +}} diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index f2b70cfaa..e47a90b5e 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -659,6 +659,12 @@ bool UITextView::setAttribute( const NodeAttribute& attribute, const Uint32& sta } } else if ( "text-selection" == name || "textselection" == name ) { mFlags|= UI_TEXT_SELECTION_ENABLED; + } else if ( "text-align" == name || "textalign" == name ) { + std::string align = String::toLower( attribute.value() ); + + if ( align == "center" ) setFlags( UI_HALIGN_CENTER ); + else if ( align == "left" ) setFlags( UI_HALIGN_LEFT ); + else if ( align == "right" ) setFlags( UI_HALIGN_RIGHT ); } else { return UIWidget::setAttribute( attribute, state ); } diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 342682404..2a153e567 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -920,9 +920,13 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state setBackgroundColor( color ); } } else if ( "background-image" == name || "backgroundimage" == name ) { - drawablePropertySet( "background", attribute.getValue(), [&] ( Drawable * drawable, bool ownIt ) { - setBackgroundDrawable( drawable, ownIt ); + drawablePropertySet( "background", attribute.getValue(), [&] ( Drawable * drawable, bool ownIt, int index ) { + setBackgroundDrawable( drawable, ownIt, index ); } ); + } else if ( "background-position" == name || "backgroundposition" == name ) { + setBackgroundPosition( attribute.value(), 0 ); + } else if ( "background-repeat" == name || "backgroundrepeat" == name ) { + setBackgroundRepeat( attribute.value(), 0 ); } else if ( "foreground" == name ) { if ( Color::isColorString( attribute.getValue() ) ) { setAttribute( NodeAttribute( "foreground-color", attribute.getValue() ) ); @@ -948,8 +952,8 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state setForegroundColor( color ); } } else if ( "foreground-image" == name || "foregroundimage" == name ) { - drawablePropertySet( "foreground", attribute.getValue(), [&] ( Drawable * drawable, bool ownIt ) { - setForegroundDrawable( drawable, ownIt ); + drawablePropertySet( "foreground", attribute.getValue(), [&] ( Drawable * drawable, bool ownIt, int index ) { + setForegroundDrawable( drawable, ownIt, index ); } ); } else if ( "foreground-radius" == name || "foregroundradius" == name ) { SAVE_NORMAL_STATE_ATTR( String::toStr( getForegroundRadius() ) ); @@ -1397,9 +1401,10 @@ std::string UIWidget::getFlagsString() const { return String::join( flagvec, '|' ); } -bool UIWidget::drawablePropertySet(const std::string& propertyName, const std::string& value, std::function funcSet) { +bool UIWidget::drawablePropertySet(const std::string& propertyName, const std::string& value, std::function funcSet) { FunctionString functionType = FunctionString::parse( value ); Drawable * res = NULL; + int index = 0; bool attributeSet = true; if ( !functionType.isEmpty() ) { @@ -1438,14 +1443,14 @@ bool UIWidget::drawablePropertySet(const std::string& propertyName, const std::s drawable->setRectColors( rectColors ); - funcSet( drawable, true ); + funcSet( drawable, true, index ); } else if ( functionType.getName() == "url" && functionType.getParameters().size() >= 1 ) { if ( NULL != ( res = DrawableSearcher::searchByName( functionType.getParameters().at(0) ) ) ) { - funcSet( res, res->getDrawableType() == Drawable::SPRITE ); + funcSet( res, res->getDrawableType() == Drawable::SPRITE, index ); } } } else if ( NULL != ( res = DrawableSearcher::searchByName( value ) ) ) { - funcSet( res, res->getDrawableType() == Drawable::SPRITE ); + funcSet( res, res->getDrawableType() == Drawable::SPRITE, index ); } else { attributeSet = false; } diff --git a/src/tools/uieditor/uieditor.cpp b/src/tools/uieditor/uieditor.cpp index faa1fbf5c..4bd2b562a 100644 --- a/src/tools/uieditor/uieditor.cpp +++ b/src/tools/uieditor/uieditor.cpp @@ -53,6 +53,7 @@ bool updateStyleSheet = false; Clock waitClock; Clock cssWaitClock; efsw::WatchID watch = 0; +efsw::WatchID styleSheetWatch = 0; std::map widgetRegistered; std::string basePath; @@ -209,6 +210,25 @@ static void loadStyleSheet( std::string cssPath ) { uiSceneNode->setStyleSheet( parser.getStyleSheet() ); currentStyleSheet = cssPath; + + std::string folder( FileSystem::fileRemoveFileName( cssPath ) ); + + bool keepWatch = false; + + for ( auto& directory : fileWatcher->directories() ) { + if ( directory == folder ) { + keepWatch = true; + } + } + + if ( !keepWatch ) { + if ( styleSheetWatch != 0 ) { + fileWatcher->removeWatch( styleSheetWatch ); + } + + styleSheetWatch = fileWatcher->addWatch( folder, listener ); + } + } } @@ -519,8 +539,8 @@ static void loadProjectNodes( pugi::xml_node node ) { if ( !styleSheetNode.empty() ) { std::string cssPath( styleSheetNode.attribute( "path" ).as_string() ); - if ( isCSS( cssPath ) && FileSystem::fileExists( cssPath ) ) { - loadStyleSheet( cssPath ); + if ( isCSS( cssPath ) && FileSystem::fileExists( basePath + cssPath ) ) { + loadStyleSheet( basePath + cssPath ); } } @@ -608,6 +628,8 @@ void loadProject( std::string projectPath ) { basePath = FileSystem::fileRemoveFileName( projectPath ); + FileSystem::changeWorkingDirectory( basePath ); + pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file( projectPath.c_str() );