The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
generator_private.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://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 #ifndef GUI_WIDGETS_GENERATOR_PRIVATE_HPP_INCLUDED
16 #define GUI_WIDGETS_GENERATOR_PRIVATE_HPP_INCLUDED
17 
19 
20 #include "asserts.hpp"
21 #include "gui/widgets/grid.hpp"
25 
26 namespace gui2
27 {
28 
29 /**
30  * Contains the policies for the tgenerator class.
31  */
32 namespace policy
33 {
34 
35 /***** ***** ***** ***** Minimum selection ***** ***** ***** *****/
36 
37 /** Contains the policy for the minimum number of selected items. */
38 namespace minimum_selection
39 {
40 
41 /** Must select at least one item. */
42 struct tone : public virtual tgenerator_
43 {
44  /**
45  * Called when an item is shown or hidden.
46  *
47  * @param index The item to show or hide.
48  * @param show If true shows the item, else hides it.
49  */
50  void set_item_shown(const unsigned index, const bool show);
51 
52  /**
53  * Called when an item is created.
54  *
55  * @param index The index of the new item.
56  */
57  void create_item(const unsigned index);
58 
59  /* Also make the overload from the generator_ visible. */
61 
62  /**
63  * Called when the users wants to deselect an item.
64  *
65  * If the item can be deselected this function should call
66  * do_deselect_item() to make the deslection happen. If not allowed no
67  * action needs to be taken.
68  *
69  * @param index The index of the item to deselect.
70  *
71  * @returns Whether the item was deselected, some
72  * actions might happen automatically upon
73  * deselecting, so if this function returns
74  * false the caller should make sure the
75  * select state is restored.
76  */
77  bool deselect_item(const unsigned index);
78 
79  /**
80  * Called just before an item is deleted.
81  *
82  * This function can if needed select another items to try to obey the
83  * policy.
84  *
85  * @param index The index of the item to be deleted.
86  */
87  void delete_item(const unsigned index);
88 };
89 
90 /** No minimum selection. */
91 struct tnone : public virtual tgenerator_
92 {
93 
94  /** See @ref minimum_selection::tone::set_item_shown(). */
95  void set_item_shown(const unsigned index, const bool show);
96 
97  /** See @ref minimum_selection::tone::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::tone::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::tone::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. */
126 namespace maximum_selection
127 {
128 
129 /** May select only one item. */
130 struct tone : public virtual tgenerator_
131 {
132  /**
133  * Called when an item is selected.
134  *
135  * This function can deselect other items to obey the policy. This
136  * function should always call do_select_item() so the new item does get
137  * selected.
138  *
139  * Since this funcion controls the maximum selection count it should only
140  * be used to select items, not to deselect them.
141  *
142  * @pre @p select == @c true
143  *
144  * @param index The item to select.
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  // select new.
154  do_select_item(index);
155  }
156  }
157 };
158 
159 /** No maximum amount of items to select. */
160 struct tinfinite : public virtual tgenerator_
161 {
162  /** See tone::select_item(). */
163  void select_item(const unsigned index, const bool select) override
164  {
165  assert(select);
166 
167  do_select_item(index);
168  }
169 };
170 
171 } // namespace maximum_selection
172 
173 /***** ***** ***** ***** Placement ***** ***** ***** *****/
174 
175 /** Controls how new items are placed. */
176 namespace placement
177 {
178 
179 /** Places the items in a horizontal row. */
180 struct thorizontal_list : public virtual tgenerator_
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 twidget::request_reduce_width. */
197  virtual void request_reduce_width(const unsigned /*maximum_width*/) override
198  {
199  /* DO NOTHING */
200  }
201 
202  /** See @ref twidget::request_reduce_height. */
203  virtual void request_reduce_height(const unsigned /*maximum_height*/)
204  override
205  {
206  /* DO NOTHING */
207  }
208 
209  /** See @ref twidget::calculate_best_size. */
210  virtual tpoint calculate_best_size() const override;
211 
212  /** See @ref twidget::place. */
213  virtual void place(const tpoint& origin, const tpoint& size) override;
214 
215  /** See @ref twidget::set_origin. */
216  virtual void set_origin(const tpoint& origin) override;
217 
218  /**
219  * Sets the visible rectangle of the generator.
220  *
221  * @param rectangle The visible rectangle.
222  */
223  void set_visible_rectangle(const SDL_Rect& rectangle);
224 
225  /** See @ref twidget::find_at. */
226  virtual twidget* find_at(const tpoint& coordinate,
227  const bool must_be_active) override;
228 
229  /** See @ref twidget::find_at. */
230  virtual const twidget* find_at(const tpoint& coordinate,
231  const bool must_be_active) const override;
232 
233  /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
234 
235  /** Inherited from tgenerator_. */
236  void handle_key_up_arrow(SDLMod /*modifier*/, bool& /*handled*/)
237  {
238  /* do nothing */
239  }
240 
241  /** Inherited from tgenerator_. */
242  void handle_key_down_arrow(SDLMod /*modifier*/, bool& /*handled*/)
243  {
244  /* do nothing */
245  }
246 
247  /** Inherited from tgenerator_. */
248  void handle_key_left_arrow(SDLMod modifier, bool& handled);
249 
250  /** Inherited from tgenerator_. */
251  void handle_key_right_arrow(SDLMod modifier, bool& handled);
252 
253 private:
254  /**
255  * Has the grid already been placed?
256  *
257  * If the grid is placed it's no problem set the location of the new
258  * item,it hasn't been placed, there's no information about its location
259  * so do nothing.
260  */
261  bool placed_;
262 };
263 
264 /** Places the items in a vertical column. */
265 struct tvertical_list : public virtual tgenerator_
266 {
267  tvertical_list();
268 
269  /** See thorizontal_list::create_item(). */
270  void create_item(const unsigned index);
271 
272  /* Also make the overload from the generator_ visible. */
274 
275  /** See @ref twidget::request_reduce_width. */
276  virtual void request_reduce_width(const unsigned /*maximum_width*/) override
277  {
278  /* DO NOTHING */
279  }
280 
281  /** See @ref twidget::request_reduce_height. */
282  virtual void request_reduce_height(const unsigned /*maximum_height*/)
283  override
284  {
285  /* DO NOTHING */
286  }
287 
288  /** See @ref twidget::calculate_best_size. */
289  virtual tpoint calculate_best_size() const override;
290 
291  /** See @ref twidget::place. */
292  virtual void place(const tpoint& origin, const tpoint& size) override;
293 
294  /** See @ref twidget::set_origin. */
295  virtual void set_origin(const tpoint& origin) override;
296 
297  /** See @ref thorizontal_list::set_visible_rectangle(). */
298  void set_visible_rectangle(const SDL_Rect& rectangle);
299 
300  /** See @ref twidget::find_at. */
301  virtual twidget* find_at(const tpoint& coordinate,
302  const bool must_be_active) override;
303 
304  /** See @ref twidget::find_at. */
305  virtual const twidget* find_at(const tpoint& coordinate,
306  const bool must_be_active) const override;
307 
308  /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
309 
310  /** Inherited from tgenerator_. */
311  void handle_key_up_arrow(SDLMod modifier, bool& handled);
312 
313  /** Inherited from tgenerator_. */
314  void handle_key_down_arrow(SDLMod modifier, bool& handled);
315 
316  /** Inherited from tgenerator_. */
317  void handle_key_left_arrow(SDLMod /*modifier*/, bool& /*handled*/)
318  { /* do nothing */
319  }
320 
321  /** Inherited from tgenerator_. */
322  void handle_key_right_arrow(SDLMod /*modifier*/, bool& /*handled*/)
323  { /* do nothing */
324  }
325 
326  // FIXME we need a delete handler as well,
327  // when deleting the last item we need to remove the placed flag.
328 
329  // FIXME we also need a clear function, called when
330  // clear is called.
331 private:
332  /**
333  * Has the grid already been placed?
334  *
335  * If the grid is placed it's no problem set the location of the new
336  * item,it hasn't been placed, there's no information about its location
337  * so do nothing.
338  */
339  bool placed_;
340 };
341 
342 /**
343  * Places the items in a grid.
344  *
345  * The items will be placed in rows and columns. It has to be determined
346  * whether the number of columns will be fixed or variable.
347  *
348  * @todo Implement.
349  */
350 struct tmatrix : public virtual tgenerator_
351 {
352  /** See thorizontal_list::create_item(). */
353  void create_item(const unsigned /*index*/)
354  {
355  ERROR_LOG(false);
356  }
357 
358  /* Also make the overload from the generator_ visible. */
360 
361  /** See @ref twidget::request_reduce_width. */
362  virtual void request_reduce_width(const unsigned /*maximum_width*/) override
363  {
364  /* DO NOTHING */
365  }
366 
367  /** See @ref twidget::request_reduce_height. */
368  virtual void request_reduce_height(const unsigned /*maximum_height*/)
369  override
370  {
371  /* DO NOTHING */
372  }
373 
374  /** See @ref twidget::calculate_best_size. */
375  virtual tpoint calculate_best_size() const override
376  {
377  ERROR_LOG(false);
378  }
379 
380  /** See @ref twidget::place. */
381  virtual void place(const tpoint& /*origin*/
382  ,
383  const tpoint& /*size*/) override
384  {
385  ERROR_LOG(false);
386  }
387 
388  /** See @ref twidget::set_origin. */
389  virtual void set_origin(const tpoint& /*origin*/) override
390  {
391  ERROR_LOG(false);
392  }
393 
394  /** See @ref thorizontal_list::set_visible_rectangle(). */
395  void set_visible_rectangle(const SDL_Rect& /*rectangle*/)
396  {
397  ERROR_LOG(false);
398  }
399 
400  /** See @ref twidget::find_at. */
401  virtual twidget* find_at(const tpoint& /*coordinate*/
402  ,
403  const bool /*must_be_active*/) override
404  {
405  ERROR_LOG(false);
406  }
407 
408  /** See @ref twidget::find_at. */
409  virtual const twidget* find_at(const tpoint& /*coordinate*/
410  ,
411  const bool /*must_be_active*/) const override
412  {
413  ERROR_LOG(false);
414  }
415 
416  /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
417 
418  /** Inherited from tgenerator_. */
420  {
421  ERROR_LOG(false);
422  }
423 
424  /** Inherited from tgenerator_. */
426  {
427  ERROR_LOG(false);
428  }
429 
430  /** Inherited from tgenerator_. */
432  {
433  ERROR_LOG(false);
434  }
435 
436  /** Inherited from tgenerator_. */
438  {
439  ERROR_LOG(false);
440  }
441 };
442 
443 /**
444  * Places the items independent of each other.
445  *
446  * This is mainly meant for when only one item is shown at the same time.
447  *
448  * @todo Implement.
449  */
450 struct tindependent : public virtual tgenerator_
451 {
452  /** See thorizontal_list::create_item(). */
453  void create_item(const unsigned /*index*/)
454  {
455  /* DO NOTHING */
456  }
457 
458  /* Also make the overload from the generator_ visible. */
460 
461  /** See @ref twidget::request_reduce_width. */
462  virtual void request_reduce_width(const unsigned maximum_width) override;
463 
464  /** See thorizontal_list::request_reduce_height. */
465  virtual void request_reduce_height(const unsigned maximum_height);
466 
467  /** See @ref twidget::calculate_best_size. */
468  virtual tpoint calculate_best_size() const override;
469 
470  /** See @ref twidget::place. */
471  virtual void place(const tpoint& origin, const tpoint& size) override;
472 
473  /** See @ref twidget::set_origin. */
474  virtual void set_origin(const tpoint& origin) override;
475 
476  /** See @ref thorizontal_list::set_visible_rectangle(). */
477  void set_visible_rectangle(const SDL_Rect& rectangle);
478 
479  /** See @ref twidget::find_at. */
480  virtual twidget* find_at(const tpoint& coordinate,
481  const bool must_be_active) override;
482 
483  /** See @ref twidget::find_at. */
484  virtual const twidget* find_at(const tpoint& coordinate,
485  const bool must_be_active) const override;
486 
487  /** See @ref twidget::find. */
488  twidget* find(const std::string& id, const bool must_be_active) override;
489 
490  /** See @ref twidget::find. */
491  const twidget* find(const std::string& id,
492  const bool must_be_active) const override;
493 
494  /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
495 
496  /** Inherited from tgenerator_. */
498  {
499  /* DO NOTHING */
500  }
501 
502  /** Inherited from tgenerator_. */
504  {
505  /* DO NOTHING */
506  }
507 
508  /** Inherited from tgenerator_. */
510  {
511  /* DO NOTHING */
512  }
513 
514  /** Inherited from tgenerator_. */
516  {
517  /* DO NOTHING */
518  }
519 };
520 
521 } // namespace placement
522 
523 /***** ***** ***** ***** Select action ***** ***** ***** *****/
524 
525 /**
526  * Contains the policy for which action to take when an item is selected or
527  * deselected.
528  */
529 namespace select_action
530 {
531 
532 /** Select the item, this requires the grid to contain a tselectable_. */
533 struct tselect : public virtual tgenerator_
534 {
535  void select(tgrid& grid, const bool select);
536 
537  /**
538  * Helper function to initialize a grid.
539  *
540  * @param grid The grid to initialize.
541  * @param data The data to initialize the parameters of
542  * the new item.
543  * @param callback The callback function to call when an item
544  * in the grid is (de)selected.
545  */
546  void init(tgrid* grid,
547  const std::map<std::string /* widget id */, string_map>& data,
548  const std::function<void(twidget&)>& callback);
549 };
550 
551 /** Show the item. */
552 struct tshow : public virtual tgenerator_
553 {
554  void select(tgrid& grid, const bool show)
555  {
558  }
559 
560  /**
561  * Helper function to initialize a grid.
562  *
563  * @param grid The grid to initialize.
564  * @param data The data to initialize the parameters of
565  * the new item. No widgets with id == "" are
566  * allowed.
567  * @param callback The callback function is not used and
568  * should be nullptr.
569  */
570  void init(tgrid* grid,
571  const std::map<std::string /* widget id */, string_map>& data,
572  const std::function<void(twidget&)>& callback);
573 };
574 
575 } // namespace select_action
576 
577 } // namespace policy
578 
579 /***** ***** ***** ***** tgenerator ***** ***** ***** *****/
580 
581 /**
582  * Basic template class to generate new items.
583  *
584  * The class is policy based so the behavior can be selected.
585  */
586 template <class minimum_selection,
587  class maximum_selection,
588  class placement,
589  class select_action>
590 class tgenerator : public minimum_selection,
591  public maximum_selection,
592  public placement,
593  public select_action
594 {
595 public:
597  : minimum_selection()
598  , maximum_selection()
599  , placement()
600  , select_action()
602  , last_selected_item_(-1)
603  , items_()
604  , order_()
605  , order_dirty_(true)
606  , order_func_()
607  {
608  }
609 
611  {
612  clear();
613  }
614 
615  /***** ***** ***** inherited ***** ****** *****/
616 
617  /** Inherited from tgenerator_. */
618  void delete_item(const unsigned index)
619  {
620  assert(index < items_.size());
621 
622  // Might be other parts of the engine want to know about the
623  // deselection, if minimum fails it gets another chance later on,
624  // since it deletes the item.
625  if(is_selected(index)) {
626  select_item(index, false);
627  }
628 
629  minimum_selection::delete_item(index);
630 
631  delete items_[index];
632  items_.erase(items_.begin() + index);
633  order_dirty_ = true;
634  }
635 
636  /** Inherited from tgenerator_. */
637  void clear()
638  {
639  for(auto item : items_)
640  {
641  delete item;
642  }
643  order_dirty_ = true;
645  }
646 
647  /** Inherited from tgenerator_. */
648  void select_item(const unsigned index, const bool select = true)
649  {
650  assert(index < items_.size());
651 
652  if(select && !is_selected(index)) {
653  maximum_selection::select_item(index, true);
655  } else if(is_selected(index)) {
656  if(!minimum_selection::deselect_item(index)) {
657  // Some items might have deseleted themselves so
658  // make sure they do get selected again.
659  select_action::select(item(index), true);
660  }
661  }
662  }
663 
664  /** Inherited from tgenerator_. */
665  bool is_selected(const unsigned index) const
666  {
667  assert(index < items_.size());
668  return (*items_[index]).selected;
669  }
670 
671  /** Inherited from tgenerator_. */
672  void set_item_shown(const unsigned index, const bool show)
673  {
674  assert(index < items_.size());
675  if(items_[index]->shown != show) {
676 
677  /*** Set the proper visible state. ***/
678  items_[index]->shown = show;
679  items_[index]
680  ->grid.set_visible(show ? twidget::tvisible::visible
682 
683  /*** Update the selection. ***/
684  minimum_selection::set_item_shown(index, show);
685  }
686  }
687 
688  /** Inherited from tgenerator_. */
689  virtual bool get_item_shown(const unsigned index) const
690  {
691  assert(index < items_.size());
692  return items_[index]->shown;
693  }
694 
695 
696  /** Inherited from tgenerator_. */
697  unsigned get_item_count() const
698  {
699  return items_.size();
700  }
701 
702  /** Inherited from tgenerator_. */
703  unsigned get_selected_item_count() const
704  {
705  return selected_item_count_;
706  }
707 
708  /** Inherited from tgenerator_. */
709  int get_selected_item() const
710  {
711 
712  if(selected_item_count_ == 0) {
713  return -1;
714  } else if(last_selected_item_ != -1
715  && last_selected_item_ < static_cast<int>(items_.size())
716  && (*items_[last_selected_item_]).selected) {
717 
718  return last_selected_item_;
719 
720  } else {
721  for(size_t i = 0; i < items_.size(); ++i) {
722  if((*items_[i]).selected) {
723  return i;
724  }
725  }
726  ERROR_LOG("No item selected.");
727  }
728  }
729 
730  /** Inherited from tgenerator_. */
731  tgrid& item(const unsigned index)
732  {
733  assert(index < items_.size());
734  return items_[index]->grid;
735  }
736 
737  /** Inherited from tgenerator_. */
738  const tgrid& item(const unsigned index) const
739  {
740  assert(index < items_.size());
741  return items_[index]->grid;
742  }
743 
744  /** Inherited from tgenerator_. */
745  tgrid& item_ordered(const unsigned index)
746  {
747  calculate_order();
748  assert(index < items_.size());
749  return items_[order_[index]]->grid;
750  }
751 
752  /** Inherited from tgenerator_. */
753  const tgrid& item_ordered(const unsigned index) const
754  {
755  calculate_order();
756  assert(index < items_.size());
757  return items_[order_[index]]->grid;
758  }
759 
760 
761  /** Inherited from tgenerator_. */
762  tgrid& create_item(const int index,
763  tbuilder_grid_const_ptr list_builder,
764  const string_map& item_data,
765  const std::function<void(twidget&)>& callback)
766  {
767  std::map<std::string, string_map> data;
768 
769  data.insert(std::make_pair("", item_data));
770  return create_item(index, list_builder, data, callback);
771  }
772 
773  /** Inherited from tgenerator_. */
775  const int index,
776  tbuilder_grid_const_ptr list_builder,
777  const std::map<std::string /* widget id */, string_map>& item_data,
778  const std::function<void(twidget&)>& callback)
779  {
780  assert(list_builder);
781  assert(index == -1 || static_cast<unsigned>(index) < items_.size());
782 
783  titem* item = new titem;
784  list_builder->build(&item->grid);
785  init(&item->grid, item_data, callback);
786 
787  const unsigned item_index = index == -1 ? items_.size() : index;
788 
789  items_.insert(items_.begin() + item_index, item);
790  order_dirty_ = true;
791  minimum_selection::create_item(item_index);
792  placement::create_item(item_index);
793  if(!is_selected(item_index)) {
794  select_action::select(item->grid, false);
795  }
796  return item->grid;
797  }
798 
799  /** Inherited from tgenerator_. */
800  virtual void create_items(
801  const int index,
802  tbuilder_grid_const_ptr list_builder,
803  const std::vector<std::map<std::string /*widget id*/, string_map> >&
804  data,
805  const std::function<void(twidget&)>& callback)
806  {
807  impl_create_items(index, list_builder, data, callback);
808  }
809 
810  /** Inherited from tgenerator_. */
811  virtual void create_items(const int index,
812  tbuilder_grid_const_ptr list_builder,
813  const std::vector<string_map>& data,
814  const std::function<void(twidget&)>& callback)
815  {
816  impl_create_items(index, list_builder, data, callback);
817  }
818 
819  /** See @ref twidget::layout_initialise. */
820  virtual void layout_initialise(const bool full_initialisation) override
821  {
822  for(auto item : items_)
823  {
825  && item->shown) {
826 
827  item->grid.layout_initialise(full_initialisation);
828  }
829  }
830  }
831 
832  /** See @ref twidget::request_reduce_width. */
833  virtual void request_reduce_width(const unsigned maximum_width) override
834  {
835  placement::request_reduce_width(maximum_width);
836  }
837 
838  /** See @ref twidget::request_reduce_height. */
839  virtual void request_reduce_height(const unsigned maximum_height) override
840  {
841  placement::request_reduce_height(maximum_height);
842  }
843 
844  /** See @ref twidget::calculate_best_size. */
845  virtual tpoint calculate_best_size() const override
846  {
847  return placement::calculate_best_size();
848  }
849 
850  /** See @ref twidget::place. */
851  virtual void place(const tpoint& origin, const tpoint& size) override
852  {
853  // Inherited, so we get useful debug info.
854  twidget::place(origin, size);
855 
856  placement::place(origin, size);
857  }
858 
859  /** See @ref twidget::set_origin. */
860  virtual void set_origin(const tpoint& origin) override
861  {
862  // Inherited.
863  twidget::set_origin(origin);
864 
865  placement::set_origin(origin);
866  }
867 
868  /** See @ref twidget::set_visible_rectangle. */
869  virtual void set_visible_rectangle(const SDL_Rect& rectangle) override
870  {
871  placement::set_visible_rectangle(rectangle);
872  }
873 
874  /** See @ref twidget::impl_draw_children. */
875  virtual void impl_draw_children(surface& frame_buffer,
876  int x_offset,
877  int y_offset) override
878  {
879  assert(this->get_visible() == twidget::tvisible::visible);
880  calculate_order();
881  for(auto index : order_)
882  {
883  titem* item = items_[index];
885  && item->shown) {
886 
887  item->grid.draw_children(frame_buffer, x_offset, y_offset);
888  }
889  }
890  }
891 
892  /** See @ref twidget::child_populate_dirty_list. */
893  virtual void
895  const std::vector<twidget*>& call_stack) override
896  {
897  for(auto item : items_)
898  {
899  std::vector<twidget*> child_call_stack = call_stack;
900  item->grid.populate_dirty_list(caller, child_call_stack);
901  }
902  }
903 
904  /** See @ref twidget::find_at. */
905  virtual twidget* find_at(const tpoint& coordinate,
906  const bool must_be_active) override
907  {
908  return placement::find_at(coordinate, must_be_active);
909  }
910 
911  /** See @ref twidget::find_at. */
912  virtual const twidget* find_at(const tpoint& coordinate,
913  const bool must_be_active) const override
914  {
915  return placement::find_at(coordinate, must_be_active);
916  }
917 
918  /** See @ref twidget::disable_click_dismiss. */
919  bool disable_click_dismiss() const override
920  {
921  for(auto item : items_)
922  {
923  if(item->grid.disable_click_dismiss()) {
924  return true;
925  }
926  }
927  return false;
928  }
929 
930  /**
931  * See @ref twidget::create_walker.
932  *
933  * @todo Implement properly.
934  */
935  virtual iterator::twalker_* create_walker() override
936  {
937  return nullptr;
938  }
939 
940  /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
941 
942  /** Inherited from tgenerator_. */
943  void handle_key_up_arrow(SDLMod modifier, bool& handled)
944  {
945  placement::handle_key_up_arrow(modifier, handled);
946  }
947 
948  /** Inherited from tgenerator_. */
949  void handle_key_down_arrow(SDLMod modifier, bool& handled)
950  {
951  placement::handle_key_down_arrow(modifier, handled);
952  }
953 
954  /** Inherited from tgenerator_. */
955  void handle_key_left_arrow(SDLMod modifier, bool& handled)
956  {
957  placement::handle_key_left_arrow(modifier, handled);
958  }
959 
960  /** Inherited from tgenerator_. */
961  void handle_key_right_arrow(SDLMod modifier, bool& handled)
962  {
963  placement::handle_key_right_arrow(modifier, handled);
964  }
965 
966 protected:
967  /** Inherited from tgenerator_. */
968  void do_select_item(const unsigned index) // fixme rename to impl
969  {
970  assert(index < items_.size());
971 
973  set_item_selected(index, true);
974  }
975 
976  /** Inherited from tgenerator_. */
977  void do_deselect_item(const unsigned index)
978  {
979  assert(index < items_.size());
980 
982  set_item_selected(index, false);
983  }
984 
985 private:
986  /** Definition of an item. */
987  struct titem
988  {
989 
990  titem() : grid(), selected(false), shown(true), ordered_index(0)
991  {
992  }
993 
994  /** The grid containing the widgets. */
996 
997  /** Is the item selected or not. */
998  bool selected;
999 
1000  /**
1001  * Is the row shown or not.
1002  *
1003  * This flag is used the help to set the visible flag, it's preferred to
1004  * test this flag for external functions.
1005  *
1006  * @todo functions now test for visible and shown, that can use some
1007  * polishing.
1008  */
1009  bool shown;
1010 
1012  };
1013 
1014  /** The number of selected items. */
1016 
1017  /** The last item selected. */
1019 
1020  /** The items in the generator. */
1021  typedef std::vector<titem*> titems;
1022  titems items_;
1023 
1024  /** the elements of order_ are indexes to items_ */
1025  mutable std::vector<size_t> order_;
1026  /** whether need to recalculate order_dirty_ */
1027  mutable bool order_dirty_;
1028 
1029  typedef std::function<bool (unsigned, unsigned)> torder_func;
1030  torder_func order_func_;
1031 
1032 
1033  virtual void set_order(const torder_func& order) override
1034  {
1035  order_func_ = order;
1036  order_dirty_ = true;
1037  this->set_is_dirty(true);
1038  }
1039 
1041  {
1042  const torder_func& order_func_;
1043  const titems& items_;
1044 
1045  calculate_order_helper(const torder_func& order_func, const titems& items)
1046  : order_func_(order_func)
1047  , items_(items)
1048  {
1049  }
1050 
1051  bool operator()(size_t a, size_t b)
1052  {
1053  return order_func_(a, b);
1054  }
1055  };
1056 
1057  virtual unsigned get_ordered_index(unsigned index) const
1058  {
1059  assert(index < items_.size());
1060  calculate_order();
1061  return items_[index]->ordered_index;
1062  }
1063 
1064  virtual unsigned get_item_at_ordered(unsigned index_ordered) const
1065  {
1066  assert(index_ordered < items_.size());
1067  calculate_order();
1068  return order_[index_ordered];
1069  }
1070 
1071  void calculate_order() const
1072  {
1073  if(order_dirty_) {
1074  if(order_.size() != items_.size()) {
1075  order_.resize(items_.size());
1076  for(size_t i = 0; i < items_.size(); ++i) {
1077  order_[i] = i;
1078  }
1079  }
1080  if(order_func_) {
1081  std::stable_sort(order_.begin(), order_.end(), calculate_order_helper(order_func_, items_));
1082  }
1083  for(size_t i = 0; i < order_.size(); ++i) {
1084  items_[order_[i]]->ordered_index = i;
1085  }
1086 
1087  order_dirty_ = false;
1088  }
1089  else {
1090  assert(order_.size() == items_.size());
1091  }
1092  }
1093  /**
1094  * Sets the selected state of an item.
1095  *
1096  * @param index The item to modify.
1097  * @param selected Select or deselect.
1098  */
1099  void set_item_selected(const unsigned index, const bool selected)
1100  {
1101  assert(index < items_.size());
1102 
1103  (*items_[index]).selected = selected;
1104  select_action::select((*items_[index]).grid, selected);
1105  }
1106 
1107  /**
1108  * Helper function for create_items().
1109  *
1110  * @tparam T Type of the data, this should be one of the
1111  * valid parameters for create_item().
1112  *
1113  * @param index The item before which to add the new item,
1114  * 0 == begin, -1 == end.
1115  * @param list_builder A grid builder that's will build the
1116  * contents of the new item.
1117  * @param data The data to initialize the parameters of
1118  * the new item.
1119  * @param callback The callback function to call when an item
1120  * in the grid is (de)selected.
1121  */
1122  template <class T>
1123  void impl_create_items(const int index,
1124  tbuilder_grid_const_ptr list_builder,
1125  const std::vector<T>& data,
1126  const std::function<void(twidget&)>& callback)
1127  {
1128  int i = index;
1129  for(const auto & item_data : data)
1130  {
1131  create_item(i, list_builder, item_data, callback);
1132  if(i != -1) {
1133  ++i;
1134  }
1135  }
1136  }
1137 
1138  /**
1139  * Helper function to initialize a grid.
1140  *
1141  * The actual part is implemented in select_action, see those
1142  * implementations for more information.
1143  *
1144  * @param grid The grid to initialize.
1145  * @param data The data to initialize the parameters of
1146  * the new item.
1147  * @param callback The callback function to call when an item
1148  * in the grid is (de)selected.
1149  */
1150  void init(tgrid* grid,
1151  const std::map<std::string /* widget id */, string_map>& data,
1152  const std::function<void(twidget&)>& callback)
1153  {
1154  assert(grid);
1155  grid->set_parent(this);
1156 
1157  select_action::init(grid, data, callback);
1158  }
1159 };
1160 
1161 } // namespace gui2
1162 
1163 #endif
bool disable_click_dismiss() const override
See twidget::disable_click_dismiss.
void impl_create_items(const int index, tbuilder_grid_const_ptr list_builder, const std::vector< T > &data, const std::function< void(twidget &)> &callback)
Helper function for create_items().
void select(tgrid &grid, const bool select)
Definition: generator.cpp:648
Definition of an item.
void handle_key_left_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
Abstract base class for the generator.
Definition: generator.hpp:41
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
virtual void set_origin(const tpoint &) override
See twidget::set_origin.
#define SDLMod
Definition: compat.hpp:30
void handle_key_left_arrow(SDLMod, bool &)
Inherited from tgenerator_.
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
const tgrid & item_ordered(const unsigned index) const
Inherited from tgenerator_.
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:2972
void handle_key_up_arrow(SDLMod, bool &)
Inherited from tgenerator_.
void set_visible_rectangle(const SDL_Rect &)
See thorizontal_list::set_visible_rectangle().
virtual unsigned get_selected_item_count() const =0
Returns the number of selected items.
void set_parent(twidget *parent)
Definition: widget.cpp:150
void create_item(const unsigned)
See thorizontal_list::create_item().
Select the item, this requires the grid to contain a tselectable_.
virtual void request_reduce_width(const unsigned maximum_width) override
See twidget::request_reduce_width.
Definition: generator.cpp:505
virtual iterator::twalker_ * create_walker() override
See twidget::create_walker.
tgrid & create_item(const int index, tbuilder_grid_const_ptr list_builder, const string_map &item_data, const std::function< void(twidget &)> &callback)
Inherited from tgenerator_.
virtual unsigned get_ordered_index(unsigned index) const
Must select at least one item.
void handle_key_down_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See twidget::set_visible_rectangle.
void init(tgrid *grid, const std::map< std::string, string_map > &data, const std::function< void(twidget &)> &callback)
Helper function to initialize a grid.
Base container class.
Definition: grid.hpp:29
unsigned get_selected_item_count() const
Inherited from tgenerator_.
virtual int get_selected_item() const =0
Returns the selected item.
tvisible::scoped_enum get_visible() const
Definition: widget.cpp:471
void init(tgrid *grid, const std::map< std::string, string_map > &data, const std::function< void(twidget &)> &callback)
Helper function to initialize a grid.
Definition: generator.cpp:657
void handle_key_up_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
Definition: generator.cpp:456
void set_item_shown(const unsigned index, const bool show)
Inherited from tgenerator_.
tgrid grid
The grid containing the widgets.
bool disable_click_dismiss() const override
See twidget::disable_click_dismiss.
Definition: grid.cpp:638
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
Definition: generator.cpp:178
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Definition: generator.cpp:344
#define ERROR_LOG(a)
Definition: asserts.hpp:42
tgrid & item_ordered(const unsigned index)
Inherited from tgenerator_.
tgrid & create_item(const int index, tbuilder_grid_const_ptr list_builder, const std::map< std::string, string_map > &item_data, const std::function< void(twidget &)> &callback)
Inherited from tgenerator_.
const std::vector< std::string > items
virtual const twidget * find_at(const tpoint &, const bool) const override
See twidget::find_at.
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
std::vector< size_t > order_
the elements of order_ are indexes to items_
virtual bool get_item_shown(const unsigned index) const
Inherited from tgenerator_.
calculate_order_helper(const torder_func &order_func, const titems &items)
bool order_dirty_
whether need to recalculate order_dirty_
void select_item(const unsigned index, const bool select) override
See tone::select_item().
virtual void layout_initialise(const bool full_initialisation) override
See twidget::layout_initialise.
void set_visible_rectangle(const SDL_Rect &rectangle)
See thorizontal_list::set_visible_rectangle().
Definition: generator.cpp:394
void set_visible_rectangle(const SDL_Rect &rectangle)
Sets the visible rectangle of the generator.
Definition: generator.cpp:195
void handle_key_up_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
unsigned selected_item_count_
The number of selected items.
int last_selected_item_
The last item selected.
void handle_key_left_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
Definition: generator.cpp:256
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
virtual void request_reduce_width(const unsigned) override
See twidget::request_reduce_width.
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
void set_item_selected(const unsigned index, const bool selected)
Sets the selected state of an item.
The user set the widget invisible, that means:
Definition: widget.hpp:103
bool placed_
Has the grid already been placed?
bool is_selected(const unsigned index) const
Inherited from tgenerator_.
void select_item(const unsigned index, const bool select) override
Called when an item is selected.
bool deselect_item(const unsigned index)
See minimum_selection::tone::deselect_item()
void handle_key_right_arrow(SDLMod, bool &)
Inherited from tgenerator_.
void delete_item(const unsigned index)
Called just before an item is deleted.
Definition: generator.cpp:66
virtual twidget * find_at(const tpoint &coordinate, const bool must_be_active) override
See twidget::find_at.
Definition: generator.cpp:572
void delete_item(const unsigned index)
See minimum_selection::tone::delete_item()
void create_item(const unsigned)
See minimum_selection::tone::create_item()
virtual void create_items(const int index, tbuilder_grid_const_ptr list_builder, const std::vector< std::map< std::string, string_map > > &data, const std::function< void(twidget &)> &callback)
Inherited from tgenerator_.
void create_item(const unsigned index)
See thorizontal_list::create_item().
Definition: generator.cpp:309
void handle_key_up_arrow(SDLMod, bool &)
Inherited from tgenerator_.
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
Definition: generator.cpp:557
virtual bool is_selected(const unsigned index) const =0
Returns whether the item is selected.
void handle_key_right_arrow(SDLMod, bool &)
Inherited from tgenerator_.
void populate_dirty_list(twindow &caller, std::vector< twidget * > &call_stack)
Adds a widget to the dirty list if it is dirty.
Definition: widget.cpp:386
virtual twidget * find_at(const tpoint &, const bool) override
See twidget::find_at.
virtual void child_populate_dirty_list(twindow &caller, const std::vector< twidget * > &call_stack) override
See twidget::child_populate_dirty_list.
std::string selected
Definition: game_config.cpp:84
virtual void request_reduce_height(const unsigned) override
See twidget::request_reduce_height.
virtual tgrid & create_item(const int index, tbuilder_grid_const_ptr list_builder, const string_map &item_data, const std::function< void(twidget &)> &callback)=0
Creates a new item.
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
Basic template class to generate new items.
virtual void place(const tpoint &, const tpoint &) override
See twidget::place.
void handle_key_right_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
Definition: generator.cpp:277
bool deselect_item(const unsigned index)
Called when the users wants to deselect an item.
Definition: generator.cpp:57
bool shown
Is the row shown or not.
void draw_children(surface &frame_buffer, int x_offset, int y_offset)
Draws the children of a widget.
Definition: widget.cpp:356
void handle_key_right_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
virtual unsigned get_item_at_ordered(unsigned index_ordered) const
The user sets the widget hidden, that means:
Definition: widget.hpp:91
virtual twidget * find_at(const tpoint &coordinate, const bool must_be_active) override
See twidget::find_at.
Definition: generator.cpp:210
virtual void request_reduce_height(const unsigned maximum_height) override
See twidget::request_reduce_height.
virtual void request_reduce_height(const unsigned) override
See twidget::request_reduce_height.
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Definition: generator.cpp:548
virtual void place(const tpoint &origin, const tpoint &size)
Places the widget.
Definition: widget.cpp:233
void init()
Initializes the gui subsystems.
Definition: registry.cpp:482
tgrid & item(const unsigned index)
Inherited from tgenerator_.
std::map< std::string, t_string > string_map
Definition: generator.hpp:23
std::vector< titem * > titems
The items in the generator.
virtual twidget * find_at(const tpoint &coordinate, const bool must_be_active) override
See twidget::find_at.
void show(CVideo &video, const std::string &window_id, const t_string &message, const tpoint &mouse)
Shows a tip.
Definition: tip.cpp:133
void delete_item(const unsigned index)
Inherited from tgenerator_.
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Definition: generator.cpp:145
virtual void set_order(const torder_func &order) override
void handle_key_right_arrow(SDLMod, bool &)
Inherited from tgenerator_.
virtual const twidget * find_at(const tpoint &coordinate, const bool must_be_active) const override
See twidget::find_at.
void create_item(const unsigned index)
Called when an item is created.
Definition: generator.cpp:110
int get_selected_item() const
Inherited from tgenerator_.
void init(tgrid *grid, const std::map< std::string, string_map > &data, const std::function< void(twidget &)> &callback)
Helper function to initialize a grid.
Definition: generator.cpp:695
virtual void request_reduce_height(const unsigned) override
See twidget::request_reduce_height.
The user sets the widget visible, that means:
Definition: widget.hpp:79
virtual twidget * find_at(const tpoint &coordinate, const bool must_be_active) override
See twidget::find_at.
Definition: generator.cpp:409
GLuint index
Definition: glew.h:1782
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
Definition: generator.cpp:319
No maximum amount of items to select.
bool selected
Is the item selected or not.
Places the items in a horizontal row.
std::function< bool(unsigned, unsigned)> torder_func
size_t i
Definition: function.cpp:1057
Holds a 2D point.
Definition: point.hpp:24
Places the items independent of each other.
void do_select_item(const unsigned index)
Inherited from tgenerator_.
const tgrid & item(const unsigned index) const
Inherited from tgenerator_.
void handle_key_left_arrow(SDLMod, bool &)
Inherited from tgenerator_.
void handle_key_up_arrow(SDLMod, bool &)
Inherited from tgenerator_.
Places the items in a vertical column.
virtual void do_select_item(const unsigned index)=0
Selects a not selected item.
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
Definition: generator.cpp:523
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
void set_item_shown(const unsigned index, const bool show)
Called when an item is shown or hidden.
Definition: generator.cpp:33
void calculate_order() const
GLsizeiptr size
Definition: glew.h:1649
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
Definition: generator.cpp:120
void handle_key_down_arrow(SDLMod modifier, bool &handled)
Inherited from tgenerator_.
Definition: generator.cpp:477
unsigned get_item_count() const
Inherited from tgenerator_.
virtual void set_origin(const tpoint &origin)
Sets the origin of the widget.
Definition: widget.cpp:216
void create_item(const unsigned index)
Called when an item is created.
Definition: generator.cpp:50
virtual void request_reduce_width(const unsigned) override
See twidget::request_reduce_width.
void handle_key_down_arrow(SDLMod, bool &)
Inherited from tgenerator_.
Base class for all widgets.
Definition: widget.hpp:49
virtual void request_reduce_width(const unsigned maximum_width) override
See twidget::request_reduce_width.
void create_item(const unsigned)
See thorizontal_list::create_item().
virtual void create_items(const int index, tbuilder_grid_const_ptr list_builder, const std::vector< string_map > &data, const std::function< void(twidget &)> &callback)
Inherited from tgenerator_.
virtual void request_reduce_height(const unsigned maximum_height)
See thorizontal_list::request_reduce_height.
Definition: generator.cpp:514
virtual void do_deselect_item(const unsigned index)=0
Deselects a selected item.
virtual void layout_initialise(const bool full_initialisation) override
See twidget::layout_initialise.
Definition: grid.cpp:191
virtual void request_reduce_width(const unsigned) override
See twidget::request_reduce_width.
void handle_key_down_arrow(SDLMod, bool &)
Inherited from tgenerator_.
The walker abstract base class.
Definition: walker.hpp:27
bool placed_
Has the grid already been placed?
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
virtual void impl_draw_children(surface &frame_buffer, int x_offset, int y_offset) override
See twidget::impl_draw_children.
void set_visible_rectangle(const SDL_Rect &rectangle)
See thorizontal_list::set_visible_rectangle().
Definition: generator.cpp:626
void set_item_shown(const unsigned index, const bool show)
See minimum_selection::tone::set_item_shown().
Definition: generator.cpp:92
void set_visible(const tvisible::scoped_enum visible)
Definition: widget.cpp:445
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void handle_key_left_arrow(SDLMod, bool &)
Inherited from tgenerator_.
twidget * find(const std::string &id, const bool must_be_active) override
See twidget::find.
Definition: generator.cpp:600
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
Definition: generator.cpp:377
void handle_key_down_arrow(SDLMod, bool &)
Inherited from tgenerator_.
void clear()
Inherited from tgenerator_.
void select(tgrid &grid, const bool show)
void do_deselect_item(const unsigned index)
Inherited from tgenerator_.
void select_item(const unsigned index, const bool select=true)
Inherited from tgenerator_.
Places the items in a grid.