Added border-radius support.

Added alias support for shorthands.
Added BorderType::Outline.
Added support for background/foreground masks.
Fixes to the border rendering.
Several fixes and clean up.
This commit is contained in:
Martín Lucas Golini
2020-03-13 05:10:53 -03:00
parent 359685cb6f
commit 3921f81ced
22 changed files with 740 additions and 198 deletions

View File

@@ -11,14 +11,21 @@ Widget {
width: 200px;
height: 200px;
background-color: white;
border-radius: 100dp;
border-top-left-radius: 50px 100px;
border-top-right-radius: 100px 50px;
border-bottom-left-radius: 100px 50%;
border-bottom-right-radius: 100% 50%;
border-color: rgba(255, 0, 0, 0.5);
border-width: 0dp;
border-type: inside;
border-width: 20dp;
border-type: outline;
transition: all 0.5s;
clip: true;
}
Widget:hover {
border-radius: 20dp;
border-top-left-radius: 5px 10px;
border-top-right-radius: 10px 5px;
border-bottom-left-radius: 100px 100%;
border-bottom-right-radius: 100% 30%;
border-width: 10dp;
}

View File

@@ -13,8 +13,9 @@ using namespace EE::System;
using namespace EE::Math;
namespace EE { namespace UI {
class UINode;
enum class BorderType : Uint32 { Inside, Outside };
enum class BorderType : Uint32 { Inside, Outside, Outline };
struct EE_API Border {
int width = 0;
@@ -35,6 +36,12 @@ struct EE_API Borders {
Border bottom;
BorderRadiuses radius;
static std::string fromBorderType( const BorderType& borderType );
static BorderType toBorderType( const std::string& borderType );
static Sizef radiusFromString( UINode* node, const std::string& val );
/** Creates the border geometry into the VertexBuffer provided. The VertexBuffer must be a
* a EE::Graphics::PrimitiveType::PRIMITIVE_TRIANGLE_STRIP with VERTEX_FLAGS_PRIMITIVE flags. */
static void createBorders( VertexBuffer* vbo, const Borders& borders, const Vector2f& pos,
@@ -46,6 +53,23 @@ struct EE_API Borders {
const Vector2f& pos, const Sizef& size, const Color& color );
};
struct BorderRadiuseStr {
std::string topLeft;
std::string topRight;
std::string bottomLeft;
std::string bottomRight;
};
struct BorderStr {
struct {
std::string left;
std::string right;
std::string top;
std::string bottom;
} width;
BorderRadiuseStr radius;
};
}} // namespace EE::UI
#endif // EE_BORDER_HPP

View File

@@ -6,18 +6,6 @@
namespace EE { namespace UI { namespace CSS {
/* Shorthands:
*
* background
* foreground
* margin
* layout_margin
* padding
* background-position
* rotation-origin-point
* scale-origin-point
* */
enum class PropertyId : Uint32 {
Id = String::hash( "id" ),
Class = String::hash( "class" ),
@@ -38,9 +26,6 @@ enum class PropertyId : Uint32 {
ForegroundRepeat = String::hash( "foreground-repeat" ),
ForegroundSize = String::hash( "foreground-size" ),
ForegroundRadius = String::hash( "foreground-radius" ),
BorderColor = String::hash( "border-color" ),
BorderWidth = String::hash( "border-width" ),
BorderRadius = String::hash( "border-radius" ),
Visible = String::hash( "visible" ),
Enabled = String::hash( "enabled" ),
Theme = String::hash( "theme" ),
@@ -207,7 +192,19 @@ enum class PropertyId : Uint32 {
PageTransitionDuration = String::hash( "page-transition-duration" ),
TimingFunction = String::hash( "timing-function" ),
PageLocked = String::hash( "page-locked" ),
BorderType = String::hash( "border-type" )
BorderType = String::hash( "border-type" ),
BorderLeftColor = String::hash( "border-left-color" ),
BorderRightColor = String::hash( "border-right-color" ),
BorderTopColor = String::hash( "border-top-color" ),
BorderBottomColor = String::hash( "border-bottom-color" ),
BorderLeftWidth = String::hash( "border-left-width" ),
BorderRightWidth = String::hash( "border-right-width" ),
BorderTopWidth = String::hash( "border-top-width" ),
BorderBottomWidth = String::hash( "border-bottom-width" ),
BorderTopLeftRadius = String::hash( "border-top-left-radius" ),
BorderTopRightRadius = String::hash( "border-top-right-radius" ),
BorderBottomLeftRadius = String::hash( "border-bottom-left-radius" ),
BorderBottomRightRadius = String::hash( "border-bottom-right-radius" ),
};
enum class PropertyType : Uint32 {
@@ -217,6 +214,7 @@ enum class PropertyType : Uint32 {
NumberInt,
NumberFloat,
NumberLength,
RadiusLength,
Color,
Vector2,
BackgroundSize,
@@ -236,7 +234,9 @@ enum class PropertyRelativeTarget : Uint32 {
BackgroundWidth,
BackgroundHeight,
ForegroundWidth,
ForegroundHeight
ForegroundHeight,
LocalBlockRadiusWidth,
LocalBlockRadiusHeight
};
class EE_API PropertyDefinition {

View File

@@ -19,7 +19,10 @@ enum class ShorthandId : Uint32 {
LayoutMarginUnderscore = String::hash( "layout_margin" ),
FillerPadding = String::hash( "filler-padding" ),
RotationOriginPoint = String::hash( "rotation-origin-point" ),
ScaleOriginPoint = String::hash( "scale-origin-point" )
ScaleOriginPoint = String::hash( "scale-origin-point" ),
BorderColor = String::hash( "border-color" ),
BorderWidth = String::hash( "border-width" ),
BorderRadius = String::hash( "border-radius" )
};
enum class ShorthandType : Uint32 {
@@ -27,7 +30,9 @@ enum class ShorthandType : Uint32 {
Background,
Vector2,
SingleValueVector,
BackgroundPosition
BackgroundPosition,
BorderBox,
Radius
};
class ShorthandDefinition {
@@ -46,6 +51,16 @@ class ShorthandDefinition {
const Uint32& getId() const;
ShorthandDefinition& addAlias( const std::string& alias );
bool isAlias( const std::string& alias ) const;
bool isAlias( const Uint32& id ) const;
bool isDefinition( const std::string& name ) const;
bool isDefinition( const Uint32& id ) const;
ShorthandId getShorthandId() const;
const std::vector<std::string>& getProperties() const;
@@ -55,6 +70,8 @@ class ShorthandDefinition {
protected:
std::string mName;
Uint32 mId;
std::vector<std::string> mAliases;
std::vector<Uint32> mAliasesHash;
std::vector<std::string> mProperties;
ShorthandType mType;
};

View File

@@ -39,7 +39,7 @@ class EE_API StyleSheetPropertiesParser {
int readComment( ReadState& rs, std::size_t pos, std::string& buffer, const std::string& str );
void addProperty( const std::string& name, std::string value );
void addProperty( std::string name, std::string value );
};
}}} // namespace EE::UI::CSS

View File

@@ -8,11 +8,13 @@ using namespace EE::Graphics;
namespace EE { namespace UI {
class UINode;
class EE_API UIBackgroundDrawable : public Drawable {
public:
static UIBackgroundDrawable* New();
static UIBackgroundDrawable* New( UINode* owner );
UIBackgroundDrawable();
UIBackgroundDrawable( UINode* owner );
virtual ~UIBackgroundDrawable();
@@ -30,13 +32,31 @@ class EE_API UIBackgroundDrawable : public Drawable {
const BorderRadiuses& getRadiuses() const;
bool hasRadius() const;
void setRadiuses( const BorderRadiuses& radiuses );
void setRadius( const Uint32& radius );
Int32 getRadius() const;
void invalidate();
void setTopWidth( const std::string& topWidth );
void setBottomWidth( const std::string& bottomWidth );
void setTopLeftRadius( const std::string& radius );
void setTopRightRadius( const std::string& radius );
void setBottomLeftRadius( const std::string& radius );
void setBottomRightRadius( const std::string& radius );
protected:
UINode* mOwner;
BorderRadiuseStr mRadiusesStr;
VertexBuffer* mVertexBuffer;
Sizef mSize;
BorderRadiuses mRadiuses;
@@ -50,6 +70,8 @@ class EE_API UIBackgroundDrawable : public Drawable {
virtual void onPositionChange();
void update();
void updateRadiuses();
};
}} // namespace EE::UI

View File

@@ -6,11 +6,13 @@
namespace EE { namespace UI {
class UINode;
class EE_API UIBorderDrawable : public Drawable {
public:
static UIBorderDrawable* New();
static UIBorderDrawable* New( UINode* owner );
UIBorderDrawable();
UIBorderDrawable( UINode* owner );
virtual ~UIBorderDrawable();
@@ -54,9 +56,31 @@ class EE_API UIBorderDrawable : public Drawable {
void setBorderType( const BorderType& borderType );
void invalidate();
void setLeftWidth( const std::string& leftWidth );
void setRightWidth( const std::string& rightWidth );
void setTopWidth( const std::string& topWidth );
void setBottomWidth( const std::string& bottomWidth );
void setTopLeftRadius( const std::string& radius );
void setTopRightRadius( const std::string& radius );
void setBottomLeftRadius( const std::string& radius );
void setBottomRightRadius( const std::string& radius );
const Borders& getBorders() const;
protected:
UINode* mOwner;
VertexBuffer* mVertexBuffer;
Borders mBorders;
BorderStr mBorderStr;
BorderType mBorderType;
Sizef mSize;
bool mNeedsUpdate;
@@ -69,6 +93,8 @@ class EE_API UIBorderDrawable : public Drawable {
virtual void onPositionChange();
void update();
void updateBorders();
};
}} // namespace EE::UI

View File

@@ -3,7 +3,9 @@
#include <eepp/scene/node.hpp>
#include <eepp/ui/base.hpp>
#include <eepp/ui/css/propertydefinition.hpp>
#include <eepp/ui/css/stylesheetlength.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/uihelper.hpp>
#include <eepp/ui/uiskin.hpp>
#include <eepp/ui/uiskinstate.hpp>
@@ -108,6 +110,14 @@ class EE_API UINode : public Node {
UINode* setBorderRadius( const unsigned int& corners );
UINode* setTopLeftRadius( const std::string& radius );
UINode* setTopRightRadius( const std::string& radius );
UINode* setBottomLeftRadius( const std::string& radius );
UINode* setBottomRightRadius( const std::string& radius );
Uint32 getBorderRadius() const;
UINodeDrawable* setForegroundFillEnabled( bool enabled );
@@ -208,11 +218,34 @@ class EE_API UINode : public Node {
virtual void setFocus();
Float
getPropertyRelativeTargetContainerLength( const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0,
const Uint32& propertyIndex = 0 );
virtual Float convertLength( const CSS::StyleSheetLength& length,
const Float& containerLength );
Float convertLengthAsDp( const CSS::StyleSheetLength& length, const Float& containerLength );
Float lengthFromValue( const std::string& value,
const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0, const Float& defaultContainerValue = 0,
const Uint32& propertyIndex = 0 );
Float lengthFromValue( const CSS::StyleSheetProperty& property, const Float& defaultValue = 0,
const Float& defaultContainerValue = 0 );
Float lengthFromValueAsDp( const std::string& value,
const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0,
const Float& defaultContainerValue = 0,
const Uint32& propertyIndex = 0 );
Float lengthFromValueAsDp( const CSS::StyleSheetProperty& property,
const Float& defaultValue = 0,
const Float& defaultContainerValue = 0 );
UISceneNode* getUISceneNode();
protected:
@@ -250,7 +283,7 @@ class EE_API UINode : public Node {
virtual void onThemeLoaded();
virtual void onChildCountChange( Node * child, const bool& removed );
virtual void onChildCountChange( Node* child, const bool& removed );
virtual Uint32 onCalculateDrag( const Vector2f& position, const Uint32& flags );

View File

@@ -159,6 +159,8 @@ class EE_API UINodeDrawable : public Drawable {
UINode* getOwner() { return mOwner; }
UIBackgroundDrawable& getBackgroundDrawable();
protected:
UINode* mOwner;
UIBackgroundDrawable mBackgroundColor;

View File

@@ -205,28 +205,6 @@ class EE_API UIWidget : public UINode {
bool isSceneNodeLoading() const;
Float
getPropertyRelativeTargetContainerLength( const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0,
const Uint32& propertyIndex = 0 );
Float lengthFromValue( const std::string& value,
const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0, const Float& defaultContainerValue = 0,
const Uint32& propertyIndex = 0 );
Float lengthFromValue( const StyleSheetProperty& property, const Float& defaultValue = 0,
const Float& defaultContainerValue = 0 );
Float lengthFromValueAsDp( const std::string& value,
const CSS::PropertyRelativeTarget& relativeTarget,
const Float& defaultValue = 0,
const Float& defaultContainerValue = 0,
const Uint32& propertyIndex = 0 );
Float lengthFromValueAsDp( const StyleSheetProperty& property, const Float& defaultValue = 0,
const Float& defaultContainerValue = 0 );
const std::string& getMinWidthEq() const;
void setMinWidthEq( const std::string& minWidthEq );

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2020-03-10T03:56:40. -->
<!-- Written by QtCreator 4.11.1, 2020-03-13T05:08:12. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@@ -1531,7 +1531,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">eepp-UIEditor-debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="QString" key="RunConfiguration.Arguments">-x assets/layouts/test2.xml -c assets/layouts/test2.css -u</value>
<value type="QString" key="RunConfiguration.Arguments">-x assets/layouts/test.xml -c assets/layouts/test.css -u</value>
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>

View File

@@ -1,5 +1,6 @@
#include <eepp/graphics/vertexbuffer.hpp>
#include <eepp/ui/border.hpp>
#include <eepp/ui/uinode.hpp>
namespace EE { namespace UI {
@@ -90,6 +91,36 @@ static void borderAddArc( VertexBuffer* vbo, Vector2f pos, Float radiW, Float ra
}
}
std::string Borders::fromBorderType( const BorderType& borderType ) {
switch ( borderType ) {
case BorderType::Outside:
return "outside";
case BorderType::Outline:
return "outline";
case BorderType::Inside:
default:
return "inside";
}
}
BorderType Borders::toBorderType( const std::string& borderType ) {
if ( borderType == "outside" ) {
return BorderType::Outside;
} else if ( borderType == "outline" ) {
return BorderType::Outline;
}
return BorderType::Inside;
}
Sizef Borders::radiusFromString( UINode* node, const std::string& val ) {
auto split = String::split( val, ' ' );
Sizef size;
size.x = node->lengthFromValue( split[0], CSS::PropertyRelativeTarget::LocalBlockRadiusWidth );
size.y = node->lengthFromValue( split[split.size() > 1 ? 1 : 0],
CSS::PropertyRelativeTarget::LocalBlockRadiusHeight );
return size;
}
void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Vector2f& pos,
const Sizef& size ) {
vbo->clear();
@@ -132,10 +163,10 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
endAngle, borders.top.color, borderTop,
Vector2f( pos.x + borderLeft, pos.y + borderTop ) );
} else {
vbo->addVertex( Vector2f( pos.x, pos.y ) );
vbo->addColor( borders.top.color );
vbo->addVertex( Vector2f( pos.x + borderLeft, pos.y + borderTop ) );
vbo->addColor( borders.top.color );
vbo->addVertex( Vector2f( pos.x, pos.y ) );
vbo->addColor( borders.top.color );
}
if ( rightW ) {
@@ -160,10 +191,10 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, rightW, rightH, startAngle, endAngle, borders.top.color,
borderTop, basePos );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y ) );
vbo->addColor( borders.top.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight, pos.y + borderTop ) );
vbo->addColor( borders.top.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y ) );
vbo->addColor( borders.top.color );
}
}
@@ -182,10 +213,10 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, Vector2f( pos.x + size.getWidth() - topW, pos.y + topH ), topW, topH,
startAngle, endAngle, borders.right.color, borderRight, basePos );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y ) );
vbo->addColor( borders.right.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight, pos.y + borderTop ) );
vbo->addColor( borders.right.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y ) );
vbo->addColor( borders.right.color );
}
if ( bottomH ) {
@@ -212,11 +243,11 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderRight, basePos );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() ) );
vbo->addColor( borders.right.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight,
pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.right.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() ) );
vbo->addColor( borders.right.color );
}
}
@@ -238,12 +269,11 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
Vector2f( pos.x + size.getWidth() - rightW, pos.y + size.getHeight() - rightH ),
rightW, rightH, startAngle, endAngle, borders.bottom.color, borderBottom, basePos );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() ) );
vbo->addColor( borders.bottom.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight,
pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.bottom.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() ) );
vbo->addColor( borders.bottom.color );
}
if ( leftW ) {
@@ -269,11 +299,11 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, leftW, leftH, startAngle, endAngle, borders.bottom.color,
borderBottom, basePos );
} else {
vbo->addVertex( Vector2f( pos.x, pos.y + size.getHeight() ) );
vbo->addColor( borders.bottom.color );
vbo->addVertex(
Vector2f( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.bottom.color );
vbo->addVertex( Vector2f( pos.x, pos.y + size.getHeight() ) );
vbo->addColor( borders.bottom.color );
}
}
@@ -293,18 +323,18 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
bottomW, bottomH, startAngle, endAngle, borders.left.color, borderLeft,
basePos );
} else {
vbo->addVertex( Vector2f( pos.x, pos.y + size.getHeight() ) );
vbo->addColor( borders.left.color );
vbo->addVertex(
Vector2f( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.left.color );
vbo->addVertex( Vector2f( pos.x, pos.y + size.getHeight() ) );
vbo->addColor( borders.left.color );
}
if ( topW ) {
double startAngle = 180;
double endAngle = 225;
Vector2f basePos( pos.x + borderLeft, pos.y + borderTop );
Vector2f tPos( pos.x + topW, pos.y + topW );
Vector2f tPos( pos.x + topW, pos.y + topH );
if ( topW > borderLeft ) {
vbo->addVertex(
@@ -324,10 +354,10 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, topW, topH, startAngle, endAngle, borders.left.color,
borderLeft, basePos );
} else {
vbo->addVertex( Vector2f( pos.x, pos.y ) );
vbo->addColor( borders.left.color );
vbo->addVertex( Vector2f( pos.x + borderLeft, pos.y + borderTop ) );
vbo->addColor( borders.left.color );
vbo->addVertex( Vector2f( pos.x, pos.y ) );
vbo->addColor( borders.left.color );
}
}
}

