* Dimension now includes UnitSize 4.x-dev

Fri, 22 Oct 2021 06:46:12 +0300

author
cemkalyoncu
date
Fri, 22 Oct 2021 06:46:12 +0300
branch
4.x-dev
changeset 1739
e2466f630836
parent 1738
dfb250be177d
child 1740
fe1c233c3a96

* Dimension now includes UnitSize

Source/Gorgon/UI/ComponentStack.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ComponentStack.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Dimension.h file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/UI/ComponentStack.cpp	Fri Oct 22 05:44:20 2021 +0300
+++ b/Source/Gorgon/UI/ComponentStack.cpp	Fri Oct 22 06:46:12 2021 +0300
@@ -40,7 +40,9 @@
         size(size),
         temp(temp),
         widgetgenerators(generators),
-        adapter(*this)
+        adapter(*this),
+        unitsize(temp.GetUnitSize()),
+        spacing(temp.GetSpacing())
     {
         //find the number of elements required in the stack
         int maxindex = 0;
@@ -1161,7 +1163,7 @@
             
             case ComponentTemplate::ModifyRotation: {
                 int emsize = getemsize(*comp);
-                pnt -=  Convert(ct.GetCenter(), comp->size, emsize);
+                pnt -=  Convert(ct.GetCenter(), comp->size, unitsize, spacing, emsize);
                 
                 //TODO calculate the angle from the center and use it
                 break;
@@ -2578,11 +2580,11 @@
             //calculate maximum size for non-oriented direction and oriented direction for absolutely placed
             //components.
             auto parentmargin = Convert(
-                temp.GetMargin(), parent.innersize, emsize
+                temp.GetMargin(), parent.innersize, unitsize, spacing, emsize
                 ).CombinePadding(
-                    Convert(cont.GetPadding(), parent.innersize, emsize)
+                    Convert(cont.GetPadding(), parent.innersize, unitsize, spacing, emsize)
                 ) + 
-                Convert(temp.GetIndent(), parent.innersize, emsize);
+                Convert(temp.GetIndent(), parent.innersize, unitsize, spacing, emsize);
             
             auto maxsize = parent.innersize - parentmargin;
             int  curtw   = (textwidth == -1 ? maxsize.Width : textwidth) - parentmargin.TotalX();
@@ -2765,42 +2767,42 @@
             
             //this will convert width to pixels
             if(widthch == -1) { //value channel is not in effect
-                comp.size.Width = size.Width(maxsize.Width - tagsize.Width, emsize) + tagsize.Width;
-                curtw = size.Width(curtw - tagsize.Width, emsize) + tagsize.Width;
+                comp.size.Width = size.Width(maxsize.Width - tagsize.Width, unitsize, spacing, emsize) + tagsize.Width;
+                curtw = size.Width(curtw - tagsize.Width, unitsize, spacing, emsize) + tagsize.Width;
             }
             else {//calculate and use value channel
                 //original width will be used as minimum size
-                auto min = size.Width(maxsize.Width, emsize) + tagsize.Width;
+                auto min = size.Width(maxsize.Width, unitsize, spacing, emsize) + tagsize.Width;
                 
                 //calculate value and use it as basis point as relative size, then covert to pixels
                 comp.size.Width = 
                     Dimension{
                         int(calculatevalue(val, widthch, comp)*10000), Dimension::BasisPoint
-                    } (maxsize.Width - min, emsize)
+                    } (maxsize.Width - min, unitsize, spacing, emsize)
                     + min;
                 
-                min = size.Width(curtw, emsize) + tagsize.Width;
+                min = size.Width(curtw, unitsize, spacing, emsize) + tagsize.Width;
                 curtw = 
                     Dimension{
                         int(calculatevalue(val, widthch, comp)*10000), Dimension::BasisPoint
-                    } (curtw - min, emsize)
+                    } (curtw - min, unitsize, spacing, emsize)
                     + min;
                     
             }
             
             //this will convert height to pixels
             if(heightch == -1) { //value channel is not in effect
-                comp.size.Height = size.Height(maxsize.Height - tagsize.Height, emsize) + tagsize.Height;
+                comp.size.Height = size.Height(maxsize.Height - tagsize.Height, unitsize, spacing, emsize) + tagsize.Height;
             }
             else {//calculate and use value channel
                 //original height will be used as minimum size
-                auto min = size.Height(maxsize.Height, emsize) + tagsize.Height;
+                auto min = size.Height(maxsize.Height, unitsize, spacing, emsize) + tagsize.Height;
                 
                 //calculate value and use it as basis point as relative size, then covert to pixels
                 comp.size.Height = 
                     Dimension{
                         int(calculatevalue(val, heightch, comp)*10000), Dimension::BasisPoint
-                    } (maxsize.Height - min, emsize)
+                    } (maxsize.Height - min, unitsize, spacing, emsize)
                     + min;                
                     
                     comp.range.Width = maxsize.Height - min;
