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