LCOV - code coverage report
Current view: top level - usr/include/irrlicht - IGUIElement.h (source / functions) Hit Total Coverage
Test: report Lines: 247 389 63.5 %
Date: 2015-07-11 18:23:49 Functions: 41 56 73.2 %

          Line data    Source code
       1             : // Copyright (C) 2002-2012 Nikolaus Gebhardt
       2             : // This file is part of the "Irrlicht Engine".
       3             : // For conditions of distribution and use, see copyright notice in irrlicht.h
       4             : 
       5             : #ifndef __I_GUI_ELEMENT_H_INCLUDED__
       6             : #define __I_GUI_ELEMENT_H_INCLUDED__
       7             : 
       8             : #include "IAttributeExchangingObject.h"
       9             : #include "irrList.h"
      10             : #include "rect.h"
      11             : #include "irrString.h"
      12             : #include "IEventReceiver.h"
      13             : #include "EGUIElementTypes.h"
      14             : #include "EGUIAlignment.h"
      15             : #include "IAttributes.h"
      16             : 
      17             : namespace irr
      18             : {
      19             : namespace gui
      20             : {
      21             : 
      22             : class IGUIEnvironment;
      23             : 
      24             : //! Base class of all GUI elements.
      25             : class IGUIElement : public virtual io::IAttributeExchangingObject, public IEventReceiver
      26             : {
      27             : public:
      28             : 
      29             :         //! Constructor
      30          11 :         IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent,
      31             :                 s32 id, const core::rect<s32>& rectangle)
      32             :                 : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle),
      33             :                 AbsoluteClippingRect(rectangle), DesiredRect(rectangle),
      34             :                 MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true),
      35             :                 IsSubElement(false), NoClip(false), ID(id), IsTabStop(false), TabOrder(-1), IsTabGroup(false),
      36             :                 AlignLeft(EGUIA_UPPERLEFT), AlignRight(EGUIA_UPPERLEFT), AlignTop(EGUIA_UPPERLEFT), AlignBottom(EGUIA_UPPERLEFT),
      37          11 :                 Environment(environment), Type(type)
      38             :         {
      39             :                 #ifdef _DEBUG
      40             :                 setDebugName("IGUIElement");
      41             :                 #endif
      42             : 
      43             :                 // if we were given a parent to attach to
      44          11 :                 if (parent)
      45             :                 {
      46          11 :                         parent->addChildToEnd(this);
      47          11 :                         recalculateAbsolutePosition(true);
      48             :                 }
      49          11 :         }
      50             : 
      51             : 
      52             :         //! Destructor
      53           6 :         virtual ~IGUIElement()
      54          12 :         {
      55             :                 // delete all children
      56           6 :                 core::list<IGUIElement*>::Iterator it = Children.begin();
      57          12 :                 for (; it != Children.end(); ++it)
      58             :                 {
      59           3 :                         (*it)->Parent = 0;
      60           3 :                         (*it)->drop();
      61             :                 }
      62           6 :         }
      63             : 
      64             : 
      65             :         //! Returns parent of this element.
      66         152 :         IGUIElement* getParent() const
      67             :         {
      68         152 :                 return Parent;
      69             :         }
      70             : 
      71             : 
      72             :         //! Returns the relative rectangle of this element.
      73           2 :         core::rect<s32> getRelativePosition() const
      74             :         {
      75           2 :                 return RelativeRect;
      76             :         }
      77             : 
      78             : 
      79             :         //! Sets the relative rectangle of this element.
      80             :         /** \param r The absolute position to set */
      81        3500 :         void setRelativePosition(const core::rect<s32>& r)
      82             :         {
      83        3500 :                 if (Parent)
      84             :                 {
      85        3500 :                         const core::rect<s32>& r2 = Parent->getAbsolutePosition();
      86             : 
      87        3500 :                         core::dimension2df d((f32)(r2.getSize().Width), (f32)(r2.getSize().Height));
      88             : 
      89        3500 :                         if (AlignLeft   == EGUIA_SCALE)
      90           0 :                                 ScaleRect.UpperLeftCorner.X = (f32)r.UpperLeftCorner.X / d.Width;
      91        3500 :                         if (AlignRight  == EGUIA_SCALE)
      92           0 :                                 ScaleRect.LowerRightCorner.X = (f32)r.LowerRightCorner.X / d.Width;
      93        3500 :                         if (AlignTop    == EGUIA_SCALE)
      94           0 :                                 ScaleRect.UpperLeftCorner.Y = (f32)r.UpperLeftCorner.Y / d.Height;
      95        3500 :                         if (AlignBottom == EGUIA_SCALE)
      96           0 :                                 ScaleRect.LowerRightCorner.Y = (f32)r.LowerRightCorner.Y / d.Height;
      97             :                 }
      98             : 
      99        3500 :                 DesiredRect = r;
     100        3500 :                 updateAbsolutePosition();
     101        3500 :         }
     102             : 
     103             :         //! Sets the relative rectangle of this element, maintaining its current width and height
     104             :         /** \param position The new relative position to set. Width and height will not be changed. */
     105           0 :         void setRelativePosition(const core::position2di & position)
     106             :         {
     107           0 :                 const core::dimension2di mySize = RelativeRect.getSize();
     108           0 :                 const core::rect<s32> rectangle(position.X, position.Y,
     109           0 :                                                 position.X + mySize.Width, position.Y + mySize.Height);
     110           0 :                 setRelativePosition(rectangle);
     111           0 :         }
     112             : 
     113             : 
     114             :         //! Sets the relative rectangle of this element as a proportion of its parent's area.
     115             :         /** \note This method used to be 'void setRelativePosition(const core::rect<f32>& r)'
     116             :         \param r  The rectangle to set, interpreted as a proportion of the parent's area.
     117             :         Meaningful values are in the range [0...1], unless you intend this element to spill
     118             :         outside its parent. */
     119             :         void setRelativePositionProportional(const core::rect<f32>& r)
     120             :         {
     121             :                 if (!Parent)
     122             :                         return;
     123             : 
     124             :                 const core::dimension2di& d = Parent->getAbsolutePosition().getSize();
     125             : 
     126             :                 DesiredRect = core::rect<s32>(
     127             :                                         core::floor32((f32)d.Width * r.UpperLeftCorner.X),
     128             :                                         core::floor32((f32)d.Height * r.UpperLeftCorner.Y),
     129             :                                         core::floor32((f32)d.Width * r.LowerRightCorner.X),
     130             :                                         core::floor32((f32)d.Height * r.LowerRightCorner.Y));
     131             : 
     132             :                 ScaleRect = r;
     133             : 
     134             :                 updateAbsolutePosition();
     135             :         }
     136             : 
     137             : 
     138             :         //! Gets the absolute rectangle of this element
     139        3515 :         core::rect<s32> getAbsolutePosition() const
     140             :         {
     141        3515 :                 return AbsoluteRect;
     142             :         }
     143             : 
     144             : 
     145             :         //! Returns the visible area of the element.
     146           0 :         core::rect<s32> getAbsoluteClippingRect() const
     147             :         {
     148           0 :                 return AbsoluteClippingRect;
     149             :         }
     150             : 
     151             : 
     152             :         //! Sets whether the element will ignore its parent's clipping rectangle
     153             :         /** \param noClip If true, the element will not be clipped by its parent's clipping rectangle. */
     154           2 :         void setNotClipped(bool noClip)
     155             :         {
     156           2 :                 NoClip = noClip;
     157           2 :                 updateAbsolutePosition();
     158           2 :         }
     159             : 
     160             : 
     161             :         //! Gets whether the element will ignore its parent's clipping rectangle
     162             :         /** \return true if the element is not clipped by its parent's clipping rectangle. */
     163             :         bool isNotClipped() const
     164             :         {
     165             :                 return NoClip;
     166             :         }
     167             : 
     168             : 
     169             :         //! Sets the maximum size allowed for this element
     170             :         /** If set to 0,0, there is no maximum size */
     171           0 :         void setMaxSize(core::dimension2du size)
     172             :         {
     173           0 :                 MaxSize = size;
     174           0 :                 updateAbsolutePosition();
     175           0 :         }
     176             : 
     177             : 
     178             :         //! Sets the minimum size allowed for this element
     179           0 :         void setMinSize(core::dimension2du size)
     180             :         {
     181           0 :                 MinSize = size;
     182           0 :                 if (MinSize.Width < 1)
     183           0 :                         MinSize.Width = 1;
     184           0 :                 if (MinSize.Height < 1)
     185           0 :                         MinSize.Height = 1;
     186           0 :                 updateAbsolutePosition();
     187           0 :         }
     188             : 
     189             : 
     190             :         //! The alignment defines how the borders of this element will be positioned when the parent element is resized.
     191           4 :         void setAlignment(EGUI_ALIGNMENT left, EGUI_ALIGNMENT right, EGUI_ALIGNMENT top, EGUI_ALIGNMENT bottom)
     192             :         {
     193           4 :                 AlignLeft = left;
     194           4 :                 AlignRight = right;
     195           4 :                 AlignTop = top;
     196           4 :                 AlignBottom = bottom;
     197             : 
     198           4 :                 if (Parent)
     199             :                 {
     200           4 :                         core::rect<s32> r(Parent->getAbsolutePosition());
     201             : 
     202           4 :                         core::dimension2df d((f32)r.getSize().Width, (f32)r.getSize().Height);
     203             : 
     204           4 :                         if (AlignLeft   == EGUIA_SCALE)
     205           0 :                                 ScaleRect.UpperLeftCorner.X = (f32)DesiredRect.UpperLeftCorner.X / d.Width;
     206           4 :                         if (AlignRight  == EGUIA_SCALE)
     207           0 :                                 ScaleRect.LowerRightCorner.X = (f32)DesiredRect.LowerRightCorner.X / d.Width;
     208           4 :                         if (AlignTop    == EGUIA_SCALE)
     209           0 :                                 ScaleRect.UpperLeftCorner.Y = (f32)DesiredRect.UpperLeftCorner.Y / d.Height;
     210           4 :                         if (AlignBottom == EGUIA_SCALE)
     211           0 :                                 ScaleRect.LowerRightCorner.Y = (f32)DesiredRect.LowerRightCorner.Y / d.Height;
     212             :                 }
     213           4 :         }
     214             : 
     215             : 
     216             :         //! Updates the absolute position.
     217          42 :         virtual void updateAbsolutePosition()
     218             :         {
     219          42 :                 recalculateAbsolutePosition(false);
     220             : 
     221             :                 // update all children
     222          42 :                 core::list<IGUIElement*>::Iterator it = Children.begin();
     223          46 :                 for (; it != Children.end(); ++it)
     224             :                 {
     225           2 :                         (*it)->updateAbsolutePosition();
     226             :                 }
     227          42 :         }
     228             : 
     229             : 
     230             :         //! Returns the topmost GUI element at the specific position.
     231             :         /**
     232             :         This will check this GUI element and all of its descendants, so it
     233             :         may return this GUI element.  To check all GUI elements, call this
     234             :         function on device->getGUIEnvironment()->getRootGUIElement(). Note
     235             :         that the root element is the size of the screen, so doing so (with
     236             :         an on-screen point) will always return the root element if no other
     237             :         element is above it at that point.
     238             :         \param point: The point at which to find a GUI element.
     239             :         \return The topmost GUI element at that point, or 0 if there are
     240             :         no candidate elements at this point.
     241             :         */
     242       29616 :         IGUIElement* getElementFromPoint(const core::position2d<s32>& point)
     243             :         {
     244       29616 :                 IGUIElement* target = 0;
     245             : 
     246             :                 // we have to search from back to front, because later children
     247             :                 // might be drawn over the top of earlier ones.
     248             : 
     249       29616 :                 core::list<IGUIElement*>::Iterator it = Children.getLast();
     250             : 
     251       29616 :                 if (isVisible())
     252             :                 {
     253       67163 :                         while(it != Children.end())
     254             :                         {
     255       26699 :                                 target = (*it)->getElementFromPoint(point);
     256       26699 :                                 if (target)
     257        3577 :                                         return target;
     258             : 
     259       23122 :                                 --it;
     260             :                         }
     261             :                 }
     262             : 
     263       26039 :                 if (isVisible() && isPointInside(point))
     264        2917 :                         target = this;
     265             : 
     266       26039 :                 return target;
     267             :         }
     268             : 
     269             : 
     270             :         //! Returns true if a point is within this element.
     271             :         /** Elements with a shape other than a rectangle should override this method */
     272       17345 :         virtual bool isPointInside(const core::position2d<s32>& point) const
     273             :         {
     274       17345 :                 return AbsoluteClippingRect.isPointInside(point);
     275             :         }
     276             : 
     277             : 
     278             :         //! Adds a GUI element as new child of this element.
     279           0 :         virtual void addChild(IGUIElement* child)
     280             :         {
     281           0 :                 addChildToEnd(child);
     282           0 :                 if (child)
     283             :                 {
     284           0 :                         child->updateAbsolutePosition();
     285             :                 }
     286           0 :         }
     287             : 
     288             :         //! Removes a child.
     289         117 :         virtual void removeChild(IGUIElement* child)
     290             :         {
     291         117 :                 core::list<IGUIElement*>::Iterator it = Children.begin();
     292         779 :                 for (; it != Children.end(); ++it)
     293         448 :                         if ((*it) == child)
     294             :                         {
     295         117 :                                 (*it)->Parent = 0;
     296         117 :                                 (*it)->drop();
     297         117 :                                 Children.erase(it);
     298         117 :                                 return;
     299             :                         }
     300             :         }
     301             : 
     302             : 
     303             :         //! Removes this element from its parent.
     304         265 :         virtual void remove()
     305             :         {
     306         265 :                 if (Parent)
     307         117 :                         Parent->removeChild(this);
     308         265 :         }
     309             : 
     310             : 
     311             :         //! Draws the element and its children.
     312        2974 :         virtual void draw()
     313             :         {
     314        2974 :                 if ( isVisible() )
     315             :                 {
     316        2974 :                         core::list<IGUIElement*>::Iterator it = Children.begin();
     317       13696 :                         for (; it != Children.end(); ++it)
     318        5361 :                                 (*it)->draw();
     319             :                 }
     320        2974 :         }
     321             : 
     322             : 
     323             :         //! animate the element and its children.
     324       13202 :         virtual void OnPostRender(u32 timeMs)
     325             :         {
     326       13202 :                 if ( isVisible() )
     327             :                 {
     328        8840 :                         core::list<IGUIElement*>::Iterator it = Children.begin();
     329       27390 :                         for (; it != Children.end(); ++it)
     330        9275 :                                 (*it)->OnPostRender( timeMs );
     331             :                 }
     332       13202 :         }
     333             : 
     334             : 
     335             :         //! Moves this element.
     336           0 :         virtual void move(core::position2d<s32> absoluteMovement)
     337             :         {
     338           0 :                 setRelativePosition(DesiredRect + absoluteMovement);
     339           0 :         }
     340             : 
     341             : 
     342             :         //! Returns true if element is visible.
     343       82330 :         virtual bool isVisible() const
     344             :         {
     345             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     346       82330 :                 return IsVisible;
     347             :         }
     348             : 
     349             : 
     350             :         //! Sets the visible state of this element.
     351        6033 :         virtual void setVisible(bool visible)
     352             :         {
     353        6033 :                 IsVisible = visible;
     354        6033 :         }
     355             : 
     356             : 
     357             :         //! Returns true if this element was created as part of its parent control
     358       10246 :         virtual bool isSubElement() const
     359             :         {
     360             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     361       10246 :                 return IsSubElement;
     362             :         }
     363             : 
     364             : 
     365             :         //! Sets whether this control was created as part of its parent.
     366             :         /** For example, it is true when a scrollbar is part of a listbox.
     367             :         SubElements are not saved to disk when calling guiEnvironment->saveGUI() */
     368          10 :         virtual void setSubElement(bool subElement)
     369             :         {
     370          10 :                 IsSubElement = subElement;
     371          10 :         }
     372             : 
     373             : 
     374             :         //! If set to true, the focus will visit this element when using the tab key to cycle through elements.
     375             :         /** If this element is a tab group (see isTabGroup/setTabGroup) then
     376             :         ctrl+tab will be used instead. */
     377          10 :         void setTabStop(bool enable)
     378             :         {
     379          10 :                 IsTabStop = enable;
     380          10 :         }
     381             : 
     382             : 
     383             :         //! Returns true if this element can be focused by navigating with the tab key
     384         100 :         bool isTabStop() const
     385             :         {
     386             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     387         100 :                 return IsTabStop;
     388             :         }
     389             : 
     390             : 
     391             :         //! Sets the priority of focus when using the tab key to navigate between a group of elements.
     392             :         /** See setTabGroup, isTabGroup and getTabGroup for information on tab groups.
     393             :         Elements with a lower number are focused first */
     394           8 :         void setTabOrder(s32 index)
     395             :         {
     396             :                 // negative = autonumber
     397           8 :                 if (index < 0)
     398             :                 {
     399           8 :                         TabOrder = 0;
     400           8 :                         IGUIElement *el = getTabGroup();
     401           8 :                         while (IsTabGroup && el && el->Parent)
     402           0 :                                 el = el->Parent;
     403             : 
     404           8 :                         IGUIElement *first=0, *closest=0;
     405           8 :                         if (el)
     406             :                         {
     407             :                                 // find the highest element number
     408           8 :                                 el->getNextElement(-1, true, IsTabGroup, first, closest, true);
     409           8 :                                 if (first)
     410             :                                 {
     411           8 :                                         TabOrder = first->getTabOrder() + 1;
     412             :                                 }
     413             :                         }
     414             : 
     415             :                 }
     416             :                 else
     417           0 :                         TabOrder = index;
     418           8 :         }
     419             : 
     420             : 
     421             :         //! Returns the number in the tab order sequence
     422          68 :         s32 getTabOrder() const
     423             :         {
     424          68 :                 return TabOrder;
     425             :         }
     426             : 
     427             : 
     428             :         //! Sets whether this element is a container for a group of elements which can be navigated using the tab key.
     429             :         /** For example, windows are tab groups.
     430             :         Groups can be navigated using ctrl+tab, providing isTabStop is true. */
     431             :         void setTabGroup(bool isGroup)
     432             :         {
     433             :                 IsTabGroup = isGroup;
     434             :         }
     435             : 
     436             : 
     437             :         //! Returns true if this element is a tab group.
     438         166 :         bool isTabGroup() const
     439             :         {
     440             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     441         166 :                 return IsTabGroup;
     442             :         }
     443             : 
     444             : 
     445             :         //! Returns the container element which holds all elements in this element's tab group.
     446           8 :         IGUIElement* getTabGroup()
     447             :         {
     448           8 :                 IGUIElement *ret=this;
     449             : 
     450          56 :                 while (ret && !ret->isTabGroup())
     451          24 :                         ret = ret->getParent();
     452             : 
     453           8 :                 return ret;
     454             :         }
     455             : 
     456             : 
     457             :         //! Returns true if element is enabled
     458             :         /** Currently elements do _not_ care about parent-states.
     459             :                 So if you want to affect childs you have to enable/disable them all.
     460             :                 The only exception to this are sub-elements which also check their parent.
     461             :         */
     462        7552 :         virtual bool isEnabled() const
     463             :         {
     464        7552 :                 if ( isSubElement() && IsEnabled && getParent() )
     465           4 :                         return getParent()->isEnabled();
     466             : 
     467             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     468        7548 :                 return IsEnabled;
     469             :         }
     470             : 
     471             : 
     472             :         //! Sets the enabled state of this element.
     473         190 :         virtual void setEnabled(bool enabled)
     474             :         {
     475         190 :                 IsEnabled = enabled;
     476         190 :         }
     477             : 
     478             : 
     479             :         //! Sets the new caption of this element.
     480          26 :         virtual void setText(const wchar_t* text)
     481             :         {
     482          26 :                 Text = text;
     483          26 :         }
     484             : 
     485             : 
     486             :         //! Returns caption of this element.
     487         801 :         virtual const wchar_t* getText() const
     488             :         {
     489         801 :                 return Text.c_str();
     490             :         }
     491             : 
     492             : 
     493             :         //! Sets the new caption of this element.
     494           4 :         virtual void setToolTipText(const wchar_t* text)
     495             :         {
     496           4 :                 ToolTipText = text;
     497           4 :         }
     498             : 
     499             : 
     500             :         //! Returns caption of this element.
     501         543 :         virtual const core::stringw& getToolTipText() const
     502             :         {
     503         543 :                 return ToolTipText;
     504             :         }
     505             : 
     506             : 
     507             :         //! Returns id. Can be used to identify the element.
     508         206 :         virtual s32 getID() const
     509             :         {
     510         206 :                 return ID;
     511             :         }
     512             : 
     513             : 
     514             :         //! Sets the id of this element
     515           0 :         virtual void setID(s32 id)
     516             :         {
     517           0 :                 ID = id;
     518           0 :         }
     519             : 
     520             : 
     521             :         //! Called if an event happened.
     522        3283 :         virtual bool OnEvent(const SEvent& event)
     523             :         {
     524        3283 :                 return Parent ? Parent->OnEvent(event) : false;
     525             :         }
     526             : 
     527             : 
     528             :         //! Brings a child to front
     529             :         /** \return True if successful, false if not. */
     530          60 :         virtual bool bringToFront(IGUIElement* element)
     531             :         {
     532          60 :                 core::list<IGUIElement*>::Iterator it = Children.begin();
     533         468 :                 for (; it != Children.end(); ++it)
     534             :                 {
     535         264 :                         if (element == (*it))
     536             :                         {
     537          60 :                                 Children.erase(it);
     538          60 :                                 Children.push_back(element);
     539          60 :                                 return true;
     540             :                         }
     541             :                 }
     542             : 
     543             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     544           0 :                 return false;
     545             :         }
     546             : 
     547             : 
     548             :         //! Moves a child to the back, so it's siblings are drawn on top of it
     549             :         /** \return True if successful, false if not. */
     550           0 :         virtual bool sendToBack(IGUIElement* child)
     551             :         {
     552           0 :                 core::list<IGUIElement*>::Iterator it = Children.begin();
     553           0 :                 if (child == (*it))     // already there
     554           0 :                         return true;
     555           0 :                 for (; it != Children.end(); ++it)
     556             :                 {
     557           0 :                         if (child == (*it))
     558             :                         {
     559           0 :                                 Children.erase(it);
     560           0 :                                 Children.push_front(child);
     561           0 :                                 return true;
     562             :                         }
     563             :                 }
     564             : 
     565             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     566           0 :                 return false;
     567             :         }
     568             : 
     569             :         //! Returns list with children of this element
     570          11 :         virtual const core::list<IGUIElement*>& getChildren() const
     571             :         {
     572          11 :                 return Children;
     573             :         }
     574             : 
     575             : 
     576             :         //! Finds the first element with the given id.
     577             :         /** \param id: Id to search for.
     578             :         \param searchchildren: Set this to true, if also children of this
     579             :         element may contain the element with the searched id and they
     580             :         should be searched too.
     581             :         \return Returns the first element with the given id. If no element
     582             :         with this id was found, 0 is returned. */
     583          12 :         virtual IGUIElement* getElementFromId(s32 id, bool searchchildren=false) const
     584             :         {
     585          12 :                 IGUIElement* e = 0;
     586             : 
     587          12 :                 core::list<IGUIElement*>::ConstIterator it = Children.begin();
     588         156 :                 for (; it != Children.end(); ++it)
     589             :                 {
     590          84 :                         if ((*it)->getID() == id)
     591          12 :                                 return (*it);
     592             : 
     593          72 :                         if (searchchildren)
     594           0 :                                 e = (*it)->getElementFromId(id, true);
     595             : 
     596          72 :                         if (e)
     597           0 :                                 return e;
     598             :                 }
     599             : 
     600           0 :                 return e;
     601             :         }
     602             : 
     603             : 
     604             :         //! returns true if the given element is a child of this one.
     605             :         //! \param child: The child element to check
     606          12 :         bool isMyChild(IGUIElement* child) const
     607             :         {
     608          12 :                 if (!child)
     609           0 :                         return false;
     610           3 :                 do
     611             :                 {
     612          15 :                         if (child->Parent)
     613          15 :                                 child = child->Parent;
     614             : 
     615          15 :                 } while (child->Parent && child != this);
     616             : 
     617             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     618          12 :                 return child == this;
     619             :         }
     620             : 
     621             : 
     622             :         //! searches elements to find the closest next element to tab to
     623             :         /** \param startOrder: The TabOrder of the current element, -1 if none
     624             :         \param reverse: true if searching for a lower number
     625             :         \param group: true if searching for a higher one
     626             :         \param first: element with the highest/lowest known tab order depending on search direction
     627             :         \param closest: the closest match, depending on tab order and direction
     628             :         \param includeInvisible: includes invisible elements in the search (default=false)
     629             :         \return true if successfully found an element, false to continue searching/fail */
     630         108 :         bool getNextElement(s32 startOrder, bool reverse, bool group,
     631             :                 IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const
     632             :         {
     633             :                 // we'll stop searching if we find this number
     634         108 :                 s32 wanted = startOrder + ( reverse ? -1 : 1 );
     635         108 :                 if (wanted==-2)
     636         108 :                         wanted = 1073741824; // maximum s32
     637             : 
     638         108 :                 core::list<IGUIElement*>::ConstIterator it = Children.begin();
     639             : 
     640             :                 s32 closestOrder, currentOrder;
     641             : 
     642         440 :                 while(it != Children.end())
     643             :                 {
     644             :                         // ignore invisible elements and their children
     645         266 :                         if ( ( (*it)->isVisible() || includeInvisible ) &&
     646         100 :                                 (group == true || (*it)->isTabGroup() == false) )
     647             :                         {
     648             :                                 // only check tab stops and those with the same group status
     649         100 :                                 if ((*it)->isTabStop() && ((*it)->isTabGroup() == group))
     650             :                                 {
     651          34 :                                         currentOrder = (*it)->getTabOrder();
     652             : 
     653             :                                         // is this what we're looking for?
     654          34 :                                         if (currentOrder == wanted)
     655             :                                         {
     656           0 :                                                 closest = *it;
     657           0 :                                                 return true;
     658             :                                         }
     659             : 
     660             :                                         // is it closer than the current closest?
     661          34 :                                         if (closest)
     662             :                                         {
     663           0 :                                                 closestOrder = closest->getTabOrder();
     664           0 :                                                 if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder)
     665           0 :                                                         ||(!reverse && currentOrder < closestOrder && currentOrder > startOrder))
     666             :                                                 {
     667           0 :                                                         closest = *it;
     668             :                                                 }
     669             :                                         }
     670             :                                         else
     671          34 :                                         if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) )
     672             :                                         {
     673           0 :                                                 closest = *it;
     674             :                                         }
     675             : 
     676             :                                         // is it before the current first?
     677          34 :                                         if (first)
     678             :                                         {
     679          26 :                                                 closestOrder = first->getTabOrder();
     680             : 
     681          26 :                                                 if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) )
     682             :                                                 {
     683          20 :                                                         first = *it;
     684             :                                                 }
     685             :                                         }
     686             :                                         else
     687             :                                         {
     688           8 :                                                 first = *it;
     689             :                                         }
     690             :                                 }
     691             :                                 // search within children
     692         100 :                                 if ((*it)->getNextElement(startOrder, reverse, group, first, closest))
     693             :                                 {
     694             :                                         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     695           0 :                                         return true;
     696             :                                 }
     697             :                         }
     698         166 :                         ++it;
     699             :                 }
     700             :                 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
     701         108 :                 return false;
     702             :         }
     703             : 
     704             : 
     705             :         //! Returns the type of the gui element.
     706             :         /** This is needed for the .NET wrapper but will be used
     707             :         later for serializing and deserializing.
     708             :         If you wrote your own GUIElements, you need to set the type for your element as first parameter
     709             :         in the constructor of IGUIElement. For own (=unknown) elements, simply use EGUIET_ELEMENT as type */
     710          16 :         EGUI_ELEMENT_TYPE getType() const
     711             :         {
     712          16 :                 return Type;
     713             :         }
     714             : 
     715             :         //! Returns true if the gui element supports the given type.
     716             :         /** This is mostly used to check if you can cast a gui element to the class that goes with the type.
     717             :         Most gui elements will only support their own type, but if you derive your own classes from interfaces
     718             :         you can overload this function and add a check for the type of the base-class additionally.
     719             :         This allows for checks comparable to the dynamic_cast of c++ with enabled rtti.
     720             :         Note that you can't do that by calling BaseClass::hasType(type), but you have to do an explicit
     721             :         comparison check, because otherwise the base class usually just checks for the membervariable
     722             :         Type which contains the type of your derived class.
     723             :         */
     724           0 :         virtual bool hasType(EGUI_ELEMENT_TYPE type) const
     725             :         {
     726           0 :                 return type == Type;
     727             :         }
     728             : 
     729             : 
     730             :         //! Returns the type name of the gui element.
     731             :         /** This is needed serializing elements. For serializing your own elements, override this function
     732             :         and return your own type name which is created by your IGUIElementFactory */
     733           0 :         virtual const c8* getTypeName() const
     734             :         {
     735           0 :                 return GUIElementTypeNames[Type];
     736             :         }
     737             :         
     738             :         //! Returns the name of the element.
     739             :         /** \return Name as character string. */
     740           0 :         virtual const c8* getName() const
     741             :         {
     742           0 :                 return Name.c_str();
     743             :         }
     744             : 
     745             : 
     746             :         //! Sets the name of the element.
     747             :         /** \param name New name of the gui element. */
     748           0 :         virtual void setName(const c8* name)
     749             :         {
     750           0 :                 Name = name;
     751           0 :         }
     752             : 
     753             : 
     754             :         //! Sets the name of the element.
     755             :         /** \param name New name of the gui element. */
     756           0 :         virtual void setName(const core::stringc& name)
     757             :         {
     758           0 :                 Name = name;
     759           0 :         }
     760             : 
     761             : 
     762             :         //! Writes attributes of the scene node.
     763             :         /** Implement this to expose the attributes of your scene node for
     764             :         scripting languages, editors, debuggers or xml serialization purposes. */
     765           0 :         virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
     766             :         {
     767           0 :                 out->addString("Name", Name.c_str());              
     768           0 :                 out->addInt("Id", ID );
     769           0 :                 out->addString("Caption", getText());
     770           0 :                 out->addRect("Rect", DesiredRect);
     771           0 :                 out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height));
     772           0 :                 out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height));
     773           0 :                 out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames);
     774           0 :                 out->addEnum("RightAlign", AlignRight, GUIAlignmentNames);
     775           0 :                 out->addEnum("TopAlign", AlignTop, GUIAlignmentNames);
     776           0 :                 out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames);
     777           0 :                 out->addBool("Visible", IsVisible);
     778           0 :                 out->addBool("Enabled", IsEnabled);
     779           0 :                 out->addBool("TabStop", IsTabStop);
     780           0 :                 out->addBool("TabGroup", IsTabGroup);
     781           0 :                 out->addInt("TabOrder", TabOrder);
     782           0 :                 out->addBool("NoClip", NoClip);
     783           0 :         }
     784             : 
     785             : 
     786             :         //! Reads attributes of the scene node.
     787             :         /** Implement this to set the attributes of your scene node for
     788             :         scripting languages, editors, debuggers or xml deserialization purposes. */
     789           0 :         virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
     790             :         {
     791           0 :                 setName(in->getAttributeAsString("Name"));
     792           0 :                 setID(in->getAttributeAsInt("Id"));
     793           0 :                 setText(in->getAttributeAsStringW("Caption").c_str());
     794           0 :                 setVisible(in->getAttributeAsBool("Visible"));
     795           0 :                 setEnabled(in->getAttributeAsBool("Enabled"));
     796           0 :                 IsTabStop = in->getAttributeAsBool("TabStop");
     797           0 :                 IsTabGroup = in->getAttributeAsBool("TabGroup");
     798           0 :                 TabOrder = in->getAttributeAsInt("TabOrder");
     799             : 
     800           0 :                 core::position2di p = in->getAttributeAsPosition2d("MaxSize");
     801           0 :                 setMaxSize(core::dimension2du(p.X,p.Y));
     802             : 
     803           0 :                 p = in->getAttributeAsPosition2d("MinSize");
     804           0 :                 setMinSize(core::dimension2du(p.X,p.Y));
     805             : 
     806           0 :                 setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames),
     807           0 :                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames),
     808           0 :                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames),
     809           0 :                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames));
     810             : 
     811           0 :                 setRelativePosition(in->getAttributeAsRect("Rect"));
     812             : 
     813           0 :                 setNotClipped(in->getAttributeAsBool("NoClip"));
     814           0 :         }
     815             : 
     816             : protected:
     817             :         // not virtual because needed in constructor
     818          11 :         void addChildToEnd(IGUIElement* child)
     819             :         {
     820          11 :                 if (child)
     821             :                 {
     822          11 :                         child->grab(); // prevent destruction when removed
     823          11 :                         child->remove(); // remove from old parent
     824          11 :                         child->LastParentRect = getAbsolutePosition();
     825          11 :                         child->Parent = this;
     826          11 :                         Children.push_back(child);
     827             :                 }
     828          11 :         }
     829             : 
     830             :         // not virtual because needed in constructor
     831          58 :         void recalculateAbsolutePosition(bool recursive)
     832             :         {
     833          58 :                 core::rect<s32> parentAbsolute(0,0,0,0);
     834          58 :                 core::rect<s32> parentAbsoluteClip;
     835          58 :                 f32 fw=0.f, fh=0.f;
     836             : 
     837          58 :                 if (Parent)
     838             :                 {
     839          58 :                         parentAbsolute = Parent->AbsoluteRect;
     840             : 
     841          58 :                         if (NoClip)
     842             :                         {
     843           0 :                                 IGUIElement* p=this;
     844           0 :                                 while (p && p->Parent)
     845           0 :                                         p = p->Parent;
     846           0 :                                 parentAbsoluteClip = p->AbsoluteClippingRect;
     847             :                         }
     848             :                         else
     849          58 :                                 parentAbsoluteClip = Parent->AbsoluteClippingRect;
     850             :                 }
     851             : 
     852          58 :                 const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
     853          58 :                 const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
     854             : 
     855          58 :                 if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE)
     856           0 :                         fw = (f32)parentAbsolute.getWidth();
     857             : 
     858          58 :                 if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE)
     859           0 :                         fh = (f32)parentAbsolute.getHeight();
     860             : 
     861          58 :                 switch (AlignLeft)
     862             :                 {
     863             :                         case EGUIA_UPPERLEFT:
     864          46 :                                 break;
     865             :                         case EGUIA_LOWERRIGHT:
     866          12 :                                 DesiredRect.UpperLeftCorner.X += diffx;
     867          12 :                                 break;
     868             :                         case EGUIA_CENTER:
     869           0 :                                 DesiredRect.UpperLeftCorner.X += diffx/2;
     870           0 :                                 break;
     871             :                         case EGUIA_SCALE:
     872           0 :                                 DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw);
     873           0 :                                 break;
     874             :                 }
     875             : 
     876          58 :                 switch (AlignRight)
     877             :                 {
     878             :                         case EGUIA_UPPERLEFT:
     879          22 :                                 break;
     880             :                         case EGUIA_LOWERRIGHT:
     881          36 :                                 DesiredRect.LowerRightCorner.X += diffx;
     882          36 :                                 break;
     883             :                         case EGUIA_CENTER:
     884           0 :                                 DesiredRect.LowerRightCorner.X += diffx/2;
     885           0 :                                 break;
     886             :                         case EGUIA_SCALE:
     887           0 :                                 DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw);
     888           0 :                                 break;
     889             :                 }
     890             : 
     891          58 :                 switch (AlignTop)
     892             :                 {
     893             :                         case EGUIA_UPPERLEFT:
     894          46 :                                 break;
     895             :                         case EGUIA_LOWERRIGHT:
     896          12 :                                 DesiredRect.UpperLeftCorner.Y += diffy;
     897          12 :                                 break;
     898             :                         case EGUIA_CENTER:
     899           0 :                                 DesiredRect.UpperLeftCorner.Y += diffy/2;
     900           0 :                                 break;
     901             :                         case EGUIA_SCALE:
     902           0 :                                 DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh);
     903           0 :                                 break;
     904             :                 }
     905             : 
     906          58 :                 switch (AlignBottom)
     907             :                 {
     908             :                         case EGUIA_UPPERLEFT:
     909          46 :                                 break;
     910             :                         case EGUIA_LOWERRIGHT:
     911          12 :                                 DesiredRect.LowerRightCorner.Y += diffy;
     912          12 :                                 break;
     913             :                         case EGUIA_CENTER:
     914           0 :                                 DesiredRect.LowerRightCorner.Y += diffy/2;
     915           0 :                                 break;
     916             :                         case EGUIA_SCALE:
     917           0 :                                 DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh);
     918           0 :                                 break;
     919             :                 }
     920             : 
     921          58 :                 RelativeRect = DesiredRect;
     922             : 
     923          58 :                 const s32 w = RelativeRect.getWidth();
     924          58 :                 const s32 h = RelativeRect.getHeight();
     925             : 
     926             :                 // make sure the desired rectangle is allowed
     927          58 :                 if (w < (s32)MinSize.Width)
     928           0 :                         RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width;
     929          58 :                 if (h < (s32)MinSize.Height)
     930           0 :                         RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height;
     931          58 :                 if (MaxSize.Width && w > (s32)MaxSize.Width)
     932           0 :                         RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width;
     933          58 :                 if (MaxSize.Height && h > (s32)MaxSize.Height)
     934           0 :                         RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height;
     935             : 
     936          58 :                 RelativeRect.repair();
     937             : 
     938          58 :                 AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
     939             : 
     940          58 :                 if (!Parent)
     941           0 :                         parentAbsoluteClip = AbsoluteRect;
     942             : 
     943          58 :                 AbsoluteClippingRect = AbsoluteRect;
     944          58 :                 AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
     945             : 
     946          58 :                 LastParentRect = parentAbsolute;
     947             : 
     948          58 :                 if ( recursive )
     949             :                 {
     950             :                         // update all children
     951          11 :                         core::list<IGUIElement*>::Iterator it = Children.begin();
     952          11 :                         for (; it != Children.end(); ++it)
     953             :                         {
     954           0 :                                 (*it)->recalculateAbsolutePosition(recursive);
     955             :                         }
     956             :                 }
     957          58 :         }
     958             : 
     959             : protected:
     960             : 
     961             :         //! List of all children of this element
     962             :         core::list<IGUIElement*> Children;
     963             : 
     964             :         //! Pointer to the parent
     965             :         IGUIElement* Parent;
     966             : 
     967             :         //! relative rect of element
     968             :         core::rect<s32> RelativeRect;
     969             : 
     970             :         //! absolute rect of element
     971             :         core::rect<s32> AbsoluteRect;
     972             : 
     973             :         //! absolute clipping rect of element
     974             :         core::rect<s32> AbsoluteClippingRect;
     975             : 
     976             :         //! the rectangle the element would prefer to be,
     977             :         //! if it was not constrained by parent or max/min size
     978             :         core::rect<s32> DesiredRect;
     979             : 
     980             :         //! for calculating the difference when resizing parent
     981             :         core::rect<s32> LastParentRect;
     982             : 
     983             :         //! relative scale of the element inside its parent
     984             :         core::rect<f32> ScaleRect;
     985             : 
     986             :         //! maximum and minimum size of the element
     987             :         core::dimension2du MaxSize, MinSize;
     988             : 
     989             :         //! is visible?
     990             :         bool IsVisible;
     991             : 
     992             :         //! is enabled?
     993             :         bool IsEnabled;
     994             : 
     995             :         //! is a part of a larger whole and should not be serialized?
     996             :         bool IsSubElement;
     997             : 
     998             :         //! does this element ignore its parent's clipping rectangle?
     999             :         bool NoClip;
    1000             : 
    1001             :         //! caption
    1002             :         core::stringw Text;
    1003             : 
    1004             :         //! tooltip
    1005             :         core::stringw ToolTipText;
    1006             :         
    1007             :         //! users can set this for identificating the element by string
    1008             :         core::stringc Name;
    1009             : 
    1010             :         //! users can set this for identificating the element by integer
    1011             :         s32 ID;
    1012             : 
    1013             :         //! tab stop like in windows
    1014             :         bool IsTabStop;
    1015             : 
    1016             :         //! tab order
    1017             :         s32 TabOrder;
    1018             : 
    1019             :         //! tab groups are containers like windows, use ctrl+tab to navigate
    1020             :         bool IsTabGroup;
    1021             : 
    1022             :         //! tells the element how to act when its parent is resized
    1023             :         EGUI_ALIGNMENT AlignLeft, AlignRight, AlignTop, AlignBottom;
    1024             : 
    1025             :         //! GUI Environment
    1026             :         IGUIEnvironment* Environment;
    1027             : 
    1028             :         //! type of element
    1029             :         EGUI_ELEMENT_TYPE Type;
    1030             : };
    1031             : 
    1032             : 
    1033             : } // end namespace gui
    1034             : } // end namespace irr
    1035             : 
    1036             : #endif
    1037             : 

Generated by: LCOV version 1.11