1 //  SuperTuxKart - a fun racing game with go-kart
2 //
3 //  Copyright (C) 2009-2015 Marianne Gagnon
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (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 General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 
20 #ifndef HEADER_WIDGET_HPP
21 #define HEADER_WIDGET_HPP
22 
23 #include <irrString.h>
24 namespace irr
25 {
26     namespace gui { class IGUIElement; }
27 }
28 #include <bitset>
29 #include <map>
30 
31 #include "guiengine/event_handler.hpp"
32 #include "guiengine/skin.hpp"
33 #include "utils/constants.hpp"
34 #include "utils/ptr_vector.hpp"
35 
36 namespace GUIEngine
37 {
38 
39     class DynamicRibbonWidget;
40     class Screen;
41 
42     enum WidgetType
43     {
44         WTYPE_NONE = -1,
45         WTYPE_RIBBON,
46         WTYPE_SPINNER,
47         WTYPE_BUTTON,
48         WTYPE_ICON_BUTTON,
49         WTYPE_CHECKBOX,
50         WTYPE_LABEL,
51         WTYPE_BUBBLE,
52         WTYPE_SPACER,
53         WTYPE_DIV,
54         WTYPE_DYNAMIC_RIBBON,
55         WTYPE_MODEL_VIEW,
56         WTYPE_LIST,
57         WTYPE_TEXTBOX,
58         WTYPE_PROGRESS,
59         WTYPE_RATINGBAR
60     };
61 
62     enum BadgeType
63     {
64         /** display a lock on the widget, to mean a certain game feature is locked */
65         LOCKED_BADGE   = 1,
66         /** display a green check on a widget, useful e.g. to display confirmation */
67         OK_BADGE       = 2,
68         /** display a red mark badge on the widget, useful e.g. to warn of an invalid choice */
69         BAD_BADGE      = 4,
70         /** display a trophy badge on the widget, useful e.g. for challenges */
71         TROPHY_BADGE   = 8,
72         /** A gamepad icon */
73         GAMEPAD_BADGE  = 16,
74         /** A keyboard icon */
75         KEYBOARD_BADGE = 32,
76         /** An hourglass badge to indicate loading */
77         LOADING_BADGE  = 64,
78         /** A zipper badge to indicate that this player receives a boost */
79         ZIPPER_BADGE   = 128,
80         /** A anchor badge to indicate that this player receives a handicap */
81         ANCHOR_BADGE   = 256
82     };
83 
84 
85     enum Property
86     {
87         PROP_ID = 100,
88         PROP_PROPORTION,
89         PROP_WIDTH,
90         PROP_HEIGHT,
91         PROP_CHILD_WIDTH,
92         PROP_CHILD_HEIGHT,
93         PROP_WORD_WRAP,
94         PROP_ALTERNATE_BG,
95         PROP_LINE_HEIGHT,
96         //PROP_GROW_WITH_TEXT, // yet unused
97         PROP_X,
98         PROP_Y,
99         PROP_LAYOUT,
100         PROP_ALIGN,
101         // PROP_TEXT, // this one is a bit special, can't go along others since it's wide strings
102         PROP_ICON,
103         PROP_FOCUS_ICON,
104         PROP_TEXT_ALIGN,
105         PROP_TEXT_VALIGN,
106         PROP_MIN_VALUE,
107         PROP_MAX_VALUE,
108         PROP_MAX_WIDTH,
109         PROP_MAX_HEIGHT,
110         PROP_SQUARE,
111         PROP_EXTEND_LABEL,
112         PROP_LABELS_LOCATION,
113         PROP_MAX_ROWS,
114         PROP_WRAP_AROUND,
115         PROP_DIV_PADDING,
116         PROP_KEEP_SELECTION,
117         PROP_CUSTOM_RATIO,
118         PROP_ICON_ALIGN,
119     };
120 
121     bool isWithinATextBox();
122     void setWithinATextBox(bool in);
123 
124     /**
125       * \brief The nearly-abstract base of all widgets
126       * (not fully abstract since a bare Widget can be created for the sole goal of containing
127       * children widgets in a group)
128       *
129       * Provides basic common functionnality, as well as providing a few callbacks
130       * for children to override if they need to do something special on event.
131       *
132       * Each widget may have an irrlicht parent (most often used to put widgets in dialogs)
133       * and also optionally one or many children.
134       *
135       * Each widget also has a set of properties stored in a map (see enum above)
136       *
137       * \ingroup guiengine
138       */
139     class Widget : public SkinWidgetContainer
140     {
141     protected:
142         unsigned int m_magic_number;
143 
144         // Used to limit event callback on this widget based on input type
145         // At the moment used for continue button in kart selection
146         std::bitset<Input::IT_LAST + 1> m_active_event_callback;
147 
148         // FIXME: find better ways than hackish "friend"?
149         friend class EventHandler;
150         friend class Screen;
151         friend class Skin;
152         friend class RibbonWidget;
153         friend class SpinnerWidget;
154         friend class ProgressBarWidget;
155         friend class DynamicRibbonWidget;
156         friend class LayoutManager;
157         friend class ModalDialog;
158         friend class AbstractTopLevelContainer;
159 
160         /** Used during loading, by the layout engine. After layout is done this is not read anymore. */
161         int m_absolute_x, m_absolute_y, m_absolute_w, m_absolute_h;
162         int m_absolute_reverse_x, m_absolute_reverse_y;
163         float m_relative_x, m_relative_y, m_relative_w, m_relative_h;
164 
165         /** PROP_TEXT is a special case : since it can be translated it can't
166          *  go in the map above, which uses narrow strings */
167         irr::core::stringw m_text;
168 
169         /** When true, this widget shall use a bigger and more colourful font */
170         bool m_title_font;
171 
172         /**
173           * Can be used in children to indicate whether a widget is selected or not
174           * - in widgets where it makes sense (e.g. ribbon children) and where the
175           * irrLicht widget can not directly contain this state
176           */
177         bool m_selected[MAX_PLAYER_COUNT];
178 
179         /**
180           * Whether to descend in the children of this widget when searching a widget
181           * from its ID or name. (children classes can override this value as they please)
182           */
183         bool m_check_inside_me;
184 
185         /**
186           * called when right key is pressed and focus is on widget.
187           * Returns 'EVENT_LET' if user's event handler should be notified of a change.
188           * Override in children to be notified of left/right events and/or make
189           * the event propagate to the user's event handler.
190           */
rightPressed(const int playerID)191         virtual EventPropagation rightPressed(const int playerID) { return EVENT_BLOCK; }
192 
193         /**
194          * called when left key is pressed and focus is on widget.
195          * Returns 'EVENT_LET' if user's event handler should be notified of a change.
196          * Override in children to be notified of left/right events and/or make
197          * the event propagate to the user's event handler.
198          */
leftPressed(const int playerID)199         virtual EventPropagation leftPressed (const int playerID) { return EVENT_BLOCK; }
200 
201         /**
202           * called when up key is pressed and focus is on widget.
203           * Returns 'EVENT_LET' if user's event handler should be notified of a change.
204           * Override in children to be notified of up/down events and/or make
205           * the event propagate to the user's event handler.
206           */
upPressed(const int playerID)207         virtual EventPropagation upPressed(const int playerID) { return EVENT_BLOCK; }
208 
209         /**
210           * called when down key is pressed and focus is on widget.
211           * Returns 'EVENT_LET' if user's event handler should be notified of a change.
212           * Override in children to be notified of up/down events and/or make
213           * the event propagate to the user's event handler.
214           */
downPressed(const int playerID)215         virtual EventPropagation downPressed(const int playerID) { return EVENT_BLOCK; }
216 
217         /** used when you set eventSupervisors - see m_event_handler explainations below
218             called when one of a widget's children is hovered.
219             \return 'EVENT_LET' if main event handler should be notified of a change, 'EVENT_BLOCK' otherwise */
mouseHovered(Widget * child,const int playerID)220         virtual EventPropagation mouseHovered(Widget* child, const int playerID) { return EVENT_BLOCK; }
221 
222         /** override in children if you need to know when the widget is focused.
223           * \return whether to block event */
focused(const int playerID)224         virtual EventPropagation focused(const int playerID) { setWithinATextBox(false); return EVENT_LET; }
225 
226         /** override in children if you need to know when the widget is unfocused. */
unfocused(const int playerID,Widget * new_focus)227         virtual void unfocused(const int playerID, Widget* new_focus) { }
228 
229         /**
230          * An irrlicht parent (most often used to put widgets in dialogs)
231          */
232         irr::gui::IGUIElement* m_parent;
233 
234         /**
235          * IrrLicht widget created to represent this object.
236          */
237         irr::gui::IGUIElement* m_element;
238 
239 
240         /** numerical ID used by irrLicht to identify this widget
241          * (not the same as the string identificator specified in the XML file)
242          */
243         int m_id;
244 
245         /** Usually, only one widget at a time can be focused. There is however a special case where all
246             players can move through the screen. This variable will then be used as a bitmask to contain
247             which players beyong player 1 have this widget focused. */
248         bool m_player_focus[MAX_PLAYER_COUNT];
249 
250         /** Whether to reserve an ID in 'm_reserved_id' when widget is added */
251         bool m_reserve_id;
252 
253         /** Type of this widget */
254         WidgetType m_type;
255 
256         /**
257          * If this widget has any children, they go here. Children can be either
258          * specified in the XML file (e.g. Ribbon or Div children), or can also
259          * be created automatically for logical widgets built with more than
260          * one irrlicht widgets (e.g. Spinner)
261          */
262         PtrVector<Widget> m_children;
263 
264         /** A bitmask of which badges to show, if any; choices are *_BADGE, defined above */
265         int m_badges;
266 
267         /** A simple flag that can be raised to deactivate this widget */
268         bool m_deactivated;
269 
270         /** A flag to indicate whether this widget should be visible or not. */
271         bool m_is_visible;
272 
273         /** Set to false if widget is something that should not receive focus */
274         bool m_focusable;
275 
276         bool m_bottom_bar;
277         bool m_top_bar;
278 
279         /** If a badge wouldn't look too pretty on the very side of the widget */
280         int m_badge_x_shift;
281 
282         bool m_has_tooltip;
283         irr::core::stringw m_tooltip_text;
284 
285         /** height of the widget before it was collapsed (only set if widget got collapsed) */
286         int m_uncollapsed_height;
287 
288         /** A flag to indicate whether this widget got collapsed. */
289         bool m_is_collapsed;
290 
291     public:
292 
293         /**
294          * This is set to NULL by default; set to something else in a widget to mean
295          * that events happening on this widget should also be passed to m_event_handler->transmitEvent,
296          * which is usually the parent analysing events from its children.
297          * This is especially useful with logical widgets built with more than
298          * one irrlicht widgets (e.g. Spinner, Ribbon)
299          */
300         Widget* m_event_handler;
301 
302         /**
303           * Whether this widget supports multiplayer interaction (i.e. whether this widget can be
304           * used by players other than by the game master)
305           */
306         bool m_supports_multiplayer;
307 
308         /** Instead of searching for widget IDs smaller/greater than that of this object, navigation
309             through widgets will start from these IDs (if they are set). */
310         int m_tab_down_root;
311 
312         /** Instead of searching for widget IDs smaller/greater than that of this object, navigation
313          through widgets will start from these IDs (if they are set). */
314         int m_tab_up_root;
315 
316         /** Coordinates of the widget once added (the difference between those x/h and PROP_WIDTH/PROP_HEIGHT is
317             that the props are read in raw form from the XML file; PROP_WIDTH can then be e.g. "10%" and w,
318             once the widget is added, will be e.g. 80.) */
319         int m_x, m_y, m_w, m_h;
320 
321         /** Whether to show a bounding box around this widget (used for sections) */
322         bool m_show_bounding_box;
323 
324         /** Only used if m_show_bounding_box is true */
325         bool m_is_bounding_box_round;
326 
327         /** Used in two cases :
328             1) For 'placeholder' divisions; at the time the layout is created, there is nothing to
329                place there yet, but we know there eventually will. So in this case pass 'true' to the
330                Widget constructor and it will reserve a widget ID and store it here.
331             2) Theorically, in 'add()', derived widgets should checked if this value is set, and use
332                it instead of creating a new ID if it is. In practice, it's not widely implemented (FIXME) */
333         int m_reserved_id;
334 
335         /**
336          * A map that holds values for all specified widget properties (in the XML file)
337          *
338          * \note Changing any of these properties will only take effect the next time
339          *       this widget is add()ed (EXCEPT for for x, y, width and height properties,
340          *       which are only read on load; after that use method Widget::move).
341          * \note Not all widgets use all properties, some widgets may ignore some properties.
342          */
343         std::map<Property, std::string> m_properties;
344 
345         Widget(WidgetType type, bool reserve_id = false);
346         virtual ~Widget();
347 
348         /**
349           * Allow (or not) an event callback for this widget based on input type.
350           */
351         virtual void setEventCallbackActive(Input::InputType type, bool active);
352 
353         /**
354           * Return if there should be an event callback for this widget based on input type.
355           */
356         virtual bool isEventCallbackActive(Input::InputType type) const;
357 
358         /**
359           * Set the irrlicht widget to be used as parent of this widget next time Widget::add()
360           * is invoked on this widget.
361           */
362         void setParent(irr::gui::IGUIElement* parent);
363 
364         /**
365          * \brief Sets the widget (and its children, if any) visible or not.
366          * Note that setting a widget invisible implicitely calls setDeactivated(), and setting
367          * it visible implicitely calls setActive(true). If you mix visiblity and (de)activated calls,
368          * undefined behavior may ensue (like invisible but clickable buttons).
369          */
370         virtual void setVisible(bool visible);
371 
372         /**
373          * \brief Sets the widget (and its children, if any) collapsed or not.
374          * !!! Note: this has to be called inside beforeAddingWidget() !!!
375          * Pass in the screen to get (the necessary) calculate Layout automatically called.
376          * This will also set the widget invisible depending of collapsed state.
377          * Note that setting a widget invisible implicitely calls setDeactivated(), and setting
378          * it visible implicitely calls setActive(true). If you mix visiblity and (de)activated calls,
379          * undefined behavior may ensue (like invisible but clickable buttons).
380          */
381         virtual void setCollapsed(bool collapsed, Screen* calling_screen = NULL);
382 
383         /**
384          * \brief Sets the widget (and its children, if any) collapsed or not.
385          * !!! Note: this has to be called inside beforeAddingWidget() !!!
386          * Pass in the screen to get (the necessary) calculate Layout automatically called.
387          * This will also set the widget invisible depending of collapsed state.
388          * Note that setting a widget invisible implicitely calls setDeactivated(), and setting
389          * it visible implicitely calls setActive(true). If you mix visiblity and (de)activated calls,
390          * undefined behavior may ensue (like invisible but clickable buttons).
391          */
392         virtual void setCollapsed(bool collapsed, int uncollapsed_height, Screen* calling_screen = NULL);
393 
394         /** Returns if the element is visible. */
395         bool isVisible() const;
396 
397         /** Returns whether the element is collapsed (through setCollapsed). */
isCollapsed() const398         bool isCollapsed() const { return  m_is_collapsed; }
399 
400         bool isActivated() const;
401 
onActivationInput(const int playerID)402         virtual EventPropagation onActivationInput(const int playerID) { return EVENT_LET; }
403 
404         /**
405          * Call to resize/move the widget. Not all widgets can resize gracefully.
406          */
407         virtual void move(const int x, const int y, const int w, const int h);
408 
409         /**
410           * Get whether this widget is selected (only makes sense in some cases where
411           * a widget is part of a bigger widget, e.g. in ribbons, and a selected item
412           * is kept)
413           */
isSelected(const int playerID) const414         bool isSelected(const int playerID) const { return m_selected[playerID]; }
setSelected(const int playerID,bool state)415         void setSelected(const int playerID, bool state) { m_selected[playerID] = state;}
416 
isBottomBar() const417         bool isBottomBar() const { return m_bottom_bar; }
isTopBar() const418         bool isTopBar   () const { return m_top_bar;    }
419 
420         /**
421          * \name Enabling or disabling widgets
422          * \{
423          */
424 
425         /** \brief Sets an widget to be either activated or deactivated
426          *  (i.e. greyed out)
427          *  \param active Active (true) or deactive (false). Defaults to
428          *         true. */
429         virtual void setActive(bool active=true);
430 
431         /**
432           * \}
433           */
434 
435         /**
436          * \name Accessing the underlying irrlicht element
437          * \{
438          */
439 
440         /**
441           * Get the underlying irrLicht GUI element, casted to the right type.
442           */
getIrrlichtElement()443         template<typename T> T* getIrrlichtElement()
444         {
445         #if HAVE_RTT
446             T* out = dynamic_cast<T*>(m_element);
447             return out;
448         #else
449             return static_cast<T*>(m_element);
450         #endif
451         }
452 
453         /**
454          * Get the underlying irrLicht GUI element, casted to the right type; const version.
455          */
getIrrlichtElement() const456         template<typename T> const T* getIrrlichtElement() const
457         {
458             #if HAVE_RTT
459                 T* out = dynamic_cast<T*>(m_element);
460                 return out;
461             #else
462                 return static_cast<T*>(m_element);
463             #endif
464         }
465 
466         /**
467          * Get the underlying irrLicht GUI element
468          */
getIrrlichtElement()469         irr::gui::IGUIElement* getIrrlichtElement() { return m_element; }
470 
471         void moveIrrlichtElement();
isSameIrrlichtWidgetAs(const Widget * ref) const472         bool isSameIrrlichtWidgetAs(const Widget* ref) const { return m_element == ref->m_element; }
473 
474         /**
475           * \}
476           */
477 
478         /**
479          * \name Get and set properties
480          * \{
481          * Note that many properties are read only by the Widget::add method; so, while
482          * it will generally work to set the properties before add() is called, modifying
483          * the widget after it was added will require other widget-specific calls.
484          */
485 
486         /**
487           * Sets the text of a widget from a wchar_t.
488           * Handy for many constant strings used in stk.
489           *
490           * \note Not all widgets use strings, so some widgets may ignore this text property
491           * \note Changing the text property will only take effect the next time this widget
492           *       is add()ed
493           */
494         virtual void setText(const irr::core::stringw &s);
495 
496         /** Returns the text of a widget. */
getText() const497         const irr::core::stringw &getText() const {return m_text; }
498 
499         /** \return Type of this widget */
getType() const500         WidgetType getType() const { return m_type; }
501 
502         /**
503           * Get the irrlicht widget ID attributed to this widget
504           * \pre Only call this method after the widget has been add()ed
505           */
getID() const506         int getID() const { return m_id; }
507 
508         /** Get whether this object is allowed to receive focus */
isFocusable() const509         bool isFocusable() const { return m_focusable; }
510 
setFocusable(bool f)511         void setFocusable(bool f) { m_focusable = f; }
512 
513         /**
514           * \}
515           */
516 
517         /**
518          * \name Focus management
519          * \{
520          */
521 
522         /**
523          * Focus the widget for the given player.
524          * \param playerID ID of the player you want to set/unset focus for, starting from 0
525          */
526         void setFocusForPlayer(const int playerID);
527 
528         /**
529          * Find whether this widget is focused by a given player.
530          * \param playerID ID of the player you want to set/unset focus for, starting from 0
531          * \return whether this widget is focused by a given player.
532          */
533         bool isFocusedForPlayer(const int playerID);
534 
535         /** Internal method, do not call it. Call the functions in GUIEngine instead to unset focus. */
536         void unsetFocusForPlayer(const int playerID);
537 
538         /**
539           * \}
540           */
541 
542         /**
543          * \name ID Counter Functions
544          * Functions used to generate IDs for new widgets. The domain of each ID
545          * encodes whether the widget can receive focus or not (this was implemented
546          * this way because navigation in irrlicht happens between sequential IDs; so
547          * to prevent navigation to a widget, one needs to give an ID that is not
548          * sequential with focusable widgets in order not to break keyboard navigation).
549          * \{
550          */
551 
552         static void resetIDCounters();
553 
554         /**
555           * \brief Provides a new unique ID on each call, for widgets that can be focused.
556           */
557         static int getNewID();
558 
559         /**
560           * \brief Provides a new unique ID on each call, for widgets that can not be focused.
561           */
562         static int getNewNoFocusID();
563 
564         /**
565           * \brief get whether the given ID represents an ID of a widget that can be focused
566           * \return whether the given ID represents an ID of a widget that can be focused
567           *         (i.e. whether it was generated by Widget::getNewID() or
568           *          Widget::getNewNoFocusID())
569           */
570         static bool isFocusableId(const int id);
571 
572         /**
573           * \}
574           */
575 
576         /**
577          * \name Handling children
578          * If this widget is a container and has children.
579          * \{
580          */
581 
582         /**
583           * \return a read-only view of the childrens of this widget, if any
584           */
getChildren() const585         const PtrVector<Widget>& getChildren() const { return m_children; }
586 
getChildren()587         PtrVector<Widget>&       getChildren()       { return m_children; }
588 
589         /**
590           * \brief removes and deletes the child with the given PROP_ID
591           * \param id PROP_ID property of the child to remove
592           *
593           * \note  If the widget has been add()ed, it is moved immediately;
594           *        if the widget is not currently visible, it will take the
595           *        new position next time it is add()ed.
596           *
597           * \return whether deletion was successful
598           */
599         bool deleteChild(const char* id);
600 
601         /**
602           * \}
603           */
604 
605         /**
606          * \{
607          * \name Callbacks for subclasses
608          * Classes that subclass Widget to provide actual implementations may override/implement these
609          * methods to change behaviour or be notified of some events.
610          */
611 
612         /**
613          * \brief Override in children to possibly receive updates (you may need to register to
614          * them first)
615          */
update(float delta)616         virtual void update(float delta) { }
617 
618         /** All widgets, including their parents (m_event_handler) will be notified on event through
619          this call. Must return whether main (GUI engine user) event callback should be notified or not.
620          Note that in the case of a hierarchy of widgets (with m_event_handler), only the topmost widget
621          of the chain decides whether the main handler is notified; return value is not read for others. */
transmitEvent(Widget * w,const std::string & originator,const int playerID)622         virtual EventPropagation transmitEvent(Widget* w,
623                                                const std::string& originator,
624                                                const int playerID)
625                 { return EVENT_LET; }
626 
627         /**
628          * \brief Create and add the irrLicht widget(s) associated with this object.
629          * Call after Widget was read from XML file and laid out.
630          */
631         virtual void add();
632 
633         /**
634           * \brief Called when irrLicht widgets cleared. Forget all references to them, they're no more valid.
635           */
636         virtual void elementRemoved();
637 
searchInsideMe() const638         bool searchInsideMe() const { return m_check_inside_me; }
639 
640         /** When inferring widget size from its label length, this method will be called to
641          * if/how much space must be added to the raw label's size for the widget to be large enough */
getWidthNeededAroundLabel() const642         virtual int getWidthNeededAroundLabel()  const { return 0; }
643 
644         /** When inferring widget size from its label length, this method will be called to
645          * if/how much space must be added to the raw label's size for the widget to be large enough */
getHeightNeededAroundLabel() const646         virtual int getHeightNeededAroundLabel() const { return 0; }
647 
648         /**
649           * \}
650           */
651 
652         /**
653          * \name Badge support
654          * "Badges" are icons that can appear on top of some widgets.
655          * \{
656          */
657 
658         /**
659          * \brief adds a particular badge to this widget.
660          * The STK widget toolkit has support for "badges". Badges are icon overlays displayed
661          * on the corner of a widget; they are useful to convey information visually.
662          */
setBadge(BadgeType badge_bit)663         void setBadge(BadgeType badge_bit)
664         {
665             m_badges |= int(badge_bit);
666         }
667 
668         /**
669          * \brief removes a particular bade from this widget, if it had it.
670          * \see GUIEngine::Widget::setBadge for more info on badge support
671          */
unsetBadge(BadgeType badge_bit)672         void unsetBadge(BadgeType badge_bit)
673         {
674             m_badges &= (~int(badge_bit));
675         }
676 
677         /** \brief sets this widget to have no badge
678          * \see GUIEngine::Widget::setBadge for more info on badge support
679          */
resetAllBadges()680         void resetAllBadges()
681         {
682             m_badges = 0;
683         }
684 
685         /**
686          * \brief Get which badges are currently on this widget
687          * \return a bitmask of BadgeType values
688          */
getBadges() const689         int getBadges() const
690         {
691             return m_badges;
692         }
693 
694         /**
695          * \}
696          */
697 
698         /**
699          * \name Tooltip support
700          * \{
701          */
702 
703 
hasTooltip() const704         bool hasTooltip() const { return m_has_tooltip; }
705 
706         /** Only call if hasTooltip() returned true */
getTooltipText() const707         irr::core::stringw getTooltipText() const { return m_tooltip_text; }
708 
setTooltip(irr::core::stringw s)709         void setTooltip(irr::core::stringw s) { m_tooltip_text = s; m_has_tooltip = true; }
710 
711         /**
712          * \}
713          */
714 
ok() const715         bool ok() const { return (m_magic_number == 0xCAFEC001); }
716 
717         /** Gets called when the widget is active and got clicked. (Only works for button widgets for now.) */
onClick()718         virtual EventPropagation onClick()  { return EVENT_LET; }
getDimension() const719         virtual irr::core::dimension2di getDimension() const { return irr::core::dimension2di(m_w, m_h); }
720     };
721 
722 
723 }
724 #endif
725