The Battle for Wesnoth  1.17.0-dev
tree_view_node.hpp
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 #pragma once
17 
18 #include "gui/widgets/widget.hpp"
19 #include "gui/widgets/grid.hpp"
20 
21 #include <memory>
22 
23 namespace gui2
24 {
25 
26 namespace implementation {
27  struct tree_node;
28 }
29 
30 class selectable_item;
31 class tree_view;
32 
33 class tree_view_node : public widget
34 {
36  friend class tree_view;
37 
38 public:
39  using node_children_vector = std::vector<std::shared_ptr<tree_view_node>>;
40 
41  bool operator==(const tree_view_node& node)
42  {
43  return &node == this;
44  }
45 
47  const std::string& id,
48  tree_view_node* parent_node,
49  tree_view& parent_tree_view,
50  const std::map<std::string /* widget id */, string_map>& data);
51 
52  ~tree_view_node();
53 
54  /**
55  * Constructs a new child node.
56  *
57  * @param id The id of the node definition to use for the
58  * new node.
59  * @param data The data to send to the set_members of the
60  * widgets. If the member id is not an empty
61  * string it is only send to the widget that has
62  * the wanted id (if any). If the member id is an
63  * empty string, it is send to all members.
64  * Having both empty and non-empty id's gives
65  * undefined behavior.
66  * @param index The item before which to add the new item,
67  * 0 == begin, -1 == end.
68  */
69  tree_view_node& add_child(const std::string& id,
70  const std::map<std::string /* widget id */, string_map>& data,
71  const int index = -1)
72  {
73  return add_child_impl(std::make_shared<tree_view_node>(id, this, get_tree_view(), data), index);
74  }
75 
76  /**
77  * Replaces all children of this tree with new children.
78  * The motivation here is to provide a way to add multiple children without calculating the trees size for each child added.
79  * This is a waste of time since the results of that resizing will be immediately thrown out except for the final child added.
80  *
81  * @param id The id of the node definition to use for the new nodes.
82  * @param data A vector of the data to provide to the tree_node_view's constructor.
83  * @return A vector of pointers to the newly created nodes.
84  */
85  std::vector<std::shared_ptr<gui2::tree_view_node>> replace_children(const std::string& id, const std::vector<std::map<std::string /* widget id */, string_map>>& data);
86 
87  /**
88  * Adds a previously-constructed node as a child of this node at the given position.
89  *
90  * @param new_node A smart pointer to the node object to insert.
91  * @param index The item before which to add the new item,
92  * 0 == begin, -1 == end.
93  */
94  tree_view_node& add_child(std::shared_ptr<tree_view_node> new_node, const int index = -1)
95  {
96  new_node->parent_node_ = this;
97  return add_child_impl(std::move(new_node), index);
98  }
99 
100  /**
101  * Adds a sibbling for a node at the end of the list.
102  *
103  * @param id The id of the node definition to use for the
104  * new node.
105  * @param data The data to send to the set_members of the
106  * widgets. If the member id is not an empty
107  * string it is only send to the widget that has
108  * the wanted id (if any). If the member id is an
109  * empty string, it is send to all members.
110  * Having both empty and non-empty id's gives
111  * undefined behavior.
112  */
114  add_sibling(const std::string& id,
115  const std::map<std::string /* widget id */, string_map>& data)
116  {
117  assert(!is_root_node());
118  return parent_node().add_child(id, data);
119  }
120 
121 private:
122  /** Implementation detail for @ref add_child. */
123  tree_view_node& add_child_impl(std::shared_ptr<tree_view_node>&& new_node, const int index);
124 
125 public:
126  /**
127  * Is this node the root node?
128  *
129  * When the parent tree view is created it adds one special node, the root
130  * node. This node has no parent node and some other special features so
131  * several code paths need to check whether they are the parent node.
132  *
133  * This also returns true for a detecthed node returned with @ref tree_view::remove_node.
134  */
135  bool is_root_node() const
136  {
137  return parent_node_ == nullptr;
138  }
139 
140  /**
141  * The indentation level of the node.
142  *
143  * The root node starts at level 0.
144  */
145  unsigned get_indentation_level() const;
146 
147  /** Does the node have children? */
148  bool empty() const
149  {
150  return children_.empty();
151  }
152 
153  /** Is the node folded? */
154  bool is_folded() const
155  {
156  return !unfolded_;
157  }
158 
159 #if 0
160  // TODO: implement if different expand modes become necessary
161  enum expand_mode {
162  recursive_restore, // recursively restores collapse mode
163  recursive_expand, // recursively expands the children
164  not_recursive
165  };
166 #endif
167 
168  void fold(const bool recursive = false);
169  void unfold(const bool recursive = false);
170 
171  /**
172  * See @ref widget::create_walker.
173  *
174  * @todo Implement properly.
175  */
176  virtual iteration::walker_base* create_walker() override;
177 
179  {
180  return children_;
181  }
182 
184  {
185  assert(!is_root_node());
186  return parent_node().children();
187  }
188 
189  /** See @ref widget::find_at. */
190  virtual widget* find_at(const point& coordinate,
191  const bool must_be_active) override;
192 
193  /** See @ref widget::find_at. */
194  virtual const widget* find_at(const point& coordinate,
195  const bool must_be_active) const override;
196 
197  /** See @ref widget::find. */
198  widget* find(const std::string& id, const bool must_be_active) override;
199 
200  /** See @ref widget::find. */
201  const widget* find(const std::string& id,
202  const bool must_be_active) const override;
203 
204  /**
205  * The number of children in this widget.
206  */
207  std::size_t count_children() const
208  {
209  return children_.size();
210  }
211 
212  /**
213  * Removes all child items from the widget.
214  */
215  void clear();
216 
217  /***** ***** ***** setters / getters for members ***** ****** *****/
218 
219  /**
220  * Returns the parent node.
221  *
222  * @pre is_root_node() == false.
223  */
224  tree_view_node& parent_node();
225 
226  /** The const version of @ref parent_node. */
227  const tree_view_node& parent_node() const;
228 
230  {
231  return *tree_view_;
232  }
233 
234  const tree_view& get_tree_view() const
235  {
236  return *tree_view_;
237  }
238 
239  tree_view_node& get_child_at(int index);
240 
241  /**
242  * Calculates the node indices needed to get from the root node to this node.
243  */
244  std::vector<int> describe_path();
245 
246  tree_view_node* get_last_visible_parent_node();
247  tree_view_node* get_node_above();
248  tree_view_node* get_node_below();
249  tree_view_node* get_selectable_node_above();
250  tree_view_node* get_selectable_node_below();
251  void select_node(bool expand_parents = false);
252  grid& get_grid() { return grid_; }
253  void layout_initialize(const bool full_initialization) override;
254 
255  void clear_before_destruct();
256 
257 private:
258  int calculate_ypos();
259 
260  /** See @ref widget::request_reduce_width. */
261  virtual void request_reduce_width(const unsigned maximum_width) override;
262 
263  /**
264  * Our parent node.
265  *
266  * All nodes except the root node have a parent node.
267  */
269 
270  /** The tree view that owns us. */
272 
273  /** Grid holding our contents. */
275 
276  /**
277  * Our children.
278  *
279  * We want the returned child nodes to remain stable so store pointers.
280  */
282 
283  /** The toggle for the folded state. */
285 
286  /** The label to show our selected state. */
288 
289  bool unfolded_;
290  void fold_internal();
291  void unfold_internal();
292 
293  /**
294  * "Inherited" from widget.
295  *
296  * This version needs to call its children, which are it's child nodes.
297  */
298  void impl_populate_dirty_list(window& caller,
299  const std::vector<widget*>& call_stack);
300 
301  /** See @ref widget::calculate_best_size. */
302  virtual point calculate_best_size() const override;
303 
304  /** See @ref widget::disable_click_dismiss. */
305  bool disable_click_dismiss() const override;
306 
307  point calculate_best_size(const int indentation_level,
308  const unsigned indentation_step_size) const;
309  /** @param assume_visible if false (default) it will return 0 if the parent node is folded*/
310  point get_current_size(bool assume_visible = false) const;
311  point get_folded_size() const;
312  point get_unfolded_size() const;
313 
314  /** See @ref widget::set_origin. */
315  virtual void set_origin(const point& origin) override;
316 
317  /** See @ref widget::place. */
318  virtual void place(const point& origin, const point& size) override;
319 
320  unsigned
321  place(const unsigned indentation_step_size, point origin, unsigned width);
322 
323  /** See @ref widget::set_visible_rectangle. */
324  virtual void set_visible_rectangle(const SDL_Rect& rectangle) override;
325 
326  /** See @ref widget::impl_draw_children. */
327  virtual void impl_draw_children(surface& frame_buffer,
328  int x_offset,
329  int y_offset) override;
330 
331  // FIXME rename to icon
332  void signal_handler_left_button_click(const event::ui_event event);
333 
334  void signal_handler_label_left_button_click(const event::ui_event event,
335  bool& handled,
336  bool& halt);
337 
338  void
339  init_grid(grid* grid,
340  const std::map<std::string /* widget id */, string_map>& data);
341 
342  /**
343  * Returns the control_type of the @ref tree_view_node.
344  *
345  * This class does not derive from @ref styled_widget but the function behaves
346  * similar as @ref styled_widget::get_control_type.
347  */
348  const std::string& get_control_type() const;
349 };
350 
351 } // namespace gui2
Small abstract helper class.
tree_view_node * parent_node_
Our parent node.
std::vector< std::shared_ptr< tree_view_node > > node_children_vector
bool is_root_node() const
Is this node the root node?
selectable_item * toggle_
The toggle for the folded state.
Base class for all widgets.
Definition: widget.hpp:49
void clear(const std::string &key)
Definition: general.cpp:186
tree_view_node & add_child(std::shared_ptr< tree_view_node > new_node, const int index=-1)
Adds a previously-constructed node as a child of this node at the given position. ...
const tree_view & get_tree_view() const
std::size_t count_children() const
The number of children in this widget.
Generic file dialog.
Definition: field-fwd.hpp:23
bool empty() const
Does the node have children?
bool operator==(const tree_view_node &node)
bool is_folded() const
Is the node folded?
Base container class.
Definition: grid.hpp:31
node_children_vector children_
Our children.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
The walker abstract base class.
Definition: walker.hpp:27
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
A tree view is a control that holds several items of the same or different types. ...
Definition: tree_view.hpp:60
selectable_item * label_
The label to show our selected state.
Holds a 2D point.
Definition: point.hpp:24
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
tree_view & get_tree_view()
node_children_vector & children()
node_children_vector & siblings()
tree_view_node & add_sibling(const std::string &id, const std::map< std::string, string_map > &data)
Adds a sibbling for a node at the end of the list.
tree_view * tree_view_
The tree view that owns us.
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
tree_view_node & add_child(const std::string &id, const std::map< std::string, string_map > &data, const int index=-1)
Constructs a new child node.
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:65
Contains the implementation details for lexical_cast and shouldn&#39;t be used directly.
ui_event
The event send to the dispatcher.
Definition: handler.hpp:48