]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUIEnvironment.cpp
Drop XML implementation, related code and dependent features
[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 "CGUIWindow.h"\r
15 #include "CGUIScrollBar.h"\r
16 #include "CGUIFont.h"\r
17 #include "CGUISpriteBank.h"\r
18 #include "CGUIImage.h"\r
19 #include "CGUIMeshViewer.h"\r
20 #include "CGUICheckBox.h"\r
21 #include "CGUIListBox.h"\r
22 #include "CGUITreeView.h"\r
23 #include "CGUIImageList.h"\r
24 #include "CGUIFileOpenDialog.h"\r
25 #include "CGUIColorSelectDialog.h"\r
26 #include "CGUIStaticText.h"\r
27 #include "CGUIEditBox.h"\r
28 #include "CGUISpinBox.h"\r
29 #include "CGUIInOutFader.h"\r
30 #include "CGUIMessageBox.h"\r
31 #include "CGUIModalScreen.h"\r
32 #include "CGUITabControl.h"\r
33 #include "CGUIContextMenu.h"\r
34 #include "CGUIComboBox.h"\r
35 #include "CGUIMenu.h"\r
36 #include "CGUIToolBar.h"\r
37 #include "CGUITable.h"\r
38 #include "CGUIProfiler.h"\r
39 \r
40 #include "CDefaultGUIElementFactory.h"\r
41 #include "IWriteFile.h"\r
42 \r
43 #include "BuiltInFont.h"\r
44 #include "os.h"\r
45 \r
46 namespace irr\r
47 {\r
48 namespace gui\r
49 {\r
50 \r
51 const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont";\r
52 \r
53 //! constructor\r
54 CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op)\r
55 : IGUIElement(EGUIET_ROOT, 0, 0, 0, core::rect<s32>(driver ? core::dimension2d<s32>(driver->getScreenSize()) : core::dimension2d<s32>(0,0))),\r
56         Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0),\r
57         FileSystem(fs), UserReceiver(0), Operator(op), FocusFlags(EFF_SET_ON_LMOUSE_DOWN|EFF_SET_ON_TAB)\r
58 {\r
59         if (Driver)\r
60                 Driver->grab();\r
61 \r
62         if (FileSystem)\r
63                 FileSystem->grab();\r
64 \r
65         if (Operator)\r
66                 Operator->grab();\r
67 \r
68         #ifdef _DEBUG\r
69         IGUIEnvironment::setDebugName("CGUIEnvironment");\r
70         #endif\r
71 \r
72         // gui factory\r
73         IGUIElementFactory* factory = new CDefaultGUIElementFactory(this);\r
74         registerGUIElementFactory(factory);\r
75         factory->drop();\r
76 \r
77         loadBuiltInFont();\r
78 \r
79         IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC );\r
80         setSkin(skin);\r
81         skin->drop();\r
82 \r
83         //set tooltip default\r
84         ToolTip.LastTime = 0;\r
85         ToolTip.EnterTime = 0;\r
86         ToolTip.LaunchTime = 1000;\r
87         ToolTip.RelaunchTime = 500;\r
88         ToolTip.Element = 0;\r
89 \r
90         // environment is root tab group\r
91         Environment = this;\r
92         setTabGroup(true);\r
93 }\r
94 \r
95 \r
96 //! destructor\r
97 CGUIEnvironment::~CGUIEnvironment()\r
98 {\r
99         clearDeletionQueue();\r
100 \r
101         if ( HoveredNoSubelement && HoveredNoSubelement != this )\r
102         {\r
103                 HoveredNoSubelement->drop();\r
104                 HoveredNoSubelement = 0;\r
105         }\r
106 \r
107         if (Hovered && Hovered != this)\r
108         {\r
109                 Hovered->drop();\r
110                 Hovered = 0;\r
111         }\r
112 \r
113         if (Focus)\r
114         {\r
115                 Focus->drop();\r
116                 Focus = 0;\r
117         }\r
118 \r
119         if (ToolTip.Element)\r
120         {\r
121                 ToolTip.Element->drop();\r
122                 ToolTip.Element = 0;\r
123         }\r
124 \r
125         // drop skin\r
126         if (CurrentSkin)\r
127         {\r
128                 CurrentSkin->drop();\r
129                 CurrentSkin = 0;\r
130         }\r
131 \r
132         u32 i;\r
133 \r
134         // delete all sprite banks\r
135         for (i=0; i<Banks.size(); ++i)\r
136                 if (Banks[i].Bank)\r
137                         Banks[i].Bank->drop();\r
138 \r
139         // delete all fonts\r
140         for (i=0; i<Fonts.size(); ++i)\r
141                 Fonts[i].Font->drop();\r
142 \r
143         // remove all factories\r
144         for (i=0; i<GUIElementFactoryList.size(); ++i)\r
145                 GUIElementFactoryList[i]->drop();\r
146 \r
147         if (Operator)\r
148         {\r
149                 Operator->drop();\r
150                 Operator = 0;\r
151         }\r
152 \r
153         if (FileSystem)\r
154         {\r
155                 FileSystem->drop();\r
156                 FileSystem = 0;\r
157         }\r
158 \r
159         if (Driver)\r
160         {\r
161                 Driver->drop();\r
162                 Driver = 0;\r
163         }\r
164 }\r
165 \r
166 \r
167 void CGUIEnvironment::loadBuiltInFont()\r
168 {\r
169         io::IReadFile* file = FileSystem->createMemoryReadFile(BuiltInFontData,\r
170                                 BuiltInFontDataSize, DefaultFontName, false);\r
171 \r
172         CGUIFont* font = new CGUIFont(this, DefaultFontName );\r
173         if (!font->load(file))\r
174         {\r
175                 os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR);\r
176                 font->drop();\r
177                 file->drop();\r
178                 return;\r
179         }\r
180 \r
181         SFont f;\r
182         f.NamedPath.setPath(DefaultFontName);\r
183         f.Font = font;\r
184         Fonts.push_back(f);\r
185 \r
186         file->drop();\r
187 }\r
188 \r
189 \r
190 //! draws all gui elements\r
191 void CGUIEnvironment::drawAll(bool useScreenSize)\r
192 {\r
193         if (useScreenSize && Driver)\r
194         {\r
195                 core::dimension2d<s32> dim(Driver->getScreenSize());\r
196                 if (AbsoluteRect.LowerRightCorner.X != dim.Width ||\r
197                         AbsoluteRect.UpperLeftCorner.X != 0 ||\r
198                         AbsoluteRect.LowerRightCorner.Y != dim.Height ||\r
199                         AbsoluteRect.UpperLeftCorner.Y != 0\r
200                         )\r
201                 {\r
202                         setRelativePosition(core::recti(0,0,dim.Width, dim.Height));\r
203                 }\r
204         }\r
205 \r
206         // make sure tooltip is always on top\r
207         if (ToolTip.Element)\r
208                 bringToFront(ToolTip.Element);\r
209 \r
210         draw();\r
211         OnPostRender ( os::Timer::getTime () );\r
212 \r
213         clearDeletionQueue();\r
214 }\r
215 \r
216 \r
217 //! sets the focus to an element\r
218 bool CGUIEnvironment::setFocus(IGUIElement* element)\r
219 {\r
220         if (Focus == element)\r
221         {\r
222                 return false;\r
223         }\r
224 \r
225         // GUI Environment should just reset the focus to 0\r
226         if (element == this)\r
227                 element = 0;\r
228 \r
229         // stop element from being deleted\r
230         if (element)\r
231                 element->grab();\r
232 \r
233         // focus may change or be removed in this call\r
234         IGUIElement *currentFocus = 0;\r
235         if (Focus)\r
236         {\r
237                 currentFocus = Focus;\r
238                 currentFocus->grab();\r
239                 SEvent e;\r
240                 e.EventType = EET_GUI_EVENT;\r
241                 e.GUIEvent.Caller = Focus;\r
242                 e.GUIEvent.Element = element;\r
243                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;\r
244                 if (Focus->OnEvent(e))\r
245                 {\r
246                         if (element)\r
247                                 element->drop();\r
248                         currentFocus->drop();\r
249                         return false;\r
250                 }\r
251                 currentFocus->drop();\r
252                 currentFocus = 0;\r
253         }\r
254 \r
255         if (element)\r
256         {\r
257                 currentFocus = Focus;\r
258                 if (currentFocus)\r
259                         currentFocus->grab();\r
260 \r
261                 // send focused event\r
262                 SEvent e;\r
263                 e.EventType = EET_GUI_EVENT;\r
264                 e.GUIEvent.Caller = element;\r
265                 e.GUIEvent.Element = Focus;\r
266                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUSED;\r
267                 if (element->OnEvent(e))\r
268                 {\r
269                         if (element)\r
270                                 element->drop();\r
271                         if (currentFocus)\r
272                                 currentFocus->drop();\r
273                         return false;\r
274                 }\r
275         }\r
276 \r
277         if (currentFocus)\r
278                 currentFocus->drop();\r
279 \r
280         if (Focus)\r
281                 Focus->drop();\r
282 \r
283         // element is the new focus so it doesn't have to be dropped\r
284         Focus = element;\r
285 \r
286         return true;\r
287 }\r
288 \r
289 \r
290 //! returns the element with the focus\r
291 IGUIElement* CGUIEnvironment::getFocus() const\r
292 {\r
293         return Focus;\r
294 }\r
295 \r
296 //! returns the element last known to be under the mouse cursor\r
297 IGUIElement* CGUIEnvironment::getHovered() const\r
298 {\r
299         return Hovered;\r
300 }\r
301 \r
302 \r
303 //! removes the focus from an element\r
304 bool CGUIEnvironment::removeFocus(IGUIElement* element)\r
305 {\r
306         if (Focus && Focus==element)\r
307         {\r
308                 SEvent e;\r
309                 e.EventType = EET_GUI_EVENT;\r
310                 e.GUIEvent.Caller = Focus;\r
311                 e.GUIEvent.Element = 0;\r
312                 e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;\r
313                 if (Focus->OnEvent(e))\r
314                 {\r
315                         return false;\r
316                 }\r
317         }\r
318         if (Focus)\r
319         {\r
320                 Focus->drop();\r
321                 Focus = 0;\r
322         }\r
323 \r
324         return true;\r
325 }\r
326 \r
327 \r
328 //! Returns whether the element has focus\r
329 bool CGUIEnvironment::hasFocus(const IGUIElement* element, bool checkSubElements) const\r
330 {\r
331         if (element == Focus)\r
332                 return true;\r
333 \r
334         if ( !checkSubElements || !element )\r
335                 return false;\r
336 \r
337         IGUIElement* f = Focus;\r
338         while ( f && f->isSubElement() )\r
339         {\r
340                 f = f->getParent();\r
341                 if ( f == element )\r
342                         return true;\r
343         }\r
344         return false;\r
345 }\r
346 \r
347 \r
348 //! returns the current video driver\r
349 video::IVideoDriver* CGUIEnvironment::getVideoDriver() const\r
350 {\r
351         return Driver;\r
352 }\r
353 \r
354 \r
355 //! returns the current file system\r
356 io::IFileSystem* CGUIEnvironment::getFileSystem() const\r
357 {\r
358         return FileSystem;\r
359 }\r
360 \r
361 \r
362 //! returns a pointer to the OS operator\r
363 IOSOperator* CGUIEnvironment::getOSOperator() const\r
364 {\r
365         return Operator;\r
366 }\r
367 \r
368 \r
369 //! clear all GUI elements\r
370 void CGUIEnvironment::clear()\r
371 {\r
372         // Remove the focus\r
373         if (Focus)\r
374         {\r
375                 Focus->drop();\r
376                 Focus = 0;\r
377         }\r
378 \r
379         if (Hovered && Hovered != this)\r
380         {\r
381                 Hovered->drop();\r
382                 Hovered = 0;\r
383         }\r
384         if ( HoveredNoSubelement && HoveredNoSubelement != this)\r
385         {\r
386                 HoveredNoSubelement->drop();\r
387                 HoveredNoSubelement = 0;\r
388         }\r
389 \r
390         // get the root's children in case the root changes in future\r
391         const core::list<IGUIElement*>& children = getRootGUIElement()->getChildren();\r
392 \r
393         while (!children.empty())\r
394                 (*children.getLast())->remove();\r
395 }\r
396 \r
397 \r
398 //! called by ui if an event happened.\r
399 bool CGUIEnvironment::OnEvent(const SEvent& event)\r
400 {\r
401 \r
402         bool ret = false;\r
403         if (UserReceiver\r
404                 && (event.EventType != EET_MOUSE_INPUT_EVENT)\r
405                 && (event.EventType != EET_KEY_INPUT_EVENT)\r
406                 && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this))\r
407         {\r
408                 ret = UserReceiver->OnEvent(event);\r
409         }\r
410 \r
411         return ret;\r
412 }\r
413 \r
414 //\r
415 void CGUIEnvironment::OnPostRender( u32 time )\r
416 {\r
417         // launch tooltip\r
418         if ( ToolTip.Element == 0 &&\r
419                 HoveredNoSubelement && HoveredNoSubelement != this &&\r
420                 (time - ToolTip.EnterTime >= ToolTip.LaunchTime\r
421                 || (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) &&\r
422                 HoveredNoSubelement->getToolTipText().size() &&\r
423                 getSkin() &&\r
424                 getSkin()->getFont(EGDF_TOOLTIP)\r
425                 )\r
426         {\r
427                 core::rect<s32> pos;\r
428 \r
429                 pos.UpperLeftCorner = LastHoveredMousePos;\r
430                 core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str());\r
431                 dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2;\r
432                 dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2;\r
433 \r
434                 pos.UpperLeftCorner.Y -= dim.Height+1;\r
435                 pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1;\r
436                 pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width;\r
437 \r
438                 pos.constrainTo(getAbsolutePosition());\r
439 \r
440                 ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true);\r
441                 ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP));\r
442                 ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND));\r
443                 ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP));\r
444                 ToolTip.Element->setSubElement(true);\r
445                 ToolTip.Element->grab();\r
446 \r
447                 s32 textHeight = ToolTip.Element->getTextHeight();\r
448                 pos = ToolTip.Element->getRelativePosition();\r
449                 pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight;\r
450                 ToolTip.Element->setRelativePosition(pos);\r
451         }\r
452 \r
453         if (ToolTip.Element && ToolTip.Element->isVisible() )   // (isVisible() check only because we might use visibility for ToolTip one day)\r
454         {\r
455                 ToolTip.LastTime = time;\r
456 \r
457                 // got invisible or removed in the meantime?\r
458                 if ( !HoveredNoSubelement ||\r
459                         !HoveredNoSubelement->isVisible() ||\r
460                         !HoveredNoSubelement->getParent()\r
461                         )       // got invisible or removed in the meantime?\r
462                 {\r
463                         ToolTip.Element->remove();\r
464                         ToolTip.Element->drop();\r
465                         ToolTip.Element = 0;\r
466                 }\r
467         }\r
468 \r
469         IGUIElement::OnPostRender ( time );\r
470 }\r
471 \r
472 void CGUIEnvironment::addToDeletionQueue(IGUIElement* element)\r
473 {\r
474         if (!element)\r
475                 return;\r
476 \r
477         element->grab();\r
478         DeletionQueue.push_back(element);\r
479 }\r
480 \r
481 void CGUIEnvironment::clearDeletionQueue()\r
482 {\r
483         if (DeletionQueue.empty())\r
484                 return;\r
485 \r
486         for (u32 i=0; i<DeletionQueue.size(); ++i)\r
487         {\r
488                 DeletionQueue[i]->remove();\r
489                 DeletionQueue[i]->drop();\r
490         }\r
491 \r
492         DeletionQueue.clear();\r
493 }\r
494 \r
495 //\r
496 void CGUIEnvironment::updateHoveredElement(core::position2d<s32> mousePos)\r
497 {\r
498         IGUIElement* lastHovered = Hovered;\r
499         IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement;\r
500         LastHoveredMousePos = mousePos;\r
501 \r
502         Hovered = getElementFromPoint(mousePos);\r
503 \r
504         if ( ToolTip.Element && Hovered == ToolTip.Element )\r
505         {\r
506                 // When the mouse is over the ToolTip we remove that so it will be re-created at a new position.\r
507                 // Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once.\r
508                 ToolTip.Element->remove();\r
509                 ToolTip.Element->drop();\r
510                 ToolTip.Element = 0;\r
511 \r
512                 // Get the real Hovered\r
513                 Hovered = getElementFromPoint(mousePos);\r
514         }\r
515 \r
516         // for tooltips we want the element itself and not some of it's subelements\r
517         HoveredNoSubelement = Hovered;\r
518         while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() )\r
519         {\r
520                 HoveredNoSubelement = HoveredNoSubelement->getParent();\r
521         }\r
522 \r
523         if (Hovered && Hovered != this)\r
524                 Hovered->grab();\r
525         if ( HoveredNoSubelement && HoveredNoSubelement != this)\r
526                 HoveredNoSubelement->grab();\r
527 \r
528         if (Hovered != lastHovered)\r
529         {\r
530                 SEvent event;\r
531                 event.EventType = EET_GUI_EVENT;\r
532 \r
533                 if (lastHovered)\r
534                 {\r
535                         event.GUIEvent.Caller = lastHovered;\r
536                         event.GUIEvent.Element = 0;\r
537                         event.GUIEvent.EventType = EGET_ELEMENT_LEFT;\r
538                         lastHovered->OnEvent(event);\r
539                 }\r
540 \r
541                 if ( Hovered )\r
542                 {\r
543                         event.GUIEvent.Caller  = Hovered;\r
544                         event.GUIEvent.Element = Hovered;\r
545                         event.GUIEvent.EventType = EGET_ELEMENT_HOVERED;\r
546                         Hovered->OnEvent(event);\r
547                 }\r
548         }\r
549 \r
550         if ( lastHoveredNoSubelement != HoveredNoSubelement )\r
551         {\r
552                 if (ToolTip.Element)\r
553                 {\r
554                         ToolTip.Element->remove();\r
555                         ToolTip.Element->drop();\r
556                         ToolTip.Element = 0;\r
557                 }\r
558 \r
559                 if ( HoveredNoSubelement )\r
560                 {\r
561                         u32 now = os::Timer::getTime();\r
562                         ToolTip.EnterTime = now;\r
563                 }\r
564         }\r
565 \r
566         if (lastHovered && lastHovered != this)\r
567                 lastHovered->drop();\r
568         if (lastHoveredNoSubelement && lastHoveredNoSubelement != this)\r
569                 lastHoveredNoSubelement->drop();\r
570 }\r
571 \r
572 \r
573 //! This sets a new event receiver for gui events. Usually you do not have to\r
574 //! use this method, it is used by the internal engine.\r
575 void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr)\r
576 {\r
577         UserReceiver = evr;\r
578 }\r
579 \r
580 \r
581 //! posts an input event to the environment\r
582 bool CGUIEnvironment::postEventFromUser(const SEvent& event)\r
583 {\r
584         switch(event.EventType)\r
585         {\r
586         case EET_GUI_EVENT:\r
587                 {\r
588                         // hey, why is the user sending gui events..?\r
589                 }\r
590 \r
591                 break;\r
592         case EET_MOUSE_INPUT_EVENT:\r
593 \r
594                 updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));\r
595 \r
596                 if ( Hovered != Focus )\r
597                 {\r
598                         IGUIElement * focusCandidate = Hovered;\r
599 \r
600                         // Only allow enabled elements to be focused (unless EFF_CAN_FOCUS_DISABLED is set)\r
601                         if ( Hovered && !Hovered->isEnabled() && !(FocusFlags & EFF_CAN_FOCUS_DISABLED))\r
602                                 focusCandidate = NULL;  // we still remove focus from the active element\r
603 \r
604                         // Please don't merge this into a single if clause, it's easier to debug the way it is\r
605                         if (FocusFlags & EFF_SET_ON_LMOUSE_DOWN &&\r
606                                 event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN )\r
607                         {\r
608                                 setFocus(focusCandidate);\r
609                         }\r
610                         else if ( FocusFlags & EFF_SET_ON_RMOUSE_DOWN &&\r
611                                 event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN )\r
612                         {\r
613                                 setFocus(focusCandidate);\r
614                         }\r
615                         else if ( FocusFlags & EFF_SET_ON_MOUSE_OVER &&\r
616                                 event.MouseInput.Event == EMIE_MOUSE_MOVED )\r
617                         {\r
618                                 setFocus(focusCandidate);\r
619                         }\r
620                 }\r
621 \r
622                 // sending input to focus\r
623                 if (Focus && Focus->OnEvent(event))\r
624                         return true;\r
625 \r
626                 // focus could have died in last call\r
627                 if (!Focus && Hovered)\r
628                 {\r
629                         return Hovered->OnEvent(event);\r
630                 }\r
631 \r
632                 break;\r
633         case EET_KEY_INPUT_EVENT:\r
634                 {\r
635                         if (Focus && Focus->OnEvent(event))\r
636                                 return true;\r
637 \r
638                         // For keys we handle the event before changing focus to give elements the chance for catching the TAB\r
639                         // Send focus changing event\r
640                         if (FocusFlags & EFF_SET_ON_TAB &&\r
641                                 event.EventType == EET_KEY_INPUT_EVENT &&\r
642                                 event.KeyInput.PressedDown &&\r
643                                 event.KeyInput.Key == KEY_TAB)\r
644                         {\r
645                                 IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control);\r
646                                 if (next && next != Focus)\r
647                                 {\r
648                                         if (setFocus(next))\r
649                                                 return true;\r
650                                 }\r
651                         }\r
652                 }\r
653                 break;\r
654         case EET_STRING_INPUT_EVENT:\r
655                 if (Focus && Focus->OnEvent(event))\r
656                         return true;\r
657                 break;\r
658         default:\r
659                 break;\r
660         } // end switch\r
661 \r
662         return false;\r
663 }\r
664 \r
665 \r
666 //! returns the current gui skin\r
667 IGUISkin* CGUIEnvironment::getSkin() const\r
668 {\r
669         return CurrentSkin;\r
670 }\r
671 \r
672 \r
673 //! Sets a new GUI Skin\r
674 void CGUIEnvironment::setSkin(IGUISkin* skin)\r
675 {\r
676         if (CurrentSkin==skin)\r
677                 return;\r
678 \r
679         if (CurrentSkin)\r
680                 CurrentSkin->drop();\r
681 \r
682         CurrentSkin = skin;\r
683 \r
684         if (CurrentSkin)\r
685                 CurrentSkin->grab();\r
686 }\r
687 \r
688 \r
689 //! Creates a new GUI Skin based on a template.\r
690 /** \return Returns a pointer to the created skin.\r
691 If you no longer need the skin, you should call IGUISkin::drop().\r
692 See IReferenceCounted::drop() for more information. */\r
693 IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type)\r
694 {\r
695         IGUISkin* skin = new CGUISkin(type, Driver);\r
696 \r
697         IGUIFont* builtinfont = getBuiltInFont();\r
698         IGUIFontBitmap* bitfont = 0;\r
699         if (builtinfont && builtinfont->getType() == EGFT_BITMAP)\r
700                 bitfont = (IGUIFontBitmap*)builtinfont;\r
701 \r
702         IGUISpriteBank* bank = 0;\r
703         skin->setFont(builtinfont);\r
704 \r
705         if (bitfont)\r
706                 bank = bitfont->getSpriteBank();\r
707 \r
708         skin->setSpriteBank(bank);\r
709 \r
710         return skin;\r
711 }\r
712 \r
713 \r
714 //! Returns the default element factory which can create all built in elements\r
715 IGUIElementFactory* CGUIEnvironment::getDefaultGUIElementFactory() const\r
716 {\r
717         return getGUIElementFactory(0);\r
718 }\r
719 \r
720 \r
721 //! Adds an element factory to the gui environment.\r
722 /** Use this to extend the gui environment with new element types which it should be\r
723 able to create automatically, for example when loading data from xml files. */\r
724 void CGUIEnvironment::registerGUIElementFactory(IGUIElementFactory* factoryToAdd)\r
725 {\r
726         if (factoryToAdd)\r
727         {\r
728                 factoryToAdd->grab();\r
729                 GUIElementFactoryList.push_back(factoryToAdd);\r
730         }\r
731 }\r
732 \r
733 \r
734 //! Returns amount of registered scene node factories.\r
735 u32 CGUIEnvironment::getRegisteredGUIElementFactoryCount() const\r
736 {\r
737         return GUIElementFactoryList.size();\r
738 }\r
739 \r
740 \r
741 //! Returns a scene node factory by index\r
742 IGUIElementFactory* CGUIEnvironment::getGUIElementFactory(u32 index) const\r
743 {\r
744         if (index < GUIElementFactoryList.size())\r
745                 return GUIElementFactoryList[index];\r
746         else\r
747                 return 0;\r
748 }\r
749 \r
750 \r
751 //! adds a GUI Element using its name\r
752 IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* parent)\r
753 {\r
754         IGUIElement* node=0;\r
755 \r
756         if (!parent)\r
757                 parent = this;\r
758 \r
759         for (s32 i=GUIElementFactoryList.size()-1; i>=0 && !node; --i)\r
760                 node = GUIElementFactoryList[i]->addGUIElement(elementName, parent);\r
761 \r
762 \r
763         return node;\r
764 }\r
765 \r
766 \r
767 //! Saves the current gui into a file.\r
768 //! \param filename: Name of the file .\r
769 bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start)\r
770 {\r
771         io::IWriteFile* file = FileSystem->createAndWriteFile(filename);\r
772         if (!file)\r
773         {\r
774                 return false;\r
775         }\r
776 \r
777         bool ret = saveGUI(file, start);\r
778         file->drop();\r
779         return ret;\r
780 }\r
781 \r
782 \r
783 //! Saves the current gui into a file.\r
784 bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start)\r
785 {\r
786         return false;\r
787 }\r
788 \r
789 \r
790 //! Loads the gui. Note that the current gui is not cleared before.\r
791 //! \param filename: Name of the file.\r
792 bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent)\r
793 {\r
794         io::IReadFile* read = FileSystem->createAndOpenFile(filename);\r
795         if (!read)\r
796         {\r
797                 os::Printer::log("Unable to open gui file", filename, ELL_ERROR);\r
798                 return false;\r
799         }\r
800 \r
801         bool ret = loadGUI(read, parent);\r
802         read->drop();\r
803 \r
804         return ret;\r
805 }\r
806 \r
807 \r
808 //! Loads the gui. Note that the current gui is not cleared before.\r
809 bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent)\r
810 {\r
811         return false;\r
812 }\r
813 \r
814 \r
815 //! Writes attributes of the environment\r
816 void CGUIEnvironment::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const\r
817 {\r
818         IGUISkin* skin = getSkin();\r
819 \r
820         if (skin)\r
821         {\r
822                 out->addEnum("Skin", getSkin()->getType(), GUISkinTypeNames);\r
823                 skin->serializeAttributes(out, options);\r
824         }\r
825 }\r
826 \r
827 \r
828 //! Reads attributes of the environment\r
829 void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)\r
830 {\r
831         if (in->existsAttribute("Skin"))\r
832         {\r
833                 IGUISkin *skin = getSkin();\r
834 \r
835                 EGUI_SKIN_TYPE t = (EGUI_SKIN_TYPE) in->getAttributeAsEnumeration("Skin",GUISkinTypeNames);\r
836                 if ( !skin || t != skin->getType())\r
837                 {\r
838                         skin = createSkin(t);\r
839                         setSkin(skin);\r
840                         skin->drop();\r
841                 }\r
842 \r
843                 skin = getSkin();\r
844 \r
845                 if (skin)\r
846                 {\r
847                         skin->deserializeAttributes(in, options);\r
848                 }\r
849 \r
850         }\r
851 \r
852         RelativeRect = AbsoluteRect =\r
853                         core::rect<s32>(Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d<s32>(0,0));\r
854 }\r
855 \r
856 \r
857 //! adds a button. The returned pointer must not be dropped.\r
858 IGUIButton* CGUIEnvironment::addButton(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)\r
859 {\r
860         IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle);\r
861         if (text)\r
862                 button->setText(text);\r
863 \r
864         if ( tooltiptext )\r
865                 button->setToolTipText ( tooltiptext );\r
866 \r
867         button->drop();\r
868         return button;\r
869 }\r
870 \r
871 \r
872 //! adds a window. The returned pointer must not be dropped.\r
873 IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool modal,\r
874                 const wchar_t* text, IGUIElement* parent, s32 id)\r
875 {\r
876         parent = parent ? parent : this;\r
877 \r
878         IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle);\r
879         if (text)\r
880                 win->setText(text);\r
881         win->drop();\r
882 \r
883         if (modal)\r
884         {\r
885                 // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very\r
886                 // careful not to get virtual function call, like OnEvent, in the window.\r
887                 CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);\r
888                 modalScreen->drop();\r
889                 modalScreen->addChild(win);\r
890         }\r
891 \r
892         return win;\r
893 }\r
894 \r
895 \r
896 //! adds a modal screen. The returned pointer must not be dropped.\r
897 IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent)\r
898 {\r
899         parent = parent ? parent : this;\r
900 \r
901         IGUIElement *win = new CGUIModalScreen(this, parent, -1);\r
902         win->drop();\r
903 \r
904         return win;\r
905 }\r
906 \r
907 \r
908 //! Adds a message box.\r
909 IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text,\r
910         bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image)\r
911 {\r
912         if (!CurrentSkin)\r
913                 return 0;\r
914 \r
915         parent = parent ? parent : this;\r
916 \r
917         core::rect<s32> rect;\r
918         core::dimension2d<u32> screenDim, msgBoxDim;\r
919 \r
920         screenDim.Width = parent->getAbsolutePosition().getWidth();\r
921         screenDim.Height = parent->getAbsolutePosition().getHeight();\r
922         msgBoxDim.Width = 2;\r
923         msgBoxDim.Height = 2;\r
924 \r
925         rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2;\r
926         rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2;\r
927         rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width;\r
928         rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height;\r
929 \r
930         IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,\r
931                 parent, id, rect, image);\r
932         win->drop();\r
933 \r
934         if (modal)\r
935         {\r
936                 // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very\r
937                 // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox.\r
938                 CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);\r
939                 modalScreen->drop();\r
940                 modalScreen->addChild( win );\r
941         }\r
942 \r
943 \r
944         return win;\r
945 }\r
946 \r
947 \r
948 //! adds a scrollbar. The returned pointer must not be dropped.\r
949 IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)\r
950 {\r
951         IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle);\r
952         bar->drop();\r
953         return bar;\r
954 }\r
955 \r
956 //! Adds a table to the environment\r
957 IGUITable* CGUIEnvironment::addTable(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, bool drawBackground)\r
958 {\r
959         CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false);\r
960         b->drop();\r
961         return b;\r
962 }\r
963 \r
964         //! Adds an element to display the information from the Irrlicht profiler\r
965 IGUIProfiler* CGUIEnvironment::addProfilerDisplay(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)\r
966 {\r
967         CGUIProfiler* p = new CGUIProfiler(this, parent ? parent : this, id, rectangle, NULL);\r
968         p->drop();\r
969         return p;\r
970 }\r
971 \r
972 //! Adds an image element.\r
973 IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos,\r
974         bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text)\r
975 {\r
976         core::dimension2d<s32> sz(0,0);\r
977         if (image)\r
978                 sz = core::dimension2d<s32>(image->getOriginalSize());\r
979 \r
980         IGUIImage* img = new CGUIImage(this, parent ? parent : this,\r
981                 id, core::rect<s32>(pos, sz));\r
982 \r
983         if (text)\r
984                 img->setText(text);\r
985 \r
986         if (useAlphaChannel)\r
987                 img->setUseAlphaChannel(true);\r
988 \r
989         if (image)\r
990                 img->setImage(image);\r
991 \r
992         img->drop();\r
993         return img;\r
994 }\r
995 \r
996 \r
997 //! adds an image. The returned pointer must not be dropped.\r
998 IGUIImage* CGUIEnvironment::addImage(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, bool useAlphaChannel)\r
999 {\r
1000         IGUIImage* img = new CGUIImage(this, parent ? parent : this,\r
1001                 id, rectangle);\r
1002 \r
1003         if (text)\r
1004                 img->setText(text);\r
1005 \r
1006         if ( useAlphaChannel )\r
1007                 img->setUseAlphaChannel(true);\r
1008 \r
1009         img->drop();\r
1010         return img;\r
1011 }\r
1012 \r
1013 \r
1014 //! adds an mesh viewer. The returned pointer must not be dropped.\r
1015 IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)\r
1016 {\r
1017         IGUIMeshViewer* v = new CGUIMeshViewer(this, parent ? parent : this,\r
1018                 id, rectangle);\r
1019 \r
1020         if (text)\r
1021                 v->setText(text);\r
1022 \r
1023         v->drop();\r
1024         return v;\r
1025 }\r
1026 \r
1027 \r
1028 //! adds a checkbox\r
1029 IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)\r
1030 {\r
1031         IGUICheckBox* b = new CGUICheckBox(checked, this,\r
1032                 parent ? parent : this , id , rectangle);\r
1033 \r
1034         if (text)\r
1035                 b->setText(text);\r
1036 \r
1037         b->drop();\r
1038         return b;\r
1039 }\r
1040 \r
1041 \r
1042 //! adds a list box\r
1043 IGUIListBox* CGUIEnvironment::addListBox(const core::rect<s32>& rectangle,\r
1044                                         IGUIElement* parent, s32 id, bool drawBackground)\r
1045 {\r
1046         IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle,\r
1047                 true, drawBackground, false);\r
1048 \r
1049         if (CurrentSkin && CurrentSkin->getSpriteBank())\r
1050         {\r
1051                 b->setSpriteBank(CurrentSkin->getSpriteBank());\r
1052         }\r
1053         else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP)\r
1054         {\r
1055                 b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank());\r
1056         }\r
1057 \r
1058         b->drop();\r
1059         return b;\r
1060 }\r
1061 \r
1062 //! adds a tree view\r
1063 IGUITreeView* CGUIEnvironment::addTreeView(const core::rect<s32>& rectangle,\r
1064                                          IGUIElement* parent, s32 id,\r
1065                                          bool drawBackground,\r
1066                                          bool scrollBarVertical, bool scrollBarHorizontal)\r
1067 {\r
1068         IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle,\r
1069                 true, drawBackground, scrollBarVertical, scrollBarHorizontal);\r
1070 \r
1071         b->setIconFont ( getBuiltInFont () );\r
1072         b->drop();\r
1073         return b;\r
1074 }\r
1075 \r
1076 //! adds a file open dialog. The returned pointer must not be dropped.\r
1077 IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title,\r
1078                                 bool modal, IGUIElement* parent, s32 id,\r
1079                                 bool restoreCWD, io::path::char_type* startDir)\r
1080 {\r
1081         parent = parent ? parent : this;\r
1082 \r
1083         IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id,\r
1084                         restoreCWD, startDir);\r
1085         d->drop();\r
1086 \r
1087         if (modal)\r
1088         {\r
1089                 // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very\r
1090                 // careful not to get virtual function call, like OnEvent, in the window.\r
1091                 CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);\r
1092                 modalScreen->drop();\r
1093                 modalScreen->addChild(d);\r
1094         }\r
1095 \r
1096         return d;\r
1097 }\r
1098 \r
1099 \r
1100 //! adds a color select dialog. The returned pointer must not be dropped.\r
1101 IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title,\r
1102                                 bool modal, IGUIElement* parent, s32 id)\r
1103 {\r
1104         parent = parent ? parent : this;\r
1105 \r
1106         IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title,\r
1107                         this, parent, id);\r
1108         d->drop();\r
1109 \r
1110         if (modal)\r
1111         {\r
1112                 // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very\r
1113                 // careful not to get virtual function call, like OnEvent, in the window.\r
1114                 CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);\r
1115                 modalScreen->drop();\r
1116                 modalScreen->addChild(d);\r
1117         }\r
1118 \r
1119         return d;\r
1120 }\r
1121 \r
1122 \r
1123 //! adds a static text. The returned pointer must not be dropped.\r
1124 IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text,\r
1125                                 const core::rect<s32>& rectangle,\r
1126                                 bool border, bool wordWrap,\r
1127                                 IGUIElement* parent, s32 id, bool background)\r
1128 {\r
1129         IGUIStaticText* d = new CGUIStaticText(text, border, this,\r
1130                         parent ? parent : this, id, rectangle, background);\r
1131 \r
1132         d->setWordWrap(wordWrap);\r
1133         d->drop();\r
1134 \r
1135         return d;\r
1136 }\r
1137 \r
1138 \r
1139 //! Adds an edit box. The returned pointer must not be dropped.\r
1140 IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text,\r
1141                         const core::rect<s32>& rectangle, bool border,\r
1142                         IGUIElement* parent, s32 id)\r
1143 {\r
1144         IGUIEditBox* d = new CGUIEditBox(text, border, this,\r
1145                         parent ? parent : this, id, rectangle);\r
1146 \r
1147         d->drop();\r
1148         return d;\r
1149 }\r
1150 \r
1151 \r
1152 //! Adds a spin box to the environment\r
1153 IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text,\r
1154                                          const core::rect<s32> &rectangle,\r
1155                                          bool border,IGUIElement* parent, s32 id)\r
1156 {\r
1157         IGUISpinBox* d = new CGUISpinBox(text, border,this,\r
1158                 parent ? parent : this, id, rectangle);\r
1159 \r
1160         d->drop();\r
1161         return d;\r
1162 }\r
1163 \r
1164 \r
1165 //! Adds a tab control to the environment.\r
1166 IGUITabControl* CGUIEnvironment::addTabControl(const core::rect<s32>& rectangle,\r
1167         IGUIElement* parent, bool fillbackground, bool border, s32 id)\r
1168 {\r
1169         IGUITabControl* t = new CGUITabControl(this, parent ? parent : this,\r
1170                 rectangle, fillbackground, border, id);\r
1171         t->drop();\r
1172         return t;\r
1173 }\r
1174 \r
1175 \r
1176 //! Adds tab to the environment.\r
1177 IGUITab* CGUIEnvironment::addTab(const core::rect<s32>& rectangle,\r
1178         IGUIElement* parent, s32 id)\r
1179 {\r
1180         IGUITab* t = new CGUITab(this, parent ? parent : this,\r
1181                 rectangle, id);\r
1182         t->drop();\r
1183         return t;\r
1184 }\r
1185 \r
1186 \r
1187 //! Adds a context menu to the environment.\r
1188 IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect<s32>& rectangle,\r
1189         IGUIElement* parent, s32 id)\r
1190 {\r
1191         IGUIContextMenu* c = new CGUIContextMenu(this,\r
1192                 parent ? parent : this, id, rectangle, true);\r
1193         c->drop();\r
1194         return c;\r
1195 }\r
1196 \r
1197 \r
1198 //! Adds a menu to the environment.\r
1199 IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id)\r
1200 {\r
1201         if (!parent)\r
1202                 parent = this;\r
1203 \r
1204         IGUIContextMenu* c = new CGUIMenu(this,\r
1205                 parent, id, core::rect<s32>(0,0,\r
1206                                 parent->getAbsolutePosition().getWidth(),\r
1207                                 parent->getAbsolutePosition().getHeight()));\r
1208 \r
1209         c->drop();\r
1210         return c;\r
1211 }\r
1212 \r
1213 \r
1214 //! Adds a toolbar to the environment. It is like a menu is always placed on top\r
1215 //! in its parent, and contains buttons.\r
1216 IGUIToolBar* CGUIEnvironment::addToolBar(IGUIElement* parent, s32 id)\r
1217 {\r
1218         if (!parent)\r
1219                 parent = this;\r
1220 \r
1221         IGUIToolBar* b = new CGUIToolBar(this, parent, id, core::rect<s32>(0,0,10,10));\r
1222         b->drop();\r
1223         return b;\r
1224 }\r
1225 \r
1226 \r
1227 //! Adds an element for fading in or out.\r
1228 IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect<s32>* rectangle, IGUIElement* parent, s32 id)\r
1229 {\r
1230         core::rect<s32> rect;\r
1231 \r
1232         if (rectangle)\r
1233                 rect = *rectangle;\r
1234         else if (Driver)\r
1235                 rect = core::rect<s32>(core::dimension2di(Driver->getScreenSize()));\r
1236 \r
1237         if (!parent)\r
1238                 parent = this;\r
1239 \r
1240         IGUIInOutFader* fader = new CGUIInOutFader(this, parent, id, rect);\r
1241         fader->drop();\r
1242         return fader;\r
1243 }\r
1244 \r
1245 \r
1246 //! Adds a combo box to the environment.\r
1247 IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect<s32>& rectangle,\r
1248         IGUIElement* parent, s32 id)\r
1249 {\r
1250         IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this,\r
1251                 id, rectangle);\r
1252         t->drop();\r
1253         return t;\r
1254 }\r
1255 \r
1256 \r
1257 //! returns the font\r
1258 IGUIFont* CGUIEnvironment::getFont(const io::path& filename)\r
1259 {\r
1260         // search existing font\r
1261 \r
1262         SFont f;\r
1263         f.NamedPath.setPath(filename);\r
1264 \r
1265         s32 index = Fonts.binary_search(f);\r
1266         if (index != -1)\r
1267                 return Fonts[index].Font;\r
1268 \r
1269         // font doesn't exist, attempt to load it\r
1270 \r
1271         // does the file exist?\r
1272 \r
1273         if (!FileSystem->existFile(filename))\r
1274         {\r
1275                 os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR);\r
1276                 return 0;\r
1277         }\r
1278 \r
1279         IGUIFont* ifont=0;\r
1280 #if 0\r
1281                 {\r
1282                         CGUIFont* font = new CGUIFont(this, filename);\r
1283                         ifont = (IGUIFont*)font;\r
1284 \r
1285                         // load the font\r
1286                         io::path directory;\r
1287                         core::splitFilename(filename, &directory);\r
1288                         if (!font->load(xml, directory))\r
1289                         {\r
1290                                 font->drop();\r
1291                                 font  = 0;\r
1292                                 ifont = 0;\r
1293                         }\r
1294                 }\r
1295 #endif\r
1296 \r
1297 \r
1298         if (!ifont)\r
1299         {\r
1300 \r
1301                 CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() );\r
1302                 ifont = (IGUIFont*)font;\r
1303                 if (!font->load(f.NamedPath.getPath()))\r
1304                 {\r
1305                         font->drop();\r
1306                         return 0;\r
1307                 }\r
1308         }\r
1309 \r
1310         // add to fonts.\r
1311 \r
1312         f.Font = ifont;\r
1313         Fonts.push_back(f);\r
1314 \r
1315         return ifont;\r
1316 }\r
1317 \r
1318 \r
1319 //! add an externally loaded font\r
1320 IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font)\r
1321 {\r
1322         if (font)\r
1323         {\r
1324                 SFont f;\r
1325                 f.NamedPath.setPath(name);\r
1326                 s32 index = Fonts.binary_search(f);\r
1327                 if (index != -1)\r
1328                         return Fonts[index].Font;\r
1329                 f.Font = font;\r
1330                 Fonts.push_back(f);\r
1331                 font->grab();\r
1332         }\r
1333         return font;\r
1334 }\r
1335 \r
1336 //! remove loaded font\r
1337 void CGUIEnvironment::removeFont(IGUIFont* font)\r
1338 {\r
1339         if ( !font )\r
1340                 return;\r
1341         for ( u32 i=0; i<Fonts.size(); ++i )\r
1342         {\r
1343                 if ( Fonts[i].Font == font )\r
1344                 {\r
1345                         Fonts[i].Font->drop();\r
1346                         Fonts.erase(i);\r
1347                         return;\r
1348                 }\r
1349         }\r
1350 }\r
1351 \r
1352 //! returns default font\r
1353 IGUIFont* CGUIEnvironment::getBuiltInFont() const\r
1354 {\r
1355         if (Fonts.empty())\r
1356                 return 0;\r
1357 \r
1358         return Fonts[0].Font;\r
1359 }\r
1360 \r
1361 \r
1362 IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename)\r
1363 {\r
1364         // search for the file name\r
1365 \r
1366         SSpriteBank b;\r
1367         b.NamedPath.setPath(filename);\r
1368 \r
1369         s32 index = Banks.binary_search(b);\r
1370         if (index != -1)\r
1371                 return Banks[index].Bank;\r
1372 \r
1373         // we don't have this sprite bank, we should load it\r
1374         if (!FileSystem->existFile(b.NamedPath.getPath()))\r
1375         {\r
1376                 if ( filename != DefaultFontName )\r
1377                 {\r
1378                         os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_DEBUG);\r
1379                 }\r
1380                 return 0;\r
1381         }\r
1382 \r
1383         // todo: load it!\r
1384 \r
1385         return 0;\r
1386 }\r
1387 \r
1388 \r
1389 IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name)\r
1390 {\r
1391         // no duplicate names allowed\r
1392 \r
1393         SSpriteBank b;\r
1394         b.NamedPath.setPath(name);\r
1395 \r
1396         const s32 index = Banks.binary_search(b);\r
1397         if (index != -1)\r
1398                 return 0;\r
1399 \r
1400         // create a new sprite bank\r
1401 \r
1402         b.Bank = new CGUISpriteBank(this);\r
1403         Banks.push_back(b);\r
1404 \r
1405         return b.Bank;\r
1406 }\r
1407 \r
1408 \r
1409 //! Creates the image list from the given texture.\r
1410 IGUIImageList* CGUIEnvironment::createImageList(  video::ITexture* texture,\r
1411                                         core::dimension2d<s32>  imageSize, bool useAlphaChannel )\r
1412 {\r
1413         CGUIImageList* imageList = new CGUIImageList( Driver );\r
1414         if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) )\r
1415         {\r
1416                 imageList->drop();\r
1417                 return 0;\r
1418         }\r
1419 \r
1420         return imageList;\r
1421 }\r
1422 \r
1423 //! Returns the root gui element.\r
1424 IGUIElement* CGUIEnvironment::getRootGUIElement()\r
1425 {\r
1426         return this;\r
1427 }\r
1428 \r
1429 \r
1430 //! Returns the next element in the tab group starting at the focused element\r
1431 IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)\r
1432 {\r
1433         // start the search at the root of the current tab group\r
1434         IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0;\r
1435         s32 startOrder = -1;\r
1436 \r
1437         // if we're searching for a group\r
1438         if (group && startPos)\r
1439         {\r
1440                 startOrder = startPos->getTabOrder();\r
1441         }\r
1442         else\r
1443         if (!group && Focus && !Focus->isTabGroup())\r
1444         {\r
1445                 startOrder = Focus->getTabOrder();\r
1446                 if (startOrder == -1)\r
1447                 {\r
1448                         // this element is not part of the tab cycle,\r
1449                         // but its parent might be...\r
1450                         IGUIElement *el = Focus;\r
1451                         while (el && el->getParent() && startOrder == -1)\r
1452                         {\r
1453                                 el = el->getParent();\r
1454                                 startOrder = el->getTabOrder();\r
1455                         }\r
1456 \r
1457                 }\r
1458         }\r
1459 \r
1460         if (group || !startPos)\r
1461                 startPos = this; // start at the root\r
1462 \r
1463         // find the element\r
1464         IGUIElement *closest = 0;\r
1465         IGUIElement *first = 0;\r
1466         startPos->getNextElement(startOrder, reverse, group, first, closest, false, (FocusFlags & EFF_CAN_FOCUS_DISABLED) != 0);\r
1467 \r
1468         if (closest)\r
1469                 return closest; // we found an element\r
1470         else if (first)\r
1471                 return first; // go to the end or the start\r
1472         else if (group)\r
1473                 return this; // no group found? root group\r
1474         else\r
1475                 return 0;\r
1476 }\r
1477 \r
1478 void CGUIEnvironment::setFocusBehavior(u32 flags)\r
1479 {\r
1480         FocusFlags = flags;\r
1481 }\r
1482 \r
1483 u32 CGUIEnvironment::getFocusBehavior() const\r
1484 {\r
1485         return FocusFlags;\r
1486 }\r
1487 \r
1488 //! creates an GUI Environment\r
1489 IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,\r
1490                                         video::IVideoDriver* Driver,\r
1491                                         IOSOperator* op)\r
1492 {\r
1493         return new CGUIEnvironment(fs, Driver, op);\r
1494 }\r
1495 \r
1496 \r
1497 } // end namespace gui\r
1498 } // end namespace irr\r
1499 \r
1500 #endif // _IRR_COMPILE_WITH_GUI_\r
1501 \r