#213 Dialog window 4.x-dev

Mon, 07 Dec 2020 12:19:19 +0200

author
cemkalyoncu
date
Mon, 07 Dec 2020 12:19:19 +0200
branch
4.x-dev
changeset 1509
79ec9cd853d1
parent 1508
58d190b948ea
child 1510
c523825917a9

#213 Dialog window

Source/Gorgon/UI/LayerAdapter.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Template.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Window.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/DialogWindow.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/DialogWindow.h 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/Panel.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Panel.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Registry.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Window.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/dir.cmake file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Component.cpp file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/UI/LayerAdapter.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/UI/LayerAdapter.h	Mon Dec 07 12:19:19 2020 +0200
@@ -79,6 +79,7 @@
             ASSERT(base, "Base layer is not set");
             
             this->spacing   = spacing;
+            issizesset      = true;
             this->unitwidth = ( base->GetWidth() - spacing * (units-1) ) / units;
             
             return base->GetWidth() - (this->unitwidth * units + this->spacing * (units-1));
--- a/Source/Gorgon/UI/Template.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/UI/Template.h	Mon Dec 07 12:19:19 2020 +0200
@@ -615,6 +615,28 @@
             else
                 return resizehandlesize;
         }
+        
+        /// for iteration
+        auto begin() {
+            return components.begin();
+        }
+        
+        /// for iteration
+        auto end() {
+            return components.end();
+        }
+        
+        /// for iteration
+        auto begin() const {
+            return components.begin();
+        }
+        
+        /// for iteration
+        auto end() const {
+            return components.end();
+        }
+        
+        
 
 
         /// This event is fired whenever template or its components are changed.
@@ -924,6 +946,8 @@
             MinimizeTag,
             MaximizeTag,
             HelpTag,
+            ButtonTag,
+            DialogButtonsTag,
         };
         
         /// Some components are repeated along some axis, this property controls how they will be
--- a/Source/Gorgon/UI/Window.cpp	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/UI/Window.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -82,19 +82,19 @@
         underadapter.SetFocusChangedHandler([this] {
             focuschangedin(underadapter);
         });
