#337 New units: fractions and spaces 4.x-dev

Sun, 31 Oct 2021 07:34:15 +0200

author
cemkalyoncu
date
Sun, 31 Oct 2021 07:34:15 +0200
branch
4.x-dev
changeset 1751
c11e4d2ab93b
parent 1750
ed90f811fcba
child 1752
1a433508cd6c

#337 New units: fractions and spaces

Resources/Gorgon-gdb.py file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Dimension.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ScrollingWidget.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ScrollingWidget.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Widget.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Widget.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/WidgetContainer.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Panel.cpp file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Resources/Gorgon-gdb.py	Sat Oct 30 08:17:43 2021 +0300
+++ b/Resources/Gorgon-gdb.py	Sun Oct 31 07:34:15 2021 +0200
@@ -59,6 +59,14 @@
             s = str(s) + 'bp'
         elif(self.val['unit'] == 4):
             s = str(s) + 'em'
+        elif(self.val['unit'] == 5):
+            s = str(s) + 'units'
+        elif(self.val['unit'] == 6):
+            s = str(s) + 'munits'
+        elif(self.val['unit'] == 7):
+            s = str(s) + 'spcs'
+        elif(self.val['unit'] == 8):
+            s = str(s) + 'fr'
         else:
             s = str(s) + str(self.val['unit'])
             
@@ -71,7 +79,7 @@
     pp.add_printer('geometry-bounds', '^Gorgon::Geometry::basic_Bounds<.*>$', geometry_bounds)
     pp.add_printer('geometry-margin', '^Gorgon::Geometry::basic_Margin<.*>$', geometry_margin)
     pp.add_printer('geometry-rect', '^Gorgon::Geometry::basic_Rectangle<.*>$', geometry_rect)
-    pp.add_printer('ui-dimension', '^Gorgon::UI::Dimension$', ui_dim)
+    pp.add_printer('ui-dimension', '^Gorgon::UI::(Unit)?Dimension$', ui_dim)
     return pp;
 
 
--- a/Source/Gorgon/UI/Dimension.h	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/Dimension.h	Sun Oct 31 07:34:15 2021 +0200
@@ -38,9 +38,15 @@
             /// Size in units defined by UI scale. Uses UnitSize and spacing
             UnitSize,
 
-            /// Size in units defined by UI scale. Uses UnitSize and spacing
+            /// Size in units defined by UI scale. Uses UnitSize and spacing.
             MilliUnitSize,
 
+            /// Spaces defined by UI scale.
+            Spaces,
+
+            /// Fractions of the container. Defaults to 6 if not set.
+            Fractions
+
         };
     private:
 
@@ -78,20 +84,22 @@
         }
 
         /// Returns the calculated dimension in pixels