@@ -3012,11 +3014,11 @@
             //calculate maximum size for non-oriented direction and oriented direction for absolutely placed
             //components.
             auto parentmargin = Convert(
-                temp.GetMargin(), parent.innersize, emsize
+                temp.GetMargin(), parent.innersize, unitsize, spacing, emsize
                 ).CombinePadding(
-                    Convert(cont.GetPadding(), parent.innersize, emsize)
+                    Convert(cont.GetPadding(), parent.innersize, unitsize, spacing, emsize)
                 ) + 
-                Convert(temp.GetIndent(), parent.innersize, emsize);
+                Convert(temp.GetIndent(), parent.innersize, unitsize, spacing, emsize);
             
             auto maxsize = parent.innersize - parentmargin;
             
@@ -3080,7 +3082,9 @@
             //if to be anchored
             if(anch) {
                 //use the margin from the component to be anchored. All sides are calculated, one will be used.
-                margin = Convert(temp.GetMargin(), parent.innersize, emsize).CombineMargins(Convert(anch->GetTemplate().GetMargin(), parent.innersize, getemsize(*anch)));
+                margin = Convert(temp.GetMargin(), parent.innersize, unitsize, spacing, emsize).CombineMargins(
+                    Convert(anch->GetTemplate().GetMargin(), parent.innersize, unitsize, spacing, getemsize(*anch))
+                );
 
                 //revert back the unoriented direction
                 if(ishor) {
@@ -3253,39 +3257,39 @@
                 //this will convert x to pixels
                 if(xch == -1) { //value channel is not in effect
                     offset.X = pos.X(
-                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : tagpos.X), emsize
+                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : tagpos.X), unitsize, spacing, emsize
                     ) + tagpos.X;
                 }
                 else {//calculate and use value channel
                     //original width will be used as minimum size
                     offset.X = pos.X(
-                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : tagpos.X), emsize
+                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : tagpos.X), unitsize, spacing, emsize
                     ) + tagpos.X;
                     
                     //calculate value and use it as basis point as relative size, then covert to pixels
                     offset.X +=
                         Dimension{
                             int(calculatevalue(val, xch, comp)*10000), Dimension::BasisPoint
-                    } (maxsize.Width - (sliding ? offset.X + comp.size.Width : 0), emsize);
+                    } (maxsize.Width - (sliding ? offset.X + comp.size.Width : 0), unitsize, spacing, emsize);
                 }
 
                 //this will convert y to pixels
                 if(ych == -1) { //value channel is not in effect
                     offset.Y = pos.Y(
-                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : tagpos.Y), emsize
+                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : tagpos.Y), unitsize, spacing, emsize
                     ) + tagpos.Y;
                 }
                 else {//calculate and use value channel
                     //original width will be used as minimum size
                     offset.Y = pos.Y(
-                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : tagpos.Y), emsize
+                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : tagpos.Y), unitsize, spacing, emsize
                     ) + tagpos.Y;
 
                     //calculate value and use it as basis point as relative size, then covert to piyels
                     offset.Y +=
                         Dimension{
                             int(calculatevalue(val, ych, comp)*10000), Dimension::BasisPoint
-                    } (maxsize.Height - (sliding ? offset.Y + comp.size.Height : 0), emsize);
+                    } (maxsize.Height - (sliding ? offset.Y + comp.size.Height : 0), unitsize, spacing, emsize);
                 }
 
                 offsets[&comp] = offset;
@@ -3392,19 +3396,19 @@
                         endused = parent.innersize.Width - endmost->location.X;
                         
                         //calculate margin
-                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, getemsize(*startmost));
-                        auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, getemsize(*endmost));
+                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, unitsize, spacing, getemsize(*startmost));
+                        auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, unitsize, spacing, getemsize(*endmost));
                         
                         //add indent
                         lastspacing = calculatemargin(s, e);
                     }
                     else { //only start side is there
                         //calculate margin
-                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, getemsize(*startmost));
-                        auto e = cont.GetPadding().Right(parent.innersize.Width, getemsize(*startmost));
+                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, unitsize, spacing, getemsize(*startmost));
+                        auto e = cont.GetPadding().Right(parent.innersize.Width, unitsize, spacing, getemsize(*startmost));
                         
                         //add indent
-                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Right(parent.innersize.Width, getemsize(*startmost));
+                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Right(parent.innersize.Width, unitsize, spacing, getemsize(*startmost));
                     }
                 }
                 else if(endmost) { //only end side is there
@@ -3412,11 +3416,11 @@
                     endused = parent.innersize.Width - endmost->location.X;
                     
                     //calculate margin
-                    auto s = cont.GetPadding().Left(parent.innersize.Width, getemsize(*endmost));
-                    auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, getemsize(*endmost));
+                    auto s = cont.GetPadding().Left(parent.innersize.Width, unitsize, spacing, getemsize(*endmost));
+                    auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, unitsize, spacing, getemsize(*endmost));
                     
                     //add indent