-    }
-
-    void Window::focuschangedin(LayerAdapter &cont) {
-        if(cont.HasFocusedWidget() && focusedadapter != &cont) {
-            if(focusedadapter == nullptr) {
-                RemoveFocus();
-            }
-            else {
-                focusedadapter->RemoveFocus();
-            }
-
-            focusedadapter = &cont;
-        }
+    }
+
+    void Window::focuschangedin(LayerAdapter &cont) {
+        if(cont.HasFocusedWidget() && focusedadapter != &cont) {
+            if(focusedadapter == nullptr) {
+                RemoveFocus();
+            }
+            else {
+                focusedadapter->RemoveFocus();
+            }
+
+            focusedadapter = &cont;
+        }
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/Widgets/DialogWindow.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -0,0 +1,83 @@
+#include "DialogWindow.h"
+
+#include "../Window.h"
+#include "../UI/Window.h"
+
+namespace Gorgon { namespace Widgets {
+    
+    DialogWindow::DialogWindow(const UI::Template &temp, const std::string &title, AutoplaceTarget autoplace) : 
+        Window(temp, title, false)
+    {
+        if(autoplace != None) {
+            bool done = false;
+            for(auto &w : Gorgon::Window::Windows) {
+                auto cont = dynamic_cast<UI::Window *>(&w);
+                if(cont && w.IsVisible() && !w.IsClosed()) {
+                    if(autoplace == DialogLevel)
+                        cont->DialogContainer().Add(*this);
+                    else
+                        cont->WindowContainer().Add(*this);
+                    
+                    done = true;
+                    break;
+                }
+            }
+
+            //UI::Window not found, search for any window that is a container
+            if(!done) {
+                for(auto &w : Gorgon::Window::Windows) {
+                    auto cont = dynamic_cast<UI::WidgetContainer *>(&w);
+                    if(cont && w.IsVisible() && !w.IsClosed()) {
+                        cont->Add(*this);
+                        done = true;
+                        break;
+                    }
+                }
+            }
+            
+            Center();
+        }
+        
+        int ind = stack.IndexOfTag(UI::ComponentTemplate::DialogButtonsTag);
+        
+        if(ind != -1) {
+            buttonsarea.SetLayer(stack.GetLayerOf(ind));
+            buttonsarea.SetFocusStrategy(Deny);
+            btnorg.AttachTo(buttonsarea);
+            buttonsarea.AutomaticUnitSize(temp.GetSpacing());
+        }
+    }
+    
+    DialogWindow::DialogWindow(const UI::Template &temp, const std::string &title, const Geometry::Size size, AutoplaceTarget autoplace) : 
+        DialogWindow(temp, title, autoplace)
+    {
+        Resize(size);
+        updatescrollvisibility();
+        
+        if(buttonsarea.IsReady())
+            buttonsarea.AutomaticUnitSize(temp.GetSpacing());
+        
+        if(autoplace != None)
+            Center();
+    }
+
+    Button &DialogWindow::AddButton(std::string text, std::function<void()> fn) {
+        Button *btn;
+        
+        auto temp = stack.GetTemplate(UI::ComponentTemplate::ButtonTag);
+        
+        if(!temp)
+            btn = new Button(text, fn, Registry::Button_Dialog);
+        else
+            btn = new Button(*temp, text, fn);
+        
+        if(buttonsarea.IsReady()) {
+            btnorg << 2 << *btn;
+        }
+        
+        Own(*btn);
+        
+        return *btn;
+    }
+    
+} }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/Widgets/DialogWindow.h	Mon Dec 07 12:19:19 2020 +0200
@@ -0,0 +1,78 @@
+#pragma once
+
+#include "Window.h"
+#include "Button.h"
+#include "../UI/Organizers/Flow.h"
+
+namespace Gorgon { namespace Widgets {
+   
+    /**
+     * Creates a dialog window. Dialog windows allow buttons to be
+     * placed at the bottom of it. Additionally, dialog windows are
+     * placed above regular windows and bars (menubar, taskbar, etc..)
+     */
+    class DialogWindow : public Window {
+    public:
+        
+        enum AutoplaceTarget {
+            None,
+            WindowLevel,
+            DialogLevel
+        };
+        
+        DialogWindow(const DialogWindow &) = delete;
+        
+        explicit DialogWindow(const UI::Template &temp, const std::string &title = "", AutoplaceTarget autoplace = DialogLevel);
+        
+                 DialogWindow(const UI::Template &temp, const std::string &title, const Geometry::Size size, AutoplaceTarget autoplace = DialogLevel);
+        
+                 DialogWindow(const UI::Template &temp, const Geometry::Size size, AutoplaceTarget autoplace = DialogLevel) : 
+                    DialogWindow(temp, "", size, autoplace) 
+                 { }
+        
+        explicit DialogWindow(Registry::TemplateType type, AutoplaceTarget autoplace = DialogLevel) : DialogWindow(Registry::Active()[type], "", autoplace) { }
+
+        explicit DialogWindow(const std::string &title = "", AutoplaceTarget autoplace = DialogLevel, Registry::TemplateType type = Registry::Window_Dialog) : 
+                    DialogWindow(Registry::Active()[type], title, autoplace) 
+                 { }
+
+        explicit DialogWindow(const std::string &title, Registry::TemplateType type) : 
+                    DialogWindow(Registry::Active()[type], title) 
+                 { }
+
+                 DialogWindow(const std::string &title, const Geometry::Size size, AutoplaceTarget autoplace = DialogLevel, Registry::TemplateType type = Registry::Window_Dialog) : 
+                    DialogWindow(Registry::Active()[type], title, size, autoplace) 
+                 { }
+
+                 DialogWindow(const std::string &title, const Geometry::Size size, Registry::TemplateType type) : 
+                    DialogWindow(Registry::Active()[type], title, size) 
+                 { }
+
+                 DialogWindow(const Geometry::Size size, AutoplaceTarget autoplace = DialogLevel, Registry::TemplateType type = Registry::Window_Dialog) : 
+                    DialogWindow(Registry::Active()[type], "", size, autoplace) 
+                 { }
+        
+                 DialogWindow(const Geometry::Size size, Registry::TemplateType type) : 
+                    DialogWindow(Registry::Active()[type], "", size) 
+                 { }
+        
+        /// Returns the organizer that manages buttons area.
+        UI::Organizers::Flow &ButtonAreaOrganizer() {
+            return btnorg;
+        }
+
+        /// Adds a new button to the buttons area of the dialog window. DialogWindow owns this button.
+        Button &AddButton(std::string text, std::function<void()> fn);
+        
+        /// Removes a widget from the buttons area 
+        void RemoveButton(Widget &w) {
+            buttonsarea.Remove(w);
+        }
+        
+    protected:
+        UI::LayerAdapter buttonsarea;
+        UI::Organizers::Flow btnorg;
+    };
+    
+} }
+    
--- a/Source/Gorgon/Widgets/Generator.cpp	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Generator.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -235,7 +235,6 @@
         return *passivewindowborder;
     }
     
