1 /* 2 Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 #pragma once 16 17 #include "widget.hpp" 18 19 #include <boost/dynamic_bitset.hpp> 20 21 #include <array> 22 23 namespace gui2 24 { 25 26 struct builder_grid; 27 typedef std::shared_ptr<const builder_grid> builder_grid_const_ptr; 28 29 class grid; 30 31 /** 32 * Abstract base class for the generator. 33 * 34 * A generator is a class which holds multiple grids and controls their 35 * placement on the screen. The final class is policy based, more info about 36 * the possible policies is documented in the build() function. This function 37 * is the factory to generate the classes as well. 38 */ 39 class generator_base : public widget 40 { 41 friend class debug_layout_graph; 42 43 public: ~generator_base()44 virtual ~generator_base() 45 { 46 } 47 48 /** Determines how the items are placed. */ 49 enum placement { 50 horizontal_list, 51 vertical_list, 52 table, 53 independent 54 }; 55 56 /** 57 * Create a new generator. 58 * 59 * @param has_minimum Does one item need to be selected? 60 * @param has_maximum Is one the maximum number of items that can 61 * be selected? 62 * @param placement The placement of the grids, see tplacement 63 * for more info. 64 * @param select If a grid is selected, what should happen? 65 * If true the grid is selected, if false the 66 * grid is shown. 67 * 68 * @returns A pointer to a new object. The caller gets 69 * ownership of the new object. 70 */ 71 static generator_base* build(const bool has_minimum, 72 const bool has_maximum, 73 const placement placement, 74 const bool select); 75 76 /** 77 * Deletes an item. 78 */ 79 virtual void delete_item(const unsigned index) = 0; 80 81 /** Deletes all items. */ 82 virtual void clear() = 0; 83 84 /** 85 * (De)selects an item. 86 * 87 * @param index The item to (de)select. 88 * @param select If true selects, if false deselects. 89 */ 90 virtual void select_item(const unsigned index, const bool select) = 0; 91 92 /** 93 * Toggles the selection state of an item. 94 * 95 * @param index The item to toggle. 96 */ toggle_item(const unsigned index)97 void toggle_item(const unsigned index) 98 { 99 select_item(index, !is_selected(index)); 100 } 101 102 /** Returns whether the item is selected. */ 103 virtual bool is_selected(const unsigned index) const = 0; 104 105 /** 106 * Shows or hides an item. 107 * 108 * The caller is responsible for reformatting the grid. If a selected item 109 * is hidden then it will be automatically deselected; if no items are 110 * shown then no items will be selected, even if has_minimum was requested. 111 * 112 * @param index The item to show or hide. 113 * @param show If true shows the item, else hides it. 114 */ 115 virtual void set_item_shown(const unsigned index, const bool show) = 0; 116 117 /** Returns whether the item is shown. */ 118 virtual bool get_item_shown(const unsigned index) const = 0; 119 120 /** Returns the visibility of all the items as a bit set. */ get_items_shown() const121 boost::dynamic_bitset<> get_items_shown() const 122 { 123 boost::dynamic_bitset<> items_shown(get_item_count()); 124 for (unsigned int i = 0u; i < get_item_count(); ++i) 125 { 126 items_shown[i] = get_item_shown(i); 127 } 128 return items_shown; 129 } 130 131 /** Returns the number of items. */ 132 virtual unsigned get_item_count() const = 0; 133 134 /** Returns the number of selected items. */ 135 virtual unsigned get_selected_item_count() const = 0; 136 137 /** 138 * Returns the selected item. 139 * 140 * If a list has multiple selected items it looks whether it knows the last 141 * item actually selected, if that item is selected that one is chosen. 142 * Else is goes through all selected items and returns the first one 143 * selected. 144 * 145 * @note stacked_widget depends on that behavior it always has all items 146 * selected and thus shown and by default the last selected item (the top 147 * one) is active. 148 * 149 * @returns The selected item, -1 if none selected. 150 */ 151 virtual int get_selected_item() const = 0; 152 153 /** Gets the grid of an item. */ 154 virtual grid& item(const unsigned index) = 0; 155 156 /** Gets the grid of an item. */ 157 virtual const grid& item(const unsigned index) const = 0; 158 159 /***** ***** ***** ***** Create items ***** ***** ***** *****/ 160 161 /** 162 * Creates a new item. 163 * 164 * The item_data is used for the first widget found, this normally should 165 * be used when there's one widget in an item. 166 * 167 * @param index The item before which to add the new item, 168 * 0 == begin, -1 == end. 169 * @param list_builder A grid builder that's will build the 170 * contents of the new item. 171 * @param item_data The data to initialize the parameters of 172 * the new item. 173 * @param callback The callback function to call when an item 174 * in the grid is (de)selected. 175 * 176 * @returns A reference to the newly created grid. 177 */ 178 virtual grid& create_item(const int index, 179 builder_grid_const_ptr list_builder, 180 const string_map& item_data, 181 const std::function<void(widget&)>& callback) 182 = 0; 183 184 /** 185 * Creates a new item. 186 * 187 * The item_data is used by id, and is meant to set multiple widgets in 188 * an item. 189 * 190 * @param index The item before which to add the new item, 191 * 0 == begin, -1 == end. 192 * @param list_builder A grid builder that's will build the 193 * contents of the new item. 194 * @param data The data to initialize the parameters of 195 * the new item. 196 * @param callback The callback function to call when an item 197 * in the grid is (de)selected. 198 * 199 * @returns A reference to the newly created grid. 200 */ 201 virtual grid& 202 create_item(const int index, 203 builder_grid_const_ptr list_builder, 204 const std::map<std::string /* widget id */, string_map>& data, 205 const std::function<void(widget&)>& callback) = 0; 206 207 /** 208 * Creates one or more new item(s). 209 * 210 * For every item in item_data a new item is generated. This version 211 * expects one widget per item. 212 * 213 * @param index The item before which to add the new item, 214 * 0 == begin, -1 == end. 215 * @param list_builder A grid builder that's will build the 216 * contents of the new item. 217 * @param data The data to initialize the parameters of 218 * the new item. 219 * @param callback The callback function to call when an item 220 * in the grid is (de)selected. 221 */ 222 virtual void create_items(const int index, 223 builder_grid_const_ptr list_builder, 224 const std::vector<string_map>& data, 225 const std::function<void(widget&)>& callback) 226 = 0; 227 228 /** 229 * Creates one or more new item(s). 230 * 231 * For every item in item_data a new item is generated. This version 232 * expects multiple widgets per item. 233 * 234 * @param index The item before which to add the new item, 235 * 0 == begin, -1 == end. 236 * @param list_builder A grid builder that's will build the 237 * contents of the new item. 238 * @param data The data to initialize the parameters of 239 * the new item. 240 * @param callback The callback function to call when an item 241 * in the grid is (de)selected. 242 */ 243 virtual void create_items( 244 const int index, 245 builder_grid_const_ptr list_builder, 246 const std::vector<std::map<std::string /*widget id*/, string_map>>& 247 data, 248 const std::function<void(widget&)>& callback) = 0; 249 250 typedef std::function<bool (unsigned, unsigned)> order_func; 251 virtual void set_order(const order_func& order) = 0; 252 253 /***** ***** ***** ***** Inherited ***** ***** ***** *****/ 254 255 /* 256 * These functions must be defined in our child classes so make sure they 257 * become pure virtuals. 258 */ 259 260 /** See @ref widget::layout_initialize. */ 261 virtual void layout_initialize(const bool full_initialization) override = 0; 262 263 /** See @ref widget::request_reduce_width. */ 264 virtual void request_reduce_width(const unsigned maximum_width) override 265 = 0; 266 267 /** See @ref widget::request_reduce_height. */ 268 virtual void request_reduce_height(const unsigned maximum_height) override 269 = 0; 270 271 /** See @ref widget::calculate_best_size. */ 272 virtual point calculate_best_size() const override = 0; 273 274 /** See @ref widget::place. */ 275 virtual void place(const point& origin, const point& size) override = 0; 276 277 /** See @ref widget::set_origin. */ 278 virtual void set_origin(const point& origin) override = 0; 279 280 /** See @ref widget::set_visible_rectangle. */ 281 virtual void set_visible_rectangle(const SDL_Rect& rectangle) override = 0; 282 283 /** See @ref widget::impl_draw_children. */ 284 virtual void impl_draw_children(surface& frame_buffer, 285 int x_offset, 286 int y_offset) override = 0; 287 288 protected: 289 /** See @ref widget::child_populate_dirty_list. */ 290 virtual void 291 child_populate_dirty_list(window& caller, 292 const std::vector<widget*>& call_stack) override 293 = 0; 294 295 public: 296 /** See @ref widget::find_at. */ 297 virtual widget* find_at(const point& coordinate, 298 const bool must_be_active) override = 0; 299 300 /** See @ref widget::find_at. */ 301 virtual const widget* find_at(const point& coordinate, 302 const bool must_be_active) const override 303 = 0; 304 305 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/ 306 307 /** 308 * Up arrow key pressed. 309 * 310 * @param modifier The SDL keyboard modifier when the key was 311 * pressed. 312 * @param handled If the function handles the key it should 313 * set handled to true else do not modify it. 314 * This is used in the keyboard event 315 * changing. 316 */ 317 virtual void handle_key_up_arrow(SDL_Keymod modifier, bool& handled) = 0; 318 319 /** 320 * Down arrow key pressed. 321 * 322 * @param modifier The SDL keyboard modifier when the key was 323 * pressed. 324 * @param handled If the function handles the key it should 325 * set handled to true else do not modify it. 326 * This is used in the keyboard event 327 * changing. 328 */ 329 virtual void handle_key_down_arrow(SDL_Keymod modifier, bool& handled) = 0; 330 331 /** 332 * Left arrow key pressed. 333 * 334 * @param modifier The SDL keyboard modifier when the key was 335 * pressed. 336 * @param handled If the function handles the key it should 337 * set handled to true else do not modify it. 338 * This is used in the keyboard event 339 * changing. 340 */ 341 virtual void handle_key_left_arrow(SDL_Keymod modifier, bool& handled) = 0; 342 343 /** 344 * Right arrow key pressed. 345 * 346 * @param modifier The SDL keyboard modifier when the key was 347 * pressed. 348 * @param handled If the function handles the key it should 349 * set handled to true else do not modify it. 350 * This is used in the keyboard event 351 * changing. 352 */ 353 virtual void handle_key_right_arrow(SDL_Keymod modifier, bool& handled) = 0; 354 355 protected: 356 /** 357 * Selects a not selected item. 358 * 359 * @param index The index of a not selected item. 360 */ 361 virtual void do_select_item(const unsigned index) = 0; 362 363 /** 364 * Deselects a selected item. 365 * 366 * @param index The index of a selected item. 367 */ 368 virtual void do_deselect_item(const unsigned index) = 0; 369 370 /** Gets the grid of an item. */ 371 virtual grid& item_ordered(const unsigned index) = 0; 372 373 /** Gets the grid of an item. */ 374 virtual const grid& item_ordered(const unsigned index) const = 0; 375 376 public: 377 /** 378 * If a sort-order is being applied, maps from unsorted to sorted indicies. 379 * This does not take account of whether each object is shown or not. 380 */ 381 virtual unsigned get_ordered_index(unsigned index) const = 0; 382 383 /** 384 * If a sort-order is being applied, maps from sorted to unsorted indicies. 385 * This does not take account of whether each object is shown or not. 386 */ 387 virtual unsigned get_item_at_ordered(unsigned index_ordered) const = 0; 388 389 }; 390 391 using generator_sort_array = std::array<generator_base::order_func, 2>; 392 393 } // namespace gui2 394