* Minimum functionality for listbox 4.x-dev

Sun, 18 Oct 2020 09:49:15 +0300

author
cemkalyoncu
date
Sun, 18 Oct 2020 09:49:15 +0300
branch
4.x-dev
changeset 1465
d750468e775b
parent 1464
fc28c4139fcc
child 1466
4f9d8dd78c18

* Minimum functionality for listbox

Source/Gorgon/UI/ComponentStack.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ComponentStack.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/ComponentStackWidget.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/LayerAdapter.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/RadioControl.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Widget.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Widget.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/WidgetBase.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/WidgetBase.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/WidgetContainer.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/UI/WidgetContainer.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Window.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/dir.cmake file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Composer.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Composer.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/GeometryBoxes.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/ListItem.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Listbox.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/RadioButtons.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Scrollbar.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Slider.h file | annotate | diff | comparison | revisions
Testing/Source/Manual/GraphicsHelper.h file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/UI/ComponentStack.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/ComponentStack.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -3,7 +3,7 @@
 #include "../Graphics/Font.h"
 #include "../Time.h"
 #include "../Config.h"
-#include "WidgetBase.h"
+#include "Widget.h"
 
 #include "math.h"
 
@@ -34,7 +34,7 @@
         return true;
     }
 
-    ComponentStack::ComponentStack(const Template& temp, Geometry::Size size, std::map<ComponentTemplate::Tag, std::function<WidgetBase *(const Template &)>> generators) : 
+    ComponentStack::ComponentStack(const Template& temp, Geometry::Size size, std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> generators) : 
         ConditionChanged(this),
         size(size),
         temp(temp),
@@ -1105,6 +1105,7 @@
             }
         }
         
+        
         //translate the given coordinate to local coordinates
         auto pnt = location;
         if(!relative)
@@ -1115,15 +1116,20 @@
             //default is position modification, if the mode is not valid
             //for mouse coordinates, this will be used.
             default: {
-                if(ct.GetPositioning() == ct.Absolute || ct.GetPositioning() == ct.AbsoluteSliding) {                    
+                if(ct.GetPositioning() == ct.Absolute || ct.GetPositioning() == ct.AbsoluteSliding) {   
                     //get the rate
                     val[0] = float(pnt.X) / bounds.Width();
                     val[1] = float(pnt.Y) / bounds.Height();
                     
                     //if x or y is effected, this will adjust the value accordingly
-                    if(ct.GetValueModification() == ContainerTemplate::ModifyX)
+                    if(ct.GetValueModification() == ContainerTemplate::ModifyX) {
+                        if(bounds.Width() == 0)
+                            return {0, 0, 0, 0};
                         val[1] = 0;
+                    }
                     else if(ct.GetValueModification() == ContainerTemplate::ModifyY) {
+                        if(bounds.Height() == 0)
+                            return {0, 0, 0, 0};
                         val[0] = val[1];
                         val[1] = 0;
                     }
@@ -1171,6 +1177,8 @@
                 //scale it to 0-1
                 val[0] = float(val[0]) / bounds.Width();
                 val[1] = float(val[1]) / bounds.Height();
+                
+                //TODO nan check
 
                 break;
         }
@@ -3585,7 +3593,21 @@
         }
     }
     
