2
// Copyright (C) 2002-2011 Nikolaus Gebhardt
3
// This file is part of the "Irrlicht Engine".
4
// For conditions of distribution and use, see copyright notice in irrlicht.h
6
#include "CGUIEnvironment.h"
8
#ifdef _IRR_COMPILE_WITH_GUI_
10
#include "IVideoDriver.h"
13
#include "CGUIButton.h"
14
#include "CGUIWindow.h"
15
#include "CGUIScrollBar.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"
36
#include "CGUIToolBar.h"
37
#include "CGUITable.h"
39
#include "CDefaultGUIElementFactory.h"
40
#include "IWriteFile.h"
41
#include "IXMLWriter.h"
43
#include "BuiltInFont.h"
51
const wchar_t* IRR_XML_FORMAT_GUI_ENV = L"irr_gui";
52
const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT = L"element";
53
const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE = L"type";
56
CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op)
57
: 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))),
58
Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0),
59
FileSystem(fs), UserReceiver(0), Operator(op)
71
IGUIEnvironment::setDebugName("CGUIEnvironment");
75
IGUIElementFactory* factory = new CDefaultGUIElementFactory(this);
76
registerGUIElementFactory(factory);
81
IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC );
87
ToolTip.EnterTime = 0;
88
ToolTip.LaunchTime = 1000;
89
ToolTip.RelaunchTime = 500;
92
// environment is root tab group
99
CGUIEnvironment::~CGUIEnvironment()
101
if ( HoveredNoSubelement && HoveredNoSubelement != this )
103
HoveredNoSubelement->drop();
104
HoveredNoSubelement = 0;
107
if (Hovered && Hovered != this)
127
ToolTip.Element->drop();
152
// delete all sprite banks
153
for (i=0; i<Banks.size(); ++i)
155
Banks[i].Bank->drop();
158
for (i=0; i<Fonts.size(); ++i)
159
Fonts[i].Font->drop();
161
// remove all factories
162
for (i=0; i<GUIElementFactoryList.size(); ++i)
163
GUIElementFactoryList[i]->drop();
167
void CGUIEnvironment::loadBuiltInFont()
169
io::path filename = "#DefaultFont";
171
io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, filename, false);
173
CGUIFont* font = new CGUIFont(this, filename );
174
if (!font->load(file))
176
os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR);
183
f.NamedPath.setPath(filename);
191
//! draws all gui elements
192
void CGUIEnvironment::drawAll()
196
core::dimension2d<s32> dim(Driver->getScreenSize());
197
if (AbsoluteRect.LowerRightCorner.X != dim.Width ||
198
AbsoluteRect.LowerRightCorner.Y != dim.Height)
200
// resize gui environment
201
DesiredRect.LowerRightCorner = dim;
202
AbsoluteClippingRect = DesiredRect;
203
AbsoluteRect = DesiredRect;
204
updateAbsolutePosition();
208
// make sure tooltip is always on top
210
bringToFront(ToolTip.Element);
213
OnPostRender ( os::Timer::getTime () );
217
//! sets the focus to an element
218
bool CGUIEnvironment::setFocus(IGUIElement* element)
220
if (Focus == element)
222
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
226
// GUI Environment should not get the focus
230
// stop element from being deleted
234
// focus may change or be removed in this call
235
IGUIElement *currentFocus = 0;
238
currentFocus = Focus;
239
currentFocus->grab();
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))
249
currentFocus->drop();
250
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
253
currentFocus->drop();
259
currentFocus = Focus;
261
currentFocus->grab();
263
// send focused event
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))
274
currentFocus->drop();
275
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
281
currentFocus->drop();
286
// element is the new focus so it doesn't have to be dropped
293
//! returns the element with the focus
294
IGUIElement* CGUIEnvironment::getFocus() const
300
//! removes the focus from an element
301
bool CGUIEnvironment::removeFocus(IGUIElement* element)
303
if (Focus && Focus==element)
306
e.EventType = EET_GUI_EVENT;
307
e.GUIEvent.Caller = Focus;
308
e.GUIEvent.Element = 0;
309
e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;
310
if (Focus->OnEvent(e))
312
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
326
//! Returns if the element has focus
327
bool CGUIEnvironment::hasFocus(IGUIElement* element) const
329
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
330
return (element == Focus);
334
//! returns the current video driver
335
video::IVideoDriver* CGUIEnvironment::getVideoDriver() const
341
//! returns the current file system
342
io::IFileSystem* CGUIEnvironment::getFileSystem() const
348
//! returns the current file system
349
IOSOperator* CGUIEnvironment::getOSOperator() const
355
//! clear all GUI elements
356
void CGUIEnvironment::clear()
365
if (Hovered && Hovered != this)
370
if ( HoveredNoSubelement && HoveredNoSubelement != this)
372
HoveredNoSubelement->drop();
373
HoveredNoSubelement = 0;
376
// get the root's children in case the root changes in future
377
const core::list<IGUIElement*>& children = getRootGUIElement()->getChildren();
379
while (!children.empty())
380
(*children.getLast())->remove();
384
//! called by ui if an event happened.
385
bool CGUIEnvironment::OnEvent(const SEvent& event)
389
&& (event.EventType != EET_MOUSE_INPUT_EVENT)
390
&& (event.EventType != EET_KEY_INPUT_EVENT)
391
&& (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this))
393
ret = UserReceiver->OnEvent(event);
396
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
402
void CGUIEnvironment::OnPostRender( u32 time )
405
if ( ToolTip.Element == 0 &&
406
HoveredNoSubelement && HoveredNoSubelement != this &&
407
(time - ToolTip.EnterTime >= ToolTip.LaunchTime
408
|| (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) &&
409
HoveredNoSubelement->getToolTipText().size() &&
411
getSkin()->getFont(EGDF_TOOLTIP)
416
pos.UpperLeftCorner = LastHoveredMousePos;
417
core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str());
418
dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2;
419
dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2;
421
pos.UpperLeftCorner.Y -= dim.Height+1;
422
pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1;
423
pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width;
425
pos.constrainTo(getAbsolutePosition());
427
ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true);
428
ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP));
429
ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND));
430
ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP));
431
ToolTip.Element->setSubElement(true);
432
ToolTip.Element->grab();
434
s32 textHeight = ToolTip.Element->getTextHeight();
435
pos = ToolTip.Element->getRelativePosition();
436
pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight;
437
ToolTip.Element->setRelativePosition(pos);
440
if (ToolTip.Element && ToolTip.Element->isVisible() ) // (isVisible() check only because we might use visibility for ToolTip one day)
442
ToolTip.LastTime = time;
444
// got invisible or removed in the meantime?
445
if ( !HoveredNoSubelement ||
446
!HoveredNoSubelement->isVisible() ||
447
!HoveredNoSubelement->getParent()
448
) // got invisible or removed in the meantime?
450
ToolTip.Element->remove();
451
ToolTip.Element->drop();
456
IGUIElement::OnPostRender ( time );
461
void CGUIEnvironment::updateHoveredElement(core::position2d<s32> mousePos)
463
IGUIElement* lastHovered = Hovered;
464
IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement;
465
LastHoveredMousePos = mousePos;
467
Hovered = getElementFromPoint(mousePos);
469
if ( ToolTip.Element && Hovered == ToolTip.Element )
471
// When the mouse is over the ToolTip we remove that so it will be re-created at a new position.
472
// Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once.
473
ToolTip.Element->remove();
474
ToolTip.Element->drop();
477
// Get the real Hovered
478
Hovered = getElementFromPoint(mousePos);
481
// for tooltips we want the element itself and not some of it's subelements
482
HoveredNoSubelement = Hovered;
483
while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() )
485
HoveredNoSubelement = HoveredNoSubelement->getParent();
488
if (Hovered && Hovered != this)
490
if ( HoveredNoSubelement && HoveredNoSubelement != this)
491
HoveredNoSubelement->grab();
493
if (Hovered != lastHovered)
496
event.EventType = EET_GUI_EVENT;
500
event.GUIEvent.Caller = lastHovered;
501
event.GUIEvent.Element = 0;
502
event.GUIEvent.EventType = EGET_ELEMENT_LEFT;
503
lastHovered->OnEvent(event);
508
event.GUIEvent.Caller = Hovered;
509
event.GUIEvent.Element = Hovered;
510
event.GUIEvent.EventType = EGET_ELEMENT_HOVERED;
511
Hovered->OnEvent(event);
515
if ( lastHoveredNoSubelement != HoveredNoSubelement )
519
ToolTip.Element->remove();
520
ToolTip.Element->drop();
524
if ( HoveredNoSubelement )
526
u32 now = os::Timer::getTime();
527
ToolTip.EnterTime = now;
531
if (lastHovered && lastHovered != this)
533
if (lastHoveredNoSubelement && lastHoveredNoSubelement != this)
534
lastHoveredNoSubelement->drop();
538
//! This sets a new event receiver for gui events. Usually you do not have to
539
//! use this method, it is used by the internal engine.
540
void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr)
546
//! posts an input event to the environment
547
bool CGUIEnvironment::postEventFromUser(const SEvent& event)
549
switch(event.EventType)
552
// hey, why is the user sending gui events..?
554
case EET_MOUSE_INPUT_EVENT:
556
updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
558
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
559
if ( (Hovered && Hovered != Focus) || !Focus )
564
// sending input to focus
565
if (Focus && Focus->OnEvent(event))
568
// focus could have died in last call
569
if (!Focus && Hovered)
571
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
572
return Hovered->OnEvent(event);
576
case EET_KEY_INPUT_EVENT:
578
if (Focus && Focus->OnEvent(event))
581
// For keys we handle the event before changing focus to give elements the chance for catching the TAB
582
// Send focus changing event
583
if (event.EventType == EET_KEY_INPUT_EVENT &&
584
event.KeyInput.PressedDown &&
585
event.KeyInput.Key == KEY_TAB)
587
IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control);
588
if (next && next != Focus)
601
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
606
//! returns the current gui skin
607
IGUISkin* CGUIEnvironment::getSkin() const
613
//! Sets a new GUI Skin
614
void CGUIEnvironment::setSkin(IGUISkin* skin)
616
if (CurrentSkin==skin)
629
//! Creates a new GUI Skin based on a template.
630
/** \return Returns a pointer to the created skin.
631
If you no longer need the skin, you should call IGUISkin::drop().
632
See IReferenceCounted::drop() for more information. */
633
IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type)
635
IGUISkin* skin = new CGUISkin(type, Driver);
637
IGUIFont* builtinfont = getBuiltInFont();
638
IGUIFontBitmap* bitfont = 0;
639
if (builtinfont && builtinfont->getType() == EGFT_BITMAP)
640
bitfont = (IGUIFontBitmap*)builtinfont;
642
IGUISpriteBank* bank = 0;
643
skin->setFont(builtinfont);
646
bank = bitfont->getSpriteBank();
648
skin->setSpriteBank(bank);
654
//! Returns the default element factory which can create all built in elements
655
IGUIElementFactory* CGUIEnvironment::getDefaultGUIElementFactory() const
657
return getGUIElementFactory(0);
661
//! Adds an element factory to the gui environment.
662
/** Use this to extend the gui environment with new element types which it should be
663
able to create automaticly, for example when loading data from xml files. */
664
void CGUIEnvironment::registerGUIElementFactory(IGUIElementFactory* factoryToAdd)
668
factoryToAdd->grab();
669
GUIElementFactoryList.push_back(factoryToAdd);
674
//! Returns amount of registered scene node factories.
675
u32 CGUIEnvironment::getRegisteredGUIElementFactoryCount() const
677
return GUIElementFactoryList.size();
681
//! Returns a scene node factory by index
682
IGUIElementFactory* CGUIEnvironment::getGUIElementFactory(u32 index) const
684
if (index < GUIElementFactoryList.size())
685
return GUIElementFactoryList[index];
691
//! adds a GUI Element using its name
692
IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* parent)
699
for (s32 i=GUIElementFactoryList.size()-1; i>=0 && !node; --i)
700
node = GUIElementFactoryList[i]->addGUIElement(elementName, parent);
707
//! Saves the current gui into a file.
708
//! \param filename: Name of the file .
709
bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start)
711
io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
714
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
718
bool ret = saveGUI(file, start);
720
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
725
//! Saves the current gui into a file.
726
bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start)
730
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
734
io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
737
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
741
writer->writeXMLHeader();
742
writeGUIElement(writer, start ? start : this);
749
//! Loads the gui. Note that the current gui is not cleared before.
750
//! \param filename: Name of the file.
751
bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent)
753
io::IReadFile* read = FileSystem->createAndOpenFile(filename);
756
os::Printer::log("Unable to open gui file", filename, ELL_ERROR);
757
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
761
bool ret = loadGUI(read, parent);
764
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
769
//! Loads the gui. Note that the current gui is not cleared before.
770
bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent)
774
os::Printer::log("Unable to open GUI file", ELL_ERROR);
775
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
779
io::IXMLReader* reader = FileSystem->createXMLReader(file);
782
os::Printer::log("GUI is not a valid XML file", file->getFileName(), ELL_ERROR);
783
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
788
while(reader->read())
790
readGUIElement(reader, parent);
801
void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node)
806
io::EXML_NODE nodeType = reader->getNodeType();
808
if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END)
811
if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
816
else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()))
818
// find node type and create it
819
const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE);
821
node = addGUIElement(attrName.c_str(), node);
824
os::Printer::log("Could not create GUI element of unknown type", attrName.c_str());
829
while(reader->read())
831
bool endreached = false;
833
switch (reader->getNodeType())
835
case io::EXN_ELEMENT_END:
836
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
837
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
842
case io::EXN_ELEMENT:
843
if (!wcscmp(L"attributes", reader->getNodeName()))
846
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
847
attr->read(reader, true);
850
node->deserializeAttributes(attr);
855
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
856
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
858
readGUIElement(reader, node);
862
os::Printer::log("Found unknown element in irrlicht GUI file",
863
core::stringc(reader->getNodeName()).c_str());
877
//! writes an element
878
void CGUIEnvironment::writeGUIElement(io::IXMLWriter* writer, IGUIElement* node)
880
if (!writer || !node )
883
const wchar_t* name = 0;
887
io::IAttributes* attr = FileSystem->createEmptyAttributes();
888
node->serializeAttributes(attr);
890
// all gui elements must have at least one attribute
891
// if they have nothing then we ignore them.
892
if (attr->getAttributeCount() != 0)
896
name = IRR_XML_FORMAT_GUI_ENV;
897
writer->writeElement(name, false);
901
name = IRR_XML_FORMAT_GUI_ELEMENT;
902
writer->writeElement(name, false, IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE,
903
core::stringw(node->getTypeName()).c_str());
906
writer->writeLineBreak();
907
writer->writeLineBreak();
910
writer->writeLineBreak();
915
core::list<IGUIElement*>::ConstIterator it = node->getChildren().begin();
916
for (; it != node->getChildren().end(); ++it)
918
if (!(*it)->isSubElement())
919
writeGUIElement(writer, (*it));
922
// write closing brace if required
923
if (attr->getAttributeCount() != 0)
925
writer->writeClosingTag(name);
926
writer->writeLineBreak();
927
writer->writeLineBreak();
934
//! Writes attributes of the environment
935
void CGUIEnvironment::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
937
IGUISkin* skin = getSkin();
941
out->addEnum("Skin", getSkin()->getType(), GUISkinTypeNames);
942
skin->serializeAttributes(out, options);
947
//! Reads attributes of the environment
948
void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
950
if (in->existsAttribute("Skin"))
952
IGUISkin *skin = getSkin();
954
EGUI_SKIN_TYPE t = (EGUI_SKIN_TYPE) in->getAttributeAsEnumeration("Skin",GUISkinTypeNames);
955
if ( !skin || t != skin->getType())
957
skin = createSkin(t);
966
skin->deserializeAttributes(in, options);
971
RelativeRect = AbsoluteRect =
972
core::rect<s32>(core::position2d<s32>(0,0),
973
Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d<s32>(0,0));
977
//! adds a button. The returned pointer must not be dropped.
978
IGUIButton* CGUIEnvironment::addButton(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)
980
IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle);
982
button->setText(text);
985
button->setToolTipText ( tooltiptext );
992
//! adds a window. The returned pointer must not be dropped.
993
IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool modal,
994
const wchar_t* text, IGUIElement* parent, s32 id)
996
parent = parent ? parent : this;
998
IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle);
1005
// 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
1006
// careful not to get virtual function call, like OnEvent, in the window.
1007
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
1008
modalScreen->drop();
1009
modalScreen->addChild(win);
1016
//! adds a modal screen. The returned pointer must not be dropped.
1017
IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent)
1019
parent = parent ? parent : this;
1021
IGUIElement *win = new CGUIModalScreen(this, parent, -1);
1028
//! Adds a message box.
1029
IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text,
1030
bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image)
1035
parent = parent ? parent : this;
1037
core::rect<s32> rect;
1038
core::dimension2d<u32> screenDim, msgBoxDim;
1040
screenDim.Width = parent->getAbsolutePosition().getWidth();
1041
screenDim.Height = parent->getAbsolutePosition().getHeight();
1042
msgBoxDim.Width = 2;
1043
msgBoxDim.Height = 2;
1045
rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2;
1046
rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2;
1047
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width;
1048
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height;
1050
IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,
1051
parent, id, rect, image);
1056
// 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
1057
// careful not to get virtual function call, like OnEvent, in the CGUIMessageBox.
1058
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
1059
modalScreen->drop();
1060
modalScreen->addChild( win );
1068
//! adds a scrollbar. The returned pointer must not be dropped.
1069
IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)
1071
IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle);
1076
//! Adds a table to the environment
1077
IGUITable* CGUIEnvironment::addTable(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, bool drawBackground)
1079
CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false);
1085
//! Adds an image element.
1086
IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos,
1087
bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text)
1089
core::dimension2d<s32> sz(0,0);
1091
sz = core::dimension2d<s32>(image->getOriginalSize());
1093
IGUIImage* img = new CGUIImage(this, parent ? parent : this,
1094
id, core::rect<s32>(pos, sz));
1099
if (useAlphaChannel)
1100
img->setUseAlphaChannel(true);
1103
img->setImage(image);
1110
//! adds an image. The returned pointer must not be dropped.
1111
IGUIImage* CGUIEnvironment::addImage(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
1113
IGUIImage* img = new CGUIImage(this, parent ? parent : this,
1124
//! adds an mesh viewer. The returned pointer must not be dropped.
1125
IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
1127
IGUIMeshViewer* v = new CGUIMeshViewer(this, parent ? parent : this,
1139
IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
1141
IGUICheckBox* b = new CGUICheckBox(checked, this,
1142
parent ? parent : this , id , rectangle);
1153
IGUIListBox* CGUIEnvironment::addListBox(const core::rect<s32>& rectangle,
1154
IGUIElement* parent, s32 id, bool drawBackground)
1156
IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle,
1157
true, drawBackground, false);
1159
if (CurrentSkin && CurrentSkin->getSpriteBank())
1161
b->setSpriteBank(CurrentSkin->getSpriteBank());
1163
else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP)
1165
b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank());
1172
//! adds a tree view
1173
IGUITreeView* CGUIEnvironment::addTreeView(const core::rect<s32>& rectangle,
1174
IGUIElement* parent, s32 id,
1175
bool drawBackground,
1176
bool scrollBarVertical, bool scrollBarHorizontal)
1178
IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle,
1179
true, drawBackground, scrollBarVertical, scrollBarHorizontal);
1181
b->setIconFont ( getBuiltInFont () );
1186
//! adds a file open dialog. The returned pointer must not be dropped.
1187
IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title,
1188
bool modal, IGUIElement* parent, s32 id)
1190
parent = parent ? parent : this;
1192
IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id);
1197
// 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
1198
// careful not to get virtual function call, like OnEvent, in the window.
1199
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
1200
modalScreen->drop();
1201
modalScreen->addChild(d);
1208
//! adds a color select dialog. The returned pointer must not be dropped.
1209
IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title,
1210
bool modal, IGUIElement* parent, s32 id)
1212
parent = parent ? parent : this;
1214
IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title,
1220
// 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
1221
// careful not to get virtual function call, like OnEvent, in the window.
1222
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
1223
modalScreen->drop();
1224
modalScreen->addChild(d);
1231
//! adds a static text. The returned pointer must not be dropped.
1232
IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text,
1233
const core::rect<s32>& rectangle,
1234
bool border, bool wordWrap,
1235
IGUIElement* parent, s32 id, bool background)
1237
IGUIStaticText* d = new CGUIStaticText(text, border, this,
1238
parent ? parent : this, id, rectangle, background);
1240
d->setWordWrap(wordWrap);
1247
//! Adds an edit box. The returned pointer must not be dropped.
1248
IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text,
1249
const core::rect<s32>& rectangle, bool border,
1250
IGUIElement* parent, s32 id)
1252
IGUIEditBox* d = new CGUIEditBox(text, border, this,
1253
parent ? parent : this, id, rectangle);
1260
//! Adds a spin box to the environment
1261
IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text,
1262
const core::rect<s32> &rectangle,
1263
bool border,IGUIElement* parent, s32 id)
1265
IGUISpinBox* d = new CGUISpinBox(text, border,this,
1266
parent ? parent : this, id, rectangle);
1273
//! Adds a tab control to the environment.
1274
IGUITabControl* CGUIEnvironment::addTabControl(const core::rect<s32>& rectangle,
1275
IGUIElement* parent, bool fillbackground, bool border, s32 id)
1277
IGUITabControl* t = new CGUITabControl(this, parent ? parent : this,
1278
rectangle, fillbackground, border, id);
1284
//! Adds tab to the environment.
1285
IGUITab* CGUIEnvironment::addTab(const core::rect<s32>& rectangle,
1286
IGUIElement* parent, s32 id)
1288
IGUITab* t = new CGUITab(-1, this, parent ? parent : this,
1295
//! Adds a context menu to the environment.
1296
IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect<s32>& rectangle,
1297
IGUIElement* parent, s32 id)
1299
IGUIContextMenu* c = new CGUIContextMenu(this,
1300
parent ? parent : this, id, rectangle, true);
1306
//! Adds a menu to the environment.
1307
IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id)
1312
IGUIContextMenu* c = new CGUIMenu(this,
1313
parent, id, core::rect<s32>(0,0,
1314
parent->getAbsolutePosition().getWidth(),
1315
parent->getAbsolutePosition().getHeight()));
1322
//! Adds a toolbar to the environment. It is like a menu is always placed on top
1323
//! in its parent, and contains buttons.
1324
IGUIToolBar* CGUIEnvironment::addToolBar(IGUIElement* parent, s32 id)
1329
IGUIToolBar* b = new CGUIToolBar(this, parent, id, core::rect<s32>(0,0,10,10));
1335
//! Adds an element for fading in or out.
1336
IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect<s32>* rectangle, IGUIElement* parent, s32 id)
1338
core::rect<s32> rect;
1343
rect = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Driver->getScreenSize()));
1348
IGUIInOutFader* fader = new CGUIInOutFader(this, parent, id, rect);
1354
//! Adds a combo box to the environment.
1355
IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect<s32>& rectangle,
1356
IGUIElement* parent, s32 id)
1358
IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this,
1365
//! returns the font
1366
IGUIFont* CGUIEnvironment::getFont(const io::path& filename)
1368
// search existing font
1371
f.NamedPath.setPath(filename);
1373
s32 index = Fonts.binary_search(f);
1375
return Fonts[index].Font;
1377
// font doesn't exist, attempt to load it
1379
// does the file exist?
1381
if (!FileSystem->existFile(filename))
1383
os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR);
1388
io::IXMLReader *xml = FileSystem->createXMLReader(filename );
1391
// this is an XML font, but we need to know what type
1392
EGUI_FONT_TYPE t = EGFT_CUSTOM;
1395
while(xml->read() && !found)
1397
if (xml->getNodeType() == io::EXN_ELEMENT)
1399
if (core::stringw(L"font") == xml->getNodeName())
1401
if (core::stringw(L"vector") == xml->getAttributeValue(L"type"))
1406
else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
1418
CGUIFont* font = new CGUIFont(this, filename);
1419
ifont = (IGUIFont*)font;
1420
// change working directory, for loading textures
1421
io::path workingDir = FileSystem->getWorkingDirectory();
1422
FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath()));
1425
if (!font->load(xml))
1431
// change working dir back again
1432
FileSystem->changeWorkingDirectoryTo( workingDir );
1434
else if (t==EGFT_VECTOR)
1436
// todo: vector fonts
1437
os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR);
1439
//CGUIFontVector* font = new CGUIFontVector(Driver);
1440
//ifont = (IGUIFont*)font;
1441
//if (!font->load(xml))
1450
CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() );
1451
ifont = (IGUIFont*)font;
1452
if (!font->load(f.NamedPath.getPath()))
1468
//! add an externally loaded font
1469
IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font)
1474
f.NamedPath.setPath(name);
1475
s32 index = Fonts.binary_search(f);
1477
return Fonts[index].Font;
1485
//! remove loaded font
1486
void CGUIEnvironment::removeFont(IGUIFont* font)
1490
for ( u32 i=0; i<Fonts.size(); ++i )
1492
if ( Fonts[i].Font == font )
1494
Fonts[i].Font->drop();
1501
//! returns default font
1502
IGUIFont* CGUIEnvironment::getBuiltInFont() const
1507
return Fonts[0].Font;
1511
IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename)
1513
// search for the file name
1516
b.NamedPath.setPath(filename);
1518
s32 index = Banks.binary_search(b);
1520
return Banks[index].Bank;
1522
// we don't have this sprite bank, we should load it
1523
if (!FileSystem->existFile(b.NamedPath.getPath()))
1525
os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_DEBUG);
1535
IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name)
1537
// no duplicate names allowed
1540
b.NamedPath.setPath(name);
1542
const s32 index = Banks.binary_search(b);
1546
// create a new sprite bank
1548
b.Bank = new CGUISpriteBank(this);
1555
//! Creates the image list from the given texture.
1556
IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture,
1557
core::dimension2d<s32> imageSize, bool useAlphaChannel )
1559
CGUIImageList* imageList = new CGUIImageList( Driver );
1560
if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) )
1569
//! Returns the root gui element.
1570
IGUIElement* CGUIEnvironment::getRootGUIElement()
1576
//! Returns the next element in the tab group starting at the focused element
1577
IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)
1579
// start the search at the root of the current tab group
1580
IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0;
1581
s32 startOrder = -1;
1583
// if we're searching for a group
1584
if (group && startPos)
1586
startOrder = startPos->getTabOrder();
1589
if (!group && Focus && !Focus->isTabGroup())
1591
startOrder = Focus->getTabOrder();
1592
if (startOrder == -1)
1594
// this element is not part of the tab cycle,
1595
// but its parent might be...
1596
IGUIElement *el = Focus;
1597
while (el && el->getParent() && startOrder == -1)
1599
el = el->getParent();
1600
startOrder = el->getTabOrder();
1606
if (group || !startPos)
1607
startPos = this; // start at the root
1610
IGUIElement *closest = 0;
1611
IGUIElement *first = 0;
1612
startPos->getNextElement(startOrder, reverse, group, first, closest);
1615
return closest; // we found an element
1617
return first; // go to the end or the start
1619
return this; // no group found? root group
1625
//! creates an GUI Environment
1626
IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,
1627
video::IVideoDriver* Driver,
1630
return new CGUIEnvironment(fs, Driver, op);
1634
} // end namespace gui
1635
} // end namespace irr
1637
#endif // _IRR_COMPILE_WITH_GUI_