The Battle for Wesnoth  1.15.12+dev
tree_view_node.hpp
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 #pragma once
16 
17 #include "gui/widgets/widget.hpp"
18 #include "gui/widgets/grid.hpp"
19 
20 #include <memory>
21 
22 namespace gui2
23 {
24 
25 namespace implementation {
26  struct tree_node;
27 }
28 
29 class selectable_item;
30 class tree_view;
31 
32 class tree_view_node : public widget
33 {
35  friend class tree_view;
36 
37 public:
38  using ptr_t = std::shared_ptr<tree_view_node>;
39  using node_children_vector = std::vector<ptr_t>;
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  * Adds a previously-constructed node as a child of this node at the given position.
78  *
79  * @param new_node A smart pointer to the node object to insert.
80  * @param index The item before which to add the new item,
81  * 0 == begin, -1 == end.
82  */
83  tree_view_node& add_child(ptr_t new_node, const int index = -1)
84  {
85  new_node->parent_node_ = this;
86  return add_child_impl(std::move(new_node), index);
87  }
88 
89  /**
90  * Adds a sibbling for a node at the end of the list.
91  *
92  * @param id The id of the node definition to use for the
93  * new node.
94  * @param data The data to send to the set_members of the
95  * widgets. If the member id is not an empty
96  * string it is only send to the widget that has
97  * the wanted id (if any). If the member id is an
98  * empty string, it is send to all members.
99  * Having both empty and non-empty id's gives
100  * undefined behavior.
101  */
103  add_sibling(const std::string& id,
104  const std::map<std::string /* widget id */, string_map>& data)
105  {
106  assert(!is_root_node());
107  return parent_node().add_child(id, data);
108  }
109 
110 private:
111  /** Implementation detail for @ref add_child. */
112  tree_view_node& add_child_impl(ptr_t&& new_node, const int index);
113 
114 public:
115  /**
116  * Is this node the root node?
117  *
118  * When the parent tree view is created it adds one special node, the root
119  * node. This node has no parent node and some other special features so
120  * several code paths need to check whether they are the parent node.
121  *
122  * This also returns true for a detecthed node returned with @ref tree_view::remove_node.
123  */
124  bool is_root_node() const
125  {
126  return parent_node_ == nullptr;
127  }
128 
129  /**
130  * The indentation level of the node.
131  *
132  * The root node starts at level 0.
133  */
134  unsigned get_indentation_level() const;
135 
136  /** Does the node have children? */
137  bool empty() const
138  {
139  return children_.empty();
140  }
141 
142  /** Is the node folded? */
143  bool is_folded() const
144  {
145  return !unfolded_;
146  }
147 
148 #if 0
149  // TODO: implement if different expand modes become necessary
150  enum expand_mode {
151  recursive_restore, // recursively restores collapse mode
152  recursive_expand, // recursively expands the children
153  not_recursive
154  };
155 #endif
156 
157  void fold(const bool recursive = false);
158  void unfold(const bool recursive = false);
159 
160  /**
161  * See @ref widget::create_walker.
162  *
163  * @todo Implement properly.
164  */
165  virtual iteration::walker_base* create_walker() override;
166 
168  {
169  return children_;
170  }
171 
173  {
174  assert(!is_root_node());
175  return parent_node().children();
176  }
177 
178  /** See @ref widget::find_at. */
179  virtual widget* find_at(const point& coordinate,
180  const bool must_be_active) override;
181 
182  /** See @ref widget::find_at. */
183  virtual const widget* find_at(const point& coordinate,
184  const bool must_be_active) const override;
185 
186  /** See @ref widget::find. */
187  widget* find(const std::string& id, const bool must_be_active) override;
188 
189  /** See @ref widget::find. */
190  const widget* find(const std::string& id,
191  const bool must_be_active) const override;
192 
193  /**
194  * The number of children in this widget.
195  */
196  std::size_t count_children() const
197  {
198  return children_.size();
199  }
200 
201  /**
202  * Removes all child items from the widget.
203  */
204  void clear();
205 
206  /***** ***** ***** setters / getters for members ***** ****** *****/
207 
208  /**
209  * Returns the parent node.
210  *
211  * @pre is_root_node() == false.
212  */
213  tree_view_node& parent_node();
214 
215  /** The const version of @ref parent_node. */
216  const tree_view_node& parent_node() const;
217 
219  {
220  return *tree_view_;
221  }
222 
223  const tree_view& get_tree_view() const
224  {
225  return *tree_view_;
226  }
227 
228  tree_view_node& get_child_at(int index);
229 
230  /**
231  * Calculates the node indices needed to get from the root node to this node.
232  */
233  std::vector<int> describe_path();
234 
235  tree_view_node* get_last_visible_parent_node();
236  tree_view_node* get_node_above();
237  tree_view_node* get_node_below();
238  tree_view_node* get_selectable_node_above();
239  tree_view_node* get_selectable_node_below();
240  void select_node(bool expand_parents = false);
241  grid& get_grid() { return grid_; }
242  void layout_initialize(const bool full_initialization) override;
243 
244  void clear_before_destruct();
245 
246 private:
247  int calculate_ypos();
248 
249  /** See @ref widget::request_reduce_width. */
250  virtual void request_reduce_width(const unsigned maximum_width) override;
251 
252  /**
253  * Our parent node.
254  *
255  * All nodes except the root node have a parent node.
256  */
258 
259  /** The tree view that owns us. */
261 
262  /** Grid holding our contents. */
264 
265  /**
266  * Our children.
267  *
268  * We want the returned child nodes to remain stable so store pointers.
269  */
271 
272  /** The toggle for the folded state. */
274 
275  /** The label to show our selected state. */
277 
278  bool unfolded_;
279  void fold_internal();
280  void unfold_internal();
281 
282  /**
283  * "Inherited" from widget.
284  *
285  * This version needs to call its children, which are it's child nodes.
286  */
287  void impl_populate_dirty_list(window& caller,
288  const std::vector<widget*>& call_stack);
289 
290  /** See @ref widget::calculate_best_size. */
291  virtual point calculate_best_size() const override;
292 
293  /** See @ref widget::disable_click_dismiss. */
294  bool disable_click_dismiss() const override;
295 
296  point calculate_best_size(const int indentation_level,
297  const unsigned indentation_step_size) const;
298  /** @param assume_visible if false (default) it will return 0 if the parent node is folded*/
299  point get_current_size(bool assume_visible = false) const;
300  point get_folded_size() const;
301  point get_unfolded_size() const;
302 
303  /** See @ref widget::set_origin. */
304  virtual void set_origin(const point& origin) override;
305 
306  /** See @ref widget::place. */
307  virtual void place(const point& origin, const point& size) override;
308 
309  unsigned
310  place(const unsigned indentation_step_size, point origin, unsigned width);
311 
312  /** See @ref widget::set_visible_rectangle. */
313  virtual void set_visible_rectangle(const SDL_Rect& rectangle) override;
314 
315  /** See @ref widget::impl_draw_children. */
316  virtual void impl_draw_children(surface& frame_buffer,
317  int x_offset,
318  int y_offset) override;
319 
320  // FIXME rename to icon
321  void signal_handler_left_button_click(const event::ui_event event);
322 
323  void signal_handler_label_left_button_click(const event::ui_event event,
324  bool& handled,
325  bool& halt);
326 
327  void
328  init_grid(grid* grid,
329  const std::map<std::string /* widget id */, string_map>& data);
330 
331  /**
332  * Returns the control_type of the @ref tree_view_node.
333  *
334  * This class does not derive from @ref styled_widget but the function behaves
335  * similar as @ref styled_widget::get_control_type.
336  */
337  const std::string& get_control_type() const;
338 };
339 
340 } // namespace gui2
Small abstract helper class.
tree_view_node * parent_node_
Our parent node.
bool is_root_node() const
Is this node the root node?
tree_view_node & add_child(ptr_t new_node, const int index=-1)
Adds a previously-constructed node as a child of this node at the given position. ...
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:203
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:22
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:30
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:86
std::shared_ptr< tree_view_node > ptr_t
The walker abstract base class.
Definition: walker.hpp:26
grid grid_
Grid holding our contents.
static thread_local std::deque< std::string > call_stack
For printing error messages when WFL parsing or evaluation fails, this contains the names of the WFL ...
Definition: function.cpp:46
A tree view is a control that holds several items of the same or different types. ...
Definition: tree_view.hpp:59
selectable_item * label_
The label to show our selected state.
Holds a 2D point.
Definition: point.hpp:23
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
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.
std::vector< ptr_t > node_children_vector
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:64
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:47