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