#331 Basic tabpanel is now working 4.x-dev

Sun, 10 Oct 2021 10:47:04 +0300

author
cemkalyoncu
date
Sun, 10 Oct 2021 10:47:04 +0300
branch
4.x-dev
changeset 1736
375fb40537e7
parent 1735
199ffd58a3a6
child 1737
1fab472b8bbb

#331 Basic tabpanel is now working

Source/Gorgon/Geometry/PointList.h file | annotate | diff | comparison | revisions
Source/Gorgon/Graphics/Rectangle.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/TabPanel.h file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_WidgetTest.cpp file | annotate | diff | comparison | revisions
--- 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);
 

mercurial