#115 Progressbar class, generator and registry entry 4.x-dev

Wed, 25 Mar 2020 21:57:18 +0200

author
cemkalyoncu
date
Wed, 25 Mar 2020 21:57:18 +0200
branch
4.x-dev
changeset 1389
f2e979f1631c
parent 1388
bf3de8a4c349
child 1390
d2cad48445cd

#115 Progressbar class, generator and registry entry
* A bug in component stack prevents progressbar to work properly.

Source/Gorgon/Geometry/Margin.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Helpers.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/dir.cmake file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Inputbox.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Progressbar.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Registry.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/dir.cmake file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Geometry/Margin.h	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Geometry/Margin.h	Wed Mar 25 21:57:18 2020 +0200
@@ -29,7 +29,7 @@
 		
 		/// Sets all Margin to the given value. Intentionally left implicit as Margin can
 		/// be represented as a simple integer
-		basic_Margin(T_ all) : Left(all), Right(all), Top(all), Bottom(all) { }
+		basic_Margin(T_ all) : Left(all), Top(all), Right(all), Bottom(all) { }
 		
 		/// Sets horizontal and vertical Margin separately
 		basic_Margin(T_ horizontal, T_ vertical) : Left(horizontal), Right(horizontal), 
@@ -37,7 +37,7 @@
 		
 		/// Sets all Margin separately
 		basic_Margin(T_ left, T_ top, T_ right, T_ bottom) : 
-			Left(left), Right(right), Top(top), Bottom(bottom) { }
+			Left(left), Top(top), Right(right), Bottom(bottom) { }
 
 		/// Converts this object to a string.
 		/// TODO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/UI/Helpers.h	Wed Mar 25 21:57:18 2020 +0200
@@ -0,0 +1,25 @@
+#pragma once
+
+namespace Gorgon { namespace UI {
+   
+    namespace internal {
+        template<class I_, class T_>
+        struct prophelper {
+            prophelper(I_ *obj) : obj(obj) {}
+
+            ~prophelper() { 
+                
+            }
+            
+            void set_(const T_&v) {
+                obj->set(v);
+            }
+            T_ get_() const {
+                return obj->get();
+            }
+
+            I_ *obj;
+        };
+    }
+    
+} }
--- a/Source/Gorgon/UI/dir.cmake	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/UI/dir.cmake	Wed Mar 25 21:57:18 2020 +0200
@@ -3,6 +3,7 @@
 	ComponentStack.h
 	ComponentStack.cpp
 	ComponentStackWidget.h
+	Helpers.h
 	Organizers
 	RadioControl.h
 	Template.h
--- a/Source/Gorgon/Widgets/Generator.cpp	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Generator.cpp	Wed Mar 25 21:57:18 2020 +0200
@@ -17,6 +17,7 @@
 namespace Gorgon { namespace OS {
     bool Start(const std::string &name, std::streambuf *&buf, const std::vector<std::string> &args);
 } }
+
 #endif
 #include "../Graphics/EmptyImage.h"
 
@@ -107,6 +108,7 @@
         delete hoverbg;
         delete downbg;
         delete disabledbg;
+        delete objectshape;
         
         for(auto p : panelborders) {
             delete p;
@@ -247,6 +249,15 @@
         return *disabledbg;
     }
 
+    Graphics::BitmapRectangleProvider &SimpleGenerator::ObjectShape() {
+        if(!objectshape) {
+            auto c = Forecolor.Regular;
+            objectshape = makeborder(0x0, c);
+        }
+
+        return *objectshape;
+    }
+
     Graphics::RectangleProvider &SimpleGenerator::FocusBorder() {
         if(!focusborder)
             focusborder = makefocusborder();
@@ -1296,5 +1307,32 @@
         return temp;
     }
 
+    UI::Template SimpleGenerator::Progressbar() {
+        Geometry::Size defsize = {WidgetWidth * 2 + Spacing, BorderedWidgetHeight};
+        
+        UI::Template temp;
+        temp.SetSize(defsize);
+        
+        {
+            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Always);
+         
+            bg.Background.SetAnimation(NormalBorder());
+            bg.SetPadding(Border.Width + Spacing);
+            
+            bg.AddIndex(1);
+        }
+        
+        {
+            auto &bar = temp.AddGraphics(1, UI::ComponentCondition::Always);
+            bar.SetSizing(UI::ComponentTemplate::Fixed);
+            bar.SetSize(100, 100, UI::Dimension::Percent);
+            bar.SetPositioning(UI::ComponentTemplate::AbsoluteSliding);
+            //bar.SetValueModification(UI::ComponentTemplate::ModifyX);
+            bar.Content.SetAnimation(ObjectShape());
+            bar.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        }
+        
+        return temp;
+    }
     
 }}
