The Battle for Wesnoth  1.15.1+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 
28 #include "utils/functional.hpp"
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 
37  const std::string& id,
38  tree_view_node* parent_node,
39  tree_view& parent_tree_view,
40  const std::map<std::string /* widget id */, string_map>& data)
41  : widget()
42  , parent_node_(parent_node)
43  , tree_view_(&parent_tree_view)
44  , grid_()
45  , children_()
46  , toggle_(nullptr)
47  , label_(nullptr)
48  , unfolded_(false)
49 {
50  grid_.set_parent(this);
51  set_parent(&parent_tree_view);
52 
53  if(id == "root") {
54  unfolded_ = true;
55  return;
56  }
57 
58  for(const auto& node_definition : get_tree_view().get_node_definitions()) {
59  if(node_definition.id != id) {
60  continue;
61  }
62 
63  node_definition.builder->build(&grid_);
64  init_grid(&grid_, data);
65 
68  }
69 
70  if(node_definition.unfolded) {
71  unfolded_ = true;
72  }
73 
74  widget* toggle_widget = grid_.find("tree_view_node_toggle", false);
75  toggle_ = dynamic_cast<selectable_item*>(toggle_widget);
76 
77  if(toggle_) {
79 
80  toggle_widget->connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
82  toggle_widget->connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
85 
86  if(unfolded_) {
87  toggle_->set_value(1);
88  }
89  }
90 
91  widget* label_widget = grid_.find("tree_view_node_label", false);
92  label_ = dynamic_cast<selectable_item*>(label_widget);
93 
94  if(label_) {
95  label_widget->connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
98  label_widget->connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
101 
103  get_tree_view().selected_item_ = this;
104  label_->set_value(true);
105  }
106  }
107 
108  return;
109  }
110 
111  // Only reached if no matching node definition was found in the above loop
112  FAIL_WITH_DEV_MESSAGE(_("Unknown builder id for tree view node."), id);
113 }
114 
116 {
117  if(tree_view_ && get_tree_view().selected_item_ == this) {
118  get_tree_view().selected_item_ = nullptr;
119  }
120 }
121 
123 {
124  tree_view_ = nullptr;
125  for(auto& child : children_) {
126  child->clear_before_destruct();
127  }
128 }
129 
131 {
132  auto itor = children_.end();
133 
134  if(static_cast<std::size_t>(index) < children_.size()) {
135  itor = children_.begin() + index;
136  }
137 
138  tree_view_node& node = **children_.insert(itor, std::move(new_node));
139 
140  // NOTE: we currently don't support moving nodes between different trees, so this
141  // just ensures that wasn't tried. Remove this if we implement support for that.
142  assert(node.tree_view_ == tree_view_);
143 
144  // Safety check. Might only fail if someone accidentally removed the parent_node_
145  // setter in add_child().
146  assert(node.parent_node_ == this);
147 
148  if(is_folded() /*|| is_root_node()*/) {
149  return node;
150  }
151 
152  if(get_tree_view().get_size() == point()) {
153  return node;
154  }
155 
156  assert(get_tree_view().content_grid());
157  const point current_size = get_tree_view().content_grid()->get_size();
158 
159  // Calculate width modification.
160  // This increases tree width if the width of the new node is greater than the current width.
161  point best_size = node.get_best_size();
163 
164  const int width_modification = best_size.x > current_size.x
165  ? best_size.x - current_size.x
166  : 0;
167 
168  // Calculate height modification.
169  // For this, we only increase height if the best size of the tree (that is, the size with the new node)
170  // is larger than its current size. This prevents the scrollbar being reserved even when there's obviously
171  // enough visual space.
172 
173  // Throw away cached best size to force a recalculation.
175 
176  const point tree_best_size = get_tree_view().get_best_size();
177 
178  const int height_modification = tree_best_size.y > current_size.y && get_tree_view().layout_size() == point()
179  ? tree_best_size.y - current_size.y
180  : 0;
181 
182  assert(height_modification >= 0);
183 
184  // Request new size.
185  get_tree_view().resize_content(width_modification, height_modification, -1, node.calculate_ypos());
186 
187  return node;
188 }
189 
191 {
192  unsigned level = 0;
193 
194  const tree_view_node* node = this;
195  while(!node->is_root_node()) {
196  node = &node->parent_node();
197  ++level;
198  }
199 
200  return level;
201 }
202 
204 {
205  assert(!is_root_node());
206  return *parent_node_;
207 }
208 
210 {
211  assert(!is_root_node());
212  return *parent_node_;
213 }
214 
215 void tree_view_node::request_reduce_width(const unsigned /*maximum_width*/)
216 {
217  /* DO NOTHING */
218 }
219 
220 void tree_view_node::fold(const bool recursive)
221 {
222  if(!is_folded()) {
223  fold_internal();
224  if(toggle_) {
225  toggle_->set_value(false);
226  }
227  }
228 
229  if(recursive) {
230  for(auto& child_node : children_) {
231  child_node->fold(true);
232  }
233  }
234 }
235 
236 void tree_view_node::unfold(const bool recursive)
237 {
238  if(is_folded()) {
239  unfold_internal();
240  if(toggle_) {
241  toggle_->set_value(true);
242  }
243  }
244 
245  if(recursive) {
246  for(auto& child_node : children_) {
247  child_node->unfold(true);
248  }
249  }
250 }
251 
253 {
254  const point current_size(get_current_size().x, get_unfolded_size().y);
255  const point new_size = get_folded_size();
256 
257  const int width_modification = std::max(0, new_size.x - current_size.x);
258  const int height_modification = new_size.y - current_size.y;
259  assert(height_modification <= 0);
260 
261  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
262  unfolded_ = false;
263 }
264 
266 {
267  const point current_size(get_current_size().x, get_folded_size().y);
268  const point new_size = get_unfolded_size();
269 
270  const int width_modification = std::max(0, new_size.x - current_size.x);
271  const int height_modification = new_size.y - current_size.y;
272  assert(height_modification >= 0);
273 
274  get_tree_view().resize_content(width_modification, height_modification, -1, calculate_ypos());
275  unfolded_ = true;
276 }
277 
279 {
280  /** @todo Also try to find the optimal width. */
281  int height_reduction = 0;
282 
283  if(!is_folded()) {
284  for(const auto & node : children_)
285  {
286  height_reduction += node->get_current_size().y;
287  }
288  }
289 
290  children_.clear();
291 
292  if(height_reduction == 0) {
293  return;
294  }
295 
296  get_tree_view().resize_content(0, -height_reduction, -1, calculate_ypos());
297 }
298 
300 {
301 private:
302  template <class W, class It>
303  static W* find_at_aux(It begin,
304  It end,
305  const point& coordinate,
306  const bool must_be_active)
307  {
308  for(It it = begin; it != end; ++it) {
309  if(W* widget = (*it)->find_at(coordinate, must_be_active)) {
310  return widget;
311  }
312  }
313  return nullptr;
314  }
315 
316 public:
317  template <class W>
319  const point& coordinate,
320  const bool must_be_active)
321  {
322  if(W* widget = tree_view_node.grid_.find_at(coordinate, must_be_active)) {
323  return widget;
324  }
325 
326  if(tree_view_node.is_folded()) {
327  return nullptr;
328  }
329 
330  return find_at_aux<W>(tree_view_node.children_.begin(),
331  tree_view_node.children_.end(),
332  coordinate,
333  must_be_active);
334  }
335 };
336 
337 widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active)
338 {
339  return tree_view_node_implementation::find_at<widget>(*this, coordinate, must_be_active);
340 }
341 
342 const widget* tree_view_node::find_at(const point& coordinate, const bool must_be_active) const
343 {
344  return tree_view_node_implementation::find_at<const widget>(*this, coordinate, must_be_active);
345 }
346 
347 widget* tree_view_node::find(const std::string& id, const bool must_be_active)
348 {
349  widget* result = widget::find(id, must_be_active);
350  if(result) {
351  return result;
352  }
353 
354  result = grid_.find(id, must_be_active);
355  if(result) {
356  return result;
357  }
358 
359  for(auto& child : children_) {
360  result = child->find(id, must_be_active);
361  if(result) {
362  return result;
363  }
364  }
365 
366  return nullptr;
367 }
368 
369 const widget* tree_view_node::find(const std::string& id, const bool must_be_active) const
370 {
371  const widget* result = widget::find(id, must_be_active);
372  if(result) {
373  return result;
374  }
375 
376  result = grid_.find(id, must_be_active);
377  if(result) {
378  return result;
379  }
380 
381  for(const auto& child : children_) {
382  result = child->find(id, must_be_active);
383  if(result) {
384  return result;
385  }
386  }
387 
388  return nullptr;
389 }
390 
391 void tree_view_node::impl_populate_dirty_list(window& caller, const std::vector<widget*>& call_stack)
392 {
393  std::vector<widget*> my_call_stack = call_stack;
394  grid_.populate_dirty_list(caller, my_call_stack);
395 
396  if(is_folded()) {
397  return;
398  }
399 
400  for(auto& node : children_) {
401  std::vector<widget*> child_call_stack = call_stack;
402  node->impl_populate_dirty_list(caller, child_call_stack);
403  }
404 }
405 
407 {
408  return calculate_best_size(-1, get_tree_view().indentation_step_size_);
409 }
410 
412 {
413  return true;
414 }
415 
416 point tree_view_node::get_current_size(bool assume_visible) const
417 {
418  if(!assume_visible && parent_node_ && parent_node_->is_folded()) {
419  return point();
420  }
421 
423  if(is_folded()) {
424  return size;
425  }
426 
427  for(const auto& node : children_) {
428  if(node->grid_.get_visible() == widget::visibility::invisible) {
429  continue;
430  }
431 
432  point node_size = node->get_current_size();
433 
434  size.y += node_size.y;
435  size.x = std::max(size.x, node_size.x);
436  }
437 
438  return size;
439 }
440 
442 {
444  if(get_indentation_level() > 1) {
446  }
447  return size;
448 }
449 
451 {
453  if(get_indentation_level() > 1) {
455  }
456 
457  for(const auto& node : children_) {
458  if(node->grid_.get_visible() == widget::visibility::invisible) {
459  continue;
460  }
461 
462  point node_size = node->get_current_size(true);
463 
464  size.y += node_size.y;
465  size.x = std::max(size.x, node_size.x);
466  }
467 
468  return size;
469 }
470 
471 point tree_view_node::calculate_best_size(const int indentation_level,
472  const unsigned indentation_step_size) const
473 {
475 
476  point best_size = grid_.get_best_size();
477  if(indentation_level > 0) {
478  best_size.x += indentation_level * indentation_step_size;
479  }
480 
481  DBG_GUI_L << LOG_HEADER << " own grid best size " << best_size << ".\n";
482 
483  for(const auto& node : children_) {
484  if(node->grid_.get_visible() == widget::visibility::invisible) {
485  continue;
486  }
487 
488  const point node_size = node->calculate_best_size(indentation_level + 1, indentation_step_size);
489 
490  if(!is_folded()) {
491  best_size.y += node_size.y;
492  }
493 
494  best_size.x = std::max(best_size.x, node_size.x);
495  }
496 
497  DBG_GUI_L << LOG_HEADER << " result " << best_size << ".\n";
498  return best_size;
499 }
500 
502 {
503  // Inherited.
504  widget::set_origin(origin);
505 
506  // Using layout_children seems to fail.
507  place(get_tree_view().indentation_step_size_, origin, get_size().x);
508 }
509 
510 void tree_view_node::place(const point& origin, const point& size)
511 {
512  // Inherited.
513  widget::place(origin, size);
514 
516 }
517 
518 unsigned tree_view_node::place(const unsigned indentation_step_size,
519  point origin,
520  unsigned width)
521 {
523  DBG_GUI_L << LOG_HEADER << " origin " << origin << ".\n";
524 
525  const unsigned offset = origin.y;
526  point best_size = grid_.get_best_size();
527  best_size.x = width;
528 
529  grid_.place(origin, best_size);
530 
531  if(!is_root_node()) {
532  origin.x += indentation_step_size;
533  assert(width >= indentation_step_size);
534  width -= indentation_step_size;
535  }
536 
537  origin.y += best_size.y;
538 
539  if(is_folded()) {
540  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
541  return origin.y - offset;
542  }
543 
544  DBG_GUI_L << LOG_HEADER << " set children.\n";
545  for(auto & node : children_) {
546  origin.y += node->place(indentation_step_size, origin, width);
547  }
548 
549  // Inherited.
550  widget::set_size(point(width, origin.y - offset));
551 
552  DBG_GUI_L << LOG_HEADER << " result " << (origin.y - offset) << ".\n";
553  return origin.y - offset;
554 }
555 
556 void tree_view_node::set_visible_rectangle(const SDL_Rect& rectangle)
557 {
559  DBG_GUI_L << LOG_HEADER << " rectangle " << rectangle << ".\n";
560  grid_.set_visible_rectangle(rectangle);
561 
562  if(is_folded()) {
563  DBG_GUI_L << LOG_HEADER << " folded node done.\n";
564  return;
565  }
566 
567  for(auto & node : children_) {
568  node->set_visible_rectangle(rectangle);
569  }
570 }
571 
573  int x_offset,
574  int y_offset)
575 {
576  grid_.draw_children(frame_buffer, x_offset, y_offset);
577 
578  if(is_folded()) {
579  return;
580  }
581 
582  for(auto & node : children_) {
583  node->impl_draw_children(frame_buffer, x_offset, y_offset);
584  }
585 }
586 
588 {
589  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
590 
591  /**
592  * @todo Rewrite this sizing code for the folding/unfolding.
593  *
594  * The code works but feels rather hacky, so better move back to the
595  * drawingboard for 1.9.
596  */
597  const bool unfolded_new = toggle_->get_value_bool();
598  if(unfolded_ == unfolded_new) {
599  return;
600  }
601 
602  unfolded_ = unfolded_new;
604 
605  fire(event::NOTIFY_MODIFIED, *this, nullptr);
606 }
607 
609  const event::ui_event event, bool& handled, bool& halt)
610 {
611  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
612 
613  assert(label_);
614 
615  // Normally, this is only an event hook and not full handling; however, if
616  // the currently selected item was selected, we halt the event to prevent
617  // deselection (which would leave no items selected).
618  if(label_->get_value()) {
619  halt = handled = true;
620  return;
621  }
622 
623  // Select the new item if a different one was selected
626  }
627 
628  get_tree_view().selected_item_ = this;
629 
630  if(get_tree_view().selection_change_callback_) {
632  }
633 }
634 
636  grid* g,
637  const std::map<std::string /* widget id */, string_map>& data)
638 {
639  assert(g);
640 
641  for(unsigned row = 0; row < g->get_rows(); ++row) {
642  for(unsigned col = 0; col < g->get_cols(); ++col) {
643  widget* wgt = g->get_widget(row, col);
644  assert(wgt);
645 
646  // toggle_button* btn = dynamic_cast<toggle_button*>(widget);
647 
648  if(toggle_panel* panel = dynamic_cast<toggle_panel*>(wgt)) {
649  panel->set_child_members(data);
650  } else if(grid* child_grid = dynamic_cast<grid*>(wgt)) {
651  init_grid(child_grid, data);
652  } else if(styled_widget* control = dynamic_cast<styled_widget*>(wgt)) {
653  auto itor = data.find(control->id());
654 
655  if(itor == data.end()) {
656  itor = data.find("");
657  }
658 
659  if(itor != data.end()) {
660  control->set_members(itor->second);
661  }
662  // control->set_members(data);
663  } else {
664  // ERROR_LOG("Widget type '" << typeid(*widget).name() << "'.");
665  }
666  }
667  }
668 }
669 
670 const std::string& tree_view_node::get_control_type() const
671 {
672  static const std::string type = "tree_view_node";
673  return type;
674 }
675 
677 {
678  assert(static_cast<std::size_t>(index) < children_.size());
679  return *children_[index];
680 }
681 
683 {
684  if(is_root_node()) {
685  return std::vector<int>();
686  }
687 
688  std::vector<int> res = parent_node_->describe_path();
689  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
690  if(parent_node_->children_[i].get() == this) {
691  res.push_back(i);
692  return res;
693  }
694  }
695 
696  assert(!"tree_view_node was not found in parent nodes children");
697  throw "assertion ignored"; //To silence 'no return value in this codepath' warning.
698 }
699 
701 {
702  if(!parent_node_) {
703  return 0;
704  }
705 
706  int res = parent_node_->calculate_ypos();
707  for(const auto& node : parent_node_->children_) {
708  if(node.get() == this) {
709  break;
710  }
711 
712  res += node->get_current_size(true).y;
713  }
714 
715  return res;
716 }
717 
719 {
720  if(!parent_node_) {
721  return this;
722  }
723 
725  return res == parent_node_ && !res->is_folded() ? this : res;
726 }
727 
729 {
730  assert(!is_root_node());
731 
732  tree_view_node* cur = nullptr;
733  for(std::size_t i = 0; i < parent_node_->count_children(); ++i) {
734  if(parent_node_->children_[i].get() == this) {
735  if(i == 0) {
736  return parent_node_->is_root_node() ? nullptr : parent_node_;
737  } else {
738  cur = parent_node_->children_[i - 1].get();
739  break;
740  }
741  }
742  }
743 
744  while(cur && !cur->is_folded() && cur->count_children() > 0) {
745  cur = &cur->get_child_at(cur->count_children() - 1);
746  }
747 
748  if (!cur)
749  throw std::domain_error("tree_view_node::get_node_above(): Cannot determine which node is this line, or which node is the line above this one, if any.");
750 
751  return cur;
752 }
753 
755 {
756  assert(!is_root_node());
757  if(!is_folded() && count_children() > 0) {
758  return &get_child_at(0);
759  }
760 
761  tree_view_node* cur = this;
762  while(cur->parent_node_ != nullptr) {
764 
765  for(std::size_t i = 0; i < parent.count_children(); ++i) {
766  if(parent.children_[i].get() == cur) {
767  if(i < parent.count_children() - 1) {
768  return parent.children_[i + 1].get();
769  } else {
770  cur = &parent;
771  }
772  break;
773  }
774  }
775  }
776 
777  return nullptr;
778 }
779 
781 {
782  tree_view_node* above = this;
783  do {
784  above = above->get_node_above();
785  } while(above != nullptr && above->label_ == nullptr);
786  return above;
787 }
788 
790 {
791  tree_view_node* below = this;
792  do {
793  below = below->get_node_below();
794  } while(below != nullptr && below->label_ == nullptr);
795  return below;
796 }
797 
798 void tree_view_node::select_node(bool expand_parents)
799 {
800  if(!label_ || label_->get_value_bool()) {
801  return;
802  }
803 
804  if(expand_parents) {
806  for(tree_view_node* cur = parent_node_; cur != root; cur = cur->parent_node_) {
807  cur->unfold();
808  }
809  }
810 
811  if(get_tree_view().selected_item_ && get_tree_view().selected_item_->label_) {
813  }
814  get_tree_view().selected_item_ = this;
815 
816  if(get_tree_view().selection_change_callback_) {
818  }
819  label_->set_value_bool(true);
820 }
821 
822 void tree_view_node::layout_initialize(const bool full_initialization)
823 {
824  // Inherited.
825  widget::layout_initialize(full_initialization);
826  grid_.layout_initialize(full_initialization);
827 
828  // Clear child caches.
829  for(auto & child : children_) {
830  child->layout_initialize(full_initialization);
831  }
832 }
833 
835 {
836  return new gui2::iteration::tree_node(*this, children_);
837 }
838 
839 } // 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:138
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
std::function< void(widget &)> selection_change_callback_
Definition: tree_view.hpp:146
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:144
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:129
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:124
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:63
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