* ComponentStack can now handle more autosize modes 4.x-dev

Fri, 04 Dec 2020 17:02:10 +0200

author
cemkalyoncu
date
Fri, 04 Dec 2020 17:02:10 +0200
branch
4.x-dev
changeset 1507
16116186d94c
parent 1506
c24aade1ec31
child 1508
58d190b948ea

* ComponentStack can now handle more autosize modes
* Button, Checkbox, Label can now be autosized

Source/Gorgon/UI/ComponentStack.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ComponentStack.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ComponentStackWidget.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Button.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Checkbox.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Label.h file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Component.cpp file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/UI/ComponentStack.cpp	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/UI/ComponentStack.cpp	Fri Dec 04 17:02:10 2020 +0200
@@ -2139,9 +2139,9 @@
             //initial states
             get(0).size = size;
             
-            if(autosize.first)
+            if(autosize.first != Autosize::None)
                 get(0).size.Width = 0;
-            if(autosize.second)
+            if(autosize.second != Autosize::None)
                 get(0).size.Height = 0;
             
             get(0).location = {0,0};
@@ -2178,17 +2178,130 @@
             }
             
             //start the update from the root
-            update(get(0), value, -1, autosize.first ? size.Width : -1, autosize.first || autosize.second);
+            update(get(0), value, -1, autosize.first != Autosize::None ? size.Width : -1, autosize.first != Autosize::None || autosize.second != Autosize::None);
             
