1 #ifndef MSP_GLTK_LIST_H_
2 #define MSP_GLTK_LIST_H_
7 #include <sigc++/signal.h>
11 #include "mspgltk_api.h"
18 Thrown if a list's item type is incompatible with its data.
20 class MSPGLTK_API incompatible_data: public std::logic_error
23 incompatible_data(const std::type_info &);
28 Shows a list of items, allowing the user to select one. A slider is included
29 to allow scrolling through a long list.
31 class MSPGLTK_API List: virtual public Widget, private Container
40 static constexpr size_t INVALID_INDEX = std::numeric_limits<size_t>::max();
42 class Loader: public DataFile::DerivedObjectLoader<List, Widget::Loader>
48 void item(const std::string &);
52 /// This exists to make disconnecting signals easier
53 class DataObserver: public sigc::trackable
61 void item_added(std::size_t);
62 void item_removed(std::size_t);
64 void refresh_item(std::size_t);
68 class Item: virtual public Widget, protected Container
74 const char *get_class() const override { return "listitem"; }
77 void autosize_special(const Part &, Geometry &) const override;
79 void set_active(bool);
81 void render_special(const Part &, GL::Renderer &) const override;
84 class SimpleItem: public Item
87 SimpleItem() = default;
89 void on_style_change() override;
92 class MultiColumnItem: public Item
95 MultiColumnItem() = default;
97 virtual void check_widths(std::vector<unsigned> &) const;
98 virtual void set_widths(const std::vector<unsigned> &);
100 void on_style_change() override;
104 class BasicItem: public SimpleItem
110 BasicItem(const std::string &);
116 ItemFactory() = default;
118 virtual ~ItemFactory() = default;
120 virtual void set_data(const ListData &) = 0;
121 virtual std::unique_ptr<Item> create_item(std::size_t) const = 0;
125 class TypedItemFactory: public ItemFactory
128 typedef typename I::ValueType ValueType;
130 const ListDataStore<ValueType> *data;
133 TypedItemFactory(const ListData &d) { set_data(d); }
135 void set_data(const ListData &d) override
137 if(const ListDataStore<ValueType> *ds = dynamic_cast<const ListDataStore<ValueType> *>(&d))
140 throw incompatible_data(typeid(ValueType));
143 std::unique_ptr<Item> create_item(std::size_t i) const override
145 return std::make_unique<I>(data->get(i));
154 Row(std::size_t f): first(f), height(0) { }
158 sigc::signal<void, std::size_t> signal_item_selected;
159 sigc::signal<void> signal_selection_cleared;
162 std::unique_ptr<ListData> own_data;
163 ListData *data = nullptr;
164 std::unique_ptr<DataObserver> observer = nullptr;
165 std::unique_ptr<ItemFactory> item_factory = nullptr;
166 ViewMode view_mode = LIST;
167 std::size_t sel_index = INVALID_INDEX;
168 std::size_t focus_index = INVALID_INDEX;
169 std::size_t first_row = 0;
170 std::size_t max_scroll = 0;
171 unsigned view_rows = 5;
172 unsigned view_columns = 5;
173 const Part *items_part = nullptr;
174 bool ignore_slider_change = false;
175 bool dragging = false;
176 int drag_start_x = 0;
177 int drag_start_y = 0;
180 std::vector<std::unique_ptr<Item>> items;
181 std::vector<Row> rows;
183 List(std::unique_ptr<ListData>);
188 const char *get_class() const override { return "list"; }
191 void autosize_special(const Part &, Geometry &) const override;
194 void set_data(ListData &);
195 ListData &get_data() { return *data; }
196 const ListData &get_data() const { return *data; }
198 void items_changed();
202 void set_item_type() { item_factory = std::make_unique<TypedItemFactory<I>>(*data); }
204 std::unique_ptr<Item> create_item(std::size_t);
207 void set_view_mode(ViewMode);
208 void set_view_size(unsigned);
209 void set_view_size(unsigned, unsigned);
212 void set_selected_index(std::size_t);
213 int get_selected_index() const { return sel_index; }
215 void set_selected_item(Widget *);
217 void rebuild_special(const Part &) override;
218 void render_special(const Part &, GL::Renderer &) const override;
221 bool key_press(unsigned, unsigned) override;
222 void button_press(int, int, unsigned) override;
223 void touch_press(int, int, unsigned) override;
224 void touch_release(int, int, unsigned) override;
225 void touch_motion(int, int, unsigned) override;
226 void focus_in() override;
227 bool navigate(Navigation) override;
229 void on_style_change() override;
231 void move_focus(Navigation, bool);
232 void set_focus_index(std::size_t);
234 void item_autosize_changed(Item *);
235 void reposition_items(bool);
236 std::size_t last_to_first_row(std::size_t) const;
237 std::size_t item_index_to_row(std::size_t) const;
238 void check_view_range();
239 void scroll_to_focus();
240 void slider_value_changed(double);
241 static void adjust_index(std::size_t &, std::size_t, std::ptrdiff_t);
244 MSPGLTK_API void operator>>(const LexicalConverter &, List::ViewMode &);