The Battle for Wesnoth  1.17.0-dev
tree_view_node.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "gettext.hpp"
22 #include "gui/core/log.hpp"
26 #include "sdl/rect.hpp"
27 #include <functional>
28 
29 #define LOG_SCOPE_HEADER get_control_type() + " [" + get_tree_view().id() + "] " + __func__
30 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
31 
32 namespace gui2
33 {
34 tree_view_node::tree_view_node(const std::string& id,
35  tree_view_node* parent_node,
36  tree_view& parent_tree_view,
37  const std::map<std::string /* widget id */, string_map>& data)
38  : widget()
39  , parent_node_(parent_node)
40  , tree_view_(&parent_tree_view)
41  , grid_()
42  , children_()
43  , toggle_(nullptr)
44  , label_(nullptr)
45  , unfolded_(false)
46 {
47  grid_.set_parent(this);
48  set_parent(&parent_tree_view);
49 
50  if(id == "root") {
51  unfolded_ = true;
52  return;
53  }
54 
55  for(const auto& node_definition : get_tree_view().get_node_definitions()) {
56  if(node_definition.id != id) {
57  continue;
58  }
59 
60  node_definition.builder->build(&grid_);
61  init_grid(&grid_, data);
62 
65  }
66 
67  if(node_definition.unfolded) {
68  unfolded_ = true;
69  }
70 
71  widget* toggle_widget = grid_.find("tree_view_node_toggle", false);
72  toggle_ = dynamic_cast<selectable_item*>(toggle_widget);
73 
74  if(toggle_) {
76 
78  std::bind(&tree_view_node::signal_handler_left_button_click, this, std::placeholders::_2));
79 
81  std::bind(&tree_view_node::signal_handler_left_button_click, this, std::placeholders::_2),
83 
84  if(unfolded_) {
85  toggle_->set_value(1);
86  }
87  }
88 
89  widget* label_widget = grid_.find("tree_view_node_label", false);
90  label_ = dynamic_cast<selectable_item*>(label_widget);
91 
92  if(label_) {
94  std::bind(&tree_view_node::signal_handler_label_left_button_click, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
96 
98  std::bind(&tree_view_node::signal_handler_label_left_button_click, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
100 
102  get_tree_view().selected_item_ = this;
103  label_->set_value(true);
104  }
105  }
106 
107  return;
108  }
109 
110  // Only reached if no matching node definition was found in the above loop
111  FAIL_WITH_DEV_MESSAGE(_("Unknown builder id for tree view node."), id);
112 }
113 
115 {
116  if(tree_view_ && get_tree_view().selected_item_ == this) {
117  get_tree_view().selected_item_ = nullptr;
118  }
119 }
120 
122 {
123  tree_view_ = nullptr;
124  for(auto& child : children_) {
125  child->clear_before_destruct();
126  }
127 }
128 
129 tree_view_node& tree_view_node::add_child_impl(std::shared_ptr<tree_view_node>&& new_node, const int index)
130 {
131  auto itor = children_.end();
132 
133  if(static_cast<std::size_t>(index) < children_.size()) {
134  itor = children_.begin() + index;
135  }
136 
137  tree_view_node& node = **children_.insert(itor, std::move(new_node));
138 
139  // NOTE: we currently don't support moving nodes between different trees, so this
140  // just ensures that wasn't tried. Remove this if we implement support for that.
141  assert(node.tree_view_ == tree_view_);
142 
143  // Safety check. Might only fail if someone accidentally removed the parent_node_
144  // setter in add_child().
145  assert(node.parent_node_ == this);
146 
147  if(is_folded() /*|| is_root_node()*/) {
148  return node;
149  }
150 
151  if(get_tree_view().get_size() == point()) {
152  return node;
153  }
154 
155  assert(get_tree_view().content_grid());
156  const point current_size = get_tree_view().content_grid()->get_size();
157 
158  // Calculate width modification.
159  // This increases tree width if the width of the new node is greater than the current width.
160  point best_size = node.get_best_size();
162 
163  const int width_modification = best_size.x > current_size.x
164  ? best_size.x - current_size.x
165  : 0;
166 
167  // Calculate height modification.
168  // For this, we only increase height if the best size of the tree (that is, the size with the new node)
169  // is larger than its current size. This prevents the scrollbar being reserved even when there's obviously
170  // enough visual space.
171 
172  // Throw away cached best size to force a recalculation.
174 
175  const point tree_best_size = get_tree_view().get_best_size();
176 
177  const int height_modification = tree_best_size.y > current_size.y && get_tree_view().layout_size() == point()
178  ? tree_best_size.y - current_size.y
179  : 0;
180 
181  assert(height_modification >= 0);
182 
183  // Request new size.
184  get_tree_view().resize_content(width_modification, height_modification, -1, node.calculate_ypos());
185 
186  return node;
187 }
188 
189 std::map<std::string, std::shared_ptr<gui2::tree_view_node>> tree_view_node::replace_children(const std::string& id, const std::map<std::string, std::map<std::string /* widget id */, string_map>>& data)
190 {
191  std::map<std::string, std::shared_ptr<gui2::tree_view_node>> nodes;
192  clear();
193 
194  if(data.size() == 0)
195  {
196  return nodes;
197  }
198 
199  int width_modification = 0;
200 
201  for(const auto& d : data)
202  {
203  std::shared_ptr<gui2::tree_view_node> new_node = std::make_shared<tree_view_node>(id, this, get_tree_view(), d.second);
204  std::shared_ptr<gui2::tree_view_node> node = *children_.insert(children_.end(), std::move(new_node));
205 
206  // NOTE: we currently don't support moving nodes between different trees, so this
207  // just ensures that wasn't tried. Remove this if we implement support for that.
208  assert(node->tree_view_ == tree_view_);
209 
210  // Safety check. Might only fail if someone accidentally removed the parent_node_ setter in add_child().
211  assert(node->parent_node_ == this);
212 
213  nodes[d.first] = node;
214 
215  if(is_folded()) {
216  continue;
217  }
218 
219  assert(get_tree_view().content_grid());
220  const point current_size = get_tree_view().content_grid()->get_size();
221 
222  // Calculate width modification.
223  // This increases tree width if the width of the new node is greater than the current width.
224  int best_size = node->get_best_size().x;
226 
227  int new_width = best_size > current_size.x
228  ? best_size - current_size.x
229  : 0;
230 
231  if(new_width > width_modification)
232  {
233  width_modification = new_width;
234  }
235  }
236 
237  if(is_folded()) {
238  return nodes;
239  }
240 
241  // Calculate height modification.
242  // For this, we only increase height if the best size of the tree (that is, the size with the new node)
243  // is larger than its current size. This prevents the scrollbar being reserved even when there's obviously
244  // enough visual space.
245 
246  // Throw away cached best size to force a recalculation.
248 
249  const point current_size = get_tree_view().content_grid()->get_size();
250  const point tree_best_size = get_tree_view().get_best_size();
251 
252  const int height_modification = tree_best_size.y > current_size.y && get_tree_view().layout_size() == point()
253  ? tree_best_size.y - current_size.y
254  : 0;
255 
256  assert(height_modification >= 0);
257 
258  // Request new size.
259  auto& last_node = children_.at(children_.size()-1);
260  get_tree_view().resize_content(width_modification, height_modification, -1, last_node->calculate_ypos());
261 
262  return nodes;
263 }
264 
266 {
267  unsigned level = 0;
268 
269  const tree_view_node* node = this;
270  while(!node->is_root_node()) {
271  node = &node->parent_node();
272  ++level;
273  }
274 
275  return level;
276 }
277 
279 {
280  assert(!is_root_node());
281  return *parent_node_;
282 }
283 
285 {
286  assert(!is_root_node());
287  return *parent_node_;
288 }
289 
290 void tree_view_node::request_reduce_width(const unsigned /*maximum_width*/)
291 {
292  /* DO NOTHING */
293 }
294 
295 void tree_view_node::fold(const bool recursive)
296 {
297  if(!is_folded()) {
298  fold_internal();
299  if(toggle_) {
300  toggle_->set_value(false);
301  }
302  }
303 
304  if(recursive) {
305  for(auto& child_node : children_) {
306  child_node->fold(true);
307  }
308  }
309 }
310 
311 void tree_view_node::unfold(const bool recursive)
312 {
313  if(is_folded()) {
314  unfold_internal();
315  if(toggle_) {
316  toggle_->set_value(true);
317  }
318  }
319 
320  if(recursive) {
321  for(auto& child_node : children_) {
322  child_node->unfold(true);
323  }
324  }
325 }
326 
328 {
329  const point current_size(get_current_size().x, get_unfolded_size().y);
330  const point new_size = get_folded_size();
331 
332  const int width_modification = std::max(0, new_size.x - current_size.x);
333  const int height_modification = new_size.y - current_size.y;
334  assert(height_modification <= 0);
335 
336  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
337  unfolded_ = false;
338 }
339 
341 {
342  const point current_size(get_current_size().x, get_folded_size().y);
343  const point new_size = get_unfolded_size();
344 
345  const int width_modification = std::max(0, new_size.x - current_size.x);
346  const int height_modification = new_size.y - current_size.y;
347  assert(height_modification >= 0);
348 
349  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
350  unfolded_ = true;
351 }
352 
354 {
355  /** @todo Also try to find the optimal width. */
356  int height_reduction = 0;
357 
358  if(!is_folded()) {
359  for(const auto& node : children_) {
360  height_reduction += node->get_current_size().y;
361  }
362  }
363 
364  children_.clear();
365 
366  if(height_reduction == 0) {
367  return;
368  }
369 
370  get_tree_view().resize_content(0, -height_reduction, -1, calculate_ypos());
371 }
372 
374 {
375 private:
376  template<class W, class It>
377  static W* find_at_aux(It begin, It end, const point& coordinate, const bool must_be_active)
378  {
379  for(It it = begin; it != end; ++it) {
380  if(W* widget = (*it)->find_at(coordinate, must_be_active)) {
381  return widget;
382  }
383  }
384 
385  return nullptr;
386  }
387 
388 public:
389  template<class W>
391  const point& coordinate,
392  const bool must_be_active)
393  {
394  if(W* widget = tree_view_node.grid_.find_at(coordinate, must_be_active)) {
395  return widget;
396  }
397 
398  if(tree_view_node.is_folded()) {
399  return nullptr;
400  }
401 
402  return find_at_aux<W>(
403  tree_view_node.children_.begin(), tree_view_node.children_.end(), coordinate, must_be_active);
404  }
405 };
406 
407 widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active)
408 {
409  return tree_view_node_implementation::find_at<widget>(*this, coordinate, must_be_active);
410 }
411 
412 const widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active) const
413 {
414  return tree_view_node_implementation::find_at<const widget>(*this, coordinate, must_be_active);
415 }
416 
417 widget* tree_view_node::find(const std::string& id, const bool must_be_active)
418 {
419  widget* result = widget::find(id, must_be_active);
420  if(result) {
421  return result;
422  }
423 
424  result = grid_.find(id, must_be_active);
425  if(result) {
426  return result;
427  }
428 
429  for(auto& child : children_) {
430  result = child->find(id, must_be_active);
431  if(result) {
432  return result;
433  }
434  }
435 
436  return nullptr;
437 }
438 
439 const widget* tree_view_node::find(const std::string& id, const bool must_be_active) const
440 {
441  const widget* result = widget::find(id, must_be_active);
442  if(result) {
443  return result;
444  }
445 
446  result = grid_.find(id, must_be_active);
447  if(result) {
448  return result;
449  }
450 
451  for(const auto& child : children_) {
452  result = child->find(id, must_be_active);
453  if(result) {
454  return result;
455  }
456  }
457 
458  return nullptr;
459 }
460 
461 void tree_view_node::impl_populate_dirty_list(window& caller, const std::vector<widget*>& call_stack)
462 {
463  std::vector<widget*> my_call_stack = call_stack;
464  grid_.populate_dirty_list(caller, my_call_stack);
465 
466  if(is_folded()) {
467  return;
468  }
469 
470  for(auto& node : children_) {
471  std::vector<widget*> child_call_stack = call_stack;
472  node->impl_populate_dirty_list(caller, child_call_stack);
473  }
474 }
475 
477 {
478  return calculate_best_size(-1, get_tree_view().indentation_step_size_);
479 }
480 
482 {
483  return true;
484 }
485 
486 point tree_view_node::get_current_size(bool assume_visible) const
487 {
488  if(!assume_visible && parent_node_ && parent_node_->is_folded()) {
489  return point();
490  }
491 
493  if(is_folded()) {
494  return size;
495  }
496 
497  for(const auto& node : children_) {
498  if(node->grid_.get_visible() == widget::visibility::invisible) {
499  continue;
500  }
501 
502  point node_size = node->get_current_size();
503 
504  size.y += node_size.y;
505  size.x = std::max(size.x, node_size.x);
506  }
507 
508  return size;
509 }
510 
512 {
514  if(get_indentation_level() > 1) {
516  }
517 
518  return size;
519 }
520 
522 {
524  if(get_indentation_level() > 1) {
526  }
527 
528  for(const auto& node : children_) {
529  if(node->grid_.get_visible() == widget::visibility::invisible) {
530  continue;
531  }
532 
533  point node_size = node->get_current_size(true);
534 
535  size.y += node_size.y;
536  size.x = std::max(size.x, node_size.x);
537  }
538 
539  return size;
540 }
541 
542 point tree_view_node::calculate_best_size(const int indentation_level, const unsigned indentation_step_size) const
543 {
545 
546  point best_size = grid_.get_best_size();
547  if(indentation_level > 0) {
548  best_size.x += indentation_level * indentation_step_size;
549  }
550 
551  DBG_GUI_L << LOG_HEADER << " own grid best size " << best_size << ".\n";
552 
553  for(const auto& node : children_) {
554  if(node->grid_.get_visible() == widget::visibility::invisible) {
555  continue;
556  }
557 
558  const point node_size = node->calculate_best_size(indentation_level + 1, indentation_step_size);
559 
560  if(!is_folded()) {
561  best_size.y += node_size.y;
562  }
563 
564  best_size.x = std::max(best_size.x, node_size.x);
565  }
566 
567  DBG_GUI_L << LOG_HEADER << " result " << best_size << ".\n";
568  return best_size;
569 }
570 
572 {
573  // Inherited.
574  widget::set_origin(origin);
575 
576  // Using layout_children seems to fail.
577  place(get_tree_view().indentation_step_size_, origin, get_size().x);
578 }
579 
580 void tree_view_node::place(const point& origin, const point& size)
581 {
582  // Inherited.
583  widget::place(origin, size);
584 
586 }
587 
588 unsigned tree_view_node::place(const unsigned indentation_step_size, point origin, unsigned width)
589 {
591  DBG_GUI_L << LOG_HEADER << " origin " << origin << ".\n";
592 
593  const unsigned offset = origin.y;
594  point best_size = grid_.get_best_size();
595  best_size.x = width;
596 
597  grid_.place(origin, best_size);
598 
599  if(!is_root_node()) {
600  origin.x += indentation_step_size;
601  assert(width >= indentation_step_size);
602  width -= indentation_step_size;
603  }
604 
605  origin.y += best_size.y;
606 
607  if(is_folded()) {
608  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
609  return origin.y - offset;
610  }
611 
612  DBG_GUI_L << LOG_HEADER << " set children.\n";
613  for(auto& node : children_) {
614  origin.y += node->place(indentation_step_size, origin, width);
615  }
616 
617  // Inherited.
618  widget::set_size(point(width, origin.y - offset));
619 
620  DBG_GUI_L << LOG_HEADER << " result " << (origin.y - offset) << ".\n";
621  return origin.y - offset;
622 }
623 
624 void tree_view_node::set_visible_rectangle(const SDL_Rect& rectangle)
625 {
627  DBG_GUI_L << LOG_HEADER << " rectangle " << rectangle << ".\n";
628  grid_.set_visible_rectangle(rectangle);
629 
630  if(is_folded()) {
631  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
632  return;
633  }
634 
635  for(auto& node : children_) {
636  node->set_visible_rectangle(rectangle);
637  }
638 }
639 
641  int x_offset,
642  int y_offset)
643 {
644  grid_.draw_children(frame_buffer, x_offset, y_offset);
645 
646  if(is_folded()) {
647  return;
648  }
649 
650  for(auto& node : children_) {
651  node->impl_draw_children(frame_buffer, x_offset, y_offset);
652  }
653 }
654 
656 {
657  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
658 
659  /**
660  * @todo Rewrite this sizing code for the folding/unfolding.
661  *
662  * The code works but feels rather hacky, so better move back to the
663  * drawingboard for 1.9.
664  */
665  const bool unfolded_new = toggle_->get_value_bool();
666  if(unfolded_ == unfolded_new) {
667  return;
668  }
669 
670  unfolded_ = unfolded_new;
672 
674 }
675 
677 {
678  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
679 
680  assert(label_);
681 
682  // Normally, this is only an event hook and not full handling; however, if
683  // the currently selected item was selected, we halt the event to prevent
684  // deselection (which would leave no items selected).
685  if(label_->get_value()) {
686  halt = handled = true;
687  return;
688  }
689 
690  // Select the new item if a different one was selected
693  }
694 
695  get_tree_view().selected_item_ = this;
696 
698 }
699 
700 void tree_view_node::init_grid(grid* g, const std::map<std::string /* widget id */, string_map>& data)
701 {
702  assert(g);
703 
704  for(unsigned row = 0; row < g->get_rows(); ++row) {
705  for(unsigned col = 0; col < g->get_cols(); ++col) {
706  widget* wgt = g->get_widget(row, col);
707  assert(wgt);
708 
709  // toggle_button* btn = dynamic_cast<toggle_button*>(widget);
710 
711  if(toggle_panel* panel = dynamic_cast<toggle_panel*>(wgt)) {
712  panel->set_child_members(data);
713  } else if(grid* child_grid = dynamic_cast<grid*>(wgt)) {
714  init_grid(child_grid, data);
715  } else if(styled_widget* control = dynamic_cast<styled_widget*>(wgt)) {
716  auto itor = data.find(control->id());
717 
718  if(itor == data.end()) {
719  itor = data.find("");
720  }
721 
722  if(itor != data.end()) {
723  control->set_members(itor->second);
724  }
725  // control->set_members(data);
726  } else {
727  // ERROR_LOG("Widget type '" << typeid(*widget).name() << "'.");
728  }
729  }
730  }
731 }
732 
733 const std::string& tree_view_node::get_control_type() const
734 {
735  static const std::string type = "tree_view_node";
736  return type;
737 }
738 
740 {
741  assert(static_cast<std::size_t>(index) < children_.size());
742  return *children_[index];
743 }
744 
746 {
747  if(is_root_node()) {
748  return std::vector<int>();
749  }
750 
751  std::vector<int> res = parent_node_->describe_path();
752  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
753  if(parent_node_->children_[i].get() == this) {
754  res.push_back(i);
755  return res;
756  }
757  }
758 
759  assert(!"tree_view_node was not found in parent nodes children");
760  throw "assertion ignored"; // To silence 'no return value in this codepath' warning.
761 }
762 
764 {
765  if(!parent_node_) {
766  return 0;
767  }
768 
769  int res = parent_node_->calculate_ypos();
770  for(const auto& node : parent_node_->children_) {
771  if(node.get() == this) {
772  break;
773  }
774 
775  res += node->get_current_size(true).y;
776  }
777 
778  return res;
779 }
780 
782 {
783  if(!parent_node_) {
784  return this;
785  }
786 
788  return res == parent_node_ && !res->is_folded() ? this : res;
789 }
790 
792 {
793  assert(!is_root_node());
794 
795  tree_view_node* cur = nullptr;
796  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
797  if(parent_node_->children_[i].get() == this) {
798  if(i == 0) {
799  return parent_node_->is_root_node() ? nullptr : parent_node_;
800  } else {
801  cur = parent_node_->children_[i - 1].get();
802  break;
803  }
804  }
805  }
806 
807  while(cur && !cur->is_folded() && cur->count_children() > 0) {
808  cur = &cur->get_child_at(cur->count_children() - 1);
809  }
810 
811  if(!cur) {
812  throw std::domain_error(
813  "tree_view_node::get_node_above(): Cannot determine which node is this line, or which "
814  "node is the line above this one, if any.");
815  }
816 
817  return cur;
818 }
819 
821 {
822  assert(!is_root_node());
823  if(!is_folded() && count_children() > 0) {
824  return &get_child_at(0);
825  }
826 
827  tree_view_node* cur = this;
828  while(cur->parent_node_ != nullptr) {
830 
831  for(std::size_t i = 0; i < parent.count_children(); ++i) {
832  if(parent.children_[i].get() == cur) {
833  if(i < parent.count_children() - 1) {
834  return parent.children_[i + 1].get();
835  } else {
836  cur = &parent;
837  }
838 
839  break;
840  }
841  }
842  }
843 
844  return nullptr;
845 }
846 
848 {
849  tree_view_node* above = this;
850  do {
851  above = above->get_node_above();
852  } while(above != nullptr && above->label_ == nullptr);
853 
854  return above;
855 }
856 
858 {
859  tree_view_node* below = this;
860  do {
861  below = below->get_node_below();
862  } while(below != nullptr && below->label_ == nullptr);
863 
864  return below;
865 }
866 
867 void tree_view_node::select_node(bool expand_parents)
868 {
869  if(!label_ || label_->get_value_bool()) {
870  return;
871  }
872 
873  if(expand_parents) {
875  for(tree_view_node* cur = parent_node_; cur != root; cur = cur->parent_node_) {
876  cur->unfold();
877  }
878  }
879 
880  if(get_tree_view().selected_item_ && get_tree_view().selected_item_->label_) {
882  }
883 
884  get_tree_view().selected_item_ = this;
885 
887 
888  label_->set_value_bool(true);
889 }
890 
891 void tree_view_node::layout_initialize(const bool full_initialization)
892 {
893  // Inherited.
894  widget::layout_initialize(full_initialization);
895  grid_.layout_initialize(full_initialization);
896 
897  // Clear child caches.
898  for(auto& child : children_) {
899  child->layout_initialize(full_initialization);
900  }
901 }
902 
904 {
905  return new gui2::iteration::tree_node(*this, children_);
906 }
907 
908 } // namespace gui2
Define the common log macros for the gui toolkit.
Class for a toggle button.
void set_value_bool(bool value, bool fire_event=false)
Small abstract helper class.
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See widget::set_visible_rectangle.
Definition: grid.cpp:603
tree_view_node * parent_node_
Our parent node.
tree_view_node * get_node_below()
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
tree_view_node * get_node_above()
void set_parent(widget *parent)
Definition: widget.cpp:154
const std::vector< node > & nodes
tree_view_node * get_selectable_node_below()
bool is_root_node() const
Is this node the root node?
#define DBG_GUI_L
Definition: log.hpp:54
virtual void layout_initialize(const bool full_initialization)
How the layout engine works.
Definition: widget.cpp:166
virtual widget * find(const std::string &id, const bool must_be_active)
Returns a widget with the wanted id.
Definition: widget.cpp:583
std::vector< int > describe_path()
Calculates the node indices needed to get from the root node to this node.
unsigned indentation_step_size_
Definition: tree_view.hpp:153
selectable_item * toggle_
The toggle for the folded state.
A panel is a visible container to hold multiple widgets.
Definition: panel.hpp:57
tree_view_node & get_root_node()
Definition: tree_view.hpp:73
const std::string & id() const
Definition: widget.cpp:109
unsigned int get_rows() const
Definition: grid.hpp:307
Base class for all widgets.
Definition: widget.hpp:48
tree_view_node & parent_node()
Returns the parent node.
lg::log_domain log_gui_layout("gui/layout")
Definition: log.hpp:53
static W * find_at_aux(It begin, It end, const point &coordinate, const bool must_be_active)
void select_node(bool expand_parents=false)
virtual point calculate_best_size() const override
See widget::calculate_best_size.
#define d
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
virtual void set_origin(const point &origin) override
See widget::set_origin.
static std::string _(const char *str)
Definition: gettext.hpp:92
typename const_clone< D, S >::reference const_clone_ref
Definition: const_clone.hpp:62
int x
x coordinate.
Definition: point.hpp:44
std::size_t count_children() const
The number of children in this widget.
Generic file dialog.
Definition: field-fwd.hpp:22
Sent by a widget to notify others its contents or state are modified.
Definition: handler.hpp:88
bool is_folded() const
Is the node folded?
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
Definition: grid.cpp:185
void signal_handler_label_left_button_click(const event::ui_event event, bool &handled, bool &halt)
Base container class.
Definition: grid.hpp:30
void init_grid(grid *grid, const std::map< std::string, string_map > &data)
node_children_vector children_
Our children.
void populate_dirty_list(window &caller, std::vector< widget *> &call_stack)
Adds a widget to the dirty list if it is dirty.
Definition: widget.cpp:416
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
point get_best_size() const
Gets the best size for the widget.
Definition: widget.cpp:192
A walker for a gui2::tree_view_node.
virtual void place(const point &origin, const point &size)
Places the widget.
Definition: widget.cpp:237
void set_visible(const visibility visible)
Definition: widget.cpp:475
tree_view_node * selected_item_
Definition: tree_view.hpp:159
virtual void set_origin(const point &origin)
Sets the origin of the widget.
Definition: widget.cpp:220
widget * parent()
Definition: widget.cpp:159
virtual iteration::walker_base * create_walker() override
See widget::create_walker.
The walker abstract base class.
Definition: walker.hpp:26
virtual void impl_draw_children(surface &frame_buffer, int x_offset, int y_offset) override
See widget::impl_draw_children.
grid grid_
Grid holding our contents.
static thread_local std::deque< std::string > call_stack
For printing error messages when WFL parsing or evaluation fails, this contains the names of the WFL ...
Definition: function.cpp:46
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: grid.cpp:655
unsigned int get_cols() const
Definition: grid.hpp:313
#define log_scope2(domain, description)
Definition: log.hpp:218
A tree view is a control that holds several items of the same or different types. ...
Definition: tree_view.hpp:59
void fold(const bool recursive=false)
void resize_content(const int width_modification, const int height_modification, const int width_modification_pos=-1, const int height_modification_pos=-1)
Resizes the content.
Definition: tree_view.cpp:120
static W * find_at(utils::const_clone_ref< tree_view_node, W > tree_view_node, const point &coordinate, const bool must_be_active)
#define LOG_HEADER
tree_view_node(const std::string &id, tree_view_node *parent_node, tree_view &parent_tree_view, const std::map< std::string, string_map > &data)
#define FAIL_WITH_DEV_MESSAGE(message, dev_message)
virtual void place(const point &origin, const point &size) override
See widget::place.
Definition: grid.cpp:479
void clear()
Removes all child items from the widget.
std::size_t i
Definition: function.cpp:940
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void impl_populate_dirty_list(window &caller, const std::vector< widget *> &call_stack)
"Inherited" from widget.
selectable_item * label_
The label to show our selected state.
std::enable_if_t< is_general_event(E)> connect_signal(const signal_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event.
Definition: dispatcher.hpp:505
#define DBG_GUI_E
Definition: log.hpp:34
tree_view_node & get_child_at(int index)
The user set the widget invisible, that means:
tree_view_node * get_last_visible_parent_node()
double g
Definition: astarsearch.cpp:64
Holds a 2D point.
Definition: point.hpp:23
void unfold(const bool recursive=false)
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
Base class for all visible items.
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
const std::string & get_control_type() const
Returns the control_type of the tree_view_node.
virtual void set_value(unsigned value, bool fire_event=false)=0
Select the styled_widget.
point get_folded_size() const
tree_view & get_tree_view()
point get_size() const
Returns the size of the widget.
Definition: widget.cpp:304
unsigned get_indentation_level() const
The indentation level of the node.
Contains the SDL_Rect helper code.
The user sets the widget visible, that means:
#define LOG_SCOPE_HEADER
The user sets the widget hidden, that means:
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
std::map< std::string, std::shared_ptr< gui2::tree_view_node > > replace_children(const std::string &id, const std::map< std::string, std::map< std::string, string_map >> &data)
Replaces all children of this tree with new children.
void layout_initialize(const bool full_initialization) override
How the layout engine works.
tree_view_node * get_selectable_node_above()
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:68
tree_view * tree_view_
The tree view that owns us.
virtual void set_size(const point &size)
Sets the size of the widget.
Definition: widget.cpp:226
const point & layout_size() const
Definition: widget.cpp:339
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See widget::set_visible_rectangle.
virtual void place(const point &origin, const point &size) override
See widget::place.
point get_unfolded_size() const
tree_view_node & add_child_impl(std::shared_ptr< tree_view_node > &&new_node, const int index)
Implementation detail for add_child.
virtual widget * find_at(const point &coordinate, const bool must_be_active)
Returns the widget at the wanted coordinates.
Definition: widget.cpp:572
void draw_children(surface &frame_buffer, int x_offset, int y_offset)
Draws the children of a widget.
Definition: widget.cpp:386
virtual void layout_children() override
See widget::layout_children.
Definition: tree_view.cpp:115
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
const widget * get_widget(const unsigned row, const unsigned col) const
Returns the widget in the selected cell.
Definition: grid.hpp:180
point get_current_size(bool assume_visible=false) const
void signal_handler_left_button_click(const event::ui_event event)
int y
y coordinate.
Definition: point.hpp:47
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:64
A left mouse button click event for a widget.
Definition: handler.hpp:62
virtual unsigned get_value() const =0
Is the styled_widget selected?
ui_event
The event send to the dispatcher.
Definition: handler.hpp:47