* First iteration of inputbox nonworking

Sun, 10 Nov 2019 11:12:44 +0200

author
cemkalyoncu
date
Sun, 10 Nov 2019 11:12:44 +0200
branch
nonworking
changeset 1303
07c77f5bf056
parent 1302
4eff6d303c87
child 1307
bc885367b17d

* First iteration of inputbox

Source/Gorgon/Property.h file | annotate | diff | comparison | revisions
Source/Gorgon/UI/Validators.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/InputBox.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Inputbox.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/dir.cmake file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Property.h	Sun Nov 10 20:49:25 2019 +0200
+++ b/Source/Gorgon/Property.h	Sun Nov 10 11:12:44 2019 +0200
@@ -18,7 +18,7 @@
 	/// good for enums mostly, its ok to use with POD structs
 	/// for direct assignment but better not to use it with 
 	/// complex data types.
-	template<class C_, class T_, T_(C_::*Getter_)() const, void(C_::*Setter_)(const T_ &)>
+	template<class C_, class T_, T_(C_::*Getter_)() const = &C_::get, void(C_::*Setter_)(const T_ &) = &C_::set>
 	class Property {
 	public:
 		using Type = T_;
--- a/Source/Gorgon/UI/Validators.h	Sun Nov 10 20:49:25 2019 +0200
+++ b/Source/Gorgon/UI/Validators.h	Sun Nov 10 11:12:44 2019 +0200
@@ -9,7 +9,32 @@
      * 
      * @page validators Validation
      * 
-     * TODO
+     * Validation in Gorgon UI is done over validator classes. These classes should have the
+     * following members:
+     * 
+     * * Type: a type declaration of the type that is managed.
+     * 
+     * * bool IsValid(std::string): returns true if the given string is a valid value for the type
+     * 
+     * * bool AllowInsert(std::string start, std::string insert, std::string end): this function
+     * is used when typing or pasting into the editor. If the `insert` is a valid string to place
+     * between `start` and `end` this function should return true. The result of this function is
+     * not IsValid(start + insert + end) as in this case, a partially correct data should be allowed.
+     * Otherwise, it might be impossible to enter input. For instance, for Geometry::Point, entering
+     * 5 when the inputbox is empty should be allowed, even though 5 is not a valid point.
+     * 
+     * * bool AllowErase(std::string before, int count, std::string after): this function is used 
+     * check if it is possible to erase `count` characters from `before`. The text after the deletion
+     * point is given in `after`. Having strong rules could cause difficulty in editing the data,
+     * thus extensive use of this function is not recommended.
+     * 
+     * * Type From(std::string text): Converts the given text in to type. This function should not
+     * throw even if the input is not valid. In this case it should return initial value for the
+     * Type.
+     * 
+     * * std::string ToString(const Type &value): Converts the given value into a string. Input
+     * validation requires a proper serialization as input systems may call ToString(From(text)) to
+     * fix the text. It is advisable to have unit tests ensuring correct serialization.
      * 
      */
     
@@ -19,6 +44,7 @@
     template<class T_>
     class EmptyValidator {
     public:
+        using Type = T_;
         
         /// Checks if the given string is valid
         bool IsValid(std::string) const {
@@ -41,12 +67,12 @@
         }
         
         /// Converts the given string to the type. If input is not valid, return initial value
-        T_ From(std::string text) const {
-            return String::To<T_>(text);
+        Type From(std::string text) const {
+            return String::To<Type>(text);
         }
         
         /// Converts the given value to string.
-        std::string ToString(const T_ &value) {
+        std::string ToString(const Type &value) const {
             return String::From(value);
         }
         
--- a/Source/Gorgon/Widgets/InputBox.h	Sun Nov 10 20:49:25 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#pragma once
-
-#include <functional>
-#include <string>
-
-#include "../Event.h"
-#include "../UI/Validators.h"
-#include "../UI/ComponentStackWidget.h"
-
-namespace Gorgon { namespace Widgets {
-    
-    /**
-     * This class allows users to enter any value to an inputbox. This
-     * class is specialized as Textbox and Numberbox. It is possible to
-     * supply a validator to a specific inputbox. Inputbox is designed
-     * for value objects that can be copied.
-     */
-    template<class T_, class V_ = UI::EmptyValidator<T_>>
-    class Inputbox : public UI::ComponentStackWidget {
-    public:
-        
-        /// Initializes the inputbox
-        explicit Inputbox(const UI::Template &temp, T_ value = T_()) : 
-            ComponentStackWidget(temp), value(value), display(validator.ToString(value))
-        {
-            stack.SetData(UI::ComponentTemplate::Text);
-        }
-        
-        /// Initializes the inputbox
-        explicit Inputbox(const UI::Template &temp, std::function<void()> changedevent) : Inputbox(temp) {
-            ChangedEvent.Register(changedevent);
-        }
-        
-        /// Initializes the inputbox
-        explicit Inputbox(const UI::Template &temp, T_ value, std::function<void()> changedevent) : Inputbox(temp, value)
-        {
-            ChangedEvent.Register(changedevent);
-        }
-        
-        
-        /// Returns the value in the box.
-        operator T_() const {
-            return value;
-        }
-        
-        /// Fired after the value of the inputbox is changed. Parameter is the previous 
-        /// value before the change. If the user is typing, this event will be fired
-        /// after typing stops for a set amount of time. ChangedEvent will be fired
-        /// immediately when a value is pasted to the box.
-        Event<Inputbox, const T_ &> ChangedEvent = Event<Inputbox>{this};
-        
-    private:
-        V_ validator;
-        T_ value;
-        std::string display;
-        
-        int selstart = 0;
-        int sellen   = 0;
-    };
-    
-} }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Gorgon/Widgets/Inputbox.h	Sun Nov 10 11:12:44 2019 +0200
@@ -0,0 +1,195 @@
+#pragma once
+
+#include <functional>
+#include <string>
+
+#include "../Event.h"
+#include "../Property.h"
+#include "../UI/Validators.h"
+#include "../UI/ComponentStackWidget.h"
+
+namespace Gorgon { namespace Widgets {
+    
+    /// @cond internal
+    namespace internal {
+        template<class I_, class T_>
+        struct prophelper {
+            virtual ~prophelper() { 
+                
+            }
+            
+            void set_(const T_&v) {
+                static_cast<I_*>(this)->set(v);
+            }
+            T_ get_() const {
+                return static_cast<const I_*>(this)->get();
+            }
+        };
+    }
+    /// @endcond
+    
+    /**
+     * This class allows users to enter any value to an inputbox. This
+     * class is specialized as Textbox and Numberbox. It is possible to
+     * supply a validator to a specific inputbox. Inputbox is designed
+     * for value objects that can be copied and serialized to string.
+     */
+    template<class T_, class V_ = UI::EmptyValidator<T_>, template<class C_, class PT_, PT_(C_::*Getter_)() const, void(C_::*Setter_)(const PT_ &)> class P_ = Gorgon::Property>
+    class Inputbox : 
+        public UI::ComponentStackWidget, 
+        private internal::prophelper<Inputbox<T_, V_, P_>, T_>, 
+        public P_<internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_> {
+    public:
+        friend struct internal::prophelper<Inputbox, T_>;
+        
+        using Type     = T_;
+        using PropType = P_<internal::prophelper<Inputbox<T_, V_, P_>, T_>, T_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::get_, &internal::prophelper<Inputbox<T_, V_, P_>, T_>::set_>;
+        
+        /// Initializes the inputbox
+        explicit Inputbox(const UI::Template &temp, T_ value = T_()) : 
+        ComponentStackWidget(temp), PropType(this), value(value), display(validator.ToString(value))
+        {
+            updatevalue();
+            updateselection();
+        }
+        
+        /// Initializes the inputbox
+        explicit Inputbox(const UI::Template &temp, std::function<void()> changedevent) : Inputbox(temp) {
+            ChangedEvent.Register(changedevent);
+        }
+        
+        /// Initializes the inputbox
+        explicit Inputbox(const UI::Template &temp, T_ value, std::function<void()> changedevent) : Inputbox(temp, value)
+        {
+            ChangedEvent.Register(changedevent);
+        }
+        
+        /// Assignment to the value type
+        Inputbox &operator =(const T_ value) {
+            set(value);
+            
+            return *this;
+        }
+        
+        /// Copy assignment will only copy the value
+        Inputbox &operator =(const Inputbox &value) {
+            set(value.Get());
+            
+            return *this;
+        }
+        
+        
+        /// Returns the value in the box.
+        operator T_() const {
+            return value;
+        }
+        
+        /// Returns the length of the text in this inputbox
+        int Length() const {
+            return display.length();
+        }
+        
+        /// Returns the current text in the inputbox. Use Get() to obtain the value of
+        /// the inputbox, this function exists for special uses.
+        std::string GetText() const {
+            return display;
+        }
+        
+        /// @name Selection
+        /// @{
+        
+        /// Selects the entire contents of this inputbox
+        void SelectAll() {
+            selstart = 0;
+            sellen   = -1;
+            updateselection();
+        }
+        
+        /// Removes any selection, does not move the start of the
+        /// cursor.
+        void SelectNone() {
+            sellen = 0;
+            updateselection();
+        }
+        
+        /// Returns the start of the selection in characters.
+        int SelectionStart() const {
+            return selstart;
+        }
+        
+        /// Returns the length of the selection in characters. Selection length could be 
+        /// negative denoting the selection is backwards.
+        int SelectionLength() const {
+            return sellen;
+        }
+        
+        /// Returns the location of the caret. It is always at the end of the selection
+        int CaretLocation() const {
+            return selstart + sellen;
+        }
+        
+        /// @}
+        
+        bool Activate() override {
+            return Focus();
+        }
+        
+        /// 
+        bool CharacterEvent(Gorgon::Char c) override  {
+            display.push_back(c);
+            
+            value = validator.From(display);
+            updatevalue(false);
+            
+            return true;
+        }
+        
+        /// Fired after the value of the inputbox is changed. Parameter is the previous 
+        /// value before the change. If the user is typing, this event will be fired
+        /// after typing stops for a set amount of time. ChangedEvent will be fired
+        /// immediately when a value is pasted to the box.
+        Event<Inputbox, const T_ &> ChangedEvent = Event<Inputbox, const T_ &>{this};
+        
+        
+    protected:
+        
+        /// updates the selection display
+        void updateselection() {
+            
+        }
+        
+        /// updates the value display
+        void updatevalue(bool updatedisplay = true) {
+            if(updatedisplay)
+                display = validator.ToString(value);
+            
+            stack.SetData(UI::ComponentTemplate::Text, display);
+        }
+        
+        /// Returns the value in the box
+        T_ get() const {
+            return value;
+        }
+        
+        /// Changes the value in the box
+        void set(const T_ &val) {
+            if(value == val)
+                return;
+            
+            value = val;
+            
+            updatevalue();
+            updateselection();
+        }
+        
+        
+    private:
+        V_ validator;
+        T_ value;
+        std::string display;
+        
+        int selstart = 0;
+        int sellen   = 0;
+    };
+    
+} }
--- a/Source/Gorgon/Widgets/dir.cmake	Sun Nov 10 20:49:25 2019 +0200
+++ b/Source/Gorgon/Widgets/dir.cmake	Sun Nov 10 11:12:44 2019 +0200
@@ -8,7 +8,7 @@
 	Generator.h
 	Generator.cpp
 	
-	InputBox.h
+	Inputbox.h
 	
 	Label.h
 	Label.cpp
--- a/Testing/Source/Manual/UI_Generate.cpp	Sun Nov 10 20:49:25 2019 +0200
+++ b/Testing/Source/Manual/UI_Generate.cpp	Sun Nov 10 11:12:44 2019 +0200
@@ -8,6 +8,7 @@
 #include <Gorgon/Widgets/RadioButtons.h>
 #include <Gorgon/Widgets/Label.h>
 #include <Gorgon/Widgets/Panel.h>
+#include <Gorgon/Widgets/Inputbox.h>
 #include <Gorgon/UI/RadioControl.h>
 #include <Gorgon/UI/Organizers/List.h>
 #include <Gorgon/Graphics/BlankImage.h>
@@ -155,6 +156,10 @@
     Widgets::Label lbl(lbltemp, "This is a label");
     Widgets::Label error(errortemp, "This is an Error label");
     
+    Widgets::Inputbox<int, UI::EmptyValidator<int>, NumericProperty> inp(lbltemp);
+    inp++;
+    sub.Add(inp);
+    
     pnl.Add(lbl);
     pnl.Add(error);
     

mercurial