#include "CGUIEnvironment.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IVideoDriver.h"
#include "CGUISkin.h"
#include "CGUIButton.h"
#include "CGUIWindow.h"
#include "CGUIScrollBar.h"
#include "CGUIFont.h"
#include "CGUISpriteBank.h"
#include "CGUIImage.h"
#include "CGUIMeshViewer.h"
#include "CGUICheckBox.h"
#include "CGUIListBox.h"
#include "CGUITreeView.h"
#include "CGUIImageList.h"
#include "CGUIFileOpenDialog.h"
#include "CGUIColorSelectDialog.h"
#include "CGUIStaticText.h"
#include "CGUIEditBox.h"
#include "CGUISpinBox.h"
#include "CGUIInOutFader.h"
#include "CGUIMessageBox.h"
#include "CGUIModalScreen.h"
#include "CGUITabControl.h"
#include "CGUIContextMenu.h"
#include "CGUIComboBox.h"
#include "CGUIMenu.h"
#include "CGUIToolBar.h"
#include "CGUITable.h"
#include "CDefaultGUIElementFactory.h"
#include "IWriteFile.h"
#include "IXMLWriter.h"
#include "BuiltInFont.h"
#include "os.h"
namespace irr
{
namespace gui
{
const wchar_t* IRR_XML_FORMAT_GUI_ENV = L"irr_gui";
const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT = L"element";
const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE = L"type";
CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op)
: 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))),
Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0),
FileSystem(fs), UserReceiver(0), Operator(op)
{
if (Driver)
Driver->grab();
if (FileSystem)
FileSystem->grab();
if (Operator)
Operator->grab();
#ifdef _DEBUG
IGUIEnvironment::setDebugName("CGUIEnvironment");
#endif
IGUIElementFactory* factory = new CDefaultGUIElementFactory(this);
registerGUIElementFactory(factory);
factory->drop();
loadBuiltInFont();
IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC );
setSkin(skin);
skin->drop();
ToolTip.LastTime = 0;
ToolTip.EnterTime = 0;
ToolTip.LaunchTime = 1000;
ToolTip.RelaunchTime = 500;
ToolTip.Element = 0;
Environment = this;
setTabGroup(true);
}
CGUIEnvironment::~CGUIEnvironment()
{
if ( HoveredNoSubelement && HoveredNoSubelement != this )
{
HoveredNoSubelement->drop();
HoveredNoSubelement = 0;
}
if (Hovered && Hovered != this)
{
Hovered->drop();
Hovered = 0;
}
if (Driver)
{
Driver->drop();
Driver = 0;
}
if (Focus)
{
Focus->drop();
Focus = 0;
}
if (ToolTip.Element)
{
ToolTip.Element->drop();
ToolTip.Element = 0;
}
if (FileSystem)
{
FileSystem->drop();
FileSystem = 0;
}
if (Operator)
{
Operator->drop();
Operator = 0;
}
if (CurrentSkin)
{
CurrentSkin->drop();
CurrentSkin = 0;
}
u32 i;
for (i=0; i<Banks.size(); ++i)
if (Banks[i].Bank)
Banks[i].Bank->drop();
for (i=0; i<Fonts.size(); ++i)
Fonts[i].Font->drop();
for (i=0; i<GUIElementFactoryList.size(); ++i)
GUIElementFactoryList[i]->drop();
}
void CGUIEnvironment::loadBuiltInFont()
{
io::path filename = "#DefaultFont";
io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, filename, false);
CGUIFont* font = new CGUIFont(this, filename );
if (!font->load(file))
{
os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR);
font->drop();
file->drop();
return;
}
SFont f;
f.NamedPath.setPath(filename);
f.Font = font;
Fonts.push_back(f);
file->drop();
}
void CGUIEnvironment::drawAll()
{
if (Driver)
{
core::dimension2d<s32> dim(Driver->getScreenSize());
if (AbsoluteRect.LowerRightCorner.X != dim.Width ||
AbsoluteRect.LowerRightCorner.Y != dim.Height)
{
DesiredRect.LowerRightCorner = dim;
AbsoluteClippingRect = DesiredRect;
AbsoluteRect = DesiredRect;
updateAbsolutePosition();
}
}
if (ToolTip.Element)
bringToFront(ToolTip.Element);
draw();
OnPostRender ( os::Timer::getTime () );
}
bool CGUIEnvironment::setFocus(IGUIElement* element)
{
if (Focus == element)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
if (element == this)
element = 0;
if (element)
element->grab();
IGUIElement *currentFocus = 0;
if (Focus)
{
currentFocus = Focus;
currentFocus->grab();
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = Focus;
e.GUIEvent.Element = element;
e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;
if (Focus->OnEvent(e))
{
if (element)
element->drop();
currentFocus->drop();
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
currentFocus->drop();
currentFocus = 0;
}
if (element)
{
currentFocus = Focus;
if (currentFocus)
currentFocus->grab();
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = element;
e.GUIEvent.Element = Focus;
e.GUIEvent.EventType = EGET_ELEMENT_FOCUSED;
if (element->OnEvent(e))
{
if (element)
element->drop();
if (currentFocus)
currentFocus->drop();
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
}
if (currentFocus)
currentFocus->drop();
if (Focus)
Focus->drop();
Focus = element;
return true;
}
IGUIElement* CGUIEnvironment::getFocus() const
{
return Focus;
}
bool CGUIEnvironment::removeFocus(IGUIElement* element)
{
if (Focus && Focus==element)
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = Focus;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST;
if (Focus->OnEvent(e))
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
}
if (Focus)
{
Focus->drop();
Focus = 0;
}
return true;
}
bool CGUIEnvironment::hasFocus(IGUIElement* element) const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return (element == Focus);
}
video::IVideoDriver* CGUIEnvironment::getVideoDriver() const
{
return Driver;
}
io::IFileSystem* CGUIEnvironment::getFileSystem() const
{
return FileSystem;
}
IOSOperator* CGUIEnvironment::getOSOperator() const
{
return Operator;
}
void CGUIEnvironment::clear()
{
if (Focus)
{
Focus->drop();
Focus = 0;
}
if (Hovered && Hovered != this)
{
Hovered->drop();
Hovered = 0;
}
if ( HoveredNoSubelement && HoveredNoSubelement != this)
{
HoveredNoSubelement->drop();
HoveredNoSubelement = 0;
}
const core::list<IGUIElement*>& children = getRootGUIElement()->getChildren();
while (!children.empty())
(*children.getLast())->remove();
}
bool CGUIEnvironment::OnEvent(const SEvent& event)
{
bool ret = false;
if (UserReceiver
&& (event.EventType != EET_MOUSE_INPUT_EVENT)
&& (event.EventType != EET_KEY_INPUT_EVENT)
&& (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this))
{
ret = UserReceiver->OnEvent(event);
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
void CGUIEnvironment::OnPostRender( u32 time )
{
if ( ToolTip.Element == 0 &&
HoveredNoSubelement && HoveredNoSubelement != this &&
(time - ToolTip.EnterTime >= ToolTip.LaunchTime
|| (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) &&
HoveredNoSubelement->getToolTipText().size() &&
getSkin() &&
getSkin()->getFont(EGDF_TOOLTIP)
)
{
core::rect<s32> pos;
pos.UpperLeftCorner = LastHoveredMousePos;
core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str());
dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2;
dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2;
pos.UpperLeftCorner.Y -= dim.Height+1;
pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1;
pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width;
pos.constrainTo(getAbsolutePosition());
ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true);
ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP));
ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND));
ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP));
ToolTip.Element->setSubElement(true);
ToolTip.Element->grab();
s32 textHeight = ToolTip.Element->getTextHeight();
pos = ToolTip.Element->getRelativePosition();
pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight;
ToolTip.Element->setRelativePosition(pos);
}
if (ToolTip.Element && ToolTip.Element->isVisible() )
{
ToolTip.LastTime = time;
if ( !HoveredNoSubelement ||
!HoveredNoSubelement->isVisible() ||
!HoveredNoSubelement->getParent()
)
{
ToolTip.Element->remove();
ToolTip.Element->drop();
ToolTip.Element = 0;
}
}
IGUIElement::OnPostRender ( time );
}
void CGUIEnvironment::updateHoveredElement(core::position2d<s32> mousePos)
{
IGUIElement* lastHovered = Hovered;
IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement;
LastHoveredMousePos = mousePos;
Hovered = getElementFromPoint(mousePos);
if ( ToolTip.Element && Hovered == ToolTip.Element )
{
ToolTip.Element->remove();
ToolTip.Element->drop();
ToolTip.Element = 0;
Hovered = getElementFromPoint(mousePos);
}
HoveredNoSubelement = Hovered;
while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() )
{
HoveredNoSubelement = HoveredNoSubelement->getParent();
}
if (Hovered && Hovered != this)
Hovered->grab();
if ( HoveredNoSubelement && HoveredNoSubelement != this)
HoveredNoSubelement->grab();
if (Hovered != lastHovered)
{
SEvent event;
event.EventType = EET_GUI_EVENT;
if (lastHovered)
{
event.GUIEvent.Caller = lastHovered;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_ELEMENT_LEFT;
lastHovered->OnEvent(event);
}
if ( Hovered )
{
event.GUIEvent.Caller = Hovered;
event.GUIEvent.Element = Hovered;
event.GUIEvent.EventType = EGET_ELEMENT_HOVERED;
Hovered->OnEvent(event);
}
}
if ( lastHoveredNoSubelement != HoveredNoSubelement )
{
if (ToolTip.Element)
{
ToolTip.Element->remove();
ToolTip.Element->drop();
ToolTip.Element = 0;
}
if ( HoveredNoSubelement )
{
u32 now = os::Timer::getTime();
ToolTip.EnterTime = now;
}
}
if (lastHovered && lastHovered != this)
lastHovered->drop();
if (lastHoveredNoSubelement && lastHoveredNoSubelement != this)
lastHoveredNoSubelement->drop();
}
void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr)
{
UserReceiver = evr;
}
bool CGUIEnvironment::postEventFromUser(const SEvent& event)
{
switch(event.EventType)
{
case EET_GUI_EVENT:
break;
case EET_MOUSE_INPUT_EVENT:
updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
if ( (Hovered && Hovered != Focus) || !Focus )
{
setFocus(Hovered);
}
if (Focus && Focus->OnEvent(event))
return true;
if (!Focus && Hovered)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return Hovered->OnEvent(event);
}
break;
case EET_KEY_INPUT_EVENT:
{
if (event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.PressedDown &&
event.KeyInput.Key == KEY_TAB)
{
IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control);
if (next && next != Focus)
{
if (setFocus(next))
return true;
}
}
if (Focus)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return Focus->OnEvent(event);
}
}
break;
default:
break;
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
IGUISkin* CGUIEnvironment::getSkin() const
{
return CurrentSkin;
}
void CGUIEnvironment::setSkin(IGUISkin* skin)
{
if (CurrentSkin==skin)
return;
if (CurrentSkin)
CurrentSkin->drop();
CurrentSkin = skin;
if (CurrentSkin)
CurrentSkin->grab();
}
IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type)
{
IGUISkin* skin = new CGUISkin(type, Driver);
IGUIFont* builtinfont = getBuiltInFont();
IGUIFontBitmap* bitfont = 0;
if (builtinfont && builtinfont->getType() == EGFT_BITMAP)
bitfont = (IGUIFontBitmap*)builtinfont;
IGUISpriteBank* bank = 0;
skin->setFont(builtinfont);
if (bitfont)
bank = bitfont->getSpriteBank();
skin->setSpriteBank(bank);
return skin;
}
IGUIElementFactory* CGUIEnvironment::getDefaultGUIElementFactory() const
{
return getGUIElementFactory(0);
}
void CGUIEnvironment::registerGUIElementFactory(IGUIElementFactory* factoryToAdd)
{
if (factoryToAdd)
{
factoryToAdd->grab();
GUIElementFactoryList.push_back(factoryToAdd);
}
}
u32 CGUIEnvironment::getRegisteredGUIElementFactoryCount() const
{
return GUIElementFactoryList.size();
}
IGUIElementFactory* CGUIEnvironment::getGUIElementFactory(u32 index) const
{
if (index < GUIElementFactoryList.size())
return GUIElementFactoryList[index];
else
return 0;
}
IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* parent)
{
IGUIElement* node=0;
if (!parent)
parent = this;
for (s32 i=GUIElementFactoryList.size()-1; i>=0 && !node; --i)
node = GUIElementFactoryList[i]->addGUIElement(elementName, parent);
return node;
}
bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start)
{
io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
if (!file)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
bool ret = saveGUI(file, start);
file->drop();
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start)
{
if (!file)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
if (!writer)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
writer->writeXMLHeader();
writeGUIElement(writer, start ? start : this);
writer->drop();
return true;
}
bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent)
{
io::IReadFile* read = FileSystem->createAndOpenFile(filename);
if (!read)
{
os::Printer::log("Unable to open gui file", filename, ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
bool ret = loadGUI(read, parent);
read->drop();
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent)
{
if (!file)
{
os::Printer::log("Unable to open GUI file", ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
io::IXMLReader* reader = FileSystem->createXMLReader(file);
if (!reader)
{
os::Printer::log("GUI is not a valid XML file", file->getFileName(), ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
while(reader->read())
{
readGUIElement(reader, parent);
}
reader->drop();
return true;
}
void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node)
{
if (!reader)
return;
io::EXML_NODE nodeType = reader->getNodeType();
if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END)
return;
if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
if (!node)
node = this;
}
else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()))
{
const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE);
node = addGUIElement(attrName.c_str(), node);
if (!node)
os::Printer::log("Could not create GUI element of unknown type", attrName.c_str());
}
while(reader->read())
{
bool endreached = false;
switch (reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
endreached = true;
}
break;
case io::EXN_ELEMENT:
if (!wcscmp(L"attributes", reader->getNodeName()))
{
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
attr->read(reader, true);
if (node)
node->deserializeAttributes(attr);
attr->drop();
}
else
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
readGUIElement(reader, node);
}
else
{
os::Printer::log("Found unknown element in irrlicht GUI file",
core::stringc(reader->getNodeName()).c_str());
}
break;
default:
break;
}
if (endreached)
break;
}
}
void CGUIEnvironment::writeGUIElement(io::IXMLWriter* writer, IGUIElement* node)
{
if (!writer || !node )
return;
const wchar_t* name = 0;
io::IAttributes* attr = FileSystem->createEmptyAttributes();
node->serializeAttributes(attr);
if (attr->getAttributeCount() != 0)
{
if (node == this)
{
name = IRR_XML_FORMAT_GUI_ENV;
writer->writeElement(name, false);
}
else
{
name = IRR_XML_FORMAT_GUI_ELEMENT;
writer->writeElement(name, false, IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE,
core::stringw(node->getTypeName()).c_str());
}
writer->writeLineBreak();
writer->writeLineBreak();
attr->write(writer);
writer->writeLineBreak();
}
core::list<IGUIElement*>::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
{
if (!(*it)->isSubElement())
writeGUIElement(writer, (*it));
}
if (attr->getAttributeCount() != 0)
{
writer->writeClosingTag(name);
writer->writeLineBreak();
writer->writeLineBreak();
}
attr->drop();
}
void CGUIEnvironment::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
IGUISkin* skin = getSkin();
if (skin)
{
out->addEnum("Skin", getSkin()->getType(), GUISkinTypeNames);
skin->serializeAttributes(out, options);
}
}
void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
if (in->existsAttribute("Skin"))
{
IGUISkin *skin = getSkin();
EGUI_SKIN_TYPE t = (EGUI_SKIN_TYPE) in->getAttributeAsEnumeration("Skin",GUISkinTypeNames);
if ( !skin || t != skin->getType())
{
skin = createSkin(t);
setSkin(skin);
skin->drop();
}
skin = getSkin();
if (skin)
{
skin->deserializeAttributes(in, options);
}
}
RelativeRect = AbsoluteRect =
core::rect<s32>(core::position2d<s32>(0,0),
Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d<s32>(0,0));
}
IGUIButton* CGUIEnvironment::addButton(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)
{
IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle);
if (text)
button->setText(text);
if ( tooltiptext )
button->setToolTipText ( tooltiptext );
button->drop();
return button;
}
IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool modal,
const wchar_t* text, IGUIElement* parent, s32 id)
{
parent = parent ? parent : this;
IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle);
if (text)
win->setText(text);
win->drop();
if (modal)
{
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(win);
}
return win;
}
IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent)
{
parent = parent ? parent : this;
IGUIElement *win = new CGUIModalScreen(this, parent, -1);
win->drop();
return win;
}
IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text,
bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image)
{
if (!CurrentSkin)
return 0;
parent = parent ? parent : this;
core::rect<s32> rect;
core::dimension2d<u32> screenDim, msgBoxDim;
screenDim.Width = parent->getAbsolutePosition().getWidth();
screenDim.Height = parent->getAbsolutePosition().getHeight();
msgBoxDim.Width = 2;
msgBoxDim.Height = 2;
rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2;
rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2;
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height;
IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,
parent, id, rect, image);
win->drop();
if (modal)
{
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild( win );
}
return win;
}
IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)
{
IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle);
bar->drop();
return bar;
}
IGUITable* CGUIEnvironment::addTable(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, bool drawBackground)
{
CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false);
b->drop();
return b;
}
IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos,
bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text)
{
core::dimension2d<s32> sz(0,0);
if (image)
sz = core::dimension2d<s32>(image->getOriginalSize());
IGUIImage* img = new CGUIImage(this, parent ? parent : this,
id, core::rect<s32>(pos, sz));
if (text)
img->setText(text);
if (useAlphaChannel)
img->setUseAlphaChannel(true);
if (image)
img->setImage(image);
img->drop();
return img;
}
IGUIImage* CGUIEnvironment::addImage(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
{
IGUIImage* img = new CGUIImage(this, parent ? parent : this,
id, rectangle);
if (text)
img->setText(text);
img->drop();
return img;
}
IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
{
IGUIMeshViewer* v = new CGUIMeshViewer(this, parent ? parent : this,
id, rectangle);
if (text)
v->setText(text);
v->drop();
return v;
}
IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text)
{
IGUICheckBox* b = new CGUICheckBox(checked, this,
parent ? parent : this , id , rectangle);
if (text)
b->setText(text);
b->drop();
return b;
}
IGUIListBox* CGUIEnvironment::addListBox(const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id, bool drawBackground)
{
IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle,
true, drawBackground, false);
if (CurrentSkin && CurrentSkin->getSpriteBank())
{
b->setSpriteBank(CurrentSkin->getSpriteBank());
}
else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP)
{
b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank());
}
b->drop();
return b;
}
IGUITreeView* CGUIEnvironment::addTreeView(const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id,
bool drawBackground,
bool scrollBarVertical, bool scrollBarHorizontal)
{
IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle,
true, drawBackground, scrollBarVertical, scrollBarHorizontal);
b->setIconFont ( getBuiltInFont () );
b->drop();
return b;
}
IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title,
bool modal, IGUIElement* parent, s32 id)
{
parent = parent ? parent : this;
IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id);
d->drop();
if (modal)
{
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(d);
}
return d;
}
IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title,
bool modal, IGUIElement* parent, s32 id)
{
parent = parent ? parent : this;
IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title,
this, parent, id);
d->drop();
if (modal)
{
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(d);
}
return d;
}
IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text,
const core::rect<s32>& rectangle,
bool border, bool wordWrap,
IGUIElement* parent, s32 id, bool background)
{
IGUIStaticText* d = new CGUIStaticText(text, border, this,
parent ? parent : this, id, rectangle, background);
d->setWordWrap(wordWrap);
d->drop();
return d;
}
IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text,
const core::rect<s32>& rectangle, bool border,
IGUIElement* parent, s32 id)
{
IGUIEditBox* d = new CGUIEditBox(text, border, this,
parent ? parent : this, id, rectangle);
d->drop();
return d;
}
IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text,
const core::rect<s32> &rectangle,
bool border,IGUIElement* parent, s32 id)
{
IGUISpinBox* d = new CGUISpinBox(text, border,this,
parent ? parent : this, id, rectangle);
d->drop();
return d;
}
IGUITabControl* CGUIEnvironment::addTabControl(const core::rect<s32>& rectangle,
IGUIElement* parent, bool fillbackground, bool border, s32 id)
{
IGUITabControl* t = new CGUITabControl(this, parent ? parent : this,
rectangle, fillbackground, border, id);
t->drop();
return t;
}
IGUITab* CGUIEnvironment::addTab(const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id)
{
IGUITab* t = new CGUITab(-1, this, parent ? parent : this,
rectangle, id);
t->drop();
return t;
}
IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id)
{
IGUIContextMenu* c = new CGUIContextMenu(this,
parent ? parent : this, id, rectangle, true);
c->drop();
return c;
}
IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id)
{
if (!parent)
parent = this;
IGUIContextMenu* c = new CGUIMenu(this,
parent, id, core::rect<s32>(0,0,
parent->getAbsolutePosition().getWidth(),
parent->getAbsolutePosition().getHeight()));
c->drop();
return c;
}
IGUIToolBar* CGUIEnvironment::addToolBar(IGUIElement* parent, s32 id)
{
if (!parent)
parent = this;
IGUIToolBar* b = new CGUIToolBar(this, parent, id, core::rect<s32>(0,0,10,10));
b->drop();
return b;
}
IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect<s32>* rectangle, IGUIElement* parent, s32 id)
{
core::rect<s32> rect;
if (rectangle)
rect = *rectangle;
else if (Driver)
rect = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Driver->getScreenSize()));
if (!parent)
parent = this;
IGUIInOutFader* fader = new CGUIInOutFader(this, parent, id, rect);
fader->drop();
return fader;
}
IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id)
{
IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this,
id, rectangle);
t->drop();
return t;
}
IGUIFont* CGUIEnvironment::getFont(const io::path& filename)
{
SFont f;
f.NamedPath.setPath(filename);
s32 index = Fonts.binary_search(f);
if (index != -1)
return Fonts[index].Font;
if (!FileSystem->existFile(filename))
{
os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR);
return 0;
}
IGUIFont* ifont=0;
io::IXMLReader *xml = FileSystem->createXMLReader(filename );
if (xml)
{
EGUI_FONT_TYPE t = EGFT_CUSTOM;
bool found=false;
while(xml->read() && !found)
{
if (xml->getNodeType() == io::EXN_ELEMENT)
{
if (core::stringw(L"font") == xml->getNodeName())
{
if (core::stringw(L"vector") == xml->getAttributeValue(L"type"))
{
t = EGFT_VECTOR;
found=true;
}
else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
{
t = EGFT_BITMAP;
found=true;
}
else found=true;
}
}
}
if (t==EGFT_BITMAP)
{
CGUIFont* font = new CGUIFont(this, filename);
ifont = (IGUIFont*)font;
io::path workingDir = FileSystem->getWorkingDirectory();
FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath()));
if (!font->load(xml))
{
font->drop();
font = 0;
ifont = 0;
}
FileSystem->changeWorkingDirectoryTo( workingDir );
}
else if (t==EGFT_VECTOR)
{
os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR);
}
xml->drop();
}
if (!ifont)
{
CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() );
ifont = (IGUIFont*)font;
if (!font->load(f.NamedPath.getPath()))
{
font->drop();
return 0;
}
}
f.Font = ifont;
Fonts.push_back(f);
return ifont;
}
IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font)
{
if (font)
{
SFont f;
f.NamedPath.setPath(name);
s32 index = Fonts.binary_search(f);
if (index != -1)
return Fonts[index].Font;
f.Font = font;
Fonts.push_back(f);
font->grab();
}
return font;
}
void CGUIEnvironment::removeFont(IGUIFont* font)
{
if ( !font )
return;
for ( u32 i=0; i<Fonts.size(); ++i )
{
if ( Fonts[i].Font == font )
{
Fonts[i].Font->drop();
Fonts.erase(i);
return;
}
}
}
IGUIFont* CGUIEnvironment::getBuiltInFont() const
{
if (Fonts.empty())
return 0;
return Fonts[0].Font;
}
IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename)
{
SSpriteBank b;
b.NamedPath.setPath(filename);
s32 index = Banks.binary_search(b);
if (index != -1)
return Banks[index].Bank;
if (!FileSystem->existFile(b.NamedPath.getPath()))
{
os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_ERROR);
return 0;
}
return 0;
}
IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name)
{
SSpriteBank b;
b.NamedPath.setPath(name);
const s32 index = Banks.binary_search(b);
if (index != -1)
return 0;
b.Bank = new CGUISpriteBank(this);
Banks.push_back(b);
return b.Bank;
}
IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture,
core::dimension2d<s32> imageSize, bool useAlphaChannel )
{
CGUIImageList* imageList = new CGUIImageList( Driver );
if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) )
{
imageList->drop();
return 0;
}
return imageList;
}
IGUIElement* CGUIEnvironment::getRootGUIElement()
{
return this;
}
IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)
{
IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0;
s32 startOrder = -1;
if (group && startPos)
{
startOrder = startPos->getTabOrder();
}
else
if (!group && Focus && !Focus->isTabGroup())
{
startOrder = Focus->getTabOrder();
if (startOrder == -1)
{
IGUIElement *el = Focus;
while (el && el->getParent() && startOrder == -1)
{
el = el->getParent();
startOrder = el->getTabOrder();
}
}
}
if (group || !startPos)
startPos = this;
IGUIElement *closest = 0;
IGUIElement *first = 0;
startPos->getNextElement(startOrder, reverse, group, first, closest);
if (closest)
return closest;
else if (first)
return first;
else if (group)
return this;
else
return 0;
}
IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,
video::IVideoDriver* Driver,
IOSOperator* op)
{
return new CGUIEnvironment(fs, Driver, op);
}
}
}
#endif