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