-    WidgetBase *ComponentStack::GetWidget(ComponentTemplate::Tag tag) {
+    const Template *ComponentStack::GetTemplate(ComponentTemplate::Tag tag) {
+        auto comp = gettag(tag);
+        
+        if(comp == nullptr)
+            return nullptr;
+        
+        auto temp = dynamic_cast<const PlaceholderTemplate*>(&comp->GetTemplate());
+        
+        if(!temp->HasTemplate())
+            return nullptr;
+        
+        return &temp->GetTemplate();
+    }
+    
+    Widget *ComponentStack::GetWidget(ComponentTemplate::Tag tag) {
         auto comp = gettag(tag);
         
         if(comp == nullptr)
--- a/Source/Gorgon/UI/ComponentStack.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/ComponentStack.h	Sun Oct 18 09:49:15 2020 +0300
@@ -12,7 +12,7 @@
 
 namespace Gorgon { namespace UI {
     
-    class WidgetBase;
+    class Widget;
 
     /**
      * Component stack is the backbone of a widget. It manages the components inside the 
@@ -28,7 +28,7 @@
         /// Initializes a component stack with the given size. Generators are used to create widgets
         /// for the placeholders. If a function is empty or returns nullptr, neither a substack nor a
         /// widget will be placed there.
-        ComponentStack(const Template &temp, Geometry::Size size, std::map<ComponentTemplate::Tag, std::function<WidgetBase *(const Template &)>> generators = {});
+        ComponentStack(const Template &temp, Geometry::Size size, std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> generators = {});
         
         /// Initiates a component stack with default size
         explicit ComponentStack(const Template &temp) : ComponentStack(temp, temp.GetSize()) 
@@ -252,9 +252,12 @@
             return temp;
         }
         
+        /// Returns the template used by the component with given tag
+        const Template *GetTemplate(ComponentTemplate::Tag tag);
+        
         /// Returns the widget associated with the tag. If such widget does not exists
         /// nullptr will be returned instead.
-        WidgetBase *GetWidget(ComponentTemplate::Tag tag);
+        Widget *GetWidget(ComponentTemplate::Tag tag);
 
         /// Updates the layout of the component stack
         virtual void Update() override { Update(false); }
@@ -713,8 +716,8 @@
         std::function<void()> update_fn;
         std::function<void()> render_fn;
         
-        std::map<ComponentTemplate::Tag, std::function<WidgetBase *(const Template &)>> widgetgenerators;
-        Containers::Hashmap<const ComponentTemplate *, WidgetBase> widgets;
+        std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> widgetgenerators;
+        Containers::Hashmap<const ComponentTemplate *, Widget> widgets;
         
         std::function<std::string(int ind, ComponentTemplate::DataEffect, const std::array<float, 4> &value)> valuetotext;
         
--- a/Source/Gorgon/UI/ComponentStackWidget.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/ComponentStackWidget.h	Sun Oct 18 09:49:15 2020 +0300
@@ -1,6 +1,6 @@
 #pragma once
 
-#include "WidgetBase.h"
+#include "Widget.h"
 #include "ComponentStack.h"
 #include "WidgetContainer.h"
 
@@ -11,9 +11,9 @@
      * This class acts as a widget base that uses component stack to handle
      * rendering, resizing and other operations.
      */
-    class ComponentStackWidget : public WidgetBase {
+    class ComponentStackWidget : public Widget {
     public:
-        ComponentStackWidget(const Template &temp, std::map<ComponentTemplate::Tag, std::function<WidgetBase *(const Template &)>> generators = {}) : stack(*new ComponentStack(temp, temp.GetSize(), generators)) { }
+        ComponentStackWidget(const Template &temp, std::map<ComponentTemplate::Tag, std::function<Widget *(const Template &)>> generators = {}) : stack(*new ComponentStack(temp, temp.GetSize(), generators)) { }
         
         ComponentStackWidget(ComponentStackWidget &&) = default;
         
@@ -23,7 +23,7 @@
             delete &stack;
         }
         
-        using WidgetBase::Move;
+        using Widget::Move;
         
         virtual void Move(const Geometry::Point &location) override {
 			stack.Move(location);
@@ -32,7 +32,7 @@
                 boundschanged();
 		}
         
-        using WidgetBase::Resize;
+        using Widget::Resize;
         
         virtual void Resize(const Geometry::Size &size) override {
             stack.Resize(size);
@@ -93,19 +93,19 @@
         }
 
 		virtual void focused() override {
-            WidgetBase::focused();
+            Widget::focused();
 			stack.AddCondition(ComponentCondition::Focused);
 			FocusEvent();
 		}
 
 		virtual void focuslost() override {
-            WidgetBase::focuslost();
+            Widget::focuslost();
 			stack.RemoveCondition(ComponentCondition::Focused);
 			FocusEvent();
 		}
         
 		virtual void removed() override {
-			WidgetBase::removed();
+			     Widget::removed();
 
 			stack.FinalizeTransitions();
 		}
--- a/Source/Gorgon/UI/LayerAdapter.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/LayerAdapter.h	Sun Oct 18 09:49:15 2020 +0300
@@ -22,12 +22,12 @@
             SetFocusStrategy(Deny);
         }
         
-        virtual bool EnsureVisible(const Gorgon::UI::WidgetBase &widget) override {
+        virtual bool EnsureVisible(const Gorgon::UI::Widget &widget) override {
             return false;
         }
         
         virtual Geometry::Size GetInteriorSize() const override {
-            return base->GetSize();
+            return base->GetCalculatedSize();
         }
         
         virtual bool ResizeInterior(Geometry::Size size) override {
@@ -40,6 +40,10 @@
             return base->IsVisible();
         }
         
+        bool IsReady() const {
+            return base != nullptr;
+        }
+        
         void SetLayer(Gorgon::Layer &value) {
             base = &value;
         }
--- a/Source/Gorgon/UI/RadioControl.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/RadioControl.h	Sun Oct 18 09:49:15 2020 +0300
@@ -178,7 +178,7 @@
             
             int col = 0;
             for(auto p : elements) {
-                auto w = dynamic_cast<WidgetBase *>(&p.second);
+                auto w = dynamic_cast<Widget*>(&p.second);
                 
                 if(!w)
                     continue;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/UI/Widget.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -0,0 +1,107 @@
+#include "Widget.h"
+#include "WidgetContainer.h"
+
+namespace Gorgon { namespace UI {
+
+	bool Widget::Remove() {
+		if(!parent)
+			return true;
+
+		return parent->Remove(*this);
+	}
+
+	bool Widget::Focus() {
+		if(!parent)
+			return false;
+
+		if(!allowfocus() || !visible || !enabled)
+			return false;
+
+		return parent->SetFocusTo(*this);
+	}
+
+	bool Widget::Defocus() {
+		if(!IsFocused() || !parent)
+			return true;
+
+		return parent->RemoveFocus();
+	}
+
+	WidgetContainer &Widget::GetParent() const {
+		if(parent == nullptr)
+			throw std::runtime_error("Widget has no parent");
+
+		return *parent;
+	}
+
+
+    void Widget::SetVisible(bool value) {
+        if(visible != value) {
+            visible = value;
+            
+            if(value)
+                show();
+            else {
+                Defocus();
+                hide();
+            }
+            
+            if(parent)
+                parent->childboundschanged(this);
+        }
+    }
+    
+    
+    bool Widget::EnsureVisible() const {
+        if(!parent)
+            return false;
+        
+        return parent->EnsureVisible(*this);
+    }
+
+    void Widget::boundschanged(){
+        if(parent)
+            parent->childboundschanged(this);
+        
+        BoundsChangedEvent();
+    }
+
+
+    /// Called when this widget added to the given container
+    void Widget::addedto(WidgetContainer &container) {
+        if(parent == &container)
+            return;
+
+        parent = &container;
+
+        if(IsVisible())
+            boundschanged();
+
+        parentenabledchanged(parent->IsEnabled());
+    }
+
+    void Widget::removed(){
+        if(!parent)
+            return;
+        
+        parent->childboundschanged(this);
+
+        parent = nullptr;
+        
+        if(IsVisible())
+            boundschanged(); 
+    }
+    
+
+    void Widget::focuslost() {
+        focus = false;
+        FocusEvent();
+    }
+
+
+    void Widget::focused() {
+        focus = true;
+        FocusEvent();
+    }
+
+} }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/UI/Widget.h	Sun Oct 18 09:49:15 2020 +0300
@@ -0,0 +1,244 @@
+#pragma once
+
+#include "../Layer.h"
+#include "../Geometry/Point.h"
+#include "../Input/Keyboard.h"
+#include "../Geometry/PointProperty.h"
+#include "../Geometry/SizeProperty.h"
+
+namespace Gorgon { namespace UI {
+
+    class WidgetContainer;
+
+    /**
+    * This class is the base for all widgets. 
+    */
+    class Widget {
+    friend class WidgetContainer;
+        //Non-virtual functions for visual studio
+
+        void resize(const Geometry::Size &size) {
+            Resize(size);
+        }
+
+        Geometry::Size getsize() const {
+            return GetSize();
+        }
+
+        void move(const Geometry::Point &value) {
+            Move(value);
+        }
+
+        Geometry::Point getlocation() const {
+            return GetLocation();
+        }
+    public:
+        
+        Widget() : Location(this), Size(this) {
+        }
+        
+        Widget(Widget &&) = default;
+        
+        Widget& operator =(Widget &&) = default;
+        
+        virtual ~Widget() { }
+        
+        /// Moves this widget to the given position.
+        void Move(int x, int y) { Move({x, y}); }
+        
+        /// Moves this widget to the given position.
+        virtual void Move(const Geometry::Point &location) = 0;
+
+        /// Returns the location of the widget
+        virtual Geometry::Point GetLocation() const = 0;
+
+        /// Changes the size of the widget.
+        virtual void Resize(int w, int h) { Resize({w, h}); };
+
+        /// Changes the size of the widget.
+        virtual void Resize(const Geometry::Size &size) = 0;
+
+        /// Returns the size of the widget
+        virtual Geometry::Size GetSize() const = 0;
+        
+        /// Returns the bounds of the widget
+        Geometry::Bounds GetBounds() const { return {GetLocation(), GetSize()}; }
+        
+        /// Returns the width of the widget
+        int GetWidth() const { return GetSize().Width; }
+        
+        /// Returns the height of the widget
+        int GetHeight() const { return GetSize().Height; }
+        
+        /// Sets the width of the widget
+        void SetWidth(int width) { Resize(width, GetHeight()); }
+        
+        /// Sets the height of the widget
+        void SetHeight(int height) { Resize(GetWidth(), height); }
+        
+        /// Activates the widget. This might perform the action if the
+        /// widget is a button, forward the focus if it is a label or
+        /// focus if it is an input field.
+        virtual bool Activate() = 0;
+
+        /// Removes the widget from its parent. Returns true if the widget
+        /// has no parent after the operation.
+        bool Remove();
+        
+        /// If this widget can be focused currently
+        bool AllowFocus() const { return allowfocus() && visible; }
+        
+        /// Transfers the focus to this widget. Returns true if the focus
+        /// is actually transferred to this widget
+        bool Focus();
+        
+        /// Removes the focus from this widget if this widget is focused.
+        /// This function will not transfer the focus to another widget.
+        bool Defocus();
+        
+        /// Returns if this widget is focused.
+        bool IsFocused() const { return focus; }
+        
+        /// Shows this widget, widgets are visible by default.
+        void Show() { SetVisible(true); }
+        
+        /// Hides this widget, when hidden, widgets cannot gain focus
+        void Hide() { SetVisible(false); }
+        
+        /// Toggles the visibility state of the widget.
+        void ToggleVisible() { SetVisible(!IsVisible()); }
+        
+        /// Changes the visibility of the widget
+        void SetVisible(bool value);
+        
+        /// Returns if the widget is visible
+        bool IsVisible() const {
+            return visible;
+        }
+        
+        /// Ensures this widget is visible in its container by scrolling it
+        /// into view. This function will not change visibility of the widget
+        /// and will return false if the widget is not visible. This function 
+        /// cannot be expected to take outside factors into account, such as 
+        /// occlusion.
+        bool EnsureVisible() const;
+
+        /// Enables the widget so that the user can interact with it
+        void Enable() { SetEnabled(true); }
+
+        /// Disables the widget so that the user cannot interact with it
+        void Disable() { SetEnabled(false); }
+
+        /// Toggles enabled state of the widget
+        void ToggleEnabled() { SetEnabled(!IsEnabled()); }
+
+        /// Sets the enabled state of the widget
+        virtual void SetEnabled(bool value) = 0;
+
+        /// Returns whether the widget is enabled.
+        virtual bool IsEnabled() const = 0;
+
+        /// Returns if this widget has a parent
+        bool HasParent() const { return parent != nullptr; }
+
+        /// Returns the parent of this widget, throws if it does not have
+        /// a parent.
+        WidgetContainer &GetParent() const;
+
+        /// This function should be called whenever a key is pressed or released.
+        virtual bool KeyEvent(Input::Key, float) { return false; }
+
+        /// This function should be called whenever a character is received from
+        /// operating system.
+        virtual bool CharacterEvent(Char) { return false; }
+        
+        /// For widgets that supports it, this will trigger finalization the user
+        /// interaction. This may cause widget fire change event or reorganize
+        /// itself.
+        virtual bool Done() { return true; }
+
+        /// This event will be fired when the widget receives or looses focus.
+        Event<Widget> FocusEvent = Event<Widget>{*this};
+
+        /// This event will be fired when the area that the widget occupies on
+        /// its container is changed. It will be fired when the widget is hidden
+        /// or shown or its parent is changed. Movement, resize and parent change
+        /// will not trigger this event if the widget is not visible. Similarly,
+        /// if the object does not have a parent movement and resize will not
+        /// trigger this event. Organizers use this event to rearrange widgets, 
+        /// thus it is not advisable to remove all handlers from this event.
+        Event<Widget> BoundsChangedEvent = Event<Widget>{*this};
+        
+        Geometry::PointProperty<Widget, &Widget::getlocation, &Widget::move> Location;
+        Geometry::SizeProperty<Widget, &Widget::getsize, &Widget::resize> Size;
+        
+        /// This is a debug feature
+        void setname(std::string value) {
+#ifndef NDEBUG
+            dbgname = value;
+#endif
+        }
+        
+#ifndef NDEBUG
+    std::string dbgname;
+#endif
+
+    protected:
+        /// Called when it is about to be added to the given container
+        virtual bool addingto(WidgetContainer &) { return true; }
+        
+        /// When called, widget should locate itself on to this layer.
+        virtual void addto(Layer &layer) = 0;
+
+        /// Called when this widget added to the given container
+        virtual void addedto(WidgetContainer &container);
+
+        /// When called, widget should remove itself from the given layer
+        virtual void removefrom(Layer &layer) = 0;
+
+        /// Called before this widget is removed from its parent.
+        virtual bool removingfrom() { return true; }
+
+        /// Called after this widget is removed from its parent.
+        virtual void removed();
+
+        /// When called, widget should reorder itself in layer hierarchy
+        virtual void setlayerorder(Layer &layer, int order) = 0;
+
+        /// Should return true if the widget can be focused
+        virtual bool allowfocus() const { return true; }
+        
+        /// This is called after the focus is transferred to this widget.
+        virtual void focused();
+        
+        /// Should return true if the widget can loose the focus right now.
+        /// Even if you return false, you still might be forced to loose
+        /// focus, even without this function getting called.
+        virtual bool canloosefocus() const { return true; }
+        
+        /// This is called after the focus is lost. This is called even if
+        /// focus removal is forced.
+        virtual void focuslost();
+        
+        /// Call this function when the widget bounds is changed
+        virtual void boundschanged();
+
+        /// This function is called when the parent's enabled state changes.
+        virtual void parentenabledchanged(bool state) { }
+        
+    private:
+        bool visible = true;
+        bool enabled = true;
+        bool focus   = false;
+        
+        /// Never call this function
+        virtual void hide() = 0;
+        
+        /// Never call this function
+        virtual void show() = 0;
+        
+        WidgetContainer *parent = nullptr;
+    };
+    
+    
+} }
--- a/Source/Gorgon/UI/WidgetBase.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-#include "WidgetBase.h"
-#include "WidgetContainer.h"
-
-namespace Gorgon { namespace UI {
-
-	bool WidgetBase::Remove() {
-		if(!parent)
-			return true;
-
-		return parent->Remove(*this);
-	}
-
-	bool WidgetBase::Focus() {
-		if(!parent)
-			return false;
-
-		if(!allowfocus() || !visible || !enabled)
-			return false;
-
-		return parent->SetFocusTo(*this);
-	}
-
-	bool WidgetBase::Defocus() {
-		if(!IsFocused() || !parent)
-			return true;
-
-		return parent->RemoveFocus();
-	}
-
-	WidgetContainer &WidgetBase::GetParent() const {
-		if(parent == nullptr)
-			throw std::runtime_error("Widget has no parent");
-
-		return *parent;
-	}
-
-
-    void WidgetBase::SetVisible(bool value) {
-        if(visible != value) {
-            visible = value;
-            
-            if(value)
-                show();
-            else {
-                Defocus();
-                hide();
-            }
-            
-            if(parent)
-                parent->childboundschanged(this);
-        }
-    }
-    
-    
-    bool WidgetBase::EnsureVisible() const {
-        if(!parent)
-            return false;
-        
-        return parent->EnsureVisible(*this);
-    }
-
-    void WidgetBase::boundschanged(){
-        if(parent)
-            parent->childboundschanged(this);
-        
-        BoundsChangedEvent();
-    }
-
-
-    /// Called when this widget added to the given container
-    void WidgetBase::addedto(WidgetContainer &container) {
-        if(parent == &container)
-            return;
-
-        parent = &container;
-
-        if(IsVisible())
-            boundschanged();
-
-        parentenabledchanged(parent->IsEnabled());
-    }
-
-    void WidgetBase::removed(){
-        if(!parent)
-            return;
-        
-        parent->childboundschanged(this);
-
-        parent = nullptr;
-        
-        if(IsVisible())
-            boundschanged(); 
-    }
-    
-
-    void WidgetBase::focuslost() {
-        focus = false;
-        FocusEvent();
-    }
-
-
-    void WidgetBase::focused() {
-        focus = true;
-        FocusEvent();
-    }
-
-} }
--- a/Source/Gorgon/UI/WidgetBase.h	Wed Oct 14 11:20:25 2020 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-#pragma once
-
-#include "../Layer.h"
-#include "../Geometry/Point.h"
-#include "../Input/Keyboard.h"
-#include "../Geometry/PointProperty.h"
-#include "../Geometry/SizeProperty.h"
-
-namespace Gorgon { namespace UI {
-
-    class WidgetContainer;
-
-    /**
-    * This class is the base for all widgets. 
-    */
-    class WidgetBase {
-    friend class WidgetContainer;
-        //Non-virtual functions for visual studio
-
-        void resize(const Geometry::Size &size) {
-            Resize(size);
-        }
-
-        Geometry::Size getsize() const {
-            return GetSize();
-        }
-
-        void move(const Geometry::Point &value) {
-            Move(value);
-        }
-
-        Geometry::Point getlocation() const {
-            return GetLocation();
-        }
-    public:
-        
-        WidgetBase() : Location(this), Size(this) {
-        }
-        
-        WidgetBase(WidgetBase &&) = default;
-        
-        WidgetBase& operator =(WidgetBase &&) = default;
-        
-        virtual ~WidgetBase() { }
-        
-        /// Moves this widget to the given position.
-        void Move(int x, int y) { Move({x, y}); }
-        
-        /// Moves this widget to the given position.
-        virtual void Move(const Geometry::Point &location) = 0;
-
-        /// Returns the location of the widget
-        virtual Geometry::Point GetLocation() const = 0;
-
-        /// Changes the size of the widget.
-        virtual void Resize(int w, int h) { Resize({w, h}); };
-
-        /// Changes the size of the widget.
-        virtual void Resize(const Geometry::Size &size) = 0;
-
-        /// Returns the size of the widget
-        virtual Geometry::Size GetSize() const = 0;
-        
-        /// Returns the bounds of the widget
-        Geometry::Bounds GetBounds() const { return {GetLocation(), GetSize()}; }
-        
-        /// Returns the width of the widget
-        int GetWidth() const { return GetSize().Width; }
-        
-        /// Returns the height of the widget
-        int GetHeight() const { return GetSize().Height; }
-        
-        /// Sets the width of the widget
-        void SetWidth(int width) { Resize(width, GetHeight()); }
-        
-        /// Sets the height of the widget
-        void SetHeight(int height) { Resize(GetWidth(), height); }
-        
-        /// Activates the widget. This might perform the action if the
-        /// widget is a button, forward the focus if it is a label or
-        /// focus if it is an input field.
-        virtual bool Activate() = 0;
-
-        /// Removes the widget from its parent. Returns true if the widget
-        /// has no parent after the operation.
-        bool Remove();
-        
-        /// If this widget can be focused currently
-        bool AllowFocus() const { return allowfocus() && visible; }
-        
-        /// Transfers the focus to this widget. Returns true if the focus
-        /// is actually transferred to this widget
-        bool Focus();
-        
-        /// Removes the focus from this widget if this widget is focused.
-        /// This function will not transfer the focus to another widget.
-        bool Defocus();
-        
-        /// Returns if this widget is focused.
-        bool IsFocused() const { return focus; }
-        
-        /// Shows this widget, widgets are visible by default.
-        void Show() { SetVisible(true); }
-        
-        /// Hides this widget, when hidden, widgets cannot gain focus
-        void Hide() { SetVisible(false); }
-        
-        /// Toggles the visibility state of the widget.
-        void ToggleVisible() { SetVisible(!IsVisible()); }
-        
-        /// Changes the visibility of the widget
-        void SetVisible(bool value);
-        
-        /// Returns if the widget is visible
-        bool IsVisible() const {
-            return visible;
-        }
-        
-        /// Ensures this widget is visible in its container by scrolling it
-        /// into view. This function will not change visibility of the widget
-        /// and will return false if the widget is not visible. This function 
-        /// cannot be expected to take outside factors into account, such as 
-        /// occlusion.
-        bool EnsureVisible() const;
-
-        /// Enables the widget so that the user can interact with it
-        void Enable() { SetEnabled(true); }
-
-        /// Disables the widget so that the user cannot interact with it
-        void Disable() { SetEnabled(false); }
-
-        /// Toggles enabled state of the widget
-        void ToggleEnabled() { SetEnabled(!IsEnabled()); }
-
-        /// Sets the enabled state of the widget
-        virtual void SetEnabled(bool value) = 0;
-
-        /// Returns whether the widget is enabled.
-        virtual bool IsEnabled() const = 0;
-
-        /// Returns if this widget has a parent
-        bool HasParent() const { return parent != nullptr; }
-
-        /// Returns the parent of this widget, throws if it does not have
-        /// a parent.
-        WidgetContainer &GetParent() const;
-
-        /// This function should be called whenever a key is pressed or released.
-        virtual bool KeyEvent(Input::Key, float) { return false; }
-
-        /// This function should be called whenever a character is received from
-        /// operating system.
-        virtual bool CharacterEvent(Char) { return false; }
-        
-        /// For widgets that supports it, this will trigger finalization the user
-        /// interaction. This may cause widget fire change event or reorganize
-        /// itself.
-        virtual bool Done() { return true; }
-
-        /// This event will be fired when the widget receives or looses focus.
-        Event<WidgetBase> FocusEvent = Event<WidgetBase>{*this};
-
-        /// This event will be fired when the area that the widget occupies on
-        /// its container is changed. It will be fired when the widget is hidden
-        /// or shown or its parent is changed. Movement, resize and parent change
-        /// will not trigger this event if the widget is not visible. Similarly,
-        /// if the object does not have a parent movement and resize will not
-        /// trigger this event. Organizers use this event to rearrange widgets, 
-        /// thus it is not advisable to remove all handlers from this event.
-        Event<WidgetBase> BoundsChangedEvent = Event<WidgetBase>{*this};
-        
-        Geometry::PointProperty<WidgetBase, &WidgetBase::getlocation, &WidgetBase::move> Location;
-        Geometry::SizeProperty<WidgetBase, &WidgetBase::getsize, &WidgetBase::resize> Size;
-        
-        /// This is a debug feature
-        void setname(std::string value) {
-#ifndef NDEBUG
-            dbgname = value;
-#endif
-        }
-        
-#ifndef NDEBUG
-    std::string dbgname;
-#endif
-
-    protected:
-        /// Called when it is about to be added to the given container
-        virtual bool addingto(WidgetContainer &) { return true; }
-        
-        /// When called, widget should locate itself on to this layer.
-        virtual void addto(Layer &layer) = 0;
-
-        /// Called when this widget added to the given container
-        virtual void addedto(WidgetContainer &container);
-
-        /// When called, widget should remove itself from the given layer
-        virtual void removefrom(Layer &layer) = 0;
-
-        /// Called before this widget is removed from its parent.
-        virtual bool removingfrom() { return true; }
-
-        /// Called after this widget is removed from its parent.
-        virtual void removed();
-
-        /// When called, widget should reorder itself in layer hierarchy
-        virtual void setlayerorder(Layer &layer, int order) = 0;
-
-        /// Should return true if the widget can be focused
-        virtual bool allowfocus() const { return true; }
-        
-        /// This is called after the focus is transferred to this widget.
-        virtual void focused();
-        
-        /// Should return true if the widget can loose the focus right now.
-        /// Even if you return false, you still might be forced to loose
-        /// focus, even without this function getting called.
-        virtual bool canloosefocus() const { return true; }
-        
-        /// This is called after the focus is lost. This is called even if
-        /// focus removal is forced.
-        virtual void focuslost();
-        
-        /// Call this function when the widget bounds is changed
-        virtual void boundschanged();
-
-        /// This function is called when the parent's enabled state changes.
-        virtual void parentenabledchanged(bool state) { }
-        
-    private:
-        bool visible = true;
-        bool enabled = true;
-        bool focus   = false;
-        
-        /// Never call this function
-        virtual void hide() = 0;
-        
-        /// Never call this function
-        virtual void show() = 0;
-        
-        WidgetContainer *parent = nullptr;
-    };
-    
-    
-} }
--- a/Source/Gorgon/UI/WidgetContainer.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/WidgetContainer.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -2,7 +2,7 @@
 
 namespace Gorgon { namespace UI {
     
-    bool WidgetContainer::Add(WidgetBase &widget) {
+    bool WidgetContainer::Add(Widget &widget) {
         if(widgets.Find(widget) != widgets.end())
             return true;
 
@@ -25,7 +25,7 @@
         return true;
     }
 
-    bool WidgetContainer::Insert(WidgetBase &widget, int index) {
+    bool WidgetContainer::Insert(Widget &widget, int index) {
         if(widgets.Find(widget) != widgets.end()) {
             ChangeFocusOrder(widget, index);
             ChangeZorder(widget, index);
@@ -54,7 +54,7 @@
         return true;
     }
 
-    bool WidgetContainer::Remove(WidgetBase &widget) {
+    bool WidgetContainer::Remove(Widget &widget) {
         auto pos = widgets.Find(widget);
 
         //not our widget
@@ -72,7 +72,7 @@
         return true;
     }
 
-    void WidgetContainer::ForceRemove(WidgetBase &widget) {
+    void WidgetContainer::ForceRemove(Widget &widget) {
         auto pos = widgets.Find(widget);
 
         //not our widget
@@ -92,7 +92,7 @@
         widget.removed();
     }
 
-    void WidgetContainer::ChangeFocusOrder(WidgetBase &widget, int order) {
+    void WidgetContainer::ChangeFocusOrder(Widget &widget, int order) {
         auto pos = widgets.Find(widget);
 
         //not our widget
@@ -115,7 +115,7 @@
         widgets.MoveBefore(widget, order);
     }
 
-    int WidgetContainer::GetFocusOrder(const WidgetBase& widget) const {
+    int WidgetContainer::GetFocusOrder(const Widget& widget) const {
         auto pos = widgets.Find(widget);
 
         if(pos == widgets.end())
@@ -124,7 +124,7 @@
         return pos - widgets.begin();
     }
 
-    void WidgetContainer::ChangeZorder(WidgetBase &widget, int order) {
+    void WidgetContainer::ChangeZorder(Widget &widget, int order) {
         auto &l = getlayer();
         auto pos = widgets.Find(widget);
 
@@ -171,8 +171,8 @@
         //if this container is top level focus will rollover
 
         // if this container is a widget
-        if(dynamic_cast<WidgetBase*>(this)) {
-            auto w = dynamic_cast<WidgetBase*>(this);
+        if(dynamic_cast<Widget*>(this)) {
+            auto w = dynamic_cast<Widget*>(this);
 
             // that has a parent
             if(w->HasParent()) {
@@ -243,8 +243,8 @@
         //if this container is top level focus will rollover
         
         // if this container is a widget
-        if(dynamic_cast<WidgetBase*>(this)) {
-            auto w = dynamic_cast<WidgetBase*>(this);
+        if(dynamic_cast<Widget*>(this)) {
+            auto w = dynamic_cast<Widget*>(this);
             
             // that has a parent
             if(w->HasParent()) {
@@ -294,7 +294,7 @@
         return false;
     }
 
-    bool WidgetContainer::SetFocusTo(WidgetBase &widget) {
+    bool WidgetContainer::SetFocusTo(Widget &widget) {
         if(CurrentFocusStrategy() == Deny)
             return false;
         
@@ -359,7 +359,7 @@
     }
 
 
-    Gorgon::UI::WidgetBase & WidgetContainer::GetFocus() const {
+    Gorgon::UI::Widget & WidgetContainer::GetFocus() const {
         if(!focused)
             throw std::runtime_error("No widget is focused");
 
@@ -428,7 +428,7 @@
             w.parentenabledchanged(state);
     }
 
-    void WidgetContainer::childboundschanged(WidgetBase *) {
+    void WidgetContainer::childboundschanged(Widget *) {
         if(organizer)
             organizer->Reorganize();
     }
--- a/Source/Gorgon/UI/WidgetContainer.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/WidgetContainer.h	Sun Oct 18 09:49:15 2020 +0300
@@ -2,7 +2,7 @@
 
 #include <stdexcept>
 
-#include "WidgetBase.h"
+#include "Widget.h"
 #include "../Layer.h"
 #include "../Input/Keyboard.h"
 #include "Organizers/Base.h"
@@ -17,7 +17,7 @@
     * at the same time.
     */
     class WidgetContainer {
-        friend class WidgetBase;
+        friend class Widget;
     public:
         /// Defines focus strategy for the container. Default is Inherit
         enum FocusStrategy {
@@ -58,35 +58,35 @@
         /// be placed to the top of the z-order, to the end of the
         /// focus order. If the given widget cannot be added, this
         /// function will return false.
-        bool Add(WidgetBase &widget);
+        bool Add(Widget &widget);
 
         /// Add the given widget to this container. Widget will
         /// be placed to the top of the z-order, and to the specified
         /// focus order. If the given widget cannot be added, this
         /// function will return false. If the index is out of bounds
         /// the widget will be added at the end.
-        bool Insert(WidgetBase &widget, int index);
+        bool Insert(Widget &widget, int index);
 
         /// Removes the given widget from this container. If the
         /// widget does not exits, this function will return true without
         /// taking any additional action. If the widget cannot be removed
         /// from the container, this function will return false.
-        bool Remove(WidgetBase &widget);
+        bool Remove(Widget &widget);
 
         /// Forcefully removes the given widget from this container.
-        void ForceRemove(WidgetBase &widget);
+        void ForceRemove(Widget &widget);
 
         /// Changes the focus order of the given widget. If the order
         /// is out of bounds, the widget will be moved to the end.
         /// You may use the functions in the widget to manage focus order.
-        void ChangeFocusOrder(WidgetBase &widget, int order);
+        void ChangeFocusOrder(Widget &widget, int order);
 
-        int GetFocusOrder(const WidgetBase &widget) const;
+        int GetFocusOrder(const Widget &widget) const;
 
         /// Changes the z-order of the widget. If the order is out of
         /// bounds, the widget will be drawn on top. You may use the
         /// functions in the widget to manage z-order.
-        void ChangeZorder(WidgetBase &widget, int order);
+        void ChangeZorder(Widget &widget, int order);
         
         /// Focuses the first widget that accepts focus. If none of the
         /// widgets accept focus or if the currently focused widget blocks
@@ -112,7 +112,7 @@
         /// accept focus then this function will return false. Additionally, 
         /// if the currently focused widget blocks focus transfer, this function 
         /// will return false.
-        bool FocusNext(const WidgetBase &widget) { return FocusNext(GetFocusOrder(widget)); }
+        bool FocusNext(const Widget &widget) { return FocusNext(GetFocusOrder(widget)); }
 
         /// Focuses the last widget in the container. If none of the
         /// widgets accept focus or if the currently focused widget blocks
@@ -131,7 +131,7 @@
         /// this function will return false. Additionally, if the currently
         /// focused widget blocks focus transfer, this function will
         /// return false.
-        bool FocusPrevious(const WidgetBase& widget) { return FocusNext(GetFocusOrder(widget)); }
+        bool FocusPrevious(const Widget& widget) { return FocusNext(GetFocusOrder(widget)); }
 
         /// Focuses the previous widget that accepts focus. If no widget 
         /// other than the currently focused widget accept focus then 
@@ -141,7 +141,7 @@
         bool FocusPrevious(int before);
 
         /// Sets the focus to the given widget
-        bool SetFocusTo(WidgetBase &widget);
+        bool SetFocusTo(Widget &widget);
         
         /// Removes the focus from the focused widget
         bool RemoveFocus();
@@ -154,14 +154,14 @@
 
         /// Returns the focused widget. If no widget is focused, this function
         /// will throw.
-        WidgetBase &GetFocus() const;
+        Widget &GetFocus() const;
         
         /// Ensures the widget is visible. Returns true if the container can be
         /// scroll to make sure the given widget is visible. This function cannot
         /// be expected to take outside factors into account, such as occlusion.
         /// This function does not change the visibility of the widget and will
         /// return false if the widget is not visible.
-        virtual bool EnsureVisible(const WidgetBase &widget) = 0;
+        virtual bool EnsureVisible(const Widget &widget) = 0;
         
         /// Should return whether the container is visible. Due to
         /// different container designs and capabilities, setting
@@ -252,12 +252,12 @@
         }
         
         /// Returns the widget at the given index
-        const WidgetBase &operator [](int ind) const {
+        const Widget &operator [](int ind) const {
             return widgets[ind];
         }
         
         /// Returns the widget at the given index
-        WidgetBase &operator [](int ind) {
+        Widget &operator [](int ind) {
             return widgets[ind];
         }
         
@@ -268,7 +268,7 @@
         /// can be designated as default widget. If there is no default object, 
         /// this function will throw. Use HasDefault to check if this container 
         /// has a default widget.
-        virtual WidgetBase &GetDefault() const {
+        virtual Widget &GetDefault() const {
             if(!def) 
                 throw std::runtime_error("Container does not have a default");
             
@@ -280,7 +280,7 @@
         
         /// Sets the default object of the container. Ideally this should be
         /// a button or a similar widget.
-        virtual void SetDefault(WidgetBase &widget) { def=&widget; }
+        virtual void SetDefault(Widget &widget) { def=&widget; }
         
         /// Removes the default widget of this container.
         virtual void RemoveDefault() { def=nullptr; }
@@ -290,7 +290,7 @@
         /// Cancel elements are generally buttons, however, any widget can 
         /// be cancel widget. If there is no cancel object set, this function 
         /// will throw. Use HasCancel to check if this container has a cancel widget.
-        virtual WidgetBase &GetCancel() const { 
+        virtual Widget &GetCancel() const { 
             if(!def) 
                 throw std::runtime_error("Container does not have a default");
             
@@ -302,7 +302,7 @@
         
         /// Sets the cancel widget of the container. Ideally this should be
         /// a button or a similar widget.
-        virtual void SetCancel(WidgetBase &widget) { cancel=&widget; }
+        virtual void SetCancel(Widget &widget) { cancel=&widget; }
         
         /// Removes the cancel widget of this container.
         virtual void RemoveCancel() { cancel=nullptr; }
@@ -369,22 +369,22 @@
 
     protected:
         /// This container is sorted by the focus order
-        Containers::Collection<WidgetBase> widgets;
+        Containers::Collection<Widget> widgets;
 
         /// This function can return false to prevent the given
         /// widget from getting added to the container.
-        virtual bool addingwidget(WidgetBase &) { return true; }
+        virtual bool addingwidget(Widget &) { return true; }
 
         /// This function is called after a widget is added.
-        virtual void widgetadded(WidgetBase &) { }
+        virtual void widgetadded(Widget &) { }
 
         /// This function is called before removing a widget. Return false
         /// to prevent that widget from getting removed. This widget is
         /// guaranteed to be in this container
-        virtual bool removingwidget(WidgetBase &) { return true; }
+        virtual bool removingwidget(Widget &) { return true; }
 
         /// This function is called after a widget is removed
-        virtual void widgetremoved(WidgetBase &) { }
+        virtual void widgetremoved(Widget &) { }
 
         /// If this widget is not top level, return the current strategy used by the
         /// parent. Never return Inherit from this function.
@@ -412,14 +412,14 @@
         void distributeparentenabled(bool state);
 
         /// The boundary of any of the children is changed. Source could be nullptr
-        virtual void childboundschanged(WidgetBase *source);
+        virtual void childboundschanged(Widget *source);
 
     private:
         bool isenabled              = true;
         bool tabswitch              = true;
-        WidgetBase *def             = nullptr;
-        WidgetBase *cancel          = nullptr;
-        WidgetBase *focused         = nullptr;
+        Widget *def             = nullptr;
+        Widget *cancel          = nullptr;
+        Widget *focused         = nullptr;
         int focusindex	            = -1;
         Organizers::Base *organizer = nullptr;
         bool ownorganizer           = false;
--- a/Source/Gorgon/UI/Window.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/Window.h	Sun Oct 18 09:49:15 2020 +0300
@@ -85,7 +85,7 @@
         }
         
         /// Window does not do any scrolling, thus cannot ensure visibility
-        bool EnsureVisible(const UI::WidgetBase &) override {
+        bool EnsureVisible(const UI::Widget &) override {
             return true;
         }
         
--- a/Source/Gorgon/UI/dir.cmake	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/UI/dir.cmake	Sun Oct 18 09:49:15 2020 +0300
@@ -14,8 +14,8 @@
 	UI.cpp
 	TwoStateControl.h
 	Validators.h
-	WidgetBase.h
-	WidgetBase.cpp
+	Widget.h
+	Widget.cpp
 	WidgetContainer.h
 	WidgetContainer.cpp
 	Window.h
--- a/Source/Gorgon/Widgets/Composer.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Composer.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -25,12 +25,12 @@
     void Composer::focused() {
         if(!HasFocusedWidget())
             FocusFirst();
-        WidgetBase::focused();
+        Widget::focused();
     }
     
     void Composer::focuslost() {
         RemoveFocus();
-        WidgetBase::focuslost();
+        Widget::focuslost();
     }
 
     void Composer::focuschanged() { 
--- a/Source/Gorgon/Widgets/Composer.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Composer.h	Sun Oct 18 09:49:15 2020 +0300
@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../UI/WidgetBase.h"
+#include "../UI/Widget.h"
 #include "../UI/WidgetContainer.h"
 
 namespace Gorgon { namespace Widgets {
@@ -16,15 +16,15 @@
      * in widgets in the composer. This object does not support scrolling, however,
      * you may place a panel in it to have that functionality.
      */
-    class Composer : public UI::WidgetBase, protected UI::WidgetContainer {
+    class Composer : public UI::Widget, protected UI::WidgetContainer {
     public:
         ~Composer() { }
         
-        using WidgetBase::Resize;
+        using Widget::Resize;
        
-        using WidgetBase::Move;
+        using Widget::Move;
 
-        using WidgetBase::Remove;
+        using Widget::Remove;
         
         using WidgetContainer::Remove;
 
@@ -57,15 +57,15 @@
         
         virtual void Move(const Geometry::Point &location) override;
 
-        using WidgetBase::EnsureVisible;
+        using Widget::EnsureVisible;
         
-        bool EnsureVisible(const UI::WidgetBase &widget) override {
+        bool EnsureVisible(const UI::Widget &widget) override {
             return true;
         }
 
-        using WidgetBase::Enable;
-        using WidgetBase::Disable;
-        using WidgetBase::ToggleEnabled;
+        using Widget::Enable;
+        using Widget::Disable;
+        using Widget::ToggleEnabled;
 
         virtual void SetEnabled(bool value) override {
             if(value != IsEnabled()) {
--- a/Source/Gorgon/Widgets/Generator.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Generator.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -1596,7 +1596,7 @@
     }
     
     UI::Template SimpleGenerator::Listbox() {
-        Geometry::Size defsize = {WidgetWidth*2+Spacing, BorderedWidgetHeight*10};
+        Geometry::Size defsize = {WidgetWidth*2+Spacing, BorderedWidgetHeight*8};
         
         UI::Template temp;
         
@@ -1612,8 +1612,7 @@
             .AddIndex(5) //scrollbar
         ;
         bg.Background.SetAnimation(NormalBG());
-        bg.SetBorderSize(Border.Width);
-        bg.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
+        bg.SetPadding(std::max(Border.Radius / 2, Focus.Spacing)+Border.Width);
         
         auto &viewport = temp.AddContainer(1, UI::ComponentCondition::Always)
             .AddIndex(2)
@@ -1630,15 +1629,27 @@
         border.SetValueRange(0, 0.5, 1);
         border.SetReversible(true);
         border.SetPositioning(UI::ComponentTemplate::Absolute);
+        border.SetMargin(-Border.Width-std::max(Border.Radius / 2, Focus.Spacing));
         border.Background.SetAnimation(NormalEmptyBorder());
         
-        temp.AddPlaceholder(4, UI::ComponentCondition::Always)
-            .SetTemplate(listbox_listitem)
-        ;
+        auto &item = temp.AddPlaceholder(4, UI::ComponentCondition::Always);
+        item.SetTemplate(listbox_listitem);
+        item.SetTag(UI::ComponentTemplate::ItemTag);
+        
+        auto &vs = temp.AddPlaceholder(5, UI::ComponentCondition::VScroll);
+        vs.SetTemplate(vst);
+        vs.SetTag(UI::ComponentTemplate::VScrollTag);
+        vs.SetSize(vst.GetWidth(), {100, UI::Dimension::Percent});
+        vs.SetSizing(UI::ComponentTemplate::Fixed);
+        vs.SetAnchor(UI::Anchor::TopRight, UI::Anchor::TopRight, UI::Anchor::TopLeft);
+        vs.SetMargin(Spacing, 0, 0, 0);
         
         
         //****** listitem
         
+        //TODO fix height
+        listbox_listitem.SetSize(defsize.Width - (Border.Width + std::max(Border.Radius / 2, Focus.Spacing)) * 2, WidgetHeight);
+        
         listbox_listitem.AddContainer(0, UI::ComponentCondition::Always)
             .AddIndex(1) //background
             .AddIndex(2) //cliped content
@@ -1661,7 +1672,7 @@
             .AddIndex(5)
         ;
         clip.SetClip(true);
-        clip.SetPadding(Focus.Spacing + Focus.Width);
+        clip.SetPadding(Focus.Width);
         clip.SetSize(100, 100, UI::Dimension::Percent);
         
         //Contents
@@ -1670,7 +1681,6 @@
             .AddIndex(7) //text
         ;
         content.SetSize(100, 100, UI::Dimension::Percent);
-        content.SetSizing(UI::ComponentTemplate::Automatic);
         content.SetPositioning(UI::ComponentTemplate::Absolute);
         content.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
         content.SetPadding(Focus.Spacing);
@@ -1712,7 +1722,7 @@
             txt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             txt.SetDataEffect(UI::ComponentTemplate::Text);
             txt.SetSize(100, 100, UI::Dimension::Percent);
-            txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+            txt.SetMargin(0, Focus.Spacing * 2);
         };
         
         setuptext(Forecolor.Regular, UI::ComponentCondition::Always);
@@ -1727,19 +1737,11 @@
         auto &img = *new Graphics::BlankImage(8, 8, Background.Selected);
         drawables.Add(img);
         textbg.Background.SetAnimation(img);
-        textbg.SetMargin(0, Focus.Spacing);
+        textbg.SetMargin(0, -Focus.Spacing);
         textbg.SetPadding(0, Focus.Spacing);
 
         setupfocus(listbox_listitem.AddGraphics(3, UI::ComponentCondition::Focused));
         
-        auto &vs = temp.AddPlaceholder(5, UI::ComponentCondition::VScroll);
-        vs.SetTemplate(vst);
-        vs.SetTag(UI::ComponentTemplate::VScrollTag);
-        vs.SetSize(vst.GetWidth(), {100, UI::Dimension::Percent});
-        vs.SetSizing(UI::ComponentTemplate::Fixed);
-        vs.SetAnchor(UI::Anchor::TopRight, UI::Anchor::TopRight, UI::Anchor::TopLeft);
-        vs.SetMargin(Spacing, 0, 0, 0);
-        
         return temp;
     }
 }}
--- a/Source/Gorgon/Widgets/GeometryBoxes.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/GeometryBoxes.h	Sun Oct 18 09:49:15 2020 +0300
@@ -17,7 +17,7 @@
     public:
         using Inputbox::operator=;
         
-        using WidgetBase::Move;
+        using Widget::Move;
 
         /// Initializes the inputbox
         explicit Pointbox(const UI::Template &temp, Geometry::Point value = {0, 0}) : Inputbox(temp, value) {
@@ -49,7 +49,7 @@
     public:
         using Inputbox::operator=;
         
-        using WidgetBase::Move;
+        using Widget::Move;
 
 
         /// Initializes the inputbox
@@ -83,7 +83,7 @@
     public:
         using Inputbox::operator=;
         
-        using WidgetBase::Move;
+        using Widget::Move;
 
 
         /// Initializes the inputbox
@@ -115,7 +115,7 @@
     public:
         using Inputbox::operator=;
 
-        using WidgetBase::Move;
+        using Widget::Move;
 
 
         /// Initializes the inputbox
--- a/Source/Gorgon/Widgets/ListItem.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/ListItem.h	Sun Oct 18 09:49:15 2020 +0300
@@ -37,7 +37,11 @@
         ListItem(const UI::Template &temp) :
             UI::ComponentStackWidget(temp)
         {
-            stack.HandleMouse();
+            stack.HandleMouse(); 
+            stack.SetClickEvent([&](auto, auto, auto) {
+                ClickEvent();
+                ToggleEvent();
+            });
         }
 
         /// Changes the text displayed. Depending on the template, text might be
--- a/Source/Gorgon/Widgets/Listbox.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Listbox.h	Sun Oct 18 09:49:15 2020 +0300
@@ -7,11 +7,10 @@
 #include "Registry.h"
 #include "ListItem.h"
 #include <vector>
+#include "Scrollbar.h"
 
 namespace Gorgon { namespace Widgets {
     
-    //TODO how to deal with pointers and references
-    
     /**
      * This is the abstract base of listboxes. It is mainly used to allow list
      * mixins to access list items.
@@ -22,8 +21,6 @@
         virtual ~ListBase() {
         }
         
-        //TODO add, remove, insert, move, push_back (for back inserter)
-        
         /// Returns the item at the given point. This operator will not perform
         /// bounds checking.
         virtual T_ &operator[](long index) = 0;
@@ -36,6 +33,19 @@
         virtual long GetCount() const = 0;
         
         /// For internal use.
+        /// Returns the first widget used to represent any item at within the 
+        /// listbox. This function will return nullptr if there are no items in the
+        /// list.
+        virtual long getindex(const W_ &widget) = 0;
+        
+        /// This function should refresh the contents of the listbox. Normally, 
+        /// calling this function is not necessary as it is handled internally.
+        /// This function may defer refresh to next frame.
+        virtual void Refresh() = 0;
+        
+    protected:
+
+        /// For internal use.
         /// Returns the widget used to represent the item at the given index. This
         /// function will return nullptr if the index does not currently have a
         /// visual representation. This is not an edge case, any item that is not
@@ -47,6 +57,7 @@
         /// listbox. This function will return nullptr if there are no items in the
         /// list.
         virtual W_ *getrepresentation() = 0;
+        
     };
     
     /// @cond internal
@@ -58,12 +69,13 @@
         class LBTR_blank {
         public:
             void Apply(W_ &, const T_ &, Geometry::Point, Geometry::Size) { }
+            
             UI::ComponentTemplate::Tag Tag(const T_ &, Geometry::Point, Geometry::Size) {
-                return UI::ComponentTemplate::UnknownTag;
+                return UI::ComponentTemplate::ItemTag;
             }
         };
         
-        template <class T_, class W_>
+        template <class T_, class W_, class F_>
         class LBTRF_blank {
             using TR_ = LBTR_blank<T_, W_>;
         protected:
@@ -92,7 +104,7 @@
         
         //This class allows single selection. The selected item will
         //follow the focus by default. If desired, this can be changed
-        template<class T_, class W_>
+        template<class T_, class W_, class F_>
         class LBSELTR_Single {
         public:
             /// Returns true if this listbox has a selected item.
@@ -107,7 +119,7 @@
                 if(selectedindex == -1)
                     throw std::runtime_error("Nothing is selected.");
                 
-                return dynamic_cast<ListBase<T_, W_>&>(*this)[selectedindex];
+                return dynamic_cast<const F_&>(*this)[selectedindex];
             }
             
             /// Returns the index of the selected item. -1 will be returned if 
@@ -120,7 +132,7 @@
             /// bounds this function will throw std::out_of_range exception. -1
             /// can be used to remove selected item.
             void SetSelectedIndex(long index) {
-                if(index < -1 || index >= dynamic_cast<ListBase<T_, W_>&>(*this).GetSize())
+                if(index < -1 || index >= dynamic_cast<F_&>(*this).GetSize())
                     throw std::out_of_range("Selected index does not exits");
                 
                 if(index == selectedindex)
@@ -128,18 +140,18 @@
                 
                 if(focusonly) {
                     if(index == -1) {
-                        W_ *elm = dynamic_cast<ListBase<T_, W_>&>(*this).getrepresentation();
+                        W_ *elm = dynamic_cast<F_&>(*this).getrepresentation();
                         if(elm != nullptr && elm->HasParent()) {
                             elm->GetParent().RemoveFocus();
                         }
                     }
                     else {
-                        W_ *elm = dynamic_cast<ListBase<T_, W_>&>(*this).getrepresentation(index);
+                        W_ *elm = dynamic_cast<F_&>(*this).getrepresentation(index);
                         if(elm != nullptr) {
                             elm->Focus();
                         }
                         else {
-                            elm = dynamic_cast<ListBase<T_, W_>&>(*this).getrepresentation();
+                            elm = dynamic_cast<F_&>(*this).getrepresentation();
                             
                             if(elm != nullptr && elm->HasParent()) {
                                 elm->GetParent().RemoveFocus();
@@ -154,13 +166,14 @@
                     selected->SetSelected(false);
                 
                 if(index != -1) {
-                    W_ *elm = dynamic_cast<ListBase<T_, W_>&>(*this).getrepresentation(index);
+                    W_ *elm = dynamic_cast<F_&>(*this).getrepresentation(index);
                     
                     if(elm)
                         elm->SetSelected(true);
                 }
                 
                 selectedindex = index;
+                ChangedEvent(selectedindex);
             }
             
             void RemoveSelection() {
@@ -170,7 +183,7 @@
             /// Selects the first item that has the given value. If item does
             /// not exists, this function will remove the selection
             void SetSelection(T_ item) {
-                auto &me = dynamic_cast<ListBase<T_, W_>&>(*this);
+                auto &me = dynamic_cast<F_&>(*this);
                 
                 for(long i=0; i<me.GetSize(); i++) {
                     if(me[i] == item) {
@@ -199,7 +212,7 @@
                     if(focusindex != -1) {
                         if(selectedindex != focusindex) {
                             selectedindex = focusindex;
-                            SelectionChanged(selectedindex);
+                            ChangedEvent(selectedindex);
                         }
                     }
                     else {
@@ -210,12 +223,22 @@
                 focusonly = value;
             }
             
-            Event<LBSELTR_Single, long> SelectionChanged = Event<LBSELTR_Single, long>{this};
+            operator T_() {
+                return GetSelectedItem();
+            }
+            
+            operator T_() const {
+                return GetSelectedItem();
+            }
+            
+            Event<LBSELTR_Single, long> ChangedEvent = Event<LBSELTR_Single, long>{this};
             
         protected:
             LBSELTR_Single() {
             }
             
+            virtual ~LBSELTR_Single() { }
+            
             void clicked(long index, W_ &w) {
                 if(focusonly) {
                     if(selectedindex == index)
@@ -225,19 +248,27 @@
                         selected->SetSelected(false);
                     
                     w.SetSelected(true);
-                    w.Focus();
+                    
+                    if(dynamic_cast<UI::Widget*>(this)->IsFocused())
+                        w.Focus();
                     
                     selected = &w;
                     selectedindex = index;
                     focusindex    = index;
+                    
+                    ChangedEvent(index);
                 }
                 else {
                     if(focusindex == index)
                         return;
                     
-                    w.Focus();
+                    if(dynamic_cast<UI::Widget*>(this)->IsFocused())
+                        w.Focus();
+                    
                     focusindex = index;
                 }
+                
+                dynamic_cast<UI::Widget*>(this)->Focus();
             }
             
             void toggled(long index, W_ &w) {
@@ -252,9 +283,13 @@
                 selected = &w;
                 
                 if(focusonly) {
-                    w.Focus();
+                    if(dynamic_cast<UI::Widget*>(this)->IsFocused())
+                        w.Focus();
+                    
                     focusindex = index;
                 }
+                
+                ChangedEvent(index);
             }
             
             void apply(long index, W_ &w, const T_ &) {
@@ -262,23 +297,28 @@
                     w.Focus();
                 }
                 else if(w.IsFocused()) {
-                    w.RemoveFocus();
+                    w.Defocus();
                 }
                 
                 if(index == selectedindex) {
                     w.SetSelected(true);
-                    w = &w;
+                    selected = &w;
                 }
                 else {
                     w.SetSelected(false);
                     
                     if(&w == selected)
-                        w = nullptr;
+                        selected = nullptr;
                 }
             }
             
-            void prepare(W_ &) {
-                //nothing to be done
+            void prepare(W_ &w) {
+                w.ClickEvent.Register([&w, this] {
+                    clicked(dynamic_cast<F_*>(this)->getindex(w), w);
+                });
+                w.ToggleEvent.Register([&w, this] {
+                    toggled(dynamic_cast<F_*>(this)->getindex(w), w);
+                });
             }
             
             void insert(long index, long count) { 
@@ -318,6 +358,7 @@
                 if(index <= focusindex) {
                     if(index+count > focusindex) {
                         focusindex = -1;
+                        ChangedEvent(-1);
                     }
                     else {
                         focusindex -= count;
@@ -327,6 +368,7 @@
                 if(index <= selectedindex) {
                     if(index+count > selectedindex) {
                         selectedindex = -1;
+                        ChangedEvent(-1);
                     }
                     else {
                         selectedindex -= count;
@@ -338,6 +380,7 @@
                 if(&w == selected) {
                     selected = nullptr;
                     selectedindex = -1;
+                    ChangedEvent(-1);
                 }
                 if(w.IsFocused()) {
                     focusindex = -1;
@@ -345,6 +388,14 @@
                 }
             }
             
+            void reapplyfocus() {
+                if(focusindex != -1) {
+                    auto w = dynamic_cast<F_*>(this)->getrepresentation(focusindex);
+                    if(w)
+                        w->Focus();
+                }
+            }
+            
             bool focusonly = true;
             
             long focusindex = -1, selectedindex = -1;
@@ -352,17 +403,71 @@
             W_ *selected = nullptr;
         };
         
-        template<class S_>
-        typename std::enable_if<TMP::FunctionTraits<decltype(&S_::size)>::IsMember, long>::type 
-        getsize(const S_ &storage) {
-            return storage.size();
-        }
+        template<class T_, class W_, class S_, class F_>
+        class LBSTR_STLVector {
+        public:
+            using Storage = S_;
+            
+            void Add(T_ val) {
+                storage.push_back(val);
+                
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            template<class... A_>
+            void Add(T_ val, A_&& ...rest) {
+                storage.push_back(val);
+                
+                Add(std::forward<A_>(rest)...);
+            }
+            
+            //insert, remove, move
+            
+            /**
+             * @name Iteration 
+             * 
+             * These functions allow iteration of the listbox. If 
+             * the contents are changed through these functions, 
+             * you must call Refresh manually.
+             * 
+             * @{
+             */
+            auto begin() {
+                return storage.begin();
+            }
+            
+            auto begin() const {
+                return storage.begin();
+            }
+            
+            auto end() {
+                return storage.end();
+            }
+            
+            auto end() const {
+                return storage.end();
+            }
+            
+            /// @}
         
-        template<class S_>
-        typename std::enable_if<TMP::FunctionTraits<decltype(&S_::GetCount)>::IsMember, long>::type
-        getsize(const S_ &storage) {
-            return storage.GetCount();
-        }
+        protected:
+            LBSTR_STLVector() {}
+            virtual ~LBSTR_STLVector() {}
+            
+            long getsize() const {
+                return storage.size();
+            }
+            
+            T_ &getelm(long index) {
+                return storage[index];
+            }
+            
+            const T_ &getelm(long index) const {
+                return storage[index];
+            }
+            
+            Storage storage;
+        };
     }
     /// @endcond
     
@@ -385,8 +490,6 @@
      * 
      * T_ is the stored data type. 
      * 
-     * S_ is the storage for T_.
-     * 
      * W_ is the widget that will be used to represent items.
      * 
      * TR_ is widget traits class that allows additional properties for each
@@ -416,6 +519,15 @@
      * as ListboxBase will be derived from TRF_. Finally, TRF_ should have a 
      * protected constructor/destructor.
      * 
+     * STR_ is the storage traits for T_. This class should contain typedef
+     * Storage which is the storage. It should have functions that allows it
+     * to handle Add/Remove/Insert/Move/getsize/getelm functions. Only 
+     * getsize and getelm functions are mandatory. getelm should take a long
+     * index and should return the stored value. GetSize should return long.
+     * Additionally, this function should have a protected storage member
+     * named storage. After every modifying operation, this function should
+     * call Refresh. Ideally, this class should contain 
+     * 
      * useisvisible controls if elements can be hidden. If this is true, TR_
      * should have IsVisible function returning bool. This parameter will
      * slowdown listbox considerably when many items are stored as each item
@@ -428,7 +540,8 @@
      * is set to internal::LBSELTR_None.
      * This class should support click and toggle functions both taking long 
      * index, const T_ & value, W_ &widget. Click function will be called when
-     * the user uses arrow keys to select an item.
+     * the user uses arrow keys to select an item. It is this classes
+     * responsibility to handle actual click and toggle functions.
      * apply function should apply selection related traits to the widget taking
      * long index, W_ &widget, const T_ & value. Any item that is benched will
      * be applied to as well with an index of -1.
@@ -446,35 +559,42 @@
      * Index parameters should be long int. These functions should be protected
      * as ListboxBase will be derived from SELTR_. Finally, SELTR_ should have a 
      * protected constructor/destructor.
+     * reapplyfocus function should apply the focus to the focused element. This
+     * function is called after listbox receives focus.
      * 
      * TW_ function should take a T_ and set this to its W_ representation. 
      * 
      * WT_ should read the data from W_ and set it to T_.
      */
     template<
-        class T_, class S_, class W_, class TR_, class TRF_, 
-        bool useisvisible = false, class SELTR_ = internal::LBSELTR_Single<T_, W_>,
+        class T_, class W_, class TR_, class TRF_, 
+        class STR_, class SELTR_, 
+        bool useisvisible = false,
         void (*TW_)(const T_ &, W_ &) = internal::SetTextUsingFrom<T_, W_>,
         void (*WT_)(W_ &, T_ &)       = internal::GetTextUsingTo  <T_, W_>
     >
-    class ListboxBase : public UI::ComponentStackWidget, public ListBase<T_, W_>, public TRF_, public SELTR_ {
+    class ListboxBase : public UI::ComponentStackWidget, 
+                        public ListBase<T_, W_>, 
+                        public TRF_, 
+                        public SELTR_, public STR_ 
+    {
     public:
         
         /// Returns the item at the given point. This operator will not perform
         /// bounds checking.
         virtual T_ &operator[](long index) override {
-            return storage[index];
+            return this->getelm(index);
         }
 
         /// Returns the item at the given point. This operator will not perform
         /// bounds checking.
         virtual const T_ &operator[](long index) const override {
-            return storage[index];
+            return this->getelm(index);
         }
         
         /// Returns the number of elements in the list.
         virtual long GetCount() const override {
-            return internal::getsize(storage);
+            return this->STR_::getsize();
         }
         
         /// For internal use.
@@ -483,7 +603,7 @@
         /// visual representation. This is not an edge case, any item that is not
         /// in view will most likely not have a representation.
         virtual W_ *getrepresentation(long index) override {
-            return nullptr;
+            return widgetlist.count(index) ? widgetlist[index] : nullptr;
         }
         
         /// For internal use.
@@ -494,34 +614,156 @@
             return nullptr;
         }
         
-        auto begin() {
-            return storage.begin();
-        }
-        
-        auto begin() const {
-            return storage.begin();
+        virtual long getindex(const W_ &widget) override {
+            return indexes.count(&widget) ? indexes[&widget] : -1;
         }
         
-        auto end() {
-            return storage.end();
+        virtual void Refresh() override {
+            if(!contents.IsReady())
+                return;
+
+            auto elms = this->STR_::getsize();
+            
+            std::map<UI::ComponentTemplate::Tag, int> tagcounts;
+            
+            //remove all first
+            for(auto &p : widgetlist) {
+                p.second->Remove();
+            }
+            indexes.clear();
+            widgetlist.clear();
+            
+            auto b = stack.TagBounds(UI::ComponentTemplate::ViewPortTag);
+            if(b.Width() == 0 || b.Height() == 0)
+                b = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
+            
+            int y = 0;
+            long i = int(scrolloffset), c = 0;
+            int totalh = 0;
+            while(y < b.Height() && i < elms) {
+                auto &v   = this->getelm(i);
+                auto  tr  = this->access(i);
+                auto  tag = tr.Tag(v, {0, (int)i}, {1, (int)elms});
+                
+                auto w = getwidget(tag, tagcounts[tag]++);
+                
+                if(w == nullptr)
+                    return;
+
+                TW_(v, *w);
+                
+                contents.Add(*w);
+                tr.Apply(*w, v, {0, (int)i}, {1, (int)elms});
+                this->SELTR_::apply(i, *w, v);
+                
+                if(y == 0) {
+                    y = -int(std::round(w->GetHeight() * (scrolloffset - int(scrolloffset))));
+                }
+                
+                indexes.insert({w, i});
+                widgetlist.insert({i, w});
+                
+                w->Move(0, y);
+                
+                //to be moved to resize
+                w->SetWidth(b.Width());
+                auto advance = w->GetHeight() + stack.GetTemplate().GetSpacing() / 2;
+                y += advance;
+                totalh += advance;
+                i++;
+                c++;
+            }
+            
+            auto scroller = dynamic_cast<VScroller<float>*>(stack.GetWidget(UI::ComponentTemplate::VScrollTag));
+            if(scroller) {
+                scroller->SetMaximum(elms);
+                
+                if(totalh == 0)
+                    scroller->Range = 0;
+                else
+                    scroller->Range = b.Height() / (float(totalh) / c);
+            }
         }
         
-        auto end() const {
-            return storage.end();
-        }
         
     protected:
         ListboxBase(const UI::Template &temp) : 
-            ComponentStackWidget(temp)
+            ComponentStackWidget(temp, { 
+                { UI::ComponentTemplate::ItemTag   , {}},
+                { UI::ComponentTemplate::HeaderTag , {}},
+                { UI::ComponentTemplate::SpacerTag , {}},
+                { UI::ComponentTemplate::VScrollTag, 
+                    std::bind(&ListboxBase::createvscroll, this, std::placeholders::_1)
+                },
+            } )
         {
             stack.HandleMouse();
+            stack.SetClickEvent([&](auto, auto, auto) {
+                Focus();
+            });
+            contents.SetLayer(stack.GetLayerOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag)));
+            stack.AddCondition(UI::ComponentCondition::VScroll);
+        }
+        
+        ~ListboxBase() {
+            for(auto &p : widgets) {
+                p.second.Destroy();
+            }
         }
         
-        ~ListboxBase() { }
+        //this will return the widget with the tag and the order (not index). If the requested
+        //widget does not exists, it will be created
+        W_ *getwidget(UI::ComponentTemplate::Tag tag, int order) {
+            auto temp = stack.GetTemplate(tag);
+            
+            if(temp == nullptr)
+                return nullptr;
+            
+            auto &ws = widgets[tag];
+            
+            while(ws.GetSize() <= order) {
+                auto &w = ws.AddNew(*temp);
+                this->TRF_::prepare(w);
+                this->SELTR_::prepare(w);
+            }
+            
+            return &ws[order];
+        }
         
-        S_ storage;
+        virtual void focused() override {
+            ComponentStackWidget::focused();
+            this->reapplyfocus();
+        }
+
+        virtual void focuslost() override {
+            ComponentStackWidget::focuslost();
+            contents.RemoveFocus();
+        }
         
-        Containers::Collection<W_> widgets;
+        UI::Widget *createvscroll(const UI::Template &temp) {
+            auto vscroller = new VScroller<float>(temp);
+            vscroller->Maximum = this->STR_::getsize();
+            vscroller->Range   = 1;
+            *vscroller         = scrolloffset;
+            //vscroller->SetSmoothChangeSpeed(scrollspeed);
+            vscroller->ValueChanged.Register(*this, &ListboxBase::scrollto);
+            
+            return vscroller;
+        }
+        
+        void scrollto(float target) {
+            if(scrolloffset == target)
+                return;
+            
+            scrolloffset = target;
+            Refresh();
+        }
+        
+        std::map<UI::ComponentTemplate::Tag, Containers::Collection<W_>> widgets;
+        std::map<const W_*, long> indexes;
+        std::map<long, W_*> widgetlist;
+        UI::LayerAdapter contents;
+        float scrolloffset = 0.f;
     };
     
     /**
@@ -531,19 +773,27 @@
      */
     template<class T_>
     class SimpleListbox : 
-        public ListboxBase<T_, 
-            std::vector<T_>, ListItem, 
+        public ListboxBase<T_, ListItem, 
             internal::LBTR_blank <T_, ListItem>,
-            internal::LBTRF_blank<T_, ListItem>
+            internal::LBTRF_blank<T_, ListItem, SimpleListbox<T_>>,
+            internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, SimpleListbox<T_>>,
+            internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_>>
         >
     {
-        using Base = ListboxBase<T_, 
-            std::vector<T_>, ListItem, 
+        using Base = ListboxBase<T_, ListItem, 
             internal::LBTR_blank <T_, ListItem>,
-            internal::LBTRF_blank<T_, ListItem>
+            internal::LBTRF_blank<T_, ListItem, SimpleListbox<T_>>,
+            internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, SimpleListbox<T_>>,
+            internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_>>
         >;
+        
+        friend internal::LBTR_blank <T_, ListItem>;
+        friend internal::LBTRF_blank<T_, ListItem, SimpleListbox<T_>>;
+        friend internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, SimpleListbox<T_>>;
+        friend internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_>>;
+        
     public:
-        SimpleListbox() : Base(Registry::Active()[Registry::Checkbox_Regular]) {
+        explicit SimpleListbox(Registry::TemplateType temp = Registry::Listbox_Regular) : Base(Registry::Active()[temp]) {
         }
         
         virtual bool Activate() {
--- a/Source/Gorgon/Widgets/Panel.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Panel.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -79,6 +79,8 @@
         stack.AddCondition(UI::ComponentCondition::VScroll);
 
         SetSmoothScrollSpeed(scrollspeed);
+        
+        scrolldist = {temp.GetWidth()/4, temp.GetHeight()/4};
     }
 
     bool Panel::Activate() {
@@ -172,12 +174,12 @@
     void Panel::focused() {
         if(!HasFocusedWidget())
             FocusFirst();
-        WidgetBase::focused();
+        Widget::focused();
     }
     
     void Panel::focuslost() {
         RemoveFocus();
-        WidgetBase::focuslost();
+        Widget::focuslost();
     }
     
     Gorgon::Layer &Panel::getlayer() {
@@ -305,7 +307,7 @@
         return scrolloffset;
     }
     
-    void Panel::childboundschanged(WidgetBase *source) {
+    void Panel::childboundschanged(Widget *source) {
         WidgetContainer::childboundschanged(source);
         
         if(updaterequired)
@@ -407,7 +409,7 @@
             stack.SetValueTransitionSpeed({(float)value / s.Width, (float)value / s.Height, 0, 0});
     }
     
-    bool Panel::EnsureVisible(const UI::WidgetBase &widget) {
+    bool Panel::EnsureVisible(const UI::Widget &widget) {
         if(widgets.Find(widget) == widgets.end())
             return false;
         
@@ -462,7 +464,7 @@
         hscroll = horizontal;
     }
     
-    UI::WidgetBase* Panel::createvscroll(const UI::Template& temp) {
+    UI::Widget* Panel::createvscroll(const UI::Template& temp) {
         auto vscroller = new VScrollbar(temp);
         vscroller->Maximum = stack.TagBounds(UI::ComponentTemplate::ContentsTag).Height();
         vscroller->Range   = GetInteriorSize().Height;
@@ -473,7 +475,7 @@
         return vscroller;
     }
     
-    UI::WidgetBase* Panel::createhscroll(const UI::Template& temp) {
+    UI::Widget* Panel::createhscroll(const UI::Template& temp) {
         auto hscroller = new HScrollbar(temp);
         hscroller->Maximum = stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width();
         hscroller->Range   = GetInteriorSize().Width;
--- a/Source/Gorgon/Widgets/Panel.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Panel.h	Sun Oct 18 09:49:15 2020 +0300
@@ -18,9 +18,9 @@
         
         explicit Panel(Registry::TemplateType type = Registry::Panel_Regular) : Panel(Registry::Active()[type]) { }
 
-        using WidgetBase::Resize;
+        using Widget::Resize;
         
-        using WidgetBase::Remove;
+        using Widget::Remove;
         
         using WidgetContainer::Remove;
         
@@ -148,13 +148,13 @@
             return scrollspeed != 0;
         }
         
-        using WidgetBase::EnsureVisible;
+        using Widget::EnsureVisible;
         
-        bool EnsureVisible(const UI::WidgetBase &widget) override;
+        bool EnsureVisible(const UI::Widget &widget) override;
 
-        using WidgetBase::Enable;
-        using WidgetBase::Disable;
-        using WidgetBase::ToggleEnabled;
+        using Widget::Enable;
+        using Widget::Disable;
+        using Widget::ToggleEnabled;
 
         virtual void SetEnabled(bool value) override {
             if(value != IsEnabled()) {
@@ -178,7 +178,7 @@
         
         void focuschanged() override;
         
-        virtual void childboundschanged(WidgetBase *source) override;
+        virtual void childboundschanged(Widget *source) override;
         
         void updatecontent();
         
@@ -214,15 +214,15 @@
                 distributeparentenabled(state);
         }
         
-        virtual UI::WidgetBase *createvscroll(const UI::Template &temp);
+        virtual UI::Widget *createvscroll(const UI::Template &temp);
         
-        virtual UI::WidgetBase *createhscroll(const UI::Template &temp);
+        virtual UI::Widget *createhscroll(const UI::Template &temp);
         
         int overscroll = 0;
         bool scrollclipped = true;
         Geometry::Point scrolldist = {80, 45};
         Geometry::Point scrolloffset = {0, 0};
-        int scrollspeed = 250;
+        int scrollspeed = 500;
         Geometry::Point target = {0, 0};
         bool isscrolling = false;
         float scrollleftover = 0;
--- a/Source/Gorgon/Widgets/RadioButtons.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/RadioButtons.h	Sun Oct 18 09:49:15 2020 +0300
@@ -17,7 +17,7 @@
      * widget might cause unexpected behavior. All other container functionality should work as intended.
      */
     template<class T_, class W_ = Checkbox>
-    class RadioButtons : public UI::WidgetBase, protected UI::RadioControl<T_, W_>, public UI::WidgetContainer {
+    class RadioButtons : public UI::Widget, protected UI::RadioControl<T_, W_>, public UI::WidgetContainer {
         friend class UI::WidgetContainer;
     public:
         explicit RadioButtons(const UI::Template &temp) : temp(temp) { 
@@ -113,14 +113,14 @@
                 elm.Check();
         }
 
-        using WidgetBase::Enable;
+        using Widget::Enable;
 
         /// Enables the given element
         void Enable(const T_ &value) {
             SetEnabled(value, true);
         }
 
-        using WidgetBase::Disable;
+        using Widget::Disable;
 
 
         /// Disables the given element
@@ -128,7 +128,7 @@
             SetEnabled(value, false);
         }
 
-        using WidgetBase::ToggleEnabled;
+        using Widget::ToggleEnabled;
 
         /// Toggles enabled state of the given element
         void ToggleEnabled(const T_ &value) {
@@ -177,15 +177,15 @@
             return contents.IsVisible();
         }
         
-        bool EnsureVisible(const UI::WidgetBase &) override {
+        bool EnsureVisible(const UI::Widget &) override {
             return EnsureVisible();
         }
 
-        using WidgetBase::Resize;
+        using Widget::Resize;
 
-        using WidgetBase::Move;
+        using Widget::Move;
         
-        using WidgetBase::EnsureVisible;
+        using Widget::EnsureVisible;
         
         void Move(const Geometry::Point &location) override {
             contents.Move(location);
@@ -207,7 +207,7 @@
 
         using UI::RadioControl<T_, W_>::Set;
         
-        using WidgetBase::IsVisible;
+        using Widget::IsVisible;
 
         virtual void SetEnabled(bool value) override {
             if(enabled == value)
@@ -269,7 +269,7 @@
             if(!HasFocusedWidget())
                 FocusFirst();
             
-            WidgetBase::focused();
+            Widget::focused();
         }
         
         Gorgon::Layer &getlayer() override {
@@ -283,7 +283,7 @@
                 distributeparentenabled(state);
         }
         
-        virtual bool addingwidget(WidgetBase &widget) override { 
+        virtual bool addingwidget(Widget &widget) override { 
             for(auto p : this->elements) {
                 if(&p.second == &widget)
                     return true;
@@ -292,7 +292,7 @@
             return false;
         }
         
-        virtual bool removingwidget(WidgetBase &) override { return false; }
+        virtual bool removingwidget(Widget &) override { return false; }
         
         void rearrange() {
             int total = 0, col = 0;
@@ -342,7 +342,7 @@
         }
 
         virtual void focuslost() override {
-            WidgetBase::focuslost();
+            Widget::focuslost();
 
             if(HasFocusedWidget()) {
                 ForceRemoveFocus();
--- a/Source/Gorgon/Widgets/Scrollbar.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Scrollbar.h	Sun Oct 18 09:49:15 2020 +0300
@@ -38,7 +38,7 @@
         {
         }
 
-        explicit Scrollbar(const UI::Template &temp, T_ cur = T_{}) : Scrollbar(temp, cur, T_{temp.GetSpacing()*64}) { }
+        explicit Scrollbar(const UI::Template &temp, T_ cur = T_{}) : Scrollbar(temp, cur, T_(temp.GetSpacing()*64)) { }
 
         Scrollbar(const UI::Template &temp, T_ cur, T_ max) : 
             Base(temp, cur, max)
@@ -93,4 +93,10 @@
     using HScrollbar = Scrollbar<int, FloatDivider<int>, FloatToValue<int>, Gorgon::NumericProperty, Registry::Scrollbar_Horizontal>;
     using VScrollbar = Scrollbar<int, FloatDivider<int>, FloatToValue<int>, Gorgon::NumericProperty, Registry::Scrollbar_Vertical>;
     
+    template<class T_>
+    using HScroller = Scrollbar<T_, FloatDivider<T_>, FloatToValue<T_>, Gorgon::NumericProperty, Registry::Scrollbar_Horizontal>;
+
+    template<class T_>
+    using VScroller = Scrollbar<T_, FloatDivider<T_>, FloatToValue<T_>, Gorgon::NumericProperty, Registry::Scrollbar_Vertical>;
+    
 } }
--- a/Source/Gorgon/Widgets/Slider.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Source/Gorgon/Widgets/Slider.h	Sun Oct 18 09:49:15 2020 +0300
@@ -356,8 +356,11 @@
             auto v = DIV_(val, min, actualmax());
             if(v < 0)
                 val = min;
-            if(v > 1)
+            else if(v > 1)
                 val = actualmax();
+            else if(!(v <= 1)) { // in case of nan
+                val = 0;
+            }
             
             if(value != val) {
                 value = val;
--- a/Testing/Source/Manual/GraphicsHelper.h	Wed Oct 14 11:20:25 2020 +0300
+++ b/Testing/Source/Manual/GraphicsHelper.h	Sun Oct 18 09:49:15 2020 +0300
@@ -68,7 +68,7 @@
 #else
         bool found = false;
         std::streambuf *buf;
-        OS::Start("fc-match", buf, {"-v", "emoji"});
+        OS::Start("fc-match", buf, {"-v", "sans"});
         
         if(buf) {
             std::istream in(buf);
--- a/Testing/Source/Manual/UI_Generate.cpp	Wed Oct 14 11:20:25 2020 +0300
+++ b/Testing/Source/Manual/UI_Generate.cpp	Sun Oct 18 09:49:15 2020 +0300
@@ -126,7 +126,7 @@
     });
     //blank.CreateOrganizer<Gorgon::UI::Organizers::List>().SetSpacing(Gorgon::Widgets::Registry::Active().GetSpacing());
 
-    auto addme = [&](auto &pnl, UI::WidgetBase &w) {
+    auto addme = [&](auto &pnl, UI::Widget &w) {
         Geometry::Point offsetx = {Widgets::Registry::Active().GetSpacing(), 0};
         if(pnl.UI::WidgetContainer::begin() != pnl.UI::WidgetContainer::end()) {
             auto &last = *(pnl.UI::WidgetContainer::end() - 1);
@@ -163,12 +163,22 @@
     Gorgon::Widgets::Sizefbox sizef;
     sizef.ChangedEvent.Register([&] {
         std::cout << "size f changed " << sizef.GetText();
-
     });
+    
+    Widgets::SimpleListbox<std::string> list;
+    list.Add("5");
+    list.Add("Âj");
+    list.Add("9");
+    list.Add("Hello", "World", "You", "are", "welcome", "to", "use", "the", "Gorgon", "Library");
+    list.ChangedEvent.Register([&list]{
+        std::cout<<list.GetSelectedItem()<<std::endl;
+    });
+    
     app.wind.Add(blank);
     addme(blank, btn);
     addme(blank, icnbtn);
     addme(blank, icnbtn2);
+    addme(blank, list);
     addme(blank, icnbtn3);
     addme(blank, l);
     addme(blank, radio);
@@ -182,9 +192,6 @@
     addme(blank, scroll2);
     addme(blank, sizef);
     
-    Widgets::SimpleListbox<int> list;
-    list.SetSelectionFollowsFocus(false);
-
     
 
     /*Widgets::Progressor<std::string, StringDiv, StringVal, Gorgon::TextualProperty> bar2;

mercurial