Irrlicht 3D Engine
IGUIElement.h
Go to the documentation of this file.
00001 // Copyright (C) 2002-2012 Nikolaus Gebhardt
00002 // This file is part of the "Irrlicht Engine".
00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
00004 
00005 #ifndef __I_GUI_ELEMENT_H_INCLUDED__
00006 #define __I_GUI_ELEMENT_H_INCLUDED__
00007 
00008 #include "IAttributeExchangingObject.h"
00009 #include "irrList.h"
00010 #include "rect.h"
00011 #include "irrString.h"
00012 #include "IEventReceiver.h"
00013 #include "EGUIElementTypes.h"
00014 #include "EGUIAlignment.h"
00015 #include "IAttributes.h"
00016 
00017 namespace irr
00018 {
00019 namespace gui
00020 {
00021 
00022 class IGUIEnvironment;
00023 
00025 class IGUIElement : public virtual io::IAttributeExchangingObject, public IEventReceiver
00026 {
00027 public:
00028 
00030     IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent,
00031         s32 id, const core::rect<s32>& rectangle)
00032         : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle),
00033         AbsoluteClippingRect(rectangle), DesiredRect(rectangle),
00034         MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true),
00035         IsSubElement(false), NoClip(false), ID(id), IsTabStop(false), TabOrder(-1), IsTabGroup(false),
00036         AlignLeft(EGUIA_UPPERLEFT), AlignRight(EGUIA_UPPERLEFT), AlignTop(EGUIA_UPPERLEFT), AlignBottom(EGUIA_UPPERLEFT),
00037         Environment(environment), Type(type)
00038     {
00039         #ifdef _DEBUG
00040         setDebugName("IGUIElement");
00041         #endif
00042 
00043         // if we were given a parent to attach to
00044         if (parent)
00045         {
00046             parent->addChildToEnd(this);
00047             recalculateAbsolutePosition(true);
00048         }
00049     }
00050 
00051 
00053     virtual ~IGUIElement()
00054     {
00055         // delete all children
00056         core::list<IGUIElement*>::Iterator it = Children.begin();
00057         for (; it != Children.end(); ++it)
00058         {
00059             (*it)->Parent = 0;
00060             (*it)->drop();
00061         }
00062     }
00063 
00064 
00066     IGUIElement* getParent() const
00067     {
00068         return Parent;
00069     }
00070 
00071 
00073     core::rect<s32> getRelativePosition() const
00074     {
00075         return RelativeRect;
00076     }
00077 
00078 
00080 
00081     void setRelativePosition(const core::rect<s32>& r)
00082     {
00083         if (Parent)
00084         {
00085             const core::rect<s32>& r2 = Parent->getAbsolutePosition();
00086 
00087             core::dimension2df d((f32)(r2.getSize().Width), (f32)(r2.getSize().Height));
00088 
00089             if (AlignLeft   == EGUIA_SCALE)
00090                 ScaleRect.UpperLeftCorner.X = (f32)r.UpperLeftCorner.X / d.Width;
00091             if (AlignRight  == EGUIA_SCALE)
00092                 ScaleRect.LowerRightCorner.X = (f32)r.LowerRightCorner.X / d.Width;
00093             if (AlignTop    == EGUIA_SCALE)
00094                 ScaleRect.UpperLeftCorner.Y = (f32)r.UpperLeftCorner.Y / d.Height;
00095             if (AlignBottom == EGUIA_SCALE)
00096                 ScaleRect.LowerRightCorner.Y = (f32)r.LowerRightCorner.Y / d.Height;
00097         }
00098 
00099         DesiredRect = r;
00100         updateAbsolutePosition();
00101     }
00102 
00104 
00105     void setRelativePosition(const core::position2di & position)
00106     {
00107         const core::dimension2di mySize = RelativeRect.getSize();
00108         const core::rect<s32> rectangle(position.X, position.Y,
00109                         position.X + mySize.Width, position.Y + mySize.Height);
00110         setRelativePosition(rectangle);
00111     }
00112 
00113 
00115 
00119     void setRelativePositionProportional(const core::rect<f32>& r)
00120     {
00121         if (!Parent)
00122             return;
00123 
00124         const core::dimension2di& d = Parent->getAbsolutePosition().getSize();
00125 
00126         DesiredRect = core::rect<s32>(
00127                     core::floor32((f32)d.Width * r.UpperLeftCorner.X),
00128                     core::floor32((f32)d.Height * r.UpperLeftCorner.Y),
00129                     core::floor32((f32)d.Width * r.LowerRightCorner.X),
00130                     core::floor32((f32)d.Height * r.LowerRightCorner.Y));
00131 
00132         ScaleRect = r;
00133 
00134         updateAbsolutePosition();
00135     }
00136 
00137 
00139     core::rect<s32> getAbsolutePosition() const
00140     {
00141         return AbsoluteRect;
00142     }
00143 
00144 
00146     core::rect<s32> getAbsoluteClippingRect() const
00147     {
00148         return AbsoluteClippingRect;
00149     }
00150 
00151 
00153 
00154     void setNotClipped(bool noClip)
00155     {
00156         NoClip = noClip;
00157         updateAbsolutePosition();
00158     }
00159 
00160 
00162 
00163     bool isNotClipped() const
00164     {
00165         return NoClip;
00166     }
00167 
00168 
00170 
00171     void setMaxSize(core::dimension2du size)
00172     {
00173         MaxSize = size;
00174         updateAbsolutePosition();
00175     }
00176 
00177 
00179     void setMinSize(core::dimension2du size)
00180     {
00181         MinSize = size;
00182         if (MinSize.Width < 1)
00183             MinSize.Width = 1;
00184         if (MinSize.Height < 1)
00185             MinSize.Height = 1;
00186         updateAbsolutePosition();
00187     }
00188 
00189 
00191     void setAlignment(EGUI_ALIGNMENT left, EGUI_ALIGNMENT right, EGUI_ALIGNMENT top, EGUI_ALIGNMENT bottom)
00192     {
00193         AlignLeft = left;
00194         AlignRight = right;
00195         AlignTop = top;
00196         AlignBottom = bottom;
00197 
00198         if (Parent)
00199         {
00200             core::rect<s32> r(Parent->getAbsolutePosition());
00201 
00202             core::dimension2df d((f32)r.getSize().Width, (f32)r.getSize().Height);
00203 
00204             if (AlignLeft   == EGUIA_SCALE)
00205                 ScaleRect.UpperLeftCorner.X = (f32)DesiredRect.UpperLeftCorner.X / d.Width;
00206             if (AlignRight  == EGUIA_SCALE)
00207                 ScaleRect.LowerRightCorner.X = (f32)DesiredRect.LowerRightCorner.X / d.Width;
00208             if (AlignTop    == EGUIA_SCALE)
00209                 ScaleRect.UpperLeftCorner.Y = (f32)DesiredRect.UpperLeftCorner.Y / d.Height;
00210             if (AlignBottom == EGUIA_SCALE)
00211                 ScaleRect.LowerRightCorner.Y = (f32)DesiredRect.LowerRightCorner.Y / d.Height;
00212         }
00213     }
00214 
00215 
00217     virtual void updateAbsolutePosition()
00218     {
00219         recalculateAbsolutePosition(false);
00220 
00221         // update all children
00222         core::list<IGUIElement*>::Iterator it = Children.begin();
00223         for (; it != Children.end(); ++it)
00224         {
00225             (*it)->updateAbsolutePosition();
00226         }
00227     }
00228 
00229 
00231 
00242     IGUIElement* getElementFromPoint(const core::position2d<s32>& point)
00243     {
00244         IGUIElement* target = 0;
00245 
00246         // we have to search from back to front, because later children
00247         // might be drawn over the top of earlier ones.
00248 
00249         core::list<IGUIElement*>::Iterator it = Children.getLast();
00250 
00251         if (isVisible())
00252         {
00253             while(it != Children.end())
00254             {
00255                 target = (*it)->getElementFromPoint(point);
00256                 if (target)
00257                     return target;
00258 
00259                 --it;
00260             }
00261         }
00262 
00263         if (isVisible() && isPointInside(point))
00264             target = this;
00265 
00266         return target;
00267     }
00268 
00269 
00271 
00272     virtual bool isPointInside(const core::position2d<s32>& point) const
00273     {
00274         return AbsoluteClippingRect.isPointInside(point);
00275     }
00276 
00277 
00279     virtual void addChild(IGUIElement* child)
00280     {
00281         addChildToEnd(child);
00282         if (child)
00283         {
00284             child->updateAbsolutePosition();
00285         }
00286     }
00287 
00289     virtual void removeChild(IGUIElement* child)
00290     {
00291         core::list<IGUIElement*>::Iterator it = Children.begin();
00292         for (; it != Children.end(); ++it)
00293             if ((*it) == child)
00294             {
00295                 (*it)->Parent = 0;
00296                 (*it)->drop();
00297                 Children.erase(it);
00298                 return;
00299             }
00300     }
00301 
00302 
00304     virtual void remove()
00305     {
00306         if (Parent)
00307             Parent->removeChild(this);
00308     }
00309 
00310 
00312     virtual void draw()
00313     {
00314         if ( isVisible() )
00315         {
00316             core::list<IGUIElement*>::Iterator it = Children.begin();
00317             for (; it != Children.end(); ++it)
00318                 (*it)->draw();
00319         }
00320     }
00321 
00322 
00324     virtual void OnPostRender(u32 timeMs)
00325     {
00326         if ( isVisible() )
00327         {
00328             core::list<IGUIElement*>::Iterator it = Children.begin();
00329             for (; it != Children.end(); ++it)
00330                 (*it)->OnPostRender( timeMs );
00331         }
00332     }
00333 
00334 
00336     virtual void move(core::position2d<s32> absoluteMovement)
00337     {
00338         setRelativePosition(DesiredRect + absoluteMovement);
00339     }
00340 
00341 
00343     virtual bool isVisible() const
00344     {
00345         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00346         return IsVisible;
00347     }
00348 
00349 
00351     virtual void setVisible(bool visible)
00352     {
00353         IsVisible = visible;
00354     }
00355 
00356 
00358     virtual bool isSubElement() const
00359     {
00360         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00361         return IsSubElement;
00362     }
00363 
00364 
00366 
00368     virtual void setSubElement(bool subElement)
00369     {
00370         IsSubElement = subElement;
00371     }
00372 
00373 
00375 
00377     void setTabStop(bool enable)
00378     {
00379         IsTabStop = enable;
00380     }
00381 
00382 
00384     bool isTabStop() const
00385     {
00386         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00387         return IsTabStop;
00388     }
00389 
00390 
00392 
00394     void setTabOrder(s32 index)
00395     {
00396         // negative = autonumber
00397         if (index < 0)
00398         {
00399             TabOrder = 0;
00400             IGUIElement *el = getTabGroup();
00401             while (IsTabGroup && el && el->Parent)
00402                 el = el->Parent;
00403 
00404             IGUIElement *first=0, *closest=0;
00405             if (el)
00406             {
00407                 // find the highest element number
00408                 el->getNextElement(-1, true, IsTabGroup, first, closest, true);
00409                 if (first)
00410                 {
00411                     TabOrder = first->getTabOrder() + 1;
00412                 }
00413             }
00414 
00415         }
00416         else
00417             TabOrder = index;
00418     }
00419 
00420 
00422     s32 getTabOrder() const
00423     {
00424         return TabOrder;
00425     }
00426 
00427 
00429 
00431     void setTabGroup(bool isGroup)
00432     {
00433         IsTabGroup = isGroup;
00434     }
00435 
00436 
00438     bool isTabGroup() const
00439     {
00440         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00441         return IsTabGroup;
00442     }
00443 
00444 
00446     IGUIElement* getTabGroup()
00447     {
00448         IGUIElement *ret=this;
00449 
00450         while (ret && !ret->isTabGroup())
00451             ret = ret->getParent();
00452 
00453         return ret;
00454     }
00455 
00456 
00458 
00462     virtual bool isEnabled() const
00463     {
00464         if ( isSubElement() && IsEnabled && getParent() )
00465             return getParent()->isEnabled();
00466 
00467         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00468         return IsEnabled;
00469     }
00470 
00471 
00473     virtual void setEnabled(bool enabled)
00474     {
00475         IsEnabled = enabled;
00476     }
00477 
00478 
00480     virtual void setText(const wchar_t* text)
00481     {
00482         Text = text;
00483     }
00484 
00485 
00487     virtual const wchar_t* getText() const
00488     {
00489         return Text.c_str();
00490     }
00491 
00492 
00494     virtual void setToolTipText(const wchar_t* text)
00495     {
00496         ToolTipText = text;
00497     }
00498 
00499 
00501     virtual const core::stringw& getToolTipText() const
00502     {
00503         return ToolTipText;
00504     }
00505 
00506 
00508     virtual s32 getID() const
00509     {
00510         return ID;
00511     }
00512 
00513 
00515     virtual void setID(s32 id)
00516     {
00517         ID = id;
00518     }
00519 
00520 
00522     virtual bool OnEvent(const SEvent& event)
00523     {
00524         return Parent ? Parent->OnEvent(event) : false;
00525     }
00526 
00527 
00529 
00530     virtual bool bringToFront(IGUIElement* element)
00531     {
00532         core::list<IGUIElement*>::Iterator it = Children.begin();
00533         for (; it != Children.end(); ++it)
00534         {
00535             if (element == (*it))
00536             {
00537                 Children.erase(it);
00538                 Children.push_back(element);
00539                 return true;
00540             }
00541         }
00542 
00543         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00544         return false;
00545     }
00546 
00547 
00549 
00550     virtual bool sendToBack(IGUIElement* child)
00551     {
00552         core::list<IGUIElement*>::Iterator it = Children.begin();
00553         if (child == (*it)) // already there
00554             return true;
00555         for (; it != Children.end(); ++it)
00556         {
00557             if (child == (*it))
00558             {
00559                 Children.erase(it);
00560                 Children.push_front(child);
00561                 return true;
00562             }
00563         }
00564 
00565         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00566         return false;
00567     }
00568 
00570     virtual const core::list<IGUIElement*>& getChildren() const
00571     {
00572         return Children;
00573     }
00574 
00575 
00577 
00583     virtual IGUIElement* getElementFromId(s32 id, bool searchchildren=false) const
00584     {
00585         IGUIElement* e = 0;
00586 
00587         core::list<IGUIElement*>::ConstIterator it = Children.begin();
00588         for (; it != Children.end(); ++it)
00589         {
00590             if ((*it)->getID() == id)
00591                 return (*it);
00592 
00593             if (searchchildren)
00594                 e = (*it)->getElementFromId(id, true);
00595 
00596             if (e)
00597                 return e;
00598         }
00599 
00600         return e;
00601     }
00602 
00603 
00606     bool isMyChild(IGUIElement* child) const
00607     {
00608         if (!child)
00609             return false;
00610         do
00611         {
00612             if (child->Parent)
00613                 child = child->Parent;
00614 
00615         } while (child->Parent && child != this);
00616 
00617         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00618         return child == this;
00619     }
00620 
00621 
00623 
00630     bool getNextElement(s32 startOrder, bool reverse, bool group,
00631         IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const
00632     {
00633         // we'll stop searching if we find this number
00634         s32 wanted = startOrder + ( reverse ? -1 : 1 );
00635         if (wanted==-2)
00636             wanted = 1073741824; // maximum s32
00637 
00638         core::list<IGUIElement*>::ConstIterator it = Children.begin();
00639 
00640         s32 closestOrder, currentOrder;
00641 
00642         while(it != Children.end())
00643         {
00644             // ignore invisible elements and their children
00645             if ( ( (*it)->isVisible() || includeInvisible ) &&
00646                 (group == true || (*it)->isTabGroup() == false) )
00647             {
00648                 // only check tab stops and those with the same group status
00649                 if ((*it)->isTabStop() && ((*it)->isTabGroup() == group))
00650                 {
00651                     currentOrder = (*it)->getTabOrder();
00652 
00653                     // is this what we're looking for?
00654                     if (currentOrder == wanted)
00655                     {
00656                         closest = *it;
00657                         return true;
00658                     }
00659 
00660                     // is it closer than the current closest?
00661                     if (closest)
00662                     {
00663                         closestOrder = closest->getTabOrder();
00664                         if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder)
00665                             ||(!reverse && currentOrder < closestOrder && currentOrder > startOrder))
00666                         {
00667                             closest = *it;
00668                         }
00669                     }
00670                     else
00671                     if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) )
00672                     {
00673                         closest = *it;
00674                     }
00675 
00676                     // is it before the current first?
00677                     if (first)
00678                     {
00679                         closestOrder = first->getTabOrder();
00680 
00681                         if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) )
00682                         {
00683                             first = *it;
00684                         }
00685                     }
00686                     else
00687                     {
00688                         first = *it;
00689                     }
00690                 }
00691                 // search within children
00692                 if ((*it)->getNextElement(startOrder, reverse, group, first, closest))
00693                 {
00694                     _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00695                     return true;
00696                 }
00697             }
00698             ++it;
00699         }
00700         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
00701         return false;
00702     }
00703 
00704 
00706 
00710     EGUI_ELEMENT_TYPE getType() const
00711     {
00712         return Type;
00713     }
00714 
00716 
00724     virtual bool hasType(EGUI_ELEMENT_TYPE type) const
00725     {
00726         return type == Type;
00727     }
00728 
00729 
00731 
00733     virtual const c8* getTypeName() const
00734     {
00735         return GUIElementTypeNames[Type];
00736     }
00737     
00739 
00740     virtual const c8* getName() const
00741     {
00742         return Name.c_str();
00743     }
00744 
00745 
00747 
00748     virtual void setName(const c8* name)
00749     {
00750         Name = name;
00751     }
00752 
00753 
00755 
00756     virtual void setName(const core::stringc& name)
00757     {
00758         Name = name;
00759     }
00760 
00761 
00763 
00765     virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
00766     {
00767         out->addString("Name", Name.c_str());       
00768         out->addInt("Id", ID );
00769         out->addString("Caption", getText());
00770         out->addRect("Rect", DesiredRect);
00771         out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height));
00772         out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height));
00773         out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames);
00774         out->addEnum("RightAlign", AlignRight, GUIAlignmentNames);
00775         out->addEnum("TopAlign", AlignTop, GUIAlignmentNames);
00776         out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames);
00777         out->addBool("Visible", IsVisible);
00778         out->addBool("Enabled", IsEnabled);
00779         out->addBool("TabStop", IsTabStop);
00780         out->addBool("TabGroup", IsTabGroup);
00781         out->addInt("TabOrder", TabOrder);
00782         out->addBool("NoClip", NoClip);
00783     }
00784 
00785 
00787 
00789     virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
00790     {
00791         setName(in->getAttributeAsString("Name"));
00792         setID(in->getAttributeAsInt("Id"));
00793         setText(in->getAttributeAsStringW("Caption").c_str());
00794         setVisible(in->getAttributeAsBool("Visible"));
00795         setEnabled(in->getAttributeAsBool("Enabled"));
00796         IsTabStop = in->getAttributeAsBool("TabStop");
00797         IsTabGroup = in->getAttributeAsBool("TabGroup");
00798         TabOrder = in->getAttributeAsInt("TabOrder");
00799 
00800         core::position2di p = in->getAttributeAsPosition2d("MaxSize");
00801         setMaxSize(core::dimension2du(p.X,p.Y));
00802 
00803         p = in->getAttributeAsPosition2d("MinSize");
00804         setMinSize(core::dimension2du(p.X,p.Y));
00805 
00806         setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames),
00807             (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames),
00808             (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames),
00809             (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames));
00810 
00811         setRelativePosition(in->getAttributeAsRect("Rect"));
00812 
00813         setNotClipped(in->getAttributeAsBool("NoClip"));
00814     }
00815 
00816 protected:
00817     // not virtual because needed in constructor
00818     void addChildToEnd(IGUIElement* child)
00819     {
00820         if (child)
00821         {
00822             child->grab(); // prevent destruction when removed
00823             child->remove(); // remove from old parent
00824             child->LastParentRect = getAbsolutePosition();
00825             child->Parent = this;
00826             Children.push_back(child);
00827         }
00828     }
00829 
00830     // not virtual because needed in constructor
00831     void recalculateAbsolutePosition(bool recursive)
00832     {
00833         core::rect<s32> parentAbsolute(0,0,0,0);
00834         core::rect<s32> parentAbsoluteClip;
00835         f32 fw=0.f, fh=0.f;
00836 
00837         if (Parent)
00838         {
00839             parentAbsolute = Parent->AbsoluteRect;
00840 
00841             if (NoClip)
00842             {
00843                 IGUIElement* p=this;
00844                 while (p && p->Parent)
00845                     p = p->Parent;
00846                 parentAbsoluteClip = p->AbsoluteClippingRect;
00847             }
00848             else
00849                 parentAbsoluteClip = Parent->AbsoluteClippingRect;
00850         }
00851 
00852         const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
00853         const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
00854 
00855         if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE)
00856             fw = (f32)parentAbsolute.getWidth();
00857 
00858         if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE)
00859             fh = (f32)parentAbsolute.getHeight();
00860 
00861         switch (AlignLeft)
00862         {
00863             case EGUIA_UPPERLEFT:
00864                 break;
00865             case EGUIA_LOWERRIGHT:
00866                 DesiredRect.UpperLeftCorner.X += diffx;
00867                 break;
00868             case EGUIA_CENTER:
00869                 DesiredRect.UpperLeftCorner.X += diffx/2;
00870                 break;
00871             case EGUIA_SCALE:
00872                 DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw);
00873                 break;
00874         }
00875 
00876         switch (AlignRight)
00877         {
00878             case EGUIA_UPPERLEFT:
00879                 break;
00880             case EGUIA_LOWERRIGHT:
00881                 DesiredRect.LowerRightCorner.X += diffx;
00882                 break;
00883             case EGUIA_CENTER:
00884                 DesiredRect.LowerRightCorner.X += diffx/2;
00885                 break;
00886             case EGUIA_SCALE:
00887                 DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw);
00888                 break;
00889         }
00890 
00891         switch (AlignTop)
00892         {
00893             case EGUIA_UPPERLEFT:
00894                 break;
00895             case EGUIA_LOWERRIGHT:
00896                 DesiredRect.UpperLeftCorner.Y += diffy;
00897                 break;
00898             case EGUIA_CENTER:
00899                 DesiredRect.UpperLeftCorner.Y += diffy/2;
00900                 break;
00901             case EGUIA_SCALE:
00902                 DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh);
00903                 break;
00904         }
00905 
00906         switch (AlignBottom)
00907         {
00908             case EGUIA_UPPERLEFT:
00909                 break;
00910             case EGUIA_LOWERRIGHT:
00911                 DesiredRect.LowerRightCorner.Y += diffy;
00912                 break;
00913             case EGUIA_CENTER:
00914                 DesiredRect.LowerRightCorner.Y += diffy/2;
00915                 break;
00916             case EGUIA_SCALE:
00917                 DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh);
00918                 break;
00919         }
00920 
00921         RelativeRect = DesiredRect;
00922 
00923         const s32 w = RelativeRect.getWidth();
00924         const s32 h = RelativeRect.getHeight();
00925 
00926         // make sure the desired rectangle is allowed
00927         if (w < (s32)MinSize.Width)
00928             RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width;
00929         if (h < (s32)MinSize.Height)
00930             RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height;
00931         if (MaxSize.Width && w > (s32)MaxSize.Width)
00932             RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width;
00933         if (MaxSize.Height && h > (s32)MaxSize.Height)
00934             RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height;
00935 
00936         RelativeRect.repair();
00937 
00938         AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
00939 
00940         if (!Parent)
00941             parentAbsoluteClip = AbsoluteRect;
00942 
00943         AbsoluteClippingRect = AbsoluteRect;
00944         AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
00945 
00946         LastParentRect = parentAbsolute;
00947 
00948         if ( recursive )
00949         {
00950             // update all children
00951             core::list<IGUIElement*>::Iterator it = Children.begin();
00952             for (; it != Children.end(); ++it)
00953             {
00954                 (*it)->recalculateAbsolutePosition(recursive);
00955             }
00956         }
00957     }
00958 
00959 protected:
00960 
00962     core::list<IGUIElement*> Children;
00963 
00965     IGUIElement* Parent;
00966 
00968     core::rect<s32> RelativeRect;
00969 
00971     core::rect<s32> AbsoluteRect;
00972 
00974     core::rect<s32> AbsoluteClippingRect;
00975 
00978     core::rect<s32> DesiredRect;
00979 
00981     core::rect<s32> LastParentRect;
00982 
00984     core::rect<f32> ScaleRect;
00985 
00987     core::dimension2du MaxSize, MinSize;
00988 
00990     bool IsVisible;
00991 
00993     bool IsEnabled;
00994 
00996     bool IsSubElement;
00997 
00999     bool NoClip;
01000 
01002     core::stringw Text;
01003 
01005     core::stringw ToolTipText;
01006     
01008     core::stringc Name;
01009 
01011     s32 ID;
01012 
01014     bool IsTabStop;
01015 
01017     s32 TabOrder;
01018 
01020     bool IsTabGroup;
01021 
01023     EGUI_ALIGNMENT AlignLeft, AlignRight, AlignTop, AlignBottom;
01024 
01026     IGUIEnvironment* Environment;
01027 
01029     EGUI_ELEMENT_TYPE Type;
01030 };
01031 
01032 
01033 } // end namespace gui
01034 } // end namespace irr
01035 
01036 #endif
01037