Several UI related fixes ( wrong updates, bad rendering, a segfault, and more ).

This commit is contained in:
Martín Lucas Golini
2020-02-11 03:32:26 -03:00
parent 4320841ade
commit 022a04e5f3
10 changed files with 382 additions and 288 deletions

View File

@@ -44,7 +44,9 @@ class EE_API ActionManager {
protected:
std::list<Action*> mActions;
std::list<Action*> mActionsRemoveList;
Mutex mMutex;
bool mUpdating;
};
}} // namespace EE::Scene

View File

@@ -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

View File

@@ -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;

View File

@@ -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 );

View File

@@ -1,6 +1,7 @@
#ifndef EE_UIUIWIDGET_HPP
#define EE_UIUIWIDGET_HPP
#include <eepp/ui/css/propertydefinition.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/stylesheetselector.hpp>
#include <eepp/ui/uinode.hpp>
@@ -185,12 +186,16 @@ class EE_API UIWidget : public UINode {
return reinterpret_cast<T*>( findByTag( tag ) );
}
UIWidget* querySelector( const CSS::StyleSheetSelector& selector );
UIWidget* querySelector( const std::string& selector );
template <typename T> T* querySelector( const std::string& selector ) {
return reinterpret_cast<T*>( querySelector( selector ) );
}
std::vector<UIWidget*> querySelectorAll( const CSS::StyleSheetSelector& selector );
std::vector<UIWidget*> 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<void( Drawable* drawable, bool ownIt, int index )> funcSet );
UIWidget* querySelector( const CSS::StyleSheetSelector& selector );
std::vector<UIWidget*> querySelectorAll( const CSS::StyleSheetSelector& selector );
bool checkPropertyDefinition( const StyleSheetProperty& property );
};

View File

@@ -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 );
}
}
}

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -1,7 +1,12 @@
#include <eepp/core/core.hpp>
#include <eepp/graphics/circledrawable.hpp>
#include <eepp/graphics/drawableresource.hpp>
#include <eepp/graphics/drawablesearcher.hpp>
#include <eepp/graphics/rectangledrawable.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/triangledrawable.hpp>
#include <eepp/math/easing.hpp>
#include <eepp/system/functionstring.hpp>
#include <eepp/ui/css/stylesheetlength.hpp>
#include <eepp/ui/uinode.hpp>
#include <eepp/ui/uinodedrawable.hpp>
@@ -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<std::string>& 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<std::string>& 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<Color> colors;
const std::vector<std::string>& 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<std::string> 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<Color> colors;
std::vector<Vector2f> vertices;
const std::vector<std::string>& 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<std::string> 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<std::string> 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<LayerDrawable*>( 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 );

View File

@@ -1,10 +1,5 @@
#include <algorithm>
#include <eepp/graphics/circledrawable.hpp>
#include <eepp/graphics/drawablesearcher.hpp>
#include <eepp/graphics/rectangledrawable.hpp>
#include <eepp/graphics/triangledrawable.hpp>
#include <eepp/scene/actions/actions.hpp>
#include <eepp/system/functionstring.hpp>
#include <eepp/ui/css/shorthanddefinition.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/stylesheetselector.hpp>
@@ -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<std::string>& UIWidget::getStyleSheetClasses() const {
}
UIWidget* UIWidget::getStyleSheetParentElement() const {
return NULL != mParentCtrl && mParentCtrl->isWidget()
? mParentCtrl->asType<UIWidget>()
: NULL;
return NULL != mParentCtrl && mParentCtrl->isWidget() ? mParentCtrl->asType<UIWidget>() : NULL;
}
UIWidget* UIWidget::getStyleSheetPreviousSiblingElement() const {
return NULL != mPrev && mPrev->isWidget() ? mPrev->asType<UIWidget>()
: NULL;
return NULL != mPrev && mPrev->isWidget() ? mPrev->asType<UIWidget>() : NULL;
}
UIWidget* UIWidget::getStyleSheetNextSiblingElement() const {
return NULL != mNext && mNext->isWidget() ? mNext->asType<UIWidget>()
: NULL;
return NULL != mNext && mNext->isWidget() ? mNext->asType<UIWidget>() : NULL;
}
const std::vector<std::string>& 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<void( Drawable*, bool, int )> 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<std::string>& 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<std::string>& 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<Color> colors;
const std::vector<std::string>& 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<std::string> 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<Color> colors;
std::vector<Vector2f> vertices;
const std::vector<std::string>& 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<std::string> 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<std::string> 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