#331 Keyboard switching 4.x-dev

Sat, 09 Oct 2021 15:23:25 +0300

author
cemkalyoncu
date
Sat, 09 Oct 2021 15:23:25 +0300
branch
4.x-dev
changeset 1735
199ffd58a3a6
parent 1734
66ce2e2dbf1f
child 1736
375fb40537e7

#331 Keyboard switching
Focus
Rollover
Button size/sizing

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/Widgets/Generator.cpp	Sat Oct 09 09:27:52 2021 +0300
+++ b/Source/Gorgon/Widgets/Generator.cpp	Sat Oct 09 15:23:25 2021 +0300
@@ -2778,7 +2778,7 @@
         graph.SetAnchor(UI::Anchor::BottomRight, UI::Anchor::BottomLeft, UI::Anchor::BottomLeft);
 
         auto &container = temp.AddPlaceholder(2, UI::ComponentCondition::Always);
-        container.SetTag(UI::ComponentTemplate::PanelTag);
+        container.SetTag(UI::ComponentTemplate::ContentsTag);
         auto &pnltmp = *new UI::Template(makepanel(AssetID::AllExceptTop, true));
         container.OwnTemplate(pnltmp);// TODO: replace?
         container.SetSize(100, 100, UI::Dimension::Percent);
--- a/Source/Gorgon/Widgets/Generator.h	Sat Oct 09 09:27:52 2021 +0300
+++ b/Source/Gorgon/Widgets/Generator.h	Sat Oct 09 15:23:25 2021 +0300
@@ -235,7 +235,8 @@
                 Edit, //rectangle with background set to edit
                 FgFilled,
                 BorderFilled,