-            if(autosize.first || autosize.second) {
+            auto ceilfn = ceiltounitsize_fn;
+            if(!ceilfn) {
+                ceilfn = [this](int s) {
+                    return (s + temp.GetUnitWidth() - 1) / temp.GetUnitWidth() * temp.GetUnitWidth();
+                };
+            }
+            
+            if(autosize.first != Autosize::None || autosize.second != Autosize::None) {
                 auto sz = size;
                 
-                if(autosize.first && get(0).size.Width >= 0)
-                    sz.Width = get(0).size.Width;
+                //handle autosize options
+                auto &rootsize = get(0).size;
                 
-                if(autosize.second && get(0).size.Height >= 0)
-                    sz.Height = get(0).size.Height;
+                if(rootsize.Width > 0) {
+                    switch(autosize.first) {
+                        case Autosize::Automatic:
+                            sz.Width = rootsize.Width;
+                            break;
+                            
+                        case Autosize::Shrink:
+                            if(sz.Width > rootsize.Width) {
+                                sz.Width = rootsize.Width;
+                            }
+                            else {
+                                rootsize.Width = sz.Width;
+                            }
+                            break;
+                            
+                        case Autosize::Grow:
+                            if(sz.Width < rootsize.Width) {
+                                sz.Width = rootsize.Width;
+                            }
+                            else {
+                                rootsize.Width = sz.Width;
+                            }
+                            break;
+                            
+                        case Autosize::Unit:
+                            sz.Width = ceilfn(rootsize.Width);
+                            rootsize.Width = sz.Width;
+                            break;
+                            
+                        case Autosize::ShrinkToUnit:
+                            if(sz.Width > rootsize.Width) {
+                                sz.Width = ceilfn(rootsize.Width);
+                                rootsize.Width = sz.Width;
+                            }
+                            else {
+                                rootsize.Width = sz.Width;
+                            }
+                            break;
+                            
+                        case Autosize::GrowToUnit:
+                            if(sz.Width < rootsize.Width) {
+                                sz.Width = ceilfn(rootsize.Width);
+                                rootsize.Width = sz.Width;
+                            }
+                            else {
+                                rootsize.Width = sz.Width;
+                            }
+                            break;
+                            
+                        default:
+                            //nothing
+                            break;
+                    }
+                }
                 
+                if(rootsize.Height > 0) {
+                    switch(autosize.second) {
+                        case Autosize::Automatic:
+                            sz.Height = rootsize.Height;
+                            break;
+                            
+                        case Autosize::Shrink:
+                            if(sz.Height > rootsize.Height) {
+                                sz.Height = rootsize.Height;
+                            }
+                            else {
+                                rootsize.Height = sz.Height;
+                            }
+                            break;
+                            
+                        case Autosize::Grow:
+                            if(sz.Height < rootsize.Height) {
+                                sz.Height = rootsize.Height;
+                            }
+                            else {
+                                rootsize.Height = sz.Height;
+                            }
+                            break;
+                            
+                        case Autosize::Unit:
+                            sz.Height = ceilfn(rootsize.Height);
+                            rootsize.Height = sz.Height;
+                            break;
+                            
+                        case Autosize::ShrinkToUnit:
+                            if(sz.Height > rootsize.Height) {
+                                sz.Height = ceilfn(rootsize.Height);
+                                rootsize.Height = sz.Height;
+                            }
+                            else {
+                                rootsize.Height = sz.Height;
+                            }
+                            break;
+                            
+                        case Autosize::GrowToUnit:
+                            if(sz.Height < rootsize.Height) {
+                                sz.Height = ceilfn(rootsize.Height);
+                                rootsize.Height = sz.Height;
+                            }
+                            else {
+                                rootsize.Height = sz.Height;
+                            }
+                            break;
+                            
+                        default:
+                            //nothing
+                            break;
+                    }
+                }
                 
                 //second run to get everything into proper size
                 update(get(0), value, -1);
--- a/Source/Gorgon/UI/ComponentStack.h	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/UI/ComponentStack.h	Fri Dec 04 17:02:10 2020 +0200
@@ -12,6 +12,37 @@
 
 namespace Gorgon { namespace UI {
     
+    
+    /**
+     * Defines autosize behavior of some widgets
+     */
+    enum class Autosize {
+        /// Automatic sizing will not be in effect
+        None,
+        
+        /// Automatic sizing will be in effect
+        Automatic,
+        
+        /// Automatic sizing will be in effect and will resize
+        /// to next size units. This is more effective horizontally.
+        Unit,
+        
+        /// Autosizing will only make the widget grow
+        Grow,
+        
+        /// Autosizing will only make the widget grow to next unit
+        /// size.
+        GrowToUnit,
+        
+        /// Autosizing will only make the widget shrink
+        Shrink,
+        
+        /// Autosizing will only make the widget shrink. It will be resized
+        /// to a unit size.
+        ShrinkToUnit,
+    };
+
+    
     class Widget;
 
     /**
@@ -153,6 +184,12 @@
         void SetValueToText(std::function<std::string(int, ComponentTemplate::DataEffect, const std::array<float, 4> &)> handler) {
             valuetotext = handler;
         }
+        
+        /// Sets the function that will be used perform Ceil operation in unit sizes. If
+        /// not set, unit width of the template will be used.
+        void SetCeilToUnitSize(std::function<int(int)> handler) {
+            ceiltounitsize_fn = handler;
+        }
 
         /**
         * @name Repeating components
@@ -430,13 +467,18 @@
         
         /// Sets whether the ComponentStack should be autosized. Autosize
         /// uses the set size for text width.
-        void SetAutoSize(bool horizontal, bool vertical) {
+        void SetAutosize(Autosize horizontal, Autosize vertical) {
             if(autosize == std::make_pair(horizontal, vertical))
                 return;
                 
             autosize = {horizontal, vertical};
             Update();
         }
+        
+        /// Returns the autosize mode of the stack
+        std::pair<Autosize, Autosize> GetAutosize() const {
+            return autosize;
+        }
 
         /** @name Events
          * These are events that can be handled
@@ -725,7 +767,7 @@
         bool handlingmouse = false;
         
         ///When set, component stack will resize itself to fit components.
-        std::pair<bool, bool> autosize = {false, false};
+        std::pair<Autosize, Autosize> autosize = {Autosize::None, Autosize::None};
 
         ///Size of the component stack
         Geometry::Size size;
@@ -761,6 +803,7 @@
         std::function<void()> beforeupdate_fn;
         std::function<void()> update_fn;
         std::function<void()> render_fn;
+        std::function<int(int)> ceiltounitsize_fn;
         
         std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> widgetgenerators;
         Containers::Hashmap<const ComponentTemplate *, Widget> widgets;
--- a/Source/Gorgon/UI/ComponentStackWidget.h	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/UI/ComponentStackWidget.h	Fri Dec 04 17:02:10 2020 +0200
@@ -13,7 +13,18 @@
      */
     class ComponentStackWidget : public Widget {
     public:
-        ComponentStackWidget(const Template &temp, std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> generators = {}) : stack(*new ComponentStack(temp, temp.GetSize(), generators)) { }
+        ComponentStackWidget(const Template &temp, std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> generators = {}) : stack(*new ComponentStack(temp, temp.GetSize(), generators)) {
+            stack.SetCeilToUnitSize([this](int s) {
+                int w;
+                if(HasParent()) {
+                    w = GetParent().GetUnitWidth();
+                }
+                else {
+                    w = stack.GetTemplate().GetUnitWidth();
+                }
+                return (s + w - 1) / w * w;
+            }); 
+        }
         
         ComponentStackWidget(ComponentStackWidget &&) = default;
 
@@ -135,6 +146,38 @@
 		virtual void setlayerorder(Layer &, int order) override {
 			stack.PlaceBefore(order);
 		}
+		
+		//Make these functions public as necessary.
+        
+        /// Adjusts autosizing of the widget. In autosize mode, set width is used to limit
+        /// text width so that it will flow to next line.
+        void SetAutosize(UI::Autosize hor, UI::Autosize ver) {
+            stack.SetAutosize(hor, ver);
+        }
+        
+        /// Adjusts autosizing of the widget. In autosize mode, set width is used to limit
+        /// text width so that it will flow to next line.
+        void SetHorizonalAutosize(UI::Autosize value) {
+            stack.SetAutosize(value, stack.GetAutosize().second);
+        }
+        
+        /// Adjusts autosizing of the widget. In autosize mode, set width is used to limit
+        /// text width so that it will flow to next line.
+        void SetVerticalAutosize(UI::Autosize value) {
+            stack.SetAutosize(stack.GetAutosize().first, value);
+        }
+        
+        /// Returns the horizontal autosize mode of the widget
+        UI::Autosize GetHorizontalAutosize() const {
+            return stack.GetAutosize().first;
+        }
+        
+        /// Returns the horizontal autosize mode of the widget
+        UI::Autosize GetVerticalAutosize() const {
+            return stack.GetAutosize().second;
+        }
+        
+        
 
     private:
         virtual void show() override {
@@ -152,4 +195,11 @@
 		}
 	};
     
+#define GORGON_UI_CSW_AUTOSIZABLE_WIDGET \
+        using ComponentStackWidget::SetAutosize; \
+        using ComponentStackWidget::SetHorizonalAutosize; \
+        using ComponentStackWidget::SetVerticalAutosize; \
+        using ComponentStackWidget::GetHorizontalAutosize; \
+        using ComponentStackWidget::GetVerticalAutosize
+    
 } }
--- a/Source/Gorgon/Widgets/Button.h	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Button.h	Fri Dec 04 17:02:10 2020 +0200
@@ -119,10 +119,11 @@
         /// minimum time between the repeats.
         void ActivateClickRepeat(int delay = 500, int repeat = 400, int accelerationtime = 2000, int minrepeat = 200);
         
-        
         /// Deactivates click repeat.
         void DeactivateClickRepeat();
         
+        GORGON_UI_CSW_AUTOSIZABLE_WIDGET;
+        
         virtual bool Activate() override;
         
         bool KeyEvent(Input::Key key, float state) override;
--- a/Source/Gorgon/Widgets/Checkbox.h	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Checkbox.h	Fri Dec 04 17:02:10 2020 +0200
@@ -119,6 +119,8 @@
         
         virtual bool Activate() override;
         
+        GORGON_UI_CSW_AUTOSIZABLE_WIDGET;
+        
         bool KeyEvent(Input::Key key, float state) override;
 
         TextualProperty<Checkbox, std::string, &Checkbox::GetText, &Checkbox::SetText> Text;
--- a/Source/Gorgon/Widgets/Label.h	Fri Dec 04 12:40:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Label.h	Fri Dec 04 17:02:10 2020 +0200
@@ -76,6 +76,8 @@
         void OwnIcon(Graphics::Bitmap &&value);
         
         virtual bool Activate() override;
+        
+        GORGON_UI_CSW_AUTOSIZABLE_WIDGET;
 
         TextualProperty<Label, std::string, &Label::GetText, &Label::SetText> Text;
 
--- a/Testing/Source/Manual/UI_Component.cpp	Fri Dec 04 12:40:22 2020 +0200
+++ b/Testing/Source/Manual/UI_Component.cpp	Fri Dec 04 17:02:10 2020 +0200
@@ -2861,7 +2861,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -2894,7 +2894,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     
@@ -2930,7 +2930,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     
@@ -2966,7 +2966,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     
@@ -3006,7 +3006,7 @@
     cont4.Background.SetAnimation(yellowimg());
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     
@@ -3039,7 +3039,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3074,7 +3074,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3115,7 +3115,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3155,7 +3155,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3178,7 +3178,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3239,7 +3239,7 @@
 
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
     auto s = stack.GetSize();
@@ -3266,7 +3266,7 @@
     cont2.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
 
     auto &stack = *new ComponentStack(temp);
-    stack.SetAutoSize(true, true);
+    stack.SetAutosize(UI::Autosize::Automatic, UI::Autosize::Automatic);
 
     layer.Add(stack);
 
--- a/Testing/Source/Manual/UI_Generate.cpp	Fri Dec 04 12:40:22 2020 +0200
+++ b/Testing/Source/Manual/UI_Generate.cpp	Fri Dec 04 17:02:10 2020 +0200
@@ -295,6 +295,8 @@
         << sizef
     ;
     
+    btn.SetHorizonalAutosize(Gorgon::UI::Autosize::Unit);
+    
     Widgets::Window wind("My window", {200, 300});
     wind.Add(btn);
     wind.OwnIcon(icon.CreateAnimation());
@@ -306,6 +308,7 @@
     });
     btn.Move(0,0);
     Widgets::Checkbox enableclosebtn("Enable close button", true);
+    enableclosebtn.SetAutosize(Gorgon::UI::Autosize::Unit, Gorgon::UI::Autosize::Automatic);
     enableclosebtn.ChangedEvent.Register([&] { wind.SetCloseButtonEnabled(enableclosebtn); });
     wind.Add(enableclosebtn);
     wind.CreateOrganizer<UI::Organizers::List>() 

mercurial