-        constexpr int operator ()(int parentwidth, int unitsize, int spacing, int emwidth = 10, bool issize = false) const {
-            return Calculate(parentwidth, unitsize, spacing, emwidth, issize);
+        constexpr int operator ()(int parentwidth, int unitsize, int spacing, int emwidth = 10, int fractions = 6, bool issize = false) const {
+            return Calculate(parentwidth, unitsize, spacing, emwidth, fractions, issize);
         }
 
         /// Returns the calculated dimension in pixels
-        constexpr int Calculate(int parentwidth, int unitsize, int spacing, int emwidth = 10, bool issize = false) const {
+        constexpr int Calculate(int parentwidth, int unitsize, int spacing, int emwidth = 10, int fractions = 6, bool issize = false) const {
             if(issize) {
                 switch(unit) {
                 case Percent:
                     return int(std::floor((double)value * parentwidth / 100));
+                case BasisPoint:
+                    return int(std::floor((double)value * parentwidth / 10000));
+                case Fractions:
+                    return int(std::floor((double)value * parentwidth / fractions));
                 case MilliPixel:
                     return int(std::floor((double)value / 1000));
-                case BasisPoint:
-                    return int(std::floor((double)value * parentwidth / 10000));
                 case EM:
                     return int(std::round(value * emwidth / 100));
                 case UnitSize:
@@ -102,6 +110,8 @@
                     if(value >= -1000 && value <= 1000)
                         return int(std::floor((double)value * unitsize / 1000));
                     return int(std::floor(((double)value * unitsize + (double)(value - 1000) * spacing) / 1000));
+                case Spaces:
+                    return value * spacing;
                 case Pixel:
                 default:
                     return value;
@@ -111,16 +121,20 @@
                 switch(unit) {
                 case Percent:
                     return int(std::round((double)value * parentwidth / 100));
+                case BasisPoint:
+                    return int(std::round((double)value * parentwidth / 10000));
+                case Fractions:
+                    return int(std::floor((double)value * parentwidth / fractions));
                 case MilliPixel:
                     return int(std::round((double)value / 1000));
-                case BasisPoint:
-                    return int(std::round((double)value * parentwidth / 10000));
                 case EM:
                     return int(std::round(value * emwidth / 100));
                 case UnitSize:
                     return value * (unitsize + spacing);
                 case MilliUnitSize:
                     return int(std::round((double)value * (unitsize + spacing) / 1000));
+                case Spaces:
+                    return value * spacing;
                 case Pixel:
                 default:
                     return value;
@@ -129,33 +143,62 @@
         }
 
         /// Returns the calculated dimension in pixels
-        constexpr float CalculateFloat(float parentwidth, int unitsize, int spacing, float emwidth = 10, bool issize = false) const {
-            switch(unit) {
-                case Percent:
-                    return (float)value * parentwidth / 100.f;
-                case BasisPoint:
-                    return (float)value * parentwidth / 10000.f;
-                case MilliPixel:
-                    return (float)value / 1000;
-                case EM:
-                    return (float)value * emwidth / 100.f;
-                case UnitSize:
-                    if(!issize || (value >= -1 && value <= 1))
-                        return value * unitsize;
-                    return value * unitsize + (value - 1) * spacing;
-                case MilliUnitSize:
-                    if(!issize || (value >= -1000 && value <= 1000))
-                        return (float)value * unitsize / 1000;
-                    return ((float)value * unitsize + (float)(value - 1000) * spacing) / 1000;
-                case Pixel:
-                default:
-                    return (float)value;
+        constexpr float CalculateFloat(float parentwidth, int unitsize, int spacing, float emwidth = 10, int fractions = 6, bool issize = false) const {
+            if(issize) {
+                switch(unit) {
+                    case Percent:
+                        return (float)value * parentwidth / 100.f;
+                    case BasisPoint:
+                        return (float)value * parentwidth / 10000.f;
+                    case Fractions:
+                        return (float)value * parentwidth / fractions;
+                    case MilliPixel:
+                        return (float)value / 1000;
+                    case EM:
+                        return (float)value * emwidth / 100.f;
+                    case UnitSize:
+                        if(!issize || (value >= -1 && value <= 1))
+                            return value * unitsize;
+                        return value * unitsize + (value - 1) * spacing;
+                    case MilliUnitSize:
+                        if(!issize || (value >= -1000 && value <= 1000))
+                            return (float)value * unitsize / 1000;
+                        return ((float)value * unitsize + (float)(value - 1000) * spacing) / 1000;
+                    case Spaces:
+                        return float(value * spacing);
+                    case Pixel:
+                    default:
+                        return (float)value;
+                }
+            }
+            else {
+                switch(unit) {
+                    case Percent:
+                        return (float)value * parentwidth / 100.f;
+                    case BasisPoint:
+                        return (float)value * parentwidth / 10000.f;
+                    case Fractions:
+                        return (float)value * parentwidth / fractions;
+                    case MilliPixel:
+                        return (float)value / 1000;
+                    case EM:
+                        return (float)value * emwidth / 100.f;
+                    case UnitSize:
+                        return value * (unitsize + spacing);
+                    case MilliUnitSize:
+                        return (float)value * (unitsize + spacing) / 1000;
+                    case Spaces:
+                        return float(value * spacing);
+                    case Pixel:
+                    default:
+                        return (float)value;
+                }
             }
         }
         
         /// Returns if the dimension is relative to the parentwidth
         constexpr bool IsRelative() const {
-            return unit == Percent || unit == BasisPoint;
+            return unit == Percent || unit == BasisPoint || unit == Fractions;
         }
 
         /// Returns the value of the dimension, should not be considered as
@@ -188,7 +231,7 @@
             return !(*this == other);
         }
 
-    private:
+    protected:
         int value;
         Unit unit;
     };
@@ -209,7 +252,7 @@
         constexpr UnitDimension(const Dimension &d) : Dimension(d) { }
 
         bool operator ==(const UnitDimension &other) const {
-            return (const Unit&)(*this) == (const Unit&)(other);
+            return other.unit == unit && other.value == value;
         }
 
         bool operator !=(const UnitDimension &other) const {
@@ -233,28 +276,28 @@
     using Margin = Geometry::basic_Margin<Dimension>;
     
     /// Converts a dimension based point to pixel based point
-    inline Geometry::Point Convert(const Point &p, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10) {
-        return {p.X(parent.Width, unitsize, spacing, emwidth), p.Y(parent.Height, unitsize, spacing, emwidth)};
+    inline Geometry::Point Convert(const Point &p, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10, int fractions = 6) {
+        return {p.X(parent.Width, unitsize, spacing, emwidth, fractions), p.Y(parent.Height, unitsize, spacing, emwidth, fractions)};
     }
 
     /// Converts a dimension based size to pixel based size
-    inline Geometry::Size Convert(const Size &s, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10) {
-        return {s.Width(parent.Width, unitsize, spacing, emwidth, true), s.Height(parent.Height, unitsize, spacing, emwidth, true)};
+    inline Geometry::Size Convert(const Size &s, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10, int fractions = 6) {
+        return {s.Width(parent.Width, unitsize, spacing, emwidth, fractions, true), s.Height(parent.Height, unitsize, spacing, emwidth, fractions, true)};
     }
 
     /// Converts a dimension based point to pixel based point
-    inline Geometry::Point Convert(const UnitPoint &p, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10) {
-        return {p.X(parent.Width, unitsize, spacing, emwidth), p.Y(parent.Height, unitsize, spacing, emwidth)};
+    inline Geometry::Point Convert(const UnitPoint &p, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10, int fractions = 6) {
+        return {p.X(parent.Width, unitsize, spacing, emwidth, fractions), p.Y(parent.Height, unitsize, spacing, emwidth, fractions)};
     }
 
     /// Converts a dimension based size to pixel based size
-    inline Geometry::Size Convert(const UnitSize &s, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10) {
-        return {s.Width(parent.Width, unitsize, spacing, emwidth, true), s.Height(parent.Height, unitsize, spacing, emwidth, true)};
+    inline Geometry::Size Convert(const UnitSize &s, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10, int fractions = 6) {
+        return {s.Width(parent.Width, unitsize, spacing, emwidth, fractions, true), s.Height(parent.Height, unitsize, spacing, emwidth, fractions, true)};
     }
 
     /// Converts a dimension based margin to pixel based margin
-    inline Geometry::Margin Convert(const Margin &m, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10) {
-        return {m.Left(parent.Width, unitsize, spacing, emwidth), m.Top(parent.Height, unitsize, spacing, emwidth), m.Right(parent.Width, unitsize, spacing, emwidth), m.Bottom(parent.Height, unitsize, spacing, emwidth), };
+    inline Geometry::Margin Convert(const Margin &m, const Geometry::Size &parent, int unitsize, int spacing, int emwidth = 10, int fractions = 6) {
+        return {m.Left(parent.Width, unitsize, spacing, emwidth, fractions), m.Top(parent.Height, unitsize, spacing, emwidth, fractions), m.Right(parent.Width, unitsize, spacing, emwidth, fractions), m.Bottom(parent.Height, unitsize, spacing, emwidth, fractions), };
     }
 
     /// Converts the given value to dimension with pixel units
@@ -277,6 +320,11 @@
         return {val, Dimension::Percent};
     }
 
+    /// Converts the given value to dimension with fractions units
+    inline constexpr Dimension Fractions(int val) {
+        return {val, Dimension::Fractions};
+    }
+
     /// Converts the given value to dimension with unit size
     inline constexpr Dimension Units(int val) {
         return {val, Dimension::UnitSize};
@@ -333,6 +381,11 @@
         return {{one, Dimension::Percent}, {two, Dimension::Percent}};
     }
 
+    /// Converts the given value to dimension with percentage units
+    inline constexpr DualDimension Fractions(int one, int two) {
+        return {{one, Dimension::Fractions}, {two, Dimension::Fractions}};
+    }
+
     /// Converts the given one, given twoue to dimension with unit size
     inline constexpr DualDimension Units(int one, int two) {
         return {{one, Dimension::UnitSize}, {two, Dimension::UnitSize}};
@@ -358,6 +411,11 @@
         return {{val.X, Dimension::Percent}, {val.Y, Dimension::Percent}};
     }
 
+    /// Converts the given value to dimension with percentage units
+    inline Point Fractions(const Geometry::Point &val) {
+        return {{val.X, Dimension::Fractions}, {val.Y, Dimension::Fractions}};
+    }
+
     /// Converts the given value to dimension with unit size
     inline Point Units(const Geometry::Point &val) {
         return {{val.X, Dimension::UnitSize}, {val.Y, Dimension::UnitSize}};
@@ -373,6 +431,11 @@
         return {{val.Width, Dimension::Percent}, {val.Height, Dimension::Percent}};
     }
 
+    /// Converts the given value to dimension with percentage units
+    inline Size Fractions(const Geometry::Size &val) {
+        return {{val.Width, Dimension::Fractions}, {val.Height, Dimension::Fractions}};
+    }
+
     /// Converts the given value to dimension with unit size
     inline Size Units(const Geometry::Size &val) {
         return {{val.Width, Dimension::UnitSize}, {val.Height, Dimension::UnitSize}};
@@ -411,6 +474,13 @@
             return {double(val), Dimension::EM};
         }
 
+        inline Dimension operator""_spcs(unsigned long long val) {
+            return {int(val), Dimension::Spaces};
+        }
+
+        inline Dimension operator""_fr(unsigned long long val) {
+            return {int(val), Dimension::Fractions};
+        }
 
     }
 
--- a/Source/Gorgon/UI/ScrollingWidget.cpp	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/ScrollingWidget.cpp	Sun Oct 31 07:34:15 2021 +0200
@@ -155,7 +155,7 @@
         auto vscroller = dynamic_cast<Widgets::VScrollbar*>(stack.GetWidget(UI::ComponentTemplate::VScrollTag));
         
         if(vscroller != nullptr) {
-            vscroller->Maximum = b.Height() + overscroll;
+            vscroller->Maximum = b.Height() + overscrollpx;
             vscroller->Range   = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).Height();
             *vscroller         = target.Y;
         }
@@ -163,14 +163,15 @@
         auto hscroller = dynamic_cast<Widgets::HScrollbar*>(stack.GetWidget(UI::ComponentTemplate::HScrollTag));
         
         if(hscroller != nullptr) {
-            hscroller->Maximum = b.Width() + overscroll;
+            hscroller->Maximum = b.Width() + overscrollpx;
             hscroller->Range   = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).Width();
             *hscroller         = target.X;
         }
     }
     
-    void ScrollingWidget::SetOverscroll(int value) {
+    void ScrollingWidget::SetOverscroll(const UnitDimension &value) {
         overscroll = value;
+        overscrollpx = Convert(overscroll, true);
         
         updatebars();
         
@@ -187,14 +188,14 @@
         if(xscroll <= 0)
             xscroll = 0;
         else
-            xscroll += overscroll;
+            xscroll += overscrollpx;
         
         int yscroll = cont.Height() - size.Height;
         
         if(yscroll <= 0)
             yscroll = 0;
         else
-            yscroll += overscroll;
+            yscroll += overscrollpx;
         
         return {xscroll, yscroll};
     }
@@ -306,7 +307,7 @@
                 doscroll = true;
             }
             else if(cb.Right < wb.Right) {
-                scrollto.X = target.X + (wb.Right - cb.Right) + overscroll;
+                scrollto.X = target.X + (wb.Right - cb.Right) + overscrollpx;
                 doscroll = true;
             }
         }
@@ -317,7 +318,7 @@
                 doscroll = true;
             }
             else if(cb.Bottom < wb.Bottom) {
-                scrollto.Y = target.Y + (wb.Bottom - cb.Bottom) + overscroll;
+                scrollto.Y = target.Y + (wb.Bottom - cb.Bottom) + overscrollpx;
                 doscroll = true;
             }
         }
@@ -348,6 +349,7 @@
         ComponentStackWidget::parentboundschanged();
         scrolldistpx = Convert(scrolldist);
         scrollspeedpx = Convert(scrollspeed, true);
+        overscrollpx = Convert(overscroll, true);
     }
 
 } }