-    
     Graphics::BitmapRectangleProvider &SimpleGenerator::PanelBorder(int missingedge) {
         if(!panelborders[missingedge])
             panelborders[missingedge] = makeborder(Border.Color, Background.Panel, missingedge);
@@ -584,8 +583,8 @@
         foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
     }
     
-    UI::Template SimpleGenerator::Button() {
-        Geometry::Size defsize = {WidgetWidth, BorderedWidgetHeight};
+    UI::Template SimpleGenerator::Button(bool border) {
+        Geometry::Size defsize = {WidgetWidth, border ? BorderedWidgetHeight : WidgetHeight};
         
         UI::Template temp = maketemplate();
         temp.SetSize(defsize);
@@ -602,16 +601,25 @@
             bg.SetPositioning(UI::ComponentTemplate::Absolute);
         };
 
-        setupborder(NormalBorder(), UI::ComponentCondition::Always);
-        setupborder(HoverBorder(), UI::ComponentCondition::Hover);
-        setupborder(DownBorder(), UI::ComponentCondition::Down);
-        setupborder(DisabledBorder(), UI::ComponentCondition::Disabled);
+        if(border) {
+            setupborder(NormalBorder(), UI::ComponentCondition::Always);
+            setupborder(HoverBorder(), UI::ComponentCondition::Hover);
+            setupborder(DownBorder(), UI::ComponentCondition::Down);
+            setupborder(DisabledBorder(), UI::ComponentCondition::Disabled);
+        }
+        else {
+            setupborder(NormalBG(), UI::ComponentCondition::Always);
+            setupborder(HoverBG(), UI::ComponentCondition::Hover);
+            setupborder(DownBG(), UI::ComponentCondition::Down);
+            setupborder(DisabledBG(), UI::ComponentCondition::Disabled);
+        }
         
         auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always)
             .AddIndex(3) //clip
             .AddIndex(4) //focus
         ;
-        boxed.SetBorderSize(Border.Width);
+        if(border)
+            boxed.SetBorderSize(Border.Width);
         boxed.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
         boxed.SetPositioning(UI::ComponentTemplate::Absolute);
         
@@ -773,6 +781,10 @@
 
         return temp;
     }
+    
+    UI::Template SimpleGenerator::DialogButton() {
+        return Button(false);
+    }
 
     UI::Template SimpleGenerator::Checkbox() {
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
@@ -1997,4 +2009,42 @@
         
         return tmp;
     }
+    
+    UI::Template SimpleGenerator::DialogWindow() {
+        auto temp = Window();
+        
+        int maxind = 0;
+        for(auto &c : temp) {
+            if(maxind < c.GetIndex())
+                maxind = c.GetIndex();
+        }
+        
+        maxind++;
+        
+        for(auto &c : temp) {
+            if(c.GetIndex() == 0) {
+                auto rootp = dynamic_cast<UI::ContainerTemplate*>(&c);
+                if(rootp) {
+                    rootp->AddIndex(maxind); //dialog button place
+                }
+            }
+        }
+        
+        auto &btndiag = operator[](Button_Dialog);
+        
+        auto &btnplace = temp.AddContainer(maxind, UI::ComponentCondition::Always);
+        btnplace.SetSize({100, UI::Dimension::Percent}, btndiag.GetHeight());
+        btnplace.SetMargin(0, Spacing, 0, 0);
+        btnplace.SetPositioning(UI::ComponentTemplate::Relative);
+        btnplace.SetAnchor(UI::Anchor::BottomCenter, UI::Anchor::TopCenter, UI::Anchor::TopCenter);
+        btnplace.SetTag(UI::ComponentTemplate::DialogButtonsTag);
+
+        auto &btn = temp.AddPlaceholder(maxind+1, UI::ComponentCondition::Always);
+        btn.SetTemplate(btndiag);
+        btn.SetTag(UI::ComponentTemplate::ButtonTag);
+        
+        
+        return temp;
+    }
+    
 }}