View File

@@ -60,7 +60,7 @@ PropertySpecification::registerShorthand( const std::string& name,
const ShorthandDefinition* PropertySpecification::getShorthand( const Uint32& id ) const {
for ( auto& shorthand : mShorthands ) {
if ( shorthand->getId() == id ) {
if ( shorthand->isDefinition( id ) ) {
return shorthand;
}
}

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <eepp/core.hpp>
#include <eepp/system/color.hpp>
#include <eepp/ui/css/shorthanddefinition.hpp>
@@ -15,7 +16,15 @@ ShorthandDefinition* ShorthandDefinition::New( const std::string& name,
ShorthandDefinition::ShorthandDefinition( const std::string& name,
const std::vector<std::string>& properties,
const ShorthandType& shorthandType ) :
mName( name ), mId( String::hash( name ) ), mProperties( properties ), mType( shorthandType ) {}
mName( name ), mId( String::hash( name ) ), mProperties( properties ), mType( shorthandType ) {
for ( auto& sep : {"-", "_"} ) {
if ( mName.find( sep ) != std::string::npos ) {
std::string alias( name );
String::replaceAll( alias, sep, "" );
addAlias( alias );
}
}
}
const std::string& ShorthandDefinition::getName() const {
return mName;
@@ -47,6 +56,28 @@ static int getIndexEndingWith( const std::vector<std::string>& vec, const std::s
return -1;
}
ShorthandDefinition& ShorthandDefinition::addAlias( const std::string& alias ) {
mAliases.push_back( alias );
mAliasesHash.push_back( String::hash( alias ) );
return *this;
}
bool ShorthandDefinition::isAlias( const std::string& alias ) const {
return isAlias( String::hash( alias ) );
}
bool ShorthandDefinition::isAlias( const Uint32& id ) const {
return std::find( mAliasesHash.begin(), mAliasesHash.end(), id ) != mAliasesHash.end();
}
bool ShorthandDefinition::isDefinition( const std::string& name ) const {
return isDefinition( String::hash( name ) );
}
bool ShorthandDefinition::isDefinition( const Uint32& id ) const {
return mId == id || isAlias( id );
}
std::vector<StyleSheetProperty>
ShorthandDefinition::parseShorthand( const ShorthandDefinition* shorthand, std::string value ) {
value = String::trim( value );
@@ -100,12 +131,11 @@ ShorthandDefinition::parseShorthand( const ShorthandDefinition* shorthand, std::
auto values = String::split( value, ' ' );
if ( values.size() >= 2 ) {
properties.emplace_back( StyleSheetProperty( propNames[0], values[0] ) );
properties.emplace_back( StyleSheetProperty( propNames[1], values[1] ) );
} else if ( values.size() == 1 ) {
properties.emplace_back( StyleSheetProperty( propNames[0], values[0] ) );
properties.emplace_back( StyleSheetProperty( propNames[1], values[0] ) );
if ( !values.empty() ) {
for ( size_t i = 0; i < propNames.size(); i++ ) {
properties.emplace_back(
StyleSheetProperty( propNames[0], values[i % values.size()] ) );
}
}
break;
}
@@ -157,6 +187,35 @@ ShorthandDefinition::parseShorthand( const ShorthandDefinition* shorthand, std::
break;
}
case ShorthandType::BorderBox: {
auto ltrbSplit = String::split( value, " ", "", "(\"" );
if ( !ltrbSplit.empty() ) {
for ( size_t i = 0; i < propNames.size(); i++ ) {
properties.emplace_back(
StyleSheetProperty( propNames[i], ltrbSplit[i % ltrbSplit.size()] ) );
}
}
break;
}
case ShorthandType::Radius: {
String::trim( value );
auto splits = String::split( value, '/' );
auto widths = String::split( splits[0], ' ' );
std::vector<std::string> heights;
if ( splits.size() >= 2 ) {
heights = String::split( splits[1], ' ' );
}
if ( !widths.empty() ) {
for ( size_t i = 0; i < propNames.size(); i++ ) {
std::string val = widths[i % widths.size()];
if ( !heights.empty() ) {
val += " " + heights[i % heights.size()];
}
properties.emplace_back( StyleSheetProperty( propNames[i], val ) );
}
}
break;
}
default:
break;
}

View File

@@ -134,7 +134,10 @@ int StyleSheetPropertiesParser::readComment( StyleSheetPropertiesParser::ReadSta
return pos;
}
void StyleSheetPropertiesParser::addProperty( const std::string& name, std::string value ) {
void StyleSheetPropertiesParser::addProperty( std::string name, std::string value ) {
String::toLowerInPlace( name );
String::trimInPlace( name );
if ( StyleSheetSpecification::instance()->isShorthand( name ) ) {
std::vector<StyleSheetProperty> properties = ShorthandDefinition::parseShorthand(
StyleSheetSpecification::instance()->getShorthand( name ), value );

View File

@@ -1,5 +1,6 @@
#include <algorithm>
#include <eepp/math/easing.hpp>
#include <eepp/ui/border.hpp>
#include <eepp/ui/css/stylesheetpropertyanimation.hpp>
#include <eepp/ui/css/stylesheetspecification.hpp>
#include <eepp/ui/uinodedrawable.hpp>
@@ -65,6 +66,18 @@ void StyleSheetPropertyAnimation::tweenProperty( UIWidget* widget, const Float&
}
break;
}
case PropertyType::RadiusLength: {
Sizef start( Borders::radiusFromString( widget, startValue ) );
Sizef end( Borders::radiusFromString( widget, endValue ) );
Float x = easingCb[timingFunction]( normalizedProgress, start.x, end.x - start.x, 1.f );
Float y = easingCb[timingFunction]( normalizedProgress, start.y, end.y - start.y, 1.f );
widget->applyProperty( StyleSheetProperty(
property, String::fromFloat( x ) + " " + String::fromFloat( y ), propertyIndex ) );
if ( isDone ) {
widget->applyProperty( StyleSheetProperty( property, endValue, propertyIndex ) );
}
break;
}
case PropertyType::Vector2: {
Vector2f start( StyleSheetProperty( property, startValue ).asVector2f() );
Vector2f end( StyleSheetProperty( property, endValue ).asVector2f() );
@@ -153,6 +166,7 @@ bool StyleSheetPropertyAnimation::animationSupported( const PropertyType& type )
case PropertyType::Vector2:
case PropertyType::BackgroundSize:
case PropertyType::ForegroundSize:
case PropertyType::RadiusLength:
return true;
default:
return false;

View File

@@ -7,13 +7,6 @@ SINGLETON_DECLARE_IMPLEMENTATION( StyleSheetSpecification )
StyleSheetSpecification::StyleSheetSpecification() {
// TODO: Add correct "background" and "foreground" shorthand.
// TODO: Support border-color top right bottom left.
// TODO: Support border-radius top right bottom left.
// TODO: Create a rule to set the border position against its box.
// Something like: "border-type", with the following options:
// inside: The border is drawn inside the box.
// outside: The border is drawn outside the box.
// over: The border is drawn in the middle point of inside and outside.
registerDefaultProperties();
registerDefaultNodeSelectors();
}
@@ -97,9 +90,6 @@ void StyleSheetSpecification::registerDefaultProperties() {
.setType( PropertyType::ForegroundSize )
.setIndexed();
registerProperty( "foreground-radius", "0px" ).setType( PropertyType::NumberLength );
registerProperty( "border-color", "" ).setType( PropertyType::Color );
registerProperty( "border-width", "" ).setType( PropertyType::NumberLength );
registerProperty( "border-radius", "0px" ).setType( PropertyType::NumberLength );
registerProperty( "visible", "true" ).setType( PropertyType::Bool );
registerProperty( "enabled", "true" ).setType( PropertyType::Bool );
registerProperty( "theme", "" );
@@ -343,7 +333,29 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerProperty( "timing-function", "linear" ).setType( PropertyType::String );
registerProperty( "page-locked", "" ).setType( PropertyType::Bool );
registerProperty( "border-type", "inside" ).setType( PropertyType::String );
registerProperty( "border-left-color", "transparent" ).setType( PropertyType::Color );
registerProperty( "border-right-color", "transparent" ).setType( PropertyType::Color );
registerProperty( "border-top-color", "transparent" ).setType( PropertyType::Color );
registerProperty( "border-bottom-color", "transparent" ).setType( PropertyType::Color );
registerProperty( "border-left-width", "0" )
.setType( PropertyType::NumberLength )
.setRelativeTarget( PropertyRelativeTarget::LocalBlockRadiusWidth );
registerProperty( "border-right-width", "0" )
.setType( PropertyType::NumberLength )
.setRelativeTarget( PropertyRelativeTarget::LocalBlockRadiusWidth );
registerProperty( "border-top-width", "0" )
.setType( PropertyType::NumberLength )
.setRelativeTarget( PropertyRelativeTarget::LocalBlockRadiusWidth );
registerProperty( "border-bottom-width", "0" )
.setType( PropertyType::NumberLength )
.setRelativeTarget( PropertyRelativeTarget::LocalBlockRadiusWidth );
registerProperty( "border-top-left-radius", "0" ).setType( PropertyType::RadiusLength );
registerProperty( "border-top-right-radius", "0" ).setType( PropertyType::RadiusLength );
registerProperty( "border-bottom-left-radius", "0" ).setType( PropertyType::RadiusLength );
registerProperty( "border-bottom-right-radius", "0" ).setType( PropertyType::RadiusLength );
// Shorthands
registerShorthand( "margin", {"margin-top", "margin-right", "margin-bottom", "margin-left"},
@@ -370,6 +382,19 @@ void StyleSheetSpecification::registerDefaultProperties() {
ShorthandType::BackgroundPosition );
registerShorthand( "foreground-position", {"foreground-position-x", "foreground-position-y"},
ShorthandType::BackgroundPosition );
registerShorthand(
"border-color",
{"border-top-color", "border-right-color", "border-bottom-color", "border-left-color"},
ShorthandType::BorderBox );
registerShorthand(
"border-width",
{"border-top-width", "border-right-width", "border-bottom-width", "border-left-width"},
ShorthandType::BorderBox );
registerShorthand( "border-radius",
{"border-top-left-radius", "border-top-right-radius",
"border-bottom-right-radius", "border-bottom-left-radius"},
ShorthandType::Radius );
/*registerShorthand( "rotation-origin-point", {"rotation-origin-point-x",
"rotation-origin-point-y"}, ShorthandType::Vector2 ); registerShorthand(
"scale-origin-point", {"scale-origin-point-x", "scale-origin-point-y"},

View File

@@ -1,15 +1,17 @@
#include <eepp/graphics/vertexbuffer.hpp>
#include <eepp/ui/uibackgrounddrawable.hpp>
#include <eepp/ui/uinode.hpp>
namespace EE { namespace UI {
UIBackgroundDrawable* UIBackgroundDrawable::New() {
return eeNew( UIBackgroundDrawable, () );
UIBackgroundDrawable* UIBackgroundDrawable::New( UINode* owner ) {
return eeNew( UIBackgroundDrawable, ( owner ) );
}
UIBackgroundDrawable::UIBackgroundDrawable() :
UIBackgroundDrawable::UIBackgroundDrawable( UINode* owner ) :
Drawable( UIBACKGROUNDDRAWABLE ),
mVertexBuffer( VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN ) ),
mOwner( owner ),
mVertexBuffer( VertexBuffer::NewVertexArray( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN ) ),
mNeedsUpdate( false ),
mColorNeedsUpdate( false ) {}
@@ -17,9 +19,13 @@ UIBackgroundDrawable::~UIBackgroundDrawable() {
eeSAFE_DELETE( mVertexBuffer );
}
void UIBackgroundDrawable::draw() {}
void UIBackgroundDrawable::draw() {
draw( mPosition, mSize );
}
void UIBackgroundDrawable::draw( const Vector2f& position ) {}
void UIBackgroundDrawable::draw( const Vector2f& position ) {
draw( position, mSize );
}
void UIBackgroundDrawable::draw( const Vector2f& position, const Sizef& size ) {
if ( mPosition != position ) {
@@ -36,6 +42,8 @@ void UIBackgroundDrawable::draw( const Vector2f& position, const Sizef& size ) {
update();
}
// TODO: Optimize rendering for square backgrounds (no radius)
// It will be cheaper to use the batch renderer for those cases.
mVertexBuffer->bind();
mVertexBuffer->draw();
mVertexBuffer->unbind();
@@ -49,6 +57,13 @@ const BorderRadiuses& UIBackgroundDrawable::getRadiuses() const {
return mRadiuses;
}
bool UIBackgroundDrawable::hasRadius() const {
return !mRadiusesStr.topLeft.empty() || !mRadiusesStr.topRight.empty() ||
!mRadiusesStr.bottomLeft.empty() || !mRadiusesStr.bottomRight.empty() ||
mRadiuses.topLeft != Sizef::Zero || mRadiuses.topRight != Sizef::Zero ||
mRadiuses.bottomLeft != Sizef::Zero || mRadiuses.bottomRight != Sizef::Zero;
}
void UIBackgroundDrawable::setRadiuses( const BorderRadiuses& radiuses ) {
mRadiuses = radiuses;
mNeedsUpdate = true;
@@ -68,10 +83,42 @@ void UIBackgroundDrawable::setRadius( const Uint32& radius ) {
}
}
void UIBackgroundDrawable::setTopLeftRadius( const std::string& radius ) {
if ( mRadiusesStr.topLeft != radius ) {
mRadiusesStr.topLeft = radius;
mNeedsUpdate = true;
}
}
void UIBackgroundDrawable::setTopRightRadius( const std::string& radius ) {
if ( mRadiusesStr.topRight != radius ) {
mRadiusesStr.topRight = radius;
mNeedsUpdate = true;
}
}
void UIBackgroundDrawable::setBottomLeftRadius( const std::string& radius ) {
if ( mRadiusesStr.bottomLeft != radius ) {
mRadiusesStr.bottomLeft = radius;
mNeedsUpdate = true;
}
}
void UIBackgroundDrawable::setBottomRightRadius( const std::string& radius ) {
if ( mRadiusesStr.bottomRight != radius ) {
mRadiusesStr.bottomRight = radius;
mNeedsUpdate = true;
}
}
Int32 UIBackgroundDrawable::getRadius() const {
return mRadiuses.topLeft.x;
}
void UIBackgroundDrawable::invalidate() {
mNeedsUpdate = true;
}
void UIBackgroundDrawable::setSize( const Sizef& size ) {
if ( size != mSize ) {
mSize = size;
@@ -96,9 +143,24 @@ void UIBackgroundDrawable::onPositionChange() {
}
void UIBackgroundDrawable::update() {
updateRadiuses();
Borders::createBackground( mVertexBuffer, mRadiuses, mPosition, mSize, mColor );
mColorNeedsUpdate = false;
mNeedsUpdate = false;
}
void UIBackgroundDrawable::updateRadiuses() {
if ( !mRadiusesStr.topLeft.empty() )
mRadiuses.topLeft = Borders::radiusFromString( mOwner, mRadiusesStr.topLeft );
if ( !mRadiusesStr.topRight.empty() )
mRadiuses.topRight = Borders::radiusFromString( mOwner, mRadiusesStr.topRight );
if ( !mRadiusesStr.bottomLeft.empty() )
mRadiuses.bottomLeft = Borders::radiusFromString( mOwner, mRadiusesStr.bottomLeft );
if ( !mRadiusesStr.bottomRight.empty() )
mRadiuses.bottomRight = Borders::radiusFromString( mOwner, mRadiusesStr.bottomRight );
}
}} // namespace EE::UI

View File

@@ -1,15 +1,17 @@
#include <eepp/core.hpp>
#include <eepp/graphics/vertexbuffer.hpp>
#include <eepp/ui/uiborderdrawable.hpp>
#include <eepp/ui/uinode.hpp>
namespace EE { namespace UI {
UIBorderDrawable* UIBorderDrawable::New() {
return eeNew( UIBorderDrawable, () );
UIBorderDrawable* UIBorderDrawable::New( UINode* owner ) {
return eeNew( UIBorderDrawable, ( owner ) );
}
UIBorderDrawable::UIBorderDrawable() :
UIBorderDrawable::UIBorderDrawable( UINode* owner ) :
Drawable( UIBORDERDRAWABLE ),
mOwner( owner ),
mVertexBuffer( VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_STRIP ) ),
mBorderType( BorderType::Inside ),
mNeedsUpdate( false ),
@@ -19,9 +21,13 @@ UIBorderDrawable::~UIBorderDrawable() {
eeSAFE_DELETE( mVertexBuffer );
}
void UIBorderDrawable::draw() {}
void UIBorderDrawable::draw() {
draw( mPosition, mSize );
}
void UIBorderDrawable::draw( const Vector2f& position ) {}
void UIBorderDrawable::draw( const Vector2f& position ) {
draw( position, mSize );
}
void UIBorderDrawable::draw( const Vector2f& position, const Sizef& size ) {
if ( mPosition != position ) {
@@ -34,6 +40,7 @@ void UIBorderDrawable::draw( const Vector2f& position, const Sizef& size ) {
mNeedsUpdate = true;
}
// TODO: Implement color update.
if ( mNeedsUpdate || mColorNeedsUpdate ) {
update();
}
@@ -98,8 +105,8 @@ Color UIBorderDrawable::getColorRight() const {
}
void UIBorderDrawable::setColorRight( const Color& colorRight ) {
if ( mBorders.left.color != colorRight ) {
mBorders.left.color = colorRight;
if ( mBorders.right.color != colorRight ) {
mBorders.right.color = colorRight;
mColorNeedsUpdate = true;
}
}
@@ -137,6 +144,70 @@ void UIBorderDrawable::setBorderType( const BorderType& borderType ) {
}
}
void UIBorderDrawable::invalidate() {
mNeedsUpdate = true;
}
void UIBorderDrawable::setLeftWidth( const std::string& leftWidth ) {
if ( mBorderStr.width.left != leftWidth ) {
mBorderStr.width.left = leftWidth;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setRightWidth( const std::string& rightWidth ) {
if ( mBorderStr.width.right != rightWidth ) {
mBorderStr.width.right = rightWidth;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setTopWidth( const std::string& topWidth ) {
if ( mBorderStr.width.top != topWidth ) {
mBorderStr.width.top = topWidth;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setBottomWidth( const std::string& bottomWidth ) {
if ( mBorderStr.width.bottom != bottomWidth ) {
mBorderStr.width.bottom = bottomWidth;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setTopLeftRadius( const std::string& radius ) {
if ( mBorderStr.radius.topLeft != radius ) {
mBorderStr.radius.topLeft = radius;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setTopRightRadius( const std::string& radius ) {
if ( mBorderStr.radius.topRight != radius ) {
mBorderStr.radius.topRight = radius;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setBottomLeftRadius( const std::string& radius ) {
if ( mBorderStr.radius.bottomLeft != radius ) {
mBorderStr.radius.bottomLeft = radius;
mNeedsUpdate = true;
}
}
void UIBorderDrawable::setBottomRightRadius( const std::string& radius ) {
if ( mBorderStr.radius.bottomRight != radius ) {
mBorderStr.radius.bottomRight = radius;
mNeedsUpdate = true;
}
}
const Borders& UIBorderDrawable::getBorders() const {
return mBorders;
}
void UIBorderDrawable::onAlphaChange() {
mBorders.left.color.a = mBorders.right.color.a = mBorders.top.color.a =
mBorders.bottom.color.a = mColor.a;
@@ -155,6 +226,8 @@ void UIBorderDrawable::onPositionChange() {
}
void UIBorderDrawable::update() {
updateBorders();
switch ( mBorderType ) {
case BorderType::Outside: {
Vector2f pos( mPosition );
@@ -184,10 +257,70 @@ void UIBorderDrawable::update() {
Borders::createBorders( mVertexBuffer, mBorders, mPosition, mSize );
break;
}
case BorderType::Outline: {
Vector2f pos( mPosition );
Sizef size( mSize );
if ( mBorders.top.width > 0 ) {
pos.y -= mBorders.top.width * 0.5f;
}
if ( mBorders.left.width > 0 ) {
pos.x -= mBorders.left.width * 0.5f;
}
if ( mBorders.right.width > 0 ) {
size.x += mBorders.right.width;
}
if ( mBorders.bottom.width > 0 ) {
size.y += mBorders.bottom.width;
}
Borders::createBorders( mVertexBuffer, mBorders, pos, size );
break;
}
}
mColorNeedsUpdate = false;
mNeedsUpdate = false;
}
void UIBorderDrawable::updateBorders() {
if ( !mBorderStr.width.left.empty() ) {
mBorders.left.width = mOwner->lengthFromValue(
mBorderStr.width.left, CSS::PropertyRelativeTarget::LocalBlockRadiusWidth );
}
if ( !mBorderStr.width.right.empty() ) {
mBorders.right.width = mOwner->lengthFromValue(
mBorderStr.width.right, CSS::PropertyRelativeTarget::LocalBlockRadiusWidth );
}
if ( !mBorderStr.width.top.empty() ) {
mBorders.top.width = mOwner->lengthFromValue(
mBorderStr.width.top, CSS::PropertyRelativeTarget::LocalBlockRadiusHeight );
}
if ( !mBorderStr.width.bottom.empty() ) {
mBorders.bottom.width = mOwner->lengthFromValue(
mBorderStr.width.bottom, CSS::PropertyRelativeTarget::LocalBlockRadiusHeight );
}
if ( !mBorderStr.radius.topLeft.empty() )
mBorders.radius.topLeft = Borders::radiusFromString( mOwner, mBorderStr.radius.topLeft );
if ( !mBorderStr.radius.topRight.empty() )
mBorders.radius.topRight = Borders::radiusFromString( mOwner, mBorderStr.radius.topRight );
if ( !mBorderStr.radius.bottomLeft.empty() )
mBorders.radius.bottomLeft =
Borders::radiusFromString( mOwner, mBorderStr.radius.bottomLeft );
if ( !mBorderStr.radius.bottomRight.empty() )
mBorders.radius.bottomRight =
Borders::radiusFromString( mOwner, mBorderStr.radius.bottomRight );
}
}} // namespace EE::UI

View File

@@ -245,7 +245,7 @@ void UINode::updateDebugData() {
}
text += String::format( "X: %2.4f Y: %2.4f\nW: %2.4f H: %2.4f", mDpPos.x, mDpPos.y,
mDpSize.x, mDpSize.y );
mDpSize.x, mDpSize.y );
widget->setTooltipText( text );
}
@@ -448,6 +448,30 @@ UINode* UINode::setBorderRadius( const unsigned int& corners ) {
return this;
}
UINode* UINode::setTopLeftRadius( const std::string& radius ) {
setBorderEnabled( true )->setTopLeftRadius( radius );
setBackgroundFillEnabled( true )->getBackgroundDrawable().setTopLeftRadius( radius );
return this;
}
UINode* UINode::setTopRightRadius( const std::string& radius ) {
setBorderEnabled( true )->setTopRightRadius( radius );
setBackgroundFillEnabled( true )->getBackgroundDrawable().setTopRightRadius( radius );
return this;
}
UINode* UINode::setBottomLeftRadius( const std::string& radius ) {
setBorderEnabled( true )->setBottomLeftRadius( radius );
setBackgroundFillEnabled( true )->getBackgroundDrawable().setBottomLeftRadius( radius );
return this;
}
UINode* UINode::setBottomRightRadius( const std::string& radius ) {
setBorderEnabled( true )->setBottomRightRadius( radius );
setBackgroundFillEnabled( true )->getBackgroundDrawable().setBottomRightRadius( radius );
return this;
}
Uint32 UINode::getBorderRadius() const {
return NULL != mBorder ? mBorder->getRadius() : 0;
}
@@ -664,7 +688,7 @@ UINodeDrawable* UINode::getForeground() {
UIBorderDrawable* UINode::getBorder() {
if ( NULL == mBorder ) {
mBorder = UIBorderDrawable::New();
mBorder = UIBorderDrawable::New( this );
mBorder->setColor( Color::Transparent );
mBorder->setLineWidth( PixelDensity::dpToPx( 1 ) );
}
@@ -1024,6 +1048,86 @@ void UINode::setFocus() {
getEventDispatcher()->setFocusControl( this );
}
Float UINode::getPropertyRelativeTargetContainerLength(
const CSS::PropertyRelativeTarget& relativeTarget, const Float& defaultValue,
const Uint32& propertyIndex ) {
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( propertyIndex )->getDrawableSize().getWidth();
break;
case PropertyRelativeTarget::BackgroundHeight:
containerLength =
getPixelsSize().getHeight() -
getBackground()->getLayer( propertyIndex )->getDrawableSize().getHeight();
break;
case PropertyRelativeTarget::ForegroundWidth:
containerLength =
getPixelsSize().getWidth() -
getForeground()->getLayer( propertyIndex )->getDrawableSize().getWidth();
break;
case PropertyRelativeTarget::ForegroundHeight:
containerLength =
getPixelsSize().getHeight() -
getForeground()->getLayer( propertyIndex )->getDrawableSize().getHeight();
break;
case PropertyRelativeTarget::LocalBlockRadiusWidth:
containerLength = getPixelsSize().getWidth() * 0.5f;
break;
case PropertyRelativeTarget::LocalBlockRadiusHeight:
containerLength = getPixelsSize().getHeight() * 0.5f;
break;
default:
break;
}
return containerLength;
}
Float UINode::lengthFromValue( const std::string& value,
const PropertyRelativeTarget& relativeTarget,
const Float& defaultValue, const Float& defaultContainerValue,
const Uint32& propertyIndex ) {
Float containerLength =
getPropertyRelativeTargetContainerLength( relativeTarget, defaultValue, propertyIndex );
return convertLength( CSS::StyleSheetLength( value, defaultValue ), containerLength );
}
Float UINode::lengthFromValue( const CSS::StyleSheetProperty& property, const Float& defaultValue,
const Float& defaultContainerValue ) {
return lengthFromValue( property.getValue(),
property.getPropertyDefinition()->getRelativeTarget(), defaultValue,
defaultContainerValue, property.getIndex() );
}
Float UINode::lengthFromValueAsDp( const std::string& value,
const PropertyRelativeTarget& relativeTarget,
const Float& defaultValue, const Float& defaultContainerValue,
const Uint32& propertyIndex ) {
Float containerLength =
getPropertyRelativeTargetContainerLength( relativeTarget, defaultValue, propertyIndex );
return convertLengthAsDp( CSS::StyleSheetLength( value, defaultValue ), containerLength );
}
Float UINode::lengthFromValueAsDp( const CSS::StyleSheetProperty& property,
const Float& defaultValue, const Float& defaultContainerValue ) {
return lengthFromValue( property.getValue(),
property.getPropertyDefinition()->getRelativeTarget(), defaultValue,
defaultContainerValue, property.getIndex() );
}
Uint32 UINode::onFocus() {
pushState( UIState::StateFocus );

View File

@@ -31,6 +31,7 @@ UINodeDrawable* UINodeDrawable::New( UINode* owner ) {
UINodeDrawable::UINodeDrawable( UINode* owner ) :
Drawable( Drawable::UINODEDRAWABLE ),
mOwner( owner ),
mBackgroundColor( owner ),
mNeedsUpdate( true ),
mClipEnabled( false ) {
mBackgroundColor.setColor( Color::Transparent );
@@ -123,6 +124,11 @@ void UINodeDrawable::setClipEnabled( bool clipEnabled ) {
void UINodeDrawable::invalidate() {
mNeedsUpdate = true;
mBackgroundColor.invalidate();
}
UIBackgroundDrawable& UINodeDrawable::getBackgroundDrawable() {
return mBackgroundColor;
}
Sizef UINodeDrawable::getSize() {
@@ -169,6 +175,16 @@ void UINodeDrawable::draw( const Vector2f& position, const Sizef& size, const Ui
}
}
bool masked = false;
ClippingMask* clippingMask = GLi->getClippingMask();
if ( !mGroup.empty() && mBackgroundColor.hasRadius() ) {
masked = true;
clippingMask->setMaskMode( ClippingMask::Inclusive );
clippingMask->clearMasks();
clippingMask->appendMask( mBackgroundColor );
clippingMask->stencilMaskEnable();
}
// Draw in reverse order to respect the background-image specification:
// "The background images are drawn on stacking context layers on top of each other. The first
// layer specified is drawn as if it is closest to the user."
@@ -185,6 +201,10 @@ void UINodeDrawable::draw( const Vector2f& position, const Sizef& size, const Ui
}
}
if ( masked ) {
clippingMask->stencilMaskDisable();
}
if ( mClipEnabled )
GLi->getClippingMask()->clipPlaneDisable();
}

View File

@@ -451,6 +451,9 @@ void UIWidget::onVisibilityChange() {
void UIWidget::onSizeChange() {
UINode::onSizeChange();
if ( mBorder != NULL )
mBorder->invalidate();
if ( mBackground != NULL )
mBackground->invalidate();
@@ -559,80 +562,6 @@ bool UIWidget::isSceneNodeLoading() const {
: false;
}
Float UIWidget::getPropertyRelativeTargetContainerLength(
const PropertyRelativeTarget& relativeTarget, const Float& defaultValue,
const Uint32& propertyIndex ) {
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( propertyIndex )->getDrawableSize().getWidth();
break;
case PropertyRelativeTarget::BackgroundHeight:
containerLength =
getPixelsSize().getHeight() -
getBackground()->getLayer( propertyIndex )->getDrawableSize().getHeight();
break;
case PropertyRelativeTarget::ForegroundWidth:
containerLength =
getPixelsSize().getWidth() -
getForeground()->getLayer( propertyIndex )->getDrawableSize().getWidth();
break;
case PropertyRelativeTarget::ForegroundHeight:
containerLength =
getPixelsSize().getHeight() -
getForeground()->getLayer( propertyIndex )->getDrawableSize().getHeight();
break;
default:
break;
}
return containerLength;
}
Float UIWidget::lengthFromValue( const std::string& value,
const PropertyRelativeTarget& relativeTarget,
const Float& defaultValue, const Float& defaultContainerValue,
const Uint32& propertyIndex ) {
Float containerLength =
getPropertyRelativeTargetContainerLength( relativeTarget, defaultValue, propertyIndex );
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, property.getIndex() );
}
Float UIWidget::lengthFromValueAsDp( const std::string& value,
const PropertyRelativeTarget& relativeTarget,
const Float& defaultValue, const Float& defaultContainerValue,
const Uint32& propertyIndex ) {
Float containerLength =
getPropertyRelativeTargetContainerLength( relativeTarget, defaultValue, propertyIndex );
return convertLengthAsDp( CSS::StyleSheetLength( value, defaultValue ), containerLength );
}
Float UIWidget::lengthFromValueAsDp( const StyleSheetProperty& property, const Float& defaultValue,
const Float& defaultContainerValue ) {
return lengthFromValue( property.getValue(),
property.getPropertyDefinition()->getRelativeTarget(), defaultValue,
defaultContainerValue, property.getIndex() );
}
const std::string& UIWidget::getMinWidthEq() const {
return mMinWidthEq;
}
@@ -1162,14 +1091,8 @@ std::string UIWidget::getPropertyString( const PropertyDefinition* propertyDef,
return getForegroundColor().toHexString();
case PropertyId::ForegroundRadius:
return String::toStr( getForegroundRadius() );
case PropertyId::BorderColor:
return getBorderColor().toHexString();
case PropertyId::BorderRadius:
return String::toStr( getBorderRadius() );
case PropertyId::BorderWidth:
return String::fromFloat( getBorderWidth() );
case PropertyId::BorderType:
return getBorder()->getBorderType() == BorderType::Inside ? "inside" : "outside";
return Borders::fromBorderType( setBorderEnabled( true )->getBorderType() );
case PropertyId::SkinColor:
return getSkinColor().toHexString();
case PropertyId::Rotation:
@@ -1224,6 +1147,38 @@ std::string UIWidget::getPropertyString( const PropertyDefinition* propertyDef,
return mMinHeightEq;
case PropertyId::MaxHeight:
return mMaxHeightEq;
case PropertyId::BorderLeftColor:
return setBorderEnabled( true )->getColorLeft().toHexString();
case PropertyId::BorderRightColor:
return setBorderEnabled( true )->getColorRight().toHexString();
case PropertyId::BorderTopColor:
return setBorderEnabled( true )->getColorTop().toHexString();
case PropertyId::BorderBottomColor:
return setBorderEnabled( true )->getColorBottom().toHexString();
case PropertyId::BorderLeftWidth:
return String::fromFloat( setBorderEnabled( true )->getBorders().left.width, "px" );
case PropertyId::BorderRightWidth:
return String::fromFloat( setBorderEnabled( true )->getBorders().right.width, "px" );
case PropertyId::BorderTopWidth:
return String::fromFloat( setBorderEnabled( true )->getBorders().top.width, "px" );
case PropertyId::BorderBottomWidth:
return String::fromFloat( setBorderEnabled( true )->getBorders().bottom.width, "px" );
case PropertyId::BorderTopLeftRadius:
return String::format( "%.2fpx %.2fpx",
setBorderEnabled( true )->getBorders().radius.topLeft.x,
getBorder()->getBorders().radius.topLeft.y );
case PropertyId::BorderTopRightRadius:
return String::format( "%.2fpx %.2fpx",
setBorderEnabled( true )->getBorders().radius.topRight.x,
getBorder()->getBorders().radius.topRight.y );
case PropertyId::BorderBottomLeftRadius:
return String::format( "%.2fpx %.2fpx",
setBorderEnabled( true )->getBorders().radius.bottomLeft.x,
getBorder()->getBorders().radius.bottomLeft.y );
case PropertyId::BorderBottomRightRadius:
return String::format( "%.2fpx %.2fpx",
setBorderEnabled( true )->getBorders().radius.bottomRight.x,
getBorder()->getBorders().radius.bottomRight.y );
default:
break;
}
@@ -1294,18 +1249,9 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::ForegroundSize:
setForegroundSize( attribute.value(), attribute.getIndex() );
break;
case PropertyId::BorderColor:
setBorderColor( attribute.asColor() );
break;
case PropertyId::BorderWidth:
setBorderWidth( lengthFromValue( attribute, PixelDensity::dpToPx( 1 ) ) );
break;
case PropertyId::BorderRadius:
setBorderRadius( lengthFromValue( attribute ) );
break;
case PropertyId::BorderType:
getBorder()->setBorderType( attribute.getValue() == "inside" ? BorderType::Inside
: BorderType::Outside );
setBorderEnabled( true )->setBorderType(
Borders::toBorderType( attribute.getValue() ) );
break;
case PropertyId::Visible:
setVisible( attribute.asBool() );
@@ -1573,6 +1519,43 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::MaxHeight:
setMaxHeightEq( attribute.getValue() );
break;
case PropertyId::BorderLeftColor:
setBorderEnabled( true )->setColorLeft( attribute.asColor() );
invalidateDraw();
break;
case PropertyId::BorderRightColor:
setBorderEnabled( true )->setColorRight( attribute.asColor() );
break;
case PropertyId::BorderTopColor:
setBorderEnabled( true )->setColorTop( attribute.asColor() );
break;
case PropertyId::BorderBottomColor:
setBorderEnabled( true )->setColorBottom( attribute.asColor() );
break;
case PropertyId::BorderLeftWidth:
setBorderEnabled( true )->setLeftWidth( attribute.asString() );
break;
case PropertyId::BorderRightWidth:
setBorderEnabled( true )->setRightWidth( attribute.asString() );
break;
case PropertyId::BorderTopWidth:
setBorderEnabled( true )->setTopWidth( attribute.asString() );
break;
case PropertyId::BorderBottomWidth:
setBorderEnabled( true )->setBottomWidth( attribute.asString() );
break;
case PropertyId::BorderTopLeftRadius:
setTopLeftRadius( attribute.asString() );
break;
case PropertyId::BorderBottomLeftRadius:
setBottomLeftRadius( attribute.asString() );
break;
case PropertyId::BorderTopRightRadius:
setTopRightRadius( attribute.asString() );
break;
case PropertyId::BorderBottomRightRadius:
setBottomRightRadius( attribute.asString() );
break;
default:
attributeSet = false;
break;