diff --git a/include/eepp/scene/actionmanager.hpp b/include/eepp/scene/actionmanager.hpp index 51ed06b73..ad2185634 100644 --- a/include/eepp/scene/actionmanager.hpp +++ b/include/eepp/scene/actionmanager.hpp @@ -44,7 +44,9 @@ class EE_API ActionManager { protected: std::list mActions; + std::list mActionsRemoveList; Mutex mMutex; + bool mUpdating; }; }} // namespace EE::Scene diff --git a/include/eepp/ui/css/stylesheetpropertytransition.hpp b/include/eepp/ui/css/stylesheetpropertytransition.hpp index 2290bd717..2aa0b5d0a 100644 --- a/include/eepp/ui/css/stylesheetpropertytransition.hpp +++ b/include/eepp/ui/css/stylesheetpropertytransition.hpp @@ -67,8 +67,6 @@ class EE_API StyleSheetPropertyTransition : public Action { Time mDuration; Time mElapsed; Ease::Interpolation mType; - - Float getContainerLength( UIWidget* node ); }; }}} // namespace EE::UI::CSS diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp index b90ab7046..103eec0b5 100644 --- a/include/eepp/ui/uinode.hpp +++ b/include/eepp/ui/uinode.hpp @@ -92,6 +92,8 @@ class EE_API UINode : public Node { UINode* setBackgroundDrawable( Drawable* drawable, bool ownIt = false, int index = 0 ); + UINode* setBackgroundDrawable( const std::string& drawable, int index ); + UINode* setBackgroundColor( const Color& color ); UINode* setBackgroundPositionX( const std::string& positionX, int index = 0 ); @@ -112,6 +114,8 @@ class EE_API UINode : public Node { UINode* setForegroundDrawable( Drawable* drawable, bool ownIt = false, int index = 0 ); + UINode* setForegroundDrawable( const std::string& drawable, int index = 0 ); + UINode* setForegroundColor( const Color& color ); UINode* setForegroundPositionX( const std::string& positionX, int index = 0 ); @@ -216,7 +220,7 @@ class EE_API UINode : public Node { Uint32 mState; UISkinState* mSkinState; UINodeDrawable* mBackground; - UINodeDrawable* mForegroundState; + UINodeDrawable* mForeground; RectangleDrawable* mBorder; Vector2f mDragPoint; Uint32 mDragButton; diff --git a/include/eepp/ui/uinodedrawable.hpp b/include/eepp/ui/uinodedrawable.hpp index a19617642..7f072fe7e 100644 --- a/include/eepp/ui/uinodedrawable.hpp +++ b/include/eepp/ui/uinodedrawable.hpp @@ -43,8 +43,12 @@ class EE_API UINodeDrawable : public Drawable { Drawable* getDrawable() const; + const std::string& getDrawableRef() const; + void setDrawable( Drawable* drawable, const bool& ownIt ); + void setDrawable( const std::string& drawableRef ); + void setOffset( const Vector2f& offset ); const Vector2f& getOffset() const; @@ -90,12 +94,15 @@ class EE_API UINodeDrawable : public Drawable { bool mNeedsUpdate; bool mOwnsDrawable; Drawable* mDrawable; + std::string mDrawableRef; Uint32 mResourceChangeCbId; Repeat mRepeat; virtual void onPositionChange(); void update(); + + Drawable* createDrawable( const std::string& value, const Sizef& size, bool& ownIt ); }; static UINodeDrawable* New( UINode* owner ); @@ -130,6 +137,8 @@ class EE_API UINodeDrawable : public Drawable { void setDrawable( int index, Drawable* drawable, bool ownIt ); + void setDrawable( int index, const std::string& drawable ); + void setDrawablePositionX( int index, const std::string& positionX ); void setDrawablePositionY( int index, const std::string& positionY ); diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp index 017a09b9b..518994e06 100644 --- a/include/eepp/ui/uiwidget.hpp +++ b/include/eepp/ui/uiwidget.hpp @@ -1,6 +1,7 @@ #ifndef EE_UIUIWIDGET_HPP #define EE_UIUIWIDGET_HPP +#include #include #include #include @@ -185,12 +186,16 @@ class EE_API UIWidget : public UINode { return reinterpret_cast( findByTag( tag ) ); } + UIWidget* querySelector( const CSS::StyleSheetSelector& selector ); + UIWidget* querySelector( const std::string& selector ); template T* querySelector( const std::string& selector ) { return reinterpret_cast( querySelector( selector ) ); } + std::vector querySelectorAll( const CSS::StyleSheetSelector& selector ); + std::vector querySelectorAll( const std::string& selector ); std::string getPropertyString( const std::string& property ); @@ -199,6 +204,17 @@ class EE_API UIWidget : public UINode { bool isSceneNodeLoading() const; + Float + getPropertyRelativeTargetContainerLength( const CSS::PropertyRelativeTarget& relativeTarget, + const Float& defaultValue = 0 ); + + Float lengthFromValue( const std::string& value, + const CSS::PropertyRelativeTarget& relativeTarget, + const Float& defaultValue = 0, const Float& defaultContainerValue = 0 ); + + Float lengthFromValue( const StyleSheetProperty& property, + const Float& defaultValue = 0, const Float& defaultContainerValue = 0 ); + protected: friend class UIManager; friend class UISceneNode; @@ -267,14 +283,6 @@ class EE_API UIWidget : public UINode { std::string getFlagsString() const; - bool - drawablePropertySet( const std::string& propertyName, const std::string& value, - std::function funcSet ); - - UIWidget* querySelector( const CSS::StyleSheetSelector& selector ); - - std::vector querySelectorAll( const CSS::StyleSheetSelector& selector ); - bool checkPropertyDefinition( const StyleSheetProperty& property ); }; diff --git a/src/eepp/scene/actionmanager.cpp b/src/eepp/scene/actionmanager.cpp index fe08a8a67..5399127a2 100644 --- a/src/eepp/scene/actionmanager.cpp +++ b/src/eepp/scene/actionmanager.cpp @@ -10,7 +10,7 @@ ActionManager* ActionManager::New() { return eeNew( ActionManager, () ); } -ActionManager::ActionManager() {} +ActionManager::ActionManager() : mUpdating( false ) {} ActionManager::~ActionManager() { clear(); @@ -84,6 +84,7 @@ void ActionManager::update( const Time& time ) { { Lock lock( mMutex ); + mUpdating = true; for ( auto it = mActions.begin(); it != mActions.end(); ++it ) { Action* action = ( *it ); @@ -96,8 +97,15 @@ void ActionManager::update( const Time& time ) { removeList.push_back( action ); } } + + mUpdating = false; } + for ( auto it = mActionsRemoveList.begin(); it != mActionsRemoveList.end(); ++it ) + removeAction( ( *it ) ); + + mActionsRemoveList.clear(); + for ( auto it = removeList.begin(); it != removeList.end(); ++it ) removeAction( ( *it ) ); } @@ -130,9 +138,17 @@ void ActionManager::removeAction( Action* action ) { Lock lock( mMutex ); if ( NULL != action ) { - mActions.remove( action ); + if ( !mUpdating ) { + bool found = std::find( mActions.begin(), mActions.end(), action ) != mActions.end(); - eeSAFE_DELETE( action ); + if ( found ) { + mActions.remove( action ); + + eeSAFE_DELETE( action ); + } + } else { + mActionsRemoveList.push_back( action ); + } } } diff --git a/src/eepp/ui/css/stylesheetpropertytransition.cpp b/src/eepp/ui/css/stylesheetpropertytransition.cpp index 4715259ed..1a67c5cf2 100644 --- a/src/eepp/ui/css/stylesheetpropertytransition.cpp +++ b/src/eepp/ui/css/stylesheetpropertytransition.cpp @@ -128,7 +128,8 @@ void StyleSheetPropertyTransition::onUpdate( const Time& ) { break; } case PropertyType::NumberLength: { - Float containerLength = getContainerLength( node ); + Float containerLength = node->getPropertyRelativeTargetContainerLength( + mProperty->getRelativeTarget() ); Float start = node->convertLength( mStartValue, containerLength ); Float end = node->convertLength( mEndValue, containerLength ); Time time = @@ -201,42 +202,6 @@ void StyleSheetPropertyTransition::onUpdate( const Time& ) { } } -Float StyleSheetPropertyTransition::getContainerLength( UIWidget* node ) { - Float containerLength = 0; - switch ( mProperty->getRelativeTarget() ) { - case PropertyRelativeTarget::ContainingBlockWidth: - containerLength = node->getParent()->getPixelsSize().getWidth(); - break; - case PropertyRelativeTarget::ContainingBlockHeight: - containerLength = node->getParent()->getPixelsSize().getHeight(); - case PropertyRelativeTarget::LocalBlockWidth: - containerLength = node->getPixelsSize().getWidth(); - break; - case PropertyRelativeTarget::LocalBlockHeight: - containerLength = node->getPixelsSize().getHeight(); - break; - case PropertyRelativeTarget::BackgroundWidth: - containerLength = node->getPixelsSize().getWidth() - - node->getBackground()->getLayer( 0 )->getDrawableSize().getWidth(); - break; - case PropertyRelativeTarget::BackgroundHeight: - containerLength = node->getPixelsSize().getHeight() - - node->getBackground()->getLayer( 0 )->getDrawableSize().getHeight(); - break; - case PropertyRelativeTarget::ForegroundWidth: - containerLength = node->getPixelsSize().getWidth() - - node->getForeground()->getLayer( 0 )->getDrawableSize().getWidth(); - break; - case PropertyRelativeTarget::ForegroundHeight: - containerLength = node->getPixelsSize().getHeight() - - node->getForeground()->getLayer( 0 )->getDrawableSize().getHeight(); - break; - default: - break; - } - return containerLength; -} - const Time& StyleSheetPropertyTransition::getElapsed() const { return mElapsed; } diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp index deb426d20..796d9e426 100644 --- a/src/eepp/ui/uinode.cpp +++ b/src/eepp/ui/uinode.cpp @@ -35,7 +35,7 @@ UINode::UINode() : mState( UIState::StateFlagNormal ), mSkinState( NULL ), mBackground( NULL ), - mForegroundState( NULL ), + mForeground( NULL ), mBorder( NULL ), mDragButton( EE_BUTTON_LMASK ), mSkinColor( Color::White ) { @@ -49,7 +49,7 @@ UINode::~UINode() { removeSkin(); eeSAFE_DELETE( mBackground ); - eeSAFE_DELETE( mForegroundState ); + eeSAFE_DELETE( mForeground ); eeSAFE_DELETE( mBorder ); if ( isDragging() ) @@ -407,6 +407,11 @@ UINode* UINode::setBackgroundDrawable( Drawable* drawable, bool ownIt, int index return this; } +UINode* UINode::setBackgroundDrawable( const std::string& drawable, int index ) { + setBackgroundFillEnabled( true )->setDrawable( index, drawable ); + return this; +} + UINode* UINode::setBackgroundColor( const Color& color ) { setBackgroundFillEnabled( true )->setBackgroundColor( color ); return this; @@ -449,13 +454,13 @@ Uint32 UINode::getBorderRadius() const { UINodeDrawable* UINode::setForegroundFillEnabled( bool enabled ) { writeFlag( UI_FILL_FOREGROUND, enabled ? 1 : 0 ); - if ( enabled && NULL == mForegroundState ) { + if ( enabled && NULL == mForeground ) { getForeground(); } invalidateDraw(); - return mForegroundState; + return mForeground; } UINode* UINode::setForegroundDrawable( Drawable* drawable, bool ownIt, int index ) { @@ -463,8 +468,13 @@ UINode* UINode::setForegroundDrawable( Drawable* drawable, bool ownIt, int index return this; } +UINode* UINode::setForegroundDrawable( const std::string& drawable, int index ) { + setForegroundFillEnabled( true )->setDrawable( index, drawable ); + return this; +} + Color UINode::getForegroundColor() const { - return NULL != mForegroundState ? mForegroundState->getBackgroundColor() : Color::Transparent; + return NULL != mForeground ? mForeground->getBackgroundColor() : Color::Transparent; } UINode* UINode::setForegroundColor( const Color& color ) { @@ -498,7 +508,7 @@ UINode* UINode::setForegroundRadius( const unsigned int& corners ) { } Uint32 UINode::getForegroundRadius() const { - return NULL != mForegroundState ? mForegroundState->getBorderRadius() : 0; + return NULL != mForeground ? mForeground->getBorderRadius() : 0; } RectangleDrawable* UINode::setBorderEnabled( bool enabled ) { @@ -543,7 +553,7 @@ UINode* UINode::setFlags( const Uint32& flags ) { if ( NULL == mBackground && ( flags & UI_FILL_BACKGROUND ) ) setBackgroundFillEnabled( true ); - if ( NULL == mForegroundState && ( flags & UI_FILL_FOREGROUND ) ) + if ( NULL == mForeground && ( flags & UI_FILL_FOREGROUND ) ) setForegroundFillEnabled( true ); if ( NULL == mBorder && ( flags & UI_BORDER ) ) @@ -583,8 +593,8 @@ void UINode::drawBackground() { } void UINode::drawForeground() { - if ( ( mFlags & UI_FILL_FOREGROUND ) && NULL != mForegroundState ) { - mForegroundState->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), + if ( ( mFlags & UI_FILL_FOREGROUND ) && NULL != mForeground ) { + mForeground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), Sizef( eefloor( mSize.getWidth() ), eefloor( mSize.getHeight() ) ), (Uint32)mAlpha ); } @@ -648,11 +658,11 @@ UINodeDrawable* UINode::getBackground() { } UINodeDrawable* UINode::getForeground() { - if ( NULL == mForegroundState ) { - mForegroundState = UINodeDrawable::New( this ); + if ( NULL == mForeground ) { + mForeground = UINodeDrawable::New( this ); } - return mForegroundState; + return mForeground; } RectangleDrawable* UINode::getBorder() { diff --git a/src/eepp/ui/uinodedrawable.cpp b/src/eepp/ui/uinodedrawable.cpp index 00b3de313..947b5ce51 100644 --- a/src/eepp/ui/uinodedrawable.cpp +++ b/src/eepp/ui/uinodedrawable.cpp @@ -1,7 +1,12 @@ #include +#include #include +#include +#include #include +#include #include +#include #include #include #include @@ -71,6 +76,12 @@ void UINodeDrawable::setDrawable( int index, Drawable* drawable, bool ownIt ) { } } +void UINodeDrawable::setDrawable( int index, const std::string& drawable ) { + if ( drawable != getLayer( index )->getDrawableRef() ) { + getLayer( index )->setDrawable( drawable ); + } +} + void UINodeDrawable::setDrawablePositionX( int index, const std::string& positionX ) { getLayer( index )->setPositionX( positionX ); } @@ -321,6 +332,10 @@ Drawable* UINodeDrawable::LayerDrawable::getDrawable() const { return mDrawable; } +const std::string& UINodeDrawable::LayerDrawable::getDrawableRef() const { + return mDrawableRef; +} + void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& ownIt ) { if ( drawable == mDrawable ) return; @@ -337,6 +352,7 @@ void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& } mDrawable = drawable; + mDrawableRef = ""; mOwnsDrawable = ownIt; invalidate(); @@ -354,6 +370,215 @@ void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& } } +void UINodeDrawable::LayerDrawable::setDrawable( const std::string& drawableRef ) { + bool ownIt; + Drawable* drawable = createDrawable( drawableRef, mSize, ownIt ); + + if ( NULL != drawable ) { + setDrawable( drawable, ownIt ); + + mDrawableRef = drawableRef; + } +} + +Drawable* UINodeDrawable::LayerDrawable::createDrawable( const std::string& value, + const Sizef& size, bool& ownIt ) { + FunctionString functionType = FunctionString::parse( value ); + Drawable* res = NULL; + ownIt = false; + + if ( !functionType.isEmpty() ) { + if ( functionType.getName() == "linear-gradient" && + functionType.getParameters().size() >= 2 ) { + RectangleDrawable* drawable = RectangleDrawable::New(); + RectColors rectColors; + + const std::vector& params( functionType.getParameters() ); + + if ( Color::isColorString( params.at( 0 ) ) && params.size() >= 2 ) { + rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 0 ) ); + rectColors.BottomLeft = rectColors.BottomRight = + Color::fromString( params.at( 1 ) ); + } else if ( params.size() >= 3 ) { + std::string direction = params.at( 0 ); + String::toLowerInPlace( direction ); + + if ( direction == "to bottom" ) { + rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 1 ) ); + rectColors.BottomLeft = rectColors.BottomRight = + Color::fromString( params.at( 2 ) ); + } else if ( direction == "to left" ) { + rectColors.TopLeft = rectColors.BottomLeft = + Color::fromString( params.at( 2 ) ); + rectColors.TopRight = rectColors.BottomRight = + Color::fromString( params.at( 1 ) ); + } else if ( direction == "to right" ) { + rectColors.TopLeft = rectColors.BottomLeft = + Color::fromString( params.at( 1 ) ); + rectColors.TopRight = rectColors.BottomRight = + Color::fromString( params.at( 2 ) ); + } else if ( direction == "to top" ) { + rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 2 ) ); + rectColors.BottomLeft = rectColors.BottomRight = + Color::fromString( params.at( 1 ) ); + } else { + rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 1 ) ); + rectColors.BottomLeft = rectColors.BottomRight = + Color::fromString( params.at( 2 ) ); + } + } else { + mContainer->setBackgroundColor( Color::fromString( params.at( 0 ) ) ); + return NULL; + } + + drawable->setRectColors( rectColors ); + ownIt = true; + return drawable; + } else if ( functionType.getName() == "circle" && + functionType.getParameters().size() >= 1 ) { + CircleDrawable* drawable = CircleDrawable::New(); + + const std::vector& params( functionType.getParameters() ); + + CSS::StyleSheetLength length( params[0] ); + drawable->setRadius( + mContainer->getOwner()->convertLength( length, size.getWidth() / 2.f ) ); + + if ( params.size() >= 2 ) { + drawable->setColor( Color::fromString( params[1] ) ); + } + + if ( params.size() >= 3 ) { + std::string fillMode( String::toLower( params[2] ) ); + if ( fillMode == "line" || fillMode == "solid" || fillMode == "fill" ) { + drawable->setFillMode( fillMode == "line" ? DRAW_LINE : DRAW_FILL ); + } + } + + drawable->setOffset( drawable->getSize() / 2.f ); + ownIt = true; + return drawable; + } else if ( functionType.getName() == "rectangle" && + functionType.getParameters().size() >= 1 ) { + RectangleDrawable* drawable = RectangleDrawable::New(); + RectColors rectColors; + std::vector colors; + + const std::vector& params( functionType.getParameters() ); + + for ( size_t i = 0; i < params.size(); i++ ) { + std::string param( String::toLower( params[i] ) ); + + if ( param == "solid" || param == "fill" ) { + drawable->setFillMode( DRAW_FILL ); + } else if ( String::startsWith( param, "line" ) ) { + drawable->setFillMode( DRAW_LINE ); + + std::vector parts( String::split( param, ' ' ) ); + + if ( parts.size() >= 2 ) { + CSS::StyleSheetLength length( parts[1] ); + drawable->setLineWidth( + mContainer->getOwner()->convertLength( length, size.getWidth() ) ); + } + } else if ( param.find( "º" ) != std::string::npos ) { + String::replaceAll( param, "º", "" ); + Float floatVal; + if ( String::fromString( floatVal, param ) ) { + drawable->setRotation( floatVal ); + } + } else if ( Color::isColorString( param ) ) { + colors.push_back( Color::fromString( param ) ); + } else { + int intVal = 0; + + if ( String::fromString( intVal, param ) ) { + drawable->setCorners( intVal ); + } + } + } + + if ( colors.size() > 0 ) { + while ( colors.size() < 4 ) { + colors.push_back( colors[colors.size() - 1] ); + }; + + rectColors.TopLeft = colors[0]; + rectColors.BottomLeft = colors[1]; + rectColors.BottomRight = colors[2]; + rectColors.TopRight = colors[3]; + drawable->setRectColors( rectColors ); + ownIt = true; + return drawable; + } else { + eeSAFE_DELETE( drawable ); + } + } else if ( functionType.getName() == "triangle" && + functionType.getParameters().size() >= 2 ) { + TriangleDrawable* drawable = TriangleDrawable::New(); + std::vector colors; + std::vector vertices; + + const std::vector& params( functionType.getParameters() ); + + for ( size_t i = 0; i < params.size(); i++ ) { + std::string param( String::toLower( params[i] ) ); + + if ( Color::isColorString( param ) ) { + colors.push_back( Color::fromString( param ) ); + } else { + std::vector vertex( String::split( param, ',' ) ); + + if ( vertex.size() == 3 ) { + for ( size_t v = 0; v < vertex.size(); v++ ) { + vertex[v] = String::trim( vertex[v] ); + std::vector coords( String::split( vertex[v], ' ' ) ); + + if ( coords.size() == 2 ) { + CSS::StyleSheetLength posX( coords[0] ); + CSS::StyleSheetLength posY( coords[1] ); + vertices.push_back( Vector2f( + mContainer->getOwner()->convertLength( posX, size.getWidth() ), + mContainer->getOwner()->convertLength( posY, + size.getHeight() ) ) ); + } + } + } + } + } + + if ( vertices.size() == 3 && !colors.empty() ) { + Triangle2f triangle; + + for ( size_t i = 0; i < 3; i++ ) { + triangle.V[i] = vertices[i]; + } + + if ( colors.size() == 3 ) { + drawable->setTriangleColors( colors[0], colors[1], colors[2] ); + } else { + drawable->setColor( colors[0] ); + } + + drawable->setTriangle( triangle ); + ownIt = true; + return drawable; + } else { + eeSAFE_DELETE( drawable ); + } + } else if ( functionType.getName() == "url" && functionType.getParameters().size() >= 1 ) { + if ( NULL != ( res = DrawableSearcher::searchByName( + functionType.getParameters().at( 0 ) ) ) ) { + return res; + } + } + } else if ( NULL != ( res = DrawableSearcher::searchByName( value ) ) ) { + return res; + } + + return NULL; +} + const Vector2f& UINodeDrawable::LayerDrawable::getOffset() const { if ( mNeedsUpdate ) const_cast( this )->update(); @@ -563,6 +788,10 @@ void UINodeDrawable::LayerDrawable::update() { if ( mDrawable == NULL ) return; + if ( !mDrawableRef.empty() ) { + setDrawable( mDrawableRef ); + } + mDrawableSize = calcDrawableSize( mSizeEq ); mOffset = calcPosition( mPositionX + " " + mPositionY ); diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index af81e8d1e..7cd0efc2e 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -1,10 +1,5 @@ #include -#include -#include -#include -#include #include -#include #include #include #include @@ -399,6 +394,13 @@ void UIWidget::onVisibilityChange() { void UIWidget::onSizeChange() { UINode::onSizeChange(); + + if ( mBackground != NULL ) + mBackground->invalidate(); + + if ( mForeground != NULL ) + mForeground->invalidate(); + notifyLayoutAttrChange(); } @@ -501,6 +503,58 @@ bool UIWidget::isSceneNodeLoading() const { : false; } +Float UIWidget::getPropertyRelativeTargetContainerLength( + const PropertyRelativeTarget& relativeTarget, const Float& defaultValue ) { + Float containerLength = defaultValue; + switch ( relativeTarget ) { + case PropertyRelativeTarget::ContainingBlockWidth: + containerLength = getParent()->getPixelsSize().getWidth(); + break; + case PropertyRelativeTarget::ContainingBlockHeight: + containerLength = getParent()->getPixelsSize().getHeight(); + case PropertyRelativeTarget::LocalBlockWidth: + containerLength = getPixelsSize().getWidth(); + break; + case PropertyRelativeTarget::LocalBlockHeight: + containerLength = getPixelsSize().getHeight(); + break; + case PropertyRelativeTarget::BackgroundWidth: + containerLength = getPixelsSize().getWidth() - + getBackground()->getLayer( 0 )->getDrawableSize().getWidth(); + break; + case PropertyRelativeTarget::BackgroundHeight: + containerLength = getPixelsSize().getHeight() - + getBackground()->getLayer( 0 )->getDrawableSize().getHeight(); + break; + case PropertyRelativeTarget::ForegroundWidth: + containerLength = getPixelsSize().getWidth() - + getForeground()->getLayer( 0 )->getDrawableSize().getWidth(); + break; + case PropertyRelativeTarget::ForegroundHeight: + containerLength = getPixelsSize().getHeight() - + getForeground()->getLayer( 0 )->getDrawableSize().getHeight(); + break; + default: + break; + } + return containerLength; +} + +Float UIWidget::lengthFromValue( const std::string& value, + const PropertyRelativeTarget& relativeTarget, + const Float& defaultValue, const Float& defaultContainerValue ) { + Float containerLength = + getPropertyRelativeTargetContainerLength( relativeTarget, defaultValue ); + return convertLength( CSS::StyleSheetLength( value, defaultValue ), containerLength ); +} + +Float UIWidget::lengthFromValue( const StyleSheetProperty& property, const Float& defaultValue, + const Float& defaultContainerValue ) { + return lengthFromValue( property.getValue(), + property.getPropertyDefinition()->getRelativeTarget(), defaultValue, + defaultContainerValue ); +} + const Rectf& UIWidget::getPadding() const { return mPadding; } @@ -578,19 +632,15 @@ const std::vector& UIWidget::getStyleSheetClasses() const { } UIWidget* UIWidget::getStyleSheetParentElement() const { - return NULL != mParentCtrl && mParentCtrl->isWidget() - ? mParentCtrl->asType() - : NULL; + return NULL != mParentCtrl && mParentCtrl->isWidget() ? mParentCtrl->asType() : NULL; } UIWidget* UIWidget::getStyleSheetPreviousSiblingElement() const { - return NULL != mPrev && mPrev->isWidget() ? mPrev->asType() - : NULL; + return NULL != mPrev && mPrev->isWidget() ? mPrev->asType() : NULL; } UIWidget* UIWidget::getStyleSheetNextSiblingElement() const { - return NULL != mNext && mNext->isWidget() ? mNext->asType() - : NULL; + return NULL != mNext && mNext->isWidget() ? mNext->asType() : NULL; } const std::vector& UIWidget::getStyleSheetPseudoClasses() const { @@ -1077,10 +1127,7 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { setBackgroundColor( attribute.asColor() ); break; case PropertyId::BackgroundImage: - drawablePropertySet( "background", attribute.getValue(), - [&]( Drawable* drawable, bool ownIt, int index ) { - setBackgroundDrawable( drawable, ownIt, index ); - } ); + setBackgroundDrawable( attribute.getValue(), 0 ); break; case PropertyId::BackgroundRepeat: setBackgroundRepeat( attribute.value(), 0 ); @@ -1092,10 +1139,7 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { setForegroundColor( attribute.asColor() ); break; case PropertyId::ForegroundImage: - drawablePropertySet( "foreground", attribute.getValue(), - [&]( Drawable* drawable, bool ownIt, int index ) { - setForegroundDrawable( drawable, ownIt, index ); - } ); + setForegroundDrawable( attribute.getValue(), 0 ); break; case PropertyId::ForegroundRadius: setForegroundRadius( attribute.asUint() ); @@ -1107,10 +1151,10 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { setBorderColor( attribute.asColor() ); break; case PropertyId::BorderWidth: - setBorderWidth( PixelDensity::dpToPxI( attribute.asDpDimensionI( "1" ) ) ); + setBorderWidth( lengthFromValue( attribute, PixelDensity::dpToPx( 1 ) ) ); break; case PropertyId::BorderRadius: - setBorderRadius( PixelDensity::dpToPxI( attribute.asDpDimensionUint() ) ); + setBorderRadius( lengthFromValue( attribute ) ); break; case PropertyId::Visible: setVisible( attribute.asBool() ); @@ -1257,8 +1301,12 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { } else { unsetFlags( UI_AUTO_SIZE ); setLayoutWidthRule( LayoutSizeRule::Fixed ); - setInternalWidth( PixelDensity::toDpFromStringI( val ) ); - onSizeChange(); + Float newVal = eefloor( PixelDensity::toDpFromString( val ) ); + if ( !( newVal == 0 && getLayoutWeight() != 0 && + getParent()->isType( UI_TYPE_LINEAR_LAYOUT ) ) ) { + setInternalWidth( newVal ); + onSizeChange(); + } } break; } @@ -1276,8 +1324,12 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { } else { unsetFlags( UI_AUTO_SIZE ); setLayoutHeightRule( LayoutSizeRule::Fixed ); - setInternalHeight( PixelDensity::toDpFromStringI( val ) ); - onSizeChange(); + Float newVal = eefloor( PixelDensity::toDpFromString( val ) ); + if ( !( newVal == 0 && getLayoutWeight() != 0 && + getParent()->isType( UI_TYPE_LINEAR_LAYOUT ) ) ) { + setInternalHeight( newVal ); + onSizeChange(); + } } break; } @@ -1454,203 +1506,4 @@ std::string UIWidget::getFlagsString() const { return String::join( flagvec, '|' ); } -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() ) { - if ( functionType.getName() == "linear-gradient" && - functionType.getParameters().size() >= 2 ) { - RectangleDrawable* drawable = RectangleDrawable::New(); - RectColors rectColors; - - const std::vector& params( functionType.getParameters() ); - - if ( Color::isColorString( params.at( 0 ) ) && params.size() >= 2 ) { - rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 0 ) ); - rectColors.BottomLeft = rectColors.BottomRight = - Color::fromString( params.at( 1 ) ); - } else if ( params.size() >= 3 ) { - std::string direction = params.at( 0 ); - String::toLowerInPlace( direction ); - - if ( direction == "to bottom" ) { - rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 1 ) ); - rectColors.BottomLeft = rectColors.BottomRight = - Color::fromString( params.at( 2 ) ); - } else if ( direction == "to left" ) { - rectColors.TopLeft = rectColors.BottomLeft = - Color::fromString( params.at( 2 ) ); - rectColors.TopRight = rectColors.BottomRight = - Color::fromString( params.at( 1 ) ); - } else if ( direction == "to right" ) { - rectColors.TopLeft = rectColors.BottomLeft = - Color::fromString( params.at( 1 ) ); - rectColors.TopRight = rectColors.BottomRight = - Color::fromString( params.at( 2 ) ); - } else if ( direction == "to top" ) { - rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 2 ) ); - rectColors.BottomLeft = rectColors.BottomRight = - Color::fromString( params.at( 1 ) ); - } else { - rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 1 ) ); - rectColors.BottomLeft = rectColors.BottomRight = - Color::fromString( params.at( 2 ) ); - } - } else { - return applyProperty( - StyleSheetProperty( propertyName + "-color", params.at( 0 ) ) ); - } - - drawable->setRectColors( rectColors ); - - funcSet( drawable, true, index ); - } else if ( functionType.getName() == "circle" && - functionType.getParameters().size() >= 1 ) { - CircleDrawable* drawable = CircleDrawable::New(); - - const std::vector& params( functionType.getParameters() ); - - CSS::StyleSheetLength length( params[0] ); - drawable->setRadius( convertLength( length, getPixelsSize().getWidth() / 2.f ) ); - - if ( params.size() >= 2 ) { - drawable->setColor( Color::fromString( params[1] ) ); - } - - if ( params.size() >= 3 ) { - std::string fillMode( String::toLower( params[2] ) ); - if ( fillMode == "line" || fillMode == "solid" || fillMode == "fill" ) { - drawable->setFillMode( fillMode == "line" ? DRAW_LINE : DRAW_FILL ); - } - } - - drawable->setOffset( drawable->getSize() / 2.f ); - - funcSet( drawable, true, index ); - } else if ( functionType.getName() == "rectangle" && - functionType.getParameters().size() >= 1 ) { - RectangleDrawable* drawable = RectangleDrawable::New(); - RectColors rectColors; - std::vector colors; - - const std::vector& params( functionType.getParameters() ); - - for ( size_t i = 0; i < params.size(); i++ ) { - std::string param( String::toLower( params[i] ) ); - - if ( param == "solid" || param == "fill" ) { - drawable->setFillMode( DRAW_FILL ); - } else if ( String::startsWith( param, "line" ) ) { - drawable->setFillMode( DRAW_LINE ); - - std::vector parts( String::split( param, ' ' ) ); - - if ( parts.size() >= 2 ) { - CSS::StyleSheetLength length( parts[1] ); - drawable->setLineWidth( - convertLength( length, getPixelsSize().getWidth() ) ); - } - } else if ( param.find( "º" ) != std::string::npos ) { - String::replaceAll( param, "º", "" ); - Float floatVal; - if ( String::fromString( floatVal, param ) ) { - drawable->setRotation( floatVal ); - } - } else if ( Color::isColorString( param ) ) { - colors.push_back( Color::fromString( param ) ); - } else { - int intVal = 0; - - if ( String::fromString( intVal, param ) ) { - drawable->setCorners( intVal ); - } - } - } - - if ( colors.size() > 0 ) { - while ( colors.size() < 4 ) { - colors.push_back( colors[colors.size() - 1] ); - }; - - rectColors.TopLeft = colors[0]; - rectColors.BottomLeft = colors[1]; - rectColors.BottomRight = colors[2]; - rectColors.TopRight = colors[3]; - drawable->setRectColors( rectColors ); - - funcSet( drawable, true, index ); - } else { - eeSAFE_DELETE( drawable ); - } - } else if ( functionType.getName() == "triangle" && - functionType.getParameters().size() >= 2 ) { - TriangleDrawable* drawable = TriangleDrawable::New(); - std::vector colors; - std::vector vertices; - - const std::vector& params( functionType.getParameters() ); - - for ( size_t i = 0; i < params.size(); i++ ) { - std::string param( String::toLower( params[i] ) ); - - if ( Color::isColorString( param ) ) { - colors.push_back( Color::fromString( param ) ); - } else { - std::vector vertex( String::split( param, ',' ) ); - - if ( vertex.size() == 3 ) { - for ( size_t v = 0; v < vertex.size(); v++ ) { - vertex[v] = String::trim( vertex[v] ); - std::vector coords( String::split( vertex[v], ' ' ) ); - - if ( coords.size() == 2 ) { - CSS::StyleSheetLength posX( coords[0] ); - CSS::StyleSheetLength posY( coords[1] ); - vertices.push_back( Vector2f( - convertLength( posX, getPixelsSize().getWidth() ), - convertLength( posY, getPixelsSize().getHeight() ) ) ); - } - } - } - } - } - - if ( vertices.size() == 3 && !colors.empty() ) { - Triangle2f triangle; - - for ( size_t i = 0; i < 3; i++ ) { - triangle.V[i] = vertices[i]; - } - - if ( colors.size() == 3 ) { - drawable->setTriangleColors( colors[0], colors[1], colors[2] ); - } else { - drawable->setColor( colors[0] ); - } - - drawable->setTriangle( triangle ); - - funcSet( drawable, true, index ); - } else { - eeSAFE_DELETE( drawable ); - } - } else if ( functionType.getName() == "url" && functionType.getParameters().size() >= 1 ) { - if ( NULL != ( res = DrawableSearcher::searchByName( - functionType.getParameters().at( 0 ) ) ) ) { - funcSet( res, res->getDrawableType() == Drawable::SPRITE, index ); - } - } - } else if ( NULL != ( res = DrawableSearcher::searchByName( value ) ) ) { - funcSet( res, res->getDrawableType() == Drawable::SPRITE, index ); - } else { - attributeSet = false; - } - - return attributeSet; -} - }} // namespace EE::UI