Wed, 25 Mar 2020 21:57:18 +0200
#115 Progressbar class, generator and registry entry
* A bug in component stack prevents progressbar to work properly.
--- 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;