1 /*
2 
3 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4 	and the "Aleph One" developers.
5 
6 	This program 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 3 of the License, or
9 	(at your option) any later version.
10 
11 	This program 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 	This license is contained in the file "COPYING",
17 	which is included with this source code; it is available online at
18 	http://www.gnu.org/licenses/gpl.html
19 
20 */
21 
22 /*
23  *  sdl_dialogs.h - SDL implementation of user dialogs
24  *
25  *  Written in 2000 by Christian Bauer
26  */
27 
28 #ifndef SDL_DIALOGS_H
29 #define SDL_DIALOGS_H
30 
31 #include "cstypes.h"
32 #include <vector>
33 #include <memory>
34 #include <boost/function.hpp>
35 #include <SDL.h>
36 
37 #ifndef NO_STD_NAMESPACE
38 using std::vector;
39 #endif
40 
41 class widget;
42 class font_info;
43 class FileSpecifier;
44 
45 
46 /*
47  *  Definitions
48  */
49 
50 class dialog;
51 
52 class placeable {
53 public:
54 	enum placement_flags
55 	{
56 		kDefault = 0x0,
57 		kAlignLeft = 0x1,
58 		kAlignCenter = 0x2,
59 		kAlignRight = 0x4,
60 		kFill = 0x8,
61 	};
62 
placeable()63 	placeable() : m_visible(true) { }
~placeable()64 	virtual ~placeable() { }
65 
66 	virtual void place(const SDL_Rect &r, placement_flags flags = kDefault) = 0;
67 	virtual int min_height() = 0;
68 	virtual int min_width() = 0;
69 
visible()70 	virtual bool visible() { return m_visible; }
visible(bool visible)71 	virtual void visible(bool visible) { m_visible = visible; }
72 
73 private:
74 	bool m_visible;
75 };
76 
77 class widget_placer : public placeable
78 {
79 public:
widget_placer()80 	widget_placer() : placeable() { }
81 	~widget_placer();
82 
83 	void place(const SDL_Rect &r, placement_flags flags = kDefault) = 0;
84 	int min_height() = 0;
85 	int min_width() = 0;
86 
87 protected:
assume_ownership(placeable * p)88 	void assume_ownership(placeable *p) { m_owned.push_back(p); }
89 
90 private:
91 	std::vector<placeable *> m_owned;
92 };
93 
94 class tab_placer : public widget_placer
95 {
96 public:
tab_placer()97 	tab_placer() : widget_placer(), m_tab(0) { }
98 	void add(placeable *p, bool assume_ownership = false);
99 	void dual_add(widget *w, dialog& d);
100 	int min_height();
101 	int min_width();
tabs()102 	int tabs() { return m_tabs.size(); };
103 	void choose_tab(int new_tab);
104 	void place(const SDL_Rect &r, placement_flags flags = kDefault);
visible()105 	bool visible() { return widget_placer::visible(); }
106 	void visible(bool visible);
107 private:
108 	int m_tab;
109 	std::vector<placeable *> m_tabs;
110 };
111 
112 class table_placer : public widget_placer
113 {
114 public:
115 	enum { kSpace = 4 };
widget_placer()116 	table_placer(int columns, int space = kSpace, bool balance_widths = false) : widget_placer(), m_add(0), m_columns(columns), m_space(space), m_balance_widths(balance_widths) { m_col_flags.resize(m_columns); m_col_min_widths.resize(m_columns);}
117 	void add(placeable *p, bool assume_ownership = false);
118 	void add_row(placeable *p, bool assume_ownership = false);
119 	void col_flags(int col, placement_flags flags = kDefault) { m_col_flags[col] = flags; }
col_min_width(int col,int min_width)120 	void col_min_width(int col, int min_width) { m_col_min_widths[col] = min_width; }
121 	void dual_add(widget *w, dialog& d);
122 	void dual_add_row(widget *w, dialog& d);
123 	int min_height();
124 	int min_width();
125 	void place(const SDL_Rect &r, placement_flags flags = kDefault);
126 	void visible(bool visible);
127 	int col_width(int column);
128 private:
129 	int row_height(int row);
130 	int m_add; // column to add next widget to
131 	int m_columns; // number of columns
132 	int m_space;
133 	bool m_balance_widths;
134 	std::vector<std::vector<placeable *> > m_table;
135 	std::vector<placement_flags> m_col_flags;
136 	std::vector<int> m_col_min_widths;
137 };
138 
139 
140 class vertical_placer : public widget_placer
141 {
142 public:
143 	enum { kSpace = 0 };
m_space(space)144 	vertical_placer(int space = kSpace) : m_space(space), widget_placer(), m_min_width(0), m_add_flags(kDefault) { }
145 
146 	void add(placeable *p, bool assume_ownership = false);
147 	void add_flags(placement_flags flags = kDefault) { m_add_flags = flags; }
148 	void dual_add(widget *w, dialog& d);
149 	int min_height();
150 	int min_width();
min_width(int w)151 	void min_width(int w) { m_min_width = w; }
152 
153 	void place(const SDL_Rect &r, placement_flags flags = kDefault);
154 	void visible(bool visible);
155 
156 private:
157 	std::vector<placeable *> m_widgets;
158 	std::vector<int> m_widget_heights;
159 	std::vector<placement_flags> m_placement_flags;
160 	int m_min_width;
161 	placement_flags m_add_flags;
162 	int m_space;
163 };
164 
165 class horizontal_placer : public widget_placer
166 {
167 public:
168 	enum { kSpace = 4 };
widget_placer()169 	horizontal_placer(int space = kSpace, bool balance_widths = false) : widget_placer(), m_space(space), m_add_flags(kDefault), m_balance_widths(balance_widths) { }
170 
171 	void add(placeable *p, bool assume_ownership = false);
172 	void add_flags(placement_flags flags = kDefault) { m_add_flags = flags; }
173 	// adds w to this placer, as well as dialog d
174 	void dual_add(widget *w, dialog& d);
175 	int min_height();
176 	int min_width();
177 
178 	void place(const SDL_Rect &r, placement_flags flags = kDefault);
179 	void visible(bool visible);
180 
181 private:
182 	std::vector<placeable *> m_widgets;
183 	std::vector<int> m_widget_widths;
184 	std::vector<placement_flags> m_placement_flags;
185 	int m_space;
186 	placement_flags m_add_flags;
187 	bool m_balance_widths;
188 };
189 
190 
191 // Dialog structure
192 class dialog {
193 public:
194 	typedef boost::function<void (dialog* d)> Callback;
195 
196 	dialog();
197 	~dialog();
198 
199 	// Add widget to dialog
200 	void add(widget *w);
201 
202 	// Run dialog modally
203 	int run(bool intro_exit_sounds = true);
204 
205 	// Put dialog on screen
206 	void start(bool play_sound = true);
207 
208 	// Process pending events, returns "done" flag
209 	bool process_events();
210 
211 	// Remove dialog from screen, returns dialog result
212 	int finish(bool play_sound = true);
213 
214 	// Quit dialog, return result
215 	void quit(int result);
216 
217 	// Draw dialog
218 	void draw(void);
219 
220         // ZZZ: Draw those widgets that are marked as needing redraw
221         // This is used automatically by the dialog code in response to user events --
222         // other code doesn't need to call this unless it's altering dialog widgets
223         // on its own (e.g. on a timer, or according to network activity, etc.)
224         void draw_dirty_widgets() const;
225 
226 	// Find the first widget with matching numerical ID
227 	widget *get_widget_by_id(short inID) const;
228 
229 	// Set custom processing function, called while dialog is idle
set_processing_function(Callback func)230 	void set_processing_function(Callback func) { processing_function = func; }
231 
232 	// Activate next selectable widget
233 	void activate_next_widget(void);
234 
235 	// exposed to allow toggling fill_the_screen
236 	// don't call this unless you know what you're doing
237 	void layout(void);
238 
239 	// takes ownership
set_widget_placer(widget_placer * w)240 	void set_widget_placer(widget_placer *w) { placer = w; }
241 
242 	void activate_widget(widget *w);
243 
244 private:
245 	SDL_Surface *get_surface(void) const;
246 	void update(SDL_Rect r) const;
247 	void draw_widget(widget *w, bool do_update = true) const;
248 	void deactivate_currently_active_widget();
249 	void activate_first_widget(void);
250 	void activate_widget(size_t num);
251 	void activate_prev_widget(void);
252 	int find_widget(int x, int y);
253 	void event(SDL_Event &e);
254 
255 	void new_layout(void);
256 
257 	SDL_Rect rect;				// Position relative to video surface, and dimensions
258 
259 	vector<widget *> widgets;	// List of widgets
260 
261 	widget *active_widget;		// Pointer to active widget
262 	widget *mouse_widget;           // Pointer to mouse event widget
263 	size_t active_widget_num;		// Number of active widget
264 
265 	int result;					// Dialog result code
266 	bool done;					// Flag: dialog done
267 	bool cursor_was_visible;	// Previous cursor state
268 
269 	dialog *parent_dialog;		// Pointer to parent dialog
270 
271 	Callback processing_function; // Custom idle procedure
272 
273 	// Frame images (frame_t, frame_l, frame_r and frame_b must be freed)
274 	SDL_Surface *frame_tl, *frame_t, *frame_tr, *frame_l, *frame_r, *frame_bl, *frame_b, *frame_br;
275 
276 	widget_placer *placer;
277 	bool layout_for_fullscreen; // is the current layout for fullscreen?
278 
279 	Uint32 last_redraw;
280 };
281 
282 // Pointer to top-level dialog, NULL = no dialog active
283 extern dialog *top_dialog;
284 
285 // Sounds
286 enum {
287 	DIALOG_INTRO_SOUND,
288 	DIALOG_OK_SOUND,
289 	DIALOG_CANCEL_SOUND,
290 	DIALOG_ERROR_SOUND,
291 	DIALOG_SELECT_SOUND,
292 	DIALOG_CLICK_SOUND,
293 	DIALOG_TYPE_SOUND,
294 	DIALOG_DELETE_SOUND,
295 	DIALOG_ERASE_SOUND,
296 	NUMBER_OF_DIALOG_SOUNDS
297 };
298 
299 /*
300  *  Functions
301  */
302 
303 extern void initialize_dialogs();
304 
305 extern bool load_dialog_theme(bool force_reload = false);
306 
307 extern uint32 get_dialog_player_color(size_t colorIndex); // ZZZ: added
308 extern void play_dialog_sound(int which);
309 
310 // new theme stuff
311 
312 // States
313 enum {
314 	DEFAULT_STATE,
315 	DISABLED_STATE,
316 	ACTIVE_STATE,
317 	CURSOR_STATE,
318 	PRESSED_STATE
319 };
320 
321 // Widget types
322 enum {
323 	DEFAULT_WIDGET,
324 	DIALOG_FRAME,
325 	TITLE_WIDGET,
326 	LABEL_WIDGET,
327 	MESSAGE_WIDGET,
328 	ITEM_WIDGET,
329 	TEXT_ENTRY_WIDGET,
330 	SPACER_WIDGET,
331 	BUTTON_WIDGET,
332 	SLIDER_WIDGET,
333 	SLIDER_THUMB,
334 	LIST_WIDGET,
335 	LIST_THUMB,
336 	CHAT_ENTRY,
337 	TINY_BUTTON,
338 	CHECKBOX,
339 	TAB_WIDGET,
340 	METASERVER_WIDGETS,
341 	METASERVER_PLAYERS,
342 	METASERVER_GAMES,
343 	HYPERLINK_WIDGET,
344 };
345 
346 enum {
347 	FOREGROUND_COLOR,
348 	BACKGROUND_COLOR,
349 	FRAME_COLOR
350 };
351 
352 enum {
353 	TL_IMAGE,
354 	T_IMAGE,
355 	TR_IMAGE,
356 	L_IMAGE,
357 	R_IMAGE,
358 	BL_IMAGE,
359 	B_IMAGE,
360 	BR_IMAGE
361 };
362 
363 enum {
364 	BUTTON_L_IMAGE,
365 	BUTTON_C_IMAGE,
366 	BUTTON_R_IMAGE
367 };
368 
369 enum {
370 	SLIDER_L_IMAGE,
371 	SLIDER_C_IMAGE,
372 	SLIDER_R_IMAGE,
373 };
374 
375 enum {
376 	SLIDER_T_SPACE,
377 	SLIDER_L_SPACE,
378 	SLIDER_R_SPACE
379 };
380 
381 enum {
382 	T_SPACE,
383 	L_SPACE,
384 	R_SPACE,
385 	B_SPACE
386 };
387 
388 enum {
389 	BUTTON_T_SPACE,
390 	BUTTON_L_SPACE,
391 	BUTTON_R_SPACE,
392 	BUTTON_HEIGHT,
393 };
394 
395 enum {
396 	TAB_LC_SPACE = BUTTON_HEIGHT + 1,
397 	TAB_RC_SPACE
398 };
399 
400 enum {
401 	TAB_L_IMAGE,
402 	TAB_LC_IMAGE,
403 	TAB_C_IMAGE,
404 	TAB_RC_IMAGE,
405 	TAB_R_IMAGE
406 };
407 
408 enum {
409 	TROUGH_T_SPACE = B_SPACE + 1,
410 	TROUGH_R_SPACE,
411 	TROUGH_B_SPACE,
412 	TROUGH_WIDTH
413 };
414 
415 enum {
416 	THUMB_T_IMAGE,
417 	THUMB_TC_IMAGE,
418 	THUMB_C_IMAGE,
419 	THUMB_BC_IMAGE,
420 	THUMB_B_IMAGE
421 };
422 
423 extern font_info *get_theme_font(int widget_type, uint16 &style);
424 
425 extern uint32 get_theme_color(int widget_type, int state, int which = 0);
426 extern SDL_Surface* get_theme_image(int widget_type, int state, int which, int width = 0, int height = 0);
427 extern bool use_theme_images(int widget_type);
428 extern bool use_theme_color(int widget_type, int which);
429 extern int get_theme_space(int widget_type, int which = 0);
430 
431 extern void dialog_ok(void *arg);
432 extern void dialog_cancel(void *arg);
433 
434 // ZZZ: some more handy callbacks
435 class w_text_entry;
436 extern void dialog_try_ok(w_text_entry* text_entry);
437 extern void dialog_disable_ok_if_empty(w_text_entry* inTextEntry);
438 
439 #endif
440