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