1 /*********************************************************************** 2 created: 18/8/2011 3 author: Martin Preisler 4 5 purpose: Defines a class representing an item in a graph 6 (deals with relative positions, relative dimensions, ...) 7 *************************************************************************/ 8 /*************************************************************************** 9 * Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining 12 * a copy of this software and associated documentation files (the 13 * "Software"), to deal in the Software without restriction, including 14 * without limitation the rights to use, copy, modify, merge, publish, 15 * distribute, sublicense, and/or sell copies of the Software, and to 16 * permit persons to whom the Software is furnished to do so, subject to 17 * the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be 20 * included in all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 * OTHER DEALINGS IN THE SOFTWARE. 29 ***************************************************************************/ 30 31 #ifndef _CEGUIElement_h_ 32 #define _CEGUIElement_h_ 33 34 #include "CEGUI/Base.h" 35 #include "CEGUI/PropertySet.h" 36 #include "CEGUI/EventSet.h" 37 #include "CEGUI/EventArgs.h" 38 39 #if defined(_MSC_VER) 40 # pragma warning(push) 41 # pragma warning(disable : 4251) 42 #endif 43 44 namespace CEGUI 45 { 46 47 /*! 48 \brief Enumerated type used when specifying horizontal alignments for Element 49 50 \see VerticalAlignment 51 */ 52 enum HorizontalAlignment 53 { 54 /** 55 * Element's position specifies an offset of it's left edge from the left 56 * edge of it's parent. 57 */ 58 HA_LEFT, 59 /** 60 * Element's position specifies an offset of it's horizontal centre from the 61 * horizontal centre of it's parent. 62 */ 63 HA_CENTRE, 64 /** 65 * Element's position specifies an offset of it's right edge from the right 66 * edge of it's parent. 67 */ 68 HA_RIGHT 69 }; 70 71 template<> 72 class PropertyHelper<HorizontalAlignment> 73 { 74 public: 75 typedef HorizontalAlignment return_type; 76 typedef return_type safe_method_return_type; 77 typedef HorizontalAlignment pass_type; 78 typedef String string_return_type; 79 getDataTypeName()80 static const String& getDataTypeName() 81 { 82 static String type("HorizontalAlignment"); 83 84 return type; 85 } 86 fromString(const String & str)87 static return_type fromString(const String& str) 88 { 89 if (str == "Centre") 90 { 91 return HA_CENTRE; 92 } 93 else if (str == "Right") 94 { 95 return HA_RIGHT; 96 } 97 else 98 { 99 return HA_LEFT; 100 } 101 } 102 toString(pass_type val)103 static string_return_type toString(pass_type val) 104 { 105 if (val == HA_CENTRE) 106 { 107 return "Centre"; 108 } 109 else if (val == HA_RIGHT) 110 { 111 return "Right"; 112 } 113 else if (val == HA_LEFT) 114 { 115 return "Left"; 116 } 117 else 118 { 119 assert(false && "Invalid horizontal alignment"); 120 return "Centre"; 121 } 122 } 123 }; 124 125 /*! 126 \brief Enumerated type used when specifying vertical alignments for Element 127 128 \see HorizontalAlignment 129 */ 130 enum VerticalAlignment 131 { 132 /** 133 * Element's position specifies an offset of it's top edge from the top edge 134 * of it's parent. 135 */ 136 VA_TOP, 137 /** 138 * Element's position specifies an offset of it's vertical centre from the 139 * vertical centre of it's parent. 140 */ 141 VA_CENTRE, 142 /** 143 * Element's position specifies an offset of it's bottom edge from the 144 * bottom edge of it's parent. 145 */ 146 VA_BOTTOM 147 }; 148 149 template<> 150 class PropertyHelper<CEGUI::VerticalAlignment> 151 { 152 public: 153 typedef VerticalAlignment return_type; 154 typedef return_type safe_method_return_type; 155 typedef VerticalAlignment pass_type; 156 typedef String string_return_type; 157 getDataTypeName()158 static const String& getDataTypeName() 159 { 160 static String type("VerticalAlignment"); 161 162 return type; 163 } 164 fromString(const String & str)165 static return_type fromString(const String& str) 166 { 167 if (str == "Centre") 168 { 169 return VA_CENTRE; 170 } 171 else if (str == "Bottom") 172 { 173 return VA_BOTTOM; 174 } 175 else 176 { 177 return VA_TOP; 178 } 179 } 180 toString(pass_type val)181 static string_return_type toString(pass_type val) 182 { 183 if (val == VA_CENTRE) 184 { 185 return "Centre"; 186 } 187 else if (val == VA_BOTTOM) 188 { 189 return "Bottom"; 190 } 191 else if (val == VA_TOP) 192 { 193 return "Top"; 194 } 195 else 196 { 197 assert(false && "Invalid vertical alignment"); 198 return "Centre"; 199 } 200 } 201 }; 202 203 /*! 204 \brief 205 EventArgs based class that is used for objects passed to handlers triggered 206 for events concerning some Element object. 207 208 \see CEGUI::Element 209 */ 210 class CEGUIEXPORT ElementEventArgs : public EventArgs 211 { 212 public: ElementEventArgs(Element * element)213 ElementEventArgs(Element* element): 214 element(element) 215 {} 216 217 //! pointer to an Element object of relevance to the event. 218 Element* element; 219 }; 220 221 /*! 222 \brief A positioned and sized rectangular node in a tree graph 223 224 This class implements positioning, alignment, sizing including minimum and 225 maximum size constraining. In its bare essense it's an unnamed rectangular node 226 that may contain other unnamed rectangular nodes. 227 228 Unless you are implementing new CEGUI functionality you do NOT want to use this 229 class directly. You most likely want to use CEGUI::Window. 230 231 \see CEGUI::Window 232 233 \internal 234 Currently only CEGUI::Window uses this but in the future Falagard might use 235 it for all widget parts, this would unify much of currently repeated code. 236 237 \internal 238 Methods retrieving Element (like getParentElement) have Element suffix so 239 that deriving classes can easily make their getParent and return the proper 240 casted type (Window* for example). 241 */ 242 class CEGUIEXPORT Element : 243 public PropertySet, 244 public EventSet, 245 public AllocatedObject<Element> 246 { 247 public: 248 //! Namespace for global events 249 static const String EventNamespace; 250 251 /** Event fired when the Element size has changed. 252 * Handlers are passed a const ElementEventArgs reference with 253 * ElementEventArgs::element set to the Element whose size was changed. 254 */ 255 static const String EventSized; 256 /** Event fired when the parent of this Element has been re-sized. 257 * Handlers are passed a const ElementEventArgs reference with 258 * ElementEventArgs::element pointing to the <em>parent element</em> that 259 * was resized, not the element whose parent was resized. 260 */ 261 static const String EventParentSized; 262 /** Event fired when the Element position has changed. 263 * Handlers are passed a const ElementEventArgs reference with 264 * ElementEventArgs::element set to the Element whose position was changed. 265 */ 266 static const String EventMoved; 267 /** Event fired when the horizontal alignment for the element is changed. 268 * Handlers are passed a const ElementEventArgs reference with 269 * ElementEventArgs::element set to the Element whose horizontal alignment 270 * setting was changed. 271 */ 272 static const String EventHorizontalAlignmentChanged; 273 /** Event fired when the vertical alignment for the element is changed. 274 * Handlers are passed a const ElementEventArgs reference with 275 * ElementEventArgs::element set to the Element whose vertical alignment 276 * setting was changed. 277 */ 278 static const String EventVerticalAlignmentChanged; 279 /** Event fired when the rotation factor(s) for the element are changed. 280 * Handlers are passed a const ElementEventArgs reference with 281 * ElementEventArgs::element set to the Element whose rotation was changed. 282 */ 283 static const String EventRotated; 284 /** Event fired when a child Element has been added. 285 * Handlers are passed a const ElementEventArgs reference with 286 * ElementEventArgs::element set to the child element that was added. 287 */ 288 static const String EventChildAdded; 289 /** Event fired when a child element has been removed. 290 * Handlers are passed a const ElementEventArgs reference with 291 * ElementEventArgs::element set to the child element that was removed. 292 */ 293 static const String EventChildRemoved; 294 /** Event fired when the z-order of the element has changed. 295 * Handlers are passed a const ElementEventArgs reference with 296 * ElementEventArgs::element set to the Element whose z order position has 297 * changed. 298 */ 299 static const String EventZOrderChanged; 300 /** Event fired when the non-client setting for the Element is changed. 301 * Handlers are passed a const ElementEventArgs reference with 302 * ElementEventArgs::element set to the Element whose non-client setting was 303 * changed. 304 */ 305 static const String EventNonClientChanged; 306 307 /*! 308 \brief A tiny wrapper to hide some of the dirty work of rect caching 309 310 This is used internally by CEGUI::Element and other classes, it is passed 311 to the user in several methods. In those circumstances you most likely 312 want the result of either the "get()" or "getFresh(..)" methods. 313 */ 314 class CachedRectf 315 { 316 public: 317 /*! 318 \brief Function to generate fresh data that might later be cached 319 320 If the bool is true all PixelAlignment settings will be overridden 321 and no pixel alignment will take place. 322 */ 323 typedef Rectf (Element::*DataGenerator)(bool) const; 324 CachedRectf(Element const * element,DataGenerator generator)325 CachedRectf(Element const* element, DataGenerator generator): 326 d_element(element), 327 d_generator(generator), 328 // we don't have to initialise d_cachedData here, it will get 329 // regenerated and reset anyways 330 d_cacheValid(false) 331 {} 332 333 /*! 334 \brief Retrieves cached Rectf or generated a fresh one and caches it 335 */ get()336 inline const Rectf& get() const 337 { 338 if (!d_cacheValid) 339 { 340 regenerateCache(); 341 } 342 343 return d_cachedData; 344 } 345 346 /*! 347 \brief Skips all caching and calls the generator 348 349 This method will cache the result if cache is invalid and 350 alignment is not being skipped. 351 */ 352 inline Rectf getFresh(bool skipAllPixelAlignment = false) const 353 { 354 // if the cache is not valid we will use this chance to regenerate it 355 // of course this is only applicable if we are allowed to use pixel alignment where applicable 356 if (!d_cacheValid && !skipAllPixelAlignment) 357 { 358 return get(); 359 } 360 361 return CEGUI_CALL_MEMBER_FN(*d_element, d_generator)(skipAllPixelAlignment); 362 } 363 364 /*! 365 \brief Invalidates the cached Rectf causing it to be regenerated 366 367 The regeneration will not happen immediately, it will happen when user 368 requests the data. 369 */ invalidateCache()370 inline void invalidateCache() const 371 { 372 d_cacheValid = false; 373 } 374 isCacheValid()375 inline bool isCacheValid() const 376 { 377 return d_cacheValid; 378 } 379 regenerateCache()380 inline void regenerateCache() const 381 { 382 // false, since when we are caching we don't want to skip anything, we want everything to act 383 // exactly as it was setup 384 d_cachedData = CEGUI_CALL_MEMBER_FN(*d_element, d_generator)(false); 385 386 d_cacheValid = true; 387 } 388 389 private: 390 Element const* d_element; 391 const DataGenerator d_generator; 392 393 mutable Rectf d_cachedData; 394 mutable bool d_cacheValid; 395 }; 396 397 /*! 398 \brief Constructor 399 */ 400 Element(); 401 402 /*! 403 \brief Destructor 404 */ 405 virtual ~Element(); 406 407 /*! 408 \brief Retrieves parent of this element 409 410 \returns 411 pointer to parent or 0, 0 means that this Element is a root of 412 the subtree it represents 413 */ getParentElement()414 inline Element* getParentElement() const 415 { 416 return d_parent; 417 } 418 419 /*! 420 \brief 421 Set the Element area. 422 423 Sets the area occupied by this Element. The defined area is offset from 424 one of the corners and edges of this Element's parent element (depending on alignments) 425 or from the top-left corner of the display if this element has no parent 426 (i.e. if it is the root element). 427 428 \param pos 429 UVector2 describing the new position of the element area. Meaning of 430 position depends on currently set alignments. By default it is the 431 offset from the top-left corner of widget's parent. 432 433 \param size 434 UVector2 describing the new size of the element area. 435 436 \see UDim 437 */ 438 virtual void setArea(const UVector2& pos, const USize& size); 439 440 //! \overload setArea(const UDim & xpos,const UDim & ypos,const UDim & width,const UDim & height)441 inline void setArea(const UDim& xpos, const UDim& ypos, 442 const UDim& width, const UDim& height) 443 { 444 setArea(UVector2(xpos, ypos), USize(width, height)); 445 } 446 447 //! \overload setArea(const URect & area)448 inline void setArea(const URect& area) 449 { 450 setArea(area.d_min, area.getSize()); 451 } 452 453 /*! 454 \brief 455 Return the element's area. 456 457 Sets the area occupied by this Element. The defined area is offset from 458 one of the corners and edges of this Element's parent element (depending on alignments) 459 or from the top-left corner of the display if this element has no parent 460 (i.e. it is the root element). 461 462 \return 463 URect describing the rectangle of the element area. 464 465 \see UDim 466 */ getArea()467 inline const URect& getArea() const 468 { 469 return d_area; 470 } 471 472 /*! 473 \brief 474 Set the element's position. 475 476 Sets the position of the area occupied by this element. The position is offset from 477 one of the corners and edges of this Element's parent element (depending on alignments) 478 or from the top-left corner of the display if this element has no parent 479 (i.e. it is the root element). 480 481 \param pos 482 UVector2 describing the new position of the element area. 483 484 \see UDim 485 \see Element::setArea(const UVector2& pos, const USize& size) 486 */ setPosition(const UVector2 & pos)487 inline void setPosition(const UVector2& pos) 488 { 489 setArea_impl(pos, d_area.getSize()); 490 } 491 492 //! \overload setXPosition(const UDim & pos)493 inline void setXPosition(const UDim& pos) 494 { 495 setPosition(UVector2(pos, getYPosition())); 496 } 497 498 //! \overload setYPosition(const UDim & pos)499 inline void setYPosition(const UDim& pos) 500 { 501 setPosition(UVector2(getXPosition(), pos)); 502 } 503 504 /*! 505 \brief 506 Get the element's position. 507 508 Sets the position of the area occupied by this element. The position is offset from 509 one of the corners of this Element's parent element (depending on alignments) 510 or from the top-left corner of the display if this element has no parent 511 (i.e. it is the root element). 512 513 \return 514 UVector2 describing the position of the element area. 515 516 \see UDim 517 */ getPosition()518 inline const UVector2& getPosition() const 519 { 520 return d_area.getPosition(); 521 } 522 523 //! \overload getXPosition()524 inline const UDim& getXPosition() const 525 { 526 return getPosition().d_x; 527 } 528 529 //! \overload getYPosition()530 inline const UDim& getYPosition() const 531 { 532 return getPosition().d_y; 533 } 534 535 /*! 536 \brief 537 Set the horizontal alignment. 538 539 Modifies the horizontal alignment for the element. This setting affects 540 how the element's position is interpreted relative to its parent. 541 542 \param alignment 543 One of the HorizontalAlignment enumerated values. 544 */ 545 virtual void setHorizontalAlignment(const HorizontalAlignment alignment); 546 547 /*! 548 \brief 549 Get the horizontal alignment. 550 551 Returns the horizontal alignment for the element. This setting affects 552 how the element's position is interpreted relative to its parent. 553 554 \return 555 One of the HorizontalAlignment enumerated values. 556 */ getHorizontalAlignment()557 inline HorizontalAlignment getHorizontalAlignment() const 558 { 559 return d_horizontalAlignment; 560 } 561 562 /*! 563 \brief 564 Set the vertical alignment. 565 566 Modifies the vertical alignment for the element. This setting affects 567 how the element's position is interpreted relative to its parent. 568 569 \param alignment 570 One of the VerticalAlignment enumerated values. 571 */ 572 virtual void setVerticalAlignment(const VerticalAlignment alignment); 573 574 /*! 575 \brief 576 Get the vertical alignment. 577 578 Returns the vertical alignment for the element. This setting affects how 579 the element's position is interpreted relative to its parent. 580 581 \return 582 One of the VerticalAlignment enumerated values. 583 */ getVerticalAlignment()584 inline VerticalAlignment getVerticalAlignment() const 585 { 586 return d_verticalAlignment; 587 } 588 589 /*! 590 \brief 591 Set the element's size. 592 593 Sets the size of the area occupied by this element. 594 595 \param size 596 USize describing the new size of the element's area. 597 598 \see UDim 599 */ setSize(const USize & size)600 inline void setSize(const USize& size) 601 { 602 setArea(d_area.getPosition(), size); 603 } 604 605 //! \overload setWidth(const UDim & width)606 inline void setWidth(const UDim& width) 607 { 608 setSize(USize(width, getSize().d_height)); 609 } 610 611 //! \overload setHeight(const UDim & height)612 inline void setHeight(const UDim& height) 613 { 614 setSize(USize(getSize().d_width, height)); 615 } 616 617 /*! 618 \brief 619 Get the element's size. 620 621 Gets the size of the area occupied by this element. 622 623 \return 624 USize describing the size of the element's area. 625 626 \see UDim 627 */ getSize()628 inline USize getSize() const 629 { 630 return d_area.getSize(); 631 } 632 633 //! \overload getWidth()634 inline UDim getWidth() const 635 { 636 return getSize().d_width; 637 } 638 639 //! \overload getHeight()640 inline UDim getHeight() const 641 { 642 return getSize().d_height; 643 } 644 645 /*! 646 \brief 647 Set the element's minimum size. 648 649 Sets the minimum size that this element's area may occupy (whether size 650 changes occur by user interaction, general system operation, or by 651 direct setting by client code). 652 653 \note 654 The scale component of UDim takes display size as the base. 655 It is not dependent on parent element's size! 656 657 \param size 658 USize describing the new minimum size of the element's area. 659 660 \see Element::setSize 661 */ 662 void setMinSize(const USize& size); 663 664 /*! 665 \brief 666 Get the element's minimum size. 667 668 Gets the minimum size that this element's area may occupy (whether size 669 changes occur by user interaction, general system operation, or by 670 direct setting by client code). 671 672 \return 673 UVector2 describing the minimum size of the element's area. 674 675 \see Element::setMinSize 676 */ getMinSize()677 inline const USize& getMinSize() const 678 { 679 return d_minSize; 680 } 681 682 /*! 683 \brief 684 Set the element's maximum size. 685 686 Sets the maximum size that this element area may occupy (whether size 687 changes occur by user interaction, general system operation, or by 688 direct setting by client code). 689 690 \note 691 The scale component of UDim takes display size as the base. 692 It is not dependent on parent element's size! 693 694 \param size 695 USize describing the new maximum size of the element's area. Note that 696 zero is used to indicate that the Element's maximum area size will be 697 unbounded. 698 699 \see Element::setSize 700 */ 701 void setMaxSize(const USize& size); 702 703 /*! 704 \brief 705 Get the element's maximum size. 706 707 Gets the maximum size that this element area may occupy (whether size 708 changes occur by user interaction, general system operation, or by 709 direct setting by client code). 710 711 \return 712 UVector2 describing the maximum size of the element's area. 713 714 \see Element::setMaxSize 715 */ getMaxSize()716 inline const USize& getMaxSize() const 717 { 718 return d_maxSize; 719 } 720 721 /*! 722 \brief Sets current aspect mode and recalculates the area rect 723 724 \param mode the new aspect mode to set 725 726 \see CEGUI::AspectMode 727 \see CEGUI::setAspectRatio 728 */ 729 void setAspectMode(const AspectMode mode); 730 731 /*! 732 \brief 733 Retrieves currently used aspect mode 734 735 \see Element::setAspectMode 736 */ getAspectMode()737 inline AspectMode getAspectMode() const 738 { 739 return d_aspectMode; 740 } 741 742 /*! 743 \brief 744 Sets target aspect ratio 745 746 \param ratio 747 The desired ratio as width / height. For example 4.0f / 3.0f, 748 16.0f / 9.0.f, ... 749 750 \note 751 This is ignored if AspectMode is AM_IGNORE. 752 753 \see Element::setAspectMode 754 */ 755 void setAspectRatio(const float ratio); 756 757 /*! 758 \brief 759 Retrieves target aspect ratio 760 761 \see Element::setAspectRatio 762 */ getAspectRatio()763 inline float getAspectRatio() const 764 { 765 return d_aspectRatio; 766 } 767 768 /*! 769 \brief 770 Sets whether this Element is pixel aligned (both position and size, basically the 4 "corners"). 771 772 \par Impact on the element tree 773 Lets say we have Element A with child Element B, A is pixel aligned 774 and it's position is 99.5, 99.5 px in screenspace. This gives us 775 100, 100 px pixel aligned position. 776 777 B's position is always relative to the pixel-aligned position of its 778 parent. Say B isn't pixel-aligned and it's position is 0.5, 0.5 px. 779 Its final position will be 100.5, 100.5 px in screenspace, not 100, 100 px! 780 781 If it were pixel-aligned the final position would be 101, 101 px. 782 783 \par Why you should pixel-align widgets 784 Pixel aligning is enabled by default and for most widgets it makes 785 a lot of sense and just looks better. Especially with text. However for 786 HUD or decorative elements pixel aligning might make transitions less 787 fluid. Feel free to experiment with the setting. 788 */ 789 void setPixelAligned(const bool setting); 790 791 /*! 792 \brief 793 Checks whether this Element is pixel aligned 794 795 \see 796 Element::setPixelAligned 797 */ isPixelAligned()798 inline bool isPixelAligned() const 799 { 800 return d_pixelAligned; 801 } 802 803 /*! 804 \brief 805 Return the element's absolute (or screen, depending on the type of the element) position in pixels. 806 807 \return 808 Vector2f object describing this element's absolute position in pixels. 809 */ getPixelPosition()810 inline const Vector2f& getPixelPosition() const 811 { 812 return getUnclippedOuterRect().get().d_min; 813 } 814 815 /*! 816 \brief 817 Return the element's size in pixels. 818 819 \return 820 Size object describing this element's size in pixels. 821 */ getPixelSize()822 inline const Sizef& getPixelSize() const 823 { 824 return d_pixelSize; 825 } 826 827 /*! 828 \brief Calculates this element's pixel size 829 830 \param skipAllPixelAlignment 831 Should all pixel-alignment be skipped when calculating the pixel size? 832 833 If you want to get the pixel size you most probably want to use the 834 Element::getPixelSize method. This method skips caching and might 835 impact performance! 836 */ 837 Sizef calculatePixelSize(bool skipAllPixelAlignment = false) const; 838 839 /*! 840 \brief Return the pixel size of the parent element. 841 842 If this element doesn't have any parent, the display size will be returned. 843 This method returns a valid Sizef object in all cases. 844 845 \return 846 Size object that describes the pixel dimensions of this Element's parent 847 */ 848 Sizef getParentPixelSize(bool skipAllPixelAlignment = false) const; 849 850 /*! 851 \brief sets rotation of this widget 852 853 \param rotation 854 A Quaternion describing the rotation 855 856 \par Euler angles 857 CEGUI used Euler angles previously. While these are easy to use and seem 858 intuitive they cause Gimbal locks when animating and are overall the worse 859 solution than using Quaternions. You can still use Euler angles, see 860 the CEGUI::Quaternion class for more info about that. 861 */ 862 void setRotation(const Quaternion& rotation); 863 864 /*! 865 \brief retrieves rotation of this widget 866 867 \see Element::setRotation 868 */ getRotation()869 inline const Quaternion& getRotation() const 870 { 871 return d_rotation; 872 } 873 874 /*! 875 \brief 876 Add the specified Element as a child of this Element. 877 878 If the Element \a element is already attached to a different Element, 879 it is detached before being added to this Element. 880 881 \param element 882 Pointer to the Element object to be added. 883 884 \exception InvalidRequestException 885 thrown if Element \a element is NULL. 886 887 \exception InvalidRequestException 888 thrown if Element \a element is "this" element 889 890 \exception InvalidRequestException 891 thrown if Element \a element is an ancestor of this Element, to prevent 892 cyclic Element structures. 893 */ 894 void addChild(Element* element); 895 896 /*! 897 \brief 898 Remove the Element Element's child list. 899 900 \exception InvalidRequestException 901 thrown if Element \a element is NULL. 902 903 \see 904 Element::addChild 905 */ 906 void removeChild(Element* element); 907 908 /*! 909 \brief 910 return a pointer to the child element that is attached to 'this' at the 911 given index. 912 913 \param idx 914 Index of the child element who's pointer should be returned. This value 915 is not bounds checked, client code should ensure that this is less than 916 the value returned by getChildCount(). 917 918 \return 919 Pointer to the child element currently attached at index position \a idx 920 */ getChildElementAtIdx(size_t idx)921 inline Element* getChildElementAtIdx(size_t idx) const 922 { 923 return d_children[idx]; 924 } 925 926 /*! 927 \brief Returns number of child elements attached to this Element 928 */ getChildCount()929 inline size_t getChildCount() const 930 { 931 return d_children.size(); 932 } 933 934 /*! 935 \brief Checks whether given element is attached to this Element 936 */ 937 bool isChild(const Element* element) const; 938 939 /*! 940 \brief Checks whether the specified Element is an ancestor of this Element 941 942 \param element 943 Pointer to the Element object to look for. 944 945 This element itself is not its own ancestor! 946 947 \return 948 - true if \a element was found to be an ancestor (parent, or parent of 949 parent, etc) of this Element. 950 - false if \a element is not an ancestor of this element. 951 */ 952 bool isAncestor(const Element* element) const; 953 954 /*! 955 \brief Set whether the Element is non-client. 956 957 A non-client element is clipped, positioned and sized according to the 958 parent element's full area as opposed to just the inner rect area used 959 for normal client element. 960 961 \param setting 962 - true if the element should be clipped, positioned and sized according 963 to the full area rectangle of it's parent. 964 - false if the element should be clipped, positioned and sized according 965 to the inner rect area of it's parent. 966 */ 967 void setNonClient(const bool setting); 968 969 /*! 970 \brief Checks whether this element was set to be non client 971 972 \see Element::setNonClient 973 */ isNonClient()974 inline bool isNonClient() const 975 { 976 return d_nonClient; 977 } 978 979 /*! 980 \brief Return a Rect that describes the unclipped outer rect area of the Element 981 982 The unclipped outer rectangle is the entire area of the element, including 983 frames and other outside decorations. 984 985 \note 986 Unclipped in this context means not limited by any ancestor Element's area. 987 988 \note 989 If you take position of the result rectangle it is the same as pixel 990 position of the Element in screenspace. 991 */ getUnclippedOuterRect()992 inline const CachedRectf& getUnclippedOuterRect() const 993 { 994 return d_unclippedOuterRect; 995 } 996 997 /*! 998 \brief Return a Rect that describes the unclipped inner rect area of the Element 999 1000 The inner rectangle is typically an area that excludes some frame or other decorations 1001 that should not be touched by rendering of client clipped child elements. 1002 1003 \note 1004 Unclipped in this context means not limited by any ancestor Element's area. 1005 1006 \return 1007 Rect object that describes, in unclipped screen pixel co-ordinates, the 1008 element object's inner rect area. 1009 */ getUnclippedInnerRect()1010 inline const CachedRectf& getUnclippedInnerRect() const 1011 { 1012 return d_unclippedInnerRect; 1013 } 1014 1015 /*! 1016 \brief Return a Rect that describes the unclipped area covered by the Element. 1017 1018 This function can return either the inner or outer area dependant upon 1019 the boolean values passed in. 1020 1021 \param inner 1022 - true if the inner rect area should be returned. 1023 - false if the outer rect area should be returned. 1024 1025 \see Element::getUnclippedOuterRect 1026 \see Element::getUnclippedInnerRect 1027 */ getUnclippedRect(const bool inner)1028 inline const CachedRectf& getUnclippedRect(const bool inner) const 1029 { 1030 return inner ? getUnclippedInnerRect() : getUnclippedOuterRect(); 1031 } 1032 1033 /*! 1034 \brief Return a Rect that is used by client child elements as content area 1035 1036 Client content area is used for relative sizing, positioning and clipping 1037 of child elements that are client (their NonClient property is "false"). 1038 1039 \see Element::getChildContentArea 1040 */ 1041 virtual const CachedRectf& getClientChildContentArea() const; 1042 1043 /*! 1044 \brief Return a Rect that is used by client child elements as content area 1045 1046 Client content area is used for relative sizing, positioning and clipping 1047 of child elements that are non-client (their NonClient property is "true"). 1048 1049 \see Element::getChildContentArea 1050 */ 1051 virtual const CachedRectf& getNonClientChildContentArea() const; 1052 1053 /*! 1054 \brief Return a Rect that is used to position and size child elements 1055 1056 It is used as the reference area for positioning and its size is used for 1057 the scale components of position and size. 1058 1059 \note 1060 By and large the area returned here will be the same as the unclipped 1061 inner rect (for client content) or the unclipped outer rect (for non 1062 client content), although certain advanced uses will require 1063 alternative Rects to be returned. 1064 1065 \note 1066 The behaviour of this function is modified by overriding the 1067 protected Element::getClientChildContentArea and/or 1068 Element::getNonClientChildContentArea functions. 1069 1070 \param non_client 1071 - true to return the non-client child content area. 1072 - false to return the client child content area (default). 1073 */ 1074 inline const CachedRectf& getChildContentArea(const bool non_client = false) const 1075 { 1076 return non_client ? getNonClientChildContentArea() : getClientChildContentArea(); 1077 } 1078 1079 /*! 1080 \brief Inform the element and (optionally) all children that screen area has changed 1081 1082 \note 1083 This will cause recomputation and recaching of various rectangles used. 1084 Such an action, especially if applied recursively, will impact performance 1085 before everything is cached again. 1086 1087 \param recursive 1088 - true to recursively call notifyScreenAreaChanged on attached child 1089 Element objects. 1090 - false to just process \e this Element. 1091 */ 1092 virtual void notifyScreenAreaChanged(bool recursive = true); 1093 1094 /*! 1095 \brief Return the size of the root container (such as screen size). 1096 1097 This is size of the hypothetical parent of the root element that has no 1098 parent element. Display size is usually used. 1099 1100 The value is significant and is used to size and position the root if 1101 it is using scale UDim component in position and/or size. 1102 */ 1103 virtual const Sizef& getRootContainerSize() const; 1104 1105 protected: 1106 /*! 1107 \brief 1108 Add standard CEGUI::Element properties. 1109 */ 1110 void addElementProperties(); 1111 1112 /*! 1113 \brief 1114 Implementation method to modify element area while correctly applying 1115 min / max size processing, and firing any appropriate events. 1116 1117 \note 1118 This is the implementation function for setting size and position. 1119 In order to simplify area management, from this point on, all 1120 modifications to element size and position (area rect) should come 1121 through here. 1122 1123 \param pos 1124 UVector2 object describing the new area position. 1125 1126 \param size 1127 USize object describing the new area size. 1128 1129 \param topLeftSizing 1130 - true to indicate the the operation is a sizing operation on the top 1131 and/or left edges of the area, and so element movement should be 1132 inhibited if size is at max or min. 1133 - false to indicate the operation is not a strict sizing operation on 1134 the top and/or left edges and that the element position may change as 1135 required 1136 1137 \param fireEvents 1138 - true if events should be fired as normal. 1139 - false to inhibit firing of events (required, for example, if you need 1140 to call this from the onSize/onMove handlers). 1141 */ 1142 virtual void setArea_impl(const UVector2& pos, const USize& size, 1143 bool topLeftSizing = false, bool fireEvents = true); 1144 1145 //! helper to return whether the inner rect size has changed isInnerRectSizeChanged()1146 inline bool isInnerRectSizeChanged() const 1147 { 1148 const Sizef old_sz(d_unclippedInnerRect.get().getSize()); 1149 d_unclippedInnerRect.invalidateCache(); 1150 return old_sz != d_unclippedInnerRect.get().getSize(); 1151 } 1152 1153 /*! 1154 \brief 1155 Set the parent element for this element object. 1156 1157 \param parent 1158 Pointer to a Element object that is to be assigned as the parent to this 1159 Element. 1160 1161 \return 1162 Nothing 1163 */ 1164 virtual void setParent(Element* parent); 1165 1166 /*! 1167 \brief 1168 Add given element to child list at an appropriate position 1169 */ 1170 virtual void addChild_impl(Element* element); 1171 1172 /*! 1173 \brief 1174 Remove given element from child list 1175 */ 1176 virtual void removeChild_impl(Element* element); 1177 1178 //! Default implementation of function to return Element's outer rect area. 1179 virtual Rectf getUnclippedOuterRect_impl(bool skipAllPixelAlignment) const; 1180 //! Default implementation of function to return Element's inner rect area. 1181 virtual Rectf getUnclippedInnerRect_impl(bool skipAllPixelAlignment) const; 1182 1183 //! helper to fire events based on changes to area rect 1184 void fireAreaChangeEvents(const bool moved, const bool sized); 1185 void notifyChildrenOfSizeChange(const bool non_client, 1186 const bool client); 1187 1188 /************************************************************************* 1189 Event trigger methods 1190 *************************************************************************/ 1191 /*! 1192 \brief 1193 Handler called when the element's size changes. 1194 1195 \param e 1196 ElementEventArgs object whose 'element' pointer field is set to the element 1197 that triggered the event. 1198 */ 1199 virtual void onSized(ElementEventArgs& e); 1200 1201 /*! 1202 \brief 1203 Handler called when this element's parent element has been resized. If 1204 this element is the root / GUI Sheet element, this call will be made when 1205 the display size changes. 1206 1207 \param e 1208 ElementEventArgs object whose 'element' pointer field is set the the 1209 element that caused the event; this is typically either this element's 1210 parent element, or NULL to indicate the screen size has changed. 1211 */ 1212 virtual void onParentSized(ElementEventArgs& e); 1213 1214 /*! 1215 \brief 1216 Handler called when the element's position changes. 1217 1218 \param e 1219 ElementEventArgs object whose 'element' pointer field is set to the element 1220 that triggered the event. 1221 */ 1222 virtual void onMoved(ElementEventArgs& e); 1223 1224 /*! 1225 \brief 1226 Handler called when the horizontal alignment setting for the element is 1227 changed. 1228 1229 \param e 1230 ElementEventArgs object initialised as follows: 1231 - element field is set to point to the element object who's alignment has 1232 changed (typically 'this'). 1233 */ 1234 virtual void onHorizontalAlignmentChanged(ElementEventArgs& e); 1235 1236 /*! 1237 \brief 1238 Handler called when the vertical alignment setting for the element is 1239 changed. 1240 1241 \param e 1242 ElementEventArgs object initialised as follows: 1243 - element field is set to point to the element object who's alignment has 1244 changed (typically 'this'). 1245 */ 1246 virtual void onVerticalAlignmentChanged(ElementEventArgs& e); 1247 1248 /*! 1249 \brief 1250 Handler called when the element's rotation is changed. 1251 1252 \param e 1253 ElementEventArgs object whose 'element' pointer field is set to the element 1254 that triggered the event. 1255 */ 1256 virtual void onRotated(ElementEventArgs& e); 1257 1258 /*! 1259 \brief 1260 Handler called when a child element is added to this element. 1261 1262 \param e 1263 ElementEventArgs object whose 'element' pointer field is set to the element 1264 that has been added. 1265 */ 1266 virtual void onChildAdded(ElementEventArgs& e); 1267 1268 /*! 1269 \brief 1270 Handler called when a child element is removed from this element. 1271 1272 \param e 1273 ElementEventArgs object whose 'element' pointer field is set the element 1274 that has been removed. 1275 */ 1276 virtual void onChildRemoved(ElementEventArgs& e); 1277 1278 /*! 1279 \brief 1280 Handler called when the element's non-client setting, affecting it's 1281 position and size relative to it's parent is changed. 1282 1283 \param e 1284 ElementEventArgs object whose 'element' pointer field is set to the element 1285 that triggered the event. For this event the trigger element is always 1286 'this'. 1287 */ 1288 virtual void onNonClientChanged(ElementEventArgs& e); 1289 1290 /************************************************************************* 1291 Implementation Data 1292 *************************************************************************/ 1293 //! definition of type used for the list of attached child elements. 1294 typedef std::vector<Element* 1295 CEGUI_VECTOR_ALLOC(Element*)> ChildList; 1296 1297 //! The list of child element objects attached to this. 1298 ChildList d_children; 1299 //! Holds pointer to the parent element. 1300 Element* d_parent; 1301 1302 //! true if element is in non-client (outside InnerRect) area of parent. 1303 bool d_nonClient; 1304 1305 //! This element objects area as defined by a URect. 1306 URect d_area; 1307 //! Specifies the base for horizontal alignment. 1308 HorizontalAlignment d_horizontalAlignment; 1309 //! Specifies the base for vertical alignment. 1310 VerticalAlignment d_verticalAlignment; 1311 //! current minimum size for the element. 1312 USize d_minSize; 1313 //! current maximum size for the element. 1314 USize d_maxSize; 1315 //! How to satisfy current aspect ratio 1316 AspectMode d_aspectMode; 1317 //! The target aspect ratio 1318 float d_aspectRatio; 1319 //! If true, the position and size are pixel aligned 1320 bool d_pixelAligned; 1321 //! Current constrained pixel size of the element. 1322 Sizef d_pixelSize; 1323 //! Rotation of this element (relative to the parent) 1324 Quaternion d_rotation; 1325 1326 //! outer area rect in screen pixels 1327 CachedRectf d_unclippedOuterRect; 1328 //! inner area rect in screen pixels 1329 CachedRectf d_unclippedInnerRect; 1330 1331 private: 1332 /************************************************************************* 1333 May not copy or assign Element objects 1334 *************************************************************************/ 1335 Element(const Element&); 1336 1337 Element& operator=(const Element&) {return *this;} 1338 }; 1339 1340 } // End of CEGUI namespace section 1341 1342 1343 #if defined(_MSC_VER) 1344 # pragma warning(pop) 1345 #endif 1346 1347 #endif // end of guard _CEGUIElement_h_ 1348