123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956 |
- // 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
|