]> git.lizzy.rs Git - dragonfireclient.git/blob - src/guiFormSpecMenu.h
Fix various performance issues reported by cppcheck (#5628)
[dragonfireclient.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 #include <stack>
26
27 #include "irrlichttypes_extrabloated.h"
28 #include "inventorymanager.h"
29 #include "modalMenu.h"
30 #include "guiTable.h"
31 #include "network/networkprotocol.h"
32 #include "client/joystick_controller.h"
33 #include "util/string.h"
34 #include "util/enriched_string.h"
35
36 class InventoryManager;
37 class ISimpleTextureSource;
38 class Client;
39
40 typedef enum {
41         f_Button,
42         f_Table,
43         f_TabHeader,
44         f_CheckBox,
45         f_DropDown,
46         f_ScrollBar,
47         f_Unknown
48 } FormspecFieldType;
49
50 typedef enum {
51         quit_mode_no,
52         quit_mode_accept,
53         quit_mode_cancel
54 } FormspecQuitMode;
55
56 struct TextDest
57 {
58         virtual ~TextDest() {};
59         // This is deprecated I guess? -celeron55
60         virtual void gotText(std::wstring text){}
61         virtual void gotText(const StringMap &fields) = 0;
62         virtual void setFormName(std::string formname)
63         { m_formname = formname;};
64
65         std::string m_formname;
66 };
67
68 class IFormSource
69 {
70 public:
71         virtual ~IFormSource(){}
72         virtual std::string getForm() = 0;
73         // Fill in variables in field text
74         virtual std::string resolveText(std::string str){ return str; }
75 };
76
77 class GUIFormSpecMenu : public GUIModalMenu
78 {
79         struct ItemSpec
80         {
81                 ItemSpec() :
82                         i(-1)
83                 {}
84
85                 ItemSpec(const InventoryLocation &a_inventoryloc,
86                                 const std::string &a_listname,
87                                 s32 a_i) :
88                         inventoryloc(a_inventoryloc),
89                         listname(a_listname),
90                         i(a_i)
91                 {}
92
93                 bool isValid() const { return i != -1; }
94
95                 InventoryLocation inventoryloc;
96                 std::string listname;
97                 s32 i;
98         };
99
100         struct ListDrawSpec
101         {
102                 ListDrawSpec()
103                 {
104                 }
105                 ListDrawSpec(const InventoryLocation &a_inventoryloc,
106                                 const std::string &a_listname,
107                                 v2s32 a_pos, v2s32 a_geom, s32 a_start_item_i):
108                         inventoryloc(a_inventoryloc),
109                         listname(a_listname),
110                         pos(a_pos),
111                         geom(a_geom),
112                         start_item_i(a_start_item_i)
113                 {
114                 }
115
116                 InventoryLocation inventoryloc;
117                 std::string listname;
118                 v2s32 pos;
119                 v2s32 geom;
120                 s32 start_item_i;
121         };
122
123         struct ListRingSpec
124         {
125                 ListRingSpec()
126                 {
127                 }
128                 ListRingSpec(const InventoryLocation &a_inventoryloc,
129                                 const std::string &a_listname):
130                         inventoryloc(a_inventoryloc),
131                         listname(a_listname)
132                 {
133                 }
134
135                 InventoryLocation inventoryloc;
136                 std::string listname;
137         };
138
139         struct ImageDrawSpec
140         {
141                 ImageDrawSpec():
142                         parent_button(NULL),
143                         clip(false)
144                 {}
145
146                 ImageDrawSpec(const std::string &a_name,
147                                 const std::string &a_item_name,
148                                 gui::IGUIButton *a_parent_button,
149                                 const v2s32 &a_pos, const v2s32 &a_geom):
150                         name(a_name),
151                         item_name(a_item_name),
152                         parent_button(a_parent_button),
153                         pos(a_pos),
154                         geom(a_geom),
155                         scale(true),
156                         clip(false)
157                 {}
158
159                 ImageDrawSpec(const std::string &a_name,
160                                 const std::string &a_item_name,
161                                 const v2s32 &a_pos, const v2s32 &a_geom):
162                         name(a_name),
163                         item_name(a_item_name),
164                         parent_button(NULL),
165                         pos(a_pos),
166                         geom(a_geom),
167                         scale(true),
168                         clip(false)
169                 {}
170
171                 ImageDrawSpec(const std::string &a_name,
172                                 const v2s32 &a_pos, const v2s32 &a_geom, bool clip=false):
173                         name(a_name),
174                         parent_button(NULL),
175                         pos(a_pos),
176                         geom(a_geom),
177                         scale(true),
178                         clip(clip)
179                 {}
180
181                 ImageDrawSpec(const std::string &a_name,
182                                 const v2s32 &a_pos):
183                         name(a_name),
184                         parent_button(NULL),
185                         pos(a_pos),
186                         scale(false),
187                         clip(false)
188                 {}
189
190                 std::string name;
191                 std::string item_name;
192                 gui::IGUIButton *parent_button;
193                 v2s32 pos;
194                 v2s32 geom;
195                 bool scale;
196                 bool clip;
197         };
198
199         struct FieldSpec
200         {
201                 FieldSpec()
202                 {
203                 }
204                 FieldSpec(const std::string &name, const std::wstring &label,
205                                 const std::wstring &default_text, int id) :
206                         fname(name),
207                         flabel(label),
208                         fdefault(unescape_enriched(default_text)),
209                         fid(id),
210                         send(false),
211                         ftype(f_Unknown),
212                         is_exit(false)
213                 {}
214
215                 std::string fname;
216                 std::wstring flabel;
217                 std::wstring fdefault;
218                 int fid;
219                 bool send;
220                 FormspecFieldType ftype;
221                 bool is_exit;
222                 core::rect<s32> rect;
223         };
224
225         struct BoxDrawSpec {
226                 BoxDrawSpec(v2s32 a_pos, v2s32 a_geom,irr::video::SColor a_color):
227                         pos(a_pos),
228                         geom(a_geom),
229                         color(a_color)
230                 {
231                 }
232                 v2s32 pos;
233                 v2s32 geom;
234                 irr::video::SColor color;
235         };
236
237         struct TooltipSpec {
238                 TooltipSpec() {}
239                 TooltipSpec(std::string a_tooltip, irr::video::SColor a_bgcolor,
240                                 irr::video::SColor a_color):
241                         tooltip(utf8_to_wide(a_tooltip)),
242                         bgcolor(a_bgcolor),
243                         color(a_color)
244                 {}
245
246                 std::wstring tooltip;
247                 irr::video::SColor bgcolor;
248                 irr::video::SColor color;
249         };
250
251         struct StaticTextSpec {
252                 StaticTextSpec():
253                         parent_button(NULL)
254                 {
255                 }
256                 StaticTextSpec(const std::wstring &a_text,
257                                 const core::rect<s32> &a_rect):
258                         rect(a_rect),
259                         parent_button(NULL)
260                 {
261                         //text = unescape_enriched(a_text);
262                         text = a_text;
263                 }
264                 StaticTextSpec(const std::wstring &a_text,
265                                 const core::rect<s32> &a_rect,
266                                 gui::IGUIButton *a_parent_button):
267                         text(a_text),
268                         rect(a_rect),
269                         parent_button(a_parent_button)
270                 {}
271
272                 std::wstring text;
273                 core::rect<s32> rect;
274                 gui::IGUIButton *parent_button;
275         };
276
277 public:
278         GUIFormSpecMenu(irr::IrrlichtDevice* dev,
279                         JoystickController *joystick,
280                         gui::IGUIElement* parent, s32 id,
281                         IMenuManager *menumgr,
282                         Client *client,
283                         ISimpleTextureSource *tsrc,
284                         IFormSource* fs_src,
285                         TextDest* txt_dst,
286                         bool remap_dbl_click = true);
287
288         ~GUIFormSpecMenu();
289
290         void setFormSpec(const std::string &formspec_string,
291                         InventoryLocation current_inventory_location)
292         {
293                 m_formspec_string = formspec_string;
294                 m_current_inventory_location = current_inventory_location;
295                 regenerateGui(m_screensize_old);
296         }
297
298         // form_src is deleted by this GUIFormSpecMenu
299         void setFormSource(IFormSource *form_src)
300         {
301                 if (m_form_src != NULL) {
302                         delete m_form_src;
303                 }
304                 m_form_src = form_src;
305         }
306
307         // text_dst is deleted by this GUIFormSpecMenu
308         void setTextDest(TextDest *text_dst)
309         {
310                 if (m_text_dst != NULL) {
311                         delete m_text_dst;
312                 }
313                 m_text_dst = text_dst;
314         }
315
316         void allowClose(bool value)
317         {
318                 m_allowclose = value;
319         }
320
321         void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
322         {
323                 m_lock = lock;
324                 m_lockscreensize = basescreensize;
325         }
326
327         void removeChildren();
328         void setInitialFocus();
329
330         void setFocus(const std::string &elementname)
331         {
332                 m_focused_element = elementname;
333         }
334
335         /*
336                 Remove and re-add (or reposition) stuff
337         */
338         void regenerateGui(v2u32 screensize);
339
340         ItemSpec getItemAtPos(v2s32 p) const;
341         void drawList(const ListDrawSpec &s, int phase, bool &item_hovered);
342         void drawSelectedItem();
343         void drawMenu();
344         void updateSelectedItem();
345         ItemStack verifySelectedItem();
346
347         void acceptInput(FormspecQuitMode quitmode);
348         bool preprocessEvent(const SEvent& event);
349         bool OnEvent(const SEvent& event);
350         bool doPause;
351         bool pausesGame() { return doPause; }
352
353         GUITable* getTable(const std::string &tablename);
354         std::vector<std::string>* getDropDownValues(const std::string &name);
355
356 #ifdef __ANDROID__
357         bool getAndroidUIInput();
358 #endif
359
360 protected:
361         v2s32 getBasePos() const
362         {
363                         return padding + offset + AbsoluteRect.UpperLeftCorner;
364         }
365
366         v2s32 padding;
367         v2s32 spacing;
368         v2s32 imgsize;
369         v2s32 offset;
370         v2s32 pos_offset;
371         std::stack<v2s32> container_stack;
372
373         irr::IrrlichtDevice* m_device;
374         InventoryManager *m_invmgr;
375         ISimpleTextureSource *m_tsrc;
376         Client *m_client;
377
378         std::string m_formspec_string;
379         InventoryLocation m_current_inventory_location;
380
381
382         std::vector<ListDrawSpec> m_inventorylists;
383         std::vector<ListRingSpec> m_inventory_rings;
384         std::vector<ImageDrawSpec> m_backgrounds;
385         std::vector<ImageDrawSpec> m_images;
386         std::vector<ImageDrawSpec> m_itemimages;
387         std::vector<BoxDrawSpec> m_boxes;
388         UNORDERED_MAP<std::string, bool> field_close_on_enter;
389         std::vector<FieldSpec> m_fields;
390         std::vector<StaticTextSpec> m_static_texts;
391         std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
392         std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
393         std::map<std::string, TooltipSpec> m_tooltips;
394         std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars;
395         std::vector<std::pair<FieldSpec, std::vector<std::string> > > m_dropdowns;
396
397         ItemSpec *m_selected_item;
398         u32 m_selected_amount;
399         bool m_selected_dragging;
400
401         // WARNING: BLACK MAGIC
402         // Used to guess and keep up with some special things the server can do.
403         // If name is "", no guess exists.
404         ItemStack m_selected_content_guess;
405         InventoryLocation m_selected_content_guess_inventory;
406
407         v2s32 m_pointer;
408         v2s32 m_old_pointer;  // Mouse position after previous mouse event
409         gui::IGUIStaticText *m_tooltip_element;
410
411         u32 m_tooltip_show_delay;
412         s32 m_hovered_time;
413         s32 m_old_tooltip_id;
414         std::wstring m_old_tooltip;
415
416         bool m_rmouse_auto_place;
417
418         bool m_allowclose;
419         bool m_lock;
420         v2u32 m_lockscreensize;
421
422         bool m_bgfullscreen;
423         bool m_slotborder;
424         video::SColor m_bgcolor;
425         video::SColor m_slotbg_n;
426         video::SColor m_slotbg_h;
427         video::SColor m_slotbordercolor;
428         video::SColor m_default_tooltip_bgcolor;
429         video::SColor m_default_tooltip_color;
430
431 private:
432         IFormSource        *m_form_src;
433         TextDest           *m_text_dst;
434         unsigned int        m_formspec_version;
435         std::string         m_focused_element;
436         JoystickController *m_joystick;
437
438         typedef struct {
439                 bool explicit_size;
440                 v2f invsize;
441                 v2s32 size;
442                 v2f32 offset;
443                 v2f32 anchor;
444                 core::rect<s32> rect;
445                 v2s32 basepos;
446                 v2u32 screensize;
447                 std::string focused_fieldname;
448                 GUITable::TableOptions table_options;
449                 GUITable::TableColumns table_columns;
450                 // used to restore table selection/scroll/treeview state
451                 UNORDERED_MAP<std::string, GUITable::DynamicData> table_dyndata;
452         } parserData;
453
454         typedef struct {
455                 bool key_up;
456                 bool key_down;
457                 bool key_enter;
458                 bool key_escape;
459         } fs_key_pendig;
460
461         fs_key_pendig current_keys_pending;
462         std::string current_field_enter_pending;
463
464         void parseElement(parserData* data, std::string element);
465
466         void parseSize(parserData* data, const std::string &element);
467         void parseContainer(parserData* data, const std::string &element);
468         void parseContainerEnd(parserData* data);
469         void parseList(parserData* data, const std::string &element);
470         void parseListRing(parserData* data, const std::string &element);
471         void parseCheckbox(parserData* data, const std::string &element);
472         void parseImage(parserData* data, const std::string &element);
473         void parseItemImage(parserData* data, const std::string &element);
474         void parseButton(parserData* data, const std::string &element,
475                         const std::string &typ);
476         void parseBackground(parserData* data, const std::string &element);
477         void parseTableOptions(parserData* data, const std::string &element);
478         void parseTableColumns(parserData* data, const std::string &element);
479         void parseTable(parserData* data, const std::string &element);
480         void parseTextList(parserData* data, const std::string &element);
481         void parseDropDown(parserData* data, const std::string &element);
482         void parseFieldCloseOnEnter(parserData *data, const std::string &element);
483         void parsePwdField(parserData* data, const std::string &element);
484         void parseField(parserData* data, const std::string &element, const std::string &type);
485         void parseSimpleField(parserData* data,std::vector<std::string> &parts);
486         void parseTextArea(parserData* data,std::vector<std::string>& parts,
487                         const std::string &type);
488         void parseLabel(parserData* data, const std::string &element);
489         void parseVertLabel(parserData* data, const std::string &element);
490         void parseImageButton(parserData* data, const std::string &element,
491                         const std::string &type);
492         void parseItemImageButton(parserData* data, const std::string &element);
493         void parseTabHeader(parserData* data, const std::string &element);
494         void parseBox(parserData* data, const std::string &element);
495         void parseBackgroundColor(parserData* data, const std::string &element);
496         void parseListColors(parserData* data, const std::string &element);
497         void parseTooltip(parserData* data, const std::string &element);
498         bool parseVersionDirect(const std::string &data);
499         bool parseSizeDirect(parserData* data, const std::string &element);
500         void parseScrollBar(parserData* data, const std::string &element);
501         bool parsePositionDirect(parserData *data, const std::string &element);
502         void parsePosition(parserData *data, const std::string &element);
503         bool parseAnchorDirect(parserData *data, const std::string &element);
504         void parseAnchor(parserData *data, const std::string &element);
505
506         void tryClose();
507
508         /**
509          * check if event is part of a double click
510          * @param event event to evaluate
511          * @return true/false if a doubleclick was detected
512          */
513         bool DoubleClickDetection(const SEvent event);
514
515         struct clickpos
516         {
517                 v2s32 pos;
518                 s32 time;
519         };
520         clickpos m_doubleclickdetect[2];
521
522         int m_btn_height;
523         gui::IGUIFont *m_font;
524
525         std::wstring getLabelByID(s32 id);
526         std::string getNameByID(s32 id);
527 #ifdef __ANDROID__
528         v2s32 m_down_pos;
529         std::string m_JavaDialogFieldName;
530 #endif
531
532         /* If true, remap a double-click (or double-tap) action to ESC. This is so
533          * that, for example, Android users can double-tap to close a formspec.
534         *
535          * This value can (currently) only be set by the class constructor
536          * and the default value for the setting is true.
537          */
538         bool m_remap_dbl_click;
539
540 };
541
542 class FormspecFormSource: public IFormSource
543 {
544 public:
545         FormspecFormSource(const std::string &formspec):
546                 m_formspec(formspec)
547         {}
548
549         ~FormspecFormSource()
550         {}
551
552         void setForm(const std::string &formspec)
553         {
554                 m_formspec = FORMSPEC_VERSION_STRING + formspec;
555         }
556
557         std::string getForm() { return m_formspec; }
558
559         std::string m_formspec;
560 };
561
562 #endif