IrrlichtEngine
IGUIElement.h
Go to the documentation of this file.
00001 // Copyright (C) 2002-2011 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 
00738 
00740 
00742         virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
00743         {
00744                 out->addInt("Id", ID );
00745                 out->addString("Caption", getText());
00746                 out->addRect("Rect", DesiredRect);
00747                 out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height));
00748                 out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height));
00749                 out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames);
00750                 out->addEnum("RightAlign", AlignRight, GUIAlignmentNames);
00751                 out->addEnum("TopAlign", AlignTop, GUIAlignmentNames);
00752                 out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames);
00753                 out->addBool("Visible", IsVisible);
00754                 out->addBool("Enabled", IsEnabled);
00755                 out->addBool("TabStop", IsTabStop);
00756                 out->addBool("TabGroup", IsTabGroup);
00757                 out->addInt("TabOrder", TabOrder);
00758                 out->addBool("NoClip", NoClip);
00759         }
00760 
00761 
00763 
00765         virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
00766         {
00767                 setID(in->getAttributeAsInt("Id"));
00768                 setText(in->getAttributeAsStringW("Caption").c_str());
00769                 setVisible(in->getAttributeAsBool("Visible"));
00770                 setEnabled(in->getAttributeAsBool("Enabled"));
00771                 IsTabStop = in->getAttributeAsBool("TabStop");
00772                 IsTabGroup = in->getAttributeAsBool("TabGroup");
00773                 TabOrder = in->getAttributeAsInt("TabOrder");
00774 
00775                 core::position2di p = in->getAttributeAsPosition2d("MaxSize");
00776                 setMaxSize(core::dimension2du(p.X,p.Y));
00777 
00778                 p = in->getAttributeAsPosition2d("MinSize");
00779                 setMinSize(core::dimension2du(p.X,p.Y));
00780 
00781                 setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames),
00782                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames),
00783                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames),
00784                         (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames));
00785 
00786                 setRelativePosition(in->getAttributeAsRect("Rect"));
00787 
00788                 setNotClipped(in->getAttributeAsBool("NoClip"));
00789         }
00790 
00791 protected:
00792         // not virtual because needed in constructor
00793         void addChildToEnd(IGUIElement* child)
00794         {
00795                 if (child)
00796                 {
00797                         child->grab(); // prevent destruction when removed
00798                         child->remove(); // remove from old parent
00799                         child->LastParentRect = getAbsolutePosition();
00800                         child->Parent = this;
00801                         Children.push_back(child);
00802                 }
00803         }
00804 
00805         // not virtual because needed in constructor
00806         void recalculateAbsolutePosition(bool recursive)
00807         {
00808                 core::rect<s32> parentAbsolute(0,0,0,0);
00809                 core::rect<s32> parentAbsoluteClip;
00810                 f32 fw=0.f, fh=0.f;
00811 
00812                 if (Parent)
00813                 {
00814                         parentAbsolute = Parent->AbsoluteRect;
00815 
00816                         if (NoClip)
00817                         {
00818                                 IGUIElement* p=this;
00819                                 while (p && p->Parent)
00820                                         p = p->Parent;
00821                                 parentAbsoluteClip = p->AbsoluteClippingRect;
00822                         }
00823                         else
00824                                 parentAbsoluteClip = Parent->AbsoluteClippingRect;
00825                 }
00826 
00827                 const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
00828                 const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
00829 
00830                 if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE)
00831                         fw = (f32)parentAbsolute.getWidth();
00832 
00833                 if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE)
00834                         fh = (f32)parentAbsolute.getHeight();
00835 
00836                 switch (AlignLeft)
00837                 {
00838                         case EGUIA_UPPERLEFT:
00839                                 break;
00840                         case EGUIA_LOWERRIGHT:
00841                                 DesiredRect.UpperLeftCorner.X += diffx;
00842                                 break;
00843                         case EGUIA_CENTER:
00844                                 DesiredRect.UpperLeftCorner.X += diffx/2;
00845                                 break;
00846                         case EGUIA_SCALE:
00847                                 DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw);
00848                                 break;
00849                 }
00850 
00851                 switch (AlignRight)
00852                 {
00853                         case EGUIA_UPPERLEFT:
00854                                 break;
00855                         case EGUIA_LOWERRIGHT:
00856                                 DesiredRect.LowerRightCorner.X += diffx;
00857                                 break;
00858                         case EGUIA_CENTER:
00859                                 DesiredRect.LowerRightCorner.X += diffx/2;
00860                                 break;
00861                         case EGUIA_SCALE:
00862                                 DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw);
00863                                 break;
00864                 }
00865 
00866                 switch (AlignTop)
00867                 {
00868                         case EGUIA_UPPERLEFT:
00869                                 break;
00870                         case EGUIA_LOWERRIGHT:
00871                                 DesiredRect.UpperLeftCorner.Y += diffy;
00872                                 break;
00873                         case EGUIA_CENTER:
00874                                 DesiredRect.UpperLeftCorner.Y += diffy/2;
00875                                 break;
00876                         case EGUIA_SCALE:
00877                                 DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh);
00878                                 break;
00879                 }
00880 
00881                 switch (AlignBottom)
00882                 {
00883                         case EGUIA_UPPERLEFT:
00884                                 break;
00885                         case EGUIA_LOWERRIGHT:
00886                                 DesiredRect.LowerRightCorner.Y += diffy;
00887                                 break;
00888                         case EGUIA_CENTER:
00889                                 DesiredRect.LowerRightCorner.Y += diffy/2;
00890                                 break;
00891                         case EGUIA_SCALE:
00892                                 DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh);
00893                                 break;
00894                 }
00895 
00896                 RelativeRect = DesiredRect;
00897 
00898                 const s32 w = RelativeRect.getWidth();
00899                 const s32 h = RelativeRect.getHeight();
00900 
00901                 // make sure the desired rectangle is allowed
00902                 if (w < (s32)MinSize.Width)
00903                         RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width;
00904                 if (h < (s32)MinSize.Height)
00905                         RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height;
00906                 if (MaxSize.Width && w > (s32)MaxSize.Width)
00907                         RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width;
00908                 if (MaxSize.Height && h > (s32)MaxSize.Height)
00909                         RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height;
00910 
00911                 RelativeRect.repair();
00912 
00913                 AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
00914 
00915                 if (!Parent)
00916                         parentAbsoluteClip = AbsoluteRect;
00917 
00918                 AbsoluteClippingRect = AbsoluteRect;
00919                 AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
00920 
00921                 LastParentRect = parentAbsolute;
00922 
00923                 if ( recursive )
00924                 {
00925                         // update all children
00926                         core::list<IGUIElement*>::Iterator it = Children.begin();
00927                         for (; it != Children.end(); ++it)
00928                         {
00929                                 (*it)->recalculateAbsolutePosition(recursive);
00930                         }
00931                 }
00932         }
00933 
00934 protected:
00935 
00937         core::list<IGUIElement*> Children;
00938 
00940         IGUIElement* Parent;
00941 
00943         core::rect<s32> RelativeRect;
00944 
00946         core::rect<s32> AbsoluteRect;
00947 
00949         core::rect<s32> AbsoluteClippingRect;
00950 
00953         core::rect<s32> DesiredRect;
00954 
00956         core::rect<s32> LastParentRect;
00957 
00959         core::rect<f32> ScaleRect;
00960 
00962         core::dimension2du MaxSize, MinSize;
00963 
00965         bool IsVisible;
00966 
00968         bool IsEnabled;
00969 
00971         bool IsSubElement;
00972 
00974         bool NoClip;
00975 
00977         core::stringw Text;
00978 
00980         core::stringw ToolTipText;
00981 
00983         s32 ID;
00984 
00986         bool IsTabStop;
00987 
00989         s32 TabOrder;
00990 
00992         bool IsTabGroup;
00993 
00995         EGUI_ALIGNMENT AlignLeft, AlignRight, AlignTop, AlignBottom;
00996 
00998         IGUIEnvironment* Environment;
00999 
01001         EGUI_ELEMENT_TYPE Type;
01002 };
01003 
01004 
01005 } // end namespace gui
01006 } // end namespace irr
01007 
01008 #endif
01009