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