--- a/Source/Gorgon/UI/ScrollingWidget.h	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/ScrollingWidget.h	Sun Oct 31 07:34:15 2021 +0200
@@ -20,11 +20,11 @@
         /// Sets the amount of extra scrolling distance after the bottom-most
         /// widget is completely visible in pixels. Default is 0. Does not
         /// apply if everything is visible.
-        void SetOverscroll(int value);
+        void SetOverscroll(const UnitDimension &value);
         
         /// Returns the amount of extra scrolling distance after the bottom-most
         /// widget is completely visible in pixels.
-        int GetOverscroll() const {
+        UnitDimension GetOverscroll() const {
             return overscroll;
         }
         
@@ -131,7 +131,8 @@
 
         virtual void parentboundschanged() override;
         
-        int overscroll = 0;
+        int overscrollpx = 0;
+        UnitDimension overscroll = 0;
         bool scrollclipped = true;
         Geometry::Point scrolldistpx = {108, 54};
         UnitPoint scrolldist = Units(4, 2);
--- a/Source/Gorgon/UI/Widget.cpp	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/Widget.cpp	Sun Oct 31 07:34:15 2021 +0200
@@ -137,12 +137,13 @@
     }
 
     void Widget::calculatebounds() {
-        int unitsize = 0, spacing = 0;
+        int unitsize = 0, spacing = 0, fr = 6;
         Geometry::Size sz;
         if(HasParent()) {
             unitsize = GetParent().GetUnitSize();
             spacing = GetParent().GetSpacing();
             sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
+            fr = GetParent().GetFractionCount();
         }
         else {
             unitsize = Widgets::Registry::Active().GetUnitSize();
@@ -153,7 +154,8 @@
         auto l= UI::Convert(
             location, sz,
             unitsize, spacing,
-            Widgets::Registry::Active().GetEmSize()
+            Widgets::Registry::Active().GetEmSize(),
+            fr
         );
 
         if(llocation != l) {
@@ -164,13 +166,13 @@
         auto s = UI::Convert(
             size, sz,
             unitsize, spacing,
-            Widgets::Registry::Active().GetEmSize()
+            Widgets::Registry::Active().GetEmSize(),
+            fr
         );
 
         if(size.Width.IsRelative()) {
             s.Width -= spacing;
         }
-
         if(size.Height.IsRelative()) {
             s.Height -= spacing;
         }
@@ -200,63 +202,27 @@
     }
 
     int Widget::Convert(const UnitDimension &val, bool vertical, bool size) const {
-        int unitsize = 0, spacing = 0;
-        Geometry::Size sz;
-        if(HasParent()) {
-            unitsize = GetParent().GetUnitSize();
-            spacing = GetParent().GetSpacing();
-            sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
-        }
-        else {
-            unitsize = Widgets::Registry::Active().GetUnitSize();
-            spacing  = Widgets::Registry::Active().GetSpacing();
-            sz = GetCurrentSize();
-        }
-
-        return val(vertical ? sz.Height : sz.Width, unitsize, spacing, size, Widgets::Registry::Active().GetEmSize());
+        return Convert(Dimension::Pixel, val, vertical, size).GetValue();
     }
 
     Geometry::Size Widget::Convert(const UnitSize &val) const {
-        int unitsize = 0, spacing = 0;
+        auto s = Convert(Dimension::Pixel, val);
+        return {s.Width.GetValue(), s.Height.GetValue()};
+    }
+
+    Geometry::Point Widget::Convert(const UnitPoint &val) const {
+        auto p = Convert(Dimension::Pixel, val);
+        return {p.X.GetValue(), p.Y.GetValue()};
+    }
+
+    UnitDimension Widget::Convert(Dimension::Unit target, const UnitDimension &val, bool vertical, bool size) const {
+        int unitsize = 0, spacing = 0, fr = 6;
         Geometry::Size sz;
         if(HasParent()) {
             unitsize = GetParent().GetUnitSize();
             spacing = GetParent().GetSpacing();
             sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
-        }
-        else {
-            unitsize = Widgets::Registry::Active().GetUnitSize();
-            spacing  = Widgets::Registry::Active().GetSpacing();
-            sz = GetCurrentSize();
-        }
-
-        return UI::Convert(val, sz, unitsize, spacing, Widgets::Registry::Active().GetEmSize());
-    }
-
-    Geometry::Point Widget::Convert(const UnitPoint &val) const {
-        int unitsize = 0, spacing = 0;
-        Geometry::Size sz;
-        if(HasParent()) {
-            unitsize = GetParent().GetUnitSize();
-            spacing = GetParent().GetSpacing();
-            sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
-        }
-        else {
-            unitsize = Widgets::Registry::Active().GetUnitSize();
-            spacing  = Widgets::Registry::Active().GetSpacing();
-            sz = GetCurrentSize();
-        }
-
-        return UI::Convert(val, sz, unitsize, spacing, Widgets::Registry::Active().GetEmSize());
-    }
-
-    UnitDimension Widget::Convert(Dimension::Unit target, const UnitDimension &val, bool vertical, bool size) const {
-        int unitsize = 0, spacing = 0;
-        Geometry::Size sz;
-        if(HasParent()) {
-            unitsize = GetParent().GetUnitSize();
-            spacing = GetParent().GetSpacing();
-            sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
+            fr = GetParent().GetFractionCount();
         }
         else {
             unitsize = Widgets::Registry::Active().GetUnitSize();
@@ -266,7 +232,11 @@
 
         int em = Widgets::Registry::Active().GetEmSize();
 
-        int px = val(vertical ? sz.Height : sz.Width, unitsize, spacing, size, em);
+        int px = val(vertical ? sz.Height : sz.Width, unitsize, spacing, em, fr, size);
+
+        if(size && val.IsRelative()) {
+            px -= spacing;
+        }
 
         switch(target) {
         case Dimension::Pixel:
@@ -276,25 +246,28 @@
             return {(float)px, Dimension::MilliPixel};
         case Dimension::Percent:
         case Dimension::BasisPoint:
-            return {(float)px/(vertical ? sz.Height : sz.Width), target};
+            return {(float)(px+size*spacing)/(vertical ? sz.Height : sz.Width), target};
         case Dimension::UnitSize:
         case Dimension::MilliUnitSize:
             if(size)
-                return {(float)(px+spacing)/(unitsize+spacing), target};
+                return {(float)(px+size*spacing)/(unitsize+spacing), target};
             else
-                return {(float)px/(unitsize+spacing), target};
+                return {(float)px/(unitsize+size*spacing), target};
+        case Dimension::Fractions:
+                return {(int)std::round((float)fr * (px+size*spacing) / (vertical ? sz.Height : sz.Width)), target};
         case Dimension::EM:
             return {(float)px/em, Dimension::EM};
         }
     }
 
     UnitSize Widget::Convert(Dimension::Unit target, const UnitSize &val) const {
-        int unitsize = 0, spacing = 0;
+        int unitsize = 0, spacing = 0, fr = 6;
         Geometry::Size sz;
         if(HasParent()) {
             unitsize = GetParent().GetUnitSize();
             spacing = GetParent().GetSpacing();
             sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
+            fr = GetParent().GetFractionCount();
         }
         else {
             unitsize = Widgets::Registry::Active().GetUnitSize();
@@ -304,7 +277,14 @@
 
         int em = Widgets::Registry::Active().GetEmSize();
 
-        auto px = UI::Convert(val, sz, unitsize, spacing, em);
+        auto px = UI::Convert(val, sz, unitsize, spacing, em, fr);
+
+        if(val.Width.IsRelative()) {
+            px.Width -= spacing;
+        }
+        if(val.Height.IsRelative()) {
+            px.Height -= spacing;
+        }
 
         switch(target) {
         case Dimension::Pixel:
@@ -314,22 +294,28 @@
             return {{(float)px.Width, target}, {(float)px.Height, target}};;
         case Dimension::Percent:
         case Dimension::BasisPoint:
-            return {{(float)px.Width/sz.Width, target}, {(float)px.Height/sz.Height, target}};;
+            return {{(float)(px.Width+spacing)/sz.Width, target}, {(float)(px.Height+spacing)/sz.Height, target}};;
         case Dimension::UnitSize:
         case Dimension::MilliUnitSize:
             return {{(float)(px.Width+spacing)/(unitsize+spacing), target}, {(float)(px.Height+spacing)/(unitsize+spacing), target}};
+        case Dimension::Fractions:
+                return {
+                    {(int)std::round((float)fr * (px.Width+spacing) / sz.Width), target},
+                    {(int)std::round((float)fr * (px.Height+spacing) / sz.Height), target},
+                };
         case Dimension::EM:
             return {{(float)px.Width/em, Dimension::EM}, {(float)px.Height/em, Dimension::EM}};;
         }
     }
 
     UnitPoint Widget::Convert(Dimension::Unit target, const UnitPoint &val) const {
-        int unitsize = 0, spacing = 0;
+        int unitsize = 0, spacing = 0, fr = 6;
         Geometry::Size sz;
         if(HasParent()) {
             unitsize = GetParent().GetUnitSize();
             spacing = GetParent().GetSpacing();
             sz = GetParent().GetInteriorSize() + Geometry::Size(spacing, spacing);
+            fr = GetParent().GetFractionCount();
         }
         else {
             unitsize = Widgets::Registry::Active().GetUnitSize();
@@ -339,8 +325,7 @@
 
         int em = Widgets::Registry::Active().GetEmSize();
 
-
-        auto px = UI::Convert(val, sz, unitsize, spacing, em);
+        auto px = UI::Convert(val, sz, unitsize, spacing, em, fr);
 
         switch(target) {
         case Dimension::Pixel:
@@ -354,6 +339,11 @@
         case Dimension::UnitSize:
         case Dimension::MilliUnitSize:
             return {{(float)px.X/(unitsize+spacing), target}, {(float)px.Y/(unitsize+spacing), target}};
+        case Dimension::Fractions:
+                return {
+                    {(int)std::round((float)fr * px.X / sz.Width), target},
+                    {(int)std::round((float)fr * px.Y / sz.Height), target},
+                };
         case Dimension::EM:
             return {{(float)px.X/em, Dimension::EM}, {(float)px.Y/em, Dimension::EM}};;
         }
--- a/Source/Gorgon/UI/Widget.h	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/Widget.h	Sun Oct 31 07:34:15 2021 +0200
@@ -210,7 +210,7 @@
         }
 
         /// Converts the given size in units to pixels
-        int Convert(const UnitDimension &val, bool vertical, bool size = false) const;
+        int Convert(const UnitDimension &val, bool isvertical, bool issize = false) const;
 
         /// Converts the given size in units to pixels
         Geometry::Size Convert(const UnitSize &size) const;
@@ -219,7 +219,7 @@
         Geometry::Point Convert(const UnitPoint &location) const;
 
         /// Converts the given size in units to requested units.
-        UnitDimension Convert(Dimension::Unit target, const UnitDimension &val, bool vertical, bool size = false) const;
+        UnitDimension Convert(Dimension::Unit target, const UnitDimension &val, bool isvertical, bool issize = false) const;
 
         /// Converts the given size in units to requested units.
         UnitSize Convert(Dimension::Unit target, const UnitSize &size) const;
--- a/Source/Gorgon/UI/WidgetContainer.h	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/UI/WidgetContainer.h	Sun Oct 31 07:34:15 2021 +0200
@@ -537,6 +537,24 @@
             return n*GetUnitSize() + (n-1)*GetSpacing();
         }
 
+        /// Number of fractions that this container have. This value can
+        /// be ignored and the used value can be calculated by the
+        /// organizers. Default value is 6.
+        void SetFractionCount(int value) {
+            if(value == fractions)
+                return;
+
+            fractions = value;
+            distributeparentboundschanged();
+        }
+
+        /// Number of fractions that this container have. This value can
+        /// be ignored and the used value can be calculated by the
+        /// organizers. Default value is 6.
+        int GetFractionCount() const {
+            return fractions;
+        }
+
     protected:
         /// This container is sorted by the focus order
         Containers::Collection<Widget> widgets;
@@ -594,6 +612,8 @@
         virtual void deleted(Widget *widget);
 
         Containers::Collection<const Widget> owned;
+
+        int fractions = 6;
         
     private:
         bool isenabled              = true;
--- a/Source/Gorgon/Widgets/Panel.cpp	Sat Oct 30 08:17:43 2021 +0300
+++ b/Source/Gorgon/Widgets/Panel.cpp	Sun Oct 31 07:34:15 2021 +0200
@@ -294,12 +294,12 @@
     }
 
 
-void Panel::Resize(const UI::UnitSize& size, std::pair< bool, bool > interiorsized) {
-    if(this->interiorsized != interiorsized)
-        lsize = {-1, -1};
-    this->interiorsized = interiorsized;
-    ComponentStackWidget::Resize(size);
-}
+    void Panel::Resize(const UI::UnitSize& size, std::pair< bool, bool > interiorsized) {
+        if(this->interiorsized != interiorsized)
+            lsize = {-1, -1};
+        this->interiorsized = interiorsized;
+        ComponentStackWidget::Resize(size);
+    }
 
 } }
 
--- a/Testing/Source/Manual/UI_Generate.cpp	Sat Oct 30 08:17:43 2021 +0300
+++ b/Testing/Source/Manual/UI_Generate.cpp	Sun Oct 31 07:34:15 2021 +0200
@@ -25,6 +25,7 @@
 #include <Gorgon/Widgets/Dropdown.h>
 #include <Gorgon/Widgets/Window.h>
 #include <Gorgon/Widgets/DialogWindow.h>
+#include <Gorgon/Widgets/ColorPicker.h>
 #include <Gorgon/UI/Dialog.h>
 #include <Gorgon/OS.h>
 
@@ -124,9 +125,9 @@
     Gorgon::Widgets::Button icnbtn2("Âj", Gorgon::Widgets::Registry::Button_Icon);
     Gorgon::Widgets::Button icnbtn3("X", Gorgon::Widgets::Registry::Button_Icon);
     btn.OwnIcon(icon2.CreateAnimation());
-    btn.Size.Width = 50_perc;
-    btn2.Size.Width = 50_perc;
-    btn2.Location.X = 50_perc;
+    btn.Size.Width = 2_fr;
+    btn2.Size.Width = 3_fr;
+    btn2.Location.X = 2_fr;
 
     icnbtn.OwnIcon(icon2.CreateAnimation());
 
@@ -203,7 +204,7 @@
     scroll2.Range = 20;
     //scroll2.SetValue(200, false);
 
-    Gorgon::Widgets::Inputbox<Graphics::RGBAf> colorin;
+    /*Gorgon::Widgets::Inputbox<Graphics::RGBAf>*/Gorgon::Widgets::ColorPicker colorin;
     colorin.ChangedEvent.Register([&] {
         std::cout << "size f changed " << colorin.GetText();
     });
@@ -295,7 +296,7 @@
     
     
     auto &org = blank.CreateOrganizer<UI::Organizers::Flow>();
-    blank.SetOverscroll(15);
+    blank.SetOverscroll(5_spcs);
 
     //org.SetAlignment(org.Center);
     
@@ -321,6 +322,7 @@
     wind.Add(btn);
     wind.Add(btn2);
     wind.SetMinSize({6,1});
+    wind.SetFractionCount(5);
     wind.SetMaxSize({50_perc,8});
     btn.Move(Pixels(0,0));
     btn.Disable();
@@ -370,7 +372,7 @@
         );
     }).SetHorizonalAutosize(Gorgon::UI::Autosize::Automatic);
 
-    wind.Move(20_perc, 5_perc);
+    wind.Move(35_perc, 5_perc);
     
     Widgets::Label tiplabel("Some text here", Gorgon::Widgets::Registry::Label_Info);
     tiplabel.SetAutosize(Gorgon::UI::Autosize::None, Gorgon::UI::Autosize::Automatic);

mercurial