Fri, 22 Oct 2021 06:46:12 +0300
* Dimension now includes UnitSize
--- 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), }; } } }