diff --git a/bin/assets/layouts/test2.css b/bin/assets/layouts/test2.css
new file mode 100644
index 000000000..5c9d1811f
--- /dev/null
+++ b/bin/assets/layouts/test2.css
@@ -0,0 +1,23 @@
+LinearLayout {
+ layout-width: match_parent;
+ layout-height: match_parent;
+ background-color: #cecece;
+}
+
+Widget {
+ clip: false;
+ margin-left: 200dp;
+ margin-top: 200dp;
+ width: 200px;
+ height: 200px;
+ background-color: white;
+ border-radius: 50dp;
+ border-color: rgba(255, 0, 0, 0.5);
+ border-width: 100dp;
+ border-type: outside;
+ transition: all 0.5s;
+}
+
+Widget:hover {
+ border-radius: 0dp;
+}
diff --git a/bin/assets/layouts/test2.xml b/bin/assets/layouts/test2.xml
new file mode 100644
index 000000000..53307a38a
--- /dev/null
+++ b/bin/assets/layouts/test2.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/include/eepp/graphics/drawable.hpp b/include/eepp/graphics/drawable.hpp
index 97f8a603d..ce9492655 100644
--- a/include/eepp/graphics/drawable.hpp
+++ b/include/eepp/graphics/drawable.hpp
@@ -28,6 +28,7 @@ class EE_API Drawable {
SKIN,
UINODEDRAWABLE,
UINODEDRAWABLE_LAYERDRAWABLE,
+ UIBORDERDRAWABLE,
CUSTOM
};
diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp
index 52995f36b..0785423f2 100644
--- a/include/eepp/ui/css/propertydefinition.hpp
+++ b/include/eepp/ui/css/propertydefinition.hpp
@@ -206,7 +206,8 @@ enum class PropertyId : Uint32 {
MaxEdgeResistance = String::hash( "max-edge-resistance" ),
PageTransitionDuration = String::hash( "page-transition-duration" ),
TimingFunction = String::hash( "timing-function" ),
- PageLocked = String::hash( "page-locked" )
+ PageLocked = String::hash( "page-locked" ),
+ BorderType = String::hash( "border-type" )
};
enum class PropertyType : Uint32 {
diff --git a/include/eepp/ui/uiborderdrawable.hpp b/include/eepp/ui/uiborderdrawable.hpp
new file mode 100644
index 000000000..d5aa7e7aa
--- /dev/null
+++ b/include/eepp/ui/uiborderdrawable.hpp
@@ -0,0 +1,113 @@
+#ifndef EE_UI_UIBORDERDRAWABLE_HPP
+#define EE_UI_UIBORDERDRAWABLE_HPP
+
+#include
+#include
+
+namespace EE { namespace Graphics {
+class VertexBuffer;
+}} // namespace EE::Graphics
+using namespace EE::Graphics;
+
+namespace EE { namespace UI {
+
+enum class BorderType : Uint32 { Inside, Outside };
+
+class EE_API UIBorderDrawable : public Drawable {
+ public:
+ static UIBorderDrawable* New();
+
+ UIBorderDrawable();
+
+ virtual ~UIBorderDrawable();
+
+ virtual Sizef getSize();
+
+ virtual void draw();
+
+ virtual void draw( const Vector2f& position );
+
+ virtual void draw( const Vector2f& position, const Sizef& size );
+
+ virtual bool isStateful();
+
+ /** Set the line width to draw primitives */
+ virtual void setLineWidth( const Float& width );
+
+ /** @return The line with to draw primitives */
+ Float getLineWidth() const;
+
+ Int32 getRadius() const;
+
+ void setRadius( const Int32& radius );
+
+ Color getColorLeft() const;
+
+ void setColorLeft( const Color& colorLeft );
+
+ Color getColorRight() const;
+
+ void setColorRight( const Color& colorRight );
+
+ Color getColorTop() const;
+
+ void setColorTop( const Color& colorTop );
+
+ Color getColorBottom() const;
+
+ void setColorBottom( const Color& colorBottom );
+
+ const BorderType& getBorderType() const;
+
+ void setBorderType( const BorderType& borderType );
+
+ protected:
+ VertexBuffer* mVertexBuffer;
+
+ struct Border {
+ int width = 0;
+ Color color;
+ };
+
+ struct BorderRadiuses {
+ Float topLeftX = 0;
+ Float topLeftY = 0;
+ Float topRightX = 0;
+ Float topRightY = 0;
+ Float bottomRightX = 0;
+ Float bottomRightY = 0;
+ Float bottomLeftX = 0;
+ Float bottomLeftY = 0;
+ };
+
+ struct Borders {
+ Border left;
+ Border top;
+ Border right;
+ Border bottom;
+ BorderRadiuses radius;
+ };
+
+ Borders mBorders;
+ BorderType mBorderType;
+ Sizef mSize;
+ bool mNeedsUpdate;
+ bool mColorNeedsUpdate;
+
+ virtual void onAlphaChange();
+
+ virtual void onColorFilterChange();
+
+ virtual void onPositionChange();
+
+ void update();
+
+ void updateColor();
+
+ void createBorders( VertexBuffer* vbo, const UIBorderDrawable::Borders& borders,
+ const Vector2f& pos, const Sizef& size );
+};
+
+}} // namespace EE::UI
+
+#endif // EE_UI_UIBORDERDRAWABLE_HPP
diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp
index 77d6e40a6..ac38cf10b 100644
--- a/include/eepp/ui/uinode.hpp
+++ b/include/eepp/ui/uinode.hpp
@@ -11,7 +11,6 @@
namespace EE { namespace Graphics {
class Drawable;
-class RectangleDrawable;
}} // namespace EE::Graphics
namespace EE { namespace Scene {
@@ -25,6 +24,7 @@ namespace EE { namespace UI {
class UISceneNode;
class UITheme;
class UINodeDrawable;
+class UIBorderDrawable;
class EE_API UINode : public Node {
public:
@@ -132,7 +132,7 @@ class EE_API UINode : public Node {
Uint32 getForegroundRadius() const;
- RectangleDrawable* setBorderEnabled( bool enabled );
+ UIBorderDrawable* setBorderEnabled( bool enabled );
UINode* setBorderColor( const Color& color );
@@ -154,7 +154,7 @@ class EE_API UINode : public Node {
UINodeDrawable* getForeground();
- RectangleDrawable* getBorder();
+ UIBorderDrawable* getBorder();
void setThemeByName( const std::string& Theme );
@@ -223,7 +223,7 @@ class EE_API UINode : public Node {
UISkinState* mSkinState;
UINodeDrawable* mBackground;
UINodeDrawable* mForeground;
- RectangleDrawable* mBorder;
+ UIBorderDrawable* mBorder;
Vector2f mDragPoint;
Uint32 mDragButton;
Color mSkinColor;
diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user
index ec02bbd82..4b248fb5d 100644
--- a/projects/linux/ee.creator.user
+++ b/projects/linux/ee.creator.user
@@ -1,6 +1,6 @@
-
+
EnvironmentId
@@ -79,7 +79,7 @@
{6d057187-158a-4883-8d5b-d470a6b6b025}
10
0
- 0
+ 15
../../make/linux
@@ -1531,7 +1531,7 @@
eepp-UIEditor-debug
ProjectExplorer.CustomExecutableRunConfiguration
- -x assets/layouts/test.xml -c assets/layouts/test.css -u
+ -x assets/layouts/test2.xml -c assets/layouts/test2.css -u
false
true
diff --git a/projects/linux/ee.files b/projects/linux/ee.files
index 5a02faf60..98eb6cc0b 100644
--- a/projects/linux/ee.files
+++ b/projects/linux/ee.files
@@ -311,6 +311,7 @@
../../include/eepp/ui/marginmove/scale.hpp
../../include/eepp/ui/tools/textureatlaseditor.hpp
../../include/eepp/ui/tools/uicolorpicker.hpp
+../../include/eepp/ui/uiborderdrawable.hpp
../../include/eepp/ui/uicheckbox.hpp
../../include/eepp/ui/uicombobox.hpp
../../include/eepp/ui/uicommondialog.hpp
@@ -745,6 +746,7 @@
../../src/eepp/ui/tools/textureatlastextureregioneditor.cpp
../../src/eepp/ui/tools/textureatlastextureregioneditor.hpp
../../src/eepp/ui/tools/uicolorpicker.cpp
+../../src/eepp/ui/uiborderdrawable.cpp
../../src/eepp/ui/uicheckbox.cpp
../../src/eepp/ui/uicombobox.cpp
../../src/eepp/ui/uicommondialog.cpp
diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp
index e2e702abb..f9f04350b 100644
--- a/src/eepp/ui/css/stylesheetspecification.cpp
+++ b/src/eepp/ui/css/stylesheetspecification.cpp
@@ -343,6 +343,7 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerProperty( "timing-function", "linear" ).setType( PropertyType::String );
registerProperty( "page-locked", "" ).setType( PropertyType::Bool );
+ registerProperty( "border-type", "inside" ).setType( PropertyType::String );
// Shorthands
registerShorthand( "margin", {"margin-top", "margin-right", "margin-bottom", "margin-left"},
diff --git a/src/eepp/ui/uiborderdrawable.cpp b/src/eepp/ui/uiborderdrawable.cpp
new file mode 100644
index 000000000..8e61cc050
--- /dev/null
+++ b/src/eepp/ui/uiborderdrawable.cpp
@@ -0,0 +1,492 @@
+#include
+#include
+#include
+#include
+#include
+
+namespace EE { namespace UI {
+
+static void borderAddArc( VertexBuffer* vbo, Vector2f pos, Float radiW, Float radiH,
+ double arcStartAngle, double arcEndAngle, Color color, Float lineW,
+ Vector2f basePos, bool decrease = false ) {
+ Float angleShift = 1;
+ double startAngle = eemin( arcStartAngle, arcEndAngle );
+ double endAngle = eemax( arcStartAngle, arcEndAngle );
+ Vector2f startPos = ( radiW > lineW ) ? pos : basePos;
+
+ if ( decrease ) {
+ for ( double i = endAngle; i >= startAngle; i -= angleShift ) {
+ if ( radiW > lineW ) {
+ vbo->addVertex( Vector2f( pos.x + ( radiW - lineW ) * Math::cosAng( i ),
+ pos.y + ( radiH - lineW ) * Math::sinAng( i ) ) );
+ } else {
+ vbo->addVertex( startPos );
+ }
+
+ vbo->addColor( color );
+
+ if ( i + angleShift < endAngle ) {
+ vbo->addVertex( Vector2f( pos.x + radiW * Math::cosAng( i + angleShift ),
+ pos.y + radiH * Math::sinAng( i + angleShift ) ) );
+ } else {
+ vbo->addVertex( Vector2f( pos.x + radiW * Math::cosAng( endAngle ),
+ pos.y + radiH * Math::sinAng( endAngle ) ) );
+ }
+
+ vbo->addColor( color );
+
+ vbo->addVertex(
+ Vector2f( pos.x + radiW * Math::cosAng( i ), pos.y + radiH * Math::sinAng( i ) ) );
+ vbo->addColor( color );
+
+ if ( radiW > lineW ) {
+ vbo->addVertex( Vector2f( pos.x + ( radiW - lineW ) * Math::cosAng( i ),
+ pos.y + ( radiH - lineW ) * Math::sinAng( i ) ) );
+ } else {
+ vbo->addVertex( startPos );
+ }
+
+ vbo->addColor( color );
+ }
+ } else {
+ for ( double i = startAngle; i <= endAngle; i += angleShift ) {
+ if ( radiW > lineW ) {
+ vbo->addVertex( Vector2f( pos.x + ( radiW - lineW ) * Math::cosAng( i ),
+ pos.y + ( radiH - lineW ) * Math::sinAng( i ) ) );
+ } else {
+ vbo->addVertex( startPos );
+ }
+
+ vbo->addColor( color );
+
+ vbo->addVertex(
+ Vector2f( pos.x + radiW * Math::cosAng( i ), pos.y + radiH * Math::sinAng( i ) ) );
+ vbo->addColor( color );
+
+ if ( i + angleShift < endAngle ) {
+ vbo->addVertex( Vector2f( pos.x + radiW * Math::cosAng( i + angleShift ),
+ pos.y + radiH * Math::sinAng( i + angleShift ) ) );
+ } else {
+ vbo->addVertex( Vector2f( pos.x + radiW * Math::cosAng( endAngle ),
+ pos.y + radiH * Math::sinAng( endAngle ) ) );
+ }
+ vbo->addColor( color );
+
+ if ( radiW > lineW ) {
+ vbo->addVertex( Vector2f( pos.x + ( radiW - lineW ) * Math::cosAng( i ),
+ pos.y + ( radiH - lineW ) * Math::sinAng( i ) ) );
+ } else {
+ vbo->addVertex( startPos );
+ }
+
+ vbo->addColor( color );
+ }
+ }
+}
+
+void UIBorderDrawable::createBorders( VertexBuffer* vbo, const UIBorderDrawable::Borders& borders,
+ const Vector2f& pos, const Sizef& size ) {
+ vbo->clear();
+
+ int borderTop = 0;
+ int borderBottom = 0;
+ int borderLeft = 0;
+ int borderRight = 0;
+ Float halfWidth = size.getWidth() * 0.5f;
+ Float halfHeight = size.getHeight() * 0.5f;
+
+ if ( borders.top.width >= 0 ) {
+ borderTop = eemin( (int)( size.getHeight() * 0.5f ), (int)borders.top.width );
+ }
+
+ if ( borders.bottom.width >= 0 ) {
+ borderBottom = eemin( (int)( size.getHeight() * 0.5f ), (int)borders.bottom.width );
+ }
+
+ if ( borders.left.width >= 0 ) {
+ borderLeft = eemin( (int)( size.getWidth() * 0.5f ), (int)borders.left.width );
+ }
+
+ if ( borders.right.width >= 0 ) {
+ borderRight = eemin( (int)( size.getWidth() * 0.5f ), (int)borders.right.width );
+ }
+
+ // draw top border
+ if ( borderTop ) {
+ double leftW = eemin( halfWidth, eemax( 0.f, borders.radius.topLeftX ) );
+ double rightW = eemin( halfHeight, eemax( 0.f, borders.radius.topRightX ) );
+ double leftH = eemin( halfWidth, eemax( 0.f, borders.radius.topLeftY ) );
+ double rightH = eemin( halfHeight, eemax( 0.f, borders.radius.topRightY ) );
+
+ if ( leftW ) {
+ double endAngle = Math::degrees( M_PI * 3.0 / 2.0 );
+ double startAngle = Math::degrees(
+ M_PI * 3.0 / 2.0 - M_PI / 2.0 / ( (double)borderLeft / (double)borderTop + 1 ) );
+
+ borderAddArc( vbo, Vector2f( pos.x + leftW, pos.y + leftH ), leftW, leftH, startAngle,
+ 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 );
+ }
+
+ if ( rightW ) {
+ vbo->addVertex( Vector2f( pos.x + size.getWidth() - rightW, pos.y ) );
+ vbo->addColor( borders.top.color );
+
+ Vector2f basePos( pos.x + size.getWidth() - borderRight, pos.y + borderTop );
+
+ double startAngle = Math::degrees( M_PI * 3.0 / 2.0 );
+ double endAngle = Math::degrees(
+ M_PI * 3.0 / 2.0 + M_PI / 2.0 / ( (double)borderRight / (double)borderTop + 1 ) );
+
+ borderAddArc( vbo, Vector2f( pos.x + size.getWidth() - rightW, pos.y + rightH ), 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 );
+ }
+ }
+
+ // draw right border
+ if ( borderRight ) {
+ double topW = eemin( halfWidth, eemax( 0.f, borders.radius.topRightX ) );
+ double bottomW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRightX ) );
+ double topH = eemin( halfWidth, eemax( 0.f, borders.radius.topRightY ) );
+ double bottomH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRightY ) );
+
+ if ( topW ) {
+ double endAngle = Math::degrees( 2 * M_PI );
+ double startAngle = Math::degrees(
+ 2 * M_PI - M_PI / 2.0 / ( (double)borderTop / (double)borderRight + 1 ) );
+
+ Vector2f basePos( pos.x + size.getWidth() - borderRight, pos.y + borderTop );
+
+ 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 );
+ }
+
+ if ( bottomH ) {
+ vbo->addVertex(
+ Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() - bottomH ) );
+ vbo->addColor( borders.right.color );
+
+ Vector2f basePos( pos.x + size.getWidth() - borderRight,
+ pos.y + size.getHeight() - borderBottom );
+ double startAngle = Math::degrees( 0 );
+ double endAngle =
+ Math::degrees( M_PI / 2.0 / ( (double)borderBottom / (double)borderRight + 1 ) );
+
+ borderAddArc(
+ vbo,
+ Vector2f( pos.x + size.getWidth() - bottomW, pos.y + size.getHeight() - bottomH ),
+ bottomW, bottomH, startAngle, endAngle, borders.right.color, 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 );
+ }
+ }
+
+ // draw bottom border
+ if ( borderBottom ) {
+ double leftW = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeftX ) );
+ double rightW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRightX ) );
+ double leftH = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeftY ) );
+ double rightH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRightY ) );
+
+ if ( rightW ) {
+ double endAngle = Math::degrees( M_PI / 2.0 );
+ double startAngle = Math::degrees(
+ M_PI / 2.0 - M_PI / 2.0 / ( (double)borderRight / (double)borderBottom + 1 ) );
+ Vector2f basePos( pos.x + size.getWidth() - borderRight,
+ pos.y + size.getHeight() - borderBottom );
+ borderAddArc(
+ vbo,
+ 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 );
+ }
+
+ if ( leftW ) {
+ double startAngle = Math::degrees( M_PI / 2.0 );
+ double endAngle = Math::degrees(
+ M_PI / 2.0 + M_PI / 2.0 / ( (double)borderLeft / (double)borderBottom + 1 ) );
+
+ Vector2f basePos( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom );
+
+ Vector2f tPos( Vector2f( pos.x + leftW, pos.y + size.getHeight() - leftH ) );
+ vbo->addVertex( Vector2f( tPos.x + leftW * Math::cosAng( startAngle ),
+ tPos.y + leftH * Math::sinAng( startAngle ) ) );
+ vbo->addColor( borders.bottom.color );
+
+ 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 );
+ }
+ }
+
+ // draw left border
+ if ( borderLeft ) {
+ double topW = eemin( halfWidth, eemax( 0.f, borders.radius.topLeftX ) );
+ double bottomW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomLeftX ) );
+ double topH = eemin( halfWidth, eemax( 0.f, borders.radius.topLeftY ) );
+ double bottomH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomLeftY ) );
+
+ if ( bottomW ) {
+ Vector2f basePos( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom );
+
+ double endAngle = Math::degrees( M_PI );
+ double startAngle = Math::degrees(
+ M_PI - M_PI / 2.0 / ( (double)borderBottom / (double)borderLeft + 1 ) );
+
+ borderAddArc( vbo, Vector2f( pos.x + bottomW, pos.y + size.getHeight() - bottomH ),
+ 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 );
+ }
+
+ if ( topW ) {
+ double startAngle = Math::degrees( M_PI );
+ double endAngle =
+ Math::degrees( M_PI + M_PI / 2.0 / ( (double)borderTop / (double)borderLeft + 1 ) );
+
+ Vector2f basePos( pos.x + borderLeft, pos.y + borderTop );
+ Vector2f tPos( pos.x + topW, pos.y + topW );
+ vbo->addVertex( Vector2f( tPos.x + topW * Math::cosAng( startAngle ),
+ tPos.y + topH * Math::sinAng( startAngle ) ) );
+ vbo->addColor( borders.left.color );
+
+ 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 );
+ }
+ }
+}
+
+UIBorderDrawable* UIBorderDrawable::New() {
+ return eeNew( UIBorderDrawable, () );
+}
+
+UIBorderDrawable::UIBorderDrawable() :
+ Drawable( UIBORDERDRAWABLE ),
+ mVertexBuffer(
+ VertexBuffer::NewVertexArray( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_STRIP ) ),
+ mBorderType( BorderType::Inside ),
+ mNeedsUpdate( false ),
+ mColorNeedsUpdate( false ) {}
+
+UIBorderDrawable::~UIBorderDrawable() {}
+
+void UIBorderDrawable::draw() {}
+
+void UIBorderDrawable::draw( const Vector2f& position ) {}
+
+void UIBorderDrawable::draw( const Vector2f& position, const Sizef& size ) {
+ if ( mPosition != position ) {
+ mPosition = position;
+ mNeedsUpdate = true;
+ }
+
+ if ( mSize != size ) {
+ mSize = size;
+ mNeedsUpdate = true;
+ }
+
+ if ( mNeedsUpdate || mColorNeedsUpdate ) {
+ update();
+ }
+
+ mVertexBuffer->bind();
+ //GLi->enable( GL_CULL_FACE );
+ mVertexBuffer->draw();
+ //GLi->disable( GL_CULL_FACE );
+ mVertexBuffer->unbind();
+}
+
+bool UIBorderDrawable::isStateful() {
+ return false;
+}
+
+void UIBorderDrawable::setLineWidth( const Float& width ) {
+ if ( mBorders.top.width != width || mBorders.left.width != width ||
+ mBorders.right.width != width || mBorders.bottom.width != width ) {
+ mBorders.top.width = mBorders.left.width = mBorders.right.width = mBorders.bottom.width =
+ width;
+ mNeedsUpdate = true;
+ }
+}
+
+Sizef UIBorderDrawable::getSize() {
+ return mSize;
+}
+
+Float UIBorderDrawable::getLineWidth() const {
+ return mBorders.top.width;
+}
+
+Int32 UIBorderDrawable::getRadius() const {
+ return mBorders.radius.topLeftX;
+}
+
+void UIBorderDrawable::setRadius( const Int32& radius ) {
+ if ( mBorders.radius.topLeftX != radius ) {
+ mBorders.radius.topLeftX = radius;
+ mBorders.radius.topLeftY = radius;
+ mBorders.radius.topRightX = radius;
+ mBorders.radius.topRightY = radius;
+ mBorders.radius.bottomLeftX = radius;
+ mBorders.radius.bottomLeftY = radius;
+ mBorders.radius.bottomRightX = radius;
+ mBorders.radius.bottomRightY = radius;
+ mNeedsUpdate = true;
+ }
+}
+
+Color UIBorderDrawable::getColorLeft() const {
+ return mBorders.left.color;
+}
+
+void UIBorderDrawable::setColorLeft( const Color& colorLeft ) {
+ if ( mBorders.left.color != colorLeft ) {
+ mBorders.left.color = colorLeft;
+ mColorNeedsUpdate = true;
+ }
+}
+
+Color UIBorderDrawable::getColorRight() const {
+ return mBorders.right.color;
+}
+
+void UIBorderDrawable::setColorRight( const Color& colorRight ) {
+ if ( mBorders.left.color != colorRight ) {
+ mBorders.left.color = colorRight;
+ mColorNeedsUpdate = true;
+ }
+}
+
+Color UIBorderDrawable::getColorTop() const {
+ return mBorders.top.color;
+}
+
+void UIBorderDrawable::setColorTop( const Color& colorTop ) {
+ if ( mBorders.top.color != colorTop ) {
+ mBorders.top.color = colorTop;
+ mColorNeedsUpdate = true;
+ }
+}
+
+Color UIBorderDrawable::getColorBottom() const {
+ return mBorders.bottom.color;
+}
+
+void UIBorderDrawable::setColorBottom( const Color& colorBottom ) {
+ if ( mBorders.bottom.color != colorBottom ) {
+ mBorders.bottom.color = colorBottom;
+ mColorNeedsUpdate = true;
+ }
+}
+
+const BorderType& UIBorderDrawable::getBorderType() const {
+ return mBorderType;
+}
+
+void UIBorderDrawable::setBorderType( const BorderType& borderType ) {
+ if ( mBorderType != borderType ) {
+ mBorderType = borderType;
+ mNeedsUpdate = true;
+ }
+}
+
+void UIBorderDrawable::onAlphaChange() {
+ mBorders.left.color.a = mBorders.right.color.a = mBorders.top.color.a =
+ mBorders.bottom.color.a = mColor.a;
+ mColorNeedsUpdate = true;
+}
+
+void UIBorderDrawable::onColorFilterChange() {
+ Drawable::onColorFilterChange();
+ mBorders.left.color = mBorders.right.color = mBorders.top.color = mBorders.bottom.color =
+ mColor;
+ mColorNeedsUpdate = true;
+}
+
+void UIBorderDrawable::onPositionChange() {
+ mNeedsUpdate = true;
+}
+
+void UIBorderDrawable::update() {
+ switch ( mBorderType ) {
+ case BorderType::Outside: {
+ Vector2f pos( mPosition );
+ Sizef size( mSize );
+
+ if ( mBorders.top.width > 0 ) {
+ pos.y -= mBorders.top.width;
+ }
+
+ if ( mBorders.left.width > 0 ) {
+ pos.x -= mBorders.left.width;
+ }
+
+ if ( mBorders.right.width > 0 ) {
+ size.x += mBorders.right.width * 2;
+ }
+
+ if ( mBorders.bottom.width > 0 ) {
+ size.y += mBorders.bottom.width * 2;
+ }
+
+ createBorders( mVertexBuffer, mBorders, pos, size );
+
+ break;
+ }
+ case BorderType::Inside: {
+ createBorders( mVertexBuffer, mBorders, mPosition, mSize );
+ break;
+ }
+ }
+
+ mColorNeedsUpdate = false;
+ mNeedsUpdate = false;
+}
+
+void UIBorderDrawable::updateColor() {
+ update();
+}
+
+}} // namespace EE::UI
diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp
index 27b24d1e6..96f4c499f 100644
--- a/src/eepp/ui/uinode.cpp
+++ b/src/eepp/ui/uinode.cpp
@@ -1,7 +1,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -12,6 +11,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -443,13 +443,13 @@ Color UINode::getBackgroundColor() const {
}
UINode* UINode::setBorderRadius( const unsigned int& corners ) {
- setBorderEnabled( true )->setCorners( corners );
+ setBorderEnabled( true )->setRadius( corners );
setBackgroundFillEnabled( true )->setBorderRadius( corners );
return this;
}
Uint32 UINode::getBorderRadius() const {
- return NULL != mBorder ? mBorder->getCorners() : 0;
+ return NULL != mBorder ? mBorder->getRadius() : 0;
}
UINodeDrawable* UINode::setForegroundFillEnabled( bool enabled ) {
@@ -512,7 +512,7 @@ Uint32 UINode::getForegroundRadius() const {
return NULL != mForeground ? mForeground->getBorderRadius() : 0;
}
-RectangleDrawable* UINode::setBorderEnabled( bool enabled ) {
+UIBorderDrawable* UINode::setBorderEnabled( bool enabled ) {
writeFlag( UI_BORDER, enabled ? 1 : 0 );
if ( enabled && NULL == mBorder ) {
@@ -587,16 +587,13 @@ UINode* UINode::resetFlags( Uint32 newFlags ) {
void UINode::drawBackground() {
if ( ( mFlags & UI_FILL_BACKGROUND ) && NULL != mBackground ) {
- mBackground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ),
- Sizef( eefloor( mSize.getWidth() ), eefloor( mSize.getHeight() ) ),
- mAlpha );
+ mBackground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), mSize.floor(), mAlpha );
}
}
void UINode::drawForeground() {
if ( ( mFlags & UI_FILL_FOREGROUND ) && NULL != mForeground ) {
- mForeground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ),
- Sizef( eefloor( mSize.getWidth() ), eefloor( mSize.getHeight() ) ),
+ mForeground->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ), mSize.floor(),
(Uint32)mAlpha );
}
}
@@ -605,8 +602,7 @@ void UINode::drawBorder() {
if ( ( mFlags & UI_BORDER ) && NULL != mBorder ) {
Uint8 alpha = mBorder->getAlpha();
mBorder->setAlpha( eemin( mAlpha * alpha / 255.f, 255 ) );
- mBorder->draw( Vector2f( mScreenPosi.x, mScreenPosi.y ),
- Sizef( eefloor( mSize.getWidth() ), eefloor( mSize.getHeight() ) ) );
+ mBorder->draw( mScreenPosi.asFloat(), mSize.floor() );
mBorder->setAlpha( alpha );
}
}
@@ -666,11 +662,10 @@ UINodeDrawable* UINode::getForeground() {
return mForeground;
}
-RectangleDrawable* UINode::getBorder() {
+UIBorderDrawable* UINode::getBorder() {
if ( NULL == mBorder ) {
- mBorder = RectangleDrawable::New();
+ mBorder = UIBorderDrawable::New();
mBorder->setColor( Color::Transparent );
- mBorder->setFillMode( PrimitiveFillMode::DRAW_LINE );
mBorder->setLineWidth( PixelDensity::dpToPx( 1 ) );
}
diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp
index 6a3abbae7..f9c33f16a 100644
--- a/src/eepp/ui/uiwidget.cpp
+++ b/src/eepp/ui/uiwidget.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1167,6 +1168,8 @@ std::string UIWidget::getPropertyString( const PropertyDefinition* propertyDef,
return String::toStr( getBorderRadius() );
case PropertyId::BorderWidth:
return String::fromFloat( getBorderWidth() );
+ case PropertyId::BorderType:
+ return getBorder()->getBorderType() == BorderType::Inside ? "inside" : "outside";
case PropertyId::SkinColor:
return getSkinColor().toHexString();
case PropertyId::Rotation:
@@ -1300,6 +1303,10 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::BorderRadius:
setBorderRadius( lengthFromValue( attribute ) );
break;
+ case PropertyId::BorderType:
+ getBorder()->setBorderType( attribute.getValue() == "inside" ? BorderType::Inside
+ : BorderType::Outside );
+ break;
case PropertyId::Visible:
setVisible( attribute.asBool() );
break;