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/auxiliary/typed_formula.hpp"
18 #include "gui/core/linked_group_definition.hpp"
19 #include "gui/widgets/grid.hpp"
20 #include "color.hpp"
21 
22 #include "utils/functional.hpp"
23 
24 class config;
25 
26 namespace gui2
27 {
28 
29 class window;
30 
31 /**
32  * Builds a window.
33  *
34  * @param type                    The type id string of the window, this window
35  *                                must be registered at startup.
36  */
37 window* build(const std::string& type);
38 
39 /** Contains the info needed to instantiate a widget. */
40 struct builder_widget
41 {
42 public:
43 	/**
44 	 * The replacements type is used to define replacement types.
45 	 *
46 	 * Certain widgets need to build a part of themselves upon instantiation
47 	 * but at the time of the definition it's not yet known what exactly. By
48 	 * using and `[instance]' widget this decision can be postponed until
49 	 * instantiation.
50 	 */
51 	typedef std::map<std::string, std::shared_ptr<builder_widget>> replacements_map;
52 
53 	explicit builder_widget(const config& cfg);
54 
~builder_widgetgui2::builder_widget55 	virtual ~builder_widget()
56 	{
57 	}
58 
59 	virtual widget* build() const = 0;
60 
61 	virtual widget* build(const replacements_map& replacements) const = 0;
62 
63 	/** Parameters for the widget. */
64 	std::string id;
65 	std::string linked_group;
66 
67 	int debug_border_mode;
68 	color_t debug_border_color;
69 };
70 
71 typedef std::shared_ptr<builder_widget> builder_widget_ptr;
72 typedef std::shared_ptr<const builder_widget> builder_widget_const_ptr;
73 
74 /**
75  * Create a widget builder.
76  *
77  * This object holds the instance builder for a single widget.
78  *
79  * @param cfg                     The config object holding the information
80  *                                regarding the widget instance.
81  *
82  * @returns                       The builder for the widget instance.
83  */
84 builder_widget_ptr create_widget_builder(const config& cfg);
85 
86 /**
87  * Helper function to implement @ref build_single_widget_instance. This keeps the main
88  * logic in the implementation despite said function being a template and therefor
89  * needing to be fully implemented in the declaration.
90  */
91 widget* build_single_widget_instance_helper(const std::string& type, const config& cfg);
92 
93 /**
94  * Builds a single widget instance of the given type with the specified attributes.
95  *
96  * This should be used in place of creating a widget object directly, as it
97  * allows the widget-specific builder code to be executed.
98  *
99  * @tparam T                      The final widget type. The widget pointer will be
100  *                                cast to this.
101  *
102  * @param type                    String ID of the widget type.
103  * @param cfg                     Data config to pass to the widget's builder.
104  */
105 template<typename T>
build_single_widget_instance(const std::string & type,const config & cfg=config ())106 T* build_single_widget_instance(const std::string& type, const config& cfg = config())
107 {
108 	return dynamic_cast<T*>(build_single_widget_instance_helper(type, cfg));
109 }
110 
111 struct builder_grid : public builder_widget
112 {
113 public:
114 	explicit builder_grid(const config& cfg);
115 
116 	unsigned rows;
117 	unsigned cols;
118 
119 	/** The grow factor for the rows / columns. */
120 	std::vector<unsigned> row_grow_factor;
121 	std::vector<unsigned> col_grow_factor;
122 
123 	/** The flags per grid cell. */
124 	std::vector<unsigned> flags;
125 
126 	/** The border size per grid cell. */
127 	std::vector<unsigned> border_size;
128 
129 	/** The widgets per grid cell. */
130 	std::vector<builder_widget_ptr> widgets;
131 
132 	grid* build() const;
133 	widget* build(const replacements_map& replacements) const;
134 
135 	grid* build(grid* grid) const;
136 	void build(grid& grid, const replacements_map& replacements) const;
137 };
138 
139 typedef std::shared_ptr<builder_grid> builder_grid_ptr;
140 typedef std::shared_ptr<const builder_grid> builder_grid_const_ptr;
141 
142 class builder_window
143 {
144 public:
builder_window(const config & cfg)145 	explicit builder_window(const config& cfg)
146 		: resolutions()
147 		, id_(cfg["id"])
148 		, description_(cfg["description"])
149 	{
150 		read(cfg);
151 	}
152 
153 	struct window_resolution
154 	{
155 	public:
156 		explicit window_resolution(const config& cfg);
157 
158 		unsigned window_width;
159 		unsigned window_height;
160 
161 		bool automatic_placement;
162 
163 		typed_formula<unsigned> x;
164 		typed_formula<unsigned> y;
165 		typed_formula<unsigned> width;
166 		typed_formula<unsigned> height;
167 		typed_formula<bool> reevaluate_best_size;
168 
169 		wfl::function_symbol_table functions;
170 
171 		unsigned vertical_placement;
172 		unsigned horizontal_placement;
173 
174 		unsigned maximum_width;
175 		unsigned maximum_height;
176 
177 		bool click_dismiss;
178 
179 		std::string definition;
180 
181 		std::vector<linked_group_definition> linked_groups;
182 
183 		/** Helper struct to store information about the tips. */
184 		struct tooltip_info
185 		{
186 			tooltip_info(const config& cfg, const std::string& tagname);
187 
188 			std::string id;
189 		};
190 
191 		tooltip_info tooltip;
192 		tooltip_info helptip;
193 
194 		builder_grid_ptr grid;
195 	};
196 
197 	/**
198 	 * Resolution options for this window instance.
199 	 *
200 	 * The window widget handles resolution options differently from other widgets.
201 	 * Most specify their resolution options in their definitions. However, windows
202 	 * define different resolution options for each window *instance*. That enables
203 	 * each dialog to have its own set of options.
204 	 */
205 	std::vector<window_resolution> resolutions;
206 
207 private:
208 	void read(const config& cfg);
209 
210 	std::string id_;
211 	std::string description_;
212 };
213 
214 /**
215  * Builds a window.
216  */
217 window* build(const builder_window::window_resolution* res);
218 
219 } // namespace gui2
220