1 /*
2 	This file is part of Warzone 2100.
3 	Copyright (C) 1999-2004  Eidos Interactive
4 	Copyright (C) 2005-2020  Warzone 2100 Project
5 
6 	Warzone 2100 is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 2 of the License, or
9 	(at your option) any later version.
10 
11 	Warzone 2100 is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with Warzone 2100; if not, write to the Free Software
18 	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 /**
21  *	@file lib/widget/widget.h
22  *	Definitions for the Widget library
23  *	@defgroup Widget Widget system
24  *	Warzone uses a pixel layout, callback based widget code. While it has several
25  *	fallbacks for drawing standard widgets, usually you want to specify your
26  *	own drawing callbacks.
27  *	@{
28  */
29 
30 #ifndef __INCLUDED_LIB_WIDGET_WIDGET_H__
31 #define __INCLUDED_LIB_WIDGET_WIDGET_H__
32 
33 #include "lib/framework/frame.h"
34 #include "lib/ivis_opengl/piepalette.h"
35 #include "widgbase.h"
36 #include <string>
37 
38 /***********************************************************************************
39  *
40  * Widget style definitions - these control how the basic widget appears on screen
41  */
42 
43 /************ Form styles ****************/
44 
45 #define WFORM_PLAIN		0	///< Plain form
46 
47 /** Invisible (i.e. see through) form - can be used in conjunction with WFORM_PLAIN. */
48 #define WFORM_INVISIBLE		2
49 
50 #define WFORM_CLICKABLE		4	///< Clickable form - return form id when the form is clicked
51 #define	WFORM_NOCLICKMOVE	8	///< Disable movement on a clickable form
52 
53 /**
54  * Control whether the primary or secondary buttons work on a clickable form.
55  * Primary works by default - this turns it off.
56  */
57 #define WFORM_NOPRIMARY		0x10
58 #define WFORM_SECONDARY		0x20	///< Enable secondary buttons
59 
60 /************ Label styles ***************/
61 
62 #define WLAB_PLAIN		0	///< Plain text only label
63 enum WzTextAlignment
64 {
65 	WLAB_ALIGNLEFT        = 0,      ///< Align the text at the left of the box
66 	WLAB_ALIGNCENTRE      = 1,      ///< Centre the text
67 	WLAB_ALIGNRIGHT       = 2,      ///< Align the text at the right of the box
68 	WLAB_ALIGNTOPLEFT     = 4,      ///< Align the text at the top left of the box
69 	WLAB_ALIGNTOP         = 4 + 1,  ///< Align the text at the top of the box
70 	WLAB_ALIGNTOPRIGHT    = 4 + 2,  ///< Align the text at the top right of the box
71 	WLAB_ALIGNBOTTOMLEFT  = 8,      ///< Align the text at the bottom left of the box
72 	WLAB_ALIGNBOTTOM      = 8 + 1,  ///< Align the text at the bottom of the box
73 	WLAB_ALIGNBOTTOMRIGHT = 8 + 2,  ///< Align the text at the bottom rightof the box
74 };
75 
76 /************ Button styles **************/
77 
78 #define WBUT_PLAIN		0	///< Plain button (text with a box around it)
79 
80 
81 /**
82  * Control whether the primary or secondary buttons work on a button. Primary works by default -
83  * this turns it off.
84  */
85 #define WBUT_NOPRIMARY		0x10
86 #define WBUT_SECONDARY		0x20	///< Enable secondary buttons.
87 #define WBUT_TXTCENTRE		0x40	///< Text only buttons. centre the text?
88 
89 /*********** Edit Box styles *************/
90 
91 #define WEDB_PLAIN		0	///< Plain edit box (text with a box around it)
92 
93 /*********** Bar Graph styles ************/
94 
95 #define WBAR_PLAIN		0	////< Plain bar graph
96 #define WBAR_TROUGH		1	///< Bar graph with a trough showing empty percentage
97 #define WBAR_DOUBLE		2	///< Double bar graph, one on top of other
98 
99 /*********** Slider styles ***************/
100 
101 #define WSLD_PLAIN		0	///< Plain slider
102 
103 /***********************************************************************************/
104 
105 /* An optional function that is used to initialize the pUserData pointer per widget instance */
106 /* (Useful if re-using a W_*INIT structure for multiple widget instances) */
107 typedef std::function<void* ()> WIDGET_INITIALIZE_PUSERDATA_FUNC;
108 
109 struct Padding
110 {
111 	uint32_t top;
112 	uint32_t right;
113 	uint32_t bottom;
114 	uint32_t left;
115 };
116 
117 /** The basic initialisation structure */
118 struct W_INIT
119 {
120 	W_INIT();
121 
122 	UDWORD                  formID;                 ///< ID number of form to put widget on. ID == 0 specifies the default form for the screen
123 	UWORD                   majorID;                ///< Which tab to put the widget on for a tabbed form
124 	UDWORD                  id;                     ///< Unique id number (chosen by user)
125 	UDWORD                  style;                  ///< widget style
126 	SWORD                   x, y;                   ///< screen location
127 	UWORD                   width, height;          ///< widget size
128 	WIDGET_DISPLAY          pDisplay;               ///< Optional display function
129 	WIDGET_CALLBACK         pCallback;              ///< Optional callback function
130 	void                   *pUserData;              ///< Optional user data pointer
131 	UDWORD                  UserData;               ///< User data (if any)
132 	WIDGET_CALCLAYOUT_FUNC  calcLayout;				///< Optional calculate layout callback function
133 	WIDGET_ONDELETE_FUNC	onDelete;				///< Optional callback called when the Widget is about to be deleted
134 	WIDGET_HITTEST_FUNC		customHitTest;			///< Optional custom hit-testing function
135 	WIDGET_INITIALIZE_PUSERDATA_FUNC initPUserDataFunc;	///< (Optional) Used to initialize the pUserData pointer per widget instance
136 };
137 
138 /** Form initialisation structure */
139 struct W_FORMINIT : public W_INIT
140 {
141 	W_FORMINIT();
142 
143 	bool                    disableChildren;
144 	std::string	            pTip;			///< Tool tip for the form itself
145 };
146 
147 /** Label initialisation structure */
148 struct W_LABINIT : public W_INIT
149 {
150 	W_LABINIT();
151 
152 	WzString	            pText;			///< label text
153 	std::string	            pTip;			///< Tool tip for the label.
154 	enum iV_fonts           FontID;			///< ID of the IVIS font to use for this widget.
155 };
156 
157 /** Button initialisation structure */
158 struct W_BUTINIT : public W_INIT
159 {
160 	W_BUTINIT();
161 
162 	const char *pText;	///< Button text
163 	std::string pTip;	///< Tool tip text
164 	enum iV_fonts FontID;	//< ID of the IVIS font to use for this widget.
165 };
166 
167 /** Edit box initialisation structure */
168 struct W_EDBINIT : public W_INIT
169 {
170 	W_EDBINIT();
171 
172 	const char *pText;		///< initial contents of the edit box
173 	enum iV_fonts FontID;		///< ID of the IVIS font to use for this widget.
174 	WIDGET_DISPLAY pBoxDisplay;	///< Optional callback to display the form.
175 };
176 
177 /* Orientation flags for the bar graph */
178 enum WBAR_ORIENTATION
179 {
180 	WBAR_LEFT = 1,                  ///< Bar graph fills from left to right
181 	WBAR_RIGHT,                     ///< Bar graph fills from right to left
182 	WBAR_TOP,                       ///< Bar graph fills from top to bottom
183 	WBAR_BOTTOM,                    ///< Bar graph fills from bottom to top
184 };
185 
186 /** Bar Graph initialisation structure */
187 struct W_BARINIT : public W_INIT
188 {
189 	W_BARINIT();
190 
191 	WBAR_ORIENTATION orientation;           ///< Orientation of the bar on the widget
192 	UWORD		size;			///< Initial percentage of the graph that is filled
193 	UWORD		minorSize;		///< Percentage of second bar graph if there is one
194 	UWORD		iRange;			///< Maximum range
195 	int             denominator;            ///< Denominator, 1 by default.
196 	int             precision;              ///< Number of places after the decimal point to display, 0 by default.
197 	PIELIGHT	sCol;			///< Bar colour
198 	PIELIGHT	sMinorCol;		///< Minor bar colour
199 	std::string      pTip;			///< Tool tip text
200 };
201 
202 
203 /* Orientation of the slider */
204 enum WSLD_ORIENTATION
205 {
206 	WSLD_LEFT = 1,                  ///< Slider is horizontal and starts at left
207 	WSLD_RIGHT,                     ///< Slider is horizontal and starts at the right
208 	WSLD_TOP,                       ///< Slider is vertical and starts at the top
209 	WSLD_BOTTOM,                    ///< Slider is vertical and starts at the bottom
210 };
211 
212 /** Slider initialisation structure */
213 struct W_SLDINIT : public W_INIT
214 {
215 	W_SLDINIT();
216 
217 	WSLD_ORIENTATION orientation;           ///< Orientation of the slider
218 	UWORD		numStops;		///< Number of stops on the slider
219 	UWORD		barSize;		///< Size of the bar
220 	UWORD		pos;			///< Initial position of the slider bar
221 	std::string pTip;			///< Tip string
222 };
223 
224 /***********************************************************************************/
225 
226 /** The maximum value for bar graph size */
227 #define WBAR_SCALE		100
228 
229 /** Initialise the widget module */
230 bool widgInitialise();
231 
232 /** Reset the widget module */
233 void widgReset();
234 
235 /** Shut down the widget module */
236 void widgShutDown();
237 
238 /** Used by the notifications system to register forms that are "over the top", and may consume click / mouse-over events */
239 void widgRegisterOverlayScreen(const std::shared_ptr<W_SCREEN> &psScreen, uint16_t zOrder);
240 void widgRegisterOverlayScreenOnTopOfScreen(const std::shared_ptr<W_SCREEN> &psScreen, const std::shared_ptr<W_SCREEN> &priorScreen);
241 void widgRemoveOverlayScreen(const std::shared_ptr<W_SCREEN> &psScreen);
242 bool isMouseOverScreenOverlayChild(int mx, int my); // global mouse coordinates - i.e. those returned from mouseX()/mouseY()
243 bool isMouseClickDownOnScreenOverlayChild();
244 bool isMouseOverSomeWidget(const std::shared_ptr<W_SCREEN> &psScreen);
245 void widgScheduleTask(std::function<void ()> f);
246 
247 /** Add a form to the widget screen */
248 WZ_DECL_NONNULL(2) W_FORM *widgAddForm(const std::shared_ptr<W_SCREEN> &psScreen, const W_FORMINIT *psInit);
249 
250 /** Add a label to the widget screen */
251 WZ_DECL_NONNULL(2) W_LABEL *widgAddLabel(const std::shared_ptr<W_SCREEN> &psScreen, const W_LABINIT *psInit);
252 
253 /** Add a button to a form */
254 WZ_DECL_NONNULL(2) W_BUTTON *widgAddButton(const std::shared_ptr<W_SCREEN> &psScreen, const W_BUTINIT *psInit);
255 
256 /** Add an edit box to a form */
257 WZ_DECL_NONNULL(2) W_EDITBOX *widgAddEditBox(const std::shared_ptr<W_SCREEN> &psScreen, const W_EDBINIT *psInit);
258 
259 /** Add a bar graph to a form */
260 WZ_DECL_NONNULL(2) W_BARGRAPH *widgAddBarGraph(const std::shared_ptr<W_SCREEN> &psScreen, const W_BARINIT *psInit);
261 
262 /** Add a slider to a form */
263 WZ_DECL_NONNULL(2) W_SLIDER *widgAddSlider(const std::shared_ptr<W_SCREEN> &psScreen, const W_SLDINIT *psInit);
264 
265 /** Delete a widget from the screen */
266 void widgDelete(WIDGET *widget);
267 void widgDelete(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
268 void widgDeleteLater(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
269 
270 /** Hide a widget */
271 void widgHide(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
272 
273 /** Reveal a widget */
274 void widgReveal(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
275 
276 /** Return a pointer to a buffer containing the current string of a widget if any.
277  * This will always return a valid string pointer.
278  * NOTE: The string must be copied out of the buffer
279  */
280 const char *widgGetString(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
281 
282 /** Return the current string of a widget, if any.
283  * This will always return a string. If the widget doesn't have a string, it will return an empty WzString.
284  */
285 const WzString& widgGetWzString(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
286 
287 /** Set the text in a widget */
288 void widgSetString(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, const char *pText);
289 
290 /** Get the current position of a slider bar */
291 UDWORD widgGetSliderPos(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
292 
293 /** Set the current size of a bar graph */
294 void widgSetBarSize(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, UDWORD size);
295 
296 /** Set the current size of a minor bar on a double graph */
297 void widgSetMinorBarSize(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, UDWORD size);
298 
299 /** Return the ID of the widget the mouse was over this frame */
300 UDWORD widgGetMouseOver(const std::shared_ptr<W_SCREEN> &psScreen);
301 
302 /** Return the user data for a widget */
303 void *widgGetUserData(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
304 
305 /** Set the user data for a widget */
306 void widgSetUserData(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, void *UserData);
307 
308 /** Return the user data for a widget */
309 UDWORD widgGetUserData2(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
310 
311 /** Set the user data for a widget */
312 void widgSetUserData2(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, UDWORD UserData);
313 
314 /** Get widget structure */
315 WIDGET *widgGetFromID(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
316 
317 /* Find a widget on a form from its id number */
318 std::shared_ptr<WIDGET> widgFormGetFromID(const std::shared_ptr<WIDGET>& widget, UDWORD id);
319 
320 /** Set tip string for a widget */
321 void widgSetTip(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, std::string pTip);
322 
323 /** Colour numbers */
324 enum _w_colour
325 {
326 	WCOL_BKGRND,	///< Background colours
327 	WCOL_TEXT,	///< Text colour
328 	WCOL_LIGHT,	///< Light colour for 3D effects
329 	WCOL_DARK,	///< Dark colour for 3D effects
330 	WCOL_HILITE,	///< Hilite colour
331 	WCOL_CURSOR,	///< Edit Box cursor colour
332 	WCOL_TIPBKGRND,	///< Background for the tool tip window
333 	WCOL_DISABLE,	///< Text colour on a disabled button
334 
335 	WCOL_MAX,	///< All colour numbers are less than this
336 };
337 
338 /** Set the global toop tip text colour. */
339 void widgSetTipColour(PIELIGHT colour);
340 
341 void widgSetButtonFlash(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
342 void widgClearButtonFlash(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
343 
344 /** Get a button or clickable form's state */
345 UDWORD widgGetButtonState(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id);
346 
347 /** Set a button or clickable form's state */
348 void widgSetButtonState(const std::shared_ptr<W_SCREEN> &psScreen, UDWORD id, UDWORD state);
349 
350 
351 /** Return which key was used to press the last returned widget */
352 UDWORD widgGetButtonKey_DEPRECATED(const std::shared_ptr<W_SCREEN> &psScreen);
353 
354 /** Execute a set of widgets for one cycle.
355  * Return the id of the widget that was activated, or 0 for none.
356  */
357 WidgetTriggers const &widgRunScreen(const std::shared_ptr<W_SCREEN> &psScreen);
358 
359 /** Display the screen's widgets in their current state
360  * (Call after calling widgRunScreen, this allows the input
361  *  processing to be separated from the display of the widgets).
362  */
363 void widgDisplayScreen(const std::shared_ptr<W_SCREEN> &psScreen);
364 
365 
366 /** Set the current audio callback function and audio id's. */
367 void WidgSetAudio(WIDGET_AUDIOCALLBACK Callback, SWORD HilightID, SWORD ClickedID, SWORD ErrorID);
368 
369 /** Get pointer to current audio callback function. */
370 WIDGET_AUDIOCALLBACK WidgGetAudioCallback();
371 
372 /** Get current audio ID for hilight. */
373 SWORD WidgGetHilightAudioID();
374 
375 /** Get current audio ID for clicked. */
376 SWORD WidgGetClickedAudioID();
377 
378 // error ID
379 SWORD WidgGetErrorAudioID();
380 
381 /** Enable or disable all sliders. */
382 void sliderEnableDrag(bool Enable);
383 
384 void setWidgetsStatus(bool var);
385 bool getWidgetsStatus();
386 
387 /** @} */
388 
389 #endif // __INCLUDED_LIB_WIDGET_WIDGET_H__
390