]> git.tdb.fi Git - libs/gltk.git/blob - source/listdata.h
00d2b9b65a154e587789b7ffaf18af1ad2334007
[libs/gltk.git] / source / listdata.h
1 #ifndef MSP_GLTK_LISTDATA_H_
2 #define MSP_GLTK_LISTDATA_H_
3
4 #include <stdexcept>
5 #include <string>
6 #include <vector>
7 #include <sigc++/signal.h>
8 #include <msp/strings/lexicalcast.h>
9 #include "mspgltk_api.h"
10
11 namespace Msp {
12 namespace GLtk {
13
14 class MSPGLTK_API ListData
15 {
16 public:
17         sigc::signal<void, unsigned> signal_item_added;
18         sigc::signal<void, unsigned> signal_item_removed;
19         sigc::signal<void> signal_cleared;
20         sigc::signal<void, unsigned> signal_refresh_item;
21
22 protected:
23         ListData() = default;
24 public:
25         virtual ~ListData() = default;
26
27         virtual unsigned size() const = 0;
28         virtual std::string get_string(unsigned) const = 0;
29         void refresh(unsigned i) const
30         {
31                 if(i>=size())
32                         throw std::out_of_range("ListData::refresh");
33                 signal_refresh_item.emit(i);
34         }
35 };
36
37 template<typename T>
38 class ListDataStore: public ListData
39 {
40 protected:
41         std::vector<T> items;
42
43         ListDataStore() = default;
44
45 public:
46         void append(const T &v) { insert(items.size(), v); }
47
48         void insert(unsigned i, const T &v)
49         {
50                 if(i>items.size())
51                         throw std::out_of_range("ListDataStore::insert");
52
53                 items.insert(items.begin()+i, v);
54                 signal_item_added.emit(i);
55         }
56
57         const T &get(unsigned i) const
58         {
59                 if(i>=items.size())
60                         throw std::out_of_range("ListDataStore::get");
61
62                 return items[i];
63         }
64
65         int find(const T &v) const
66         {
67                 for(unsigned i=0; i<items.size(); ++i)
68                         if(items[i]==v)
69                                 return i;
70                 return -1;
71         }
72
73         using ListData::refresh;
74         void refresh(const T &v) const
75         {
76                 int i = find(v);
77                 if(i>=0)
78                         signal_refresh_item.emit(i);
79         }
80
81         void remove(unsigned i)
82         {
83                 if(i>=items.size())
84                         throw std::out_of_range("ListDataStore::remove");
85
86                 items.erase(items.begin()+i);
87                 signal_item_removed.emit(i);
88         }
89
90         void clear()
91         {
92                 items.clear();
93                 signal_cleared.emit();
94         }
95
96         virtual unsigned size() const { return items.size(); }
97 };
98
99 template<typename T>
100 class BasicListData: public ListDataStore<T>
101 {
102 public:
103         virtual std::string get_string(unsigned i) const
104         { return lexical_cast<std::string>(this->get(i)); }
105 };
106
107 template<typename T>
108 class FunctionListData: public ListDataStore<T>
109 {
110 public:
111         typedef std::string Func(const T &);
112
113 private:
114         Func *func = 0;
115
116 public:
117         FunctionListData(Func f): func(f) { }
118
119         virtual std::string get_string(unsigned i) const
120         { return func(this->get(i)); }
121 };
122
123 } // namespace GLtk
124 } // namespace Msp
125
126 #endif