-                Caret
+                Caret,
+                TabButton,
             };
             
             enum BorderSide {
--- a/Source/Gorgon/Widgets/TabPanel.h	Sat Oct 09 09:27:52 2021 +0300
+++ b/Source/Gorgon/Widgets/TabPanel.h	Sat Oct 09 15:23:25 2021 +0300
@@ -9,6 +9,8 @@
 #include "../UI/RadioControl.h"
 #include "../UI/Organizers/Flow.h"
 
+//TODO: Better tab buttons, Overflow options, Disable/hide tab, Tab icons
+
 namespace Gorgon { namespace Widgets {
     template <class Key_>
     class basic_TabPanel;
@@ -98,11 +100,22 @@
         explicit basic_TabPanel(const UI::Template &temp) : 
             ComponentStackComposer(temp, {
                 {UI::ComponentTemplate::ButtonTag, {}},
-                {UI::ComponentTemplate::PanelTag, {}},
-            })
+                {UI::ComponentTemplate::ContentsTag, {}},
+            }),
+            buttonsize(GetUnitWidth() * 3 + GetSpacing() * 2, GetUnitWidth())
         {
+            stack.SetMouseUpEvent([this](auto, auto, auto) {
+                Focus();
+            });
+
             stack.AddGenerator(UI::ComponentTemplate::ButtonsTag, std::bind(&basic_TabPanel::getbtns, this, std::placeholders::_1));
-            radio.ChangedEvent.Register(*this, &basic_TabPanel::Activate);
+            radio.ChangedEvent.Register([this](const Key_ &key) {
+                if(!updating) {
+                    Activate(key);
+                    if(HasActiveTab())
+                        GetActiveTab().Focus();
+                }
+            });
 
             Refresh();
         }
@@ -119,7 +132,7 @@
 
         /// Create a new tab with the given key and title
         Tab<Key_> &New(const Key_ &key, const std::string &title) {
-            auto layertemp = stack.GetTemplate(UI::ComponentTemplate::PanelTag);
+            auto layertemp = stack.GetTemplate(UI::ComponentTemplate::ContentsTag);
             if(!layertemp)
                 layertemp = &Registry::Active()[Registry::Panel_Blank];
             
@@ -135,13 +148,29 @@
             tabs.Add(tab);
             mapping.Add(key, tab);
 
-            auto &btn = *new Checkbox(*buttontemp, title);
-            btn.SetHorizonalAutosize(UI::Autosize::Unit);
-            buttons.Add(btn);
-            radio.Add(key, btn);
+            auto &button = *new Checkbox(*buttontemp, title);
+            buttons.Add(button);
+            radio.Add(key, button);
+
+            switch(sizing) {
+                default:
+                case Fill:
+                case Adaptive:
+                case AutoUnit:
+                    button.SetHorizonalAutosize(true);
+                    button.Resize(buttonsize);
+                    break;
+                case Auto:
+                    button.SetHorizonalAutosize(UI::Autosize::Automatic);
+                    button.Resize(buttonsize);
+                    break;
+                case Fixed:
+                    button.Resize(buttonsize);
+                    break;
+            }
 
             if(buttonspnl)
-                buttonspnl->Add(btn);
+                buttonspnl->Add(button);
 
             if(tabs.GetSize() == 1) {
                 Activate(key);
@@ -182,14 +211,18 @@
         }
 
         /// Remove the tab at the given key
-        void Remove(const Key_ &key);
-
-        /// Remove all tabs with the supplied title
-        void RemoveAllOf(const std::string &title);
+        void Remove(const Key_ &key) {
+            auto &tab = mapping[key];
+            tabs.Remove(tab);
+            mapping.Remove(key);
+            delete tab;
+        }
 
         /// Moves the tab at the given key before another tab. If the before tab does not exit, the tab
         /// will be moved to the end.
-        void MoveBefore(const Key_ &before, const Key_ &tab);
+        void MoveBefore(const Key_ &tab, const Key_ &before) {
+            tabs.MoveBefore(mapping[tab], mapping[before]);
+        }
 
         /// Return the tab with the supplied key
         Tab<Key_> &operator [](const Key_ &key) {
@@ -213,11 +246,16 @@
         /// Activates the tab with the key. If key does not exist nothing is done.
         void Activate(const Key_ &key) {
             if(mapping.Exists(key)) {
-                if(radio.Get() != key)
+                if(radio.Get() != key) {
+                    updating = true;
                     radio.Set(key);
+                    updating = false;
+                }
 
-                mapping[key].Resize(stack.GetTagSize(UI::ComponentTemplate::PanelTag));
-                stack.SetWidget(UI::ComponentTemplate::PanelTag, &mapping[key]);
+                mapping[key].Resize(stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag)).GetSize());
+                //stack.SetWidget(UI::ComponentTemplate::ContentsTag, &mapping[key]);
+                Clear();
+                Add(mapping[key]);
 
                 hasactive = true;
             }
@@ -226,15 +264,55 @@
         /// Deactivate the currently active tab.
         void Deactivate() {
             radio.Set(Key_{});
-            stack.SetWidget(UI::ComponentTemplate::PanelTag, nullptr);
+            stack.SetWidget(UI::ComponentTemplate::ContentsTag, nullptr);
             hasactive = false;
         }
 
         /// Activates the next tab
-        void ActivateNext();
+        void ActivateNext() {
+            long ind = -1;
+            if(!HasActiveTab()) {
+                if(tabs.GetCount()) {
+                    ind = 0;
+                }
+            }
+            else {
+                ind = tabs.FindLocation(GetActiveTab());
+                if(ind == tabs.GetCount()-1) {
+                    if(rollover) {
+                        ind = 0;
+                    }
+                }
+                else {
+                    ind++;
+                }
+            }
+
+            if(ind != -1)
+                Activate(tabs[ind].GetKey());
+        }
 
         /// Activates the previous tab
-        void ActivatePrevious();
+        void ActivatePrevious() {
+            long ind = -1;
+            if(!HasActiveTab()) {
+                ind = tabs.GetCount() - 1;
+            }
+            else {
+                ind = tabs.FindLocation(GetActiveTab());
+                if(ind == 0) {
+                    if(rollover) {
+                        ind = tabs.GetCount() - 1;
+                    }
+                }
+                else {
+                    ind--;
+                }
+            }
+
+            if(ind != -1)
+                Activate(tabs[ind].GetKey());
+        }
 
         /// Returns if there is an active tab.
         bool HasActiveTab() const {
@@ -258,7 +336,33 @@
         }
 
         /// Set how the tab buttons will be resized. Default is AutoUnit
-        void SetButtonSizing(ButtonSizing value);
+        void SetButtonSizing(ButtonSizing value) {
+            if(value == sizing)
+                return;
+
+            sizing = value;
+
+            for(auto &button : buttons) {
+                switch(sizing) {
+                    default:
+                    case Fill:
+                    case Adaptive:
+                    case AutoUnit:
+                        button.SetHorizonalAutosize(true);
+                        button.Resize(buttonsize);
+                        break;
+                    case Auto:
+                        button.SetHorizonalAutosize(UI::Autosize::Automatic);
+                        button.Resize(buttonsize);
+                        break;
+                    case Fixed:
+                        button.Resize(buttonsize);
+                        break;
+                }
+            }
+
+            Refresh();
+        }
 
         /// Returns how the tab buttons will be resized
         ButtonSizing GetButtonSizing() const {
@@ -297,7 +401,21 @@
 
         /// Sets the size of the tab buttons. The size will be used according
         /// to ButtonSizing.
-        void SetButtonSize(const Geometry::Size &size);
+        void SetButtonSize(const Geometry::Size &value) {
+            if(buttonsize == value)
+                return;
+
+            buttonsize = value;
+            Refresh();
+        }
+
+        void SetButtonWidth(int size) {
+            SetButtonSize(size, buttonsize.Height);
+        }
+
+        void SetButtonHeight(int size) {
+            SetButtonSize(buttonsize.Width, size);
+        }
 
         /// Returns the size of the buttons
         Geometry::Size GetButtonSize() const {
@@ -305,7 +423,9 @@
         }
 
         /// Sets if next or previous tab switches will rollover. Default is false
-        void SetTabRollover(bool value);
+        void SetTabRollover(bool value) {
+            rollover = value;
+        }
 
         /// Returns if next or previous tab switches will rollover.
         bool GetTabRollover() const {
@@ -316,11 +436,14 @@
         void Refresh() {
             int x = 0;
             for(int i=0; i<tabs.GetCount(); i++) {
-                buttons[i].SetText(tabs[i].GetTitle());
-                buttons[i].Location.X = x;
-                buttons[i].SetTextWrap(buttontextwrap);
-                x = buttons[i].GetBounds().Right;
-                tabs[i].Resize(stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::PanelTag)).GetSize());
+                auto &button = buttons[i];
+                auto &tab    = tabs[i];
+                button.SetText(tab.GetTitle());
+                button.Location.X = x;
+                button.SetTextWrap(buttontextwrap);
+                x = button.GetBounds().Right;
+
+                tab.Resize(stack.BoundsOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag)).GetSize());
             }
 
             if(buttonspnl) {
@@ -355,6 +478,37 @@
             return tabs.end();
         }
 
+        bool KeyPressed(Input::Key key, float state) override {
+            namespace Keycodes = Input::Keyboard::Keycodes;
+
+            if(state == 0)
+                return false;
+
+            if(key == Keycodes::Tab) {
+                if(Input::Keyboard::CurrentModifier == Input::Keyboard::Modifier::Ctrl) {
+                    ActivateNext();
+
+                    if(HasActiveTab())
+                        GetActiveTab().Focus();
+
+                    return true;
+                }
+                else if(Input::Keyboard::CurrentModifier == Input::Keyboard::Modifier::ShiftCtrl) {
+                    ActivatePrevious();
+
+                    if(HasActiveTab())
+                        GetActiveTab().Focus();
+
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+
+
+
     private:
         //for key mapping
         Containers::Hashmap<Key_, Tab<Key_>> mapping;
@@ -364,10 +518,11 @@
 
         ButtonSizing    sizing          = AutoUnit;
         bool            buttontextwrap  = false;
-        ButtonOverflow  overflow        = Scale;
+        ButtonOverflow  overflow        = HideExcess;
         Geometry::Size  buttonsize; //constructor will initialize to 3x1U
         bool            rollover        = false;
         bool            hasactive       = false;
+        bool            updating        = false;
 
         Panel *buttonspnl = nullptr;
         Containers::Collection<Checkbox> buttons;
--- a/Testing/Source/Manual/UI_WidgetTest.cpp	Sat Oct 09 09:27:52 2021 +0300
+++ b/Testing/Source/Manual/UI_WidgetTest.cpp	Sat Oct 09 15:23:25 2021 +0300
@@ -25,8 +25,12 @@
     org
         << wgt1;
 
+    wgt1.Focus();
+
     wgt1.New("Tab 1", "Tab 1 long text");
     wgt1.New("Tab 2");
+    wgt1.SetTabRollover(true);
+    //wgt1.SetButtonTextWrap(true);
 
     Widgets::Button btn1("Hey tab 1");
     Widgets::Label lbl1("Hey tab 2");
@@ -42,6 +46,7 @@
     btn2.Location.Y = 400;
     btn2.Location.X = Widgets::Registry::Active().GetUnitSize(3) + Widgets::Registry::Active().GetSpacing();
 
+    wgt1.ActivateNext();
         
     
     app.wind.Run();

mercurial