diff --git a/bin/assets/layouts/test_widgets.xml b/bin/assets/layouts/test_widgets.xml
index a1840c0f1..e5d0d0a72 100644
--- a/bin/assets/layouts/test_widgets.xml
+++ b/bin/assets/layouts/test_widgets.xml
@@ -1,9 +1,9 @@
-
-
-
+
+
+
@@ -11,7 +11,7 @@
- Test 2
- Test 3
-
+
- Test
- Test 2
@@ -29,6 +29,7 @@
+
@@ -38,7 +39,7 @@
-
+
@@ -64,4 +65,3 @@
-
diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css
new file mode 100644
index 000000000..fb329d5f5
--- /dev/null
+++ b/bin/assets/ui/breeze.css
@@ -0,0 +1,325 @@
+
+:root {
+ --primary: #3daee9;
+ --back: #31363b;
+ --font: #eff0f1;
+ --button-back: #30353a;
+ --button-border: #6b6f73;
+ --button-radius: 2dp;
+ --base-horizontal-padding: 5dp;
+ --base-vertical-padding: 7dp;
+ --border-width: 1dp;
+ --list-back: #232629;
+ --separator: #383a3d;
+ --item-hover: #284150;
+ --scroll-button: #6b6d6f;
+ --slider-back: #676a6e;
+ --slider-button: #31363b;
+ --slider-border: #787b80;
+ --scrollbar-border: #373a3d;
+ --scrollbar-button: #4085a9;
+ --scrollbar-hback-hover: #606365;
+}
+
+* {
+ color: var(--font);
+ font-size: 11dp;
+ selection-back-color: var(--primary);
+}
+
+PushButton,
+SelectButton,
+DropDownList {
+ padding-left: var(--base-horizontal-padding);
+ padding-right: var(--base-horizontal-padding);
+ padding-top: var(--base-vertical-padding);
+ padding-bottom: var(--base-vertical-padding);
+ background-color: var(--button-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+ transition: all 0.125s;
+}
+
+PushButton:hover,
+DropDownList:hover,
+SelectButton:hover {
+ border-color: var(--primary);
+}
+
+PushButton:pressed,
+SelectButton:pressed,
+SelectButton:selected,
+SelectButton:selectedpressed {
+ background-color: var(--primary);
+}
+
+CheckBox::active,
+CheckBox::inactive {
+ width: 12dp;
+ height: 12dp;
+ border-width: 1dp;
+ border-radius: var(--button-radius);
+}
+
+CheckBox::inactive {
+ border-color: var(--button-border);
+}
+
+CheckBox::active {
+ border-color: var(--primary);
+ background-image: rectangle(solid, var(--primary));
+ background-size: 70% 70%;
+ background-position: center;
+}
+
+RadioButton::active,
+RadioButton::inactive {
+ width: 12dp;
+ height: 12dp;
+ border-width: 1dp;
+ border-radius: 100%;
+}
+
+RadioButton::inactive {
+ border-color: var(--button-border);
+}
+
+RadioButton::active {
+ border-color: var(--primary);
+ background-image: circle(solid, var(--primary));
+ background-size: 8dp 8dp;
+ background-position: 6dp 6dp;
+}
+
+ListBox,
+DropDownList::ListBox {
+ background-color: var(--list-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+ transition: all 0.15;
+}
+
+ListBox::item {
+ padding-left: 4dp;
+ background-image: linear-gradient( to right, #232629, #383a3d ), linear-gradient( to right, #383a3d, #232629 );
+ background-size: 50% 1dp, 50% 1dp;
+ background-position: left bottom, right bottom;
+}
+
+ListBox:hover {
+ border-color: var(--primary);
+}
+
+ListBox::item:hover {
+ background-color: var(--item-hover);
+}
+
+ListBox::item:selected {
+ background-color: var(--primary);
+}
+
+DropDownList::ListBox::item {
+ padding-left: 4dp;
+}
+
+DropDownList::ListBox::item:hover,
+DropDownList::ListBox::item:selected {
+ background-color: var(--primary);
+}
+
+TextInput {
+ padding-left: var(--base-horizontal-padding);
+ padding-right: var(--base-horizontal-padding);
+ padding-top: var(--base-vertical-padding);
+ padding-bottom: var(--base-vertical-padding);
+ background-color: var(--list-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+ transition: all 0.15;
+}
+
+TextInput:hover,
+TextInput:focus,
+SpinBox:hover,
+SpinBox:focus {
+ border-color: var(--primary);
+}
+
+SpinBox {
+ background-color: var(--list-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+ transition: all 0.15;
+}
+
+SpinBox::input {
+ padding-left: var(--base-horizontal-padding);
+ padding-right: var(--base-horizontal-padding);
+ padding-top: var(--base-vertical-padding);
+ padding-bottom: var(--base-vertical-padding);
+}
+
+SpinBox::input,
+SpinBox::input::hover,
+SpinBox::input::focus {
+ border-width: 0dp;
+ border-color: transparent;
+}
+
+SpinBox::btnup,
+SpinBox::btndown {
+ width: 13dp;
+ height: 13dp;
+}
+
+TextEdit {
+ background-color: var(--list-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+}
+
+TextEdit::input {
+ padding-left: var(--base-horizontal-padding);
+ padding-right: var(--base-horizontal-padding);
+ padding-top: var(--base-vertical-padding);
+ padding-bottom: var(--base-vertical-padding);
+}
+
+Tooltip {
+ padding-left: var(--base-horizontal-padding);
+ padding-right: var(--base-horizontal-padding);
+ padding-top: var(--base-vertical-padding);
+ padding-bottom: var(--base-vertical-padding);
+ background-color: var(--button-back);
+ border-color: var(--button-border);
+ border-radius: var(--button-radius);
+ border-width: var(--border-width);
+ font-style: shadow;
+}
+
+Slider {
+ min-width: 11dp;
+ min-height: 11dp;
+ half-slider: true;
+}
+
+Slider::vback {
+ background-color: var(--slider-back);
+ border-radius: 4dp;
+ min-width: 5dp;
+ min-height: 64dp;
+ transition: all 0.15s;
+}
+
+Slider::hback {
+ background-color: var(--slider-back);
+ border-radius: 4dp;
+ min-width: 64dp;
+ min-height: 5dp;
+ transition: all 0.15s;
+}
+
+Slider::vbutton,
+Slider::hbutton {
+ background-color: var(--slider-button);
+ border-color: var(--slider-border);
+ border-width: 1dp;
+ border-radius: 100%;
+ min-width: 11dp;
+ min-height: 11dp;
+}
+
+Slider::vbutton:hover,
+Slider::vbutton:focus,
+Slider::hbutton:hover,
+Slider::hbutton:focus {
+ border-color: var(--primary);
+}
+
+ScrollBar {
+ scrollbar-style: no-buttons;
+}
+
+ScrollBar::hback {
+ min-height: 6dp;
+ border-radius: 4dp;
+ background-color: transparent;
+}
+
+ScrollBar::vback {
+ min-width: 6dp;
+ border-radius: 4dp;
+ background-color: transparent;
+}
+
+ScrollBar::hslider,
+ScrollBar::vslider {
+ border-width: 1dp;
+ border-color: var(--scrollbar-border);
+ background-color: var(--list-back);
+ padding: 4dp;
+ transition: all 0.15s;
+}
+
+ScrollBar::hbutton {
+ min-height: 6dp;
+ background-color: var(--scrollbar-button);
+ border-radius: 4dp;
+ border-width: 0dp;
+ transition: all 0.15s;
+}
+
+ScrollBar::vbutton {
+ min-width: 6dp;
+ background-color: var(--scrollbar-button);
+ border-radius: 4dp;
+ border-width: 0dp;
+ transition: all 0.15s;
+}
+
+ScrollBar::hslider:hover ScrollBar::hback,
+ScrollBar::vslider:hover ScrollBar::vback {
+ background-color: var(--scrollbar-hback-hover);
+}
+
+ScrollBar::vslider:hover ScrollBar::vbutton,
+ScrollBar::vbutton:hover,
+ScrollBar::hslider:hover ScrollBar::hbutton,
+ScrollBar::hbutton:hover {
+ background-color: var(--primary);
+}
+
+ProgressBar {
+ min-height: 6dp;
+}
+
+ProgressBar::filler {
+ border-radius: 4dp;
+ background-color: var(--primary);
+}
+
+TabWidget {
+ tab-separation: -1dp;
+}
+
+TabWidget::TabContainer {
+ background-image: rectangle(solid, #2f3030);
+ background-size: 100% 1dp;
+ background-position-y: bottom;
+ min-height: 24dp;
+}
+
+Tab {
+ background-color: var(--list-back);
+ min-height: 24dp;
+}
+
+Tab::text {
+ padding-left: 4dp;
+ padding-right: 4dp;
+}
diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md
index 8ab76456b..b8d2c7a0f 100644
--- a/docs/articles/cssspecification.md
+++ b/docs/articles/cssspecification.md
@@ -1398,11 +1398,11 @@ Defines how the scrollbar should fit inside an scrollable element.
---
-### scrollbar-type
+### scrollbar-style
Sets the scrollbar style (for the moment defines if it contains buttons at its edge or it's simply a bar).
-* Applicable to: EE::UI::UIScrollBar (ScrollBar), EE::UI::UIListBox (ListBox), EE::UI::UIDropDownLis
+* Applicable to: EE::UI::UIScrollBar (ScrollBar), EE::UI::UIListBox (ListBox), EE::UI::UIDropDownList
(DropDownList), EE::UI::UITable (Table), EE::UI::UIScrollView (ScrollView)
* Data Type: [string-list](#string-list-data-type)
* Value List:
diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp
index 08141adad..cd7e27d26 100644
--- a/include/eepp/core/string.hpp
+++ b/include/eepp/core/string.hpp
@@ -189,6 +189,18 @@ class EE_API String {
*/
static bool endsWith( const String& haystack, const String& needle );
+ /** @return True if a string contains a substring.
+ * @param haystack The string to search in.
+ * @param needle The searched string.
+ */
+ static bool contains( const std::string& haystack, const std::string& needle );
+
+ /** @return True if a string contains a substring.
+ * @param haystack The string to search in.
+ * @param needle The searched string.
+ */
+ static bool contains( const String& haystack, const String& needle );
+
/** Replace all occurrences of the search string with the replacement string. */
static void replaceAll( std::string& target, const std::string& that, const std::string& with );
diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp
index db11a20db..b58ca4f01 100644
--- a/include/eepp/graphics/text.hpp
+++ b/include/eepp/graphics/text.hpp
@@ -118,7 +118,7 @@ class EE_API Text {
void setStyleConfig( const FontStyleConfig& styleConfig );
/** Finds the closest cursor position to the point position */
- Int32 findCharacterFromPos( const Vector2i& pos );
+ Int32 findCharacterFromPos( const Vector2i& pos, bool returnNearest = true );
/** Simulates a selection request and return the initial and end cursor position when the
* selection worked. Otherwise both parameters will be -1. */
diff --git a/include/eepp/math/vector2.hpp b/include/eepp/math/vector2.hpp
index 740342336..0291e2705 100644
--- a/include/eepp/math/vector2.hpp
+++ b/include/eepp/math/vector2.hpp
@@ -23,29 +23,29 @@ template class Vector2 {
Vector2 copy();
/** @return The Dot product of the 2D vectors. */
- T dot( const Vector2& V2 );
+ T dot( const Vector2& V2 ) const;
/** @return The Cross product of the 2D vectors. */
- T cross( const Vector2& V2 );
+ T cross( const Vector2& V2 ) const;
/** @return The perpendicular vector */
- Vector2 perp();
+ Vector2 perp() const;
/** @return The reveser perpendicular vector */
- Vector2 rPerp();
+ Vector2 rPerp() const;
/** Uses complex multiplication to rotate self by vec. Scaling will occur if self is not a unit
* vector. */
- Vector2 rotate( const Vector2& V2 );
+ Vector2 rotate( const Vector2& V2 ) const;
/** Inverse of Vector2::rotate */
- Vector2 unrotate( const Vector2& V2 );
+ Vector2 unrotate( const Vector2& V2 ) const;
/** @return The vector Length */
- T length();
+ T length() const;
/** @return The square of the length of the 2D vector. */
- T lengthSq();
+ T lengthSq() const;
/** Normalize the vector */
void normalize();
@@ -54,7 +54,7 @@ template class Vector2 {
void clamp( T len );
/** @return The unit length vector for the given angle (radians) */
- Vector2 forAngle( const T& a );
+ Vector2 forAngle( const T& a ) const;
/** @return The angular direction vector is pointing in (radians). */
T toAngle();
@@ -66,25 +66,25 @@ template class Vector2 {
void rotate( const T& Angle, const Vector2& RotationCenter );
/** @return The distance between two vectors */
- T distance( const Vector2& Vec );
+ T distance( const Vector2& Vec ) const;
/** @return The square of the distance between two vectors */
- T distanceSq( const Vector2& Vec );
+ T distanceSq( const Vector2& Vec ) const;
/** @return True if the distance between the two vectors is less than Dist */
- bool nearDist( const Vector2& Vec, T Dist );
+ bool nearDist( const Vector2& Vec, T Dist ) const;
/** @return The spherical linear interpolation between two 2D vectors. */
- Vector2 sphericalLerp( const Vector2& Vec, T Time );
+ Vector2 sphericalLerp( const Vector2& Vec, T Time ) const;
/** Spherical linear interpolation between two vectors */
- Vector2 sphericalLerpConst( const Vector2& Vec, T Angle );
+ Vector2 sphericalLerpConst( const Vector2& Vec, T Angle ) const;
/** Performs a linear interpolation between two 2D vectors. */
- Vector2 lerp( const Vector2& Vec, T Time );
+ Vector2 lerp( const Vector2& Vec, T Time ) const;
/** @return A vector interpolated from self towards Vec with length Dist. */
- Vector2 lerpConst( const Vector2& Vec, T Dist );
+ Vector2 lerpConst( const Vector2& Vec, T Dist ) const;
/** Scales the vector position against another vector */
void scale( const Vector2& scale, const Vector2& Center );
@@ -92,15 +92,15 @@ template class Vector2 {
/** Scales the vector position against another vector */
void scale( const T& scale, const Vector2& Center );
- Vector2 ceil();
+ Vector2 ceil() const;
- Vector2 floor();
+ Vector2 floor() const;
- Vector2 abs();
+ Vector2 abs() const;
- Vector2 asFloat();
+ Vector2 asFloat() const;
- Vector2 asInt();
+ Vector2 asInt() const;
T x;
T y;
@@ -114,17 +114,17 @@ template const Vector2 Vector2::One = Vector2( 1, 1 );
template const Vector2 Vector2::Zero = Vector2( 0, 0 );
-template Vector2 Vector2::lerp( const Vector2& Vec, T Time ) {
+template Vector2 Vector2::lerp( const Vector2& Vec, T Time ) const {
return *this * ( 1 - Time ) + Vec * Time;
}
-template Vector2 Vector2::lerpConst( const Vector2& Vec, T Dist ) {
+template Vector2 Vector2::lerpConst( const Vector2& Vec, T Dist ) const {
Vector2 t( *this + ( Vec - *this ) );
t.clamp( Dist );
return t;
}
-template Vector2 Vector2::sphericalLerp( const Vector2& Vec, T Time ) {
+template Vector2 Vector2::sphericalLerp( const Vector2& Vec, T Time ) const {
T omega = eeacos( dot( Vec ) );
if ( omega ) {
@@ -137,7 +137,8 @@ template Vector2 Vector2::sphericalLerp( const Vector2& Ve
}
}
-template Vector2 Vector2::sphericalLerpConst( const Vector2& Vec, T Angle ) {
+template
+Vector2 Vector2::sphericalLerpConst( const Vector2& Vec, T Angle ) const {
T angle = eeacos( dot( Vec ) );
return lerp( Vec, ( ( Angle < angle ) ? Angle : angle ) / angle );
}
@@ -305,35 +306,35 @@ template void Vector2::scale( const T& scale, const Vector2&
scale( Vector2( scale, scale ), Center );
}
-template T Vector2::dot( const Vector2& V2 ) {
+template T Vector2::dot( const Vector2& V2 ) const {
return x * V2.x + y * V2.y;
}
-template T Vector2::cross( const Vector2& V2 ) {
+template T Vector2::cross( const Vector2& V2 ) const {
return x * V2.x - y * V2.y;
}
-template Vector2 Vector2::perp() {
+template Vector2 Vector2::perp() const {
return Vector2( -y, x );
}
-template Vector2 Vector2::rPerp() {
+template Vector2 Vector2::rPerp() const {
return Vector2( y, -x );
}
-template Vector2 Vector2::rotate( const Vector2& V2 ) {
+template Vector2 Vector2::rotate( const Vector2& V2 ) const {
return Vector2( x * V2.x - y * V2.y, x * V2.y + y * V2.x );
}
-template Vector2 Vector2::unrotate( const Vector2& V2 ) {
+template Vector2 Vector2::unrotate( const Vector2& V2 ) const {
return Vector2( x * V2.x - y * V2.y, x * V2.x + y * V2.y );
}
-template T Vector2::length() {
+template T Vector2::length() const {
return eesqrt( dot( Vector2( x, y ) ) );
}
-template T Vector2::lengthSq() {
+template T Vector2::lengthSq() const {
return dot( Vector2( x, y ) );
}
@@ -348,7 +349,7 @@ template void Vector2::normalize() {
}
}
-template Vector2 Vector2::forAngle( const T& a ) {
+template Vector2 Vector2::forAngle( const T& a ) const {
return Vector2( eecos( a ), eesin( a ) );
}
@@ -356,11 +357,11 @@ template T Vector2::toAngle() {
return eeatan2( y, x );
}
-template T Vector2::distance( const Vector2& Vec ) {
+template T Vector2::distance( const Vector2& Vec ) const {
return eesqrt( ( x - Vec.x ) * ( x - Vec.x ) + ( y - Vec.y ) * ( y - Vec.y ) );
}
-template T Vector2::distanceSq( const Vector2& Vec ) {
+template T Vector2::distanceSq( const Vector2& Vec ) const {
return ( *this - Vec ).lengthSq();
}
@@ -373,27 +374,27 @@ template void Vector2::clamp( T len ) {
}
}
-template Vector2 Vector2::ceil() {
+template Vector2 Vector2::ceil() const {
return Vector2( eeceil( x ), eeceil( y ) );
}
-template Vector2 Vector2::floor() {
+template Vector2 Vector2::floor() const {
return Vector2( eefloor( x ), eefloor( y ) );
}
-template Vector2 Vector2::abs() {
+template Vector2 Vector2::abs() const {
return Vector2( eeabs( x ), eeabs( y ) );
}
-template Vector2 Vector2::asFloat() {
+template Vector2 Vector2::asFloat() const {
return Vector2( x, y );
}
-template Vector2 Vector2::asInt() {
+template Vector2 Vector2::asInt() const {
return Vector2( x, y );
}
-template bool Vector2::nearDist( const Vector2& Vec, T Dist ) {
+template bool Vector2::nearDist( const Vector2& Vec, T Dist ) const {
return 0 != ( distanceSq( Vec ) < Dist * Dist );
}
diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp
index d11196af7..a698ed763 100644
--- a/include/eepp/ui/uinode.hpp
+++ b/include/eepp/ui/uinode.hpp
@@ -248,9 +248,19 @@ class EE_API UINode : public Node {
UISceneNode* getUISceneNode();
+
+ void setMinWidth( const Float& width );
+
+ void setMinHeight( const Float& height );
+
+ void setMinSize( const Sizef& size );
+
+ const Sizef& getMinSize() const;
+
protected:
Vector2f mDpPos;
Sizef mDpSize;
+ Sizef mMinSize;
Uint32 mFlags;
Uint32 mState;
UISkinState* mSkinState;
diff --git a/include/eepp/ui/uiprogressbar.hpp b/include/eepp/ui/uiprogressbar.hpp
index 12933a06f..02f370671 100644
--- a/include/eepp/ui/uiprogressbar.hpp
+++ b/include/eepp/ui/uiprogressbar.hpp
@@ -7,6 +7,8 @@
namespace EE { namespace UI {
+class UIProgressBarFiller;
+
class EE_API UIProgressBar : public UIWidget {
public:
class StyleConfig {
@@ -36,8 +38,6 @@ class EE_API UIProgressBar : public UIWidget {
const Float& getTotalSteps() const;
- virtual void draw();
-
virtual void scheduledUpdate( const Time& time );
void setMovementSpeed( const Vector2f& Speed );
@@ -62,17 +62,20 @@ class EE_API UIProgressBar : public UIWidget {
const StyleConfig& getStyleConfig() const;
protected:
+ friend class UIProgressBarFiller;
StyleConfig mStyleConfig;
Float mProgress;
Float mTotalSteps;
UITextView* mTextBox;
Vector2f mOffset;
- UISkin* mFillerSkin;
+ UIProgressBarFiller* mFiller;
virtual Uint32 onValueChange();
virtual void onSizeChange();
+ virtual void onPaddingChange();
+
virtual void onThemeLoaded();
void updateTextBox();
diff --git a/include/eepp/ui/uiscrollbar.hpp b/include/eepp/ui/uiscrollbar.hpp
index 1f1595a82..1828e6623 100644
--- a/include/eepp/ui/uiscrollbar.hpp
+++ b/include/eepp/ui/uiscrollbar.hpp
@@ -60,7 +60,7 @@ class EE_API UIScrollBar : public UIWidget {
ScrollBarType getScrollBarType() const;
- void setScrollBarType( const ScrollBarType& scrollBarType );
+ void setScrollBarStyle( const ScrollBarType& scrollBarType );
bool getExpandBackground() const;
@@ -72,7 +72,7 @@ class EE_API UIScrollBar : public UIWidget {
const Uint32& propertyIndex = 0 );
protected:
- ScrollBarType mScrollBarType;
+ ScrollBarType mScrollBarStyle;
UISlider* mSlider;
UIWidget* mBtnUp;
UIWidget* mBtnDown;
@@ -90,6 +90,8 @@ class EE_API UIScrollBar : public UIWidget {
virtual Uint32 onMessage( const NodeMessage* Msg );
virtual void onPaddingChange();
+
+ void updateOrientation();
};
}} // namespace EE::UI
diff --git a/include/eepp/ui/uislider.hpp b/include/eepp/ui/uislider.hpp
index fa8501659..94856ed3c 100644
--- a/include/eepp/ui/uislider.hpp
+++ b/include/eepp/ui/uislider.hpp
@@ -76,6 +76,7 @@ class EE_API UISlider : public UIWidget {
UIOrientation mOrientation;
bool mAllowHalfSliderOut;
bool mExpandBackground;
+ bool mUpdating;
UIWidget* mBackSlider;
UIWidget* mSlider;
Float mMinValue;
@@ -103,6 +104,8 @@ class EE_API UISlider : public UIWidget {
virtual void onAlphaChange();
virtual Uint32 onMessage( const NodeMessage* Msg );
+
+ void updateOrientation();
};
}} // namespace EE::UI
diff --git a/include/eepp/ui/uispinbox.hpp b/include/eepp/ui/uispinbox.hpp
index 02d6a8a93..14de3782c 100644
--- a/include/eepp/ui/uispinbox.hpp
+++ b/include/eepp/ui/uispinbox.hpp
@@ -61,8 +61,8 @@ class EE_API UISpinBox : public UIWidget {
protected:
UITextInput* mInput;
- UINode* mPushUp;
- UINode* mPushDown;
+ UIWidget* mPushUp;
+ UIWidget* mPushDown;
Float mMinValue;
Float mMaxValue;
Float mValue;
diff --git a/include/eepp/ui/uistyle.hpp b/include/eepp/ui/uistyle.hpp
index ca288a9f2..65ab66d99 100644
--- a/include/eepp/ui/uistyle.hpp
+++ b/include/eepp/ui/uistyle.hpp
@@ -105,6 +105,8 @@ class EE_API UIStyle : public UIState {
void removeAnimation( const CSS::PropertyDefinition* propertyDefinition,
const Uint32& propertyIndex );
+
+ std::string varToVal( const std::string& varDef );
};
}} // namespace EE::UI
diff --git a/include/eepp/ui/uitextinput.hpp b/include/eepp/ui/uitextinput.hpp
index 1fb422f08..b85faf97a 100644
--- a/include/eepp/ui/uitextinput.hpp
+++ b/include/eepp/ui/uitextinput.hpp
@@ -109,8 +109,6 @@ class EE_API UITextInput : public UITextView {
void autoPadding();
- virtual Uint32 onMouseClick( const Vector2i& position, const Uint32& flags );
-
virtual Uint32 onMouseDown( const Vector2i& position, const Uint32& flags );
virtual Uint32 onMouseDoubleClick( const Vector2i& position, const Uint32& flags );
diff --git a/include/eepp/ui/uitextview.hpp b/include/eepp/ui/uitextview.hpp
index da616e74d..f00f8c2c5 100644
--- a/include/eepp/ui/uitextview.hpp
+++ b/include/eepp/ui/uitextview.hpp
@@ -69,7 +69,7 @@ class EE_API UITextView : public UIWidget {
const int& getNumLines() const;
- const Vector2f& getAlignOffset() const;
+ Vector2f getAlignOffset() const;
virtual void shrinkText( const Uint32& MaxWidth );
@@ -88,7 +88,6 @@ class EE_API UITextView : public UIWidget {
Text* mTextCache;
String mString;
UIFontStyleConfig mFontStyleConfig;
- Vector2f mAlignOffset;
Vector2f mRealAlignOffset;
Int32 mSelCurInit;
Int32 mSelCurEnd;
diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp
index 5ee6cb6ef..61fb76ab1 100644
--- a/include/eepp/ui/uiwidget.hpp
+++ b/include/eepp/ui/uiwidget.hpp
@@ -233,7 +233,6 @@ class EE_API UIWidget : public UINode {
UITheme* mTheme;
UIStyle* mStyle;
UITooltip* mTooltip;
- Sizef mMinControlSize;
Rect mDistToBorder;
Rect mLayoutMargin;
Rectf mPadding;
diff --git a/projects/linux/ee.files b/projects/linux/ee.files
index 82c453b32..a4050e235 100644
--- a/projects/linux/ee.files
+++ b/projects/linux/ee.files
@@ -4,6 +4,7 @@
../../bin/assets/layouts/test.css
../../bin/assets/layouts/test.xml
../../bin/assets/layouts/test_widgets.xml
+../../bin/assets/ui/breeze.css
../../bin/assets/ui/uitheme.css
../../docs/articles/cssspecification.md
../../docs/articles/uiintroduction.md
diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp
index 53cc0a16b..589a354f8 100644
--- a/src/eepp/core/string.cpp
+++ b/src/eepp/core/string.cpp
@@ -281,6 +281,14 @@ bool String::endsWith( const String& haystack, const String& needle ) {
haystack.compare( haystack.size() - needle.size(), needle.size(), needle ) == 0;
}
+bool String::contains( const std::string& haystack, const std::string& needle ) {
+ return haystack.find( needle ) != std::string::npos;
+}
+
+bool String::contains( const String& haystack, const String& needle ) {
+ return haystack.find( needle ) != String::InvalidPos;
+}
+
void String::replaceAll( std::string& target, const std::string& that, const std::string& with ) {
std::string::size_type pos = 0;
diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp
index 831a48fec..c622b2398 100644
--- a/src/eepp/graphics/text.cpp
+++ b/src/eepp/graphics/text.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
namespace EE { namespace Graphics {
@@ -281,7 +282,7 @@ Vector2f Text::findCharacterPos( std::size_t index ) const {
return mGlyphPos[index];
}
-Int32 Text::findCharacterFromPos( const Vector2i& pos ) {
+Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest ) {
if ( NULL == mFont )
return 0;
@@ -289,8 +290,12 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos ) {
Float Width = 0, lWidth = 0, Height = vspace, lHeight = 0;
Uint32 CharID;
Uint32 prevChar = 0;
+ Int32 nearest = -1;
+ Int32 minDist = std::numeric_limits::max();
+ Int32 curDist = -1;
std::size_t tSize = mString.size();
bool bold = ( mStyle & Bold ) != 0;
+ Vector2f fpos( pos.asFloat() );
Float hspace = static_cast( mFont->getGlyph( L' ', mRealFontSize, bold ).advance );
@@ -318,7 +323,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos ) {
if ( pos.x <= Width && pos.x >= lWidth && pos.y <= Height && pos.y >= lHeight ) {
if ( i + 1 < tSize ) {
Int32 curDist = eeabs( pos.x - lWidth );
- Int32 nextDist = eeabs( pos.x - ( lWidth + glyph.advance ) );
+ Int32 nextDist = eeabs( pos.x - Width );
if ( nextDist < curDist ) {
return i + 1;
@@ -328,6 +333,15 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos ) {
return i;
}
+ if ( returnNearest ) {
+ curDist = eeabs( fpos.distance( Vector2f( Width - ( Width - lWidth ) * 0.5f,
+ Height - ( Height - lHeight ) * 0.5f ) ) );
+ if ( curDist < minDist ) {
+ nearest = i;
+ minDist = curDist;
+ }
+ }
+
if ( CharID == '\n' ) {
lHeight = Height;
Height += vspace;
@@ -342,7 +356,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos ) {
return tSize;
}
- return -1;
+ return nearest;
}
static bool isStopSelChar( Uint32 c ) {
diff --git a/src/eepp/ui/css/stylesheetproperty.cpp b/src/eepp/ui/css/stylesheetproperty.cpp
index c0412bee6..53728784b 100644
--- a/src/eepp/ui/css/stylesheetproperty.cpp
+++ b/src/eepp/ui/css/stylesheetproperty.cpp
@@ -25,7 +25,7 @@ StyleSheetProperty::StyleSheetProperty( const PropertyDefinition* definition,
mIndex( index ),
mVolatile( false ),
mImportant( false ),
- mIsVarValue( String::startsWith( mValue, "var(" ) ),
+ mIsVarValue( String::contains( mValue, "var(" ) ),
mPropertyDefinition( definition ),
mShorthandDefinition( NULL ) {
cleanValue();
@@ -48,7 +48,7 @@ StyleSheetProperty::StyleSheetProperty( const bool& isVolatile,
mIndex( index ),
mVolatile( false ),
mImportant( false ),
- mIsVarValue( String::startsWith( mValue, "var(" ) ),
+ mIsVarValue( String::contains( mValue, "var(" ) ),
mPropertyDefinition( definition ),
mShorthandDefinition( NULL ) {
cleanValue();
@@ -68,7 +68,7 @@ StyleSheetProperty::StyleSheetProperty( const std::string& name, const std::stri
mIndex( 0 ),
mVolatile( false ),
mImportant( false ),
- mIsVarValue( String::startsWith( mValue, "var(" ) ),
+ mIsVarValue( String::contains( mValue, "var(" ) ),
mPropertyDefinition( StyleSheetSpecification::instance()->getProperty( mNameHash ) ),
mShorthandDefinition( NULL == mPropertyDefinition
? StyleSheetSpecification::instance()->getShorthand( mNameHash )
@@ -92,7 +92,7 @@ StyleSheetProperty::StyleSheetProperty( const std::string& name, const std::stri
mIndex( index ),
mVolatile( isVolatile ),
mImportant( false ),
- mIsVarValue( String::startsWith( mValue, "var(" ) ),
+ mIsVarValue( String::contains( mValue, "var(" ) ),
mPropertyDefinition( StyleSheetSpecification::instance()->getProperty( mNameHash ) ),
mShorthandDefinition( NULL == mPropertyDefinition
? StyleSheetSpecification::instance()->getShorthand( mNameHash )
diff --git a/src/eepp/ui/uicheckbox.cpp b/src/eepp/ui/uicheckbox.cpp
index 1ea1e00b0..e091fd008 100644
--- a/src/eepp/ui/uicheckbox.cpp
+++ b/src/eepp/ui/uicheckbox.cpp
@@ -65,7 +65,7 @@ void UICheckBox::onThemeLoaded() {
mInactiveButton->centerVertical();
}
- mMinControlSize = mActiveButton->getSkinSize();
+ mMinSize = mActiveButton->getSkinSize();
onPaddingChange();
@@ -188,8 +188,6 @@ void UICheckBox::alignFix() {
mActiveButton->getPixelsSize().getWidth() + PixelDensity::dpToPx( mTextSeparation );
break;
}
-
- mAlignOffset = PixelDensity::pxToDp( mRealAlignOffset );
}
UIWidget* UICheckBox::getCheckedButton() const {
diff --git a/src/eepp/ui/uidropdownlist.cpp b/src/eepp/ui/uidropdownlist.cpp
index 0d2f007ef..1f0b34bf1 100644
--- a/src/eepp/ui/uidropdownlist.cpp
+++ b/src/eepp/ui/uidropdownlist.cpp
@@ -83,12 +83,12 @@ void UIDropDownList::setFriendControl( UINode* friendCtrl ) {
}
void UIDropDownList::onAutoSize() {
+ Float max = eemax( PixelDensity::dpToPxI( getSkinSize().getHeight() ), getTextHeight() );
+
if ( mLayoutHeightRule == LayoutSizeRule::WrapContent ) {
- setInternalPixelsHeight( PixelDensity::dpToPxI( getSkinSize().getHeight() ) +
- mRealPadding.Top + mRealPadding.Bottom );
- } else if ( ( ( mFlags & UI_AUTO_SIZE ) || 0 == getSize().getHeight() ) &&
- 0 != getSkinSize().getHeight() ) {
- setInternalHeight( getSkinSize().getHeight() );
+ setInternalPixelsHeight( max + mRealPadding.Top + mRealPadding.Bottom );
+ } else if ( ( ( mFlags & UI_AUTO_SIZE ) || 0 == getSize().getHeight() ) && max > 0 ) {
+ setInternalHeight( max );
}
}
diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp
index 4c29a8a70..6fc2a1ca2 100644
--- a/src/eepp/ui/uilistbox.cpp
+++ b/src/eepp/ui/uilistbox.cpp
@@ -1074,11 +1074,11 @@ bool UIListBox::applyProperty( const StyleSheetProperty& attribute ) {
String::toLowerInPlace( val );
if ( "no-buttons" == val || "nobuttons" == val ) {
- mVScrollBar->setScrollBarType( UIScrollBar::NoButtons );
- mHScrollBar->setScrollBarType( UIScrollBar::NoButtons );
+ mVScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
+ mHScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
} else if ( "two-buttons" == val || "twobuttons" == val ) {
- mVScrollBar->setScrollBarType( UIScrollBar::TwoButtons );
- mHScrollBar->setScrollBarType( UIScrollBar::NoButtons );
+ mVScrollBar->setScrollBarStyle( UIScrollBar::TwoButtons );
+ mHScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
}
break;
}
diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp
index 504fb3185..0738a4d5f 100644
--- a/src/eepp/ui/uinode.cpp
+++ b/src/eepp/ui/uinode.cpp
@@ -135,26 +135,51 @@ const Vector2f& UINode::getPixelsPosition() const {
}
void UINode::setInternalSize( const Sizef& size ) {
+ Sizef s( size );
+
+ if ( s.x < mMinSize.x )
+ s.x = mMinSize.x;
+
+ if ( s.y < mMinSize.y )
+ s.y = mMinSize.y;
+
mDpSize = size;
- mSize = PixelDensity::dpToPx( size );
+ mSize = PixelDensity::dpToPx( s );
updateCenter();
sendCommonEvent( Event::OnSizeChange );
invalidateDraw();
}
void UINode::setInternalPixelsSize( const Sizef& size ) {
- mDpSize = PixelDensity::pxToDp( size );
- mSize = size;
+ Sizef s( size );
+ Sizef pMinSize( PixelDensity::dpToPx( mMinSize ) );
+
+ if ( s.x < pMinSize.x )
+ s.x = pMinSize.x;
+
+ if ( s.y < pMinSize.y )
+ s.y = pMinSize.y;
+
+ mDpSize = PixelDensity::pxToDp( s );
+ mSize = s;
updateCenter();
sendCommonEvent( Event::OnSizeChange );
invalidateDraw();
}
Node* UINode::setSize( const Sizef& Size ) {
- if ( Size != mDpSize ) {
- Vector2f sizeChange( Size.x - mDpSize.x, Size.y - mDpSize.y );
+ Sizef s( Size );
- setInternalSize( Size );
+ if ( s.x < mMinSize.x )
+ s.x = mMinSize.x;
+
+ if ( s.y < mMinSize.y )
+ s.y = mMinSize.y;
+
+ if ( s != mDpSize ) {
+ Vector2f sizeChange( s.x - mDpSize.x, s.y - mDpSize.y );
+
+ setInternalSize( s );
onSizeChange();
@@ -198,6 +223,31 @@ void UINode::setInternalPixelsHeight( const Float& height ) {
setInternalPixelsSize( Sizef( mSize.x, height ) );
}
+void UINode::setMinSize( const Sizef& size ) {
+ if ( size != mMinSize ) {
+ mMinSize = size;
+ setSize( getSize() );
+ }
+}
+
+void UINode::setMinWidth( const Float& width ) {
+ if ( width != mMinSize.x ) {
+ mMinSize.x = width;
+ setSize( getSize() );
+ }
+}
+
+void UINode::setMinHeight( const Float& height ) {
+ if ( height != mMinSize.y ) {
+ mMinSize.y = height;
+ setSize( getSize() );
+ }
+}
+
+const Sizef& UINode::getMinSize() const {
+ return mMinSize;
+}
+
void UINode::updateOriginPoint() {
Node::updateOriginPoint();
diff --git a/src/eepp/ui/uiprogressbar.cpp b/src/eepp/ui/uiprogressbar.cpp
index 82c13903a..cdac7488d 100644
--- a/src/eepp/ui/uiprogressbar.cpp
+++ b/src/eepp/ui/uiprogressbar.cpp
@@ -6,16 +6,68 @@
namespace EE { namespace UI {
+class UIProgressBarFiller : public UIWidget {
+ public:
+ static UIProgressBarFiller* New( UIProgressBar* parent ) {
+ return eeNew( UIProgressBarFiller, ( parent ) );
+ }
+
+ UIProgressBarFiller( UIProgressBar* parent ) :
+ UIWidget( "progressbar::filler" ), mProgressBar( NULL ), mFillerSkin( NULL ) {
+ setParent( parent );
+ mProgressBar = parent;
+ }
+
+ void draw() override {
+ UIWidget::draw();
+
+ if ( NULL == mFillerSkin )
+ return;
+
+ Float Height = (Float)mSize.getHeight();
+
+ if ( !mProgressBar->getStyleConfig().VerticalExpand )
+ Height = (Float)mFillerSkin->getSize().getHeight();
+
+ if ( Height > mSize.getHeight() )
+ Height = mSize.getHeight();
+
+ Sizef fSize( mSize );
+ Sizei rSize( PixelDensity::dpToPxI( mFillerSkin->getSize() ) );
+ Sizei numTiles( (Int32)eeceil( (Float)fSize.getWidth() / (Float)rSize.getWidth() + 2 ),
+ (Int32)eeceil( (Float)fSize.getHeight() / (Float)rSize.getHeight() ) + 2 );
+
+ clipSmartEnable( mScreenPos.x, mScreenPos.y, fSize.getWidth(), fSize.getHeight() );
+
+ Vector2f offset( mProgressBar->mOffset );
+
+ for ( int y = -1; y < numTiles.y; y++ ) {
+ for ( int x = -1; x < numTiles.x; x++ ) {
+ mFillerSkin->draw( Vector2f( (Int32)offset.x + mScreenPosi.x + x * rSize.getWidth(),
+ offset.y + mScreenPosi.y + y * rSize.getHeight() ),
+ Sizef( rSize.getWidth(), rSize.getHeight() ) );
+ }
+ }
+
+ clipSmartDisable();
+ }
+
+ UIProgressBar* mProgressBar;
+ UISkin* mFillerSkin;
+};
+
UIProgressBar* UIProgressBar::New() {
return eeNew( UIProgressBar, () );
}
-UIProgressBar::UIProgressBar() :
- UIWidget( "progressbar" ), mProgress( 0.f ), mTotalSteps( 100.f ), mFillerSkin( NULL ) {
+UIProgressBar::UIProgressBar() : UIWidget( "progressbar" ), mProgress( 0.f ), mTotalSteps( 100.f ) {
subscribeScheduledUpdate();
setFlags( UI_AUTO_PADDING | UI_AUTO_SIZE );
+ mFiller = UIProgressBarFiller::New( this );
+ mFiller->setEnabled( true );
+
mTextBox = UITextView::NewWithTag( "progressbar::text" );
mTextBox->setHorizontalAlign( UI_HALIGN_CENTER );
mTextBox->setParent( this );
@@ -36,52 +88,15 @@ bool UIProgressBar::isType( const Uint32& type ) const {
return UIProgressBar::getType() == type ? true : UIWidget::isType( type );
}
-void UIProgressBar::draw() {
- UINode::draw();
-
- if ( NULL == mFillerSkin )
- return;
-
- Float Height = (Float)mSize.getHeight();
-
- if ( !mStyleConfig.VerticalExpand )
- Height = (Float)mFillerSkin->getSize().getHeight();
-
- if ( Height > mSize.getHeight() )
- Height = mSize.getHeight();
-
- Sizef fSize( ( ( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) * mProgress ) /
- mTotalSteps,
- Height - mRealPadding.Top - mRealPadding.Bottom );
- Sizei rSize( PixelDensity::dpToPxI( mFillerSkin->getSize() ) );
- Sizei numTiles( (Int32)eeceil( (Float)fSize.getWidth() / (Float)rSize.getWidth() + 2 ),
- (Int32)eeceil( (Float)fSize.getHeight() / (Float)rSize.getHeight() ) + 2 );
-
- clipSmartEnable( mScreenPos.x + mRealPadding.Left, mScreenPos.y + mRealPadding.Top,
- fSize.getWidth(), fSize.getHeight() );
-
- for ( int y = -1; y < numTiles.y; y++ ) {
- for ( int x = -1; x < numTiles.x; x++ ) {
- mFillerSkin->draw(
- Vector2f( (Int32)mOffset.x + mScreenPosi.x + mRealPadding.Left +
- x * rSize.getWidth(),
- mOffset.y + mScreenPosi.y + mRealPadding.Top + y * rSize.getHeight() ),
- Sizef( rSize.getWidth(), rSize.getHeight() ) );
- }
- }
-
- clipSmartDisable();
-}
-
void UIProgressBar::scheduledUpdate( const Time& time ) {
- if ( NULL == mFillerSkin )
+ if ( NULL == mFiller->mFillerSkin )
return;
Vector2f offset( mOffset );
mOffset += mStyleConfig.MovementSpeed * ( Float )( time.asSeconds() );
- Sizei rSize( PixelDensity::dpToPxI( mFillerSkin->getSize() ) );
+ Sizei rSize( PixelDensity::dpToPxI( mFiller->mFillerSkin->getSize() ) );
if ( mOffset.x > rSize.getWidth() || mOffset.x < -rSize.getWidth() )
mOffset.x = 0.f;
@@ -97,14 +112,14 @@ void UIProgressBar::setTheme( UITheme* Theme ) {
UIWidget::setTheme( Theme );
setThemeSkin( Theme, "progressbar" );
- mFillerSkin = Theme->getSkin( "progressbar_filler" );
+ mFiller->mFillerSkin = Theme->getSkin( "progressbar_filler" );
- if ( mFillerSkin ) {
+ if ( mFiller->mFillerSkin ) {
if ( mFlags & UI_AUTO_PADDING ) {
Float meH = (Float)getSkinSize().getHeight();
- Float otH = (Float)mFillerSkin->getSize().getHeight();
+ Float otH = (Float)mFiller->mFillerSkin->getSize().getHeight();
Float res = Math::roundUp( ( meH - otH ) * 0.5f );
- setPadding( Rectf( res, res, res, res ) );
+ mFiller->setPadding( Rectf( res, res, res, res ) );
}
}
@@ -112,8 +127,8 @@ void UIProgressBar::setTheme( UITheme* Theme ) {
}
void UIProgressBar::onThemeLoaded() {
- mMinControlSize.x = eemax( mMinControlSize.x, getSkinSize().getWidth() );
- mMinControlSize.y = eemax( mMinControlSize.y, getSkinSize().getHeight() );
+ mMinSize.x = eemax( mMinSize.x, getSkinSize().getWidth() );
+ mMinSize.y = eemax( mMinSize.y, getSkinSize().getHeight() );
if ( mFlags & UI_AUTO_SIZE ) {
setSize( getSize().getWidth(), getSkinSize().getHeight() );
@@ -124,16 +139,24 @@ void UIProgressBar::onThemeLoaded() {
Uint32 UIProgressBar::onValueChange() {
UINode::onValueChange();
-
onSizeChange();
-
return 1;
}
void UIProgressBar::onSizeChange() {
+ Sizef fSize( ( ( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) * getProgress() ) /
+ getTotalSteps(),
+ mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom );
+ mFiller->setPixelsSize( fSize );
+ mFiller->setPixelsPosition( mRealPadding.Left, mRealPadding.Top );
updateTextBox();
}
+void UIProgressBar::onPaddingChange() {
+ onSizeChange();
+ UIWidget::onPaddingChange();
+}
+
void UIProgressBar::setProgress( Float Val ) {
mProgress = Val;
diff --git a/src/eepp/ui/uiradiobutton.cpp b/src/eepp/ui/uiradiobutton.cpp
index abc2bc5a8..7be08ade6 100644
--- a/src/eepp/ui/uiradiobutton.cpp
+++ b/src/eepp/ui/uiradiobutton.cpp
@@ -69,7 +69,7 @@ void UIRadioButton::onThemeLoaded() {
mInactiveButton->centerVertical();
}
- mMinControlSize = mActiveButton->getSkinSize();
+ mMinSize = mActiveButton->getSkinSize();
onPaddingChange();
@@ -255,8 +255,6 @@ void UIRadioButton::alignFix() {
mActiveButton->getPixelsSize().getWidth() + PixelDensity::dpToPx( mTextSeparation );
break;
}
-
- mAlignOffset = PixelDensity::pxToDp( mRealAlignOffset );
}
UIWidget* UIRadioButton::getActiveButton() const {
diff --git a/src/eepp/ui/uiscrollbar.cpp b/src/eepp/ui/uiscrollbar.cpp
index 3e89c3a6a..b95d26e6d 100644
--- a/src/eepp/ui/uiscrollbar.cpp
+++ b/src/eepp/ui/uiscrollbar.cpp
@@ -19,9 +19,9 @@ UIScrollBar* UIScrollBar::NewVertical() {
UIScrollBar::UIScrollBar( const UIOrientation& orientation ) :
UIWidget( "scrollbar" ),
#ifdef EE_PLATFORM_TOUCH
- mScrollBarType( NoButtons )
+ mScrollBarStyle( NoButtons )
#else
- mScrollBarType( TwoButtons )
+ mScrollBarStyle( TwoButtons )
#endif
{
mFlags |= UI_AUTO_SIZE;
@@ -41,15 +41,23 @@ UIScrollBar::UIScrollBar( const UIOrientation& orientation ) :
mBtnDown->setSize( 16, 16 );
mSlider = UISlider::New();
- mSlider->addEventListener( Event::OnValueChange,
- cb::Make1( this, &UIScrollBar::onValueChangeCb ) );
- mSlider->setElementTag( "scrollbar::slider" );
mSlider->setOrientation( orientation );
mSlider->setParent( this );
mSlider->setAllowHalfSliderOut( false );
mSlider->setExpandBackground( false );
- mSlider->getSliderButton()->setElementTag( "scrollbar::button" );
- mSlider->getBackSlider()->setElementTag( "scrollbar::back" );
+
+ if ( orientation == UIOrientation::Vertical ) {
+ mSlider->setElementTag( "scrollbar::vslider" );
+ mSlider->getSliderButton()->setElementTag( "scrollbar::vbutton" );
+ mSlider->getBackSlider()->setElementTag( "scrollbar::vback" );
+ } else {
+ mSlider->setElementTag( "scrollbar::hslider" );
+ mSlider->getSliderButton()->setElementTag( "scrollbar::hbutton" );
+ mSlider->getBackSlider()->setElementTag( "scrollbar::hback" );
+ }
+
+ mSlider->addEventListener( Event::OnValueChange,
+ cb::Make1( this, &UIScrollBar::onValueChangeCb ) );
adjustChilds();
@@ -76,8 +84,6 @@ void UIScrollBar::setTheme( UITheme* Theme ) {
mSlider->getSliderButton()->setThemeSkin( Theme, "hscrollbar_button" );
mBtnUp->setThemeSkin( Theme, "hscrollbar_btnup" );
mBtnDown->setThemeSkin( Theme, "hscrollbar_btndown" );
- mBtnDown->setElementTag( "scrollbar::btnleft" );
- mBtnUp->setElementTag( "scrollbar::btnright" );
} else {
UINode::setThemeSkin( Theme, "vscrollbar" );
mSlider->setThemeSkin( Theme, "vscrollbar_slider" );
@@ -85,8 +91,6 @@ void UIScrollBar::setTheme( UITheme* Theme ) {
mSlider->getSliderButton()->setThemeSkin( Theme, "vscrollbar_button" );
mBtnUp->setThemeSkin( Theme, "vscrollbar_btnup" );
mBtnDown->setThemeSkin( Theme, "vscrollbar_btndown" );
- mBtnDown->setElementTag( "scrollbar::btndown" );
- mBtnUp->setElementTag( "scrollbar::btnup" );
}
UISkin* tSkin = mBtnUp->getSkin();
@@ -115,7 +119,7 @@ void UIScrollBar::onAutoSize() {
if ( NULL != tSkin ) {
size = tSkin->getSize();
- mMinControlSize = PixelDensity::pxToDp( size );
+ setMinSize( PixelDensity::pxToDp( size ) );
if ( mFlags & UI_AUTO_SIZE ) {
if ( mSlider->isVertical() ) {
@@ -132,6 +136,8 @@ void UIScrollBar::onAutoSize() {
if ( NULL != tSkin ) {
size = tSkin->getSize();
+ setMinSize( PixelDensity::pxToDp( size ) );
+
if ( mFlags & UI_AUTO_SIZE ) {
if ( mSlider->isVertical() ) {
setSize( size.getWidth(), getSize().getHeight() );
@@ -144,9 +150,9 @@ void UIScrollBar::onAutoSize() {
if ( mLayoutWidthRule == LayoutSizeRule::WrapContent ||
mLayoutHeightRule == LayoutSizeRule::WrapContent ) {
- size = PixelDensity::dpToPx( mSlider->getMinimumSize() ) + mRealPadding;
+ size = PixelDensity::dpToPx( mSlider->getSize() ) + mRealPadding;
- if ( mScrollBarType == TwoButtons ) {
+ if ( mScrollBarStyle == TwoButtons ) {
if ( mSlider->isVertical() ) {
size.y +=
mBtnDown->getPixelsSize().getHeight() + mBtnUp->getPixelsSize().getHeight();
@@ -180,7 +186,7 @@ void UIScrollBar::adjustChilds() {
mBtnUp->setPosition( 0, 0 );
- switch ( mScrollBarType ) {
+ switch ( mScrollBarStyle ) {
case NoButtons: {
mBtnDown->setVisible( false )->setEnabled( false );
mBtnUp->setVisible( false )->setEnabled( false );
@@ -390,9 +396,9 @@ bool UIScrollBar::applyProperty( const StyleSheetProperty& attribute ) {
String::toLowerInPlace( val );
if ( "no-buttons" == val || "nobuttons" == val ) {
- setScrollBarType( NoButtons );
+ setScrollBarStyle( NoButtons );
} else if ( "two-buttons" == val || "twobuttons" == val ) {
- setScrollBarType( TwoButtons );
+ setScrollBarStyle( TwoButtons );
}
break;
}
@@ -407,12 +413,12 @@ bool UIScrollBar::applyProperty( const StyleSheetProperty& attribute ) {
}
UIScrollBar::ScrollBarType UIScrollBar::getScrollBarType() const {
- return mScrollBarType;
+ return mScrollBarStyle;
}
-void UIScrollBar::setScrollBarType( const ScrollBarType& scrollBarType ) {
- if ( mScrollBarType != scrollBarType ) {
- mScrollBarType = scrollBarType;
+void UIScrollBar::setScrollBarStyle( const ScrollBarType& scrollBarType ) {
+ if ( mScrollBarStyle != scrollBarType ) {
+ mScrollBarStyle = scrollBarType;
onAutoSize();
@@ -428,6 +434,7 @@ UINode* UIScrollBar::setOrientation( const UIOrientation& orientation ) {
if ( mSlider->getOrientation() != orientation ) {
mSlider->setOrientation( orientation );
+ updateOrientation();
applyDefaultTheme();
}
@@ -450,4 +457,20 @@ void UIScrollBar::onPaddingChange() {
UIWidget::onPaddingChange();
}
+void UIScrollBar::updateOrientation() {
+ if ( mSlider->getOrientation() == UIOrientation::Vertical ) {
+ mBtnDown->setElementTag( "scrollbar::btndown" );
+ mBtnUp->setElementTag( "scrollbar::btnup" );
+ mSlider->setElementTag( "scrollbar::vslider" );
+ mSlider->getSliderButton()->setElementTag( "scrollbar::vbutton" );
+ mSlider->getBackSlider()->setElementTag( "scrollbar::vback" );
+ } else {
+ mBtnDown->setElementTag( "scrollbar::btnleft" );
+ mBtnUp->setElementTag( "scrollbar::btnright" );
+ mSlider->setElementTag( "scrollbar::hslider" );
+ mSlider->getSliderButton()->setElementTag( "scrollbar::hbutton" );
+ mSlider->getBackSlider()->setElementTag( "scrollbar::hback" );
+ }
+}
+
}} // namespace EE::UI
diff --git a/src/eepp/ui/uiscrollview.cpp b/src/eepp/ui/uiscrollview.cpp
index 626897350..44a510389 100644
--- a/src/eepp/ui/uiscrollview.cpp
+++ b/src/eepp/ui/uiscrollview.cpp
@@ -320,11 +320,11 @@ bool UIScrollView::applyProperty( const StyleSheetProperty& attribute ) {
String::toLowerInPlace( val );
if ( "no-buttons" == val || "nobuttons" == val ) {
- mVScroll->setScrollBarType( UIScrollBar::NoButtons );
- mHScroll->setScrollBarType( UIScrollBar::NoButtons );
+ mVScroll->setScrollBarStyle( UIScrollBar::NoButtons );
+ mHScroll->setScrollBarStyle( UIScrollBar::NoButtons );
} else if ( "two-buttons" == val || "twobuttons" == val ) {
- mVScroll->setScrollBarType( UIScrollBar::TwoButtons );
- mHScroll->setScrollBarType( UIScrollBar::NoButtons );
+ mVScroll->setScrollBarStyle( UIScrollBar::TwoButtons );
+ mHScroll->setScrollBarStyle( UIScrollBar::NoButtons );
}
break;
}
diff --git a/src/eepp/ui/uislider.cpp b/src/eepp/ui/uislider.cpp
index 9d6223aff..015d64ed4 100644
--- a/src/eepp/ui/uislider.cpp
+++ b/src/eepp/ui/uislider.cpp
@@ -22,6 +22,7 @@ UISlider::UISlider( const UIOrientation& orientation ) :
mOrientation( orientation ),
mAllowHalfSliderOut( false ),
mExpandBackground( false ),
+ mUpdating( false ),
mBackSlider( NULL ),
mSlider( NULL ),
mMinValue( 0.f ),
@@ -32,24 +33,34 @@ UISlider::UISlider( const UIOrientation& orientation ) :
mOnPosChange( false ) {
Sizef bgSize;
- if ( UIOrientation::Horizontal == mOrientation )
+ if ( UIOrientation::Horizontal == mOrientation ) {
bgSize = Sizef( getSize().getWidth() - 16, 8 );
- else
+
+ mBackSlider = UIWidget::NewWithTag( "slider::hback" );
+ mSlider = UIWidget::NewWithTag( "slider::hbutton" );
+ } else {
bgSize = Sizef( 8, getSize().getHeight() - 16 );
- mBackSlider = UIWidget::NewWithTag( "slider::back" );
+ mBackSlider = UIWidget::NewWithTag( "slider::vback" );
+ mSlider = UIWidget::NewWithTag( "slider::hbutton" );
+ }
+
+ auto cb = [&]( const Event* event ) {
+ if ( !mUpdating )
+ adjustChilds();
+ };
+
mBackSlider->setParent( this );
mBackSlider->setVisible( true );
mBackSlider->setEnabled( true );
mBackSlider->setSize( bgSize );
mBackSlider->center();
- mSlider = UIWidget::NewWithTag( "slider::button" );
mSlider->setParent( this );
mSlider->setEnabled( true );
mSlider->setVisible( true );
mSlider->setDragEnabled( true );
- mSlider->setSize( 16, 16 );
+ mSlider->setSize( 4, 4 );
mSlider->setPosition( 0, 0 );
mSlider->addEventListener( Event::OnPositionChange,
[&]( const Event* event ) { fixSliderPos(); } );
@@ -59,6 +70,9 @@ UISlider::UISlider( const UIOrientation& orientation ) :
else
mSlider->centerHorizontal();
+ mBackSlider->addEventListener( Event::OnSizeChange, cb );
+ mSlider->addEventListener( Event::OnSizeChange, cb );
+
applyDefaultTheme();
}
@@ -105,72 +119,90 @@ void UISlider::onPaddingChange() {
}
void UISlider::adjustChilds() {
+ mUpdating = true;
+
UISkin* tSkin = mSlider->getSkin();
- if ( NULL != tSkin ) {
- if ( mPageStep == 0 ) {
- mSlider->setSize( tSkin->getSize() );
- } else {
- Float percent = ( mPageStep / ( mMaxValue - mMinValue ) );
+ if ( NULL != tSkin )
+ mSlider->setMinSize( tSkin->getSize() );
- if ( UIOrientation::Horizontal == mOrientation ) {
- Float size =
- eemax( ( (Float)getSize().getWidth() * percent ), tSkin->getSize().getWidth() );
-
- mSlider->setSize( size, tSkin->getSize().getHeight() );
- } else {
- Float size = eemax( ( (Float)getSize().getHeight() * percent ),
- tSkin->getSize().getHeight() );
-
- mSlider->setSize( tSkin->getSize().getWidth(), size );
- }
- }
+ if ( mPageStep == 0 ) {
+ mSlider->setSize( mSlider->getMinSize() );
+ } else {
+ Float percent = ( mPageStep / ( mMaxValue - mMinValue ) );
if ( UIOrientation::Horizontal == mOrientation ) {
- mSlider->centerVertical();
+ Float size = eemax( ( (Float)getSize().getWidth() * percent ),
+ mSlider->getMinSize().getWidth() );
+
+ mSlider->setSize( size, mSlider->getSize().getHeight() );
} else {
- mSlider->centerHorizontal();
+ Float size = eemax( ( (Float)getSize().getHeight() * percent ),
+ mSlider->getMinSize().getHeight() );
+
+ mSlider->setSize( mSlider->getSize().getWidth(), size );
}
}
+ if ( UIOrientation::Horizontal == mOrientation ) {
+ if ( mSlider->getSize().getHeight() > getMinSize().getHeight() )
+ setMinHeight( mSlider->getSize().getHeight() );
+
+ mSlider->centerVertical();
+ } else {
+ if ( mSlider->getSize().getWidth() > getMinimumSize().getWidth() )
+ setMinWidth( mSlider->getSize().getWidth() );
+
+ mSlider->centerHorizontal();
+ }
+
tSkin = mBackSlider->getSkin();
- if ( NULL != tSkin ) {
- if ( UIOrientation::Horizontal == mOrientation ) {
- Float Height;
+ if ( NULL != tSkin )
+ mBackSlider->setMinSize( tSkin->getSize() );
- if ( mExpandBackground )
- Height = getSize().getHeight() - mPadding.Top - mPadding.Bottom;
- else
- Height = tSkin->getSize().getHeight();
+ if ( UIOrientation::Horizontal == mOrientation ) {
+ Float Height;
- if ( mAllowHalfSliderOut )
- mBackSlider->setSize( Sizef( getSize().getWidth() - mSlider->getSize().getWidth() -
- mPadding.Left - mPadding.Right,
- Height ) );
- else
- mBackSlider->setSize(
- Sizef( getSize().getWidth() - mPadding.Left - mPadding.Right, Height ) );
- } else {
- Float Width;
+ if ( mExpandBackground )
+ Height = getSize().getHeight() - mPadding.Top - mPadding.Bottom;
+ else
+ Height = mBackSlider->getMinSize().getHeight();
- if ( mExpandBackground )
- Width = getSize().getWidth() - mPadding.Left - mPadding.Right;
- else
- Width = tSkin->getSize().getWidth();
+ if ( mAllowHalfSliderOut )
+ mBackSlider->setSize( Sizef( getSize().getWidth() - mSlider->getSize().getWidth() -
+ mPadding.Left - mPadding.Right,
+ Height ) );
+ else
+ mBackSlider->setSize(
+ Sizef( getSize().getWidth() - mPadding.Left - mPadding.Right, Height ) );
- if ( mAllowHalfSliderOut )
- mBackSlider->setSize( Sizef( Width, getSize().getHeight() -
- mSlider->getSize().getHeight() -
- mPadding.Top - mPadding.Bottom ) );
- else
- mBackSlider->setSize( Sizef( Width, getSize().getHeight() ) );
- }
+ if ( Height > getMinSize().getHeight() )
+ setMinHeight( Height );
+ } else {
+ Float Width;
- mBackSlider->center();
+ if ( mExpandBackground )
+ Width = getSize().getWidth() - mPadding.Left - mPadding.Right;
+ else
+ Width = mBackSlider->getMinSize().getWidth();
+
+ if ( mAllowHalfSliderOut )
+ mBackSlider->setSize( Sizef( Width, getSize().getHeight() -
+ mSlider->getSize().getHeight() - mPadding.Top -
+ mPadding.Bottom ) );
+ else
+ mBackSlider->setSize( Sizef( Width, getSize().getHeight() ) );
+
+ if ( Width > getMinimumSize().getWidth() )
+ setMinWidth( Width );
}
+ mBackSlider->center();
+
adjustSliderPos();
+
+ mUpdating = false;
}
void UISlider::fixSliderPos() {
@@ -395,6 +427,7 @@ UISlider* UISlider::setOrientation( const UIOrientation& orientation ) {
if ( orientation != mOrientation ) {
mOrientation = orientation;
+ updateOrientation();
applyDefaultTheme();
}
@@ -469,6 +502,16 @@ Uint32 UISlider::onMessage( const NodeMessage* Msg ) {
return 0;
}
+void UISlider::updateOrientation() {
+ if ( UIOrientation::Horizontal == mOrientation ) {
+ mBackSlider->setElementTag( "slider::hback" );
+ mSlider->setElementTag( "slider::hbutton" );
+ } else {
+ mBackSlider->setElementTag( "slider::vback" );
+ mSlider->setElementTag( "slider::hbutton" );
+ }
+}
+
std::string UISlider::getPropertyString( const PropertyDefinition* propertyDef,
const Uint32& propertyIndex ) {
if ( NULL == propertyDef )
diff --git a/src/eepp/ui/uispinbox.cpp b/src/eepp/ui/uispinbox.cpp
index cbe8bf702..732558654 100644
--- a/src/eepp/ui/uispinbox.cpp
+++ b/src/eepp/ui/uispinbox.cpp
@@ -25,13 +25,13 @@ UISpinBox::UISpinBox() :
mPushUp->setVisible( true );
mPushUp->setEnabled( true );
mPushUp->setParent( this );
- mPushUp->setSize( 16, 16 );
+ mPushUp->setSize( 8, 8 );
mPushDown = UIWidget::NewWithTag( "spinbox::btndown" );
mPushDown->setVisible( true );
mPushDown->setEnabled( true );
mPushDown->setParent( this );
- mPushDown->setSize( 16, 16 );
+ mPushDown->setSize( 8, 8 );
mInput->getInputTextBuffer()->setAllowOnlyNumbers( true, false );
mInput->addEventListener( Event::OnBufferChange,
@@ -312,13 +312,38 @@ bool UISpinBox::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::ClickStep:
setClickStep( attribute.asFloat() );
break;
+ case PropertyId::Text:
+ case PropertyId::AllowEditing:
+ case PropertyId::MaxLength:
+ case PropertyId::FreeEditing:
+ case PropertyId::Numeric:
+ case PropertyId::AllowFloat:
+ case PropertyId::Hint:
+ case PropertyId::HintColor:
+ case PropertyId::HintShadowColor:
+ case PropertyId::HintFontSize:
+ case PropertyId::HintFontFamily:
+ case PropertyId::HintFontStyle:
+ case PropertyId::HintStrokeWidth:
+ case PropertyId::HintStrokeColor:
+ case PropertyId::Color:
+ case PropertyId::ShadowColor:
+ case PropertyId::SelectionColor:
+ case PropertyId::SelectionBackColor:
+ case PropertyId::FontFamily:
+ case PropertyId::FontSize:
+ case PropertyId::FontStyle:
+ case PropertyId::Wordwrap:
+ case PropertyId::TextStrokeWidth:
+ case PropertyId::TextStrokeColor:
+ case PropertyId::TextSelection:
+ case PropertyId::TextAlign:
+ return mInput->applyProperty( attribute );
default:
attributeSet = UIWidget::applyProperty( attribute );
break;
}
- mInput->applyProperty( attribute );
-
return attributeSet;
}
diff --git a/src/eepp/ui/uistyle.cpp b/src/eepp/ui/uistyle.cpp
index b5679853a..3d5231e5e 100644
--- a/src/eepp/ui/uistyle.cpp
+++ b/src/eepp/ui/uistyle.cpp
@@ -194,26 +194,56 @@ void UIStyle::findVariables( const StyleSheetStyle& style ) {
}
}
-void UIStyle::setVariableFromValue( StyleSheetProperty& property, const std::string& value ) {
- FunctionString functionType = FunctionString::parse( value );
+std::string UIStyle::varToVal( const std::string& varDef ) {
+ FunctionString functionType = FunctionString::parse( varDef );
if ( !functionType.getParameters().empty() ) {
for ( auto& val : functionType.getParameters() ) {
if ( String::startsWith( val, "--" ) ) {
StyleSheetVariable variable( getVariable( val ) );
-
if ( !variable.isEmpty() ) {
- property.setValue( variable.getValue() );
- break;
+ return variable.getValue();
}
} else if ( String::startsWith( val, "var(" ) ) {
- return setVariableFromValue( property, val );
+ return varToVal( val );
} else {
- property.setValue( val );
- break;
+ return val;
}
}
}
+
+ return "";
+}
+
+void UIStyle::setVariableFromValue( StyleSheetProperty& property, const std::string& value ) {
+ std::string::size_type tokenStart = 0;
+ std::string::size_type tokenEnd = 0;
+ std::string newValue( value );
+
+ while ( true ) {
+ tokenStart = newValue.find( "var(", tokenStart );
+
+ if ( tokenStart != std::string::npos ) {
+ tokenEnd = String::findCloseBracket( value, tokenStart, '(', ')' );
+
+ if ( tokenEnd != std::string::npos ) {
+ std::string varDef( newValue.substr( tokenStart, tokenEnd + 1 - tokenStart ) );
+
+ String::replaceAll( newValue, varDef, varToVal( varDef ) );
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ };
+
+ property.setValue( newValue );
+
+ if ( newValue.empty() ) {
+ eePRINTL( "Invalid var: \"%s\" for property: %s", value.c_str(),
+ property.getName().c_str() );
+ }
}
void UIStyle::applyVarValues( StyleSheetStyle& style ) {
diff --git a/src/eepp/ui/uitable.cpp b/src/eepp/ui/uitable.cpp
index 9d1125f54..a3f4bac82 100644
--- a/src/eepp/ui/uitable.cpp
+++ b/src/eepp/ui/uitable.cpp
@@ -695,11 +695,11 @@ bool UITable::applyProperty( const StyleSheetProperty& attribute ) {
String::toLowerInPlace( val );
if ( "no-buttons" == val || "nobuttons" == val ) {
- mVScrollBar->setScrollBarType( UIScrollBar::NoButtons );
- mHScrollBar->setScrollBarType( UIScrollBar::NoButtons );
+ mVScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
+ mHScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
} else if ( "two-buttons" == val || "twobuttons" == val ) {
- mVScrollBar->setScrollBarType( UIScrollBar::TwoButtons );
- mHScrollBar->setScrollBarType( UIScrollBar::NoButtons );
+ mVScrollBar->setScrollBarStyle( UIScrollBar::TwoButtons );
+ mHScrollBar->setScrollBarStyle( UIScrollBar::NoButtons );
}
break;
}
diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp
index bcf98de2b..eda471b3b 100644
--- a/src/eepp/ui/uitextedit.cpp
+++ b/src/eepp/ui/uitextedit.cpp
@@ -33,12 +33,15 @@ UITextEdit::UITextEdit() :
mTextInput->setEnabled( true );
mTextInput->setSize( getSize() );
- mTextInput->addEventListener( Event::OnSizeChange,
- cb::Make1( this, &UITextEdit::onInputSizeChange ) );
- mTextInput->addEventListener( Event::OnTextChanged,
- cb::Make1( this, &UITextEdit::onInputSizeChange ) );
- mTextInput->addEventListener( Event::OnPressEnter,
- cb::Make1( this, &UITextEdit::onInputSizeChange ) );
+ auto cb = [&]( const Event* event ) {
+ mNodeFlags |= NODE_FLAG_FREE_USE;
+ onInputSizeChange( event );
+ mNodeFlags &= ~NODE_FLAG_FREE_USE;
+ };
+
+ mTextInput->addEventListener( Event::OnSizeChange, cb );
+ mTextInput->addEventListener( Event::OnTextChanged, cb );
+ mTextInput->addEventListener( Event::OnPressEnter, cb );
mTextInput->addEventListener( Event::OnCursorPosChange,
cb::Make1( this, &UITextEdit::onCursorPosChange ) );
@@ -295,9 +298,7 @@ void UITextEdit::onInputSizeChange( const Event* Event ) {
if ( mTextInput->getTextHeight() > Height ) {
Width -= mVScrollBar->getPixelsSize().getWidth();
- mNodeFlags |= NODE_FLAG_FREE_USE;
mTextInput->getInputTextBuffer()->setBuffer( text );
- mNodeFlags &= ~NODE_FLAG_FREE_USE;
shrinkText( Width );
diff --git a/src/eepp/ui/uitextinput.cpp b/src/eepp/ui/uitextinput.cpp
index 6aabc5a88..cb5b63475 100644
--- a/src/eepp/ui/uitextinput.cpp
+++ b/src/eepp/ui/uitextinput.cpp
@@ -76,8 +76,8 @@ void UITextInput::drawWaitingCursor() {
Primitives P;
P.setColor( mFontStyleConfig.FontColor );
- Float CurPosX = eefloor( mScreenPos.x + mRealAlignOffset.x + mCurPos.x +
- PixelDensity::dpToPx( 1.f ) + mRealPadding.Left );
+ Float CurPosX =
+ eefloor( mScreenPos.x + mRealAlignOffset.x + mCurPos.x + mRealPadding.Left );
Float CurPosY = mScreenPos.y + mRealAlignOffset.y + mCurPos.y + mRealPadding.Top;
if ( CurPosX > (Float)mScreenPos.x + (Float)mSize.x )
@@ -189,6 +189,7 @@ void UITextInput::resetWaitCursor() {
}
void UITextInput::alignFix() {
+ Vector2f rOffset( mRealAlignOffset );
UITextView::alignFix();
if ( Font::getHorizontalAlign( getFlags() ) == UI_HALIGN_LEFT ) {
@@ -201,18 +202,20 @@ void UITextInput::alignFix() {
mTextBuffer.getBuffer().substr( NLPos, mTextBuffer.getCursorPosition() - NLPos ) );
Float tW = textCache.getTextWidth();
- Float tX = mRealAlignOffset.x + tW;
-
mCurPos.x = tW;
mCurPos.y = (Float)LineNum * (Float)mTextCache->getFont()->getLineSpacing(
mTextCache->getCharacterSizePx() );
- if ( !mTextBuffer.setSupportNewLine() ) {
- if ( tX < 0.f )
+ if ( !mTextBuffer.setSupportNewLine() && mSize.getWidth() > 0 ) {
+ mRealAlignOffset.x = rOffset.x;
+ Float tX = mRealAlignOffset.x + tW;
+
+ if ( tX < 0.f ) {
mRealAlignOffset.x = -( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) );
- else if ( tX > mSize.getWidth() - mRealPadding.Left - mRealPadding.Right )
+ } else if ( tX > mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) {
mRealAlignOffset.x = mSize.getWidth() - mRealPadding.Left - mRealPadding.Right -
( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) );
+ }
}
}
}
@@ -228,7 +231,7 @@ void UITextInput::setTheme( UITheme* Theme ) {
void UITextInput::onThemeLoaded() {
UITextView::onThemeLoaded();
- mMinControlSize.y = eemax( mMinControlSize.y, getSkinSize().getHeight() );
+ mMinSize.y = eemax( mMinSize.y, getSkinSize().getHeight() );
autoPadding();
onAutoSize();
@@ -298,33 +301,6 @@ void UITextInput::shrinkText( const Uint32& MaxWidth ) {
void UITextInput::updateText() {}
-Uint32 UITextInput::onMouseClick( const Vector2i& Pos, const Uint32& Flags ) {
- UITextView::onMouseClick( Pos, Flags );
-
- if ( ( Flags & EE_BUTTON_LMASK ) ) {
- if ( selCurInit() == selCurEnd() ) {
- Vector2f controlPos( Vector2f( Pos.x, Pos.y ) );
- worldToNode( controlPos );
- controlPos = PixelDensity::dpToPx( controlPos ) - mRealAlignOffset;
-
- Int32 curPos =
- mTextCache->findCharacterFromPos( Vector2i( controlPos.x, controlPos.y ) );
-
- if ( -1 != curPos ) {
- mTextBuffer.setCursorPosition( curPos );
- onCursorPositionChange();
- resetWaitCursor();
- }
- } else {
- mTextBuffer.setCursorPosition( selCurEnd() );
- onCursorPositionChange();
- resetWaitCursor();
- }
- }
-
- return 1;
-}
-
Uint32 UITextInput::onMouseDown( const Vector2i& position, const Uint32& flags ) {
int endPos = selCurEnd();
@@ -351,7 +327,7 @@ Uint32 UITextInput::onMouseDoubleClick( const Vector2i& Pos, const Uint32& Flags
return 1;
}
-Uint32 UITextInput::onMouseOver(const Vector2i& position, const Uint32& flags) {
+Uint32 UITextInput::onMouseOver( const Vector2i& position, const Uint32& flags ) {
if ( NULL != mSceneNode )
mSceneNode->setCursor( Cursor::IBeam );
diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp
index fc4e10fd9..052f9b88d 100644
--- a/src/eepp/ui/uitextview.cpp
+++ b/src/eepp/ui/uitextview.cpp
@@ -318,8 +318,6 @@ void UITextView::alignFix() {
mRealAlignOffset.y = 0;
break;
}
-
- mAlignOffset = PixelDensity::pxToDp( mRealAlignOffset );
}
Uint32 UITextView::onFocusLoss() {
@@ -386,8 +384,8 @@ const int& UITextView::getNumLines() const {
return mTextCache->getNumLines();
}
-const Vector2f& UITextView::getAlignOffset() const {
- return mAlignOffset;
+Vector2f UITextView::getAlignOffset() const {
+ return PixelDensity::pxToDp( mRealAlignOffset );
}
Uint32 UITextView::onMouseDoubleClick( const Vector2i& Pos, const Uint32& Flags ) {
@@ -395,8 +393,9 @@ Uint32 UITextView::onMouseDoubleClick( const Vector2i& Pos, const Uint32& Flags
Vector2f controlPos( Vector2f( Pos.x, Pos.y ) );
worldToNode( controlPos );
controlPos = PixelDensity::dpToPx( controlPos ) - mRealAlignOffset;
+ controlPos -= Vector2f( mRealPadding.Left, mRealPadding.Top );
- Int32 curPos = mTextCache->findCharacterFromPos( Vector2i( controlPos.x, controlPos.y ) );
+ Int32 curPos = mTextCache->findCharacterFromPos( controlPos.asInt() );
if ( -1 != curPos ) {
Int32 tSelCurInit, tSelCurEnd;
@@ -433,9 +432,10 @@ Uint32 UITextView::onMouseDown( const Vector2i& Pos, const Uint32& Flags ) {
getEventDispatcher()->getDownControl() == this ) {
Vector2f controlPos( Vector2f( Pos.x, Pos.y ) );
worldToNode( controlPos );
- controlPos = PixelDensity::dpToPx( controlPos ) - mRealAlignOffset;
+ controlPos = PixelDensity::dpToPx( controlPos ) - mRealAlignOffset +
+ Vector2f( mRealPadding.Left, mRealPadding.Top );
- Int32 curPos = mTextCache->findCharacterFromPos( Vector2i( controlPos.x, controlPos.y ) );
+ Int32 curPos = mTextCache->findCharacterFromPos( controlPos.asInt() );
if ( -1 != curPos ) {
if ( -1 == selCurInit() || !mSelecting ) {
diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp
index 606292a08..af0de5164 100644
--- a/src/eepp/ui/uiwidget.cpp
+++ b/src/eepp/ui/uiwidget.cpp
@@ -34,7 +34,6 @@ UIWidget::UIWidget( const std::string& tag ) :
mTheme( NULL ),
mStyle( NULL ),
mTooltip( NULL ),
- mMinControlSize(),
mLayoutWeight( 0 ),
mLayoutGravity( 0 ),
mLayoutWidthRule( LayoutSizeRule::WrapContent ),
@@ -344,11 +343,11 @@ void UIWidget::tooltipRemove() {
Node* UIWidget::setSize( const Sizef& size ) {
Sizef s( size );
- if ( s.x < mMinControlSize.x )
- s.x = mMinControlSize.x;
+ if ( s.x < mMinSize.x )
+ s.x = mMinSize.x;
- if ( s.y < mMinControlSize.y )
- s.y = mMinControlSize.y;
+ if ( s.y < mMinSize.y )
+ s.y = mMinSize.y;
if ( !mMinWidthEq.empty() ) {
Float length =
@@ -505,8 +504,8 @@ void UIWidget::updateAnchors( const Vector2f& SizeChange ) {
newSize.x = mParentCtrl->getSize().getWidth() - mDpPos.x -
PixelDensity::pxToDpI( mDistToBorder.Right );
- if ( newSize.x < mMinControlSize.getWidth() )
- newSize.x = mMinControlSize.getWidth();
+ if ( newSize.x < mMinSize.getWidth() )
+ newSize.x = mMinSize.getWidth();
}
}
@@ -519,8 +518,8 @@ void UIWidget::updateAnchors( const Vector2f& SizeChange ) {
newSize.y =
mParentCtrl->getSize().y - mDpPos.y - PixelDensity::pxToDpI( mDistToBorder.Bottom );
- if ( newSize.y < mMinControlSize.getHeight() )
- newSize.y = mMinControlSize.getHeight();
+ if ( newSize.y < mMinSize.getHeight() )
+ newSize.y = mMinSize.getHeight();
}
}
@@ -577,14 +576,31 @@ void UIWidget::setMinSizeEq( const std::string& minWidthEq, const std::string& m
if ( mMinWidthEq != minWidthEq || mMinHeightEq != minHeightEq ) {
mMinWidthEq = minWidthEq;
mMinHeightEq = minHeightEq;
- setSize( mSize );
+
+ if ( !mMinWidthEq.empty() ) {
+ mMinSize.x =
+ lengthFromValue( mMinWidthEq, CSS::PropertyRelativeTarget::ContainingBlockWidth );
+ }
+
+ if ( !mMinHeightEq.empty() ) {
+ mMinSize.y =
+ lengthFromValue( mMinHeightEq, CSS::PropertyRelativeTarget::ContainingBlockHeight );
+ }
+
+ setSize( mDpSize );
}
}
void UIWidget::setMinWidthEq( const std::string& minWidthEq ) {
if ( mMinWidthEq != minWidthEq ) {
mMinWidthEq = minWidthEq;
- setSize( mSize );
+
+ if ( !mMinWidthEq.empty() ) {
+ mMinSize.x =
+ lengthFromValue( mMinWidthEq, CSS::PropertyRelativeTarget::ContainingBlockWidth );
+ }
+
+ setSize( mDpSize );
}
}
@@ -595,7 +611,13 @@ const std::string& UIWidget::getMinHeightEq() const {
void UIWidget::setMinHeightEq( const std::string& minHeightEq ) {
if ( mMinHeightEq != minHeightEq ) {
mMinHeightEq = minHeightEq;
- setSize( mSize );
+
+ if ( !mMinHeightEq.empty() ) {
+ mMinSize.y =
+ lengthFromValue( mMinHeightEq, CSS::PropertyRelativeTarget::ContainingBlockHeight );
+ }
+
+ setSize( mDpSize );
}
}
@@ -607,14 +629,14 @@ void UIWidget::setMaxSizeEq( const std::string& maxWidthEq, const std::string& m
if ( mMaxWidthEq != maxWidthEq || mMaxHeightEq != maxHeightEq ) {
mMaxWidthEq = maxWidthEq;
mMaxHeightEq = maxHeightEq;
- setSize( mSize );
+ setSize( mDpSize );
}
}
void UIWidget::setMaxWidthEq( const std::string& maxWidthEq ) {
if ( mMaxWidthEq != maxWidthEq ) {
mMaxWidthEq = maxWidthEq;
- setSize( mSize );
+ setSize( mDpSize );
}
}