The Battle for Wesnoth  1.15.2+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 "utils/functional.hpp"
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 
79 
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, _2, _3, _4),
96 
98  std::bind(&tree_view_node::signal_handler_label_left_button_click, this, _2, _3, _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 
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 
190 {
191  unsigned level = 0;
192 
193  const tree_view_node* node = this;
194  while(!node->is_root_node()) {
195  node = &node->parent_node();
196  ++level;
197  }
198 
199  return level;
200 }
201 
203 {
204  assert(!is_root_node());
205  return *parent_node_;
206 }
207 
209 {
210  assert(!is_root_node());
211  return *parent_node_;
212 }
213 
214 void tree_view_node::request_reduce_width(const unsigned /*maximum_width*/)
215 {
216  /* DO NOTHING */
217 }
218 
219 void tree_view_node::fold(const bool recursive)
220 {
221  if(!is_folded()) {
222  fold_internal();
223  if(toggle_) {
224  toggle_->set_value(false);
225  }
226  }
227 
228  if(recursive) {
229  for(auto& child_node : children_) {
230  child_node->fold(true);
231  }
232  }
233 }
234 
235 void tree_view_node::unfold(const bool recursive)
236 {
237  if(is_folded()) {
238  unfold_internal();
239  if(toggle_) {
240  toggle_->set_value(true);
241  }
242  }
243 
244  if(recursive) {
245  for(auto& child_node : children_) {
246  child_node->unfold(true);
247  }
248  }
249 }
250 
252 {
253  const point current_size(get_current_size().x, get_unfolded_size().y);
254  const point new_size = get_folded_size();
255 
256  const int width_modification = std::max(0, new_size.x - current_size.x);
257  const int height_modification = new_size.y - current_size.y;
258  assert(height_modification <= 0);
259 
260  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
261  unfolded_ = false;
262 }
263 
265 {
266  const point current_size(get_current_size().x, get_folded_size().y);
267  const point new_size = get_unfolded_size();
268 
269  const int width_modification = std::max(0, new_size.x - current_size.x);
270  const int height_modification = new_size.y - current_size.y;
271  assert(height_modification >= 0);
272 
273  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
274  unfolded_ = true;
275 }
276 
278 {
279  /** @todo Also try to find the optimal width. */
280  int height_reduction = 0;
281 
282  if(!is_folded()) {
283  for(const auto& node : children_) {
284  height_reduction += node->get_current_size().y;
285  }
286  }
287 
288  children_.clear();
289 
290  if(height_reduction == 0) {
291  return;
292  }
293 
294  get_tree_view().resize_content(0, -height_reduction, -1, calculate_ypos());
295 }
296 
298 {
299 private:
300  template<class W, class It>
301  static W* find_at_aux(It begin, It end, const point& coordinate, const bool must_be_active)
302  {
303  for(It it = begin; it != end; ++it) {
304  if(W* widget = (*it)->find_at(coordinate, must_be_active)) {
305  return widget;
306  }
307  }
308 
309  return nullptr;
310  }
311 
312 public:
313  template<class W>
315  const point& coordinate,
316  const bool must_be_active)
317  {
318  if(W* widget = tree_view_node.grid_.find_at(coordinate, must_be_active)) {
319  return widget;
320  }
321 
322  if(tree_view_node.is_folded()) {
323  return nullptr;
324  }
325 
326  return find_at_aux<W>(
327  tree_view_node.children_.begin(), tree_view_node.children_.end(), coordinate, must_be_active);
328  }
329 };
330 
331 widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active)
332 {
333  return tree_view_node_implementation::find_at<widget>(*this, coordinate, must_be_active);
334 }
335 
336 const widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active) const
337 {
338  return tree_view_node_implementation::find_at<const widget>(*this, coordinate, must_be_active);
339 }
340 
341 widget* tree_view_node::find(const std::string& id, const bool must_be_active)
342 {
343  widget* result = widget::find(id, must_be_active);
344  if(result) {
345  return result;
346  }
347 
348  result = grid_.find(id, must_be_active);
349  if(result) {
350  return result;
351  }
352 
353  for(auto& child : children_) {
354  result = child->find(id, must_be_active);
355  if(result) {
356  return result;
357  }
358  }
359 
360  return nullptr;
361 }
362 
363 const widget* tree_view_node::find(const std::string& id, const bool must_be_active) const
364 {
365  const widget* result = widget::find(id, must_be_active);
366  if(result) {
367  return result;
368  }
369 
370  result = grid_.find(id, must_be_active);
371  if(result) {
372  return result;
373  }
374 
375  for(const auto& child : children_) {
376  result = child->find(id, must_be_active);
377  if(result) {
378  return result;
379  }
380  }
381 
382  return nullptr;
383 }
384 
385 void tree_view_node::impl_populate_dirty_list(window& caller, const std::vector<widget*>& call_stack)
386 {
387  std::vector<widget*> my_call_stack = call_stack;
388  grid_.populate_dirty_list(caller, my_call_stack);
389 
390  if(is_folded()) {
391  return;
392  }
393 
394  for(auto& node : children_) {
395  std::vector<widget*> child_call_stack = call_stack;
396  node->impl_populate_dirty_list(caller, child_call_stack);
397  }
398 }
399 
401 {
402  return calculate_best_size(-1, get_tree_view().indentation_step_size_);
403 }
404 
406 {
407  return true;
408 }
409 
410 point tree_view_node::get_current_size(bool assume_visible) const
411 {
412  if(!assume_visible && parent_node_ && parent_node_->is_folded()) {
413  return point();
414  }
415 
417  if(is_folded()) {
418  return size;
419  }
420 
421  for(const auto& node : children_) {
422  if(node->grid_.get_visible() == widget::visibility::invisible) {
423  continue;
424  }
425 
426  point node_size = node->get_current_size();
427 
428  size.y += node_size.y;
429  size.x = std::max(size.x, node_size.x);
430  }
431 
432  return size;
433 }
434 
436 {
438  if(get_indentation_level() > 1) {
440  }
441 
442  return size;
443 }
444 
446 {
448  if(get_indentation_level() > 1) {
450  }
451 
452  for(const auto& node : children_) {
453  if(node->grid_.get_visible() == widget::visibility::invisible) {
454  continue;
455  }
456 
457  point node_size = node->get_current_size(true);
458 
459  size.y += node_size.y;
460  size.x = std::max(size.x, node_size.x);
461  }
462 
463  return size;
464 }
465 
466 point tree_view_node::calculate_best_size(const int indentation_level, const unsigned indentation_step_size) const
467 {
469 
470  point best_size = grid_.get_best_size();
471  if(indentation_level > 0) {
472  best_size.x += indentation_level * indentation_step_size;
473  }
474 
475  DBG_GUI_L << LOG_HEADER << " own grid best size " << best_size << ".\n";
476 
477  for(const auto& node : children_) {
478  if(node->grid_.get_visible() == widget::visibility::invisible) {
479  continue;
480  }
481 
482  const point node_size = node->calculate_best_size(indentation_level + 1, indentation_step_size);
483 
484  if(!is_folded()) {
485  best_size.y += node_size.y;
486  }
487 
488  best_size.x = std::max(best_size.x, node_size.x);
489  }
490 
491  DBG_GUI_L << LOG_HEADER << " result " << best_size << ".\n";
492  return best_size;
493 }
494 
496 {
497  // Inherited.
498  widget::set_origin(origin);
499 
500  // Using layout_children seems to fail.
501  place(get_tree_view().indentation_step_size_, origin, get_size().x);
502 }
503 
504 void tree_view_node::place(const point& origin, const point& size)
505 {
506  // Inherited.
507  widget::place(origin, size);
508 
510 }
511 
512 unsigned tree_view_node::place(const unsigned indentation_step_size, point origin, unsigned width)
513 {
515  DBG_GUI_L << LOG_HEADER << " origin " << origin << ".\n";
516 
517  const unsigned offset = origin.y;
518  point best_size = grid_.get_best_size();
519  best_size.x = width;
520 
521  grid_.place(origin, best_size);
522 
523  if(!is_root_node()) {
524  origin.x += indentation_step_size;
525  assert(width >= indentation_step_size);
526  width -= indentation_step_size;
527  }
528 
529  origin.y += best_size.y;
530 
531  if(is_folded()) {
532  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
533  return origin.y - offset;
534  }
535 
536  DBG_GUI_L << LOG_HEADER << " set children.\n";
537  for(auto& node : children_) {
538  origin.y += node->place(indentation_step_size, origin, width);
539  }
540 
541  // Inherited.
542  widget::set_size(point(width, origin.y - offset));
543 
544  DBG_GUI_L << LOG_HEADER << " result " << (origin.y - offset) << ".\n";
545  return origin.y - offset;
546 }
547 
548 void tree_view_node::set_visible_rectangle(const SDL_Rect& rectangle)
549 {
551  DBG_GUI_L << LOG_HEADER << " rectangle " << rectangle << ".\n";
552  grid_.set_visible_rectangle(rectangle);
553 
554  if(is_folded()) {
555  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
556  return;
557  }
558 
559  for(auto& node : children_) {
560  node->set_visible_rectangle(rectangle);
561  }
562 }
563 
565  int x_offset,
566  int y_offset)
567 {
568  grid_.draw_children(frame_buffer, x_offset, y_offset);
569 
570  if(is_folded()) {
571  return;
572  }
573 
574  for(auto& node : children_) {
575  node->impl_draw_children(frame_buffer, x_offset, y_offset);
576  }
577 }
578 
580 {
581  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
582 
583  /**
584  * @todo Rewrite this sizing code for the folding/unfolding.
585  *
586  * The code works but feels rather hacky, so better move back to the
587  * drawingboard for 1.9.
588  */
589  const bool unfolded_new = toggle_->get_value_bool();
590  if(unfolded_ == unfolded_new) {
591  return;
592  }
593 
594  unfolded_ = unfolded_new;
596 
598 }
599 
601 {
602  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
603 
604  assert(label_);
605 
606  // Normally, this is only an event hook and not full handling; however, if
607  // the currently selected item was selected, we halt the event to prevent
608  // deselection (which would leave no items selected).
609  if(label_->get_value()) {
610  halt = handled = true;
611  return;
612  }
613 
614  // Select the new item if a different one was selected
617  }
618 
619  get_tree_view().selected_item_ = this;
620 
622 }
623 
624 void tree_view_node::init_grid(grid* g, const std::map<std::string /* widget id */, string_map>& data)
625 {
626  assert(g);
627 
628  for(unsigned row = 0; row < g->get_rows(); ++row) {
629  for(unsigned col = 0; col < g->get_cols(); ++col) {
630  widget* wgt = g->get_widget(row, col);
631  assert(wgt);
632 
633  // toggle_button* btn = dynamic_cast<toggle_button*>(widget);
634 
635  if(toggle_panel* panel = dynamic_cast<toggle_panel*>(wgt)) {
636  panel->set_child_members(data);
637  } else if(grid* child_grid = dynamic_cast<grid*>(wgt)) {
638  init_grid(child_grid, data);
639  } else if(styled_widget* control = dynamic_cast<styled_widget*>(wgt)) {
640  auto itor = data.find(control->id());
641 
642  if(itor == data.end()) {
643  itor = data.find("");
644  }
645 
646  if(itor != data.end()) {
647  control->set_members(itor->second);
648  }
649  // control->set_members(data);
650  } else {
651  // ERROR_LOG("Widget type '" << typeid(*widget).name() << "'.");
652  }
653  }
654  }
655 }
656 
657 const std::string& tree_view_node::get_control_type() const
658 {
659  static const std::string type = "tree_view_node";
660  return type;
661 }
662 
664 {
665  assert(static_cast<std::size_t>(index) < children_.size());
666  return *children_[index];
667 }
668 
670 {
671  if(is_root_node()) {
672  return std::vector<int>();
673  }
674 
675  std::vector<int> res = parent_node_->describe_path();
676  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
677  if(parent_node_->children_[i].get() == this) {
678  res.push_back(i);
679  return res;
680  }
681  }
682 
683  assert(!"tree_view_node was not found in parent nodes children");
684  throw "assertion ignored"; // To silence 'no return value in this codepath' warning.
685 }
686 
688 {
689  if(!parent_node_) {
690  return 0;
691  }
692 
693  int res = parent_node_->calculate_ypos();
694  for(const auto& node : parent_node_->children_) {
695  if(node.get() == this) {
696  break;
697  }
698 
699  res += node->get_current_size(true).y;
700  }
701 
702  return res;
703 }
704 
706 {
707  if(!parent_node_) {
708  return this;
709  }
710 
712  return res == parent_node_ && !res->is_folded() ? this : res;
713 }
714 
716 {
717  assert(!is_root_node());
718 
719  tree_view_node* cur = nullptr;
720  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
721  if(parent_node_->children_[i].get() == this) {
722  if(i == 0) {
723  return parent_node_->is_root_node() ? nullptr : parent_node_;
724  } else {
725  cur = parent_node_->children_[i - 1].get();
726  break;
727  }
728  }
729  }
730 
731  while(cur && !cur->is_folded() && cur->count_children() > 0) {
732  cur = &cur->get_child_at(cur->count_children() - 1);
733  }
734 
735  if(!cur) {
736  throw std::domain_error(
737  "tree_view_node::get_node_above(): Cannot determine which node is this line, or which "
738  "node is the line above this one, if any.");
739  }
740 
741  return cur;
742 }
743 
745 {
746  assert(!is_root_node());
747  if(!is_folded() && count_children() > 0) {
748  return &get_child_at(0);
749  }
750 
751  tree_view_node* cur = this;
752  while(cur->parent_node_ != nullptr) {
754 
755  for(std::size_t i = 0; i < parent.count_children(); ++i) {
756  if(parent.children_[i].get() == cur) {
757  if(i < parent.count_children() - 1) {
758  return parent.children_[i + 1].get();
759  } else {
760  cur = &parent;
761  }
762 
763  break;
764  }
765  }
766  }
767 
768  return nullptr;
769 }
770 
772 {
773  tree_view_node* above = this;
774  do {
775  above = above->get_node_above();
776  } while(above != nullptr && above->label_ == nullptr);
777 
778  return above;
779 }
780 
782 {
783  tree_view_node* below = this;
784  do {
785  below = below->get_node_below();
786  } while(below != nullptr && below->label_ == nullptr);
787 
788  return below;
789 }
790 
791 void tree_view_node::select_node(bool expand_parents)
792 {
793  if(!label_ || label_->get_value_bool()) {
794  return;
795  }
796 
797  if(expand_parents) {
799  for(tree_view_node* cur = parent_node_; cur != root; cur = cur->parent_node_) {
800  cur->unfold();
801  }
802  }
803 
804  if(get_tree_view().selected_item_ && get_tree_view().selected_item_->label_) {
806  }
807 
808  get_tree_view().selected_item_ = this;
809 
811 
812  label_->set_value_bool(true);
813 }
814 
815 void tree_view_node::layout_initialize(const bool full_initialization)
816 {
817  // Inherited.
818  widget::layout_initialize(full_initialization);
819  grid_.layout_initialize(full_initialization);
820 
821  // Clear child caches.
822  for(auto& child : children_) {
823  child->layout_initialize(full_initialization);
824  }
825 }
826 
828 {
829  return new gui2::iteration::tree_node(*this, children_);
830 }
831 
832 } // 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:152
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:57
virtual void layout_initialize(const bool full_initialization)
How the layout engine works.
Definition: widget.cpp:164
virtual widget * find(const std::string &id, const bool must_be_active)
Returns a widget with the wanted id.
Definition: widget.cpp:581
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:133
selectable_item * toggle_
The toggle for the folded state.
Visible container to hold multiple widgets.
Definition: panel.hpp:37
tree_view_node & get_root_node()
Definition: tree_view.hpp:53
unsigned int get_rows() const
Definition: grid.hpp:307
Base class for all widgets.
Definition: widget.hpp:47
tree_view_node & parent_node()
Returns the parent node.
lg::log_domain log_gui_layout("gui/layout")
Definition: log.hpp:56
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.
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.
std::enable_if_t< has_key< set_event, E >::value > connect_signal(const signal_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event.
Definition: dispatcher.hpp:393
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:96
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.
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
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:414
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:190
std::shared_ptr< tree_view_node > ptr_t
A walker for a gui2::tree_view_node.
virtual void place(const point &origin, const point &size)
Places the widget.
Definition: widget.cpp:235
void set_visible(const visibility visible)
Definition: widget.cpp:473
tree_view_node * selected_item_
Definition: tree_view.hpp:139
virtual void set_origin(const point &origin)
Sets the origin of the widget.
Definition: widget.cpp:218
widget * parent()
Definition: widget.cpp:157
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.
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
tree_view_node & add_child_impl(ptr_t &&new_node, const int index)
Implementation detail for add_child.
#define log_scope2(domain, description)
Definition: log.hpp:187
void fold(const bool recursive=false)
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)
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
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:933
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.
#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:302
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:130
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:224
const point & layout_size() const
Definition: widget.cpp:337
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
virtual widget * find_at(const point &coordinate, const bool must_be_active)
Returns the widget at the wanted coordinates.
Definition: widget.cpp:570
void draw_children(surface &frame_buffer, int x_offset, int y_offset)
Draws the children of a widget.
Definition: widget.cpp:384
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:62
A left mouse button click event for a widget.
Definition: handler.hpp:70
static std::deque< std::string > call_stack
Definition: function.cpp:39
virtual unsigned get_value() const =0
Is the styled_widget selected?
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55