--- a/Source/Gorgon/Widgets/Generator.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Generator.h	Mon Dec 07 12:19:19 2020 +0200
@@ -25,6 +25,9 @@
         /// Generates a button template with the given default size.
         virtual UI::Template IconButton(Geometry::Size iconsize = {-1, -1}) = 0;
         
+        /// Generates a button template
+        virtual UI::Template DialogButton() = 0;
+        
         
         virtual UI::Template Checkbox() = 0;
         
@@ -70,8 +73,11 @@
         
         virtual UI::Template Dropdown() = 0;
         
+        
         virtual UI::Template Window() = 0;
         
+        virtual UI::Template DialogWindow() = 0;
+        
     protected:
         
         virtual UI::Template &generate(Gorgon::Widgets::Registry::TemplateType type) override {
@@ -80,6 +86,8 @@
                 return *new UI::Template(Button());
             case Button_Icon:
                 return *new UI::Template(IconButton());
+            case Button_Dialog:
+                return *new UI::Template(DialogButton());
             case Label_Regular:
                 return *new UI::Template(Label());
             case Label_Error:
@@ -120,6 +128,8 @@
                 return *new UI::Template(Dropdown());
             case Window_Regular:
                 return *new UI::Template(Window());
+            case Window_Dialog:
+                return *new UI::Template(DialogWindow());
             default:
                 return *new UI::Template();
             }
@@ -149,10 +159,14 @@
         
         virtual ~SimpleGenerator();
         
-        virtual UI::Template Button() override;
+                UI::Template Button(bool border);
+        
+        virtual UI::Template Button() override { return Button(true); }
         
         virtual UI::Template IconButton(Geometry::Size iconsize = {-1, -1}) override;
         
+        virtual UI::Template DialogButton() override;
+        
         
         virtual UI::Template Checkbox() override;
         
@@ -189,17 +203,21 @@
         virtual UI::Template VScrollbar() override;
         
         
-        
         virtual UI::Template BlankLayerbox() override;
         
         virtual UI::Template Layerbox() override;
         
+        
         virtual UI::Template Listbox() override;
         
+        
         virtual UI::Template Dropdown() override;
         
+        
         virtual UI::Template Window() override;
         
+        virtual UI::Template DialogWindow() override;
+        
 
         virtual int GetSpacing() const override {
             return Spacing;
@@ -373,6 +391,7 @@
         Graphics::RectangleProvider *focusborder = nullptr;
         
         UI::Template listbox_listitem;
+        UI::Template empty;
 
         std::pair<int, int> lettervsize, asciivsize;
     };
--- a/Source/Gorgon/Widgets/Panel.cpp	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Panel.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -10,6 +10,7 @@
         { UI::ComponentTemplate::HScrollTag, 
             std::bind(&Panel::createhscroll, this, std::placeholders::_1)
         },
