Crazy Eddie's GUI System  0.8.4
Element.h
00001 /***********************************************************************
00002     created:    18/8/2011
00003     author:     Martin Preisler
00004 
00005     purpose:    Defines a class representing an item in a graph
00006                 (deals with relative positions, relative dimensions, ...)
00007 *************************************************************************/
00008 /***************************************************************************
00009  *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
00010  *
00011  *   Permission is hereby granted, free of charge, to any person obtaining
00012  *   a copy of this software and associated documentation files (the
00013  *   "Software"), to deal in the Software without restriction, including
00014  *   without limitation the rights to use, copy, modify, merge, publish,
00015  *   distribute, sublicense, and/or sell copies of the Software, and to
00016  *   permit persons to whom the Software is furnished to do so, subject to
00017  *   the following conditions:
00018  *
00019  *   The above copyright notice and this permission notice shall be
00020  *   included in all copies or substantial portions of the Software.
00021  *
00022  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00023  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00024  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00025  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00026  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00027  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00028  *   OTHER DEALINGS IN THE SOFTWARE.
00029  ***************************************************************************/
00030 
00031 #ifndef _CEGUIElement_h_
00032 #define _CEGUIElement_h_
00033 
00034 #include "CEGUI/Base.h"
00035 #include "CEGUI/PropertySet.h"
00036 #include "CEGUI/EventSet.h"
00037 #include "CEGUI/EventArgs.h"
00038 
00039 #if defined(_MSC_VER)
00040 #   pragma warning(push)
00041 #   pragma warning(disable : 4251)
00042 #endif
00043 
00044 namespace CEGUI
00045 {
00046 
00052 enum HorizontalAlignment
00053 {
00058     HA_LEFT,
00063     HA_CENTRE,
00068     HA_RIGHT
00069 };
00070 
00071 template<>
00072 class PropertyHelper<HorizontalAlignment>
00073 {
00074 public:
00075     typedef HorizontalAlignment return_type;
00076     typedef return_type safe_method_return_type;
00077     typedef HorizontalAlignment pass_type;
00078     typedef String string_return_type;
00079 
00080     static const String& getDataTypeName()
00081     {
00082         static String type("HorizontalAlignment");
00083 
00084         return type;
00085     }
00086 
00087     static return_type fromString(const String& str)
00088     {
00089         if (str == "Centre")
00090         {
00091             return HA_CENTRE;
00092         }
00093         else if (str == "Right")
00094         {
00095             return HA_RIGHT;
00096         }
00097         else
00098         {
00099             return HA_LEFT;
00100         }
00101     }
00102 
00103     static string_return_type toString(pass_type val)
00104     {
00105         if (val == HA_CENTRE)
00106         {
00107             return "Centre";
00108         }
00109         else if (val == HA_RIGHT)
00110         {
00111             return "Right";
00112         }
00113         else if (val == HA_LEFT)
00114         {
00115             return "Left";
00116         }
00117         else
00118         {
00119             assert(false && "Invalid horizontal alignment");
00120             return "Centre";
00121         }
00122     }
00123 };
00124 
00130 enum VerticalAlignment
00131 {
00136     VA_TOP,
00141     VA_CENTRE,
00146     VA_BOTTOM
00147 };
00148 
00149 template<>
00150 class PropertyHelper<CEGUI::VerticalAlignment>
00151 {
00152 public:
00153     typedef VerticalAlignment return_type;
00154     typedef return_type safe_method_return_type;
00155     typedef VerticalAlignment pass_type;
00156     typedef String string_return_type;
00157 
00158     static const String& getDataTypeName()
00159     {
00160         static String type("VerticalAlignment");
00161 
00162         return type;
00163     }
00164 
00165     static return_type fromString(const String& str)
00166     {
00167       if (str == "Centre")
00168       {
00169           return VA_CENTRE;
00170       }
00171       else if (str == "Bottom")
00172       {
00173           return VA_BOTTOM;
00174       }
00175       else
00176       {
00177           return VA_TOP;
00178       }
00179     }
00180 
00181     static string_return_type toString(pass_type val)
00182     {
00183         if (val == VA_CENTRE)
00184         {
00185             return "Centre";
00186         }
00187         else if (val == VA_BOTTOM)
00188         {
00189             return "Bottom";
00190         }
00191         else if (val == VA_TOP)
00192         {
00193             return "Top";
00194         }
00195         else
00196         {
00197             assert(false && "Invalid vertical alignment");
00198             return "Centre";
00199         }
00200     }
00201 };
00202 
00210 class CEGUIEXPORT ElementEventArgs : public EventArgs
00211 {
00212 public:
00213     ElementEventArgs(Element* element):
00214         element(element)
00215     {}
00216 
00218     Element* element;
00219 };
00220 
00242 class CEGUIEXPORT Element :
00243     public PropertySet,
00244     public EventSet,
00245     public AllocatedObject<Element>
00246 {
00247 public:
00249     static const String EventNamespace;
00250 
00255     static const String EventSized;
00261     static const String EventParentSized;
00266     static const String EventMoved;
00272     static const String EventHorizontalAlignmentChanged;
00278     static const String EventVerticalAlignmentChanged;
00283     static const String EventRotated;
00288     static const String EventChildAdded;
00293     static const String EventChildRemoved;
00299     static const String EventZOrderChanged;
00305     static const String EventNonClientChanged;
00306 
00314     class CachedRectf
00315     {
00316     public:
00323         typedef Rectf (Element::*DataGenerator)(bool) const;
00324 
00325         CachedRectf(Element const* element, DataGenerator generator):
00326             d_element(element),
00327             d_generator(generator),
00328             // we don't have to initialise d_cachedData here, it will get
00329             // regenerated and reset anyways
00330             d_cacheValid(false)
00331         {}
00332 
00336         inline const Rectf& get() const
00337         {
00338             if (!d_cacheValid)
00339             {
00340                 regenerateCache();
00341             }
00342 
00343             return d_cachedData;
00344         }
00345 
00352         inline Rectf getFresh(bool skipAllPixelAlignment = false) const
00353         {
00354             // if the cache is not valid we will use this chance to regenerate it
00355             // of course this is only applicable if we are allowed to use pixel alignment where applicable
00356             if (!d_cacheValid && !skipAllPixelAlignment)
00357             {
00358                 return get();
00359             }
00360 
00361             return CEGUI_CALL_MEMBER_FN(*d_element, d_generator)(skipAllPixelAlignment);
00362         }
00363 
00370         inline void invalidateCache() const
00371         {
00372             d_cacheValid = false;
00373         }
00374 
00375         inline bool isCacheValid() const
00376         {
00377             return d_cacheValid;
00378         }
00379 
00380         inline void regenerateCache() const
00381         {
00382             // false, since when we are caching we don't want to skip anything, we want everything to act
00383             // exactly as it was setup
00384             d_cachedData = CEGUI_CALL_MEMBER_FN(*d_element, d_generator)(false);
00385 
00386             d_cacheValid = true;
00387         }
00388 
00389     private:
00390         Element const* d_element;
00391         const DataGenerator d_generator;
00392 
00393         mutable Rectf d_cachedData;
00394         mutable bool  d_cacheValid;
00395     };
00396 
00400     Element();
00401 
00405     virtual ~Element();
00406 
00414     inline Element* getParentElement() const
00415     {
00416         return d_parent;
00417     }
00418 
00438     virtual void setArea(const UVector2& pos, const USize& size);
00439 
00441     inline void setArea(const UDim& xpos, const UDim& ypos,
00442                         const UDim& width, const UDim& height)
00443     {
00444         setArea(UVector2(xpos, ypos), USize(width, height));
00445     }
00446 
00448     inline void setArea(const URect& area)
00449     {
00450         setArea(area.d_min, area.getSize());
00451     }
00452 
00467     inline const URect& getArea() const
00468     {
00469         return d_area;
00470     }
00471 
00487     inline void setPosition(const UVector2& pos)
00488     {
00489         setArea_impl(pos, d_area.getSize());
00490     }
00491 
00493     inline void setXPosition(const UDim& pos)
00494     {
00495         setPosition(UVector2(pos, getYPosition()));
00496     }
00497 
00499     inline void setYPosition(const UDim& pos)
00500     {
00501         setPosition(UVector2(getXPosition(), pos));
00502     }
00503 
00518     inline const UVector2& getPosition() const
00519     {
00520         return d_area.getPosition();
00521     }
00522 
00524     inline const UDim& getXPosition() const
00525     {
00526         return getPosition().d_x;
00527     }
00528 
00530     inline const UDim& getYPosition() const
00531     {
00532         return getPosition().d_y;
00533     }
00534 
00545     virtual void setHorizontalAlignment(const HorizontalAlignment alignment);
00546 
00557     inline HorizontalAlignment getHorizontalAlignment() const
00558     {
00559         return d_horizontalAlignment;
00560     }
00561 
00572     virtual void setVerticalAlignment(const VerticalAlignment alignment);
00573 
00584     inline VerticalAlignment getVerticalAlignment() const
00585     {
00586         return d_verticalAlignment;
00587     }
00588 
00600     inline void setSize(const USize& size)
00601     {
00602         setArea(d_area.getPosition(), size);
00603     }
00604 
00606     inline void setWidth(const UDim& width)
00607     {
00608         setSize(USize(width, getSize().d_height));
00609     }
00610 
00612     inline void setHeight(const UDim& height)
00613     {
00614         setSize(USize(getSize().d_width, height));
00615     }
00616 
00628     inline USize getSize() const
00629     {
00630         return d_area.getSize();
00631     }
00632 
00634     inline UDim getWidth() const
00635     {
00636         return getSize().d_width;
00637     }
00638 
00640     inline UDim getHeight() const
00641     {
00642         return getSize().d_height;
00643     }
00644 
00662     void setMinSize(const USize& size);
00663 
00677     inline const USize& getMinSize() const
00678     {
00679         return d_minSize;
00680     }
00681 
00701     void setMaxSize(const USize& size);
00702 
00716     inline const USize& getMaxSize() const
00717     {
00718         return d_maxSize;
00719     }
00720 
00729     void setAspectMode(const AspectMode mode);
00730 
00737     inline AspectMode getAspectMode() const
00738     {
00739         return d_aspectMode;
00740     }
00741 
00755     void setAspectRatio(const float ratio);
00756 
00763     inline float getAspectRatio() const
00764     {
00765         return d_aspectRatio;
00766     }
00767 
00789     void setPixelAligned(const bool setting);
00790 
00798     inline bool isPixelAligned() const
00799     {
00800         return d_pixelAligned;
00801     }
00802 
00810     inline const Vector2f& getPixelPosition() const
00811     {
00812         return getUnclippedOuterRect().get().d_min;
00813     }
00814 
00822     inline const Sizef& getPixelSize() const
00823     {
00824         return d_pixelSize;
00825     }
00826 
00837     Sizef calculatePixelSize(bool skipAllPixelAlignment = false) const;
00838 
00848     Sizef getParentPixelSize(bool skipAllPixelAlignment = false) const;
00849 
00862     void setRotation(const Quaternion& rotation);
00863 
00869     inline const Quaternion& getRotation() const
00870     {
00871         return d_rotation;
00872     }
00873 
00894     void addChild(Element* element);
00895 
00906     void removeChild(Element* element);
00907 
00921     inline Element* getChildElementAtIdx(size_t idx) const
00922     {
00923         return d_children[idx];
00924     }
00925 
00929     inline size_t getChildCount() const
00930     {
00931         return d_children.size();
00932     }
00933 
00937     bool isChild(const Element* element) const;
00938 
00952     bool isAncestor(const Element* element) const;
00953 
00967     void setNonClient(const bool setting);
00968 
00974     inline bool isNonClient() const
00975     {
00976         return d_nonClient;
00977     }
00978 
00992     inline const CachedRectf& getUnclippedOuterRect() const
00993     {
00994         return d_unclippedOuterRect;
00995     }
00996 
01010     inline const CachedRectf& getUnclippedInnerRect() const
01011     {
01012         return d_unclippedInnerRect;
01013     }
01014 
01028     inline const CachedRectf& getUnclippedRect(const bool inner) const
01029     {
01030         return inner ? getUnclippedInnerRect() : getUnclippedOuterRect();
01031     }
01032 
01041     virtual const CachedRectf& getClientChildContentArea() const;
01042 
01051     virtual const CachedRectf& getNonClientChildContentArea() const;
01052 
01074     inline const CachedRectf& getChildContentArea(const bool non_client = false) const
01075     {
01076         return non_client ? getNonClientChildContentArea() : getClientChildContentArea();
01077     }
01078 
01092     virtual void notifyScreenAreaChanged(bool recursive = true);
01093 
01103     virtual const Sizef& getRootContainerSize() const;
01104 
01105 protected:
01110     void addElementProperties();
01111 
01142     virtual void setArea_impl(const UVector2& pos, const USize& size,
01143                               bool topLeftSizing = false, bool fireEvents = true);
01144 
01146     inline bool isInnerRectSizeChanged() const
01147     {
01148         const Sizef old_sz(d_unclippedInnerRect.get().getSize());
01149         d_unclippedInnerRect.invalidateCache();
01150         return old_sz != d_unclippedInnerRect.get().getSize();
01151     }
01152 
01164     virtual void setParent(Element* parent);
01165 
01170     virtual void addChild_impl(Element* element);
01171 
01176     virtual void removeChild_impl(Element* element);
01177 
01179     virtual Rectf getUnclippedOuterRect_impl(bool skipAllPixelAlignment) const;
01181     virtual Rectf getUnclippedInnerRect_impl(bool skipAllPixelAlignment) const;
01182 
01184     void fireAreaChangeEvents(const bool moved, const bool sized);
01185     void notifyChildrenOfSizeChange(const bool non_client,
01186                                     const bool client);
01187 
01188     /*************************************************************************
01189         Event trigger methods
01190     *************************************************************************/
01199     virtual void onSized(ElementEventArgs& e);
01200 
01212     virtual void onParentSized(ElementEventArgs& e);
01213 
01222     virtual void onMoved(ElementEventArgs& e);
01223 
01234     virtual void onHorizontalAlignmentChanged(ElementEventArgs& e);
01235 
01246     virtual void onVerticalAlignmentChanged(ElementEventArgs& e);
01247 
01256     virtual void onRotated(ElementEventArgs& e);
01257 
01266     virtual void onChildAdded(ElementEventArgs& e);
01267 
01276     virtual void onChildRemoved(ElementEventArgs& e);
01277 
01288     virtual void onNonClientChanged(ElementEventArgs& e);
01289 
01290     /*************************************************************************
01291         Implementation Data
01292     *************************************************************************/
01294     typedef std::vector<Element*
01295         CEGUI_VECTOR_ALLOC(Element*)> ChildList;
01296 
01298     ChildList d_children;
01300     Element* d_parent;
01301 
01303     bool d_nonClient;
01304 
01306     URect d_area;
01308     HorizontalAlignment d_horizontalAlignment;
01310     VerticalAlignment d_verticalAlignment;
01312     USize d_minSize;
01314     USize d_maxSize;
01316     AspectMode d_aspectMode;
01318     float d_aspectRatio;
01320     bool d_pixelAligned;
01322     Sizef d_pixelSize;
01324     Quaternion d_rotation;
01325 
01327     CachedRectf d_unclippedOuterRect;
01329     CachedRectf d_unclippedInnerRect;
01330 
01331 private:
01332     /*************************************************************************
01333         May not copy or assign Element objects
01334     *************************************************************************/
01335     Element(const Element&);
01336 
01337     Element& operator=(const Element&) {return *this;}
01338 };
01339 
01340 } // End of  CEGUI namespace section
01341 
01342 
01343 #if defined(_MSC_VER)
01344 #   pragma warning(pop)
01345 #endif
01346 
01347 #endif  // end of guard _CEGUIElement_h_
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends