| 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