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