The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
generator_private.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#pragma once
17
19
21#include "gui/widgets/grid.hpp"
25#include "gui/widgets/window.hpp" // For widget::visibility
26#include "wml_exception.hpp"
27
28#include <cassert>
29
30namespace gui2
31{
32/**
33 * Contains the policies for the generator class.
34 */
35namespace policy
36{
37/***** ***** ***** ***** Minimum selection ***** ***** ***** *****/
38
39/** Contains the policy for the minimum number of selected items. */
40namespace minimum_selection
41{
42/** Must select at least one item. */
43struct one_item : public virtual generator_base
44{
45 /**
46 * Called when an item is shown or hidden.
47 *
48 * @param index The item to show or hide.
49 * @param show If true shows the item, else hides it.
50 */
51 void set_item_shown(const unsigned index, const bool show);
52
53 /**
54 * Called when an item is created.
55 *
56 * @param index The index of the new item.
57 */
58 void create_item(const unsigned index);
59
60 /* Also make the overload from the generator_ visible. */
62
63 /**
64 * Called when the users wants to deselect an item.
65 *
66 * If the item can be deselected this function should call
67 * do_deselect_item() to make the deselection happen. If not allowed no
68 * action needs to be taken.
69 *
70 * @param index The index of the item to deselect.
71 *
72 * @returns Whether the item was deselected, some
73 * actions might happen automatically upon
74 * deselecting, so if this function returns
75 * false the caller should make sure the
76 * select state is restored.
77 */
78 bool deselect_item(const unsigned index);
79
80 /**
81 * Called just before an item is deleted.
82 *
83 * This function can if needed select another items to try to obey the
84 * policy.
85 *
86 * @param index The index of the item to be deleted.
87 */
88 void delete_item(const unsigned index);
89};
90
91/** No minimum selection. */
92struct no_item : public virtual generator_base
93{
94 /** See @ref minimum_selection::one_item::set_item_shown(). */
95 void set_item_shown(const unsigned index, const bool show);
96
97 /** See @ref minimum_selection::one_item::create_item() */
98 void create_item(const unsigned /*index*/)
99 {
100 }
101
102 /* Also make the overload from the generator_ visible. */
104
105 /** See @ref minimum_selection::one_item::deselect_item() */
106 bool deselect_item(const unsigned index)
107 {
108 do_deselect_item(index);
109 return true;
110 }
111
112 /** See @ref minimum_selection::one_item::delete_item() */
113 void delete_item(const unsigned index)
114 {
115 if(is_selected(index)) {
116 do_deselect_item(index);
117 }
118 }
119};
120
121} // namespace minimum_selection
122
123/***** ***** ***** ***** Maximum selection ***** ***** ***** *****/
124
125/** Contains the policy for the maximum number of selected items. */
126namespace maximum_selection
127{
128/** May select only one item. */
129struct one_item : public virtual generator_base
130{
131 /**
132 * Called when an item is selected.
133 *
134 * This function can deselect other items to obey the policy. This
135 * function should always call do_select_item() so the new item does get
136 * selected.
137 *
138 * Since this function controls the maximum selection count it should only
139 * be used to select items, not to deselect them.
140 *
141 * @pre @p select == @c true
142 *
143 * @param index The item to select.
144 * @param select Should always be true.
145 */
146 void select_item(const unsigned index, const bool select) override
147 {
148 assert(select);
149
150 if(get_selected_item_count() == 1) {
151 // deselect current.
153 }
154
155 // select new.
156 do_select_item(index);
157 }
158};
159
160/** No maximum amount of items to select. */
161struct many_items : public virtual generator_base
162{
163 /** See one_item::select_item(). */
164 void select_item(const unsigned index, const bool select) override
165 {
166 assert(select);
167
168 do_select_item(index);
169 }
170};
171
172} // namespace maximum_selection
173
174/***** ***** ***** ***** Placement ***** ***** ***** *****/
175
176/** Controls how new items are placed. */
177namespace placement
178{
179/** Places the items in a horizontal row. */
180struct horizontal_list : public virtual generator_base
181{
183
184 /**
185 * Called when an item is created.
186 *
187 * This function should place the new item.
188 *
189 * @param index The index of the new item.
190 */
191 void create_item(const unsigned index);
192
193 /* Also make the overload from the generator_ visible. */
195
196 /** See @ref widget::request_reduce_width. */
197 virtual void request_reduce_width(const unsigned /*maximum_width*/) override
198 {
199 /* DO NOTHING */
200 }
201
202 /** See @ref widget::request_reduce_height. */
203 virtual void request_reduce_height(const unsigned /*maximum_height*/) override
204 {
205 /* DO NOTHING */
206 }
207
208 /** See @ref widget::calculate_best_size. */
209 virtual point calculate_best_size() const override;
210
211 /** See @ref widget::place. */
212 virtual void place(const point& origin, const point& size) override;
213
214 /** See @ref widget::set_origin. */
215 virtual void set_origin(const point& origin) override;
216
217 /**
218 * Sets the visible rectangle of the generator.
219 *
220 * @param rectangle The visible rectangle.
221 */
222 void set_visible_rectangle(const rect& rectangle) override;
223
224 /** See @ref widget::find_at. */
225 virtual widget* find_at(const point& coordinate, const bool must_be_active) override;
226
227 /** See @ref widget::find_at. */
228 virtual const widget* find_at(const point& coordinate, const bool must_be_active) const override;
229
230 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
231
232 /** Inherited from generator_base. */
233 void handle_key_up_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override
234 {
235 /* DO NOTHING */
236 }
237
238 /** Inherited from generator_base. */
239 void handle_key_down_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override
240 {
241 /* DO NOTHING */
242 }
243
244 /** Inherited from generator_base. */
245 void handle_key_left_arrow(SDL_Keymod modifier, bool& handled) override;
246
247 /** Inherited from generator_base. */
248 void handle_key_right_arrow(SDL_Keymod modifier, bool& handled) override;
249
250private:
251 /**
252 * Has the grid already been placed?
253 *
254 * If the grid is placed it's no problem set the location of the new
255 * item,it hasn't been placed, there's no information about its location
256 * so do nothing.
257 */
259};
260
261/** Places the items in a vertical column. */
262struct vertical_list : public virtual generator_base
263{
265
266 /** See horizontal_list::create_item(). */
267 void create_item(const unsigned index);
268
269 /* Also make the overload from the generator_ visible. */
271
272 /** See @ref widget::request_reduce_width. */
273 virtual void request_reduce_width(const unsigned /*maximum_width*/) override
274 {
275 /* DO NOTHING */
276 }
277
278 /** See @ref widget::request_reduce_height. */
279 virtual void request_reduce_height(const unsigned /*maximum_height*/) override
280 {
281 /* DO NOTHING */
282 }
283
284 /** See @ref widget::calculate_best_size. */
285 virtual point calculate_best_size() const override;
286
287 /** See @ref widget::place. */
288 virtual void place(const point& origin, const point& size) override;
289
290 /** See @ref widget::set_origin. */
291 virtual void set_origin(const point& origin) override;
292
293 /** See @ref horizontal_list::set_visible_rectangle(). */
294 void set_visible_rectangle(const rect& rectangle) override;
295
296 /** See @ref widget::find_at. */
297 virtual widget* find_at(const point& coordinate, const bool must_be_active) override;
298
299 /** See @ref widget::find_at. */
300 virtual const widget* find_at(const point& coordinate, const bool must_be_active) const override;
301
302 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
303
304 /** Inherited from generator_base. */
305 void handle_key_up_arrow(SDL_Keymod modifier, bool& handled) override;
306
307 /** Inherited from generator_base. */
308 void handle_key_down_arrow(SDL_Keymod modifier, bool& handled) override;
309
310 /** Inherited from generator_base. */
311 void handle_key_left_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override
312 {
313 /* DO NOTHING */
314 }
315
316 /** Inherited from generator_base. */
317 void handle_key_right_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override
318 {
319 /* DO NOTHING */
320 }
321
322 // FIXME we need a delete handler as well,
323 // when deleting the last item we need to remove the placed flag.
324
325 // FIXME we also need a clear function, called when
326 // clear is called.
327private:
328 /**
329 * Has the grid already been placed?
330 *
331 * If the grid is placed it's no problem set the location of the new
332 * item,it hasn't been placed, there's no information about its location
333 * so do nothing.
334 */
336};
337
338/**
339 * Places the items in a grid.
340 *
341 * The items will be placed in rows and columns. It has to be determined
342 * whether the number of columns will be fixed or variable.
343 *
344 * @todo Implement.
345 */
346struct table : public virtual generator_base
347{
348 table();
349
350 /** See horizontal_list::create_item(). */
351 void create_item(const unsigned /*index*/);
352
353 /* Also make the overload from the generator_ visible. */
355
356 /** See @ref widget::request_reduce_width. */
357 virtual void request_reduce_width(const unsigned /*maximum_width*/) override
358 {
359 /* DO NOTHING */
360 }
361
362 /** See @ref widget::request_reduce_height. */
363 virtual void request_reduce_height(const unsigned /*maximum_height*/) override
364 {
365 /* DO NOTHING */
366 }
367
368 /** See @ref widget::calculate_best_size. */
369 virtual point calculate_best_size() const override;
370
371 /** See @ref widget::place. */
372 virtual void place(const point& /*origin*/, const point& /*size*/) override;
373
374 /** See @ref widget::set_origin. */
375 virtual void set_origin(const point& /*origin*/) override;
376
377 /** See @ref horizontal_list::set_visible_rectangle(). */
378 void set_visible_rectangle(const rect& /*rectangle*/) override;
379
380 /** See @ref widget::find_at. */
381 virtual widget* find_at(const point& /*coordinate*/
382 ,
383 const bool /*must_be_active*/) override;
384
385 /** See @ref widget::find_at. */
386 virtual const widget* find_at(const point& /*coordinate*/
387 ,
388 const bool /*must_be_active*/) const override;
389
390 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
391
392 /** Inherited from generator_base. */
393 void handle_key_up_arrow(SDL_Keymod, bool&) override;
394
395 /** Inherited from generator_base. */
396 void handle_key_down_arrow(SDL_Keymod, bool&) override;
397
398 /** Inherited from generator_base. */
399 void handle_key_left_arrow(SDL_Keymod, bool&) override;
400
401 /** Inherited from generator_base. */
402 void handle_key_right_arrow(SDL_Keymod, bool&) override;
403
404private:
405 /**
406 * Has the grid already been placed?
407 *
408 * If the grid is placed it's no problem set the location of the new
409 * item,it hasn't been placed, there's no information about its location
410 * so do nothing.
411 */
413};
414
415/**
416 * Places the items independent of each other.
417 *
418 * This is mainly meant for when only one item is shown at the same time.
419 *
420 * @todo Implement.
421 */
422struct independent : public virtual generator_base
423{
424 /** See horizontal_list::create_item(). */
425 void create_item(const unsigned /*index*/)
426 {
427 /* DO NOTHING */
428 }
429
430 /* Also make the overload from the generator_ visible. */
432
433 /** See @ref widget::request_reduce_width. */
434 virtual void request_reduce_width(const unsigned maximum_width) override;
435
436 /** See horizontal_list::request_reduce_height. */
437 virtual void request_reduce_height(const unsigned maximum_height) override;
438
439 /** See @ref widget::calculate_best_size. */
440 virtual point calculate_best_size() const override;
441
442 /** See @ref widget::place. */
443 virtual void place(const point& origin, const point& size) override;
444
445 /** See @ref widget::set_origin. */
446 virtual void set_origin(const point& origin) override;
447
448 /** See @ref horizontal_list::set_visible_rectangle(). */
449 void set_visible_rectangle(const rect& rectangle) override;
450
451 /** See @ref widget::find_at. */
452 virtual widget* find_at(const point& coordinate, const bool must_be_active) override;
453
454 /** See @ref widget::find_at. */
455 virtual const widget* find_at(const point& coordinate, const bool must_be_active) const override;
456
457 /** See @ref widget::find. */
458 widget* find(const std::string_view id, const bool must_be_active) override;
459
460 /** See @ref widget::find. */
461 const widget* find(const std::string_view id, const bool must_be_active) const override;
462
463 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
464
465 /** Inherited from generator_base. */
466 void handle_key_up_arrow(SDL_Keymod, bool&) override
467 {
468 /* DO NOTHING */
469 }
470
471 /** Inherited from generator_base. */
472 void handle_key_down_arrow(SDL_Keymod, bool&) override
473 {
474 /* DO NOTHING */
475 }
476
477 /** Inherited from generator_base. */
478 void handle_key_left_arrow(SDL_Keymod, bool&) override
479 {
480 /* DO NOTHING */
481 }
482
483 /** Inherited from generator_base. */
484 void handle_key_right_arrow(SDL_Keymod, bool&) override
485 {
486 /* DO NOTHING */
487 }
488};
489
490} // namespace placement
491
492/***** ***** ***** ***** Select action ***** ***** ***** *****/
493
494/**
495 * Contains the policy for which action to take when an item is selected or
496 * deselected.
497 */
498namespace select_action
499{
500/** Select the item, this requires the grid to contain a selectable_item. */
501struct selection : public virtual generator_base
502{
503 void select(grid& grid, const bool select);
504
505 /**
506 * Helper function to initialize a grid.
507 *
508 * @param grid The grid to initialize.
509 * @param data The data to initialize the parameters of
510 * the new item.
511 * @param callback The callback function to call when an item
512 * in the grid is (de)selected.
513 */
514 void init(grid* grid,
515 const widget_data& data,
516 const std::function<void(widget&)>& callback);
517};
518
519/** Show the item. */
520struct show : public virtual generator_base
521{
526
527 /**
528 * Helper function to initialize a grid.
529 *
530 * @param grid The grid to initialize.
531 * @param data The data to initialize the parameters of
532 * the new item. No widgets with id == "" are
533 * allowed.
534 * @param callback The callback function is not used and
535 * should be nullptr.
536 */
537 void init(grid* grid,
538 const widget_data& data,
539 const std::function<void(widget&)>& callback);
540};
541
542} // namespace select_action
543
544} // namespace policy
545
546/***** ***** ***** ***** generator ***** ***** ***** *****/
547
548/**
549 * Basic template class to generate new items.
550 *
551 * The class is policy based so the behavior can be selected.
552 */
553template<class minimum_selection,
554 class maximum_selection,
555 class my_placement,
556 class select_action>
557class generator : public minimum_selection,
558 public maximum_selection,
559 public my_placement,
560 public select_action
561{
562public:
564 : minimum_selection()
565 , maximum_selection()
566 , my_placement()
567 , select_action()
570 , items_()
571 , order_()
572 , order_dirty_(true)
573 , order_func_()
574 {
575 }
576
578 {
579 clear();
580 }
581
582 /***** ***** ***** inherited ***** ****** *****/
583
584 /** Inherited from generator_base. */
585 void delete_item(const unsigned index) override
586 {
587 assert(index < items_.size());
588
589 // Might be other parts of the engine want to know about the
590 // deselection, if minimum fails it gets another chance later on,
591 // since it deletes the item.
592 if(is_selected(index)) {
593 select_item(index, false);
594 }
595
596 minimum_selection::delete_item(index);
597
598 items_.erase(items_.begin() + index);
599 order_dirty_ = true;
600 }
601
602 /** Inherited from generator_base. */
603 void clear() override
604 {
605 items_.clear();
606 order_dirty_ = true;
608 }
609
610 /** Inherited from generator_base. */
611 void select_item(const unsigned index, const bool select = true) override
612 {
613 assert(index < items_.size());
614
615 if(select && !is_selected(index)) {
616 maximum_selection::select_item(index, true);
617 last_selected_item_ = index;
618 } else if(is_selected(index)) {
619 if(!minimum_selection::deselect_item(index)) {
620 // Some items might have deselected themselves so
621 // make sure they do get selected again.
622 select_action::select(item(index), true);
623 }
624 }
625 }
626
627 /** Inherited from generator_base. */
628 bool is_selected(const unsigned index) const override
629 {
630 assert(index < items_.size());
631 return (*items_[index]).selected;
632 }
633
634 /** Inherited from generator_base. */
635 void set_item_shown(const unsigned index, const bool show) override
636 {
637 assert(index < items_.size());
638 if(items_[index]->shown != show) {
639 /*** Set the proper visible state. ***/
640 items_[index]->shown = show;
641 items_[index]->child_grid.set_visible(show);
642
643 /*** Update the selection. ***/
644 minimum_selection::set_item_shown(index, show);
645 }
646 }
647
648 /** Inherited from generator_base. */
649 virtual bool get_item_shown(const unsigned index) const override
650 {
651 assert(index < items_.size());
652 return items_[index]->shown && items_[index]->child_grid.get_visible() != widget::visibility::invisible;
653 }
654
655 /** Inherited from generator_base. */
656 unsigned get_item_count() const override
657 {
658 return items_.size();
659 }
660
661 /** Inherited from generator_base. */
662 unsigned get_selected_item_count() const override
663 {
665 }
666
667 /** Inherited from generator_base. */
668 int get_selected_item() const override
669 {
670 if(selected_item_count_ == 0) {
671 return -1;
672 } else if(last_selected_item_ != -1 && last_selected_item_ < static_cast<int>(items_.size())
673 && (*items_[last_selected_item_]).selected)
674 {
675 return last_selected_item_;
676 } else {
677 for(std::size_t i = 0; i < items_.size(); ++i) {
678 if((*items_[i]).selected) {
679 return i;
680 }
681 }
682
684 "No item selected.", "selected_item_count_ was non-zero, yet no selected item was found.");
685 }
686 }
687
688 /** Inherited from generator_base. */
689 grid& item(const unsigned index) override
690 {
691 assert(index < items_.size());
692 return items_[index]->child_grid;
693 }
694
695 /** Inherited from generator_base. */
696 const grid& item(const unsigned index) const override
697 {
698 assert(index < items_.size());
699 return items_[index]->child_grid;
700 }
701
702 /** Inherited from generator_base. */
703 grid& item_ordered(const unsigned index) override
704 {
706 assert(index < items_.size());
707 return items_[order_[index]]->child_grid;
708 }
709
710 /** Inherited from generator_base. */
711 const grid& item_ordered(const unsigned index) const override
712 {
714 assert(index < items_.size());
715 return items_[order_[index]]->child_grid;
716 }
717
718 /** Inherited from generator_base. */
719 grid& create_item(const int index,
720 const builder_grid& list_builder,
721 const widget_item& item_data,
722 const std::function<void(widget&)>& callback) override
723 {
725
726 data.emplace("", item_data);
727 return create_item(index, list_builder, data, callback);
728 }
729
730 /** Inherited from generator_base. */
731 grid& create_item(const int index,
732 const builder_grid& list_builder,
733 const widget_data& item_data,
734 const std::function<void(widget&)>& callback) override
735 {
736 assert(index == -1 || static_cast<unsigned>(index) <= items_.size());
737
738 auto item = std::make_unique<child>();
739 grid& child_grid = item->child_grid;
740
741 list_builder.build(child_grid);
742 init(&child_grid, item_data, callback);
743
744 const std::size_t item_index = index == -1 ? items_.size() : index;
745 items_.emplace(items_.begin() + item_index, std::move(item));
746
747 order_dirty_ = true;
748
749 minimum_selection::create_item(item_index);
750
751 my_placement::create_item(item_index);
752
753 if(!is_selected(item_index)) {
754 select_action::select(child_grid, false);
755 }
756
757 return child_grid;
758 }
759
760 /** Inherited from generator_base. */
761 virtual void create_items(const int index,
762 const builder_grid& list_builder,
763 const std::vector<widget_data>& data,
764 const std::function<void(widget&)>& callback) override
765 {
766 impl_create_items(index, list_builder, data, callback);
767 }
768
769 /** Inherited from generator_base. */
770 virtual void create_items(const int index,
771 const builder_grid& list_builder,
772 const std::vector<widget_item>& data,
773 const std::function<void(widget&)>& callback) override
774 {
775 impl_create_items(index, list_builder, data, callback);
776 }
777
778 /** See @ref widget::layout_initialize. */
779 virtual void layout_initialize(const bool full_initialization) override
780 {
781 for(auto& item : items_) {
782 if(item->child_grid.get_visible() != widget::visibility::invisible && item->shown) {
783 item->child_grid.layout_initialize(full_initialization);
784 }
785 }
786 }
787
788 /** See @ref widget::request_reduce_width. */
789 virtual void request_reduce_width(const unsigned maximum_width) override
790 {
791 my_placement::request_reduce_width(maximum_width);
792 }
793
794 /** See @ref widget::request_reduce_height. */
795 virtual void request_reduce_height(const unsigned maximum_height) override
796 {
797 my_placement::request_reduce_height(maximum_height);
798 }
799
800 /** See @ref widget::calculate_best_size. */
801 virtual point calculate_best_size() const override
802 {
803 return my_placement::calculate_best_size();
804 }
805
806 /** See @ref widget::place. */
807 virtual void place(const point& origin, const point& size) override
808 {
809 // Inherited, so we get useful debug info.
810 widget::place(origin, size);
811
812 my_placement::place(origin, size);
813 }
814
815 /** See @ref widget::set_origin. */
816 virtual void set_origin(const point& origin) override
817 {
818 // Inherited.
819 widget::set_origin(origin);
820
821 my_placement::set_origin(origin);
822 }
823
824 /** See @ref widget::set_visible_rectangle. */
825 virtual void set_visible_rectangle(const rect& rectangle) override
826 {
827 my_placement::set_visible_rectangle(rectangle);
828 }
829
830 /** See @ref widget::impl_draw_children. */
831 virtual void impl_draw_children() override
832 {
833 assert(this->get_visible() == widget::visibility::visible);
834
836
837 for(auto index : order_) {
838 child* item = items_[index].get();
839
840 if(item->child_grid.get_visible() == widget::visibility::visible && item->shown) {
841 item->child_grid.draw_children();
842 }
843 }
844 }
845
846 /** See @ref widget::find_at. */
847 virtual widget* find_at(const point& coordinate, const bool must_be_active) override
848 {
849 return my_placement::find_at(coordinate, must_be_active);
850 }
851
852 /** See @ref widget::find_at. */
853 virtual const widget* find_at(const point& coordinate, const bool must_be_active) const override
854 {
855 return my_placement::find_at(coordinate, must_be_active);
856 }
857
858 /** See @ref widget::disable_click_dismiss. */
859 bool disable_click_dismiss() const override
860 {
861 for(auto& item : items_) {
862 if(item->child_grid.disable_click_dismiss()) {
863 return true;
864 }
865 }
866
867 return false;
868 }
869
870 /**
871 * See @ref widget::create_walker.
872 *
873 * @todo Implement properly.
874 */
876 {
877 return nullptr;
878 }
879
880 /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
881
882 /** Inherited from generator_base. */
883 void handle_key_up_arrow(SDL_Keymod modifier, bool& handled) override
884 {
885 my_placement::handle_key_up_arrow(modifier, handled);
886 }
887
888 /** Inherited from generator_base. */
889 void handle_key_down_arrow(SDL_Keymod modifier, bool& handled) override
890 {
891 my_placement::handle_key_down_arrow(modifier, handled);
892 }
893
894 /** Inherited from generator_base. */
895 void handle_key_left_arrow(SDL_Keymod modifier, bool& handled) override
896 {
897 my_placement::handle_key_left_arrow(modifier, handled);
898 }
899
900 /** Inherited from generator_base. */
901 void handle_key_right_arrow(SDL_Keymod modifier, bool& handled) override
902 {
903 my_placement::handle_key_right_arrow(modifier, handled);
904 }
905
906protected:
907 /** Inherited from generator_base. */
908 void do_select_item(const unsigned index) override
909 {
910 assert(index < items_.size());
911
913 set_item_selected(index, true);
914 }
915
916 /** Inherited from generator_base. */
917 void do_deselect_item(const unsigned index) override
918 {
919 assert(index < items_.size());
920
922 set_item_selected(index, false);
923 }
924
925private:
926 /** Definition of an item. */
927 struct child
928 {
929 /** The grid containing the widgets. */
931
932 /** Is the item selected or not. */
933 bool selected = false;
934
935 /**
936 * Is the row shown or not.
937 *
938 * This flag is used the help to set the visible flag, it's preferred to
939 * test this flag for external functions.
940 *
941 * @todo functions now test for visible and shown, that can use some
942 * polishing.
943 */
944 bool shown = true;
945
946 std::size_t ordered_index = 0;
947 };
948
949 /** The number of selected items. */
951
952 /** The last item selected. */
954
955 /** The items in the generator. */
956 typedef std::vector<std::unique_ptr<child>> child_list;
958
959 /** the elements of order_ are indexes to items_ */
960 mutable std::vector<std::size_t> order_;
961 /** whether need to recalculate order_dirty_ */
962 mutable bool order_dirty_;
963
964 typedef std::function<bool(unsigned, unsigned)> order_func;
966
967 virtual void set_order(const order_func& order) override
968 {
969 order_func_ = order;
970 order_dirty_ = true;
971 this->queue_redraw();
972 }
973
974 virtual unsigned get_ordered_index(unsigned index) const override
975 {
976 assert(index < items_.size());
978 return items_[index]->ordered_index;
979 }
980
981 virtual unsigned get_item_at_ordered(unsigned index_ordered) const override
982 {
983 assert(index_ordered < items_.size());
985 return order_[index_ordered];
986 }
987
988 void calculate_order() const
989 {
990 if(order_dirty_) {
991 if(order_.size() != items_.size()) {
992 order_.resize(items_.size());
993
994 for(std::size_t i = 0; i < items_.size(); ++i) {
995 order_[i] = i;
996 }
997 }
998
999 if(order_func_) {
1000 std::stable_sort(order_.begin(), order_.end(), order_func_);
1001 }
1002
1003 for(std::size_t i = 0; i < order_.size(); ++i) {
1004 items_[order_[i]]->ordered_index = i;
1005 }
1006
1007 order_dirty_ = false;
1008 } else {
1009 assert(order_.size() == items_.size());
1010 }
1011 }
1012 /**
1013 * Sets the selected state of an item.
1014 *
1015 * @param index The item to modify.
1016 * @param selected Select or deselect.
1017 */
1018 void set_item_selected(const unsigned index, const bool selected)
1019 {
1020 assert(index < items_.size());
1021
1022 (*items_[index]).selected = selected;
1023 select_action::select((*items_[index]).child_grid, selected);
1024 }
1025
1026 /**
1027 * Helper function for create_items().
1028 *
1029 * @tparam T Type of the data, this should be one of the
1030 * valid parameters for create_item().
1031 *
1032 * @param index The item before which to add the new item,
1033 * 0 == begin, -1 == end.
1034 * @param list_builder A grid builder that's will build the
1035 * contents of the new item.
1036 * @param data The data to initialize the parameters of
1037 * the new item.
1038 * @param callback The callback function to call when an item
1039 * in the grid is (de)selected.
1040 */
1041 template<class T>
1042 void impl_create_items(const int index,
1043 const builder_grid& list_builder,
1044 const std::vector<T>& data,
1045 const std::function<void(widget&)>& callback)
1046 {
1047 int i = index;
1048
1049 for(const auto& item_data : data) {
1050 create_item(i, list_builder, item_data, callback);
1051 if(i != -1) {
1052 ++i;
1053 }
1054 }
1055 }
1056
1057 /**
1058 * Helper function to initialize a grid.
1059 *
1060 * The actual part is implemented in select_action, see those
1061 * implementations for more information.
1062 *
1063 * @param grid The grid to initialize.
1064 * @param data The data to initialize the parameters of
1065 * the new item.
1066 * @param callback The callback function to call when an item
1067 * in the grid is (de)selected.
1068 */
1070 const std::function<void(widget&)>& callback)
1071 {
1072 assert(grid);
1073 grid->set_parent(this);
1074
1075 select_action::init(grid, data, callback);
1076 }
1077};
1078
1079} // namespace gui2
Abstract base class for the generator.
Definition generator.hpp:39
virtual unsigned get_selected_item_count() const =0
Returns the number of selected items.
virtual grid & create_item(const int index, const builder_grid &list_builder, const widget_item &item_data, const std::function< void(widget &)> &callback)=0
Creates a new item.
virtual bool is_selected(const unsigned index) const =0
Returns whether the item is selected.
virtual void do_select_item(const unsigned index)=0
Selects a not selected item.
virtual void do_deselect_item(const unsigned index)=0
Deselects a selected item.
virtual int get_selected_item() const =0
Returns the selected item.
Basic template class to generate new items.
virtual void request_reduce_height(const unsigned maximum_height) override
See widget::request_reduce_height.
int last_selected_item_
The last item selected.
void calculate_order() const
std::function< bool(unsigned, unsigned)> order_func
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
unsigned selected_item_count_
The number of selected items.
void clear() override
Inherited from generator_base.
void handle_key_up_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
bool order_dirty_
whether need to recalculate order_dirty_
grid & item_ordered(const unsigned index) override
Inherited from generator_base.
std::vector< std::unique_ptr< child > > child_list
The items in the generator.
virtual const widget * find_at(const point &coordinate, const bool must_be_active) const override
See widget::find_at.
void set_item_shown(const unsigned index, const bool show) override
Inherited from generator_base.
const grid & item(const unsigned index) const override
Inherited from generator_base.
virtual iteration::walker_ptr create_walker() override
See widget::create_walker.
virtual void create_items(const int index, const builder_grid &list_builder, const std::vector< widget_item > &data, const std::function< void(widget &)> &callback) override
Inherited from generator_base.
void delete_item(const unsigned index) override
Inherited from generator_base.
virtual bool get_item_shown(const unsigned index) const override
Inherited from generator_base.
void set_item_selected(const unsigned index, const bool selected)
Sets the selected state of an item.
bool is_selected(const unsigned index) const override
Inherited from generator_base.
void select_item(const unsigned index, const bool select=true) override
Inherited from generator_base.
virtual void impl_draw_children() override
See widget::impl_draw_children.
virtual void set_order(const order_func &order) override
virtual unsigned get_item_at_ordered(unsigned index_ordered) const override
unsigned get_selected_item_count() const override
Inherited from generator_base.
grid & create_item(const int index, const builder_grid &list_builder, const widget_item &item_data, const std::function< void(widget &)> &callback) override
Inherited from generator_base.
void init(grid *grid, const widget_data &data, const std::function< void(widget &)> &callback)
Helper function to initialize a grid.
virtual void set_visible_rectangle(const rect &rectangle) override
See widget::set_visible_rectangle.
std::vector< std::size_t > order_
the elements of order_ are indexes to items_
virtual void set_origin(const point &origin) override
See widget::set_origin.
grid & create_item(const int index, const builder_grid &list_builder, const widget_data &item_data, const std::function< void(widget &)> &callback) override
Inherited from generator_base.
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
void handle_key_left_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
grid & item(const unsigned index) override
Inherited from generator_base.
virtual void create_items(const int index, const builder_grid &list_builder, const std::vector< widget_data > &data, const std::function< void(widget &)> &callback) override
Inherited from generator_base.
void do_select_item(const unsigned index) override
Inherited from generator_base.
void handle_key_down_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
void do_deselect_item(const unsigned index) override
Inherited from generator_base.
void handle_key_right_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
int get_selected_item() const override
Inherited from generator_base.
virtual void place(const point &origin, const point &size) override
See widget::place.
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
void impl_create_items(const int index, const builder_grid &list_builder, const std::vector< T > &data, const std::function< void(widget &)> &callback)
Helper function for create_items().
virtual unsigned get_ordered_index(unsigned index) const override
unsigned get_item_count() const override
Inherited from generator_base.
const grid & item_ordered(const unsigned index) const override
Inherited from generator_base.
Base container class.
Definition grid.hpp:32
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
Definition grid.cpp:670
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
Definition grid.cpp:190
Base class for all widgets.
Definition widget.hpp:55
virtual void place(const point &origin, const point &size)
Places the widget.
Definition widget.cpp:248
void set_visible(const visibility visible)
Definition widget.cpp:479
visibility get_visible() const
Definition widget.cpp:506
void set_parent(widget *parent)
Definition widget.cpp:165
void draw_children()
Draws the children of a widget.
Definition widget.cpp:402
virtual void set_origin(const point &origin)
Sets the origin of the widget.
Definition widget.cpp:230
@ visible
The user sets the widget visible, that means:
@ invisible
The user set the widget invisible, that means:
@ hidden
The user sets the widget hidden, that means:
This file contains the window object, this object is a top level container which has the event manage...
std::unique_ptr< class walker_base > walker_ptr
Definition widget.hpp:44
Generic file dialog.
void init()
Initializes the GUI subsystems.
Definition gui.cpp:108
std::map< std::string, widget_item > widget_data
Definition widget.hpp:36
std::map< std::string, t_string > widget_item
Definition widget.hpp:33
std::string_view data
Definition picture.cpp:188
virtual std::unique_ptr< widget > build() const override
Inherited from builder_widget.
Definition of an item.
grid child_grid
The grid containing the widgets.
bool selected
Is the item selected or not.
bool shown
Is the row shown or not.
No maximum amount of items to select.
void select_item(const unsigned index, const bool select) override
See one_item::select_item().
void select_item(const unsigned index, const bool select) override
Called when an item is selected.
void delete_item(const unsigned index)
See minimum_selection::one_item::delete_item()
bool deselect_item(const unsigned index)
See minimum_selection::one_item::deselect_item()
void create_item(const unsigned)
See minimum_selection::one_item::create_item()
void set_item_shown(const unsigned index, const bool show)
See minimum_selection::one_item::set_item_shown().
Definition generator.cpp:90
void delete_item(const unsigned index)
Called just before an item is deleted.
Definition generator.cpp:84
bool deselect_item(const unsigned index)
Called when the users wants to deselect an item.
Definition generator.cpp:74
void create_item(const unsigned index)
Called when an item is created.
Definition generator.cpp:67
void set_item_shown(const unsigned index, const bool show)
Called when an item is shown or hidden.
Definition generator.cpp:33
Places the items in a horizontal row.
void set_visible_rectangle(const rect &rectangle) override
Sets the visible rectangle of the generator.
virtual void set_origin(const point &origin) override
See widget::set_origin.
virtual void request_reduce_height(const unsigned) override
See widget::request_reduce_height.
virtual void request_reduce_width(const unsigned) override
See widget::request_reduce_width.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
void create_item(const unsigned index)
Called when an item is created.
void handle_key_left_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
void handle_key_right_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
virtual void place(const point &origin, const point &size) override
See widget::place.
bool placed_
Has the grid already been placed?
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void handle_key_down_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
void handle_key_up_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
Places the items independent of each other.
void handle_key_left_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
void set_visible_rectangle(const rect &rectangle) override
See horizontal_list::set_visible_rectangle().
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void handle_key_down_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual void request_reduce_height(const unsigned maximum_height) override
See horizontal_list::request_reduce_height.
virtual void place(const point &origin, const point &size) override
See widget::place.
void handle_key_up_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
widget * find(const std::string_view id, const bool must_be_active) override
See widget::find.
void create_item(const unsigned)
See horizontal_list::create_item().
void handle_key_right_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
virtual void set_origin(const point &origin) override
See widget::set_origin.
Places the items in a grid.
virtual void place(const point &, const point &) override
See widget::place.
bool placed_
Has the grid already been placed?
void set_visible_rectangle(const rect &) override
See horizontal_list::set_visible_rectangle().
void handle_key_up_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
void handle_key_right_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual void set_origin(const point &) override
See widget::set_origin.
void handle_key_down_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
virtual void request_reduce_width(const unsigned) override
See widget::request_reduce_width.
void handle_key_left_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual widget * find_at(const point &, const bool) override
See widget::find_at.
void create_item(const unsigned)
See horizontal_list::create_item().
virtual void request_reduce_height(const unsigned) override
See widget::request_reduce_height.
Places the items in a vertical column.
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
virtual void set_origin(const point &origin) override
See widget::set_origin.
void handle_key_up_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
void handle_key_right_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
void create_item(const unsigned index)
See horizontal_list::create_item().
virtual void request_reduce_height(const unsigned) override
See widget::request_reduce_height.
virtual void request_reduce_width(const unsigned) override
See widget::request_reduce_width.
virtual void place(const point &origin, const point &size) override
See widget::place.
void set_visible_rectangle(const rect &rectangle) override
See horizontal_list::set_visible_rectangle().
bool placed_
Has the grid already been placed?
void handle_key_left_arrow(SDL_Keymod, bool &) override
Inherited from generator_base.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
void handle_key_down_arrow(SDL_Keymod modifier, bool &handled) override
Inherited from generator_base.
Select the item, this requires the grid to contain a selectable_item.
void select(grid &grid, const bool select)
void select(grid &grid, const bool show)
Holds a 2D point.
Definition point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define FAIL_WITH_DEV_MESSAGE(message, dev_message)
#define i