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