diff --git a/examples/ScrolledWindowViewport.cpp b/examples/ScrolledWindowViewport.cpp index 48da76e1..db10994c 100644 --- a/examples/ScrolledWindowViewport.cpp +++ b/examples/ScrolledWindowViewport.cpp @@ -38,6 +38,9 @@ int main() { // Set the ScrolledWindow to always show the horizontal scrollbar // and only show the vertical scrollbar when needed. scrolledwindow->SetScrollbarPolicy( sfg::ScrolledWindow::HORIZONTAL_ALWAYS | sfg::ScrolledWindow::VERTICAL_AUTOMATIC ); + + // Set sticking ON + scrolledwindow->SetStick(sfg::ScrolledWindow::ScrollbarSticking::YES); // Add the ScrolledWindow box to the ScrolledWindow // and create a new viewport automatically. diff --git a/include/SFGUI/Adjustment.hpp b/include/SFGUI/Adjustment.hpp index a9cc06ad..035eb3ea 100644 --- a/include/SFGUI/Adjustment.hpp +++ b/include/SFGUI/Adjustment.hpp @@ -25,9 +25,10 @@ class SFGUI_API Adjustment : public Object, public std::enable_shared_from_this< * @param minor_step Minor change value (such as clicking on arrow button). * @param major_step Major change value (such as clicking on the scroll area). * @param page_size Page size (how many entries are visible / slider size). + * @param stick True if the adjustment should stick to the maximum value. * @return Adjustment. */ - static Ptr Create( float value = .0f, float lower = .0f, float upper = .0f, float minor_step = 1.f, float major_step = 5.f, float page_size = .0f ); + static Ptr Create( float value = .0f, float lower = .0f, float upper = .0f, float minor_step = 1.f, float major_step = 5.f, float page_size = .0f, bool stick = false ); /** Assignment operator * @param adjustment Adjustment whose values are to be assigned to this one. @@ -65,6 +66,21 @@ class SFGUI_API Adjustment : public Object, public std::enable_shared_from_this< */ void SetUpper( float new_upper ); + /** Get Adjustment stick setting + * @return Adjustment stick setting + */ + bool GetStick() const; + + /** Set Adjustment stick setting + * @param new_stick new stick setting + */ + void SetStick(bool new_stick); + + /** Check if value is set to maximum + * @return True is Value at Upper + */ + bool IsAtUpper() const; + /** Get Adjustment minor step * @return Adjustment minor step */ @@ -102,8 +118,9 @@ class SFGUI_API Adjustment : public Object, public std::enable_shared_from_this< * @param new_minor_step Minor change value (such as clicking on arrow button). * @param new_major_step Major change value (such as clicking on the scroll area). * @param new_page_size Page size (how many entries are visible / slider size). + * @param stick True if the adjustment should stick to the maximum value. */ - void Configure( float new_value, float new_lower, float new_upper, float new_minor_step, float new_major_step, float new_page_size ); + void Configure( float new_value, float new_lower, float new_upper, float new_minor_step, float new_major_step, float new_page_size, bool new_stick); /** Increment current value */ @@ -132,15 +149,17 @@ class SFGUI_API Adjustment : public Object, public std::enable_shared_from_this< * @param minor_step Minor change value (such as clicking on arrow button). * @param major_step Major change value (such as clicking on the scroll area). * @param page_size Page size (how many entries are visible / slider size). + * @param stick True if the adjustment should stick to the maximum value. */ - Adjustment( float value, float lower, float upper, float minor_step, float major_step, float page_size ); + Adjustment( float value, float lower, float upper, float minor_step, float major_step, float page_size, bool new_stick); float m_value; float m_lower; float m_upper; float m_minor_step; float m_major_step; - float m_page_size; + float m_page_size; + float m_stick; }; } diff --git a/include/SFGUI/ResizableImage.hpp b/include/SFGUI/ResizableImage.hpp index c8a5427b..8a1cd6e8 100644 --- a/include/SFGUI/ResizableImage.hpp +++ b/include/SFGUI/ResizableImage.hpp @@ -189,7 +189,7 @@ namespace sfg if (m_KeepAspect) { // Use same scale for both sides of the sprite - float lowerScale = std::min(scaleX, scaleY); + float lowerScale = scaleX < scaleY ? scaleX : scaleY; tempSprite.scale(lowerScale, lowerScale); diff --git a/include/SFGUI/ScrolledWindow.hpp b/include/SFGUI/ScrolledWindow.hpp index bf01f393..c55efdbf 100644 --- a/include/SFGUI/ScrolledWindow.hpp +++ b/include/SFGUI/ScrolledWindow.hpp @@ -39,6 +39,14 @@ class SFGUI_API ScrolledWindow : public Container { DEFAULT = HORIZONTAL_ALWAYS | VERTICAL_ALWAYS }; + /** Scrollbar sticking. + */ + enum class ScrollbarSticking : char { + NO = 0, //!< Do not move scrollbar. + YES, //!< Keep scrollbar sticked to the bottom. + DEFAULT = NO + }; + /** Create scrolled window. * @return ScrolledWindow. */ @@ -88,6 +96,11 @@ class SFGUI_API ScrolledWindow : public Container { */ void SetPlacement( Placement placement ); + /** Set the scrollbar behaviour when the bottom child is expanding. + * @param stick new ScrollbarSticking. + */ + void SetStick(ScrollbarSticking stick); + /** Get the allocation of the content area of this Scrolled Window * @return Allocation of the content area of this Scrolled Window */ @@ -146,7 +159,8 @@ class SFGUI_API ScrolledWindow : public Container { std::shared_ptr m_viewport; char m_policy; - Placement m_placement; + Placement m_placement; + ScrollbarSticking m_stick; }; } diff --git a/src/SFGUI/Adjustment.cpp b/src/SFGUI/Adjustment.cpp index 8f27e863..1198ef73 100644 --- a/src/SFGUI/Adjustment.cpp +++ b/src/SFGUI/Adjustment.cpp @@ -5,18 +5,19 @@ namespace sfg { // Signals. Signal::SignalID Adjustment::OnChange = 0; -Adjustment::Adjustment( float value, float lower, float upper, float minor_step, float major_step, float page_size ) : +Adjustment::Adjustment( float value, float lower, float upper, float minor_step, float major_step, float page_size, bool stick ) : m_value( value ), m_lower( lower ), m_upper( upper ), m_minor_step( minor_step ), m_major_step( major_step ), - m_page_size( page_size ) + m_page_size( page_size ), + m_stick ( stick ) { } -Adjustment::Ptr Adjustment::Create( float value, float lower, float upper, float minor_step, float major_step, float page_size ) { - return Adjustment::Ptr( new Adjustment( value, lower, upper, minor_step, major_step, page_size ) ); +Adjustment::Ptr Adjustment::Create( float value, float lower, float upper, float minor_step, float major_step, float page_size, bool stick ) { + return Adjustment::Ptr( new Adjustment( value, lower, upper, minor_step, major_step, page_size, stick) ); } Adjustment& Adjustment::operator=( const Adjustment& adjustment ) { @@ -25,7 +26,8 @@ Adjustment& Adjustment::operator=( const Adjustment& adjustment ) { SetMinorStep( adjustment.m_minor_step ); SetMajorStep( adjustment.m_major_step ); SetPageSize( adjustment.m_page_size ); - SetValue( adjustment.m_value ); + SetValue( adjustment.m_value ); + SetValue( adjustment.m_stick ); return *this; } @@ -51,6 +53,10 @@ void Adjustment::SetValue( float new_value ) { } } +bool Adjustment::IsAtUpper() const { + return m_value + m_page_size >= m_upper; +} + float Adjustment::GetLower() const { return m_lower; } @@ -70,13 +76,25 @@ float Adjustment::GetUpper() const { } void Adjustment::SetUpper( float new_upper ) { - m_upper = new_upper; + if (m_upper != new_upper) + { + bool sticked = m_stick && IsAtUpper(); + m_upper = new_upper; - if( m_upper < m_lower ) { - m_lower = m_upper; - } + if (m_upper < m_lower) { + m_lower = m_upper; + } - SetValue( GetValue() ); + SetValue(sticked ? m_upper : GetValue()); + } +} + +bool Adjustment::GetStick() const { + return m_stick; +} + +void Adjustment::SetStick(bool new_stick) { + m_stick = new_stick; } float Adjustment::GetMinorStep() const { @@ -109,13 +127,14 @@ void Adjustment::SetPageSize( float new_page_size ) { SetValue( GetValue() ); } -void Adjustment::Configure( float new_value, float new_lower, float new_upper, float new_minor_step, float new_major_step, float new_page_size ) { +void Adjustment::Configure( float new_value, float new_lower, float new_upper, float new_minor_step, float new_major_step, float new_page_size, bool new_stick ) { SetValue( new_value ); SetLower( new_lower ); SetUpper( new_upper ); SetMinorStep( new_minor_step ); SetMajorStep( new_major_step ); - SetPageSize( new_page_size ); + SetPageSize(new_page_size); + SetStick(new_stick); } void Adjustment::Increment() { diff --git a/src/SFGUI/ListBox.cpp b/src/SFGUI/ListBox.cpp index 1b4f1670..7433dea2 100644 --- a/src/SFGUI/ListBox.cpp +++ b/src/SFGUI/ListBox.cpp @@ -543,7 +543,8 @@ void ListBox::UpdateScrollbarAdjustment() { static_cast( m_items.size() ), 1.f, static_cast( m_max_displayed_items_count ), - static_cast( m_max_displayed_items_count ) + static_cast( m_max_displayed_items_count ), + false // stick ); } diff --git a/src/SFGUI/ScrolledWindow.cpp b/src/SFGUI/ScrolledWindow.cpp index fb79bf33..d129d643 100644 --- a/src/SFGUI/ScrolledWindow.cpp +++ b/src/SFGUI/ScrolledWindow.cpp @@ -14,7 +14,8 @@ ScrolledWindow::ScrolledWindow( Adjustment::Ptr horizontal_adjustment, Adjustmen m_vertical_scrollbar(), m_viewport(), m_policy( ScrollbarPolicy::DEFAULT ), - m_placement( Placement::DEFAULT ) + m_placement( Placement::DEFAULT ), + m_stick(ScrollbarSticking::DEFAULT) { m_horizontal_scrollbar = Scrollbar::Create( horizontal_adjustment, Scrollbar::Orientation::HORIZONTAL ); m_vertical_scrollbar = Scrollbar::Create( vertical_adjustment, Scrollbar::Orientation::VERTICAL ); @@ -81,6 +82,15 @@ void ScrolledWindow::SetPlacement( Placement placement ) { Invalidate(); } +void ScrolledWindow::SetStick(ScrollbarSticking stick) { + m_stick = stick; + GetHorizontalAdjustment()->SetStick(stick == ScrollbarSticking::YES); + GetVerticalAdjustment()->SetStick(stick == ScrollbarSticking::YES); + + RecalculateContentAllocation(); + Invalidate(); +} + bool ScrolledWindow::IsHorizontalScrollbarVisible() const { if( m_policy & HORIZONTAL_ALWAYS ) { return true; diff --git a/src/SFGUI/SpinButton.cpp b/src/SFGUI/SpinButton.cpp index 4b48117d..8c9cfb66 100644 --- a/src/SFGUI/SpinButton.cpp +++ b/src/SFGUI/SpinButton.cpp @@ -25,7 +25,7 @@ SpinButton::SpinButton() : SpinButton::Ptr SpinButton::Create( float minimum, float maximum, float step ) { auto adjustment = Adjustment::Create(); - adjustment->Configure( minimum, minimum, maximum, step, 0.f, 0.f ); + adjustment->Configure( minimum, minimum, maximum, step, 0.f, 0.f, false /* stick */ ); auto ptr = Ptr( new SpinButton ); ptr->SetAdjustment( adjustment );