-                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Left(parent.innersize.Width, getemsize(*endmost));
+                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Left(parent.innersize.Width, unitsize, spacing, getemsize(*endmost));
                 }
                 
                 //calculate remaining space for percent based components
@@ -3434,18 +3438,18 @@
                         endused = parent.innersize.Height - endmost->location.Y;
                         
                         //calculate margin
-                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, getemsize(*startmost));
-                        auto e = endmost->GetTemplate().GetMargin().Top(parent.innersize.Height, getemsize(*endmost));
+                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, unitsize, spacing, getemsize(*startmost));
+                        auto e = endmost->GetTemplate().GetMargin().Top(parent.innersize.Height, unitsize, spacing, getemsize(*endmost));
                         
                         lastspacing = calculatemargin(s, e);
                     }
                     else { //only start side is there
                         //calculate margin
-                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, getemsize(*startmost));
-                        auto e = cont.GetPadding().Bottom(parent.innersize.Height, getemsize(*startmost));
+                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, unitsize, spacing, getemsize(*startmost));
+                        auto e = cont.GetPadding().Bottom(parent.innersize.Height, unitsize, spacing, getemsize(*startmost));
                         
                         //add indent
-                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Bottom(0, getemsize(*startmost));
+                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Bottom(0, unitsize, spacing, getemsize(*startmost));
                     }
                 }
                 else if(endmost) { //only end side is there
@@ -3453,11 +3457,11 @@
                     endused = parent.innersize.Height - endmost->location.Y;
                     
                     //calculate margin
-                    auto s = cont.GetPadding().Top(parent.innersize.Height, getemsize(*endmost));
-                    auto e = endmost->GetTemplate().GetMargin().Top(0, getemsize(*endmost));
+                    auto s = cont.GetPadding().Top(parent.innersize.Height, unitsize, spacing, getemsize(*endmost));
+                    auto e = endmost->GetTemplate().GetMargin().Top(0, unitsize, spacing, getemsize(*endmost));
                     
                     //add indent
-                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Top(0, getemsize(*endmost));
+                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Top(0, unitsize, spacing, getemsize(*endmost));
                 }
                 
                 //calculate remaining space for percent based components
@@ -3483,11 +3487,11 @@
                 int r = comp.size.Width + std::max(0, comp.location.X);
                 
                 auto m = Convert(
-                        comp.GetTemplate().GetMargin(), parent.innersize, emsize
+                        comp.GetTemplate().GetMargin(), parent.innersize, unitsize, spacing, emsize
                     ).CombinePadding(
-                        Convert(cont.GetPadding(), parent.innersize, emsize)
+                        Convert(cont.GetPadding(), parent.innersize, unitsize, spacing, emsize)
                     ) + 
-                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, emsize)
+                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, unitsize, spacing, emsize)
                 ;
                 
                 r += m.Right;
@@ -3509,11 +3513,11 @@
                 int b = comp.size.Height + std::max(0, comp.location.Y);
                 
                 auto m = Convert(
-                        comp.GetTemplate().GetMargin(), parent.innersize, emsize
+                        comp.GetTemplate().GetMargin(), parent.innersize, unitsize, spacing, emsize
                     ).CombinePadding(
-                        Convert(cont.GetPadding(), parent.innersize, emsize)
+                        Convert(cont.GetPadding(), parent.innersize, unitsize, spacing, emsize)
                     ) + 
-                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, emsize)
+                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, unitsize, spacing, emsize)
                 ;
                 
                 b += m.Bottom;
--- a/Source/Gorgon/UI/ComponentStack.h	Fri Oct 22 05:44:20 2021 +0300
+++ b/Source/Gorgon/UI/ComponentStack.h	Fri Oct 22 06:46:12 2021 +0300
@@ -339,6 +339,12 @@
         void SetEMSize(int value) {
             emsize = value;
         }
+
+        /// Changes the unitsize. Default value is obtained from the template.
+        void SetUnitSize(int unitsize, int spacing) {
+            this->unitsize = unitsize;
+            this->spacing = spacing;
+        }
         
         /// This function instructs stack to handle mouse to automatically change hover/down
         /// states, unless disabled state is active. Propagates to substacks.
@@ -854,6 +860,8 @@
         std::vector<Graphics::AdvancedPrinter::Region> regions;
         
         LayerAdapter adapter;
+
+        int unitsize, spacing;
     };
 
 }}
