1 /*
2    Copyright (C) 2008 - 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/grid.hpp"
18 #include "gui/widgets/styled_widget.hpp"
19 #include "gui/core/window_builder.hpp"
20 
21 namespace gui2
22 {
23 namespace implementation
24 {
25 struct builder_styled_widget;
26 }
27 
28 /**
29  * A generic container base class.
30  *
31  * A container is a class build with multiple items either acting as one
32  * widget.
33  *
34  */
35 class container_base : public styled_widget
36 {
37 	friend class debug_layout_graph;
38 
39 public:
40 	explicit container_base(const implementation::builder_styled_widget& builder, const std::string& control_type);
41 
42 	/**
43 	 * Returns the client rect.
44 	 *
45 	 * The client rect is the area which is used for child items. The rest of
46 	 * the area of this widget is used for its own decoration.
47 	 *
48 	 * @returns                   The client rect.
49 	 */
50 	virtual SDL_Rect get_client_rect() const;
51 
52 	/***** ***** ***** ***** layout functions ***** ***** ***** *****/
53 
54 	/** See @ref widget::layout_initialize. */
55 	virtual void layout_initialize(const bool full_initialization) override;
56 
57 	/**
58 	 * Tries to reduce the width of a container.
59 	 *
60 	 * See @ref layout_algorithm for more information.
61 	 *
62 	 * @param maximum_width       The wanted maximum width.
63 	 */
64 	void reduce_width(const unsigned maximum_width);
65 
66 	/** See @ref widget::request_reduce_width. */
67 	virtual void request_reduce_width(const unsigned maximum_width) override;
68 
69 	/** See @ref widget::demand_reduce_width. */
70 	virtual void demand_reduce_width(const unsigned maximum_width) override;
71 
72 	/**
73 	 * Tries to reduce the height of a container.
74 	 *
75 	 * See @ref layout_algorithm for more information.
76 	 *
77 	 * @param maximum_height      The wanted maximum height.
78 	 */
79 	void reduce_height(const unsigned maximum_height);
80 
81 	/** See @ref widget::request_reduce_height. */
82 	virtual void request_reduce_height(const unsigned maximum_height) override;
83 
84 	/** See @ref widget::demand_reduce_height. */
85 	virtual void demand_reduce_height(const unsigned maximum_height) override;
86 
87 protected:
88 	/** See @ref widget::calculate_best_size. */
89 	virtual point calculate_best_size() const override;
90 
91 public:
92 	/** See @ref widget::can_wrap. */
93 	virtual bool can_wrap() const override;
94 
95 	/** See @ref widget::place. */
96 	virtual void place(const point& origin, const point& size) override;
97 
98 	/***** ***** ***** ***** Inherited ***** ***** ***** *****/
99 
100 	/** See @ref widget::has_widget. */
101 	virtual bool has_widget(const widget& widget) const override;
102 
103 	/** See @ref widget::set_origin. */
104 	virtual void set_origin(const point& origin) override;
105 
106 	/** See @ref widget::set_visible_rectangle. */
107 	virtual void set_visible_rectangle(const SDL_Rect& rectangle) override;
108 
109 	/** See @ref widget::impl_draw_children. */
110 	virtual void impl_draw_children(surface& frame_buffer,
111 									int x_offset,
112 									int y_offset) override;
113 
114 protected:
115 	/** See @ref widget::layout_children. */
116 	virtual void layout_children() override;
117 
118 	/** See @ref widget::child_populate_dirty_list. */
119 	virtual void
120 	child_populate_dirty_list(window& caller,
121 							  const std::vector<widget*>& call_stack) override;
122 
123 public:
124 	/** See @ref widget::find_at. */
125 	virtual widget* find_at(const point& coordinate,
126 							 const bool must_be_active) override;
127 
128 	/** See @ref widget::find_at. */
129 	virtual const widget* find_at(const point& coordinate,
130 								   const bool must_be_active) const override;
131 
132 	/** See @ref widget::find. */
133 	widget* find(const std::string& id, const bool must_be_active) override;
134 
135 	/** See @ref widget::find. */
136 	const widget* find(const std::string& id,
137 						const bool must_be_active) const override;
138 
139 	/** See @ref styled_widget::set_active. */
140 	virtual void set_active(const bool active) override;
141 
142 	/** See @ref widget::disable_click_dismiss. */
143 	bool disable_click_dismiss() const override;
144 
145 	/**
146 	 * See @ref widget::create_walker.
147 	 *
148 	 * @todo Implement properly.
149 	 */
create_walker()150 	virtual iteration::walker_base* create_walker() override
151 	{
152 		return nullptr;
153 	}
154 
155 	/**
156 	 * Initializes and builds the grid.
157 	 *
158 	 * This function should only be called upon an empty grid.
159 	 *
160 	 * @param grid_builder        The builder for the grid.
161 	 */
162 	void init_grid(const std::shared_ptr<builder_grid>& grid_builder);
163 
164 	/***** **** ***** ***** wrappers to the grid **** ********* *****/
165 
begin()166 	grid::iterator begin()
167 	{
168 		return grid_.begin();
169 	}
end()170 	grid::iterator end()
171 	{
172 		return grid_.end();
173 	}
174 
add_row(const unsigned count=1)175 	unsigned add_row(const unsigned count = 1)
176 	{
177 		return grid_.add_row(count);
178 	}
179 
set_rows(const unsigned rows)180 	void set_rows(const unsigned rows)
181 	{
182 		grid_.set_rows(rows);
183 	}
get_rows() const184 	unsigned int get_rows() const
185 	{
186 		return grid_.get_rows();
187 	}
188 
set_cols(const unsigned cols)189 	void set_cols(const unsigned cols)
190 	{
191 		grid_.set_cols(cols);
192 	}
get_cols() const193 	unsigned int get_cols() const
194 	{
195 		return grid_.get_cols();
196 	}
197 
set_rows_cols(const unsigned rows,const unsigned cols)198 	void set_rows_cols(const unsigned rows, const unsigned cols)
199 	{
200 		grid_.set_rows_cols(rows, cols);
201 	}
202 
set_child(widget * widget,const unsigned row,const unsigned col,const unsigned flags,const unsigned border_size)203 	void set_child(widget* widget,
204 				   const unsigned row,
205 				   const unsigned col,
206 				   const unsigned flags,
207 				   const unsigned border_size)
208 	{
209 		grid_.set_child(widget, row, col, flags, border_size);
210 	}
211 
set_row_grow_factor(const unsigned row,const unsigned factor)212 	void set_row_grow_factor(const unsigned row, const unsigned factor)
213 	{
214 		grid_.set_row_grow_factor(row, factor);
215 	}
216 
set_column_grow_factor(const unsigned column,const unsigned factor)217 	void set_column_grow_factor(const unsigned column, const unsigned factor)
218 	{
219 		grid_.set_column_grow_factor(column, factor);
220 	}
221 
222 public:
223 	/***** ***** ***** setters / getters for members ***** ****** *****/
224 
225 	// Public due to the fact that window needs to be able to swap the
226 	// children, might be protected again later.
get_grid() const227 	const grid& get_grid() const
228 	{
229 		return grid_;
230 	}
get_grid()231 	grid& get_grid()
232 	{
233 		return grid_;
234 	}
235 
236 private:
237 	/** The grid which holds the child objects. */
238 	grid grid_;
239 
240 	/** Returns the space used by the border. */
241 	virtual point border_space() const;
242 
243 	/**
244 	 * Helper for set_active.
245 	 *
246 	 * This function should set the styled_widget itself active. It's called by
247 	 * set_active if the state needs to change. The widget is set to dirty() by
248 	 * set_active so we only need to change the state.
249 	 */
250 	virtual void set_self_active(const bool active) = 0;
251 
252 	void inject_linked_groups();
253 };
254 
255 } // namespace gui2
256