Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials
IGUIElement.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2010 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 
9 #include "irrList.h"
10 #include "rect.h"
11 #include "irrString.h"
12 #include "IEventReceiver.h"
13 #include "EGUIElementTypes.h"
14 #include "EGUIAlignment.h"
15 #include "IAttributes.h"
16 
17 namespace irr
18 {
19 namespace gui
20 {
21 
22 class IGUIEnvironment;
23 
26 {
27 public:
28 
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),
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);
48  }
49  }
50 
51 
53  virtual ~IGUIElement()
54  {
55  // delete all children
57  for (; it != Children.end(); ++it)
58  {
59  (*it)->Parent = 0;
60  (*it)->drop();
61  }
62  }
63 
64 
67  {
68  return Parent;
69  }
70 
71 
74  {
75  return RelativeRect;
76  }
77 
78 
80 
82  {
83  if (Parent)
84  {
86 
87  core::dimension2df d((f32)(r2.getSize().Width), (f32)(r2.getSize().Height));
88 
89  if (AlignLeft == EGUIA_SCALE)
91  if (AlignRight == EGUIA_SCALE)
93  if (AlignTop == EGUIA_SCALE)
95  if (AlignBottom == EGUIA_SCALE)
97  }
98 
99  DesiredRect = r;
101  }
102 
104 
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 
115 
120  {
121  if (!Parent)
122  return;
123 
125 
131 
132  ScaleRect = r;
133 
135  }
136 
137 
140  {
141  return AbsoluteRect;
142  }
143 
144 
147  {
148  return AbsoluteClippingRect;
149  }
150 
151 
153 
154  void setNotClipped(bool noClip)
155  {
156  NoClip = noClip;
158  }
159 
160 
162 
163  bool isNotClipped() const
164  {
165  return NoClip;
166  }
167 
168 
170 
172  {
173  MaxSize = size;
175  }
176 
177 
180  {
181  MinSize = size;
182  if (MinSize.Width < 1)
183  MinSize.Width = 1;
184  if (MinSize.Height < 1)
185  MinSize.Height = 1;
187  }
188 
189 
192  {
193  AlignLeft = left;
194  AlignRight = right;
195  AlignTop = top;
196  AlignBottom = bottom;
197 
198  if (Parent)
199  {
201 
202  core::dimension2df d((f32)r.getSize().Width, (f32)r.getSize().Height);
203 
204  if (AlignLeft == EGUIA_SCALE)
206  if (AlignRight == EGUIA_SCALE)
208  if (AlignTop == EGUIA_SCALE)
210  if (AlignBottom == EGUIA_SCALE)
212  }
213  }
214 
215 
217  virtual void updateAbsolutePosition()
218  {
220 
221  // update all children
223  for (; it != Children.end(); ++it)
224  {
225  (*it)->updateAbsolutePosition();
226  }
227  }
228 
229 
231 
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 
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 
271 
272  virtual bool isPointInside(const core::position2d<s32>& point) const
273  {
274  return AbsoluteClippingRect.isPointInside(point);
275  }
276 
277 
279  virtual void addChild(IGUIElement* child)
280  {
281  addChildToEnd(child);
282  if (child)
283  {
284  child->updateAbsolutePosition();
285  }
286  }
287 
289  virtual void removeChild(IGUIElement* child)
290  {
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 
304  virtual void remove()
305  {
306  if (Parent)
307  Parent->removeChild(this);
308  }
309 
310 
312  virtual void draw()
313  {
314  if ( isVisible() )
315  {
317  for (; it != Children.end(); ++it)
318  (*it)->draw();
319  }
320  }
321 
322 
324  virtual void OnPostRender(u32 timeMs)
325  {
326  if ( isVisible() )
327  {
329  for (; it != Children.end(); ++it)
330  (*it)->OnPostRender( timeMs );
331  }
332  }
333 
334 
336  virtual void move(core::position2d<s32> absoluteMovement)
337  {
338  setRelativePosition(DesiredRect + absoluteMovement);
339  }
340 
341 
343  virtual bool isVisible() const
344  {
346  return IsVisible;
347  }
348 
349 
351  virtual void setVisible(bool visible)
352  {
353  IsVisible = visible;
354  }
355 
356 
358  virtual bool isSubElement() const
359  {
361  return IsSubElement;
362  }
363 
364 
366 
368  virtual void setSubElement(bool subElement)
369  {
370  IsSubElement = subElement;
371  }
372 
373 
375 
377  void setTabStop(bool enable)
378  {
379  IsTabStop = enable;
380  }
381 
382 
384  bool isTabStop() const
385  {
387  return IsTabStop;
388  }
389 
390 
392 
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 
422  s32 getTabOrder() const
423  {
424  return TabOrder;
425  }
426 
427 
429 
431  void setTabGroup(bool isGroup)
432  {
433  IsTabGroup = isGroup;
434  }
435 
436 
438  bool isTabGroup() const
439  {
441  return IsTabGroup;
442  }
443 
444 
447  {
448  IGUIElement *ret=this;
449 
450  while (ret && !ret->isTabGroup())
451  ret = ret->getParent();
452 
453  return ret;
454  }
455 
456 
458  virtual bool isEnabled() const
459  {
461  return IsEnabled;
462  }
463 
464 
466  virtual void setEnabled(bool enabled)
467  {
468  IsEnabled = enabled;
469  }
470 
471 
473  virtual void setText(const wchar_t* text)
474  {
475  Text = text;
476  }
477 
478 
480  virtual const wchar_t* getText() const
481  {
482  return Text.c_str();
483  }
484 
485 
487  virtual void setToolTipText(const wchar_t* text)
488  {
489  ToolTipText = text;
490  }
491 
492 
494  virtual const core::stringw& getToolTipText() const
495  {
496  return ToolTipText;
497  }
498 
499 
501  virtual s32 getID() const
502  {
503  return ID;
504  }
505 
506 
508  virtual void setID(s32 id)
509  {
510  ID = id;
511  }
512 
513 
515  virtual bool OnEvent(const SEvent& event)
516  {
517  return Parent ? Parent->OnEvent(event) : false;
518  }
519 
520 
522 
523  virtual bool bringToFront(IGUIElement* element)
524  {
526  for (; it != Children.end(); ++it)
527  {
528  if (element == (*it))
529  {
530  Children.erase(it);
531  Children.push_back(element);
532  return true;
533  }
534  }
535 
537  return false;
538  }
539 
540 
542  virtual const core::list<IGUIElement*>& getChildren() const
543  {
544  return Children;
545  }
546 
547 
549 
555  virtual IGUIElement* getElementFromId(s32 id, bool searchchildren=false) const
556  {
557  IGUIElement* e = 0;
558 
560  for (; it != Children.end(); ++it)
561  {
562  if ((*it)->getID() == id)
563  return (*it);
564 
565  if (searchchildren)
566  e = (*it)->getElementFromId(id, true);
567 
568  if (e)
569  return e;
570  }
571 
572  return e;
573  }
574 
575 
578  bool isMyChild(IGUIElement* child) const
579  {
580  if (!child)
581  return false;
582  do
583  {
584  if (child->Parent)
585  child = child->Parent;
586 
587  } while (child->Parent && child != this);
588 
590  return child == this;
591  }
592 
593 
595 
602  bool getNextElement(s32 startOrder, bool reverse, bool group,
603  IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const
604  {
605  // we'll stop searching if we find this number
606  s32 wanted = startOrder + ( reverse ? -1 : 1 );
607  if (wanted==-2)
608  wanted = 1073741824; // maximum s32
609 
611 
612  s32 closestOrder, currentOrder;
613 
614  while(it != Children.end())
615  {
616  // ignore invisible elements and their children
617  if ( ( (*it)->isVisible() || includeInvisible ) &&
618  (group == true || (*it)->isTabGroup() == false) )
619  {
620  // only check tab stops and those with the same group status
621  if ((*it)->isTabStop() && ((*it)->isTabGroup() == group))
622  {
623  currentOrder = (*it)->getTabOrder();
624 
625  // is this what we're looking for?
626  if (currentOrder == wanted)
627  {
628  closest = *it;
629  return true;
630  }
631 
632  // is it closer than the current closest?
633  if (closest)
634  {
635  closestOrder = closest->getTabOrder();
636  if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder)
637  ||(!reverse && currentOrder < closestOrder && currentOrder > startOrder))
638  {
639  closest = *it;
640  }
641  }
642  else
643  if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) )
644  {
645  closest = *it;
646  }
647 
648  // is it before the current first?
649  if (first)
650  {
651  closestOrder = first->getTabOrder();
652 
653  if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) )
654  {
655  first = *it;
656  }
657  }
658  else
659  {
660  first = *it;
661  }
662  }
663  // search within children
664  if ((*it)->getNextElement(startOrder, reverse, group, first, closest))
665  {
667  return true;
668  }
669  }
670  ++it;
671  }
673  return false;
674  }
675 
676 
678 
683  {
684  return Type;
685  }
686 
688 
696  virtual bool hasType(EGUI_ELEMENT_TYPE type) const
697  {
698  return type == Type;
699  }
700 
701 
703 
705  virtual const c8* getTypeName() const
706  {
707  return GUIElementTypeNames[Type];
708  }
709 
710 
712 
715  {
716  out->addInt("Id", ID );
717  out->addString("Caption", getText());
718  out->addRect("Rect", DesiredRect);
721  out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames);
722  out->addEnum("RightAlign", AlignRight, GUIAlignmentNames);
723  out->addEnum("TopAlign", AlignTop, GUIAlignmentNames);
724  out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames);
725  out->addBool("Visible", IsVisible);
726  out->addBool("Enabled", IsEnabled);
727  out->addBool("TabStop", IsTabStop);
728  out->addBool("TabGroup", IsTabGroup);
729  out->addInt("TabOrder", TabOrder);
730  out->addBool("NoClip", NoClip);
731  }
732 
733 
735 
738  {
739  setID(in->getAttributeAsInt("Id"));
740  setText(in->getAttributeAsStringW("Caption").c_str());
741  setVisible(in->getAttributeAsBool("Visible"));
742  setEnabled(in->getAttributeAsBool("Enabled"));
743  IsTabStop = in->getAttributeAsBool("TabStop");
744  IsTabGroup = in->getAttributeAsBool("TabGroup");
745  TabOrder = in->getAttributeAsInt("TabOrder");
746 
747  core::position2di p = in->getAttributeAsPosition2d("MaxSize");
749 
750  p = in->getAttributeAsPosition2d("MinSize");
752 
757 
759 
760  setNotClipped(in->getAttributeAsBool("NoClip"));
761  }
762 
763 protected:
764  // not virtual because needed in constructor
766  {
767  if (child)
768  {
769  child->grab(); // prevent destruction when removed
770  child->remove(); // remove from old parent
772  child->Parent = this;
773  Children.push_back(child);
774  }
775  }
776 
777  // not virtual because needed in constructor
778  void recalculateAbsolutePosition(bool recursive)
779  {
780  core::rect<s32> parentAbsolute(0,0,0,0);
781  core::rect<s32> parentAbsoluteClip;
782  f32 fw=0.f, fh=0.f;
783 
784  if (Parent)
785  {
786  parentAbsolute = Parent->AbsoluteRect;
787 
788  if (NoClip)
789  {
790  IGUIElement* p=this;
791  while (p && p->Parent)
792  p = p->Parent;
793  parentAbsoluteClip = p->AbsoluteClippingRect;
794  }
795  else
796  parentAbsoluteClip = Parent->AbsoluteClippingRect;
797  }
798 
799  const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
800  const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
801 
803  fw = (f32)parentAbsolute.getWidth();
804 
806  fh = (f32)parentAbsolute.getHeight();
807 
808  switch (AlignLeft)
809  {
810  case EGUIA_UPPERLEFT:
811  break;
812  case EGUIA_LOWERRIGHT:
813  DesiredRect.UpperLeftCorner.X += diffx;
814  break;
815  case EGUIA_CENTER:
816  DesiredRect.UpperLeftCorner.X += diffx/2;
817  break;
818  case EGUIA_SCALE:
820  break;
821  }
822 
823  switch (AlignRight)
824  {
825  case EGUIA_UPPERLEFT:
826  break;
827  case EGUIA_LOWERRIGHT:
828  DesiredRect.LowerRightCorner.X += diffx;
829  break;
830  case EGUIA_CENTER:
831  DesiredRect.LowerRightCorner.X += diffx/2;
832  break;
833  case EGUIA_SCALE:
835  break;
836  }
837 
838  switch (AlignTop)
839  {
840  case EGUIA_UPPERLEFT:
841  break;
842  case EGUIA_LOWERRIGHT:
843  DesiredRect.UpperLeftCorner.Y += diffy;
844  break;
845  case EGUIA_CENTER:
846  DesiredRect.UpperLeftCorner.Y += diffy/2;
847  break;
848  case EGUIA_SCALE:
850  break;
851  }
852 
853  switch (AlignBottom)
854  {
855  case EGUIA_UPPERLEFT:
856  break;
857  case EGUIA_LOWERRIGHT:
858  DesiredRect.LowerRightCorner.Y += diffy;
859  break;
860  case EGUIA_CENTER:
861  DesiredRect.LowerRightCorner.Y += diffy/2;
862  break;
863  case EGUIA_SCALE:
865  break;
866  }
867 
869 
870  const s32 w = RelativeRect.getWidth();
871  const s32 h = RelativeRect.getHeight();
872 
873  // make sure the desired rectangle is allowed
874  if (w < (s32)MinSize.Width)
876  if (h < (s32)MinSize.Height)
878  if (MaxSize.Width && w > (s32)MaxSize.Width)
880  if (MaxSize.Height && h > (s32)MaxSize.Height)
882 
884 
885  AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
886 
887  if (!Parent)
888  parentAbsoluteClip = AbsoluteRect;
889 
891  AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
892 
893  LastParentRect = parentAbsolute;
894 
895  if ( recursive )
896  {
897  // update all children
899  for (; it != Children.end(); ++it)
900  {
901  (*it)->recalculateAbsolutePosition(recursive);
902  }
903  }
904  }
905 
906 protected:
907 
910 
913 
916 
919 
922 
926 
929 
932 
935 
937  bool IsVisible;
938 
940  bool IsEnabled;
941 
944 
946  bool NoClip;
947 
950 
953 
956 
958  bool IsTabStop;
959 
962 
965 
968 
971 
974 };
975 
976 
977 } // end namespace gui
978 } // end namespace irr
979 
980 #endif
981 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Tue Jun 5 2012 17:57:11 by Doxygen (1.8.1)