irrlicht/tools/GUIEditor/CGUIEditWorkspace.cpp

956 lines
26 KiB
C++

// Copyright (C) 2002-2012 Nikolaus Gebhardt / Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// Thanks to Midnight for all his testing, bug fixes and patches :)
#include "CGUIEditWorkspace.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IOSOperator.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "IXMLWriter.h"
#include "IGUISkin.h"
#include "IGUIElementFactory.h"
#include "CGUIEditWindow.h"
#include "IGUIContextMenu.h"
#include "IGUIFileOpenDialog.h"
#include "IGUITreeView.h"
#include "CGUIAttribute.h"
#include "CMemoryReadWriteFile.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIEditWorkspace::CGUIEditWorkspace(IGUIEnvironment* environment, s32 id, IGUIElement *parent)
: IGUIElement(EGUIET_ELEMENT, environment, parent ? parent : environment->getRootGUIElement(), id, environment->getRootGUIElement()->getAbsolutePosition()),
CurrentMode(EGUIEDM_SELECT), MouseOverMode(EGUIEDM_SELECT),
GridSize(10,10), MenuCommandStart(0x3D17), DrawGrid(false), UseGrid(true),
MouseOverElement(0), SelectedElement(0), EditorWindow(0)
{
#ifdef _DEBUG
setDebugName("CGUIEditWorkspace");
#endif
// this element is never saved.
setSubElement(true);
// it resizes to fit a resizing window
setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
// Types which we currently can't handle in editor
// Most of them also just don't make sense in here (like Dialogs)
// TODO: We should have a way to create context-menus
UnusableElementTypeFilter.push_back(EGUIET_CONTEXT_MENU);
UnusableElementTypeFilter.push_back(EGUIET_FILE_OPEN_DIALOG);
UnusableElementTypeFilter.push_back(EGUIET_COLOR_SELECT_DIALOG);
UnusableElementTypeFilter.push_back(EGUIET_MESSAGE_BOX);
UnusableElementTypeFilter.push_back(EGUIET_MODAL_SCREEN);
UnusableElementTypeFilter.push_back(EGUIET_ELEMENT); // wouldn't do anything, so don't show in menu
UnusableElementTypeFilter.push_back(EGUIET_ROOT); // wouldn't do anything, so don't show in menu
EditorWindow = (CGUIEditWindow*) Environment->addGUIElement("GUIEditWindow", this);
if (EditorWindow)
{
EditorWindow->grab();
EditorWindow->setSubElement(true);
Environment->setFocus(EditorWindow);
serializeAttributes(EditorWindow->getOptionEditor()->getAttribs());
EditorWindow->getOptionEditor()->refreshAttribs();
if (EditorWindow->getEnvironmentEditor())
{
Environment->serializeAttributes(EditorWindow->getEnvironmentEditor()->getAttribs());
EditorWindow->getEnvironmentEditor()->refreshAttribs();
}
}
}
//! destructor
CGUIEditWorkspace::~CGUIEditWorkspace()
{
if (EditorWindow)
EditorWindow->drop();
}
void CGUIEditWorkspace::setMenuCommandIDStart(s32 id)
{
MenuCommandStart = id;
}
CGUIEditWorkspace::EGUIEDIT_MODE CGUIEditWorkspace::getModeFromPos(core::position2di p)
{
if (SelectedElement)
{
core::rect<s32> r = SelectedElement->getAbsolutePosition();
if (TLRect.isPointInside(p))
return EGUIEDM_RESIZE_TL;
else if (TRRect.isPointInside(p))
return EGUIEDM_RESIZE_TR;
else if (BLRect.isPointInside(p) )
return EGUIEDM_RESIZE_BL;
else if (BRRect.isPointInside(p))
return EGUIEDM_RESIZE_BR;
else if (TopRect.isPointInside(p))
return EGUIEDM_RESIZE_T;
else if (BRect.isPointInside(p))
return EGUIEDM_RESIZE_B;
else if (LRect.isPointInside(p))
return EGUIEDM_RESIZE_L;
else if (RRect.isPointInside(p))
return EGUIEDM_RESIZE_R;
else if (getEditableElementFromPoint(SelectedElement, p) == SelectedElement)
return EGUIEDM_MOVE;
else
return EGUIEDM_SELECT;
}
return EGUIEDM_SELECT;
}
IGUIElement* CGUIEditWorkspace::getEditableElementFromPoint(IGUIElement *start, const core::position2di &point, s32 index )
{
IGUIElement* target = 0;
// we have to search from back to front.
core::list<IGUIElement*>::ConstIterator it = start->getChildren().getLast();
s32 count=0;
while(it != start->getChildren().end())
{
target = getEditableElementFromPoint((*it),point);
if (target)
{
if (!target->isSubElement() && !isMyChild(target) && target != this)
{
if (index == count)
return target;
else
count++;
}
else
target = 0;
}
--it;
}
if (start->getAbsolutePosition().isPointInside(point))
target = start;
return target;
}
void CGUIEditWorkspace::setSelectedElement(IGUIElement *sel)
{
IGUIElement* focus = Environment->getFocus();
// we only give focus back to children
if (!isMyChild(focus))
focus = 0;
if (SelectedElement != Parent)
{
if (SelectedElement != sel && EditorWindow)
{
EditorWindow->setSelectedElement(sel);
SelectedElement = sel;
}
}
else
SelectedElement = 0;
if (focus)
Environment->setFocus(focus);
else
Environment->setFocus(this);
}
IGUIElement* CGUIEditWorkspace::getSelectedElement()
{
return SelectedElement;
}
void CGUIEditWorkspace::selectNextSibling()
{
IGUIElement* p=0;
if (SelectedElement && SelectedElement->getParent())
p = SelectedElement->getParent();
else
p = Parent;
core::list<IGUIElement*>::ConstIterator it = p->getChildren().begin();
// find selected element
if (SelectedElement)
while (*it != SelectedElement)
++it;
if (it !=p->getChildren().end())
++it;
// find next non sub-element
while (it != p->getChildren().end() && (*it)->isSubElement())
++it;
if (it != p->getChildren().end())
setSelectedElement(*it);
}
void CGUIEditWorkspace::selectPreviousSibling()
{
IGUIElement* p=0;
if (SelectedElement && SelectedElement->getParent())
p = SelectedElement->getParent();
else
p = Parent;
core::list<IGUIElement*>::ConstIterator it = p->getChildren().getLast();
// find selected element
if (SelectedElement)
while (*it != SelectedElement)
--it;
if (it != p->getChildren().end())
--it;
// find next non sub-element
while (it != p->getChildren().end() && (*it)->isSubElement())
--it;
if (it != p->getChildren().end())
setSelectedElement(*it);
}
//! called if an event happened.
bool CGUIEditWorkspace::OnEvent(const SEvent &e)
{
IGUIFileOpenDialog* dialog=0;
switch(e.EventType)
{
case ATTRIBEDIT_ATTRIB_CHANGED:
{
switch (e.UserEvent.UserData1)
{
case EGUIEDCE_ATTRIB_EDITOR:
{
// update selected items attributes
if (SelectedElement)
{
SelectedElement->deserializeAttributes(EditorWindow->getAttributeEditor()->getAttribs());
EditorWindow->updateTree();
}
return true;
}
case EGUIEDCE_OPTION_EDITOR:
{
// update editor options
deserializeAttributes(EditorWindow->getOptionEditor()->getAttribs());
return true;
}
case EGUIEDCE_ENV_EDITOR:
{
// update environment
Environment->deserializeAttributes(EditorWindow->getEnvironmentEditor()->getAttribs());
return true;
}
}
}
break;
case EET_KEY_INPUT_EVENT:
if (!e.KeyInput.PressedDown)
{
switch (e.KeyInput.Key)
{
case KEY_DELETE:
if (SelectedElement)
{
IGUIElement* el = SelectedElement;
setSelectedElement(0);
MouseOverElement = 0;
el->remove();
EditorWindow->updateTree();
}
break;
case KEY_KEY_X:
if (e.KeyInput.Control && SelectedElement)
{
// cut
CopySelectedElementXML();
// delete element
IGUIElement *el = SelectedElement;
setSelectedElement(0);
MouseOverElement = 0;
el->remove();
}
break;
case KEY_KEY_C:
// copy
if (e.KeyInput.Control && SelectedElement)
{
CopySelectedElementXML();
}
break;
case KEY_KEY_V:
// paste
if (e.KeyInput.Control)
{
PasteXMLToSelectedElement();
}
break;
default:
break;
}
return true;
}
break;
case EET_MOUSE_INPUT_EVENT:
switch(e.MouseInput.Event)
{
case EMIE_MOUSE_WHEEL:
{
f32 wheel = e.MouseInput.Wheel;
if (wheel > 0)
selectPreviousSibling();
else
selectNextSibling();
}
break;
case EMIE_LMOUSE_PRESSED_DOWN:
{
core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y);
IGUIElement* newSelection = getElementFromPoint(p);
if (newSelection != this && isMyChild(newSelection) ) // redirect event
{
Environment->setFocus(newSelection);
return true;
}
// hide the gui editor
if (EditorWindow)
EditorWindow->setVisible(false);
if (CurrentMode == EGUIEDM_SELECT)
{
if (SelectedElement)
{
// start moving or dragging
CurrentMode = getModeFromPos(p);
if (CurrentMode == EGUIEDM_MOVE)
StartMovePos = SelectedElement->getAbsolutePosition().UpperLeftCorner;
DragStart = p;
SelectedArea = SelectedElement->getAbsolutePosition();
}
if (CurrentMode < EGUIEDM_MOVE)
{
// selecting an element...
MouseOverElement = getEditableElementFromPoint(Parent, p);
if (MouseOverElement == Parent)
MouseOverElement = 0;
setSelectedElement(MouseOverElement);
}
}
break;
}
case EMIE_RMOUSE_PRESSED_DOWN:
if (CurrentMode == EGUIEDM_SELECT_NEW_PARENT || CurrentMode >= EGUIEDM_MOVE)
{
// cancel dragging
CurrentMode = EGUIEDM_SELECT;
}
else
{
DragStart = core::position2di(e.MouseInput.X,e.MouseInput.Y);
// root menu
IGUIContextMenu* mnu = Environment->addContextMenu(
core::rect<s32>(e.MouseInput.X, e.MouseInput.Y, e.MouseInput.Y+100, e.MouseInput.Y+100),this);
mnu->addItem(L"File",-1,true,true);
mnu->addItem(L"Edit",-1,true,true);
mnu->addItem(L"View",-1,true,true);
mnu->addItem(SelectedElement ? L"Add child" : L"Add" ,-1,true,true);
// file menu
IGUIContextMenu* sub = mnu->getSubMenu(0);
IGUIContextMenu* sub2 =0;
sub->addItem(L"New", MenuCommandStart + EGUIEDMC_FILE_NEW );
sub->addItem(L"Load...",MenuCommandStart + EGUIEDMC_FILE_LOAD);
sub->addItem(L"Save...",MenuCommandStart + EGUIEDMC_FILE_SAVE);
// edit menu
sub = mnu->getSubMenu(1);
sub->addItem(L"Cut (ctrl+x)", MenuCommandStart + EGUIEDMC_CUT_ELEMENT, (SelectedElement != 0));
sub->addItem(L"Copy (ctrl+c)", MenuCommandStart + EGUIEDMC_COPY_ELEMENT, (SelectedElement != 0));
sub->addItem(L"Paste (ctrl+v)", MenuCommandStart + EGUIEDMC_PASTE_ELEMENT,
(core::stringc(Environment->getOSOperator()->getTextFromClipboard()) != ""));
sub->addItem(L"Delete (del)", MenuCommandStart + EGUIEDMC_DELETE_ELEMENT, (SelectedElement != 0));
sub->addSeparator();
sub->addItem(L"Set parent", MenuCommandStart + EGUIEDMC_SET_PARENT, (SelectedElement != 0));
sub->addItem(L"Bring to front", MenuCommandStart + EGUIEDMC_BRING_TO_FRONT, (SelectedElement != 0));
sub->addSeparator();
sub->addItem(L"Save to XML...", MenuCommandStart + EGUIEDMC_SAVE_ELEMENT, (SelectedElement != 0));
sub = mnu->getSubMenu(2);
// view menu
if (EditorWindow)
sub->addItem(EditorWindow->isVisible() ? L"Hide window" : L"Show window", MenuCommandStart + EGUIEDMC_TOGGLE_EDITOR);
sub = mnu->getSubMenu(3);
s32 i,j,c=0;
sub->addItem(L"Default factory",-1,true, true);
// add elements from each factory
for (i=0; u32(i) < Environment->getRegisteredGUIElementFactoryCount(); ++i)
{
sub2 = sub->getSubMenu(i);
IGUIElementFactory *f = Environment->getGUIElementFactory(i);
for (j=0; j< f->getCreatableGUIElementTypeCount(); ++j)
{
EGUI_ELEMENT_TYPE type = f->getCreateableGUIElementType(j);
if ( UnusableElementTypeFilter.linear_search(type) < 0 )
sub2->addItem(core::stringw(f->getCreateableGUIElementTypeName(j)).c_str(), MenuCommandStart + EGUIEDMC_COUNT + c);
c++;
}
if (u32(i+1) < Environment->getRegisteredGUIElementFactoryCount())
{
core::stringw strFact;
strFact = L"Factory ";
strFact += i+1;
sub->addItem(strFact.c_str(),-1, true, true);
}
}
sub->addSeparator();
sub->addItem(L"From XML...", MenuCommandStart + EGUIEDMC_INSERT_XML);
// set focus to menu
Environment->setFocus(mnu);
}
break;
case EMIE_LMOUSE_LEFT_UP:
// make window visible again
if (EditorWindow)
EditorWindow->setVisible(true);
if (CurrentMode == EGUIEDM_SELECT_NEW_PARENT)
{
if (SelectedElement)
{
MouseOverElement = getEditableElementFromPoint(Parent,
core::position2di(e.MouseInput.X,e.MouseInput.Y));
if (MouseOverElement)
{
MouseOverElement->addChild(SelectedElement);
setSelectedElement(0);
setSelectedElement(SelectedElement);
}
}
CurrentMode = EGUIEDM_SELECT;
}
else if (CurrentMode >= EGUIEDM_MOVE)
{
IGUIElement *sel = SelectedElement;
// unselect
setSelectedElement(0);
// move
core::position2d<s32> p(0,0);
if (sel->getParent())
p = sel->getParent()->getAbsolutePosition().UpperLeftCorner;
sel->setRelativePosition(SelectedArea - p);
// select
setSelectedElement(sel);
// reset selection mode...
CurrentMode = EGUIEDM_SELECT;
}
break;
case EMIE_MOUSE_MOVED:
// always on top
Parent->bringToFront(this);
// if selecting
if (CurrentMode == EGUIEDM_SELECT || CurrentMode == EGUIEDM_SELECT_NEW_PARENT)
{
core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y);
// highlight the element that the mouse is over
MouseOverElement = getEditableElementFromPoint(Parent, p);
if (MouseOverElement == Parent)
{
MouseOverElement = 0;
}
if (CurrentMode == EGUIEDM_SELECT)
{
MouseOverMode = getModeFromPos(p);
if (MouseOverMode > EGUIEDM_MOVE)
{
MouseOverElement = SelectedElement;
}
}
}
else if (CurrentMode == EGUIEDM_MOVE)
{
// get difference
core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y);
p -= DragStart;
// apply to top corner
p = StartMovePos + p;
if (UseGrid)
{
p.X = (p.X/GridSize.Width)*GridSize.Width;
p.Y = (p.Y/GridSize.Height)*GridSize.Height;
}
SelectedArea += p - SelectedArea.UpperLeftCorner;
}
else if (CurrentMode > EGUIEDM_MOVE)
{
// get difference from start position
core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y);
if (UseGrid)
{
p.X = (p.X/GridSize.Width)*GridSize.Width;
p.Y = (p.Y/GridSize.Height)*GridSize.Height;
}
switch(CurrentMode)
{
case EGUIEDM_RESIZE_T:
SelectedArea.UpperLeftCorner.Y = p.Y;
break;
case EGUIEDM_RESIZE_B:
SelectedArea.LowerRightCorner.Y = p.Y;
break;
case EGUIEDM_RESIZE_L:
SelectedArea.UpperLeftCorner.X = p.X;
break;
case EGUIEDM_RESIZE_R:
SelectedArea.LowerRightCorner.X = p.X;
break;
case EGUIEDM_RESIZE_TL:
SelectedArea.UpperLeftCorner = p;
break;
case EGUIEDM_RESIZE_TR:
SelectedArea.UpperLeftCorner.Y = p.Y;
SelectedArea.LowerRightCorner.X = p.X;
break;
case EGUIEDM_RESIZE_BL:
SelectedArea.UpperLeftCorner.X = p.X;
SelectedArea.LowerRightCorner.Y = p.Y;
break;
case EGUIEDM_RESIZE_BR:
SelectedArea.LowerRightCorner = p;
break;
default:
break;
}
}
break;
default:
break;
}
break;
case EET_GUI_EVENT:
switch(e.GUIEvent.EventType)
{
case EGET_TREEVIEW_NODE_SELECT:
{
IGUITreeViewNode* eventnode = ((IGUITreeView*)e.GUIEvent.Caller)->getLastEventNode();
if(!eventnode->isRoot())
setSelectedElement((IGUIElement*)(eventnode->getData()));
break;
}
// load a gui file
case EGET_FILE_SELECTED:
{
dialog = (IGUIFileOpenDialog*)e.GUIEvent.Caller;
core::stringc guiFilename(core::stringc(dialog->getFileName()).c_str());
clearParentElements();
Environment->loadGUI(guiFilename, Parent);
EditorWindow->updateTree();
break;
}
case EGET_MENU_ITEM_SELECTED:
{
IGUIContextMenu *menu = (IGUIContextMenu*)e.GUIEvent.Caller;
s32 cmdID = menu->getItemCommandId(menu->getSelectedItem()) - MenuCommandStart;
IGUIElement* el;
switch(cmdID)
{
//! file commands
case EGUIEDMC_FILE_NEW:
clearParentElements();
break;
case EGUIEDMC_FILE_LOAD:
Environment->addFileOpenDialog(L"Please select a GUI file to open", false, this);
break;
case EGUIEDMC_FILE_SAVE:
Environment->saveGUI("guiTest.xml");
break;
//! edit menu
case EGUIEDMC_CUT_ELEMENT:
{
CopySelectedElementXML();
// delete element
el = SelectedElement;
setSelectedElement(0);
MouseOverElement = 0;
el->remove();
break;
}
case EGUIEDMC_COPY_ELEMENT:
CopySelectedElementXML();
break;
case EGUIEDMC_PASTE_ELEMENT:
PasteXMLToSelectedElement();
break;
case EGUIEDMC_DELETE_ELEMENT:
el = SelectedElement;
setSelectedElement(0);
MouseOverElement = 0;
el->remove();
break;
case EGUIEDMC_SET_PARENT:
CurrentMode = EGUIEDM_SELECT_NEW_PARENT;
break;
case EGUIEDMC_BRING_TO_FRONT:
if (SelectedElement->getParent())
SelectedElement->getParent()->bringToFront(SelectedElement);
break;
case EGUIEDMC_SAVE_ELEMENT:
//TODO: add 'save' dialog.
Environment->saveGUI("guiTest.xml", SelectedElement ? SelectedElement : Environment->getRootGUIElement() );
break;
//! toggle edit window
case EGUIEDMC_TOGGLE_EDITOR:
break;
case EGUIEDMC_INSERT_XML:
Environment->loadGUI("guiTest.xml", SelectedElement ? SelectedElement : Environment->getRootGUIElement() );
break;
default:
// create element from factory?
if (cmdID >= EGUIEDMC_COUNT)
{
s32 num = cmdID - EGUIEDMC_COUNT; // get index
// loop through all factories
s32 i, c=Environment->getRegisteredGUIElementFactoryCount();
for (i=0; i<c && num > Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount(); ++i)
{
num -= Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount();
}
if (num < Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount() )
{
core::stringc name = Environment->getGUIElementFactory(i)->getCreateableGUIElementTypeName(num);
IGUIElement *parentElement = SelectedElement ? SelectedElement : Environment->getRootGUIElement();
// add it
IGUIElement *newElement = Environment->getGUIElementFactory(i)->addGUIElement(name.c_str(),parentElement);
if (newElement)
{
core::position2di p = DragStart - parentElement->getAbsolutePosition().UpperLeftCorner;
newElement->setRelativePosition(core::rect<s32>(p,p+core::position2di(100,100)));
//Environment->removeFocus(newElement);
}
}
}
break;
}
EditorWindow->updateTree();
}
return true;
default:
break;
}
break;
default:
break;
}
// even if we didn't absorb the event,
// we never pass events back to the GUI we're editing!
return false;
}
//! draws the element and its children
void CGUIEditWorkspace::draw()
{
video::IVideoDriver *driver = Environment->getVideoDriver();
if (DrawGrid)
{
// draw the grid
core::rect<s32> r = getAbsolutePosition();
s32 cy = r.UpperLeftCorner.Y;
while (cy < r.LowerRightCorner.Y)
{
s32 cx = r.UpperLeftCorner.X;
while (cx < r.LowerRightCorner.X)
{
driver->draw2DRectangle(video::SColor(40,0,0,90),core::rect<s32>(cx+1,cy+1,GridSize.Width+cx,GridSize.Height+cy));
cx += GridSize.Width;
}
cy += GridSize.Height;
}
}
if (MouseOverElement &&
MouseOverElement != SelectedElement &&
MouseOverElement != Parent)
{
core::rect<s32> r = MouseOverElement->getAbsolutePosition();
driver->draw2DRectangle(video::SColor(100,0,0,255), r);
}
if (SelectedElement && CurrentMode == EGUIEDM_SELECT)
{
driver->draw2DRectangle(video::SColor(100,0,255,0),SelectedElement->getAbsolutePosition());
}
if (CurrentMode >= EGUIEDM_MOVE)
{
driver->draw2DRectangle(video::SColor(100,255,0,0),SelectedArea);
}
if ( (SelectedElement && CurrentMode >= EGUIEDM_MOVE) ||
(SelectedElement && MouseOverElement == SelectedElement && MouseOverMode >= EGUIEDM_MOVE) )
{
// draw handles for moving
EGUIEDIT_MODE m = CurrentMode;
core::rect<s32> r = SelectedArea;
if (m < EGUIEDM_MOVE)
{
m = MouseOverMode;
r = SelectedElement->getAbsolutePosition();
}
core::position2di d = core::position2di(4,4);
TLRect = core::rect<s32>(r.UpperLeftCorner, r.UpperLeftCorner + d );
TRRect = core::rect<s32>(r.LowerRightCorner.X-4, r.UpperLeftCorner.Y, r.LowerRightCorner.X, r.UpperLeftCorner.Y+4);
TopRect = core::rect<s32>(r.getCenter().X-2, r.UpperLeftCorner.Y,r.getCenter().X+2, r.UpperLeftCorner.Y+4 );
BLRect = core::rect<s32>(r.UpperLeftCorner.X, r.LowerRightCorner.Y-4, r.UpperLeftCorner.X+4, r.LowerRightCorner.Y);
LRect = core::rect<s32>(r.UpperLeftCorner.X,r.getCenter().Y-2, r.UpperLeftCorner.X+4, r.getCenter().Y+2 );
RRect = core::rect<s32>(r.LowerRightCorner.X-4,r.getCenter().Y-2, r.LowerRightCorner.X, r.getCenter().Y+2 );
BRRect = core::rect<s32>(r.LowerRightCorner-d, r.LowerRightCorner);
BRect = core::rect<s32>(r.getCenter().X-2, r.LowerRightCorner.Y-4,r.getCenter().X+2, r.LowerRightCorner.Y );
// top left
if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_RESIZE_L || m == EGUIEDM_RESIZE_TL || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), TLRect);
if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_RESIZE_R || m == EGUIEDM_RESIZE_TR || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), TRRect);
if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), TopRect);
if (m == EGUIEDM_RESIZE_L || m == EGUIEDM_RESIZE_BL || m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), BLRect);
if (m == EGUIEDM_RESIZE_L || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), LRect);
if (m == EGUIEDM_RESIZE_R || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), RRect);
if (m == EGUIEDM_RESIZE_R || m == EGUIEDM_RESIZE_BR || m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), BRRect );
if (m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE )
driver->draw2DRectangle(video::SColor(100,255,255,255), BRect);
}
IGUIElement::draw();
}
void CGUIEditWorkspace::setDrawGrid(bool drawGrid)
{
DrawGrid = drawGrid;
}
void CGUIEditWorkspace::setGridSize(const core::dimension2di& gridSize)
{
GridSize = gridSize;
if (GridSize.Width < 2)
GridSize.Width = 2;
if (GridSize.Height < 2)
GridSize.Height = 2;
}
void CGUIEditWorkspace::setUseGrid(bool useGrid)
{
UseGrid = useGrid;
}
//! Removes a child.
void CGUIEditWorkspace::removeChild(IGUIElement* child)
{
IGUIElement::removeChild(child);
// TODO: Can anyone find out why the workspace removes itself when it has no more children
// and document it here?
if (Children.empty())
remove();
}
void CGUIEditWorkspace::clearParentElements()
{
setSelectedElement(0);
MouseOverElement = 0;
IGUIElement * el = Parent;
grab();
if ( el->isMyChild(Environment->getFocus()) )
Environment->setFocus(0);
while (!el->getChildren().empty())
{
el->removeChild(*(el->getChildren().begin()));
}
el->addChild(this);
drop();
}
void CGUIEditWorkspace::updateAbsolutePosition()
{
core::rect<s32> parentRect(0,0,0,0);
if (Parent)
{
parentRect = Parent->getAbsolutePosition();
RelativeRect.UpperLeftCorner.X = 0;
RelativeRect.UpperLeftCorner.Y = 0;
RelativeRect.LowerRightCorner.X = parentRect.getWidth();
RelativeRect.LowerRightCorner.Y = parentRect.getHeight();
}
IGUIElement::updateAbsolutePosition();
}
void CGUIEditWorkspace::CopySelectedElementXML()
{
core::stringc XMLText;
core::stringw wXMLText;
// create memory write file
io::CMemoryReadWriteFile* memWrite = new io::CMemoryReadWriteFile("#Clipboard#");
// save gui to mem file
io::IXMLWriter* xml = Environment->getFileSystem()->createXMLWriter(memWrite);
Environment->writeGUIElement(xml, SelectedElement);
// copy to clipboard- wide chars not supported yet :(
wXMLText = (wchar_t*)&memWrite->getData()[0];
u32 i = memWrite->getData().size()/sizeof(wchar_t);
if (wXMLText.size() > i)
wXMLText[i] = L'\0';
XMLText = wXMLText.c_str();
memWrite->drop();
xml->drop();
Environment->getOSOperator()->copyToClipboard(XMLText.c_str());
}
void CGUIEditWorkspace::PasteXMLToSelectedElement()
{
// get clipboard data
const char * p = Environment->getOSOperator()->getTextFromClipboard();
irr::core::stringw wXMLText;
core::multibyteToWString(wXMLText, p);
io::CMemoryReadWriteFile* memWrite = new io::CMemoryReadWriteFile("#Clipboard#");
io::IXMLWriter* xmlw = Environment->getFileSystem()->createXMLWriter(memWrite);
xmlw->writeXMLHeader(); // it needs one of those
xmlw->drop();
// write clipboard data
memWrite->write((void*)&wXMLText[0], wXMLText.size() * sizeof(wchar_t));
// rewind file
memWrite->seek(0, false);
// read xml
Environment->loadGUI(memWrite, SelectedElement);
// reset focus
Environment->setFocus(this);
// drop the read file
memWrite->drop();
}
void CGUIEditWorkspace::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)
{
out->addBool("DrawGrid", DrawGrid);
out->addBool("UseGrid", UseGrid);
out->addPosition2d("GridSize", core::position2di(GridSize.Width, GridSize.Height));
out->addInt("MenuCommandStart", MenuCommandStart);
}
void CGUIEditWorkspace::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
setDrawGrid(in->getAttributeAsBool("DrawGrid"));
setUseGrid(in->getAttributeAsBool("UseGrid"));
core::position2di tmpp = in->getAttributeAsPosition2d("GridSize");
core::dimension2di tmpd(tmpp.X, tmpp.Y);
setGridSize(tmpd);
setMenuCommandIDStart(in->getAttributeAsInt("MenuCommandStart"));
}
} // end namespace gui
} // end namespace irr