+#ifndef MSP_GLTK_LISTDATA_H_
+#define MSP_GLTK_LISTDATA_H_
+
+#include <string>
+#include <vector>
+#include <sigc++/signal.h>
+#include <msp/strings/lexicalcast.h>
+
+namespace Msp {
+namespace GLtk {
+
+class ListData
+{
+public:
+ sigc::signal<void, unsigned> signal_item_added;
+ sigc::signal<void, unsigned> signal_item_removed;
+ sigc::signal<void> signal_cleared;
+ sigc::signal<void> signal_refresh_strings;
+
+protected:
+ ListData() { }
+public:
+ virtual ~ListData() { }
+
+ virtual unsigned size() const = 0;
+ virtual std::string get_string(unsigned) const = 0;
+ void refresh_strings() const { signal_refresh_strings.emit(); }
+};
+
+template<typename T>
+class ListDataStore: public ListData
+{
+protected:
+ std::vector<T> items;
+
+ ListDataStore() { }
+
+public:
+ void append(const T &v) { insert(items.size(), v); }
+
+ void insert(unsigned i, const T & v)
+ {
+ if(i>items.size())
+ throw std::out_of_range("ListDataStore::insert");
+
+ items.insert(items.begin()+i, v);
+ signal_item_added.emit(i);
+ }
+
+ const T &get(unsigned i) const
+ {
+ if(i>=items.size())
+ throw std::out_of_range("ListDataStore::get");
+
+ return items[i];
+ }
+
+ void remove(unsigned i)
+ {
+ if(i>=items.size())
+ throw std::out_of_range("ListDataStore::remove");
+
+ items.erase(items.begin()+i);
+ signal_item_removed.emit(i);
+ }
+
+ void clear()
+ {
+ items.clear();
+ signal_cleared.emit();
+ }
+
+ virtual unsigned size() const { return items.size(); }
+};
+
+template<typename T>
+class BasicListData: public ListDataStore<T>
+{
+public:
+ virtual std::string get_string(unsigned i) const
+ { return lexical_cast<std::string>(this->get(i)); }
+};
+
+template<typename T>
+class FunctionListData: public ListDataStore<T>
+{
+public:
+ typedef std::string Func(const T &);
+
+private:
+ Func *func;
+
+public:
+ FunctionListData(Func f): func(f) { }
+
+ virtual std::string get_string(unsigned i) const
+ { return func(this->get(i)); }
+};
+
+} // namespace GLtk
+} // namespace Msp
+
+#endif