--- a/Source/Gorgon/UI/Dimension.h	Fri Oct 22 05:44:20 2021 +0300
+++ b/Source/Gorgon/UI/Dimension.h	Fri Oct 22 06:46:12 2021 +0300
@@ -5,6 +5,7 @@
 #include "../Geometry/Bounds.h"
 
 namespace Gorgon { namespace UI {
+
     /// Dimension data for components. Allows relative position and sizing.
     class Dimension {
     public:
@@ -33,21 +34,56 @@
             /// found, 10px will be used for EM dash. Thus, 1 unit will be 0.1
             /// pixels.
             EM,
-            
-            //todo add line height
+
+            /// Size in units defined by UI scale. Uses UnitSize and spacing
+            UnitSize,
+
+            /// Size in units defined by UI scale. Uses UnitSize and spacing
+            MilliUnitSize,
+
         };
 
-        /// Constructs a new dimension or type casts integer to dimension		 
+        /// Constructs a new dimension or type casts integer to dimension
         Dimension(int value = 0, Unit unit = Pixel) : value(value), unit(unit) {/* implicit */
         }
 
-        /// Returns the calculated dimension in pixels
-        int operator ()(int parentwidth, int emwidth = 10) const {
-            return Calculate(parentwidth, emwidth);
+
+        /// Constructs a new dimension or type casts real number to dimension
+        Dimension(double value, Unit unit = Percent) {
+            switch(unit) {
+            case Percent:
+                Set(int(std::round(value * 100)), unit);
+                break;
+            case MilliPixel:
+                Set(int(std::round(value * 1000)), unit);
+                break;
+            case BasisPoint:
+                Set(int(std::round(value * 10000)), unit);
+                break;
+            case EM:
+                Set(int(std::round(value * 100)), unit);
+                break;
+            case MilliUnitSize:
+                Set(int(std::round(value * 1000)), unit);
+                break;
+            default:
+                Set(int(std::round(value)), unit);
+                break;
+            }
+        }
+
+        /// Constructs a new dimension or type casts real number to dimension
+        Dimension(float value, Unit unit = Percent) : Dimension((double)value, unit) {
+
         }
 
         /// Returns the calculated dimension in pixels
-        int Calculate(int parentwidth, int emwidth = 10) const {
+        int operator ()(int parentwidth, int unitsize, int spacing, int emwidth = 10) const {
+            return Calculate(parentwidth, unitsize, spacing, emwidth);
+        }
+
+        /// Returns the calculated dimension in pixels
+        int Calculate(int parentwidth, int unitsize, int spacing, int emwidth = 10) const {
             switch(unit) {
                 case Percent:
                     return int(std::round((double)value * parentwidth / 100));
@@ -57,6 +93,14 @@
                     return int(std::round((double)value * parentwidth / 10000));
                 case EM:
                     return int(std::round(value * emwidth / 100));
+                case UnitSize:
+                    if(value >= -1 && value <= 1)
+                        return value * unitsize;
+                    return value * unitsize + (value - 1) * spacing;
+                case MilliUnitSize:
+                    if(value >= -1000 && value <= 1000)
+                        return int(std::round((double)value * unitsize / 1000));
+                    return int(std::round(((double)value * unitsize + (double)(value - 1000) * spacing) / 1000));
                 case Pixel:
                 default:
                     return value;
@@ -112,6 +156,22 @@
         Unit unit;
     };
 
+    /// Similar to Dimension except default unit is UnitSize and supports floats and
+    /// doubles for automatic conversion
+    class UnitDimension : public Dimension {
+    public:
+        UnitDimension(int value, Unit unit = UnitSize) : Dimension(value, unit) {
+        }
+
+        UnitDimension(double value, Unit unit = MilliUnitSize) : Dimension(value, unit) {
+        }
+
+        UnitDimension(float value, Unit unit = MilliUnitSize) : Dimension((double)value, unit) {
+        }
+
+        UnitDimension(const Dimension &d) : Dimension(d) { }
+    };
+
     /// This class stores the location information for a box object
     using Point = Geometry::basic_Point<Dimension>;
 
@@ -122,18 +182,18 @@
     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 emwidth = 10) {
-        return {p.X(parent.Width, emwidth), p.Y(parent.Height, emwidth)};
+    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)};
     }
     
     /// Converts a dimension based size to pixel based size
-    inline Geometry::Size Convert(const Size &s, const Geometry::Size &parent, int emwidth = 10) {
-        return {s.Width(parent.Width, emwidth), s.Height(parent.Height, emwidth)};
+    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), s.Height(parent.Height, unitsize, spacing, emwidth)};
     }
     
     /// Converts a dimension based margin to pixel based margin
-    inline Geometry::Margin Convert(const Margin &m, const Geometry::Size &parent, int emwidth = 10) {
-        return {m.Left(parent.Width, emwidth), m.Top(parent.Height, emwidth), m.Right(parent.Width, emwidth), m.Bottom(parent.Height, emwidth), };
+    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), };
     }
 
 } }

mercurial