]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUIEnvironment.cpp
Drop obsolete configuration macros
[irrlicht.git] / source / Irrlicht / CGUIEnvironment.cpp
1 \r
2 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
3 // This file is part of the "Irrlicht Engine".\r
4 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
5 \r
6 #include "CGUIEnvironment.h"\r
7 \r
8 #ifdef _IRR_COMPILE_WITH_GUI_\r
9 \r
10 #include "IVideoDriver.h"\r
11 \r
12 #include "CGUISkin.h"\r
13 #include "CGUIButton.h"\r
14 #include "CGUIScrollBar.h"\r
15 #include "CGUIFont.h"\r
16 #include "CGUISpriteBank.h"\r
17 #include "CGUIImage.h"\r
18 #include "CGUICheckBox.h"\r
19 #include "CGUIListBox.h"\r
20 #include "CGUIImageList.h"\r
21 #include "CGUIFileOpenDialog.h"\r
22 #include "CGUIStaticText.h"\r
23 #include "CGUIEditBox.h"\r
24 #include "CGUITabControl.h"\r
25 #include "CGUIComboBox.h"\r
26 \r
27 #include "IWriteFile.h"\r
28 #ifdef IRR_ENABLE_BUILTIN_FONT\r
29 #include "BuiltInFont.h"\r
30 #endif\r
31 #include "os.h"\r
32 \r
33 namespace irr\r
34 {\r
35 namespace gui\r
36 {\r
37 \r
38 const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont";\r
39 \r
40 //! constructor\r
41 CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op)\r
42 : IGUIElement(EGUIET_ROOT, 0, 0, 0, core::rect<s32>(driver ? core::dimension2d<s32>(driver->getScreenSize()) : core::dimension2d<s32>(0,0))),\r
43         Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0),\r
44         FileSystem(fs), UserReceiver(0), Operator(op), FocusFlags(EFF_SET_ON_LMOUSE_DOWN|EFF_SET_ON_TAB)\r
45 {\r
46         if (Driver)\r
47                 Driver->grab();\r
48 \r
49         if (FileSystem)\r
50                 FileSystem->grab();\r
51 \r
52         if (Operator)\r
53                 Operator->grab();\r
54 \r
55         #ifdef _DEBUG\r
56         IGUIEnvironment::setDebugName("CGUIEnvironment");\r
57         #endif\r
58 \r
59         loadBuiltInFont();\r
60 \r
61         IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC );\r
62         setSkin(skin);\r
63         skin->drop();\r
64 \r
65         //set tooltip default\r
66         ToolTip.LastTime = 0;\r
67         ToolTip.EnterTime = 0;\r
68         ToolTip.LaunchTime = 1000;\r
69         ToolTip.RelaunchTime = 500;\r
70         ToolTip.Element = 0;\r
71 \r
72         // environment is root tab group\r
73         Environment = this;\r
74         setTabGroup(true);\r
75 }\r
76 \r
77 \r
78 //! destructor\r
79 CGUIEnvironment::~CGUIEnvironment()\r
80 {\r
81         clearDeletionQueue();\r
82 \r
83         if ( HoveredNoSubelement && HoveredNoSubelement != this )\r
84         {\r
85                 HoveredNoSubelement->drop();\r
86                 HoveredNoSubelement = 0;\r
87         }\r
88 \r
89         if (Hovered && Hovered != this)\r
90         {\r
91                 Hovered->drop();\r
92                 Hovered = 0;\r
93         }\r
94 \r
95         if (Focus)\r
96         {\r
97                 Focus->drop();\r
98                 Focus = 0;\r
99         }\r
100 \r
101         if (ToolTip.Element)\r
102         {\r
103                 ToolTip.Element->drop();\r
104                 ToolTip.Element = 0;\r
105         }\r
106 \r
107         // drop skin\r
108         if (CurrentSkin)\r
109         {\r
110                 CurrentSkin->drop();\r
111                 CurrentSkin = 0;\r
112         }\r
113 \r
114         u32 i;\r
115 \r
116         // delete all sprite banks\r
117         for (i=0; i<Banks.size(); ++i)\r
118                 if (Banks[i].Bank)\r
119                         Banks[i].Bank->drop();\r
120 \r
121         // delete all fonts\r
122         for (i=0; i<Fonts.size(); ++i)\r
123                 Fonts[i].Font->drop();\r
124 \r
125         if (Operator)\r
126         {\r
127                 Operator->drop();\r
128                 Operator = 0;\r
129         }\r
130 \r
131         if (FileSystem)\r
132         {\r
133                 FileSystem->drop();\r
134                 FileSystem = 0;\r
135         }\r
136 \r
137         if (Driver)\r
138         {\r
139                 Driver->drop();\r
140                 Driver = 0;\r
141         }\r
142 }\r
143 \r
144 \r
145 void CGUIEnvironment::loadBuiltInFont()\r
146 {\r
147 #ifdef IRR_ENABLE_BUILTIN_FONT\r
148         io::IReadFile* file = FileSystem->createMemoryReadFile(BuiltInFontData,\r
149                                 BuiltInFontDataSize, DefaultFontName, false);\r
150 \r
151         CGUIFont* font = new CGUIFont(this, DefaultFontName );\r
152         if (!font->load(file))\r
153         {\r
154                 os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR);\r
155                 font->drop();\r
156                 file->drop();\r
157                 return;\r
158         }\r
159 \r
160         SFont f;\r
161         f.NamedPath.setPath(DefaultFontName);\r
162         f.Font = font;\r
163         Fonts.push_back(f);\r
164 \r
165         file->drop();\r
166 #endif\r
167 }\r
168 \r
169 \r
170 //! draws all gui elements\r
171 void CGUIEnvironment::drawAll(bool useScreenSize)\r
172 {\r
173         if (useScreenSize && Driver)\r
174         {\r
175                 core::dimension2d<s32> dim(Driver->getScreenSize());\r
176                 if (AbsoluteRect.LowerRightCorner.X != dim.Width ||\r
177                         AbsoluteRect.UpperLeftCorner.X != 0 ||\r
178                         AbsoluteRect.LowerRightCorner.Y != dim.Height ||\r
179                         AbsoluteRect.UpperLeftCorner.Y != 0\r
180                         )\r
181                 {\r
182                         setRelativePosition(core::recti(0,0,dim.Width, dim.Height));\r
183                 }\r
184         }\r
185 \r
186         // make sure tooltip is always on top\r
187         if (ToolTip.Element)\r
188                 bringToFront(ToolTip.Element);\r
189 \r
190         draw();\r
191         OnPostRender ( os::Timer::getTime () );\r
192 \r
193         clearDeletionQueue();\r
194 }\r
195 \r
196 \r
197 //! sets the focus to an element\r
198 bool CGUIEnvironment::setFocus(IGUIElement* element)\r
199 {\r
200         if (Focus == element)\r
201         {\r
202                 return false;\r
203         }\r
204 \r
205         // GUI Environment should just reset the focus to 0\r
206         if (element == this)\r
207                 element = 0;\r
208 \r
209         // stop element from being deleted\r
210         if (element)\r
211                 element->grab();\r
212 \r
213         // focus may change or be removed in this call\r
214         IGUIElement *currentFocus = 0;\r
215         if (Focus)\r
216         {\r
217                 currentFocus = Focus;\r
218                 currentFocus->grab();\r
219                 SEvent e;\r
220                 e.EventType = EET_GUI_EVENT;\r
221                 e.GUIEvent.Caller = Focus;\r
222                 e.GUIEvent.Element = element;\r
223                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;\r
224                 if (Focus->OnEvent(e))\r
225                 {\r
226                         if (element)\r
227                                 element->drop();\r
228                         currentFocus->drop();\r
229                         return false;\r
230                 }\r
231                 currentFocus->drop();\r
232                 currentFocus = 0;\r
233         }\r
234 \r
235         if (element)\r
236         {\r
237                 currentFocus = Focus;\r
238                 if (currentFocus)\r
239                         currentFocus->grab();\r
240 \r
241                 // send focused event\r
242                 SEvent e;\r
243                 e.EventType = EET_GUI_EVENT;\r
244                 e.GUIEvent.Caller = element;\r
245                 e.GUIEvent.Element = Focus;\r
246                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUSED;\r
247                 if (element->OnEvent(e))\r
248                 {\r
249                         if (element)\r
250                                 element->drop();\r
251                         if (currentFocus)\r
252                                 currentFocus->drop();\r
253                         return false;\r
254                 }\r
255         }\r
256 \r
257         if (currentFocus)\r
258                 currentFocus->drop();\r
259 \r
260         if (Focus)\r
261                 Focus->drop();\r
262 \r
263         // element is the new focus so it doesn't have to be dropped\r
264         Focus = element;\r
265 \r
266         return true;\r
267 }\r
268 \r
269 \r
270 //! returns the element with the focus\r
271 IGUIElement* CGUIEnvironment::getFocus() const\r
272 {\r
273         return Focus;\r
274 }\r
275 \r
276 //! returns the element last known to be under the mouse cursor\r
277 IGUIElement* CGUIEnvironment::getHovered() const\r
278 {\r
279         return Hovered;\r
280 }\r
281 \r
282 \r
283 //! removes the focus from an element\r
284 bool CGUIEnvironment::removeFocus(IGUIElement* element)\r
285 {\r
286         if (Focus && Focus==element)\r
287         {\r
288                 SEvent e;\r
289                 e.EventType = EET_GUI_EVENT;\r
290                 e.GUIEvent.Caller = Focus;\r
291                 e.GUIEvent.Element = 0;\r
292                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;\r
293                 if (Focus->OnEvent(e))\r
294                 {\r
295                         return false;\r
296                 }\r
297         }\r
298         if (Focus)\r
299         {\r
300                 Focus->drop();\r
301                 Focus = 0;\r
302         }\r
303 \r
304         return true;\r
305 }\r
306 \r
307 \r
308 //! Returns whether the element has focus\r
309 bool CGUIEnvironment::hasFocus(const IGUIElement* element, bool checkSubElements) const\r
310 {\r
311         if (element == Focus)\r
312                 return true;\r
313 \r
314         if ( !checkSubElements || !element )\r
315                 return false;\r
316 \r
317         IGUIElement* f = Focus;\r
318         while ( f && f->isSubElement() )\r
319         {\r
320                 f = f->getParent();\r
321                 if ( f == element )\r
322                         return true;\r
323         }\r
324         return false;\r
325 }\r
326 \r
327 \r
328 //! returns the current video driver\r
329 video::IVideoDriver* CGUIEnvironment::getVideoDriver() const\r
330 {\r
331         return Driver;\r
332 }\r
333 \r
334 \r
335 //! returns the current file system\r
336 io::IFileSystem* CGUIEnvironment::getFileSystem() const\r
337 {\r
338         return FileSystem;\r
339 }\r
340 \r
341 \r
342 //! returns a pointer to the OS operator\r
343 IOSOperator* CGUIEnvironment::getOSOperator() const\r
344 {\r
345         return Operator;\r
346 }\r
347 \r
348 \r
349 //! clear all GUI elements\r
350 void CGUIEnvironment::clear()\r
351 {\r
352         // Remove the focus\r
353         if (Focus)\r
354         {\r
355                 Focus->drop();\r
356                 Focus = 0;\r
357         }\r
358 \r
359         if (Hovered && Hovered != this)\r
360         {\r
361                 Hovered->drop();\r
362                 Hovered = 0;\r
363         }\r
364         if ( HoveredNoSubelement && HoveredNoSubelement != this)\r
365         {\r
366                 HoveredNoSubelement->drop();\r
367                 HoveredNoSubelement = 0;\r
368         }\r
369 \r
370         getRootGUIElement()->removeAllChildren();\r
371 }\r
372 \r
373 \r
374 //! called by ui if an event happened.\r
375 bool CGUIEnvironment::OnEvent(const SEvent& event)\r
376 {\r
377 \r
378         bool ret = false;\r
379         if (UserReceiver\r
380                 && (event.EventType != EET_MOUSE_INPUT_EVENT)\r
381                 && (event.EventType != EET_KEY_INPUT_EVENT)\r
382                 && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this))\r
383         {\r
384                 ret = UserReceiver->OnEvent(event);\r
385         }\r
386 \r
387         return ret;\r
388 }\r
389 \r
390 //\r
391 void CGUIEnvironment::OnPostRender( u32 time )\r
392 {\r
393         // launch tooltip\r
394         if ( ToolTip.Element == 0 &&\r
395                 HoveredNoSubelement && HoveredNoSubelement != this &&\r
396                 (time - ToolTip.EnterTime >= ToolTip.LaunchTime\r
397                 || (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) &&\r
398                 HoveredNoSubelement->getToolTipText().size() &&\r
399                 getSkin() &&\r
400                 getSkin()->getFont(EGDF_TOOLTIP)\r
401                 )\r
402         {\r
403                 core::rect<s32> pos;\r
404 \r
405                 pos.UpperLeftCorner = LastHoveredMousePos;\r
406                 core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str());\r
407                 dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2;\r
408                 dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2;\r
409 \r
410                 pos.UpperLeftCorner.Y -= dim.Height+1;\r
411                 pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1;\r
412                 pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width;\r
413 \r
414                 pos.constrainTo(getAbsolutePosition());\r
415 \r
416                 ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true);\r
417                 ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP));\r
418                 ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND));\r
419                 ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP));\r
420                 ToolTip.Element->setSubElement(true);\r
421                 ToolTip.Element->grab();\r
422 \r
423                 s32 textHeight = ToolTip.Element->getTextHeight();\r
424                 pos = ToolTip.Element->getRelativePosition();\r
425                 pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight;\r
426                 ToolTip.Element->setRelativePosition(pos);\r
427         }\r
428 \r
429         if (ToolTip.Element && ToolTip.Element->isVisible() )   // (isVisible() check only because we might use visibility for ToolTip one day)\r
430         {\r
431                 ToolTip.LastTime = time;\r
432 \r
433                 // got invisible or removed in the meantime?\r
434                 if ( !HoveredNoSubelement ||\r
435                         !HoveredNoSubelement->isVisible() ||\r
436                         !HoveredNoSubelement->getParent()\r
437                         )       // got invisible or removed in the meantime?\r
438                 {\r
439                         ToolTip.Element->remove();\r
440                         ToolTip.Element->drop();\r
441                         ToolTip.Element = 0;\r
442                 }\r
443         }\r
444 \r
445         IGUIElement::OnPostRender ( time );\r
446 }\r
447 \r
448 void CGUIEnvironment::addToDeletionQueue(IGUIElement* element)\r
449 {\r
450         if (!element)\r
451                 return;\r
452 \r
453         element->grab();\r
454         DeletionQueue.push_back(element);\r
455 }\r
456 \r
457 void CGUIEnvironment::clearDeletionQueue()\r
458 {\r
459         if (DeletionQueue.empty())\r
460                 return;\r
461 \r
462         for (u32 i=0; i<DeletionQueue.size(); ++i)\r
463         {\r
464                 DeletionQueue[i]->remove();\r
465                 DeletionQueue[i]->drop();\r
466         }\r
467 \r
468         DeletionQueue.clear();\r
469 }\r
470 \r
471 //\r
472 void CGUIEnvironment::updateHoveredElement(core::position2d<s32> mousePos)\r
473 {\r
474         IGUIElement* lastHovered = Hovered;\r
475         IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement;\r
476         LastHoveredMousePos = mousePos;\r
477 \r
478         Hovered = getElementFromPoint(mousePos);\r
479 \r
480         if ( ToolTip.Element && Hovered == ToolTip.Element )\r
481         {\r
482                 // When the mouse is over the ToolTip we remove that so it will be re-created at a new position.\r
483                 // Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once.\r
484                 ToolTip.Element->remove();\r
485                 ToolTip.Element->drop();\r
486                 ToolTip.Element = 0;\r
487 \r
488                 // Get the real Hovered\r
489                 Hovered = getElementFromPoint(mousePos);\r
490         }\r
491 \r
492         // for tooltips we want the element itself and not some of it's subelements\r
493         HoveredNoSubelement = Hovered;\r
494         while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() )\r
495         {\r
496                 HoveredNoSubelement = HoveredNoSubelement->getParent();\r
497         }\r
498 \r
499         if (Hovered && Hovered != this)\r
500                 Hovered->grab();\r
501         if ( HoveredNoSubelement && HoveredNoSubelement != this)\r
502                 HoveredNoSubelement->grab();\r
503 \r
504         if (Hovered != lastHovered)\r
505         {\r
506                 SEvent event;\r
507                 event.EventType = EET_GUI_EVENT;\r
508 \r
509                 if (lastHovered)\r
510                 {\r
511                         event.GUIEvent.Caller = lastHovered;\r
512                         event.GUIEvent.Element = 0;\r
513                         event.GUIEvent.EventType = EGET_ELEMENT_LEFT;\r
514                         lastHovered->OnEvent(event);\r
515                 }\r
516 \r
517                 if ( Hovered )\r
518                 {\r
519                         event.GUIEvent.Caller  = Hovered;\r
520                         event.GUIEvent.Element = Hovered;\r
521                         event.GUIEvent.EventType = EGET_ELEMENT_HOVERED;\r
522                         Hovered->OnEvent(event);\r
523                 }\r
524         }\r
525 \r
526         if ( lastHoveredNoSubelement != HoveredNoSubelement )\r
527         {\r
528                 if (ToolTip.Element)\r
529                 {\r
530                         ToolTip.Element->remove();\r
531                         ToolTip.Element->drop();\r
532                         ToolTip.Element = 0;\r
533                 }\r
534 \r
535                 if ( HoveredNoSubelement )\r
536                 {\r
537                         u32 now = os::Timer::getTime();\r
538                         ToolTip.EnterTime = now;\r
539                 }\r
540         }\r
541 \r
542         if (lastHovered && lastHovered != this)\r
543                 lastHovered->drop();\r
544         if (lastHoveredNoSubelement && lastHoveredNoSubelement != this)\r
545                 lastHoveredNoSubelement->drop();\r
546 }\r
547 \r
548 \r
549 //! This sets a new event receiver for gui events. Usually you do not have to\r
550 //! use this method, it is used by the internal engine.\r
551 void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr)\r
552 {\r
553         UserReceiver = evr;\r
554 }\r
555 \r
556 \r
557 //! posts an input event to the environment\r
558 bool CGUIEnvironment::postEventFromUser(const SEvent& event)\r
559 {\r
560         switch(event.EventType)\r
561         {\r
562         case EET_GUI_EVENT:\r
563                 {\r
564                         // hey, why is the user sending gui events..?\r
565                 }\r
566 \r
567                 break;\r
568         case EET_MOUSE_INPUT_EVENT:\r
569 \r
570                 updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));\r
571 \r
572                 if ( Hovered != Focus )\r
573                 {\r
574                         IGUIElement * focusCandidate = Hovered;\r
575 \r
576                         // Only allow enabled elements to be focused (unless EFF_CAN_FOCUS_DISABLED is set)\r
577                         if ( Hovered && !Hovered->isEnabled() && !(FocusFlags & EFF_CAN_FOCUS_DISABLED))\r
578                                 focusCandidate = NULL;  // we still remove focus from the active element\r
579 \r
580                         // Please don't merge this into a single if clause, it's easier to debug the way it is\r
581                         if (FocusFlags & EFF_SET_ON_LMOUSE_DOWN &&\r
582                                 event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN )\r
583                         {\r
584                                 setFocus(focusCandidate);\r
585                         }\r
586                         else if ( FocusFlags & EFF_SET_ON_RMOUSE_DOWN &&\r
587                                 event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN )\r
588                         {\r
589                                 setFocus(focusCandidate);\r
590                         }\r
591                         else if ( FocusFlags & EFF_SET_ON_MOUSE_OVER &&\r
592                                 event.MouseInput.Event == EMIE_MOUSE_MOVED )\r
593                         {\r
594                                 setFocus(focusCandidate);\r
595                         }\r
596                 }\r
597 \r
598                 // sending input to focus\r
599                 if (Focus && Focus->OnEvent(event))\r
600                         return true;\r
601 \r
602                 // focus could have died in last call\r
603                 if (!Focus && Hovered)\r
604                 {\r
605                         return Hovered->OnEvent(event);\r
606                 }\r
607 \r
608                 break;\r
609         case EET_KEY_INPUT_EVENT:\r
610                 {\r
611                         if (Focus && Focus->OnEvent(event))\r
612                                 return true;\r
613 \r
614                         // For keys we handle the event before changing focus to give elements the chance for catching the TAB\r
615                         // Send focus changing event\r
616                         // CAREFUL when changing - there's an identical check in CGUIModalScreen::OnEvent\r
617                         if (FocusFlags & EFF_SET_ON_TAB &&\r
618                                 event.KeyInput.PressedDown &&\r
619                                 event.KeyInput.Key == KEY_TAB)\r
620                         {\r
621                                 IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control);\r
622                                 if (next && next != Focus)\r
623                                 {\r
624                                         if (setFocus(next))\r
625                                                 return true;\r
626                                 }\r
627                         }\r
628                 }\r
629                 break;\r
630         case EET_STRING_INPUT_EVENT:\r
631                 if (Focus && Focus->OnEvent(event))\r
632                         return true;\r
633                 break;\r
634         default:\r
635                 break;\r
636         } // end switch\r
637 \r
638         return false;\r
639 }\r
640 \r
641 \r
642 //! returns the current gui skin\r
643 IGUISkin* CGUIEnvironment::getSkin() const\r
644 {\r
645         return CurrentSkin;\r
646 }\r
647 \r
648 \r
649 //! Sets a new GUI Skin\r
650 void CGUIEnvironment::setSkin(IGUISkin* skin)\r
651 {\r
652         if (CurrentSkin==skin)\r
653                 return;\r
654 \r
655         if (CurrentSkin)\r
656                 CurrentSkin->drop();\r
657 \r
658         CurrentSkin = skin;\r
659 \r
660         if (CurrentSkin)\r
661                 CurrentSkin->grab();\r
662 }\r
663 \r
664 \r
665 //! Creates a new GUI Skin based on a template.\r
666 /** \return Returns a pointer to the created skin.\r
667 If you no longer need the skin, you should call IGUISkin::drop().\r
668 See IReferenceCounted::drop() for more information. */\r
669 IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type)\r
670 {\r
671         IGUISkin* skin = new CGUISkin(type, Driver);\r
672 \r
673         IGUIFont* builtinfont = getBuiltInFont();\r
674         IGUIFontBitmap* bitfont = 0;\r
675         if (builtinfont && builtinfont->getType() == EGFT_BITMAP)\r
676                 bitfont = (IGUIFontBitmap*)builtinfont;\r
677 \r
678         IGUISpriteBank* bank = 0;\r
679         skin->setFont(builtinfont);\r
680 \r
681         if (bitfont)\r
682                 bank = bitfont->getSpriteBank();\r
683 \r
684         skin->setSpriteBank(bank);\r
685 \r
686         return skin;\r
687 }\r
688 \r
689 \r
690 //! adds a button. The returned pointer must not be dropped.\r
691 IGUIButton* CGUIEnvironment::addButton(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)\r
692 {\r
693         IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle);\r
694         if (text)\r
695                 button->setText(text);\r
696 \r
697         if ( tooltiptext )\r
698                 button->setToolTipText ( tooltiptext );\r
699 \r
700         button->drop();\r
701         return button;\r
702 }\r
703 \r
704 \r
705 //! adds a scrollbar. The returned pointer must not be dropped.\r
706 IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)\r
707 {\r
708         IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle);\r
709         bar->drop();\r
710         return bar;\r
711 }\r
712 \r
713 \r
714 //! Adds an image element.\r
715 IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos,\r
716         bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text)\r
717 {\r
718         core::dimension2d<s32> sz(0,0);\r
719         if (image)\r
720                 sz = core::dimension2d<s32>(image->getOriginalSize());\r
721 \r
722         IGUIImage* img = new CGUIImage(this, parent ? parent : this,\r
723                 id, core::rect<s32>(pos, sz));\r
724 \r
725         if (text)\r
726                 img->setText(text);\r
727 \r
728         if (useAlphaChannel)\r
729                 img->setUseAlphaChannel(true);\r
730 \r
731         if (image)\r
732                 img->setImage(image);\r
733 \r
734         img->drop();\r
735         return img;\r
736 }\r
737 \r
738 \r
739 //! adds an image. The returned pointer must not be dropped.\r
740 IGUIImage* CGUIEnvironment::addImage(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, bool useAlphaChannel)\r
741 {\r
742         IGUIImage* img = new CGUIImage(this, parent ? parent : this,\r
743                 id, rectangle);\r
744 \r
745         if (text)\r
746                 img->setText(text);\r
747 \r
748         if ( useAlphaChannel )\r
749                 img->setUseAlphaChannel(true);\r
750 \r
751         img->drop();\r
752         return img;\r
753 }\r
754 \r
755 \r
756 //! adds a checkbox\r
757 IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)\r
758 {\r
759         IGUICheckBox* b = new CGUICheckBox(checked, this,\r
760                 parent ? parent : this , id , rectangle);\r
761 \r
762         if (text)\r
763                 b->setText(text);\r
764 \r
765         b->drop();\r
766         return b;\r
767 }\r
768 \r
769 \r
770 //! adds a list box\r
771 IGUIListBox* CGUIEnvironment::addListBox(const core::rect<s32>& rectangle,\r
772                                         IGUIElement* parent, s32 id, bool drawBackground)\r
773 {\r
774         IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle,\r
775                 true, drawBackground, false);\r
776 \r
777         if (CurrentSkin && CurrentSkin->getSpriteBank())\r
778         {\r
779                 b->setSpriteBank(CurrentSkin->getSpriteBank());\r
780         }\r
781         else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP)\r
782         {\r
783                 b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank());\r
784         }\r
785 \r
786         b->drop();\r
787         return b;\r
788 }\r
789 \r
790 \r
791 //! adds a file open dialog. The returned pointer must not be dropped.\r
792 IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title,\r
793                                 bool modal, IGUIElement* parent, s32 id,\r
794                                 bool restoreCWD, io::path::char_type* startDir)\r
795 {\r
796         parent = parent ? parent : this;\r
797 \r
798         if (modal)\r
799                 return nullptr;\r
800 \r
801         IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id,\r
802                         restoreCWD, startDir);\r
803         d->drop();\r
804 \r
805         return d;\r
806 }\r
807 \r
808 \r
809 //! adds a static text. The returned pointer must not be dropped.\r
810 IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text,\r
811                                 const core::rect<s32>& rectangle,\r
812                                 bool border, bool wordWrap,\r
813                                 IGUIElement* parent, s32 id, bool background)\r
814 {\r
815         IGUIStaticText* d = new CGUIStaticText(text, border, this,\r
816                         parent ? parent : this, id, rectangle, background);\r
817 \r
818         d->setWordWrap(wordWrap);\r
819         d->drop();\r
820 \r
821         return d;\r
822 }\r
823 \r
824 \r
825 //! Adds an edit box. The returned pointer must not be dropped.\r
826 IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text,\r
827                         const core::rect<s32>& rectangle, bool border,\r
828                         IGUIElement* parent, s32 id)\r
829 {\r
830         IGUIEditBox* d = new CGUIEditBox(text, border, this,\r
831                         parent ? parent : this, id, rectangle);\r
832 \r
833         d->drop();\r
834         return d;\r
835 }\r
836 \r
837 \r
838 //! Adds a tab control to the environment.\r
839 IGUITabControl* CGUIEnvironment::addTabControl(const core::rect<s32>& rectangle,\r
840         IGUIElement* parent, bool fillbackground, bool border, s32 id)\r
841 {\r
842         IGUITabControl* t = new CGUITabControl(this, parent ? parent : this,\r
843                 rectangle, fillbackground, border, id);\r
844         t->drop();\r
845         return t;\r
846 }\r
847 \r
848 \r
849 //! Adds tab to the environment.\r
850 IGUITab* CGUIEnvironment::addTab(const core::rect<s32>& rectangle,\r
851         IGUIElement* parent, s32 id)\r
852 {\r
853         IGUITab* t = new CGUITab(this, parent ? parent : this,\r
854                 rectangle, id);\r
855         t->drop();\r
856         return t;\r
857 }\r
858 \r
859 \r
860 //! Adds a combo box to the environment.\r
861 IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect<s32>& rectangle,\r
862         IGUIElement* parent, s32 id)\r
863 {\r
864         IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this,\r
865                 id, rectangle);\r
866         t->drop();\r
867         return t;\r
868 }\r
869 \r
870 \r
871 //! returns the font\r
872 IGUIFont* CGUIEnvironment::getFont(const io::path& filename)\r
873 {\r
874         // search existing font\r
875 \r
876         SFont f;\r
877         f.NamedPath.setPath(filename);\r
878 \r
879         s32 index = Fonts.binary_search(f);\r
880         if (index != -1)\r
881                 return Fonts[index].Font;\r
882 \r
883         // font doesn't exist, attempt to load it\r
884 \r
885         // does the file exist?\r
886 \r
887         if (!FileSystem->existFile(filename))\r
888         {\r
889                 os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR);\r
890                 return 0;\r
891         }\r
892 \r
893         IGUIFont* ifont=0;\r
894 #if 0\r
895                 {\r
896                         CGUIFont* font = new CGUIFont(this, filename);\r
897                         ifont = (IGUIFont*)font;\r
898 \r
899                         // load the font\r
900                         io::path directory;\r
901                         core::splitFilename(filename, &directory);\r
902                         if (!font->load(xml, directory))\r
903                         {\r
904                                 font->drop();\r
905                                 font  = 0;\r
906                                 ifont = 0;\r
907                         }\r
908                 }\r
909 #endif\r
910 \r
911 \r
912         if (!ifont)\r
913         {\r
914 \r
915                 CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() );\r
916                 ifont = (IGUIFont*)font;\r
917                 if (!font->load(f.NamedPath.getPath()))\r
918                 {\r
919                         font->drop();\r
920                         return 0;\r
921                 }\r
922         }\r
923 \r
924         // add to fonts.\r
925 \r
926         f.Font = ifont;\r
927         Fonts.push_back(f);\r
928 \r
929         return ifont;\r
930 }\r
931 \r
932 \r
933 //! add an externally loaded font\r
934 IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font)\r
935 {\r
936         if (font)\r
937         {\r
938                 SFont f;\r
939                 f.NamedPath.setPath(name);\r
940                 s32 index = Fonts.binary_search(f);\r
941                 if (index != -1)\r
942                         return Fonts[index].Font;\r
943                 f.Font = font;\r
944                 Fonts.push_back(f);\r
945                 font->grab();\r
946         }\r
947         return font;\r
948 }\r
949 \r
950 //! remove loaded font\r
951 void CGUIEnvironment::removeFont(IGUIFont* font)\r
952 {\r
953         if ( !font )\r
954                 return;\r
955         for ( u32 i=0; i<Fonts.size(); ++i )\r
956         {\r
957                 if ( Fonts[i].Font == font )\r
958                 {\r
959                         Fonts[i].Font->drop();\r
960                         Fonts.erase(i);\r
961                         return;\r
962                 }\r
963         }\r
964 }\r
965 \r
966 //! returns default font\r
967 IGUIFont* CGUIEnvironment::getBuiltInFont() const\r
968 {\r
969         if (Fonts.empty())\r
970                 return 0;\r
971 \r
972         return Fonts[0].Font;\r
973 }\r
974 \r
975 \r
976 IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename)\r
977 {\r
978         // search for the file name\r
979 \r
980         SSpriteBank b;\r
981         b.NamedPath.setPath(filename);\r
982 \r
983         s32 index = Banks.binary_search(b);\r
984         if (index != -1)\r
985                 return Banks[index].Bank;\r
986 \r
987         // we don't have this sprite bank, we should load it\r
988         if (!FileSystem->existFile(b.NamedPath.getPath()))\r
989         {\r
990                 if ( filename != DefaultFontName )\r
991                 {\r
992                         os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_DEBUG);\r
993                 }\r
994                 return 0;\r
995         }\r
996 \r
997         // todo: load it!\r
998 \r
999         return 0;\r
1000 }\r
1001 \r
1002 \r
1003 IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name)\r
1004 {\r
1005         // no duplicate names allowed\r
1006 \r
1007         SSpriteBank b;\r
1008         b.NamedPath.setPath(name);\r
1009 \r
1010         const s32 index = Banks.binary_search(b);\r
1011         if (index != -1)\r
1012                 return 0;\r
1013 \r
1014         // create a new sprite bank\r
1015 \r
1016         b.Bank = new CGUISpriteBank(this);\r
1017         Banks.push_back(b);\r
1018 \r
1019         return b.Bank;\r
1020 }\r
1021 \r
1022 \r
1023 //! Creates the image list from the given texture.\r
1024 IGUIImageList* CGUIEnvironment::createImageList(  video::ITexture* texture,\r
1025                                         core::dimension2d<s32>  imageSize, bool useAlphaChannel )\r
1026 {\r
1027         CGUIImageList* imageList = new CGUIImageList( Driver );\r
1028         if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) )\r
1029         {\r
1030                 imageList->drop();\r
1031                 return 0;\r
1032         }\r
1033 \r
1034         return imageList;\r
1035 }\r
1036 \r
1037 //! Returns the root gui element.\r
1038 IGUIElement* CGUIEnvironment::getRootGUIElement()\r
1039 {\r
1040         return this;\r
1041 }\r
1042 \r
1043 \r
1044 //! Returns the next element in the tab group starting at the focused element\r
1045 IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)\r
1046 {\r
1047         // start the search at the root of the current tab group\r
1048         IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0;\r
1049         s32 startOrder = -1;\r
1050 \r
1051         // if we're searching for a group\r
1052         if (group && startPos)\r
1053         {\r
1054                 startOrder = startPos->getTabOrder();\r
1055         }\r
1056         else\r
1057         if (!group && Focus && !Focus->isTabGroup())\r
1058         {\r
1059                 startOrder = Focus->getTabOrder();\r
1060                 if (startOrder == -1)\r
1061                 {\r
1062                         // this element is not part of the tab cycle,\r
1063                         // but its parent might be...\r
1064                         IGUIElement *el = Focus;\r
1065                         while (el && el->getParent() && startOrder == -1)\r
1066                         {\r
1067                                 el = el->getParent();\r
1068                                 startOrder = el->getTabOrder();\r
1069                         }\r
1070 \r
1071                 }\r
1072         }\r
1073 \r
1074         if (group || !startPos)\r
1075                 startPos = this; // start at the root\r
1076 \r
1077         // find the element\r
1078         IGUIElement *closest = 0;\r
1079         IGUIElement *first = 0;\r
1080         startPos->getNextElement(startOrder, reverse, group, first, closest, false, (FocusFlags & EFF_CAN_FOCUS_DISABLED) != 0);\r
1081 \r
1082         if (closest)\r
1083                 return closest; // we found an element\r
1084         else if (first)\r
1085                 return first; // go to the end or the start\r
1086         else if (group)\r
1087                 return this; // no group found? root group\r
1088         else\r
1089                 return 0;\r
1090 }\r
1091 \r
1092 void CGUIEnvironment::setFocusBehavior(u32 flags)\r
1093 {\r
1094         FocusFlags = flags;\r
1095 }\r
1096 \r
1097 u32 CGUIEnvironment::getFocusBehavior() const\r
1098 {\r
1099         return FocusFlags;\r
1100 }\r
1101 \r
1102 //! creates an GUI Environment\r
1103 IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,\r
1104                                         video::IVideoDriver* Driver,\r
1105                                         IOSOperator* op)\r
1106 {\r
1107         return new CGUIEnvironment(fs, Driver, op);\r
1108 }\r
1109 \r
1110 \r
1111 } // end namespace gui\r
1112 } // end namespace irr\r
1113 \r
1114 #endif // _IRR_COMPILE_WITH_GUI_\r
1115 \r