+        { UI::ComponentTemplate::ButtonTag, { } },
     }) 
     {
         stack.HandleMouse();
--- a/Source/Gorgon/Widgets/Panel.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Panel.h	Mon Dec 07 12:19:19 2020 +0200
@@ -197,6 +197,7 @@
         int AutomaticUnitSize(int spacing, int units = 6) {
             this->spacing   = spacing;
             this->unitwidth = ( GetInteriorSize().Width - spacing * (units-1) ) / units;
+            issizesset      = true;
             
             return GetInteriorSize().Width - (this->unitwidth * units + this->spacing * (units-1));
         }
--- a/Source/Gorgon/Widgets/Registry.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Registry.h	Mon Dec 07 12:19:19 2020 +0200
@@ -18,6 +18,7 @@
         enum TemplateType {
             Button_Regular,
             Button_Icon,
+            Button_Dialog,
             
             Label_Regular,
             Label_Error,
@@ -36,8 +37,8 @@
             Panel_Bottom,
             Panel_Right,
             
-            
             Window_Regular,
+            Window_Dialog,
             
             Progress_Regular,
             
@@ -51,6 +52,7 @@
             
             Dropdown_Regular,
             
+            
             ///Do not use this value
             Max 
         };
--- a/Source/Gorgon/Widgets/Window.h	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/Window.h	Mon Dec 07 12:19:19 2020 +0200
@@ -17,7 +17,7 @@
     class Window : public Panel {
     public:
         
-        Window(const Panel &) = delete;
+        Window(const Window &) = delete;
         
         explicit Window(const UI::Template &temp, const std::string &title = "", bool autoplace = true);
         
--- a/Source/Gorgon/Widgets/dir.cmake	Sun Dec 06 16:14:58 2020 +0200
+++ b/Source/Gorgon/Widgets/dir.cmake	Mon Dec 07 12:19:19 2020 +0200
@@ -44,4 +44,7 @@
 	
 	Window.h
 	Window.cpp
+	
+	DialogWindow.h
+	DialogWindow.cpp
 )
--- a/Testing/Source/Manual/UI_Component.cpp	Sun Dec 06 16:14:58 2020 +0200
+++ b/Testing/Source/Manual/UI_Component.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -905,11 +905,12 @@
 
 TestData test_relanchvertrelsize(Layer &layer) {
     auto &temp = *new Template;
-    temp.SetSize(60, 80);
+    temp.SetSize(60, 110);
 
     auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
     cont1.AddIndex(1);
     cont1.AddIndex(2);
+    cont1.AddIndex(3);
     cont1.SetOrientation(Gorgon::Graphics::Orientation::Vertical);
     cont1.Background.SetAnimation(whiteimg());
 
@@ -922,12 +923,18 @@
     cont3.Background.SetAnimation(redimg());
     cont3.SetSize(20, {100, Gorgon::UI::Dimension::Percent});
     cont3.SetAnchor(Gorgon::UI::Anchor::BottomLeft, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    
+    auto &cont4 = temp.AddContainer(3, Gorgon::UI::ComponentCondition::Always);
+    cont4.Background.SetAnimation(blueimg());
+    cont4.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont4.SetAnchor(Gorgon::UI::Anchor::BottomLeft, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont4.SetMargin(0,10,0,0);
 
     auto &stack = *new ComponentStack(temp);
 
     layer.Add(stack);
 
-    return {"Relative anchoring vertical relative sizing", "Size 20x20 and 20x50 objects on a 60x80 white background, first one should be aligned to top left, second should be under the first one after 10px of space. Objects are green and red.", stack};
+    return {"Relative anchoring vertical relative sizing", "Size 20x20, 20x50, 20x20 objects on a 60x110 white background, first one should be aligned to top left, second should be under the first one after 10px of space, third should be 10 from the second. Objects are green, red, and blue.", stack};
 }
 
 TestData test_relanch2(Layer &layer) {
@@ -3277,7 +3284,7 @@
 
 std::vector<std::function<TestData(Layer &)>> tests = {
     //BEGIN layout
-    &test_graphic,
+    /*&test_graphic,
     &test_text,
     
     &test_setsize,
@@ -3312,7 +3319,7 @@
     
     &test_relanch,
     &test_relanch2,
-    &test_relanchvert,
+    &test_relanchvert,*/
     &test_relanchvertrelsize,
     
     &test_anchbaseline,
--- a/Testing/Source/Manual/UI_Generate.cpp	Sun Dec 06 16:14:58 2020 +0200
+++ b/Testing/Source/Manual/UI_Generate.cpp	Mon Dec 07 12:19:19 2020 +0200
@@ -23,6 +23,7 @@
 #include <Gorgon/Graphics/TintedObject.h>
 #include <Gorgon/Widgets/Dropdown.h>
 #include <Gorgon/Widgets/Window.h>
+#include <Gorgon/Widgets/DialogWindow.h>
 
 enum DaysOfWeek {
     Monday,
@@ -296,7 +297,7 @@
     
     btn.SetHorizonalAutosize(Gorgon::UI::Autosize::Unit);
     
-    Widgets::Window wind("My window", {200, 300});
+    Widgets::DialogWindow wind("My window", {200, 300});
     wind.Add(btn);
     wind.OwnIcon(icon.CreateAnimation());
     int closetrycount = 0;
@@ -315,6 +316,10 @@
         << "Click close twice"
     ;
     wind.AllowResize();
+    wind.AddButton("Hello", []{
+        std::cout << "Hello" << std::endl;
+    });
+    wind.AddButton("World", []{});
 
     app.wind.Add(blank);
     app.wind.Run();

mercurial