1 /*************************************************************************/
2 /*  control.h                                                            */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #ifndef CONTROL_H
31 #define CONTROL_H
32 
33 #include "math_2d.h"
34 #include "rid.h"
35 #include "scene/2d/canvas_item.h"
36 #include "scene/gui/input_action.h"
37 #include "scene/main/node.h"
38 #include "scene/main/timer.h"
39 #include "scene/resources/theme.h"
40 /**
41 	@author Juan Linietsky <reduzio@gmail.com>
42 */
43 
44 class Viewport;
45 class Label;
46 class Panel;
47 
48 class Control : public CanvasItem {
49 
50 	OBJ_TYPE(Control, CanvasItem);
51 	OBJ_CATEGORY("GUI Nodes");
52 
53 public:
54 	enum AnchorType {
55 		ANCHOR_BEGIN,
56 		ANCHOR_END,
57 		ANCHOR_RATIO,
58 		ANCHOR_CENTER,
59 	};
60 
61 	enum FocusMode {
62 		FOCUS_NONE,
63 		FOCUS_CLICK,
64 		FOCUS_ALL
65 	};
66 
67 	enum SizeFlags {
68 
69 		SIZE_EXPAND = 1,
70 		SIZE_FILL = 2,
71 		SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL
72 
73 	};
74 
75 	enum CursorShape {
76 		CURSOR_ARROW,
77 		CURSOR_IBEAM,
78 		CURSOR_POINTING_HAND,
79 		CURSOR_CROSS,
80 		CURSOR_WAIT,
81 		CURSOR_BUSY,
82 		CURSOR_DRAG,
83 		CURSOR_CAN_DROP,
84 		CURSOR_FORBIDDEN,
85 		CURSOR_VSIZE,
86 		CURSOR_HSIZE,
87 		CURSOR_BDIAGSIZE,
88 		CURSOR_FDIAGSIZE,
89 		CURSOR_MOVE,
90 		CURSOR_VSPLIT,
91 		CURSOR_HSPLIT,
92 		CURSOR_HELP,
93 		CURSOR_MAX
94 	};
95 
96 private:
97 	struct CComparator {
98 
operatorCComparator99 		bool operator()(const Control *p_a, const Control *p_b) const {
100 			if (p_a->get_canvas_layer() == p_b->get_canvas_layer())
101 				return p_b->is_greater_than(p_a);
102 			else
103 				return p_a->get_canvas_layer() < p_b->get_canvas_layer();
104 		}
105 	};
106 
107 	struct Data {
108 
109 		Point2 pos_cache;
110 		Size2 size_cache;
111 
112 		float margin[4];
113 		AnchorType anchor[4];
114 		FocusMode focus_mode;
115 
116 		float rotation;
117 		Vector2 scale;
118 
119 		bool pending_resize;
120 
121 		int h_size_flags;
122 		int v_size_flags;
123 		float expand;
124 		bool pending_min_size_update;
125 		Point2 custom_minimum_size;
126 
127 		bool ignore_mouse;
128 		bool stop_mouse;
129 
130 		Control *parent;
131 		ObjectID drag_owner;
132 		bool modal;
133 		bool modal_exclusive;
134 		uint64_t modal_frame; //frame used to put something as modal
135 		Ref<Theme> theme;
136 		Control *theme_owner;
137 		String tooltip;
138 		CursorShape default_cursor;
139 
140 		List<Control *>::Element *MI; //modal item
141 		List<Control *>::Element *SI;
142 		List<Control *>::Element *RI;
143 
144 		CanvasItem *parent_canvas_item;
145 
146 		ObjectID modal_prev_focus_owner;
147 
148 		NodePath focus_neighbour[4];
149 
150 		HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override;
151 		HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override;
152 		HashMap<StringName, Ref<StyleBox>, StringNameHasher> style_override;
153 		HashMap<StringName, Ref<Font>, StringNameHasher> font_override;
154 		HashMap<StringName, Color, StringNameHasher> color_override;
155 		HashMap<StringName, int, StringNameHasher> constant_override;
156 		Map<Ref<Font>, int> font_refcount;
157 
158 	} data;
159 
160 	// used internally
161 	Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Matrix32 &p_xform, Matrix32 &r_inv_xform);
162 
163 	void _window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest);
164 	Control *_get_focus_neighbour(Margin p_margin, int p_count = 0);
165 
166 	void _set_anchor(Margin p_margin, AnchorType p_anchor);
167 
168 	float _get_parent_range(int p_idx) const;
169 	float _get_range(int p_idx) const;
170 	float _s2a(float p_val, AnchorType p_anchor, float p_range) const;
171 	float _a2s(float p_val, AnchorType p_anchor, float p_range) const;
172 	void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true);
173 	void _theme_changed();
174 
175 	void _change_notify_margins();
176 	void _update_minimum_size();
177 
178 	void _update_scroll();
179 	void _resize(const Size2 &p_size);
180 
181 	void _size_changed();
182 	String _get_tooltip() const;
183 
184 	// Deprecated, should be removed in a future version.
185 	void _set_rotation_deg(float p_degrees);
186 	float _get_rotation_deg() const;
187 
188 	void _ref_font(Ref<Font> p_sc);
189 	void _unref_font(Ref<Font> p_sc);
190 	void _font_changed();
191 
192 	friend class Viewport;
193 	void _modal_stack_remove();
194 	void _modal_set_prev_focus_owner(ObjectID p_prev);
195 
196 protected:
197 	//virtual void _window_input_event(InputEvent p_event);
198 
199 	bool _set(const StringName &p_name, const Variant &p_value);
200 	bool _get(const StringName &p_name, Variant &r_ret) const;
201 	void _get_property_list(List<PropertyInfo> *p_list) const;
202 
203 	void _notification(int p_notification);
204 
205 	static void _bind_methods();
206 
207 	//bind helpers
208 
209 public:
210 	enum {
211 
212 		/*		NOTIFICATION_DRAW=30,
213 		NOTIFICATION_VISIBILITY_CHANGED=38*/
214 		NOTIFICATION_RESIZED = 40,
215 		NOTIFICATION_MOUSE_ENTER = 41,
216 		NOTIFICATION_MOUSE_EXIT = 42,
217 		NOTIFICATION_FOCUS_ENTER = 43,
218 		NOTIFICATION_FOCUS_EXIT = 44,
219 		NOTIFICATION_THEME_CHANGED = 45,
220 		NOTIFICATION_MODAL_CLOSE = 46,
221 		NOTIFICATION_SCROLL_BEGIN = 47,
222 		NOTIFICATION_SCROLL_END = 48,
223 
224 	};
225 
226 	virtual Variant edit_get_state() const;
227 	virtual void edit_set_state(const Variant &p_state);
228 	virtual void edit_set_rect(const Rect2 &p_edit_rect);
229 	virtual Size2 edit_get_minimum_size() const;
230 
231 	void accept_event();
232 
233 	virtual Size2 get_minimum_size() const;
234 	virtual Size2 get_combined_minimum_size() const;
235 	virtual bool has_point(const Point2 &p_point) const;
236 	virtual bool clips_input() const;
237 	virtual void set_drag_forwarding(Control *p_target);
238 	virtual Variant get_drag_data(const Point2 &p_point);
239 	virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
240 	virtual void drop_data(const Point2 &p_point, const Variant &p_data);
241 	void set_drag_preview(Control *p_control);
242 	void force_drag(const Variant &p_data, Control *p_control);
243 
244 	void set_custom_minimum_size(const Size2 &p_custom);
245 	Size2 get_custom_minimum_size() const;
246 
247 	bool is_window_modal_on_top() const;
248 	uint64_t get_modal_frame() const; //frame in which this was made modal
249 
250 	Control *get_parent_control() const;
251 
252 	/* POSITIONING */
253 
254 	void set_anchor(Margin p_margin, AnchorType p_anchor, bool p_keep_margin = false);
255 	void set_anchor_and_margin(Margin p_margin, AnchorType p_anchor, float p_pos);
256 
257 	AnchorType get_anchor(Margin p_margin) const;
258 
259 	void set_margin(Margin p_margin, float p_value);
260 
261 	void set_begin(const Point2 &p_point); // helper
262 	void set_end(const Point2 &p_point); // helper
263 
264 	float get_margin(Margin p_margin) const;
265 	Point2 get_begin() const;
266 	Point2 get_end() const;
267 
268 	void set_pos(const Point2 &p_point);
269 	void set_size(const Size2 &p_size);
270 	void set_global_pos(const Point2 &p_point);
271 
272 	Point2 get_pos() const;
273 	Point2 get_global_pos() const;
274 	Size2 get_size() const;
275 	Rect2 get_rect() const;
276 	Rect2 get_global_rect() const;
277 	Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
278 
279 	void set_rotation(float p_radians);
280 	void set_rotation_deg(float p_degrees);
281 	float get_rotation() const;
282 	float get_rotation_deg() const;
283 
284 	void set_scale(const Vector2 &p_scale);
285 	Vector2 get_scale() const;
286 
287 	void set_area_as_parent_rect(int p_margin = 0);
288 
289 	void show_modal(bool p_exclusive = false);
290 
291 	void set_theme(const Ref<Theme> &p_theme);
292 	Ref<Theme> get_theme() const;
293 
294 	void set_h_size_flags(int p_flags);
295 	int get_h_size_flags() const;
296 
297 	void set_v_size_flags(int p_flags);
298 	int get_v_size_flags() const;
299 
300 	void set_stretch_ratio(float p_ratio);
301 	float get_stretch_ratio() const;
302 
303 	void minimum_size_changed();
304 
305 	/* FOCUS */
306 
307 	void set_focus_mode(FocusMode p_focus_mode);
308 	FocusMode get_focus_mode() const;
309 	bool has_focus() const;
310 	void grab_focus();
311 	void release_focus();
312 
313 	Control *find_next_valid_focus() const;
314 	Control *find_prev_valid_focus() const;
315 
316 	void set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour);
317 	NodePath get_focus_neighbour(Margin p_margin) const;
318 
319 	Control *get_focus_owner() const;
320 
321 	void set_ignore_mouse(bool p_ignore);
322 	bool is_ignoring_mouse() const;
323 
324 	void set_stop_mouse(bool p_stop);
325 	bool is_stopping_mouse() const;
326 
327 	/* SKINNING */
328 
329 	void add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon);
330 	void add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader);
331 	void add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style);
332 	void add_font_override(const StringName &p_name, const Ref<Font> &p_font);
333 	void add_color_override(const StringName &p_name, const Color &p_color);
334 	void add_constant_override(const StringName &p_name, int p_constant);
335 
336 	Ref<Texture> get_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
337 	Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
338 	Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
339 	Ref<Font> get_font(const StringName &p_name, const StringName &p_type = StringName()) const;
340 	Color get_color(const StringName &p_name, const StringName &p_type = StringName()) const;
341 	int get_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
342 
343 	bool has_icon_override(const StringName &p_name) const;
344 	bool has_shader_override(const StringName &p_name) const;
345 	bool has_stylebox_override(const StringName &p_name) const;
346 	bool has_font_override(const StringName &p_name) const;
347 	bool has_color_override(const StringName &p_name) const;
348 	bool has_constant_override(const StringName &p_name) const;
349 
350 	bool has_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
351 	bool has_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
352 	bool has_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
353 	bool has_font(const StringName &p_name, const StringName &p_type = StringName()) const;
354 	bool has_color(const StringName &p_name, const StringName &p_type = StringName()) const;
355 	bool has_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
356 
357 	/* TOOLTIP */
358 
359 	void set_tooltip(const String &p_tooltip);
360 	virtual String get_tooltip(const Point2 &p_pos) const;
361 
362 	/* CURSOR */
363 
364 	void set_default_cursor_shape(CursorShape p_shape);
365 	CursorShape get_default_cursor_shape() const;
366 	virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const;
367 
368 	virtual Rect2 get_item_rect() const;
369 	virtual Matrix32 get_transform() const;
370 
371 	bool is_toplevel_control() const;
372 
373 	Size2 get_parent_area_size() const;
374 
375 	void grab_click_focus();
376 
377 	void warp_mouse(const Point2 &p_to_pos);
378 
379 	virtual bool is_text_field() const;
380 
381 	Control *get_root_parent_control() const;
382 
383 	Control();
384 	~Control();
385 };
386 
387 VARIANT_ENUM_CAST(Control::AnchorType);
388 VARIANT_ENUM_CAST(Control::FocusMode);
389 VARIANT_ENUM_CAST(Control::SizeFlags);
390 VARIANT_ENUM_CAST(Control::CursorShape);
391 
392 #endif
393