--- a/Source/Gorgon/Widgets/Generator.h	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Generator.h	Wed Mar 25 21:57:18 2020 +0200
@@ -53,6 +53,9 @@
         
         virtual UI::Template Inputbox() = 0;
         
+        
+        virtual UI::Template Progressbar() = 0;
+        
     protected:
         
         virtual UI::Template &generate(Gorgon::Widgets::Registry::TemplateType type) override {
@@ -85,6 +88,8 @@
                 return *new UI::Template(BottomPanel());
             case Panel_Right:
                 return *new UI::Template(RightPanel());
+            case Progress_Regular:
+                return *new UI::Template(Progressbar());
             default:
                 return *new UI::Template();
             }
@@ -130,6 +135,7 @@
 
         virtual UI::Template ErrorLabel() override;
         
+        
         virtual UI::Template BlankPanel() override;
         
         virtual UI::Template Panel() override;
@@ -145,6 +151,9 @@
         
         virtual UI::Template Inputbox() override;
         
+        
+        virtual UI::Template Progressbar() override;
+        
         Graphics::BitmapRectangleProvider &NormalBorder();
         Graphics::BitmapRectangleProvider &HoverBorder();
         Graphics::BitmapRectangleProvider &DownBorder();
@@ -162,6 +171,7 @@
         Graphics::BitmapRectangleProvider &HoverBG();
         Graphics::BitmapRectangleProvider &DownBG();
         Graphics::BitmapRectangleProvider &DisabledBG();
+        Graphics::BitmapRectangleProvider &ObjectShape();
         
         Graphics::RectangleProvider &FocusBorder();
         
@@ -248,6 +258,7 @@
         Graphics::BitmapRectangleProvider *hoverbg = nullptr;
         Graphics::BitmapRectangleProvider *downbg = nullptr;
         Graphics::BitmapRectangleProvider *disabledbg = nullptr;
+        Graphics::BitmapRectangleProvider *objectshape = nullptr;
         
         Graphics::RectangleProvider *focusborder = nullptr;
 
--- a/Source/Gorgon/Widgets/Inputbox.h	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Inputbox.h	Wed Mar 25 21:57:18 2020 +0200
@@ -7,31 +7,14 @@
 #include "../Property.h"
 #include "../UI/Validators.h"
 #include "../UI/ComponentStackWidget.h"
