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