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