]> git.lizzy.rs Git - dragonfireclient.git/blob - src/gui/guiFormSpecMenu.h
Add limit parameter to decompressZlib
[dragonfireclient.git] / src / gui / 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 #pragma once
21
22 #include <utility>
23 #include <stack>
24 #include <unordered_set>
25
26 #include "irrlichttypes_extrabloated.h"
27 #include "inventorymanager.h"
28 #include "modalMenu.h"
29 #include "guiInventoryList.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 #include "StyleSpec.h"
36
37 class InventoryManager;
38 class ISimpleTextureSource;
39 class Client;
40 class GUIScrollBar;
41
42 typedef enum {
43         f_Button,
44         f_Table,
45         f_TabHeader,
46         f_CheckBox,
47         f_DropDown,
48         f_ScrollBar,
49         f_Box,
50         f_ItemImage,
51         f_Unknown
52 } FormspecFieldType;
53
54 typedef enum {
55         quit_mode_no,
56         quit_mode_accept,
57         quit_mode_cancel
58 } FormspecQuitMode;
59
60 struct TextDest
61 {
62         virtual ~TextDest() = default;
63
64         // This is deprecated I guess? -celeron55
65         virtual void gotText(const std::wstring &text) {}
66         virtual void gotText(const StringMap &fields) = 0;
67
68         std::string m_formname;
69 };
70
71 class IFormSource
72 {
73 public:
74         virtual ~IFormSource() = default;
75         virtual const std::string &getForm() const = 0;
76         // Fill in variables in field text
77         virtual std::string resolveText(const std::string &str) { return str; }
78 };
79
80 class GUIFormSpecMenu : public GUIModalMenu
81 {
82         struct ListRingSpec
83         {
84                 ListRingSpec() = default;
85
86                 ListRingSpec(const InventoryLocation &a_inventoryloc,
87                                 const std::string &a_listname):
88                         inventoryloc(a_inventoryloc),
89                         listname(a_listname)
90                 {
91                 }
92
93                 InventoryLocation inventoryloc;
94                 std::string listname;
95         };
96
97         struct FieldSpec
98         {
99                 FieldSpec() = default;
100
101                 FieldSpec(const std::string &name, const std::wstring &label,
102                                 const std::wstring &default_text, s32 id, int priority = 0,
103                                 gui::ECURSOR_ICON cursor_icon = ECI_NORMAL) :
104                         fname(name),
105                         flabel(label),
106                         fdefault(unescape_enriched(translate_string(default_text))),
107                         fid(id),
108                         send(false),
109                         ftype(f_Unknown),
110                         is_exit(false),
111                         priority(priority),
112                         fcursor_icon(cursor_icon)
113                 {
114                 }
115
116                 std::string fname;
117                 std::wstring flabel;
118                 std::wstring fdefault;
119                 s32 fid;
120                 bool send;
121                 FormspecFieldType ftype;
122                 bool is_exit;
123                 // Draw priority for formspec version < 3
124                 int priority;
125                 core::rect<s32> rect;
126                 gui::ECURSOR_ICON fcursor_icon;
127         };
128
129         struct TooltipSpec
130         {
131                 TooltipSpec() = default;
132                 TooltipSpec(const std::wstring &a_tooltip, irr::video::SColor a_bgcolor,
133                                 irr::video::SColor a_color):
134                         tooltip(translate_string(a_tooltip)),
135                         bgcolor(a_bgcolor),
136                         color(a_color)
137                 {
138                 }
139
140                 std::wstring tooltip;
141                 irr::video::SColor bgcolor;
142                 irr::video::SColor color;
143         };
144
145 public:
146         GUIFormSpecMenu(JoystickController *joystick,
147                         gui::IGUIElement* parent, s32 id,
148                         IMenuManager *menumgr,
149                         Client *client,
150                         ISimpleTextureSource *tsrc,
151                         IFormSource* fs_src,
152                         TextDest* txt_dst,
153                         const std::string &formspecPrepend,
154                         bool remap_dbl_click = true);
155
156         ~GUIFormSpecMenu();
157
158         static void create(GUIFormSpecMenu *&cur_formspec, Client *client,
159                 JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest,
160                 const std::string &formspecPrepend);
161
162         void setFormSpec(const std::string &formspec_string,
163                         const InventoryLocation &current_inventory_location)
164         {
165                 m_formspec_string = formspec_string;
166                 m_current_inventory_location = current_inventory_location;
167                 regenerateGui(m_screensize_old);
168         }
169
170         const InventoryLocation &getFormspecLocation()
171         {
172                 return m_current_inventory_location;
173         }
174
175         void setFormspecPrepend(const std::string &formspecPrepend)
176         {
177                 m_formspec_prepend = formspecPrepend;
178         }
179
180         // form_src is deleted by this GUIFormSpecMenu
181         void setFormSource(IFormSource *form_src)
182         {
183                 delete m_form_src;
184                 m_form_src = form_src;
185         }
186
187         // text_dst is deleted by this GUIFormSpecMenu
188         void setTextDest(TextDest *text_dst)
189         {
190                 delete m_text_dst;
191                 m_text_dst = text_dst;
192         }
193
194         void allowClose(bool value)
195         {
196                 m_allowclose = value;
197         }
198
199         void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
200         {
201                 m_lock = lock;
202                 m_lockscreensize = basescreensize;
203         }
204
205         void removeChildren();
206         void setInitialFocus();
207
208         void setFocus(const std::string &elementname)
209         {
210                 m_focused_element = elementname;
211         }
212
213         Client *getClient() const
214         {
215                 return m_client;
216         }
217
218         const GUIInventoryList::ItemSpec *getSelectedItem() const
219         {
220                 return m_selected_item;
221         }
222
223         const u16 getSelectedAmount() const
224         {
225                 return m_selected_amount;
226         }
227
228         bool doTooltipAppendItemname() const
229         {
230                 return m_tooltip_append_itemname;
231         }
232
233         void addHoveredItemTooltip(const std::string &name)
234         {
235                 m_hovered_item_tooltips.emplace_back(name);
236         }
237
238         /*
239                 Remove and re-add (or reposition) stuff
240         */
241         void regenerateGui(v2u32 screensize);
242
243         GUIInventoryList::ItemSpec getItemAtPos(v2s32 p) const;
244         void drawSelectedItem();
245         void drawMenu();
246         void updateSelectedItem();
247         ItemStack verifySelectedItem();
248
249         void acceptInput(FormspecQuitMode quitmode);
250         bool preprocessEvent(const SEvent& event);
251         bool OnEvent(const SEvent& event);
252         bool doPause;
253         bool pausesGame() { return doPause; }
254
255         GUITable* getTable(const std::string &tablename);
256         std::vector<std::string>* getDropDownValues(const std::string &name);
257
258 #ifdef __ANDROID__
259         bool getAndroidUIInput();
260 #endif
261
262 protected:
263         v2s32 getBasePos() const
264         {
265                         return padding + offset + AbsoluteRect.UpperLeftCorner;
266         }
267         std::wstring getLabelByID(s32 id);
268         std::string getNameByID(s32 id);
269         const FieldSpec *getSpecByID(s32 id);
270         v2s32 getElementBasePos(const std::vector<std::string> *v_pos);
271         v2s32 getRealCoordinateBasePos(const std::vector<std::string> &v_pos);
272         v2s32 getRealCoordinateGeometry(const std::vector<std::string> &v_geom);
273
274         std::unordered_map<std::string, StyleSpec> theme_by_type;
275         std::unordered_map<std::string, StyleSpec> theme_by_name;
276         std::unordered_set<std::string> property_warned;
277
278         StyleSpec getStyleForElement(const std::string &type,
279                         const std::string &name="", const std::string &parent_type="");
280
281         v2s32 padding;
282         v2f32 spacing;
283         v2s32 imgsize;
284         v2s32 offset;
285         v2f32 pos_offset;
286         std::stack<v2f32> container_stack;
287
288         InventoryManager *m_invmgr;
289         ISimpleTextureSource *m_tsrc;
290         Client *m_client;
291
292         std::string m_formspec_string;
293         std::string m_formspec_prepend;
294         InventoryLocation m_current_inventory_location;
295
296         std::vector<GUIInventoryList *> m_inventorylists;
297         std::vector<ListRingSpec> m_inventory_rings;
298         std::vector<gui::IGUIElement *> m_backgrounds;
299         std::unordered_map<std::string, bool> field_close_on_enter;
300         std::vector<FieldSpec> m_fields;
301         std::vector<std::pair<FieldSpec, GUITable *>> m_tables;
302         std::vector<std::pair<FieldSpec, gui::IGUICheckBox *>> m_checkboxes;
303         std::map<std::string, TooltipSpec> m_tooltips;
304         std::vector<std::pair<gui::IGUIElement *, TooltipSpec>> m_tooltip_rects;
305         std::vector<std::pair<FieldSpec, GUIScrollBar *>> m_scrollbars;
306         std::vector<std::pair<FieldSpec, std::vector<std::string>>> m_dropdowns;
307
308         GUIInventoryList::ItemSpec *m_selected_item = nullptr;
309         u16 m_selected_amount = 0;
310         bool m_selected_dragging = false;
311         ItemStack m_selected_swap;
312
313         gui::IGUIStaticText *m_tooltip_element = nullptr;
314
315         u64 m_tooltip_show_delay;
316         bool m_tooltip_append_itemname;
317         u64 m_hovered_time = 0;
318         s32 m_old_tooltip_id = -1;
319
320         bool m_auto_place = false;
321
322         bool m_allowclose = true;
323         bool m_lock = false;
324         v2u32 m_lockscreensize;
325
326         bool m_bgnonfullscreen;
327         bool m_bgfullscreen;
328         video::SColor m_bgcolor;
329         video::SColor m_fullscreen_bgcolor;
330         video::SColor m_default_tooltip_bgcolor;
331         video::SColor m_default_tooltip_color;
332
333
334 private:
335         IFormSource        *m_form_src;
336         TextDest           *m_text_dst;
337         u16                 m_formspec_version = 1;
338         std::string         m_focused_element = "";
339         JoystickController *m_joystick;
340
341         typedef struct {
342                 bool explicit_size;
343                 bool real_coordinates;
344                 u8 simple_field_count;
345                 v2f invsize;
346                 v2s32 size;
347                 v2f32 offset;
348                 v2f32 anchor;
349                 core::rect<s32> rect;
350                 v2s32 basepos;
351                 v2u32 screensize;
352                 std::string focused_fieldname;
353                 GUITable::TableOptions table_options;
354                 GUITable::TableColumns table_columns;
355
356                 GUIInventoryList::Options inventorylist_options;
357
358                 struct {
359                         s32 max = 1000;
360                         s32 min = 0;
361                         s32 small_step = 10;
362                         s32 large_step = 100;
363                         s32 thumb_size = 1;
364                         GUIScrollBar::ArrowVisibility arrow_visiblity = GUIScrollBar::DEFAULT;
365                 } scrollbar_options;
366
367                 // used to restore table selection/scroll/treeview state
368                 std::unordered_map<std::string, GUITable::DynamicData> table_dyndata;
369         } parserData;
370
371         typedef struct {
372                 bool key_up;
373                 bool key_down;
374                 bool key_enter;
375                 bool key_escape;
376         } fs_key_pendig;
377
378         fs_key_pendig current_keys_pending;
379         std::string current_field_enter_pending = "";
380         std::vector<std::string> m_hovered_item_tooltips;
381
382         void parseElement(parserData* data, const std::string &element);
383
384         void parseSize(parserData* data, const std::string &element);
385         void parseContainer(parserData* data, const std::string &element);
386         void parseContainerEnd(parserData* data);
387         void parseList(parserData* data, const std::string &element);
388         void parseListRing(parserData* data, const std::string &element);
389         void parseCheckbox(parserData* data, const std::string &element);
390         void parseImage(parserData* data, const std::string &element);
391         void parseItemImage(parserData* data, const std::string &element);
392         void parseButton(parserData* data, const std::string &element,
393                         const std::string &typ);
394         void parseBackground(parserData* data, const std::string &element);
395         void parseTableOptions(parserData* data, const std::string &element);
396         void parseTableColumns(parserData* data, const std::string &element);
397         void parseTable(parserData* data, const std::string &element);
398         void parseTextList(parserData* data, const std::string &element);
399         void parseDropDown(parserData* data, const std::string &element);
400         void parseFieldCloseOnEnter(parserData *data, const std::string &element);
401         void parsePwdField(parserData* data, const std::string &element);
402         void parseField(parserData* data, const std::string &element, const std::string &type);
403         void createTextField(parserData *data, FieldSpec &spec,
404                 core::rect<s32> &rect, bool is_multiline);
405         void parseSimpleField(parserData* data,std::vector<std::string> &parts);
406         void parseTextArea(parserData* data,std::vector<std::string>& parts,
407                         const std::string &type);
408         void parseHyperText(parserData *data, const std::string &element);
409         void parseLabel(parserData* data, const std::string &element);
410         void parseVertLabel(parserData* data, const std::string &element);
411         void parseImageButton(parserData* data, const std::string &element,
412                         const std::string &type);
413         void parseItemImageButton(parserData* data, const std::string &element);
414         void parseTabHeader(parserData* data, const std::string &element);
415         void parseBox(parserData* data, const std::string &element);
416         void parseBackgroundColor(parserData* data, const std::string &element);
417         void parseListColors(parserData* data, const std::string &element);
418         void parseTooltip(parserData* data, const std::string &element);
419         bool parseVersionDirect(const std::string &data);
420         bool parseSizeDirect(parserData* data, const std::string &element);
421         void parseScrollBar(parserData* data, const std::string &element);
422         void parseScrollBarOptions(parserData *data, const std::string &element);
423         bool parsePositionDirect(parserData *data, const std::string &element);
424         void parsePosition(parserData *data, const std::string &element);
425         bool parseAnchorDirect(parserData *data, const std::string &element);
426         void parseAnchor(parserData *data, const std::string &element);
427         bool parseStyle(parserData *data, const std::string &element, bool style_type);
428
429         void tryClose();
430
431         void showTooltip(const std::wstring &text, const irr::video::SColor &color,
432                 const irr::video::SColor &bgcolor);
433
434         /**
435          * In formspec version < 2 the elements were not ordered properly. Some element
436          * types were drawn before others.
437          * This function sorts the elements in the old order for backwards compatibility.
438          */
439         void legacySortElements(core::list<IGUIElement *>::Iterator from);
440
441         /**
442          * check if event is part of a double click
443          * @param event event to evaluate
444          * @return true/false if a doubleclick was detected
445          */
446         bool DoubleClickDetection(const SEvent event);
447
448         struct clickpos
449         {
450                 v2s32 pos;
451                 s64 time;
452         };
453         clickpos m_doubleclickdetect[2];
454
455         int m_btn_height;
456         gui::IGUIFont *m_font = nullptr;
457
458         /* If true, remap a double-click (or double-tap) action to ESC. This is so
459          * that, for example, Android users can double-tap to close a formspec.
460         *
461          * This value can (currently) only be set by the class constructor
462          * and the default value for the setting is true.
463          */
464         bool m_remap_dbl_click;
465 };
466
467 class FormspecFormSource: public IFormSource
468 {
469 public:
470         FormspecFormSource(const std::string &formspec):
471                 m_formspec(formspec)
472         {
473         }
474
475         ~FormspecFormSource() = default;
476
477         void setForm(const std::string &formspec)
478         {
479                 m_formspec = formspec;
480         }
481
482         const std::string &getForm() const
483         {
484                 return m_formspec;
485         }
486
487         std::string m_formspec;
488 };