+#include "../UI/Helpers.h"
 #include "../Input/KeyRepeater.h"
 #include "Registry.h"
 
 namespace Gorgon { namespace Widgets {
     
     /// @cond internal
-    namespace internal {
-        template<class I_, class T_>
-        struct prophelper {
-            prophelper(I_ *obj) : obj(obj) {}
-
-            ~prophelper() { 
-                
-            }
-            
-            void set_(const T_&v) {
-                obj->set(v);
-            }
-            T_ get_() const {
-                return obj->get();
-            }
-
-            I_ *obj;
-        };
-        
+    namespace internal {        
         class Inputbox_base : public UI::ComponentStackWidget {
         protected:
             Inputbox_base(const UI::Template &temp);
@@ -342,18 +325,18 @@
     template<class T_, class V_ = UI::ConversionValidator<T_>, template<class C_, class PT_, PT_(C_::*Getter_)() const, void(C_::*Setter_)(const PT_ &)> class P_ = Gorgon::Property, Widgets::Registry::TemplateType DEFTMP_ = Widgets::Registry::Inputbox_Regular>
     class Inputbox : 
         public internal::Inputbox_base, 
-        public P_<internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_> {
+        public P_<UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_> {
 
 
     public:
         
         using Type     = T_;
-        using PropType = P_<internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_>;
+        using PropType = P_<UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_>;
 
-        friend class P_<internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_>;
+        friend class P_<UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_>;
         template<class T1_, class V1_, template<class C_, class PT_, PT_(C_::*Getter_)() const, void(C_::*Setter_)(const PT_&)> class P1_, Widgets::Registry::TemplateType DEFTMP1_>
         friend class Inputbox;
-        friend struct internal::prophelper<Inputbox<T_, V_, P_>, T_>;
+        friend struct UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>;
         
         /// Initializes the inputbox
         explicit Inputbox(const UI::Template &temp, T_ value = T_()) : 
@@ -466,7 +449,7 @@
         V_ validator;
         T_ value;
 
-        struct internal::prophelper<Inputbox<T_, V_, P_>, T_> helper = internal::prophelper<Inputbox<T_, V_, P_>, T_>(this);
+        struct UI::internal::prophelper<Inputbox<T_, V_, P_>, T_> helper = UI::internal::prophelper<Inputbox<T_, V_, P_>, T_>(this);
     };
     
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/Widgets/Progressbar.h	Wed Mar 25 21:57:18 2020 +0200
@@ -0,0 +1,222 @@
+#pragma once
+
+#include "../UI/ComponentStackWidget.h"
+#include "../UI/Helpers.h"
+#include "../Property.h"
+#include "Registry.h"
+
+namespace Gorgon { namespace Widgets {
+    
+    template<class T_>
+    float FloatDivider(T_ left, T_ min, T_ max) {
+        if(min == max) return 0.f;
+        
+        return float(left - min) / float(max - min);
+    }
+
+    template<
+        class T_ = int, 
+        float(*DIV_)(T_, T_, T_) = FloatDivider<T_>, 
+        template<class C_, class PT_, PT_(C_::*Getter_)() const, void(C_::*Setter_)(const PT_ &)> class P_ = Gorgon::NumericProperty
+    >
+    class Progressor : 
+        public UI::ComponentStackWidget,
+        public P_<
+            UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>, 
+            T_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::get_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::set_
+        >
+    {
+    public:
+        using Type     = T_;
+        using PropType = P_<
+            UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>, 
+            T_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::get_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::set_
+        >;
+        
+        friend class P_<
+            UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>, 
+            T_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::get_, 
+            &UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>::set_
+        >;
+        
+        template<
+            class T1_, 
+            float(*DIV1_)(T1_, T1_, T1_), 
+            template<
+                class C_, 
+                class PT_, 
+                PT_(C_::*Getter_)() const, 
+                void(C_::*Setter_)(const PT_&)
+            > class P1_
+        >
+        friend class Progressor;
+        
+        friend struct UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>;
+
+        Progressor(const Progressor &) = delete;
+        
+        explicit Progressor(T_ cur, T_ max, Registry::TemplateType type = Registry::Progress_Regular) : 
+            Progressor(Registry::Active()[type], cur, max) 
+        {
+        }
+        
+        explicit Progressor(T_ cur = T_{}, Registry::TemplateType type = Registry::Progress_Regular) : 
+            Progressor(Registry::Active()[type], cur) 
+        {
+        }
+
+        explicit Progressor(const UI::Template &temp, T_ cur = T_{}) : Progressor(temp, cur, T_{}) { }
+
+        Progressor(const UI::Template &temp, T_ cur, T_ max) : 
+            ComponentStackWidget(temp),
+            PropType(&helper), value(cur), max(max)
+        { 
+            refreshprogress();
+        }
+        
+        /// Sets the maximum value that this progressor reaches up to. If equal to minimum,
+        /// progress will display 0. Progressor will always keep the value between minimum
+        /// and maximum. If maximum is less than minimum, this function will automatically
+        /// exchange these values.
+        void SetMaximum(T_ value) {
+            if(value < min) {
+                max = min;
+                min = value;
+            }
+            else {
+                max = value;
+            }
+            
+            if(!setval(value)) //if returns true, refresh is already called
+                refreshprogress();
+        }
+        
+        /// Returns the current maximum value.
+        T_ GetMaximum() const {
+            return max;
+        }
+        
+        /// Sets the minimum value that this progressor reaches up to. If equal to maximum,
+        /// progress will display 0. Progressor will always keep the value between minimum
+        /// and maximum. If maximum is less than minimum, this function will automatically
+        /// exchange these values.
+        void SetMinimum(T_ value) {
+            if(value > max) {
+                min = max;
+                max = value;
+            }
+            else {
+                min = value;
+            }
+            
+            if(!setval(value)) //if returns true, refresh is already called
+                refreshprogress();
+        }
+        
+        /// Sets minimum and maximum limits. If minimum is equal to maximum,
+        /// progress will display 0. Progressor will always keep the value between minimum
+        /// and maximum. If maximum is less than minimum, this function will automatically
+        /// exchange these values if exchange is set. If exchange is not set, they will both
+        /// be set to T_{}, effectively locking progress at 0.
+        void SetLimits(T_ min, T_ max, bool exchange = true) {
+            if(min > max) {
+                if(exchange) {
+                    using std::swap;
+                    
+                    swap(min, max);
+                }
+                else {
+                    min = T_{};
+                    max = T_{};
+                }
+            }
+            
+            this->min = min;
+            this->max = max;
+            
+            if(setval(value)) //if returns true, refresh is already called
+                refreshprogress();
+        }
+        
+        /// Returns the current minimum value. 
+        T_ GetMinimum() const {
+            return min;
+        }
+        
+        /// Sets the current value of the progressor
+        Progressor &operator =(T_ value) {
+            set(value);
+            
+            return *this;
+        }
+        
+        /// Returns the current value of the progressor
+        operator T_() const {
+            return get();
+        }
+
+        virtual bool Activate() override {
+            return false;
+        }
+        
+        
+        Event<Progressor, T_> ProgressChanged = Event<Progressor, T_>(this);
+        
+        
+    protected:
+        virtual bool allowfocus() const override { return false; }
+        
+        /// Returns the value in the box
+        T_ get() const {
+            return value;
+        }
+        
+        /// Changes the value in the box
+        void set(const T_ &val) {
+            setval(val);
+        }
+        
+        bool setval(T_ val) {
+            if(val > max)
+                val = max;
+            
+            if(val < min)
+                val = min;
+            
+            if(value != val) {
+                value = val;
+                
+                ProgressChanged(value);
+            
+                refreshprogress();
+                
+                return true;
+            }
+            
+            return false;
+        }
+        
+        void refreshprogress() {
+            float progress = DIV_(value, min, max);
+            
+            stack.SetValue(progress);
+        }
+        
+        T_ value;
+        T_ min = T_{};
+        T_ max;
+        
+        
+    private:
+        struct UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_> helper = UI::internal::prophelper<Progressor<T_, DIV_, P_>, T_>(this);
+
+    };
+    
+    using Progressbar = Progressor<int>;
+    
+} }
--- a/Source/Gorgon/Widgets/Registry.h	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Widgets/Registry.h	Wed Mar 25 21:57:18 2020 +0200
@@ -36,6 +36,8 @@
             Panel_Bottom,
             Panel_Right,
             
+            Progress_Regular,
+            
             ///Do not use this value
             Max 
         };
--- a/Source/Gorgon/Widgets/dir.cmake	Mon Mar 23 06:56:22 2020 +0200
+++ b/Source/Gorgon/Widgets/dir.cmake	Wed Mar 25 21:57:18 2020 +0200
@@ -19,5 +19,7 @@
 	Panel.h
 	Panel.cpp
 	
+	Progressbar.h
+	
 	RadioButtons.h
 )
--- a/Testing/Source/Manual/UI_Generate.cpp	Mon Mar 23 06:56:22 2020 +0200
+++ b/Testing/Source/Manual/UI_Generate.cpp	Wed Mar 25 21:57:18 2020 +0200
@@ -11,6 +11,7 @@
 #include <Gorgon/Widgets/Textbox.h>
 #include <Gorgon/Widgets/Numberbox.h>
 #include <Gorgon/Widgets/GeometryBoxes.h>
+#include <Gorgon/Widgets/Progressbar.h>
 #include <Gorgon/UI/RadioControl.h>
 #include <Gorgon/UI/Organizers/List.h>
 #include <Gorgon/Graphics/BlankImage.h>
@@ -32,7 +33,7 @@
 
 int main() {
     basic_Application<UI::Window> app("uitest", "UI Generator Test", helptext, 1, 0x80);
-    
+    /*
     Widgets::SimpleGenerator gen;
     Widgets::SimpleGenerator gen2(12, "", false);
     gen.Init(15);
@@ -169,9 +170,16 @@
     inp.SelectAll();
     inp.ChangedEvent.Register([](Geometry::Point val) {
         std::cout << val << std::endl;
-    });
+    });*/
     //inp.Readonly = true;
 
+    Widgets::Progressbar progress;
+    
+    progress = 36;
+    
+    app.wind.Add(progress);
+    /*
+    pnl.Add(progress);
     pnl.Add(chk);
     pnl.Add(lbl);
     pnl.Add(error);
@@ -188,7 +196,7 @@
     //error.Move(lbl.GetLocation().X,lbl.GetLocation().Y + 25);
     lbl.OwnIcon(prep(*new Graphics::Bitmap(Triangle(8, 8))));
     
-    
+    */
     app.wind.Run();
 
     return 0;

mercurial