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