Sun, 10 Oct 2021 10:47:04 +0300
#331 Basic tabpanel is now working
--- a/Source/Gorgon/Geometry/PointList.h Sat Oct 09 15:23:25 2021 +0300 +++ b/Source/Gorgon/Geometry/PointList.h Sun Oct 10 10:47:04 2021 +0300 @@ -183,13 +183,24 @@ void Push(P_ point) { Points.push_back(point); } - + /// Adds a new point to the end of the point list template<class ...T_> void Push(T_&&... params) { Points.emplace_back(std::forward<T_>(params)...); } - + + /// Adds a new point to the end of the point list + void Insert(long index, P_ point) { + Points.insert(Points.begin()+index, point); + } + + /// Adds a new point to the end of the point list + template<class ...T_> + void Insert(long index, T_&&... params) { + Points.emplace(Points.begin()+index, std::forward<T_>(params)...); + } + /// Removes the last point from the list void Pop() { Points.pop_back();
--- a/Source/Gorgon/Graphics/Rectangle.cpp Sat Oct 09 15:23:25 2021 +0300 +++ b/Source/Gorgon/Graphics/Rectangle.cpp Sun Oct 10 10:47:04 2021 +0300 @@ -85,7 +85,7 @@ Geometry::Rectanglef(r.X + maxl, r.Y + maxt, r.Width-maxl-maxr, r.Height-maxt-maxb), color); mr.DrawIn(target, prov.GetSideTiling() ? Tiling::Vertical : Tiling::None, - Geometry::Rectanglef(r.Right() - maxr, r.Y + maxt, (Float)ml.GetWidth(), r.Height-maxt-maxb), + Geometry::Rectanglef(r.Right() - maxr, r.Y + maxt, (Float)mr.GetWidth(), r.Height-maxt-maxb), color);
--- a/Source/Gorgon/Widgets/Generator.cpp Sat Oct 09 15:23:25 2021 +0300 +++ b/Source/Gorgon/Widgets/Generator.cpp Sun Oct 10 10:47:04 2021 +0300 @@ -303,10 +303,13 @@ h2 = dynamic_cast<Graphics::BasicPrinter*>(h2renderer); h3 = dynamic_cast<Graphics::BasicPrinter*>(h3renderer); info = dynamic_cast<Graphics::BasicPrinter*>(smallrenderer); - + centered.SetGlyphRenderer(*regularrenderer); centered.AlignCenter(); - + + infocentered.SetGlyphRenderer(*smallrenderer); + infocentered.AlignCenter(); + auto regcol = colors.Get(Graphics::Color::Regular).Forecolor; auto regularfnt = regular; @@ -550,35 +553,38 @@ return *prov; } - Graphics::RectangularAnimationProvider *SimpleGenerator::makeborder(Graphics::RGBA border, Graphics::RGBA bg, AssetID::BorderSide borders, int w, int r) { + Graphics::RectangularAnimationProvider *SimpleGenerator::makeborder( + Graphics::RGBA border, Graphics::RGBA bg, + AssetID::BorderSide borders, int w, int r + ) { if(w == -1) w = Border.Width; - + if(r == -1) r = Border.Radius; - + int coff = r + (border.A > 0 ? w+1 : 0); int bsize = coff * 2 + 16; float off = (border.A ? float(w / 2.0f) : 0); - + auto &bi = *new Graphics::Bitmap({bsize, bsize}, Graphics::ColorMode::RGBA); bi.Clear(); - + if(r == 0 || AssetID::TotalBorders(borders) < 3) { if(borders == AssetID::None) { coff = 0; off = 0; } - + Geometry::PointList<Geometry::Pointf> list = {{off, bsize-off}, {bsize-off, bsize-off}, {bsize-off, off}, {off,off}}; - + CGI::Polyfill(bi.GetData(), list, CGI::SolidFill<>(bg)); - + if(border.A != 0) { switch(borders) { case AssetID::Horizontal: CGI::DrawLines(bi.GetData(), - {{off, off}, {bsize-off, off}}, + {{off, off}, {bsize-off, off}}, (float)w, CGI::SolidFill<>(border) ); CGI::DrawLines(bi.GetData(), @@ -588,7 +594,7 @@ break; case AssetID::Vertical: CGI::DrawLines(bi.GetData(), - {{off, off}, {off, bsize-off}}, + {{off, off}, {off, bsize-off}}, (float)w, CGI::SolidFill<>(border) ); CGI::DrawLines(bi.GetData(), @@ -602,7 +608,7 @@ break; case AssetID::Left: CGI::DrawLines(bi.GetData(), - {{off, off}, {off, bsize-off}}, + {{off, off}, {off, bsize-off}}, (float)w, CGI::SolidFill<>(border) ); break; @@ -614,7 +620,7 @@ break; case AssetID::Top: CGI::DrawLines(bi.GetData(), - {{off, off}, {off, bsize-off}}, + {{off, off}, {off, bsize-off}}, (float)w, CGI::SolidFill<>(border) ); break; @@ -636,13 +642,13 @@ } else { Geometry::PointList<Geometry::Pointf> list; - + int div = Border.Divisions+1; float angperdivision = -PI/2/div; float angstart = -PI/2; - + int missingedge = AssetID::TotalBorders(borders) == 3 ? borders - AssetID::AllExceptLeft : -1; - + if(missingedge != -1) { list.Push({off, 0}); } @@ -652,19 +658,19 @@ list.Push(Geometry::Pointf::FromVector((float)r, ang, Geometry::Pointf{off+r, off+r})); } } - + angstart = PI; for(int i=0; i<=div; i++) { float ang = angstart + angperdivision*i; list.Push(Geometry::Pointf::FromVector((float)r, ang, Geometry::Pointf{off+r, bsize-off-r})); } - + angstart = PI/2; for(int i=0; i<=div; i++) { float ang = angstart + angperdivision*i; list.Push(Geometry::Pointf::FromVector((float)r, ang, Geometry::Pointf{bsize-off-r, bsize-off-r})); } - + if(missingedge != -1) { list.Push({bsize-off, 0}); } @@ -675,21 +681,21 @@ list.Push(Geometry::Pointf::FromVector((float)r, ang, Geometry::Pointf{bsize-off-r, off+r})); } } - + CGI::Polyfill(bi.GetData(), list, CGI::SolidFill<>(bg)); - - + + if(missingedge == -1) { list.Push(list.Front()); } - + if(border.A != 0) CGI::DrawLines(bi.GetData(), list, (float)w, CGI::SolidFill<>(border)); - + if(missingedge == 0) { bi = bi.Rotate90(); } - else if(missingedge == 3) { + else if(missingedge == 1) { bi = bi.Rotate180(); } else if(missingedge == 2) { @@ -699,25 +705,25 @@ if(coff > 0) { drawables.Add(bi); - + auto ret = new Graphics::BitmapRectangleProvider(Graphics::Slice(bi, { - coff, - coff, + coff, + coff, bsize-coff, bsize-coff })); - + ret->Prepare(); - + return ret; } else { bi.Prepare(); - + return &bi; } } - + Graphics::BitmapRectangleProvider *SimpleGenerator::makecheckeredbg() { //TODO: Use masked object auto r = Border.Radius; @@ -1336,7 +1342,7 @@ return temp; } - UI::Template SimpleGenerator::CheckboxButton() { + UI::Template SimpleGenerator::checkboxbutton(AssetID::BorderSide tabbutton) { UI::Template temp = maketemplate(); temp.SetSpacing(spacing); @@ -1357,17 +1363,31 @@ bg.SetPositioning(UI::ComponentTemplate::Absolute); }; - setupbg(A(Background, Regular), UI::ComponentCondition::Always); - setupbg(A(Background, Hover), UI::ComponentCondition::Hover); - setupbg(A(Background, Down), UI::ComponentCondition::Down); - setupbg(A(Background, Disabled), UI::ComponentCondition::Disabled); + if(tabbutton == AssetID::None) { + setupbg(A(Background, Regular), UI::ComponentCondition::Always); + setupbg(A(Background, Hover), UI::ComponentCondition::Hover); + setupbg(A(Background, Down), UI::ComponentCondition::Down); + setupbg(A(Background, Disabled), UI::ComponentCondition::Disabled); + } + else { + setupbg(GetAsset({AssetID::Background, Graphics::Color::Regular, tabbutton}), UI::ComponentCondition::Always); + setupbg(GetAsset({AssetID::Background, Graphics::Color::Hover, tabbutton}), UI::ComponentCondition::Hover); + setupbg(GetAsset({AssetID::Background, Graphics::Color::Down, tabbutton}), UI::ComponentCondition::Down); + setupbg(GetAsset({AssetID::Background, Graphics::Color::Disabled, tabbutton}), UI::ComponentCondition::Disabled); + } //checked border auto &border = temp.AddContainer(8, UI::ComponentCondition::Always, UI::ComponentCondition::State2); border.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition); border.SetValueRange(0, 0.25, 1); border.SetReversible(true); - border.Background.SetAnimation(A(Frame, Hover)); + + if(tabbutton == AssetID::None) { + border.Background.SetAnimation(A(Frame, Hover)); + } + else { + border.Background.SetAnimation(GetAsset({AssetID::Frame, Graphics::Color::Hover, tabbutton})); + } //boxed content auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always) @@ -1416,7 +1436,10 @@ //Text only visible when no icon is set auto setuptext = [&](Graphics::RGBA color, UI::ComponentCondition condition) { auto &txt = temp.AddTextholder(7, condition); - txt.SetRenderer(centered); + if(tabbutton != AssetID::None) + txt.SetRenderer(infocentered); + else + txt.SetRenderer(centered); txt.SetColor(color); txt.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter); txt.SetDataEffect(UI::ComponentTemplate::Text); @@ -1433,7 +1456,11 @@ return temp; } - + + UI::Template SimpleGenerator::CheckboxButton() { + return checkboxbutton(AssetID::None); + } + UI::Template SimpleGenerator::RadioButton() { Geometry::Size defsize = {GetUnitSize(6), borderlessheight}; @@ -2750,6 +2777,7 @@ //Main container temp.AddContainer(0, UI::ComponentCondition::Always) .AddIndex(1) //button container + .AddIndex(4) //additional graphics .AddIndex(2) //panel container .AddIndex(5) //Button .SetOrientation(Graphics::Orientation::Vertical) @@ -2758,11 +2786,13 @@ //Button container auto &buttonsarea = temp.AddContainer(1, UI::ComponentCondition::Always) .AddIndex(3) //button panel - .AddIndex(4) //additional graphics ; buttonsarea.SetSizing(UI::ComponentTemplate::Fixed, UI::ComponentTemplate::GrowOnly); buttonsarea.SetSize({100, UI::Dimension::Percent}, unitsize); + buttonsarea.SetTag(UI::ComponentTemplate::HeaderTag); + buttonsarea.SetAnchor(UI::Anchor::BottomLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft); //buttonsarea.Background.SetAnimation(A(Background, Regular, None)); + buttonsarea.SetClip(true); auto &buttonspanel = temp.AddPlaceholder(3, UI::ComponentCondition::Always); buttonspanel.SetTag(UI::ComponentTemplate::ButtonsTag); @@ -2773,9 +2803,10 @@ auto &graph = temp.AddGraphics(4, UI::ComponentCondition::Always); graph.Content.SetAnimation(A(BorderFilled, Regular, None)); graph.SetSize({100, UI::Dimension::Percent}, Border.Width); + //graph.SetPositioning(UI::ComponentTemplate::Absolute); graph.SetFillArea(true); graph.SetSizing(UI::ComponentTemplate::Fixed); - graph.SetAnchor(UI::Anchor::BottomRight, UI::Anchor::BottomLeft, UI::Anchor::BottomLeft); + graph.SetAnchor(UI::Anchor::BottomLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft); auto &container = temp.AddPlaceholder(2, UI::ComponentCondition::Always); container.SetTag(UI::ComponentTemplate::ContentsTag); @@ -2784,9 +2815,11 @@ container.SetSize(100, 100, UI::Dimension::Percent); container.SetSizing(UI::ComponentTemplate::Fixed); container.SetAnchor(UI::Anchor::BottomLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft); + container.SetClip(true); auto &btn = temp.AddPlaceholder(5, UI::ComponentCondition::Always); - btn.SetTemplate((*this)[Checkbox_Button]); // TODO: replace + auto &btntmp = *new UI::Template(checkboxbutton(AssetID::AllExceptBottom)); + btn.OwnTemplate(btntmp); btn.SetTag(UI::ComponentTemplate::ButtonTag); btn.SetPositioning(UI::ComponentTemplate::Absolute);
--- a/Source/Gorgon/Widgets/Generator.h Sat Oct 09 15:23:25 2021 +0300 +++ b/Source/Gorgon/Widgets/Generator.h Sun Oct 10 10:47:04 2021 +0300 @@ -235,8 +235,7 @@ Edit, //rectangle with background set to edit FgFilled, BorderFilled, - Caret, - TabButton, + Caret }; enum BorderSide { @@ -246,9 +245,9 @@ Right, Bottom, AllExceptLeft, - AllExceptTop, + AllExceptBottom, AllExceptRight, - AllExceptBottom, + AllExceptTop, Horizontal, Vertical, All @@ -701,6 +700,8 @@ //will fit into the box of the same size Graphics::Bitmap *circlefill(Graphics::RGBA color, Geometry::Size size); Graphics::BitmapAnimationProvider *caret(); + + UI::Template checkboxbutton(AssetID::BorderSide tabbutton); /// This is the height of a bordered widget @@ -778,6 +779,7 @@ Graphics::BasicPrinter *h3; Graphics::BasicPrinter *info; Graphics::StyledPrinter centered; + Graphics::StyledPrinter infocentered; Graphics::AdvancedPrinter printer; Graphics::AdvancedPrinter infoprinter;
--- a/Source/Gorgon/Widgets/TabPanel.h Sat Oct 09 15:23:25 2021 +0300 +++ b/Source/Gorgon/Widgets/TabPanel.h Sun Oct 10 10:47:04 2021 +0300 @@ -9,7 +9,7 @@ #include "../UI/RadioControl.h" #include "../UI/Organizers/Flow.h" -//TODO: Better tab buttons, Overflow options, Disable/hide tab, Tab icons +//TODO: More overflow options, repeat bar, Disable/hide tab, Tab icons namespace Gorgon { namespace Widgets { template <class Key_> @@ -386,7 +386,11 @@ /// Sets how the overflowing tab buttons are managed. Default is Scale. /// Some options are not implemented yet and will default to Scale. - void SetButtonOverflow(ButtonOverflow value); + void SetButtonOverflow(ButtonOverflow value) { + overflow = value; + + Refresh(); + } /// Returns how the overflowing tab buttons are managed. ButtonOverflow GetButtonOverflow() const { @@ -435,26 +439,50 @@ /// Refreshes the tab buttons and their locations. This function is called automatically. void Refresh() { int x = 0; + int y = 0; + int w = stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::HeaderTag)).Width(); + int curh = 0; + int maxw = 0; + for(int i=0; i<tabs.GetCount(); i++) { auto &button = buttons[i]; auto &tab = tabs[i]; button.SetText(tab.GetTitle()); + + if(button.GetWidth() + x > w && overflow == ExpandLines) { + y += curh + GetSpacing(); + x = 0; + } + button.Location.X = x; + button.Location.Y = y; + button.SetTextWrap(buttontextwrap); - x = button.GetBounds().Right; - tab.Resize(stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag)).GetSize()); + if(maxw < button.GetBounds().Right) { + maxw = button.GetBounds().Right; + } + + x = button.GetBounds().Right + GetSpacing(); + if(button.GetHeight() > curh) + curh = button.GetHeight(); } if(buttonspnl) { if(buttons.GetSize()) { - buttonspnl->Resize((Geometry::Size)buttons.Last()->GetBounds().BottomRight()); + buttonspnl->Resize(maxw, buttons.Last()->GetBounds().Bottom); } else { buttonspnl->Resize({0, GetUnitWidth()}); } - stack.SetTagSize(UI::ComponentTemplate::ButtonsTag, buttonspnl->GetSize()); + stack.SetTagSize(UI::ComponentTemplate::ButtonsTag, {0, buttonspnl->GetHeight()}); + } + + stack.Update(true); + auto pnlsize = stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag)).GetSize(); + for(auto &tab : tabs) { + tab.Resize(pnlsize); } }
--- a/Testing/Source/Manual/UI_WidgetTest.cpp Sat Oct 09 15:23:25 2021 +0300 +++ b/Testing/Source/Manual/UI_WidgetTest.cpp Sun Oct 10 10:47:04 2021 +0300 @@ -27,8 +27,10 @@ wgt1.Focus(); - wgt1.New("Tab 1", "Tab 1 long text"); + wgt1.New("Tab 1"); wgt1.New("Tab 2"); + wgt1.New("Tab 3"); + wgt1.New("Tab 4"); wgt1.SetTabRollover(true); //wgt1.SetButtonTextWrap(true);