qMax <qwiglydee@gmail.com>'s font patch, adds unicode support and support for drawing...
[supertux.git] / src / gui / menu.hpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #ifndef SUPERTUX_MENU_H
21 #define SUPERTUX_MENU_H
22
23 #include <vector>
24 #include <list>
25 #include <memory>
26 #include <set>
27 #include <string>
28 #include <utility>
29 #include <assert.h>
30
31 #include <SDL.h>
32
33 #include "video/surface.hpp"
34 #include "video/font.hpp"
35 #include "mousecursor.hpp"
36
37 bool confirm_dialog(Surface* background, std::string text);
38
39 /* Kinds of menu items */
40 enum MenuItemKind {
41   MN_ACTION,
42   MN_GOTO,
43   MN_TOGGLE,
44   MN_BACK,
45   MN_INACTIVE,
46   MN_TEXTFIELD,
47   MN_NUMFIELD,
48   MN_CONTROLFIELD,
49   MN_STRINGSELECT,
50   MN_LABEL,
51   MN_HL, /* horizontal line */
52 };
53
54 class Menu;
55 \f
56 class MenuItem
57 {
58 public:
59   MenuItem(MenuItemKind kind, int id = -1);
60   MenuItemKind kind;
61   int id;   // item id
62   bool toggled;
63   std::string text;
64   std::string input;
65   std::string help;
66
67   std::vector<std::string> list; // list of values for a STRINGSELECT item
68   size_t selected; // currently selected item
69
70   Menu* target_menu;
71
72   void set_help(const std::string& help_text);
73
74   void change_text (const std::string& text);
75   void change_input(const std::string& text);
76
77   static MenuItem* create(MenuItemKind kind, const std::string& text,
78                           int init_toggle, Menu* target_menu, int id, int key);
79
80   std::string get_input_with_symbol(bool active_item);   // returns the text with an input symbol
81
82 private:
83   /// copy-construction not allowed
84   MenuItem(const MenuItem& ) { assert(false); }
85   /// assignment not allowed
86   void operator= (const MenuItem& ) { assert(false); }
87
88   /// keyboard key or joystick button
89   bool input_flickering;
90 };
91 \f
92 class Menu
93 {
94   static Color default_color;
95   static Color active_color;
96   static Color inactive_color;
97   static Color label_color;
98   static Color field_color;
99 private:
100   static std::vector<Menu*> last_menus;
101
102   /** Pointers to all currently available menus, used to handle repositioning on window resize */
103   static std::list<Menu*>   all_menus;
104
105   static Menu* previous;
106   static Menu* current_;
107
108 public:
109   /** Set the current menu, if pmenu is NULL, hide the current menu */
110   static void set_current(Menu* pmenu);
111
112   static void push_current(Menu* pmenu);
113   static void pop_current();
114
115
116   static void recalc_pos();
117
118   /** Return the current active menu or NULL if none is active */
119   static Menu* current()
120   {
121     return current_;
122   }
123
124 private:
125   /* Action done on the menu */
126   enum MenuAction {
127     MENU_ACTION_NONE = -1,
128     MENU_ACTION_UP,
129     MENU_ACTION_DOWN,
130     MENU_ACTION_LEFT,
131     MENU_ACTION_RIGHT,
132     MENU_ACTION_HIT,
133     MENU_ACTION_INPUT,
134     MENU_ACTION_REMOVE,
135     MENU_ACTION_BACK
136   };
137
138   /** Number of the item that got 'hit' (ie. pressed) in the last
139       event()/update() call, -1 if none */
140   int hit_item;
141
142   // position of the menu (ie. center of the menu, not top/left)
143   float pos_x;
144   float pos_y;
145
146   /** input event for the menu (up, down, left, right, etc.) */
147   MenuAction menuaction;
148
149   /* input implementation variables */
150   int   delete_character;
151   char  mn_input_char;
152   float menu_repeat_time;
153
154   bool close;
155
156 public:
157   std::vector<MenuItem*> items;
158
159   Menu();
160   virtual ~Menu();
161
162   MenuItem* add_hl();
163   MenuItem* add_label(const std::string& text);
164   MenuItem* add_entry(int id, const std::string& text);
165   MenuItem* add_toggle(int id, const std::string& text, bool toggled = false);
166   MenuItem* add_inactive(int id, const std::string& text);
167   MenuItem* add_back(const std::string& text);
168   MenuItem* add_submenu(const std::string& text, Menu* submenu, int id = -1);
169   MenuItem* add_controlfield(int id, const std::string& text,
170                              const std::string& mapping = "");
171   MenuItem* add_string_select(int id, const std::string& text);
172
173   virtual void menu_action(MenuItem* item);
174
175   void update();
176
177   /** Remove all entries from the menu */
178   void clear();
179
180   /** Return the index of the menu item that was 'hit' (ie. the user
181       clicked on it) in the last event() call */
182   int check ();
183
184   MenuItem& get_item(int index)
185   {
186     return *(items[index]);
187   }
188   MenuItem& get_item_by_id(int id);
189   const MenuItem& get_item_by_id(int id) const;
190
191   int get_active_item_id();
192   void set_active_item(int id);
193
194   void draw(DrawingContext& context);
195   void set_pos(float x, float y, float rw = 0, float rh = 0);
196
197   void event(const SDL_Event& event);
198
199   bool is_toggled(int id) const;
200   void set_toggled(int id, bool toggled);
201
202   Menu* get_parent() const;
203
204 protected:
205   void additem(MenuItem* pmenu_item);
206   float get_width() const;
207   float get_height() const;
208
209 private:
210   void check_controlfield_change_event(const SDL_Event& event);
211   void draw_item(DrawingContext& context, int index);
212   float effect_progress;
213   float effect_start_time;
214   int arrange_left;
215   int active_item;
216
217   std::auto_ptr<Surface> checkbox;
218   std::auto_ptr<Surface> checkbox_checked;
219   std::auto_ptr<Surface> back;
220   std::auto_ptr<Surface> arrow_left;
221   std::auto_ptr<Surface> arrow_right;
222 };
223
224 #endif