Formspec textlist: Black Irrlicht magic to detect fake doubleclicks
[oweals/minetest.git] / src / guiFormSpecMenu.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20
21 #ifndef GUIINVENTORYMENU_HEADER
22 #define GUIINVENTORYMENU_HEADER
23
24 #include <utility>
25
26 #include "irrlichttypes_extrabloated.h"
27 #include "inventory.h"
28 #include "inventorymanager.h"
29 #include "modalMenu.h"
30
31 class IGameDef;
32 class InventoryManager;
33
34 typedef enum {
35         f_Button,
36         f_ListBox,
37         f_TabHeader,
38         f_CheckBox,
39         f_DropDown,
40         f_Unknown
41 } FormspecFieldType;
42
43 struct TextDest
44 {
45         virtual ~TextDest() {};
46         // This is deprecated I guess? -celeron55
47         virtual void gotText(std::wstring text){}
48         virtual void gotText(std::map<std::string, std::string> fields) = 0;
49 };
50
51 class IFormSource
52 {
53 public:
54         virtual ~IFormSource(){}
55         virtual std::string getForm() = 0;
56         // Fill in variables in field text
57         virtual std::string resolveText(std::string str){ return str; }
58 };
59
60 class GUIFormSpecMenu : public GUIModalMenu
61 {
62         struct ItemSpec
63         {
64                 ItemSpec()
65                 {
66                         i = -1;
67                 }
68                 ItemSpec(const InventoryLocation &a_inventoryloc,
69                                 const std::string &a_listname,
70                                 s32 a_i)
71                 {
72                         inventoryloc = a_inventoryloc;
73                         listname = a_listname;
74                         i = a_i;
75                 }
76                 bool isValid() const
77                 {
78                         return i != -1;
79                 }
80
81                 InventoryLocation inventoryloc;
82                 std::string listname;
83                 s32 i;
84         };
85
86         struct ListDrawSpec
87         {
88                 ListDrawSpec()
89                 {
90                 }
91                 ListDrawSpec(const InventoryLocation &a_inventoryloc,
92                                 const std::string &a_listname,
93                                 v2s32 a_pos, v2s32 a_geom, s32 a_start_item_i):
94                         inventoryloc(a_inventoryloc),
95                         listname(a_listname),
96                         pos(a_pos),
97                         geom(a_geom),
98                         start_item_i(a_start_item_i)
99                 {
100                 }
101
102                 InventoryLocation inventoryloc;
103                 std::string listname;
104                 v2s32 pos;
105                 v2s32 geom;
106                 s32 start_item_i;
107         };
108
109         struct ImageDrawSpec
110         {
111                 ImageDrawSpec()
112                 {
113                 }
114                 ImageDrawSpec(const std::string &a_name,
115                                 v2s32 a_pos, v2s32 a_geom):
116                         name(a_name),
117                         pos(a_pos),
118                         geom(a_geom)
119                 {
120                         scale = true;
121                 }
122                 ImageDrawSpec(const std::string &a_name,
123                                 v2s32 a_pos):
124                         name(a_name),
125                         pos(a_pos)
126                 {
127                         scale = false;
128                 }
129                 std::string name;
130                 v2s32 pos;
131                 v2s32 geom;
132                 bool scale;
133         };
134         
135         struct FieldSpec
136         {
137                 FieldSpec()
138                 {
139                 }
140                 FieldSpec(const std::wstring name, const std::wstring label, const std::wstring fdeflt, int id):
141                         fname(name),
142                         flabel(label),
143                         fdefault(fdeflt),
144                         fid(id)
145                 {
146                         send = false;
147                         ftype = f_Unknown;
148                         is_exit = false;
149                         tooltip="";
150                 }
151                 std::wstring fname;
152                 std::wstring flabel;
153                 std::wstring fdefault;
154                 int fid;
155                 bool send;
156                 FormspecFieldType ftype;
157                 bool is_exit;
158                 core::rect<s32> rect;
159                 std::string tooltip;
160         };
161
162         struct BoxDrawSpec {
163                 BoxDrawSpec(v2s32 a_pos, v2s32 a_geom,irr::video::SColor a_color):
164                         pos(a_pos),
165                         geom(a_geom),
166                         color(a_color)
167                 {
168                 }
169                 v2s32 pos;
170                 v2s32 geom;
171                 irr::video::SColor color;
172         };
173
174 public:
175         GUIFormSpecMenu(irr::IrrlichtDevice* dev,
176                         gui::IGUIElement* parent, s32 id,
177                         IMenuManager *menumgr,
178                         InventoryManager *invmgr,
179                         IGameDef *gamedef
180                         );
181
182         ~GUIFormSpecMenu();
183
184         void setFormSpec(const std::string &formspec_string,
185                         InventoryLocation current_inventory_location)
186         {
187                 m_formspec_string = formspec_string;
188                 m_current_inventory_location = current_inventory_location;
189                 regenerateGui(m_screensize_old);
190         }
191         
192         // form_src is deleted by this GUIFormSpecMenu
193         void setFormSource(IFormSource *form_src)
194         {
195                 m_form_src = form_src;
196         }
197
198         // text_dst is deleted by this GUIFormSpecMenu
199         void setTextDest(TextDest *text_dst)
200         {
201                 m_text_dst = text_dst;
202         }
203
204         void allowClose(bool value)
205         {
206                 m_allowclose = value;
207         }
208
209         void useGettext(bool value) {
210                 m_use_gettext = true;
211         }
212
213         void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) {
214                 m_lock = lock;
215                 m_lockscreensize = basescreensize;
216         }
217
218         void removeChildren();
219         /*
220                 Remove and re-add (or reposition) stuff
221         */
222         void regenerateGui(v2u32 screensize);
223         
224         ItemSpec getItemAtPos(v2s32 p) const;
225         void drawList(const ListDrawSpec &s, int phase);
226         void drawSelectedItem();
227         void drawMenu();
228         void updateSelectedItem();
229         ItemStack verifySelectedItem();
230
231         void acceptInput();
232         bool OnEvent(const SEvent& event);
233
234         int getListboxIndex(std::string listboxname);
235
236 protected:
237         v2s32 getBasePos() const
238         {
239                         return padding + offset + AbsoluteRect.UpperLeftCorner;
240         }
241
242         v2s32 padding;
243         v2s32 spacing;
244         v2s32 imgsize;
245         v2s32 offset;
246         
247         irr::IrrlichtDevice* m_device;
248         InventoryManager *m_invmgr;
249         IGameDef *m_gamedef;
250
251         std::string m_formspec_string;
252         InventoryLocation m_current_inventory_location;
253         IFormSource *m_form_src;
254         TextDest *m_text_dst;
255
256         std::vector<ListDrawSpec> m_inventorylists;
257         std::vector<ImageDrawSpec> m_backgrounds;
258         std::vector<ImageDrawSpec> m_images;
259         std::vector<ImageDrawSpec> m_itemimages;
260         std::vector<BoxDrawSpec> m_boxes;
261         std::vector<FieldSpec> m_fields;
262         std::vector<std::pair<FieldSpec,gui::IGUIListBox*> > m_listboxes;
263         std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
264
265         ItemSpec *m_selected_item;
266         u32 m_selected_amount;
267         bool m_selected_dragging;
268         
269         // WARNING: BLACK MAGIC
270         // Used to guess and keep up with some special things the server can do.
271         // If name is "", no guess exists.
272         ItemStack m_selected_content_guess;
273         InventoryLocation m_selected_content_guess_inventory;
274
275         // WARNING: BLACK IRRLICHT MAGIC, see checkListboxClick()
276         std::wstring m_listbox_click_fname;
277         int m_listbox_click_index;
278         u32 m_listbox_click_time;
279         bool m_listbox_doubleclick;
280
281         v2s32 m_pointer;
282         gui::IGUIStaticText *m_tooltip_element;
283
284         bool m_allowclose;
285         bool m_use_gettext;
286         bool m_lock;
287         v2u32 m_lockscreensize;
288 private:
289         typedef struct {
290                 v2s32 size;
291                 s32 helptext_h;
292                 core::rect<s32> rect;
293                 v2s32 basepos;
294                 int bp_set;
295                 v2u32 screensize;
296                 std::map<std::wstring,int> listbox_selections;
297         } parserData;
298
299         typedef struct {
300                 bool key_up;
301                 bool key_down;
302                 bool key_enter;
303                 bool key_escape;
304         } fs_key_pendig;
305
306         std::vector<video::ITexture *> m_Textures;
307
308         fs_key_pendig current_keys_pending;
309
310         // Determine whether listbox click was double click
311         // (Using some black Irrlicht magic)
312         bool checkListboxClick(std::wstring wlistboxname, int eventtype);
313
314         void parseElement(parserData* data,std::string element);
315
316         void parseSize(parserData* data,std::string element);
317         void parseList(parserData* data,std::string element);
318         void parseCheckbox(parserData* data,std::string element);
319         void parseImage(parserData* data,std::string element);
320         void parseItemImage(parserData* data,std::string element);
321         void parseButton(parserData* data,std::string element,std::string typ);
322         void parseBackground(parserData* data,std::string element);
323         void parseTextList(parserData* data,std::string element);
324         void parseDropDown(parserData* data,std::string element);
325         void parsePwdField(parserData* data,std::string element);
326         void parseField(parserData* data,std::string element,std::string type);
327         void parseSimpleField(parserData* data,std::vector<std::string> &parts);
328         void parseTextArea(parserData* data,std::vector<std::string>& parts,std::string type);
329         void parseLabel(parserData* data,std::string element);
330         void parseVertLabel(parserData* data,std::string element);
331         void parseImageButton(parserData* data,std::string element,std::string type);
332         void parseItemImageButton(parserData* data,std::string element);
333         void parseTabHeader(parserData* data,std::string element);
334         void parseBox(parserData* data,std::string element);
335
336         bool parseColor(std::string color, irr::video::SColor& outcolor); 
337 };
338
339 class FormspecFormSource: public IFormSource
340 {
341 public:
342         FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec)
343         {
344                 m_formspec = formspec;
345                 m_game_formspec = game_formspec;
346         }
347
348         ~FormspecFormSource()
349         {
350                 *m_game_formspec = 0;
351         }
352
353         void setForm(std::string formspec) {
354                 m_formspec = formspec;
355         }
356
357         std::string getForm()
358         {
359                 return m_formspec;
360         }
361
362         std::string m_formspec;
363         FormspecFormSource** m_game_formspec;
364 };
365
366 #endif
367