#139: Collectionbox 4.x-dev

Sun, 01 Nov 2020 12:12:40 +0200

author
cemkalyoncu
date
Sun, 01 Nov 2020 12:12:40 +0200
branch
4.x-dev
changeset 1477
06d418851b00
parent 1476
e9317f02166d
child 1478
77a352b45f0c

#139: Collectionbox

Source/Gorgon/Containers/Collection.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/ListItem.cpp 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
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Containers/Collection.h	Sat Oct 31 16:15:47 2020 +0200
+++ b/Source/Gorgon/Containers/Collection.h	Sun Nov 01 12:12:40 2020 +0200
@@ -243,25 +243,34 @@
 			}
 
 
-			/// Adds the given item to the end of the list
-			void Add(T_* Data) {
-				if(std::find(list.begin(), list.end(), Data)==list.end())
+			/// Adds the given item to the end of the list if it is not
+			/// already in the list
+			bool Add(T_* Data) {
+				if(std::find(list.begin(), list.end(), Data)==list.end()) {
 					list.push_back(Data);
+                    
+                    return true;
+                }
+                
+                return false;
 			}
 
-			/// Adds a the given item to the end of the list
-			void Add(T_& data) {
-				Add(&data);
+			/// Adds a the given item to the end of the list if it is not
+			/// already in the list
+			bool Add(T_& data) {
+				return Add(&data);
 			}
 
-			/// Adds the given item to the end of the list
-			void Push(T_* Data) {
-				Add(Data);
+			/// Adds the given item to the end of the list if it is not
+			/// already in the list
+			bool Push(T_* Data) {
+				return Add(Data);
 			}
 
-			/// Adds a the given item to the end of the list
-			void Push(T_& data) {
-				Add(data);
+			/// Adds a the given item to the end of the list if it is not
+			/// already in the list
+			bool Push(T_& data) {
+				return Add(data);
 			}
 			
 			/// Removes and returns the last item in the collection
@@ -276,18 +285,23 @@
 				return ret;
 			}
 
-			/// Adds the given item to the end of the list
+			/// Adds the given item to the end of the list, returns the number
+			/// of added elements
 			template<typename... Args_>
-			void Add(T_* Data, Args_ *... args) {
-				Add(Data);
-				Add(args...);
+			int Add(T_* Data, Args_ *... args) {
+				int ret = Add(Data) ? 1 : 0;
+				ret += Add(args...);
+                
+                return ret;
 			}
 
 			/// Adds a the given item to the end of the list
 			template<typename... Args_>
-			void Add(T_& data, Args_ &... args) {
-				Add(&data);
-				Add(args...);
+			int Add(T_& data, Args_ &... args) {
+				int ret = Add(&data) ? 1 : 0;
+				ret += Add(args...);
+                
+                return ret;
 			}
 
 			/// Creates a new item and adds to the end of the collection
@@ -301,15 +315,17 @@
 
 			/// this method adds the given object in front of the reference. You may use the size of the collection
 			/// for this function to behave like Add.
-			void Insert(T_* data, long before) {
-				if(std::find(list.begin(), list.end(), data)!=list.end()) return;
+			bool Insert(T_* data, long before) {
+				if(std::find(list.begin(), list.end(), data)!=list.end()) return false;
+                
+                if(before==-1)
+                    before=(long)list.size();
 
 				if(before<0 || before>(long)list.size())
 					throw std::out_of_range("Invalid location");
 
 				if(before==list.size()) {
-					Add(data);
-					return;
+					return Add(data);
 				}
 
 				list.resize(list.size()+1);
@@ -318,24 +334,26 @@
 					list[i]=list[i-1];
 
 				list[before]=data;
+                
+                return true;
 			}
 
 			/// this method adds the given object in front of the reference. You may use the size of the collection
 			/// for this function to behave like Add.
-			void Insert(T_& data, unsigned before) {
-				Insert(&data, before);
+			bool Insert(T_& data, long before) {
+				return Insert(&data, before);
 			}
 
 			/// this method adds the given object in front of the reference. You may use the size of the collection
 			/// for this function to behave like Add.
-			void Insert(T_* data, const T_ &before) {
-				Insert(data, FindLocation(before));
+			bool Insert(T_* data, const T_ &before) {
+				return Insert(data, FindLocation(before));
 			}
 
 			/// this method adds the given object in front of the reference. You may use the size of the collection
 			/// for this function to behave like Add.
-			void Insert(T_& data, const T_ &before) {
-				Insert(&data, FindLocation(before));
+			bool Insert(T_& data, const T_ &before) {
+				return Insert(&data, FindLocation(before));
 			}
 
 			/// Creates a new item and inserts it before the given reference. You may use the size of the collection
--- a/Source/Gorgon/Widgets/ListItem.cpp	Sat Oct 31 16:15:47 2020 +0200
+++ b/Source/Gorgon/Widgets/ListItem.cpp	Sun Nov 01 12:12:40 2020 +0200
@@ -3,6 +3,24 @@
 
 namespace Gorgon { namespace Widgets {
         
+    ListItem::ListItem(const UI::Template& temp) :
+        UI::ComponentStackWidget(temp) 
+    {
+        stack.HandleMouse();
+        stack.SetClickEvent([&](auto tag, auto location, auto) {
+            if(tag == UI::ComponentTemplate::NoTag) {
+                auto ind = stack.ComponentAt(location);
+                if(ind != -1) 
+                    tag = stack.GetTemplate(ind).GetTag();
+            }
+            
+            ClickEvent();
+            
+            if(tag == UI::ComponentTemplate::ToggleTag || stack.IndexOfTag(UI::ComponentTemplate::ToggleTag) == -1)
+                ToggleEvent();
+        });
+    }
+
     void ListItem::SetText(const std::string& value) {
         text = value;
         stack.SetData(UI::ComponentTemplate::Text, value);
@@ -190,4 +208,5 @@
     }
     
 
+
 } }
--- a/Source/Gorgon/Widgets/ListItem.h	Sat Oct 31 16:15:47 2020 +0200
+++ b/Source/Gorgon/Widgets/ListItem.h	Sun Nov 01 12:12:40 2020 +0200
@@ -34,15 +34,7 @@
     public:
 
         /// Constructor requires template. ListItem
-        ListItem(const UI::Template &temp) :
-            UI::ComponentStackWidget(temp)
-        {
-            stack.HandleMouse(); 
-            stack.SetClickEvent([&](auto, auto, auto) {
-                ClickEvent();
-                ToggleEvent();
-            });
-        }
+        ListItem(const UI::Template &temp);
 
         /// Changes the text displayed. Depending on the template, text might be
         /// overwritten by icon.
--- a/Source/Gorgon/Widgets/Listbox.h	Sat Oct 31 16:15:47 2020 +0200
+++ b/Source/Gorgon/Widgets/Listbox.h	Sun Nov 01 12:12:40 2020 +0200
@@ -1035,12 +1035,14 @@
         public:
             using Storage = S_;
             
+            /// Adds the given item to the listbox
             void Add(T_ val) {
                 storage.push_back(val);
                 
                 dynamic_cast<F_*>(this)->Refresh();
             }
             
+            /// Adds the given items to the listbox
             template<class... A_>
             void Add(T_ val, A_&& ...rest) {
                 storage.push_back(val);
@@ -1048,15 +1050,31 @@
                 Add(std::forward<A_>(rest)...);
             }
             
+            /// Inserts the given item before the given location. You may use
+            /// Find to find the location of a specific item. If location is
+            /// -1, then item is added at the end.
             void Insert(long before, T_ val) {
+                if(before == -1) {
+                    Add(val);
+                    return;
+                }
+                
                 storage.insert(storage.begin()+before, val);
                 
                 dynamic_cast<F_*>(this)->sel_insert(before, 1);
                 dynamic_cast<F_*>(this)->Refresh();
             }
             
+            /// Inserts the given items before the given location. You may use
+            /// Find to find the location of a specific item. If location is
+            /// -1, then items are added at the end.
             template<class... A_>
             void Insert(long before, T_ val, A_&& ...rest) {
+                if(before == -1) {
+                    Add(val, rest...);
+                    return;
+                }
+                
                 //TODO optimize
                 Insert(std::forward<A_>(rest)...);
                 
@@ -1064,6 +1082,7 @@
                 dynamic_cast<F_*>(this)->sel_insert(before, 1);
             }
             
+            /// Removes the item at the given index.
             void Remove(long index) {
                 storage.erase(storage.begin()+index);
                 
@@ -1071,18 +1090,14 @@
                 dynamic_cast<F_*>(this)->Refresh();
             }
             
+            /// Moves the item at the given index before the given location.
+            /// If before is -1 or equal or larger than the number of items, 
+            /// then the item is moved to the end.
             void MoveBefore(long index, long before) {
                 if(index==before)
                     return;
 
-                if(index>before) {
-                    auto t = storage[index];
-                    for(unsigned i=index; i>before; i--)
-                        storage[i] = storage[i-1];
-
-                    storage[before]=t;
-                }
-                else if(before==storage.size()) {
+                if(before >= storage.size() || before == -1) {
                     auto t = storage[index];
 
                     for(unsigned i=index; i<storage.size()-1; i++)
@@ -1090,6 +1105,13 @@
 
                     storage[storage.size()-1] = t;
                 }
+                else if(index>before) {
+                    auto t = storage[index];
+                    for(unsigned i=index; i>before; i--)
+                        storage[i] = storage[i-1];
+
+                    storage[before]=t;
+                }
                 else {
                     auto t = storage[index];
                     for(unsigned i=index; i<before; i++)
@@ -1112,6 +1134,11 @@
                     return it-storage.begin();
             }
             
+            /// Allocates memory for the given amount of items
+            void Reserve(long amount) {
+                storage.reserve(amount);
+            }
+            
             /**
              * @name Iteration 
              * 
@@ -1157,6 +1184,186 @@
             
             Storage storage;
         };
+        
+        template<class T_, class W_, class F_>
+        class LBSTR_Collection {
+        public:
+            using Storage = Containers::Collection<T_>;
+            
+            /// Adds the given item to the list 
+            void Add(T_ &val) {
+                storage.Push(val);
+                
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            template<class... A_>
+            T_ &AddNew(A_&& ...args) {
+                auto &t = storage.AddNew(args...);
+                
+                dynamic_cast<F_*>(this)->Refresh();
+                
+                return t;
+            }
+            
+            template<class... A_>
+            void Add(T_ &val, A_& ...rest) {
+                storage.Push(val);
+                
+                Add(std::forward<A_>(rest)...);
+            }
+            
+            void Insert(long before, T_ &val) {
+                if(storage.Insert(before, val)) {
+                    dynamic_cast<F_*>(this)->sel_insert(before, 1);
+                    dynamic_cast<F_*>(this)->Refresh();
+                }
+            }
+            
+            void Insert(const T_ &before, T_ &val) {
+                Insert(FindLocation(before), val);
+            }
+            
+            template<class... A_>
+            T_ &InsertNew(const T_ &before, A_&& ...args) {
+                auto &t = storage.InsertNew(FindLocation(before), args...);
+                
+                dynamic_cast<F_*>(this)->sel_insert(before, 1);
+                dynamic_cast<F_*>(this)->Refresh();
+                
+                return t;
+            }
+            
+            void Remove(long index) {
+                storage.Remove(index);
+                
+                dynamic_cast<F_*>(this)->sel_remove(index, 1);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            void Remove(const T_ &item) {
+                long index = storage.FindLocation(item);
+                if(index == -1)
+                    return;
+                
+                storage.Remove(index);
+                
+                dynamic_cast<F_*>(this)->sel_remove(index, 1);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            /// Deletes an item from the listbox. Deleting both removes the item from the list and 
+            /// free the item itself. If given item does not exists, this function deletes the item
+            /// and does nothing else
+            void Delete(const T_ &item) {
+                long index = storage.FindLocation(item);
+                if(index == -1) {
+                    delete &item;
+                    
+                    return;
+                }
+                
+                storage.Delete(index);
+                
+                dynamic_cast<F_*>(this)->sel_remove(index, 1);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            /// Deletes the item with the given index
+            void Delete(long index) {
+                storage.Delete(index);
+                
+                dynamic_cast<F_*>(this)->sel_remove(index, 1);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            void MoveBefore(long index, long before) {
+                if(index==before)
+                    return;
+                
+                storage.MoveBefore(index, before);
+                
+                dynamic_cast<F_*>(this)->sel_move(index, before);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            /// Return the location of the given item.
+            /// Returns -1 if item not found.
+            long Find(const T_ &item) {
+                return storage.FindLocation(item);
+            }
+            
+            /// Deletes and removes all elements in the listbox
+            void DeleteAll() {
+                auto s = storage.GetSize();
+                
+                storage.DeleteAll();
+                
+                dynamic_cast<F_*>(this)->sel_remove(0, s);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            /// Deletes and removes all elements in the listbox. This function
+            /// also clears the memory associated with the storage.
+            void Destroy() {
+                auto s = storage.GetSize();
+                
+                storage.Destroy();
+                
+                dynamic_cast<F_*>(this)->sel_remove(0, s);
+                dynamic_cast<F_*>(this)->Refresh();
+            }
+            
+            /// Allocates memory for the given amount of items
+            void Reserve(long amount) {
+                storage.Reserve(amount);
+            }
+            
+            /**
+             * @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();
+            }
+            
+            /// @}
+        
+        protected:
+            LBSTR_Collection() {}
+            virtual ~LBSTR_Collection() {}
+            
+            long getsize() const {
+                return storage.GetSize();
+            }
+            
+            T_ &getelm(long index) {
+                return storage[index];
+            }
+            
+            const T_ &getelm(long index) const {
+                return storage[index];
+            }
+            
+            Storage storage;
+        };
     }
     /// @endcond
     
@@ -1250,6 +1457,8 @@
      * protected constructor/destructor.
      * reapplyfocus function should apply the focus to the focused element. This
      * function is called after listbox receives focus.
+     * GetFocusIndex and SetFocusIndex functions should exist to handle focus
+     * changes through keyboard keys.
      * 
      * TW_ function should take a T_ and set this to its W_ representation. 
      * 
@@ -1804,5 +2013,98 @@
         using internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, MultiListbox<T_>>::Remove;
     };
     
+    /**
+     * This is a simple collectionbox. It does not store any additional information
+     * about each item, therefore, can store large amounts of items. Items are
+     * stored in a Containers::Collection. Only one element can be selected at a time.
+     */
+    template<class T_>
+    class SimpleCollectionbox : 
+        public ListboxBase<T_, ListItem, 
+            internal::LBTR_blank <T_, ListItem>,
+            internal::LBTRF_blank<T_, ListItem, SimpleCollectionbox<T_>>,
+            internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_>>,
+            internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_>>
+        >
+    {
+        using Base = ListboxBase<T_, ListItem, 
+            internal::LBTR_blank <T_, ListItem>,
+            internal::LBTRF_blank<T_, ListItem, SimpleCollectionbox<T_>>,
+            internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_>>,
+            internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_>>
+        >;
+        
+        friend internal::LBTR_blank <T_, ListItem>;
+        friend internal::LBTRF_blank<T_, ListItem, SimpleCollectionbox<T_>>;
+        friend internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_>>;
+        friend internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_>>;
+        
+    public:
+        explicit SimpleCollectionbox(Registry::TemplateType temp = Registry::Listbox_Regular) : Base(Registry::Active()[temp]) {
+        }
+        
+        virtual bool Activate() {
+            return false;
+        }
+        
+        SimpleCollectionbox &operator =(const T_ value) {
+            this->SetSelection(value);
+            
+            return *this;
+        }
+        
+        using Base::ComponentStackWidget::Widget::Remove;
+        using internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_>>::Remove;
+    };
+    
+    /**
+     * This is a simple multi select collectionbox. It does not store any additional 
+     * information about each item, therefore, can store large amounts of items.
+     * However, default event strategy is triggering the event for every selected
+     * and unselected item. This might cause problems if the list is too long. 
+     * When the event method is set to single, only one event will be called for
+     * single action. Items are stored in Containers::Collection. You may use Selection
+     * and SelectedIndices to iterate selected elements. In both members, selection
+     * is always sorted by the position in the collectionbox.
+     */
+    template<class T_>
+    class MultiCollectionbox : 
+        public ListboxBase<T_, ListItem, 
+            internal::LBTR_blank <T_, ListItem>,
+            internal::LBTRF_blank<T_, ListItem, MultiCollectionbox<T_>>,
+            internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_>>,
+            internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_>>
+        >
+    {
+        using Base = ListboxBase<T_, ListItem, 
+            internal::LBTR_blank <T_, ListItem>,
+            internal::LBTRF_blank<T_, ListItem, MultiCollectionbox<T_>>,
+            internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_>>,
+            internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_>>
+        >;
+        
+        friend internal::LBTR_blank <T_, ListItem>;
+        friend internal::LBTRF_blank<T_, ListItem, MultiCollectionbox<T_>>;
+        friend internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_>>;
+        friend internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_>>;
+        
+    public:
+        explicit MultiCollectionbox(Registry::TemplateType temp = Registry::Listbox_Regular) : Base(Registry::Active()[temp]) {
+        }
+        
+        virtual bool Activate() {
+            return false;
+        }
+        
+        MultiCollectionbox &operator =(const T_ value) {
+            this->SetSelection(value);
+            
+            return *this;
+        }
+        
+        using Base::ComponentStackWidget::Widget::Remove;
+        using internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_>>::Remove;
+    };
+    
 } }
 
--- a/Testing/Source/Manual/UI_Generate.cpp	Sat Oct 31 16:15:47 2020 +0200
+++ b/Testing/Source/Manual/UI_Generate.cpp	Sun Nov 01 12:12:40 2020 +0200
@@ -165,28 +165,28 @@
         std::cout << "size f changed " << sizef.GetText();
     });
     
-    Widgets::SimpleListbox<std::string> list;
-    /*list.SetSelectionMethod(list.UseCtrl);
-    list.SetEventMethod(list.Once);*/
-    list.SetSelectionFollowsFocus(false);
-    list.Add("5");
-    list.Add("Âj");
-    list.Add("9");
-    list.Add("Hello", "World", "You", "are", "welcome", "to", "use", "the", "Gorgon", "Library");
+    Widgets::MultiCollectionbox<std::string> list;
+    //list.SetSelectionMethod(list.UseCtrl);
+    list.SetEventMethod(list.Once);
+    //list.SetSelectionFollowsFocus(false);
+    list.AddNew("5");
+    list.AddNew("Âj");
+    list.AddNew("9");
+    list.AddNew("Hello");
+    auto &item = *new std::string("World");
+    list.Add(item);
     //list.AddToSelection(3);
     //list.AddToSelection(1, 4);
-    list.Insert(2, "!");
-    list.Remove(2);
-    list.MoveBefore(2, 5);
-    list.SetOverscroll(2);
     //list.InvertSelection();
-    /*list.ChangedEvent.Register([&list](long index, bool state) {
-        const auto &l = list;
-        for(auto s : l.Selection)
-            std::cout<<s<<std::endl;
-
-        std::cout<<index<<": "<<(state ? "true" : "false")<<std::endl;
-    });*/
+    list.ChangedEvent.Register([&](long index, bool status) {
+        if(index == -1)
+            return;
+        
+        std::cout << list[index] << ": " << status << std::endl;
+        std::cout << "Eq : " << (&item == &list[index]) << std::endl;
+/*        if(index >= 1)
+            list.Delete(index - 1);*/
+    });
     list.EnsureVisible(11);
     list.EnsureVisible(1);
     

mercurial