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_widgets.h - Widgets for SDL dialogs
24  *
25  *  Written in 2000 by Christian Bauer
26  *
27  *  Sept-Nov 2001 (Woody Zenfell) - significant changes to many widgets:
28  *    addition of more alignment and layout features, addition of methods to dynamically
29  *    alter widget parts not previously alterable, addition of callback mechanisms to
30  *    let user code respond to various events of interest, addition of widget enabling/disabling,
31  *    addition of mechanisms to let user code find a widget in a dialog and get a widget's dialog
32  *
33  *  Mar 1, 2002 (Woody Zenfell):
34  *      moved w_levels here (from shell_sdl); am using it in Setup Network Game dialog box.
35  *
36  *  August 27, 2003 (Woody Zenfell):
37  *	new w_enabling_toggle can enable/disable a bank of other widgets according to its state
38  *	new w_file_chooser displays filename; allows selection of file (via FileSpecifier::ReadDialog())
39  *	miscellaneous minor code cleanup (dead code removal etc.)
40  */
41 
42 #ifndef SDL_WIDGETS_H
43 #define SDL_WIDGETS_H
44 
45 #include	<SDL.h>
46 
47 #include	"cseries.h"
48 #include	"sdl_dialogs.h"
49 #include        "sdl_fonts.h"
50 #include        "screen_drawing.h"
51 
52 #include    "map.h" // for entry_point, for w_levels
53 #include	"tags.h"	// for Typecode, for w_file_chooser
54 #include	"FileHandler.h"	// for FileSpecifier, for w_file_chooser
55 
56 #include	<vector>
57 #include	<set>
58 #include	<boost/function.hpp>
59 #include 	<boost/bind.hpp>
60 
61 #include "metaserver_messages.h" // for GameListMessage, for w_games_in_room and MetaserverPlayerInfo, for w_players_in_room
62 #include "network.h" // for prospective_joiner_info
63 
64 #include	"binders.h"
65 
66 struct SDL_Surface;
67 //class sdl_font_info;
68 
69 typedef boost::function<void (void)> ControlHitCallback;
70 typedef boost::function<void (char)> GotCharacterCallback;
71 
72 /*
73  *  Widget base class
74  */
75 class w_label;
76 
77 class widget : public placeable{
78 	friend class dialog;
79 
80 public:
81     enum alignment {
82             kAlignNatural,
83             kAlignLeft,
84             kAlignCenter,
85             kAlignRight
86     };
87 
88     // ZZZ: initialize identifier, owning dialog, layout extensions
89 	widget();
90         widget(int theme_widget);
~widget()91 	virtual ~widget() {}
92 
93 	// Draw widget
94 	virtual void draw(SDL_Surface *s) const = 0;
95 
96     // ZZZ: (dis)allow user interactions.  assume widget alters its drawing behavior for disabled state.
97     void set_enabled(bool inEnabled);
98 
99 	// Handle event
mouse_move(int,int)100 	virtual void mouse_move(int /*x*/, int /*y*/) {}
mouse_down(int x,int y)101 	virtual void mouse_down(int x, int y) { click(x, y); }
mouse_up(int,int)102 	virtual void mouse_up(int /*x*/, int /*y*/) {}
click(int,int)103 	virtual void click(int /*x*/, int /*y*/) {}
event(SDL_Event &)104 	virtual void event(SDL_Event & /*e*/) {}
105 
106 	// Widget selectable?  (ZZZ change to use enabled by default)
is_selectable(void)107 	virtual bool is_selectable(void) const {return enabled; /* was "true" */ }
108 
109         // ZZZ: Get/set ID - see dialog::get_widget_by_id()
get_identifier()110         short	get_identifier() const {return identifier;}
set_identifier(short id)111         void	set_identifier(short id) {identifier = id;}
112 
113         // ZZZ: Get dialog
get_owning_dialog()114         dialog*	get_owning_dialog() { return owning_dialog; }
115 
116 	// New positioning stuff
set_rect(const SDL_Rect & r)117 	virtual void set_rect(const SDL_Rect &r) { rect = r; }
118 
119 	// implement placeable
120 	void place(const SDL_Rect &r, placement_flags flags);
min_height()121 	int min_height() { return saved_min_height; }
min_width()122 	int min_width() { return saved_min_width; }
123 
is_dirty()124 	virtual bool is_dirty() { return dirty; }
125 
126 	// labels are activated/enabled/disabled at the same time as this widget
127 
128 	// creates and returns a new label
129 	w_label *label(const char *);
130 	void associate_label(w_label *label);
131 
132 protected:
133         // ZZZ: called by friend class dialog when we're added
set_owning_dialog(dialog * new_owner)134         void	set_owning_dialog(dialog* new_owner) { owning_dialog = new_owner; }
135 
136 	SDL_Rect rect;	// Position relative to dialog surface, and dimensions
137 
138 	virtual void set_active(bool new_active);
139 	bool active;	// Flag: widget active (ZZZ note: this means it has the focus)
140 	bool dirty;		// Flag: widget needs redraw
141     bool    enabled; // ZZZ Flag: roughly, should the user be allowed to interact with the widget?
142 
143 	font_info *font;
144 	uint16 style;				// Widget font style
145 
146         short	identifier;	// ZZZ: numeric ID in support of dialog::find_widget_by_id()
147         dialog*	owning_dialog;	// ZZZ: which dialog currently contains us?  for get_dialog()
148 
149 	int saved_min_width;
150 	int saved_min_height;
151 
152 	w_label* associated_label;
153 };
154 
155 
156 /*
157  *  Vertical space
158  */
159 
160 class w_spacer : public placeable {
161 public:
m_space(space)162 	w_spacer(uint16 space = get_theme_space(SPACER_WIDGET)) : m_space(space) { }
163 
min_height()164 	int min_height() { return m_space; }
min_width()165 	int min_width() { return m_space; }
place(const SDL_Rect &,placement_flags)166 	void place(const SDL_Rect&, placement_flags) { }
167 
168 private:
169 	uint16 m_space;
170 };
171 
172 
173 /*
174  *  Static text
175  */
176 
177 // ZZZ change: static_text now owns its own copy of whatever string(s) you give it, so constructor
178 // allocates storage, destructor frees, etc.
179 class w_static_text : public widget {
180 public:
181 	w_static_text(const char *text, int theme_type = MESSAGE_WIDGET);
182 
183 	void draw(SDL_Surface *s) const;
184 
185         // ZZZ addition: change text after creation
186         void set_text(const char* t);
187 
is_selectable(void)188 	bool is_selectable(void) const {return false;}
189 
190         ~w_static_text();
191 
192 protected:
193 	char *text;
194 	int theme_type;
195 };
196 
197 class w_label : public w_static_text {
198 	friend class dialog;
199 	friend class w_slider;
200 public:
w_label(const char * text)201 	w_label(const char *text) : w_static_text(text, LABEL_WIDGET), associated_widget(0) {}
202 
associate_widget(widget * w)203 	void associate_widget(widget *w) { associated_widget = w; }
204 	void draw(SDL_Surface *s) const;
205 	void click(int, int);
is_selectable(void)206 	bool is_selectable(void) const { if (associated_widget) return associated_widget->is_selectable(); else return false; }
207 private:
208 	widget *associated_widget;
209 };
210 
211 class w_title : public w_static_text {
212 public:
w_title(const char * text)213 	w_title(const char *text) : w_static_text(text, TITLE_WIDGET) {}
214 };
215 
216 class w_styled_text : public w_static_text {
217 public:
218 	w_styled_text(const char *text, int theme_type = MESSAGE_WIDGET);
219 
220 	void set_text(const char* t);
221 	void draw(SDL_Surface *s) const;
222 private:
223 	std::string text_string;
224 };
225 
226 class w_slider_text : public w_static_text {
227 	friend class w_slider;
228 public:
w_slider_text(const char * text)229 	w_slider_text(const char *text) : w_static_text(text) {}
230 	void draw(SDL_Surface *s) const;
231 protected:
232 	class w_slider *associated_slider;
233 };
234 
235 
236 /*
237  *  Picture (PICT resource)
238  */
239 
240 class w_pict : public widget {
241 public:
242 	w_pict(int id);
243 	~w_pict();
244 
245 	void draw(SDL_Surface *s) const;
is_selectable(void)246 	bool is_selectable(void) const {return false;}
247 
248 private:
249 	SDL_Surface *picture;
250 };
251 
252 
253 /*
254  *  Button
255  */
256 
257 // typedef void (*action_proc)(void *);
258 typedef boost::function<void (void*)> action_proc;
259 
260 class w_button_base : public widget {
261 public:
262 	w_button_base(const char *text, action_proc proc = NULL, void *arg = NULL, int type = BUTTON_WIDGET);
263 	virtual ~w_button_base();
264 
265 	void set_callback (action_proc proc, void *arg);
266 
267 	void draw(SDL_Surface *s) const;
268 	void mouse_move(int x, int y);
269 	void mouse_down(int x, int y);
270 	void mouse_up(int x, int y);
271 	void click(int x, int y);
272 
273 protected:
274 	const std::string text;
275 	action_proc proc;
276 	void *arg;
277 
278 	bool down, pressed;
279 
280 	int type;
281 	// cache button centers since they are tiled or scaled
282 	SDL_Surface *button_c_default;
283 	SDL_Surface *button_c_active;
284 	SDL_Surface *button_c_disabled;
285 	SDL_Surface *button_c_pressed;
286 };
287 
288 
289 class w_button : public w_button_base {
290 public:
w_button_base(text,proc,arg,BUTTON_WIDGET)291 	w_button(const char *text, action_proc proc = NULL, void *arg = NULL) : w_button_base(text, proc, arg, BUTTON_WIDGET) {}
292 };
293 
294 class w_tiny_button : public w_button_base {
295 public:
w_button_base(text,proc,arg,TINY_BUTTON)296 	w_tiny_button(const char *text, action_proc proc = NULL, void *arg = NULL) : w_button_base(text, proc, arg, TINY_BUTTON) {}
297 };
298 
299 class w_hyperlink : public w_button_base {
300 public:
301 	w_hyperlink(const char *url, const char *text = NULL);
302 
303 	void draw(SDL_Surface *s) const;
304 	void prochandler(void* arg);
305 };
306 
307 /*
308  * Tabs
309  */
310 
311 class w_tab : public widget {
312 public:
313 	w_tab(const vector<string>& labels, tab_placer *placer);
314 	~w_tab();
315 	void draw(SDL_Surface *s) const;
316 	void click(int x, int y);
317 	void event(SDL_Event& e);
318 
319 	void choose_tab(int i);
320 private:
321 	vector<string> labels;
322 	vector<int> widths;
323 	tab_placer *placer;
324 
325 	vector<vector<SDL_Surface *> > images;
326 
327 	int pressed_tab;
328 	int active_tab;
329 };
330 
331 /*
332  *  Selection button
333  */
334 
335 class w_select_button : public widget {
336 public:
337 	w_select_button(const char *selection, action_proc proc = NULL, void *arg = NULL, bool utf8 = false);
338 
339 	void draw(SDL_Surface *s) const;
340 	void click(int x, int y);
341 
342 	void set_selection(const char *selection);
set_callback(action_proc p,void * a)343 	void set_callback(action_proc p, void* a) { proc = p; arg = a; }
344 
345 	void place(const SDL_Rect& r, placement_flags flags = placeable::kDefault);
346 
347 protected:
set_arg(void * arg)348 	void set_arg(void *arg) { this->arg = arg; }
349 	placement_flags p_flags;
350 private:
351 	const char *selection;
352 	action_proc proc;
353 	void *arg;
354 
355 	int16 selection_x;			// X offset of selection display
356 	bool utf8; // render utf8 text instead of roman
357 };
358 
359 
360 /*
361  *  Selection widget (base class)
362  */
363 
364 // ZZZ: type for callback function
365 class w_select;
366 // typedef void (*selection_changed_callback_t)(w_select* theWidget);
367 typedef boost::function<void (w_select*)> selection_changed_callback_t;
368 
369 class w_select : public widget {
370 public:
371 	w_select(size_t selection, const char **labels);
372 	virtual ~w_select();
373 
374 	void draw(SDL_Surface *s) const;
375 	void click(int x, int y);
376 	void event(SDL_Event &e);
377 
378 	void place(const SDL_Rect& r, placement_flags flags = placeable::kDefault);
379 	int min_width();
380 
get_selection(void)381 	size_t get_selection(void) const {return (num_labels > 0 ? selection : UNONE);}
382 	void set_selection(size_t selection, bool simulate_user_input = false);
383 
384 	// ZZZ: change labels after creation (used for entry-point selection when game type changes)
385 	// this is the "old way" - superseded (I hope) by set_labels_stringset.
386 	// both should still be valid, and should not have any evil interactions, so I may as well leave this in.
387 	// note that storage for string pointers AND storage for string data must be "kept alive" until
388 	// the widget is destroyed or another set_labels[_stringset] call is made.
389 	void	set_labels(const char** inLabels);
390 
391 	// ZZZ: install stringset to use as labels
392 	// stringset is not copied.  altering stringset and not calling this method again -> no guarantees.
393 	// between widget and stringset, storage should be taken care of.  relax.
394 	void	set_labels_stringset(short inStringSetID);
395 
396 	// ZZZ: set selection-changed callback - this will be called (if set) at the end of selection_changed (currently, anytime it "beeps")
397 	// removes need to subclass this class (or its subclasses!) just to add selection-changed behavior.
set_selection_changed_callback(selection_changed_callback_t proc)398 	void	set_selection_changed_callback(selection_changed_callback_t proc) { selection_changed_callback = proc; }
399 
labels_are_utf8(bool _utf8)400 	void labels_are_utf8(bool _utf8) { utf8 = _utf8; }
401 
402 protected:
403 	virtual void selection_changed(void);
404 
405 	const char **labels;
406 	size_t num_labels;
407 	bool	we_own_labels;	// true if set up via stringset; false if not
408 	// Currently stringset approach allocates memory for pointers to strings, but shares string storage
409 	// with the stringset itself.  So we don't really own the *labels* - the strings - but we own the
410 	// storage for the data member "labels".
411 
412 	size_t selection;			// UNONE means unknown selection
413 
414 	// ZZZ: storage for callback function
415 	selection_changed_callback_t	selection_changed_callback;
416 
417 	// ZZZ: ripped this out for sharing
418 	uint16				get_largest_label_width();
419 
420 	bool utf8; // labels are UTF-8
421 };
422 
423 
424 /*
425  *  On-off toggle
426  */
427 
428 class w_toggle : public w_select {
429 public:
430 	static const char *onoff_labels[3];
431 
432 	w_toggle(bool selection, const char **labels = onoff_labels);
433 	int min_width();
434 	void draw(SDL_Surface *) const;
435 };
436 
437 
438 /*
439  *	Enabling toggle (ZZZ)
440  *
441  *	Can enable/disable a bank of other widgets according to its state
442  */
443 
444 class w_enabling_toggle : public w_toggle
445 {
446 public:
447 	w_enabling_toggle(bool inSelection, bool inEnablesWhenOn = true, const char** inLabels = onoff_labels);
add_dependent_widget(widget * inWidget)448 	void add_dependent_widget(widget* inWidget) { dependents.insert(inWidget); update_widget_enabled(inWidget); }
remove_dependent_widget(widget * inWidget)449 	void remove_dependent_widget(widget* inWidget) { dependents.erase(inWidget); }
450 
451 protected:
452 	void selection_changed();
453 
454 private:
update_widget_enabled(widget * inWidget)455 	void update_widget_enabled(widget* inWidget)
456 	{
457 		inWidget->set_enabled(selection == enables_when_on);
458 	}
459 
460 	typedef std::set<widget*> DependentCollection;
461 
462 	DependentCollection	dependents;
463 	bool			enables_when_on;
464 };
465 
466 
467 /*
468  *  Player color selection
469  */
470 
471 class w_player_color : public w_select {
472 public:
473 	w_player_color(int selection);
474 
475 	void draw(SDL_Surface *s) const;
476 };
477 
478 /*
479  *  Text entry widget
480  */
481 
482 class w_text_entry : public widget {
483 	friend class w_number_entry;
484 public:
485 	typedef boost::function<void (w_text_entry*)> Callback;
486 
487 	w_text_entry(size_t max_chars, const char *initial_text = NULL);
488 	~w_text_entry();
489 
490 	void draw(SDL_Surface *s) const;
491 	void event(SDL_Event &e);
492 	void click(int, int);
493 
494 	void set_text(const char *text);
get_text(void)495 	const char *get_text(void) {return buf;}
496 
set_min_width(int w)497 	void set_min_width(int w) { saved_min_width = w; }
498 
499         // ZZZ: set callback for "enter" or "return" keypress
set_enter_pressed_callback(Callback func)500         void	set_enter_pressed_callback(Callback func) { enter_pressed_callback = func; }
501 
502         // ZZZ: set callback for value changed (will be called if value changed programmatically also)
503         // (thought: this probably ought to be unified with w_select selection changed callback)
set_value_changed_callback(Callback func)504         void	set_value_changed_callback(Callback func) { value_changed_callback = func; }
505 
506 	void enable_mac_roman_input(bool enable = true) { enable_mac_roman = enable; }
507 	void place(const SDL_Rect& r, placement_flags flags);
508 
509 
510 protected:
511 	char *buf;		// Text entry buffer
512 	void set_active(bool new_active);
513 
514         Callback	enter_pressed_callback;
515         Callback	value_changed_callback;
516 
517 private:
518 	void modified_text(void);
519 
520 	size_t num_chars;		// Length of text in buffer
521 	size_t max_chars;		// Maximum number of chars in buffer
522 	int16 text_x;			// X offset of text display
523 	uint16 max_text_width;	// Maximum width of text display
524 	size_t cursor_position;	// cursor position within buffer
525 
526 	bool enable_mac_roman; // enable MacRoman input
527 };
528 
529 class w_chat_entry : public w_text_entry {
530 public:
w_chat_entry(size_t max_c)531 	w_chat_entry(size_t max_c) : w_text_entry(max_c, "") {
532 		font = get_theme_font(CHAT_ENTRY, style);
533 		saved_min_height =  (int16) font->get_ascent() + font->get_descent() + font->get_leading();
534 	}
535 };
536 /*
537  *  Number entry widget
538  */
539 
540 class w_number_entry : public w_text_entry {
541 public:
542 	w_number_entry(int initial_number = 0);
543 
544 	void event(SDL_Event &e);
545 
546 	void set_number(int number);
get_number(void)547 	int get_number(void) {return atoi(get_text());}
548 };
549 
550 /*
551  * Displays asterisks instead of password
552  */
553 
554 class w_password_entry : public w_text_entry {
555 public:
556 	w_password_entry(size_t max_chars, const char *initial_text = 0);
557 
558 	void draw(SDL_Surface *s) const;
559 };
560 
561 /*
562  *  Key name widget
563  */
564 
565 class w_key : public widget {
566 public:
567 	enum Type {
568 		KeyboardKey,
569 		MouseButton,
570 		JoystickButton
571 	} event_type;
572 
573 	static Type event_type_for_key(SDL_Scancode key);
574 
575 	w_key(SDL_Scancode key, w_key::Type event_type);
576 
577 	void draw(SDL_Surface *s) const;
578 	void click(int x, int y);
579 	void event(SDL_Event &e);
580 
581 	virtual void set_key(SDL_Scancode key);
get_key(void)582 	SDL_Scancode get_key(void) {return key;}
583 	void place(const SDL_Rect& r, placement_flags flags);
584 
585 protected:
586 	virtual void set_active(bool new_active);
587 
588 private:
589 	const char *name;
590 
591 	int16 key_x;			// X offset of key name
592 
593 	SDL_Scancode key;
594 	bool binding;		// Flag: next key press will bind key
595 };
596 
597 
598 /*
599  *  Progress Bar (ZZZ)
600  */
601 
602 class w_progress_bar : public widget {
603 public:
w_progress_bar(int inWidth)604 w_progress_bar(int inWidth) : widget(), max_value(10), value(0) {
605 		rect.w = inWidth;
606 		rect.h = 14;
607 
608 		saved_min_width = rect.w;
609 		saved_min_height = rect.h;
610         }
611 
~w_progress_bar()612         ~w_progress_bar() {}
613 
614         void draw(SDL_Surface* s) const;
615 
is_selectable()616         bool is_selectable() { return false; }
617 
618         void set_progress(int inValue, int inMaxValue);
619 
620 protected:
621         int max_value;
622         int value;
623 };
624 
625 
626 
627 /*
628  *  Slider
629  */
630 
631 class w_slider;
632 typedef boost::function<void (w_slider*)> slider_changed_callback_t;
633 
634 class w_slider : public widget {
635 	friend class w_slider_text;
636 public:
637 	w_slider(int num_items, int sel);
638 	~w_slider();
639 
640 	void draw(SDL_Surface *s) const;
641 	void mouse_move(int x, int y);
642 	void click(int x, int y);
643 	void event(SDL_Event &e);
644 
get_selection(void)645 	int get_selection(void) {return selection;}
646 	void set_selection(int selection);
647 
item_selected(void)648 	virtual void item_selected(void) {}
649 	virtual std::string formatted_value(void);
650 
651 	void place(const SDL_Rect& r, placement_flags flags);
652 
set_slider_changed_callback(slider_changed_callback_t proc)653 	void set_slider_changed_callback(slider_changed_callback_t proc) { slider_changed_callback = proc; }
654 
655 
656 protected:
657 	void init_formatted_value(void);
658 
659 	w_slider_text *readout; // display current slider value
660 	int readout_x;			// relative X offset where readout is drawn
661 
662 	int16 slider_x;			// X offset of slider image
663 
664 	int selection;			// Currently selected item
665 	int num_items;			// Total number of items
666 
667 	bool thumb_dragging;	// Flag: currently dragging thumb
668 	int thumb_x;			// X position of thumb
669 	int trough_width;		// Width of trough
670 
671 	int thumb_drag_x;		// X start position when dragging
672 
673 	SDL_Surface *slider_l, *slider_c, *slider_r, *thumb;
674 
675 	slider_changed_callback_t slider_changed_callback;
676 
677 private:
678 	int thumb_width() const;
679 	void selection_changed(void);
680 };
681 
682 class w_percentage_slider : public w_slider {
683 public:
w_percentage_slider(int num_items,int sel)684 	w_percentage_slider(int num_items, int sel) : w_slider(num_items, sel) {
685 		init_formatted_value();
686 	}
687 
688 	virtual std::string formatted_value(void);
689 };
690 
691 class w_color_picker : public widget {
692 public:
w_color_picker(rgb_color & color)693 	w_color_picker(rgb_color &color) : widget(MESSAGE_WIDGET), m_color(color) {
694 		saved_min_width = 48;
695 		saved_min_height = font->get_line_height();
696 	}
697 
get_selection()698 	const rgb_color& get_selection() { return m_color; }
699 
700 	void draw(SDL_Surface *s) const;
701 	void click(int, int);
702 
703 private:
704 	rgb_color m_color;
705 
706 	struct update_color {
update_colorupdate_color707 		update_color(w_percentage_slider *red, w_percentage_slider *green, w_percentage_slider *blue, uint16 *i_red, uint16 *i_green, uint16 *i_blue) : red_w(red), green_w(green), blue_w(blue), red(i_red), blue(i_blue), green(i_green) { }
operatorupdate_color708 		void operator()(dialog *) {
709 			*red = red_w->get_selection() << 12;
710 			*green = green_w->get_selection() << 12;
711 			*blue = blue_w->get_selection() << 12;
712 		}
713 
714 		w_percentage_slider *red_w;
715 		w_percentage_slider *green_w;
716 		w_percentage_slider *blue_w;
717 
718 		uint16* red;
719 		uint16* blue;
720 		uint16* green;
721 	};
722 };
723 
724 
725 /*
726  *  Template for list selection widgets
727  */
728 
729 class w_list_base : public widget {
730 public:
731 	w_list_base(uint16 width, size_t lines, size_t sel);
732 	~w_list_base();
733 
734 	void draw(SDL_Surface *s) const;
735 	void mouse_move(int x, int y);
736 	void click(int x, int y);
737 	void event(SDL_Event &e);
738 
get_selection(void)739 	size_t get_selection(void) {return selection;}
740 
is_item_selectable(size_t)741 	virtual bool is_item_selectable(size_t /*i*/) {return true;}
742 	virtual void item_selected(void) = 0;
743 
744 	void place(const SDL_Rect& r, placement_flags flags);
745 
746 protected:
747 	virtual void draw_items(SDL_Surface *s) const = 0;
748 	void draw_image(SDL_Surface *dst, SDL_Surface *s, int16 x, int16 y) const;
749 	void set_selection(size_t s);
750 	void new_items(void);
751 	void center_item(size_t i);
752 	void set_top_item(size_t i);
item_height()753 	virtual uint16 item_height() const { return font->get_line_height(); }
754 
755 	static const int kListScrollSpeed = 1;
756 
757 	size_t selection;		// Currently selected item
758 
759 	size_t num_items;		// Total number of items
760 	size_t shown_items;		// Number of shown items
761 	size_t top_item;		// Number of first visible item
762 
763 	bool thumb_dragging;	// Flag: currently dragging scroll bar thumb
764 	SDL_Rect trough_rect;	// Dimensions of trough
765 	uint16 thumb_height;		// Height of thumb
766 	uint16 min_thumb_height;	// Minimal height of thumb
767 	int16 thumb_y;			// Y position of thumb
768 
769 	int thumb_drag_y;		// Y start position when dragging
770 
771 	SDL_Surface *frame_tl, *frame_t, *frame_tr, *frame_l, *frame_r, *frame_bl, *frame_b, *frame_br;
772 	SDL_Surface *thumb_t, *thumb_tc, *thumb_c, *thumb_bc, *thumb_b;
773 };
774 
775 template <class T>
776 class w_list : public w_list_base {
777 public:
w_list(const vector<T> & it,uint16 width,size_t lines,size_t sel)778 	w_list(const vector<T> &it, uint16 width, size_t lines, size_t sel) : w_list_base(width, lines, sel), items(it)
779 	{
780 		num_items = items.size();
781 		new_items();
782 		set_selection(sel);
783 		center_item(selection);
784 	}
785 
item_height()786 	uint16 item_height() const { return font->get_line_height(); }
787 
~w_list()788 	~w_list() {}
789 
790 protected:
draw_items(SDL_Surface * s)791 	void draw_items(SDL_Surface *s) const
792 	{
793 		typename vector<T>::const_iterator i = items.begin() + top_item;
794 		int16 x = rect.x + get_theme_space(LIST_WIDGET, L_SPACE);
795 		int16 y = rect.y + get_theme_space(LIST_WIDGET, T_SPACE);
796 		uint16 width = rect.w - get_theme_space(LIST_WIDGET, L_SPACE) - get_theme_space(LIST_WIDGET, R_SPACE);
797 		for (size_t n=top_item; n<top_item + MIN(shown_items, num_items); n++, i++, y=y+item_height())
798 			draw_item(i, s, x, y, width, n == selection && active);
799 	}
800 
801 	const vector<T> &items;	// List of items
802 
803 private:
804 	virtual void draw_item(typename vector<T>::const_iterator i, SDL_Surface *s, int16 x, int16 y, uint16 width, bool selected) const = 0;
805 
806 	w_list(const w_list<T>&);
807 	w_list<T>& operator =(const w_list<T>&);
808 };
809 
810 
811 
812 /*
813  *  Level number dialog
814  *
815  *  ZZZ: new constructor gives more control over appearance (including omission of level numbers).
816  */
817 
818 class w_levels : public w_list<entry_point> {
819 public:
820 	w_levels(const vector<entry_point> &items, dialog *d);
821 	w_levels(const vector<entry_point>& items, dialog* d, uint16 inWidth,
822 	size_t inNumLines, size_t inSelectedItem, bool in_show_level_numbers);
823 
824 	void item_selected(void);
825 
826 	void draw_item(vector<entry_point>::const_iterator i, SDL_Surface *s, int16 x, int16 y, uint16 width, bool selected) const;
827 
828 private:
829 	dialog *parent;
830 	bool    show_level_numbers;
831 };
832 
833 
834 /*
835  *  String List
836  */
837 
838 class w_string_list : public w_list<string> {
839 public:
840 	w_string_list(const vector<string> &items, dialog *d, int sel);
841 
842 	void item_selected(void);
843 
844 	void draw_item(vector<string>::const_iterator i, SDL_Surface *s, int16 x, int16 y, uint16 width, bool selected) const;
845 
846 private:
847 	dialog *parent;
848 };
849 
850 
851 /*
852  *  Selection Popup
853  */
854 
855 class w_select_popup : public w_select_button {
856 public:
857 	w_select_popup (action_proc p = NULL, void *a = NULL);
858 
859 	void set_labels (const vector<string>& inLabels);/* {labels = inLabels;}*/
860 	void set_selection (int value);
get_selection()861 	int get_selection () {return selection;}
862 
863 	// Not to be confused with set_callback as inherited from w_select_button
set_popup_callback(action_proc p,void * a)864 	void set_popup_callback (action_proc p, void* a) {action = p; arg = a;}
865 
866 private:
867 	int selection;
868 	vector<string> labels;
869 
870 	action_proc action;
871 	void* arg;
872 
gotSelectedCallback(void * arg)873 	static void gotSelectedCallback (void* arg) {reinterpret_cast<w_select_popup*>(arg)->gotSelected();}
874 	void gotSelected ();
875 };
876 
877 
878 /*
879  *	General file-chooser (ZZZ)
880  */
881 
882 class w_file_chooser : public w_select_button
883 {
884 public:
885 	w_file_chooser(const char* inDialogPrompt, Typecode inTypecode);
886 
887 	void click(int x, int y);
888 
889 	void set_file(const FileSpecifier& inFile);
get_file()890 	const FileSpecifier& get_file() { return file; }
891 
892 	// we also have void set_callback(action_proc, void*)
893 	// as inherited from w_select_button
set_callback(ControlHitCallback callback)894 	void set_callback (ControlHitCallback callback) { m_callback = callback; }
895 
896 private:
897 	void update_filename();
898 
899 	FileSpecifier	file;
900 	char		filename[256];
901 	char		dialog_prompt[256];
902 	Typecode	typecode;
903 	ControlHitCallback m_callback;
904 };
905 
906 
907 /*
908  *	Lists for metaserver dialog; moved from SdlMetaserverClientUi.cpp
909  */
910 
911 extern void set_drawing_clip_rectangle(short top, short left, short bottom, short right);
912 
913 const string w_items_in_room_get_name_of_item (GameListMessage::GameListEntry item);
914 const string w_items_in_room_get_name_of_item (prospective_joiner_info item);
915 const string w_items_in_room_get_name_of_item (MetaserverPlayerInfo item);
916 
917 template <typename tElement>
918 class w_items_in_room : public w_list_base
919 {
920 public:
921 	typedef typename boost::function<void (const tElement& item)> ItemClickedCallback;
922 	typedef typename std::vector<tElement> ElementVector;
923 
w_items_in_room(ItemClickedCallback itemClicked,int width,int numRows)924 	w_items_in_room(ItemClickedCallback itemClicked, int width, int numRows) :
925 		w_list_base(width, numRows, 0),
926 		m_itemClicked(itemClicked)
927 	{
928 		num_items = 0;
929 		new_items();
930 	}
931 
set_collection(const std::vector<tElement> & elements)932 	void set_collection(const std::vector<tElement>& elements) {
933 		m_items = elements;
934 		num_items = m_items.size();
935 		new_items();
936 
937 		// do other crap - manage selection, force redraw, etc.
938 		get_owning_dialog ()->draw_dirty_widgets ();
939 	}
940 
set_item_clicked_callback(ItemClickedCallback itemClicked)941 	void set_item_clicked_callback (ItemClickedCallback itemClicked) { m_itemClicked = itemClicked; }
942 
item_selected()943 	void item_selected() {
944 		if(m_itemClicked)
945 			m_itemClicked(m_items[selection]);
946 	}
947 
item_height()948 	uint16 item_height() const { return font->get_line_height(); }
949 
950 protected:
draw_items(SDL_Surface * s)951 	void draw_items(SDL_Surface* s) const {
952 		typename ElementVector::const_iterator i = m_items.begin();
953 		int16 x = rect.x + get_theme_space(LIST_WIDGET, L_SPACE);
954 		int16 y = rect.y + get_theme_space(LIST_WIDGET, T_SPACE);
955 		uint16 width = rect.w - get_theme_space(LIST_WIDGET, L_SPACE) - get_theme_space(LIST_WIDGET, R_SPACE);
956 
957 		for(size_t n = 0; n < top_item; n++)
958 			++i;
959 
960 		for (size_t n=top_item; n<top_item + MIN(shown_items, num_items); n++, ++i, y=y+item_height())
961 			draw_item(*i, s, x, y, width, n == selection && active);
962 	}
963 
964 private:
965 	ElementVector			m_items;
966 	ItemClickedCallback		m_itemClicked;
967 
968 	// This should be factored out into a "drawer" object/Strategy
draw_item(const tElement & item,SDL_Surface * s,int16 x,int16 y,uint16 width,bool selected)969 	virtual void draw_item(const tElement& item, SDL_Surface* s,
970 			int16 x, int16 y, uint16 width, bool selected) const {
971 		y += font->get_ascent();
972 		set_drawing_clip_rectangle(0, x, static_cast<short>(s->h), x + width);
973 		draw_text(s, w_items_in_room_get_name_of_item(item).c_str(), x, y, selected ? get_theme_color(ITEM_WIDGET, ACTIVE_STATE) : get_theme_color(ITEM_WIDGET, DEFAULT_STATE), font, style);
974 		set_drawing_clip_rectangle(SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
975 	}
976 
977 	w_items_in_room(const w_items_in_room<tElement>&);
978 	w_items_in_room<tElement>& operator =(const w_items_in_room<tElement>&);
979 };
980 
981 
982 typedef w_items_in_room<prospective_joiner_info> w_joining_players_in_room;
983 
984 class w_games_in_room : public w_items_in_room<GameListMessage::GameListEntry>
985 {
986 public:
w_games_in_room(w_items_in_room<GameListMessage::GameListEntry>::ItemClickedCallback itemClicked,int width,int numRows)987 	w_games_in_room(w_items_in_room<GameListMessage::GameListEntry>::ItemClickedCallback itemClicked, int width, int numRows)
988 		: w_items_in_room<GameListMessage::GameListEntry>(itemClicked, width, numRows), kGameSpacing(get_theme_space(METASERVER_GAMES, GAME_SPACING))
989 		{ font = get_theme_font(METASERVER_GAMES, style); saved_min_height = item_height() * static_cast<uint16>(shown_items) + get_theme_space(LIST_WIDGET, T_SPACE) + get_theme_space(LIST_WIDGET, B_SPACE); }
990 
item_height()991 	uint16 item_height() const { return 3 * font->get_line_height() + 2 + kGameSpacing; }
992 
refresh()993 	void refresh() {
994 		dirty = true;
995 		get_owning_dialog()->draw_dirty_widgets();
996 	}
997 
998 	enum {
999 		GAME_ENTRIES,
1000 		GAME_SPACING,
1001 	};
1002 
1003 	enum {
1004 		GAME,
1005 		RUNNING_GAME,
1006 		INCOMPATIBLE_GAME,
1007 		SELECTED_GAME,
1008 		SELECTED_RUNNING_GAME,
1009 		SELECTED_INCOMPATIBLE_GAME,
1010 	};
1011 private:
1012 	const int kGameSpacing;
1013 	void draw_item(const GameListMessage::GameListEntry& item, SDL_Surface* s, int16 x, int16 y, uint16 width, bool selected) const;
1014 };
1015 
1016 class w_players_in_room : public w_items_in_room<MetaserverPlayerInfo>
1017 {
1018 public:
w_players_in_room(w_items_in_room<MetaserverPlayerInfo>::ItemClickedCallback itemClicked,int width,int numRows)1019 	w_players_in_room(w_items_in_room<MetaserverPlayerInfo>::ItemClickedCallback itemClicked, int width, int numRows)
1020 	: w_items_in_room<MetaserverPlayerInfo>(itemClicked, width, numRows)
1021 	{
1022 		font = get_theme_font(METASERVER_PLAYERS, style);
1023 		saved_min_height = item_height() * static_cast<uint16>(shown_items) + get_theme_space(LIST_WIDGET, T_SPACE) + get_theme_space(LIST_WIDGET, B_SPACE);
1024 	}
1025 
1026 protected:
item_height()1027 	uint16 item_height() const { return font->get_line_height() + 4; }
1028 private:
1029 	static const int kPlayerColorSwatchWidth = 8;
1030 	static const int kTeamColorSwatchWidth = 4;
1031 	static const int kSwatchGutter = 2;
1032 
1033 	void draw_item(const MetaserverPlayerInfo& item, SDL_Surface* s,
1034 		int16 x, int16 y, uint16 width, bool selected) const;
1035 };
1036 
1037 
1038 
1039 struct ColoredChatEntry
1040 {
1041 	enum Type {
1042 		ChatMessage,
1043 		PrivateMessage,
1044 		ServerMessage,
1045 		LocalMessage
1046 	} type;
1047 
1048 	// these next two are only valid for chat and private
1049 	// otherwise they should be gray and ""
1050 	rgb_color color;
1051 	std::string sender;
1052 
1053 	std::string message;
1054 
ColoredChatEntryColoredChatEntry1055 	ColoredChatEntry() : type(ChatMessage) { color.red = color.blue = color.green = 0x7fff; }
1056 };
1057 
1058 class w_colorful_chat : public w_list<ColoredChatEntry>
1059 {
1060 private:
1061 	vector<ColoredChatEntry> entries;
1062 public:
w_colorful_chat(int width,int numRows)1063 	w_colorful_chat(int width, int numRows) :
1064 		w_list<ColoredChatEntry>(entries, width, numRows, 0),
1065 		kNameWidth(get_theme_space(CHAT_ENTRY) - taper_width())
1066 		{ num_items = 0; font = get_theme_font(CHAT_ENTRY, style); saved_min_height = item_height() * static_cast<uint16>(shown_items) + get_theme_space(LIST_WIDGET, T_SPACE) + get_theme_space(LIST_WIDGET, B_SPACE); }
1067 
is_selectable(void)1068 	virtual bool is_selectable(void) const { return true; }
1069 
item_selected()1070 	void item_selected() {}
1071 
1072 	void append_entry(const ColoredChatEntry&);
1073 
clear()1074 	void clear() { entries.clear(); num_items = 0; new_items(); }
1075 
~w_colorful_chat()1076 	~w_colorful_chat() {}
1077 
item_height()1078 	uint16 item_height() const { return font->get_line_height() + 2; }
1079 
1080 private:
1081 	const int kNameWidth;
1082 
taper_width()1083 	uint16 taper_width() const { return (font->get_line_height() + 1) / 2 - 1; }
1084 
1085 	void draw_item(vector<ColoredChatEntry>::const_iterator i, SDL_Surface *s, int16 x, int16 y, uint16 width, bool selected) const;
1086 };
1087 
1088 /*
1089  *	Wrappers to common widget interface follow
1090  */
1091 
1092 class SDLWidgetWidget
1093 {
1094 public:
1095 	void hide ();
1096 	void show ();
1097 
1098 	void activate ();
1099 	void deactivate ();
1100 
1101 protected:
SDLWidgetWidget(widget * in_widget)1102 	SDLWidgetWidget (widget* in_widget)
1103 		: m_widget (in_widget)
1104 		, hidden (false)
1105 		, inactive (false)
1106 		{}
1107 
1108 	widget* m_widget;
1109 
1110 private:
1111 	bool hidden, inactive;
1112 };
1113 
1114 class ColorfulChatWidgetImpl : public SDLWidgetWidget
1115 {
1116 public:
ColorfulChatWidgetImpl(w_colorful_chat * w)1117 	ColorfulChatWidgetImpl(w_colorful_chat* w)
1118 		: SDLWidgetWidget(w), m_chat(w) { }
1119 
Append(const ColoredChatEntry & e)1120 	void Append(const ColoredChatEntry& e) { m_chat->append_entry(e); }
Clear()1121 	void Clear () { m_chat->clear (); }
1122 
1123 private:
1124 	w_colorful_chat *m_chat;
1125 };
1126 
1127 
1128 class ToggleWidget : public SDLWidgetWidget, public Bindable<bool>
1129 {
1130 public:
ToggleWidget(w_toggle * toggle)1131 	ToggleWidget (w_toggle* toggle)
1132 		: SDLWidgetWidget (toggle)
1133 		, m_toggle (toggle)
1134 		, m_callback (NULL)
1135 		{ m_toggle->set_selection_changed_callback (boost::bind(&ToggleWidget::massage_callback, this, _1)); }
1136 
set_callback(ControlHitCallback callback)1137 	void set_callback (ControlHitCallback callback) { m_callback = callback; }
1138 
get_value()1139 	bool get_value () { return m_toggle->get_selection (); }
set_value(bool value)1140 	void set_value (bool value) { m_toggle->set_selection (value); }
1141 
bind_export()1142 	bool bind_export () { return get_value (); }
bind_import(bool value)1143 	void bind_import (bool value) { set_value (value); }
1144 
1145 private:
massage_callback(w_select * ignored)1146 	void massage_callback (w_select* ignored)
1147 		{ if (m_callback) m_callback (); }
1148 
1149 	w_toggle* m_toggle;
1150 	ControlHitCallback m_callback;
1151 };
1152 
1153 class SelectorWidget : public SDLWidgetWidget, public Bindable<int>
1154 {
1155 public:
set_callback(ControlHitCallback callback)1156 	virtual void set_callback (ControlHitCallback callback) { m_callback = callback; }
1157 
set_labels(int stringset)1158 	virtual void set_labels (int stringset) { set_labels (build_stringvector_from_stringset (stringset)); }
1159 	virtual void set_labels (const std::vector<std::string>& labels) = 0;
1160 
1161 	virtual int get_value () = 0;
1162 	virtual void set_value (int value) = 0;
1163 
bind_export()1164 	int bind_export () { return get_value (); }
bind_import(int value)1165 	void bind_import (int value) { set_value (value); }
1166 
~SelectorWidget()1167 	virtual ~SelectorWidget () {}
1168 
1169 protected:
SelectorWidget(widget * in_widget)1170 	SelectorWidget (widget* in_widget)
1171 		: SDLWidgetWidget (in_widget)
1172 		, m_callback (NULL)
1173 		{}
1174 
1175 	ControlHitCallback m_callback;
1176 };
1177 
1178 class PopupSelectorWidget : public SelectorWidget
1179 {
1180 public:
PopupSelectorWidget(w_select_popup * select_popup_w)1181 	PopupSelectorWidget (w_select_popup* select_popup_w)
1182 		: SelectorWidget (select_popup_w)
1183 		, m_select_popup (select_popup_w)
1184 		{ select_popup_w->set_popup_callback (boost::bind(&PopupSelectorWidget::massage_callback, this, _1), NULL); }
1185 
set_labels(const std::vector<std::string> & labels)1186 	virtual void set_labels (const std::vector<std::string>& labels) { m_select_popup->set_labels (labels); }
1187 
get_value()1188 	virtual int get_value () { return m_select_popup->get_selection (); }
set_value(int value)1189 	virtual void set_value (int value) { m_select_popup->set_selection (value); }
1190 
1191 private:
1192 	w_select_popup* m_select_popup;
1193 
massage_callback(void * ignored)1194 	void massage_callback (void* ignored) { if (m_callback) m_callback (); }
1195 };
1196 
1197 class SelectSelectorWidget : public SelectorWidget
1198 {
1199 public:
SelectSelectorWidget(w_select * select_w)1200 	SelectSelectorWidget (w_select* select_w)
1201 		: SelectorWidget (select_w)
1202 		, m_select (select_w)
1203 		{ m_select->set_selection_changed_callback (boost::bind(&SelectSelectorWidget::massage_callback, this, _1)); }
1204 
1205 	// w_select only knows how to set labels from stringsets
set_labels(int stringset)1206 	virtual void set_labels (int stringset) { m_select->set_labels_stringset (stringset); }
set_labels(const std::vector<std::string> & labels)1207 	virtual void set_labels (const std::vector<std::string>& labels) {}
1208 
get_value()1209 	virtual int get_value () { return m_select->get_selection (); }
set_value(int value)1210 	virtual void set_value (int value) { m_select->set_selection (value); }
1211 
1212 private:
1213 	w_select* m_select;
1214 
massage_callback(w_select * ignored)1215 	void massage_callback (w_select* ignored)
1216 		{ if (m_callback) m_callback (); }
1217 };
1218 
1219 class ColourSelectorWidget : public SelectSelectorWidget
1220 {
1221 public:
ColourSelectorWidget(w_player_color * player_color_w)1222 	ColourSelectorWidget (w_player_color* player_color_w)
1223 		: SelectSelectorWidget (player_color_w) {}
1224 
1225 	// We ignore the labels and use swatches of colour instead
set_labels(int stringset)1226 	virtual void set_labels (int stringset) {}
set_labels(const std::vector<std::string> & labels)1227 	virtual void set_labels (const std::vector<std::string>& labels) {}
1228 };
1229 
1230 class SliderSelectorWidget : public SelectorWidget
1231 {
1232 public:
SliderSelectorWidget(w_slider * slider_w)1233 	SliderSelectorWidget (w_slider* slider_w)
1234 		: SelectorWidget (slider_w)
1235 		, m_slider (slider_w)
1236 		{}
1237 
1238 	// Sliders don't get labels
set_labels(const std::vector<std::string> & labels)1239 	virtual void set_labels (const std::vector<std::string>& labels) {};
1240 
get_value()1241 	virtual int get_value () { return m_slider->get_selection (); }
set_value(int value)1242 	virtual void set_value (int value) { m_slider->set_selection (value); }
1243 
1244 	// Sliders don't get callbacks either
1245 
1246 private:
1247 	w_slider* m_slider;
1248 };
1249 
1250 class ButtonWidget : public SDLWidgetWidget
1251 {
1252 public:
ButtonWidget(w_button_base * button)1253 	ButtonWidget (w_button_base* button)
1254 		: SDLWidgetWidget (button)
1255 		, m_button (button)
1256 		, m_callback (NULL)
1257 		{ m_button->set_callback (bounce_callback, this); }
1258 
set_callback(ControlHitCallback callback)1259 	void set_callback (ControlHitCallback callback) { m_callback = callback; }
1260 
push()1261 	void push () { if (m_callback) m_callback (); }
1262 
1263 private:
bounce_callback(void * arg)1264 	static void bounce_callback(void* arg)
1265 		{ reinterpret_cast<ButtonWidget*>(arg)->push (); }
1266 
1267 	w_button_base* m_button;
1268 	ControlHitCallback m_callback;
1269 };
1270 
1271 class StaticTextWidget : public SDLWidgetWidget
1272 {
1273 public:
StaticTextWidget(w_static_text * static_text_w)1274 	StaticTextWidget (w_static_text* static_text_w)
1275 		: SDLWidgetWidget (static_text_w)
1276 		, m_static_text (static_text_w)
1277 		{}
1278 
set_text(std::string s)1279 	void set_text (std::string s) { m_static_text->set_text (s.c_str ()); }
1280 
1281 private:
1282 	w_static_text* m_static_text;
1283 };
1284 
1285 class EditTextWidget : public SDLWidgetWidget, public Bindable<std::string>
1286 {
1287 public:
EditTextWidget(w_text_entry * text_entry)1288 	EditTextWidget (w_text_entry* text_entry)
1289 		: SDLWidgetWidget (text_entry)
1290 		, m_text_entry (text_entry)
1291 		{ m_text_entry->set_enter_pressed_callback (boost::bind(&EditTextWidget::got_submit, this, _1)); }
1292 
set_callback(GotCharacterCallback callback)1293 	void set_callback (GotCharacterCallback callback) { m_callback = callback; }
1294 
set_text(string s)1295 	void set_text (string s) { m_text_entry->set_text(s.c_str ()); }
get_text()1296 	const string get_text () { return string(m_text_entry->get_text()); }
1297 
bind_export()1298 	std::string bind_export () { return get_text (); }
bind_import(std::string s)1299 	void bind_import (std::string s) { set_text (s); }
1300 
1301 private:
1302 	w_text_entry* m_text_entry;
1303 	GotCharacterCallback m_callback;
1304 
1305 	// Yeah, I know.  Interface can be refined later.
got_submit(w_text_entry * ignored)1306 	void got_submit(w_text_entry* ignored) { if (m_callback) m_callback ('\r'); }
1307 };
1308 
1309 class EditNumberWidget : public SDLWidgetWidget, public Bindable<int>
1310 {
1311 public:
EditNumberWidget(w_number_entry * number_entry)1312 	EditNumberWidget (w_number_entry* number_entry)
1313 		: SDLWidgetWidget (number_entry)
1314 		, m_number_entry (number_entry)
1315 		{}
1316 
set_label(const std::string & s)1317 	void set_label (const std::string& s) {  }
1318 
set_value(int value)1319 	void set_value (int value) { m_number_entry->set_number (value); }
get_value()1320 	int get_value () { return m_number_entry->get_number (); }
1321 
bind_export()1322 	int bind_export () { return get_value (); }
bind_import(int value)1323 	void bind_import (int value) { set_value (value); }
1324 
1325 private:
1326 	w_number_entry* m_number_entry;
1327 };
1328 
1329 class FileChooserWidget : public SDLWidgetWidget, public Bindable<FileSpecifier>
1330 {
1331 public:
FileChooserWidget(w_file_chooser * file_chooser)1332 	FileChooserWidget (w_file_chooser* file_chooser)
1333 		: SDLWidgetWidget (file_chooser)
1334 		, m_file_chooser (file_chooser)
1335 		{}
1336 
set_callback(ControlHitCallback callback)1337 	void set_callback (ControlHitCallback callback) { m_file_chooser->set_callback (callback); }
1338 
set_file(const FileSpecifier & file)1339 	void set_file (const FileSpecifier& file) { m_file_chooser->set_file (file); }
get_file()1340 	FileSpecifier get_file () { return m_file_chooser->get_file (); }
1341 
bind_export()1342 	virtual FileSpecifier bind_export () { return get_file (); }
bind_import(FileSpecifier f)1343 	virtual void bind_import (FileSpecifier f) { set_file (f); }
1344 
1345 private:
1346 	w_file_chooser* m_file_chooser;
1347 };
1348 
1349 
1350 class GameListWidget
1351 {
1352 public:
GameListWidget(w_games_in_room * games_in_room)1353 	GameListWidget (w_games_in_room* games_in_room)
1354 		: m_games_in_room (games_in_room)
1355 		{
1356 			m_games_in_room->set_item_clicked_callback(boost::bind(&GameListWidget::bounce_callback, this, _1));
1357 		}
1358 
SetItems(const vector<GameListMessage::GameListEntry> & items)1359 	void SetItems(const vector<GameListMessage::GameListEntry>& items) { m_games_in_room->set_collection (items); }
1360 
SetItemSelectedCallback(const boost::function<void (GameListMessage::GameListEntry)> itemSelected)1361 	void SetItemSelectedCallback(const boost::function<void (GameListMessage::GameListEntry)> itemSelected)
1362 		{ m_callback = itemSelected; }
1363 
1364 private:
1365 	w_games_in_room* m_games_in_room;
1366 	boost::function<void (GameListMessage::GameListEntry)> m_callback;
1367 
bounce_callback(GameListMessage::GameListEntry thingy)1368 	void bounce_callback (GameListMessage::GameListEntry thingy)
1369 		{ m_callback (thingy); }
1370 };
1371 
1372 class PlayerListWidget
1373 {
1374 public:
PlayerListWidget(w_players_in_room * players_in_room)1375 	PlayerListWidget (w_players_in_room* players_in_room)
1376 		: m_players_in_room (players_in_room) {
1377 		m_players_in_room->set_item_clicked_callback(boost::bind(&PlayerListWidget::bounce_callback, this, _1));
1378 	}
1379 
SetItems(const vector<MetaserverPlayerInfo> & items)1380 	void SetItems(const vector<MetaserverPlayerInfo>& items) { m_players_in_room->set_collection (items); }
SetItemSelectedCallback(const boost::function<void (MetaserverPlayerInfo)> itemSelected)1381 	void SetItemSelectedCallback(const boost::function<void (MetaserverPlayerInfo)> itemSelected)
1382 	{ m_callback = itemSelected; }
1383 
1384 
1385 
1386 private:
1387 	w_players_in_room* m_players_in_room;
1388 	boost::function<void (MetaserverPlayerInfo)> m_callback;
1389 
bounce_callback(MetaserverPlayerInfo thingy)1390 	void bounce_callback (MetaserverPlayerInfo thingy)
1391 	{ m_callback(thingy); }
1392 };
1393 
1394 class JoiningPlayerListWidget
1395 {
1396 public:
JoiningPlayerListWidget(w_joining_players_in_room * joining_players_in_room)1397 	JoiningPlayerListWidget (w_joining_players_in_room* joining_players_in_room)
1398 		: m_joining_players_in_room (joining_players_in_room)
1399 		{
1400 			m_joining_players_in_room->set_item_clicked_callback(boost::bind(&JoiningPlayerListWidget::bounce_callback, this, _1));
1401 		}
1402 
SetItems(const vector<prospective_joiner_info> & items)1403 	void SetItems(const vector<prospective_joiner_info>& items) { m_joining_players_in_room->set_collection (items); }
1404 
SetItemSelectedCallback(const boost::function<void (prospective_joiner_info)> itemSelected)1405 	void SetItemSelectedCallback(const boost::function<void (prospective_joiner_info)> itemSelected)
1406 		{ m_callback = itemSelected; }
1407 
1408 private:
1409 	w_joining_players_in_room* m_joining_players_in_room;
1410 	boost::function<void (prospective_joiner_info)> m_callback;
1411 
bounce_callback(prospective_joiner_info thingy)1412 	void bounce_callback (prospective_joiner_info thingy)
1413 		{ m_callback (thingy); }
1414 };
1415 
1416 class w_players_in_game2;
1417 class PlayersInGameWidget : SDLWidgetWidget
1418 {
1419 public:
1420 	PlayersInGameWidget (w_players_in_game2*);
1421 
1422 	void redraw ();
1423 
1424 private:
1425 	w_players_in_game2* m_pig;
1426 };
1427 
1428 // There are no colour pickers in sdl; we never try to actually construct one of these guys
1429 class ColourPickerWidget : public Bindable<RGBColor> {};
1430 
1431 #endif
1432