The Battle for Wesnoth  1.15.2+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::
123  * remove_node.
124  */
125  bool is_root_node() const
126  {
127  return parent_node_ == nullptr;
128  }
129 
130  /**
131  * The indentation level of the node.
132  *
133  * The root node starts at level 0.
134  */
135  unsigned get_indentation_level() const;
136 
137  /** Does the node have children? */
138  bool empty() const
139  {
140  return children_.empty();
141  }
142 
143  /** Is the node folded? */
144  bool is_folded() const
145  {
146  return !unfolded_;
147  }
148 
149 #if 0
150  // TODO: implement if different expand modes become necessary
151  enum expand_mode {
152  recursive_restore, // recursively restores collapse mode
153  recursive_expand, // recursively expands the children
154  not_recursive
155  };
156 #endif
157 
158  void fold(const bool recursive = false);
159  void unfold(const bool recursive = false);
160 
161  /**
162  * See @ref widget::create_walker.
163  *
164  * @todo Implement properly.
165  */
166  virtual iteration::walker_base* create_walker() override;
167 
169  {
170  return children_;
171  }
172 
173  /** See @ref widget::find_at. */
174  virtual widget* find_at(const point& coordinate,
175  const bool must_be_active) override;
176 
177  /** See @ref widget::find_at. */
178  virtual const widget* find_at(const point& coordinate,
179  const bool must_be_active) const override;
180 
181  /** See @ref widget::find. */
182  widget* find(const std::string& id, const bool must_be_active) override;
183 
184  /** See @ref widget::find. */
185  const widget* find(const std::string& id,
186  const bool must_be_active) const override;
187 
188  /**
189  * The number of children in this widget.
190  */
191  std::size_t count_children() const
192  {
193  return children_.size();
194  }
195 
196  /**
197  * Removes all child items from the widget.
198  */
199  void clear();
200 
201  /***** ***** ***** setters / getters for members ***** ****** *****/
202 
203  /**
204  * Returns the parent node.
205  *
206  * @pre is_root_node() == false.
207  */
208  tree_view_node& parent_node();
209 
210  /** The const version of @ref parent_node. */
211  const tree_view_node& parent_node() const;
212 
214  {
215  return *tree_view_;
216  }
217 
218  const tree_view& get_tree_view() const
219  {
220  return *tree_view_;
221  }
222 
223  tree_view_node& get_child_at(int index);
224 
225  /**
226  * Calculates the node indices needed to get from the root node to this node.
227  */
228  std::vector<int> describe_path();
229 
230  tree_view_node* get_last_visible_parent_node();
231  tree_view_node* get_node_above();
232  tree_view_node* get_node_below();
233  tree_view_node* get_selectable_node_above();
234  tree_view_node* get_selectable_node_below();
235  void select_node(bool expand_parents = false);
236  grid& get_grid() { return grid_; }
237  void layout_initialize(const bool full_initialization) override;
238 
239  void clear_before_destruct();
240 
241 private:
242  int calculate_ypos();
243 
244  /** See @ref widget::request_reduce_width. */
245  virtual void request_reduce_width(const unsigned maximum_width) override;
246 
247  /**
248  * Our parent node.
249  *
250  * All nodes except the root node have a parent node.
251  */
253 
254  /** The tree view that owns us. */
256 
257  /** Grid holding our contents. */
259 
260  /**
261  * Our children.
262  *
263  * We want the returned child nodes to remain stable so store pointers.
264  */
266 
267  /** The toggle for the folded state. */
269 
270  /** The label to show our selected state. */
272 
273  bool unfolded_;
274  void fold_internal();
275  void unfold_internal();
276 
277  /**
278  * "Inherited" from widget.
279  *
280  * This version needs to call its children, which are it's child nodes.
281  */
282  void impl_populate_dirty_list(window& caller,
283  const std::vector<widget*>& call_stack);
284 
285  /** See @ref widget::calculate_best_size. */
286  virtual point calculate_best_size() const override;
287 
288  /** See @ref widget::disable_click_dismiss. */
289  bool disable_click_dismiss() const override;
290 
291  point calculate_best_size(const int indentation_level,
292  const unsigned indentation_step_size) const;
293  /** @param assume_visible if false (default) it will return 0 if the parent node is folded*/
294  point get_current_size(bool assume_visible = false) const;
295  point get_folded_size() const;
296  point get_unfolded_size() const;
297 
298  /** See @ref widget::set_origin. */
299  virtual void set_origin(const point& origin) override;
300 
301  /** See @ref widget::place. */
302  virtual void place(const point& origin, const point& size) override;
303 
304  unsigned
305  place(const unsigned indentation_step_size, point origin, unsigned width);
306 
307  /** See @ref widget::set_visible_rectangle. */
308  virtual void set_visible_rectangle(const SDL_Rect& rectangle) override;
309 
310  /** See @ref widget::impl_draw_children. */
311  virtual void impl_draw_children(surface& frame_buffer,
312  int x_offset,
313  int y_offset) override;
314 
315  // FIXME rename to icon
316  void signal_handler_left_button_click(const event::ui_event event);
317 
318  void signal_handler_label_left_button_click(const event::ui_event event,
319  bool& handled,
320  bool& halt);
321 
322  void
323  init_grid(grid* grid,
324  const std::map<std::string /* widget id */, string_map>& data);
325 
326  /**
327  * Returns the control_type of the @ref tree_view_node.
328  *
329  * This class does not derive from @ref styled_widget but the function behaves
330  * similar as @ref styled_widget::get_control_type.
331  */
332  const std::string& get_control_type() const;
333 };
334 
335 } // 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:47
void clear(const std::string &key)
Definition: general.cpp:205
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.
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()
bool find(E event, F functor)
Tests whether an event handler is available.
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:63
static std::deque< std::string > call_stack
Definition: function.cpp:39
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:55