PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/CaWE/GuiEditor/ChildFrame.cpp

https://bitbucket.org/cafu/cafu
C++ | 961 lines | 711 code | 206 blank | 44 comment | 85 complexity | ce1161b3abb116642e7f1e91db48e6e8 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0, BSD-3-Clause, LGPL-3.0, LGPL-2.1, AGPL-3.0
  1. /*
  2. Cafu Engine, http://www.cafu.de/
  3. Copyright (c) Carsten Fuchs and other contributors.
  4. This project is licensed under the terms of the MIT license.
  5. */
  6. #include "ChildFrame.hpp"
  7. #include "GuiDocument.hpp"
  8. #include "RenderWindow.hpp"
  9. #include "WindowHierarchy.hpp"
  10. #include "WindowInspector.hpp"
  11. #include "GuiInspector.hpp"
  12. #include "LivePreview.hpp"
  13. #include "Commands/AddComponent.hpp"
  14. #include "Commands/Create.hpp"
  15. #include "Commands/Delete.hpp"
  16. #include "Commands/Select.hpp"
  17. #include "Commands/ChangeWindowHierarchy.hpp"
  18. #include "Commands/Paste.hpp"
  19. #include "../GameConfig.hpp"
  20. #include "../ParentFrame.hpp"
  21. #include "../SetCompVar.hpp"
  22. #include "GuiSys/AllComponents.hpp"
  23. #include "GuiSys/CompBase.hpp"
  24. #include "GuiSys/CompText.hpp"
  25. #include "GuiSys/Window.hpp"
  26. #include "GuiSys/GuiImpl.hpp"
  27. #include "Math3D/Misc.hpp"
  28. #include "wx/wx.h"
  29. #include "wx/artprov.h"
  30. #include "wx/aui/auibar.h"
  31. #include "wx/confbase.h"
  32. #include "wx/settings.h"
  33. #include "wx/file.h"
  34. #include "wx/filename.h"
  35. #include "wx/numdlg.h"
  36. #include <fstream>
  37. namespace
  38. {
  39. // Default perspective set by the first childframe instance and used to restore default settings later.
  40. wxString AUIDefaultPerspective;
  41. bool CompareTypeInfoNames(const cf::TypeSys::TypeInfoT* const& TI1, const cf::TypeSys::TypeInfoT* const& TI2)
  42. {
  43. return wxStricmp(TI1->ClassName, TI2->ClassName) < 0;
  44. }
  45. // This function has been duplicated into other modules, too... can we reconcile them?
  46. wxMenuItem* AppendMI(wxMenu& Menu, int MenuID, const wxString& Label, const wxArtID& ArtID, bool Active=true, const wxString& Help="")
  47. {
  48. wxMenuItem* MI = new wxMenuItem(&Menu, MenuID, Label, Help);
  49. // Under wxMSW (2.9.2), the bitmap must be set before the menu item is added to the menu.
  50. if (ArtID != "")
  51. MI->SetBitmap(wxArtProvider::GetBitmap(ArtID, wxART_MENU));
  52. // Under wxGTK (2.9.2), the menu item must be added to the menu before we can call Enable().
  53. Menu.Append(MI);
  54. MI->Enable(Active);
  55. return MI;
  56. }
  57. }
  58. /*static*/ void GuiEditor::ChildFrameT::BuildComponentsMenu(wxMenu* MenuParent, const cf::TypeSys::TypeInfoT* TypeParent)
  59. {
  60. // For each child of TypeParent (but not TypeParent itself), add an item to MenuParent.
  61. ArrayT<const cf::TypeSys::TypeInfoT*> CompTIs;
  62. for (const cf::TypeSys::TypeInfoT* TI = TypeParent->Child; TI; TI = TI->Sibling)
  63. {
  64. // The topmost root and thus the ComponentBaseT class is never added.
  65. wxASSERT(TI->Base);
  66. // Skip fundamental component types (each window has one instance anyway).
  67. if (cf::GuiSys::IsFundamental(TI)) continue;
  68. // Skip the ComponentSelectionT class, that is specific to this GUI Editor application.
  69. if (TI == &ComponentSelectionT::TypeInfo) continue;
  70. CompTIs.PushBack(TI);
  71. }
  72. CompTIs.QuickSort(CompareTypeInfoNames);
  73. for (unsigned int TINr = 0; TINr < CompTIs.Size(); TINr++)
  74. {
  75. const cf::TypeSys::TypeInfoT* TI = CompTIs[TINr];
  76. wxString Name = TI->ClassName;
  77. if (Name.StartsWith("Component") && Name.EndsWith("T"))
  78. Name = Name.SubString(9, Name.length() - 2);
  79. if (Name.StartsWith("GuiSys::Component") && Name.EndsWith("T"))
  80. Name = Name.SubString(17, Name.length() - 2);
  81. wxASSERT(ID_MENU_CREATE_COMPONENT_FIRST + TI->TypeNr <= ID_MENU_CREATE_COMPONENT_MAX);
  82. if (TI->Child)
  83. {
  84. wxMenu* SubMenu = new wxMenu;
  85. BuildComponentsMenu(SubMenu, TI);
  86. MenuParent->AppendSubMenu(SubMenu, "&" + Name);
  87. }
  88. else
  89. {
  90. MenuParent->Append(ID_MENU_CREATE_COMPONENT_FIRST + TI->TypeNr, "&" + Name, "Add component to the selected window");
  91. }
  92. }
  93. }
  94. BEGIN_EVENT_TABLE(GuiEditor::ChildFrameT, wxMDIChildFrame)
  95. EVT_MENU_RANGE (ID_MENU_FILE_CLOSE, ID_MENU_FILE_SAVEAS, GuiEditor::ChildFrameT::OnMenuFile)
  96. EVT_UPDATE_UI_RANGE(ID_MENU_FILE_CLOSE, ID_MENU_FILE_SAVEAS, GuiEditor::ChildFrameT::OnMenuFileUpdate)
  97. EVT_MENU_RANGE (wxID_UNDO, wxID_REDO, GuiEditor::ChildFrameT::OnMenuUndoRedo)
  98. EVT_UPDATE_UI_RANGE(wxID_UNDO, wxID_REDO, GuiEditor::ChildFrameT::OnUpdateEditUndoRedo)
  99. EVT_UPDATE_UI_RANGE(wxID_CUT, wxID_PASTE, GuiEditor::ChildFrameT::OnMenuEditUpdate)
  100. EVT_UPDATE_UI_RANGE(ID_MENU_EDIT_DELETE, ID_MENU_EDIT_SET_GRID_SIZE, GuiEditor::ChildFrameT::OnMenuEditUpdate)
  101. EVT_MENU (wxID_CUT, GuiEditor::ChildFrameT::OnMenuEditCut)
  102. EVT_MENU (wxID_COPY, GuiEditor::ChildFrameT::OnMenuEditCopy)
  103. EVT_MENU (wxID_PASTE, GuiEditor::ChildFrameT::OnMenuEditPaste)
  104. EVT_MENU (ID_MENU_EDIT_DELETE, GuiEditor::ChildFrameT::OnMenuEditDelete)
  105. EVT_MENU_RANGE (ID_MENU_EDIT_SNAP_TO_GRID, ID_MENU_EDIT_SET_GRID_SIZE, GuiEditor::ChildFrameT::OnMenuEditGrid)
  106. EVT_MENU_RANGE (ID_MENU_CREATE_WINDOW, ID_MENU_CREATE_COMPONENT_MAX, GuiEditor::ChildFrameT::OnMenuCreate)
  107. EVT_MENU_RANGE (ID_MENU_VIEW_WINDOW_HIERARCHY, ID_MENU_VIEW_SAVE_USER_LAYOUT, GuiEditor::ChildFrameT::OnMenuView)
  108. EVT_UPDATE_UI_RANGE(ID_MENU_VIEW_WINDOW_HIERARCHY, ID_MENU_VIEW_GUIINSPECTOR, GuiEditor::ChildFrameT::OnMenuViewUpdate)
  109. EVT_CLOSE ( GuiEditor::ChildFrameT::OnClose)
  110. EVT_TOOL_RANGE (ID_TOOLBAR_DOC_PREVIEW, ID_TOOLBAR_ZOOM_100, GuiEditor::ChildFrameT::OnToolbar)
  111. END_EVENT_TABLE()
  112. GuiEditor::ChildFrameT::ChildFrameT(ParentFrameT* Parent, const wxString& FileName, GuiDocumentT* GuiDocument)
  113. : wxMDIChildFrame(Parent, wxID_ANY, FileName, wxDefaultPosition, wxSize(800, 600), wxDEFAULT_FRAME_STYLE | wxMAXIMIZE),
  114. m_GuiDocument(GuiDocument), // Must use a fixed size in place of wxDefaultSize, see <http://trac.wxwidgets.org/ticket/12490> for details.
  115. m_FileName(FileName),
  116. m_GameConfig(GuiDocument->GetGameConfig()),
  117. m_LastSavedAtCommandNr(0),
  118. m_SnapToGrid(true),
  119. m_GridSpacing(5),
  120. m_ToolManager(GuiDocument, this),
  121. m_Parent(Parent),
  122. m_RenderWindow(NULL),
  123. m_WindowHierarchy(NULL),
  124. m_WindowInspector(NULL),
  125. m_FileMenu(NULL),
  126. m_EditMenu(NULL),
  127. m_CreateMenu(NULL),
  128. m_ViewMenu(NULL)
  129. {
  130. // Register us with the parents list of children.
  131. m_Parent->m_GuiChildFrames.PushBack(this);
  132. // Set up menu.
  133. wxMenuBar *item0 = new wxMenuBar;
  134. m_FileMenu=new wxMenu;
  135. wxMenu* NewMenu = new wxMenu;
  136. NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_MAP, wxT("New &Map\tCtrl+N"), wxT(""));
  137. NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_MODEL, wxT("New M&odel\tCtrl+Shift+N"), wxT(""));
  138. NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_GUI, wxT("New &GUI\tCtrl+Alt+N"), wxT(""));
  139. NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_FONT, wxT("New &Font"), wxT(""));
  140. m_FileMenu->AppendSubMenu(NewMenu, wxT("&New"));
  141. m_FileMenu->Append(ParentFrameT::ID_MENU_FILE_OPEN, wxT("&Open...\tCtrl+O"), wxT("") );
  142. m_FileMenu->Append(ID_MENU_FILE_CLOSE, wxT("&Close\tCtrl+F4"), wxT("") );
  143. m_FileMenu->Append(ID_MENU_FILE_SAVE, wxT("&Save\tCtrl+S"), wxT("") );
  144. m_FileMenu->Append(ID_MENU_FILE_SAVEAS, wxT("Save &As..."), wxT("") );
  145. m_FileMenu->AppendSeparator();
  146. m_FileMenu->Append(ParentFrameT::ID_MENU_FILE_CONFIGURE, wxT("Conf&igure CaWE..."), wxT("") );
  147. m_FileMenu->Append(ParentFrameT::ID_MENU_FILE_EXIT, wxT("E&xit"), wxT("") );
  148. m_Parent->m_FileHistory.UseMenu(m_FileMenu);
  149. m_Parent->m_FileHistory.AddFilesToMenu(m_FileMenu);
  150. item0->Append( m_FileMenu, wxT("&File") );
  151. m_EditMenu=new wxMenu;
  152. m_EditMenu->Append(wxID_UNDO, "&Undo\tCtrl+Z", "");
  153. m_EditMenu->Append(wxID_REDO, "&Redo\tCtrl+Y", "");
  154. m_EditMenu->AppendSeparator();
  155. m_EditMenu->Append(wxID_CUT, "Cu&t\tCtrl+X", "");
  156. m_EditMenu->Append(wxID_COPY, "&Copy\tCtrl+C", "");
  157. m_EditMenu->Append(wxID_PASTE, "&Paste\tCtrl+V", "");
  158. m_EditMenu->Append(ID_MENU_EDIT_DELETE, "&Delete\tShift+Del", "");
  159. m_EditMenu->AppendSeparator();
  160. m_EditMenu->Append(ID_MENU_EDIT_SNAP_TO_GRID, wxString::Format("Snap to grid (%lu)\tCtrl+G", m_GridSpacing), "", wxITEM_CHECK);
  161. m_EditMenu->Append(ID_MENU_EDIT_SET_GRID_SIZE, "Set grid size\tCtrl+H", "");
  162. item0->Append(m_EditMenu, "&Edit");
  163. m_CreateMenu = new wxMenu;
  164. AppendMI(*m_CreateMenu, ID_MENU_CREATE_WINDOW, "Window", "window-new", true, "Create new window");
  165. m_CreateMenu->AppendSeparator();
  166. const ArrayT<const cf::TypeSys::TypeInfoT*>& CompRoots = cf::GuiSys::GetComponentTIM().GetTypeInfoRoots();
  167. for (unsigned long RootNr = 0; RootNr < CompRoots.Size(); RootNr++)
  168. {
  169. BuildComponentsMenu(m_CreateMenu, CompRoots[RootNr]);
  170. if (RootNr + 1 < CompRoots.Size())
  171. m_CreateMenu->AppendSeparator();
  172. }
  173. item0->Append(m_CreateMenu, "&Create");
  174. m_ViewMenu=new wxMenu;
  175. m_ViewMenu->Append(ID_MENU_VIEW_WINDOW_HIERARCHY, "Window Hierarchy", "Show/Hide the Window Hierarchy", wxITEM_CHECK);
  176. m_ViewMenu->Append(ID_MENU_VIEW_WINDOWINSPECTOR, "Window Inspector", "Show/Hide the Window Inspector", wxITEM_CHECK);
  177. m_ViewMenu->Append(ID_MENU_VIEW_GUIINSPECTOR, "GUI Inspector", "Show/Hide the GUI Inspector", wxITEM_CHECK);
  178. m_ViewMenu->AppendSeparator();
  179. m_ViewMenu->Append(ID_MENU_VIEW_RESTORE_DEFAULT_LAYOUT, "Restore default layout", "Restores the GUI editor default layout");
  180. m_ViewMenu->Append(ID_MENU_VIEW_RESTORE_USER_LAYOUT, "Restore user layout", "Restores the GUI editor user defined layout");
  181. m_ViewMenu->Append(ID_MENU_VIEW_SAVE_USER_LAYOUT, "Save user layout", "Saves the current GUI editor layout as user defined layout");
  182. item0->Append(m_ViewMenu, "&View");
  183. wxMenu* HelpMenu = new wxMenu;
  184. HelpMenu->Append(ParentFrameT::ID_MENU_HELP_CONTENTS, wxT("&CaWE Help\tF1"), wxT("") );
  185. HelpMenu->AppendSeparator();
  186. HelpMenu->Append(ParentFrameT::ID_MENU_HELP_CAFU_WEBSITE, wxT("Cafu &Website"), wxT("") );
  187. HelpMenu->Append(ParentFrameT::ID_MENU_HELP_CAFU_FORUM, wxT("Cafu &Forum"), wxT("") );
  188. HelpMenu->AppendSeparator();
  189. HelpMenu->Append(ParentFrameT::ID_MENU_HELP_ABOUT, wxT("&About..."), wxT("") );
  190. item0->Append(HelpMenu, wxT("&Help") );
  191. SetMenuBar(item0);
  192. // Setup wxAUI.
  193. m_AUIManager.SetManagedWindow(this);
  194. // Create GUI views.
  195. m_RenderWindow =new RenderWindowT (this);
  196. m_WindowHierarchy=new WindowHierarchyT(this, wxSize(230, 500));
  197. m_WindowInspector=new WindowInspectorT(this, wxSize(230, 500));
  198. m_GuiInspector =new GuiInspectorT (this, wxSize(230, 150));
  199. m_AUIManager.AddPane(m_RenderWindow, wxAuiPaneInfo().
  200. Name("RenderWindow").Caption("Render Window").
  201. CenterPane());
  202. m_AUIManager.AddPane(m_WindowHierarchy, wxAuiPaneInfo().
  203. Name("WindowHierarchy").Caption("Window Hierarchy").
  204. Left().Position(0));
  205. m_AUIManager.AddPane(m_WindowInspector, wxAuiPaneInfo().
  206. Name("WindowInspector").Caption("Window Inspector").
  207. Right().Position(0));
  208. m_AUIManager.AddPane(m_GuiInspector, wxAuiPaneInfo().
  209. Name("GuiInspector").Caption("GUI Inspector").
  210. Left().Position(1));
  211. // Create AUI toolbars.
  212. wxAuiToolBar* ToolbarDocument=new wxAuiToolBar(this, wxID_ANY);
  213. ToolbarDocument->AddTool(ParentFrameT::ID_MENU_FILE_NEW_GUI, "New", wxArtProvider::GetBitmap(wxART_NEW, wxART_TOOLBAR), "Create a new file");
  214. ToolbarDocument->AddTool(ParentFrameT::ID_MENU_FILE_OPEN, "Open", wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR), "Open an existing file");
  215. ToolbarDocument->AddTool(ID_MENU_FILE_SAVE, "Save", wxArtProvider::GetBitmap(wxART_FILE_SAVE, wxART_TOOLBAR), "Save the file");
  216. ToolbarDocument->AddTool(ID_MENU_FILE_SAVEAS, "Save as", wxArtProvider::GetBitmap(wxART_FILE_SAVE_AS, wxART_TOOLBAR), "Save the file under a different name");
  217. ToolbarDocument->AddSeparator();
  218. ToolbarDocument->AddTool(wxID_UNDO, "Undo", wxArtProvider::GetBitmap(wxART_UNDO, wxART_TOOLBAR), "Undo the last action");
  219. ToolbarDocument->AddTool(wxID_REDO, "Redo", wxArtProvider::GetBitmap(wxART_REDO, wxART_TOOLBAR), "Redo the previously undone action");
  220. ToolbarDocument->AddSeparator();
  221. ToolbarDocument->AddTool(wxID_CUT, "Cut", wxArtProvider::GetBitmap(wxART_CUT, wxART_TOOLBAR), "Cut");
  222. ToolbarDocument->AddTool(wxID_COPY, "Copy", wxArtProvider::GetBitmap(wxART_COPY, wxART_TOOLBAR), "Copy");
  223. ToolbarDocument->AddTool(wxID_PASTE, "Paste", wxArtProvider::GetBitmap(wxART_PASTE, wxART_TOOLBAR), "Paste");
  224. ToolbarDocument->AddTool(ID_MENU_EDIT_DELETE, "Delete", wxArtProvider::GetBitmap(wxART_DELETE, wxART_TOOLBAR), "Delete");
  225. ToolbarDocument->Realize();
  226. m_ToolbarTools=new wxAuiToolBar(this, wxID_ANY);
  227. m_ToolbarTools->AddTool(ID_TOOLBAR_TOOL_SELECTION, "Selection tool", wxArtProvider::GetBitmap("cursor_mouse", wxART_TOOLBAR, wxSize(16, 16) /*The only one that we have at this time; don't scale it.*/), "Selection tool", wxITEM_CHECK);
  228. m_ToolbarTools->ToggleTool(ID_TOOLBAR_TOOL_SELECTION, true); // Selection tool is active by default.
  229. m_ToolbarTools->AddTool(ID_TOOLBAR_TOOL_NEW_WINDOW, "Window Creation tool", wxArtProvider::GetBitmap("window-new", wxART_TOOLBAR), "Window creation tool (in this version, use the Create menu, or the context menu in the Window Hierarchy or main view in order to create new windows)", wxITEM_CHECK);
  230. m_ToolbarTools->EnableTool(ID_TOOLBAR_TOOL_NEW_WINDOW, false);
  231. m_ToolbarTools->Realize();
  232. wxAuiToolBar* ToolbarWindow=new wxAuiToolBar(this, wxID_ANY);
  233. ToolbarWindow->AddTool(ID_TOOLBAR_WINDOW_MOVE_UP, "Move up", wxArtProvider::GetBitmap("list-selection-up", wxART_TOOLBAR), "Move window up in the parent's list of children");
  234. ToolbarWindow->AddTool(ID_TOOLBAR_WINDOW_MOVE_DOWN, "Move down", wxArtProvider::GetBitmap("list-selection-down", wxART_TOOLBAR), "Move window down in the parent's list of children");
  235. ToolbarWindow->AddTool(ID_TOOLBAR_WINDOW_ROTATE_CCW, "Rotate anticlockwise", wxArtProvider::GetBitmap("transform-rotate-left", wxART_TOOLBAR), "Rotate anticlockwise");
  236. ToolbarWindow->AddTool(ID_TOOLBAR_WINDOW_ROTATE_CW, "Rotate clockwise", wxArtProvider::GetBitmap("transform-rotate-right", wxART_TOOLBAR), "Rotate clockwise");
  237. ToolbarWindow->Realize();
  238. wxAuiToolBar* ToolbarText=new wxAuiToolBar(this, wxID_ANY);
  239. ToolbarText->AddTool(ID_TOOLBAR_TEXT_ALIGN_LEFT, "Align left", wxArtProvider::GetBitmap("format-justify-left", wxART_TOOLBAR), "Left align text");
  240. ToolbarText->AddTool(ID_TOOLBAR_TEXT_ALIGN_CENTER, "Align center", wxArtProvider::GetBitmap("format-justify-center", wxART_TOOLBAR), "Center text");
  241. ToolbarText->AddTool(ID_TOOLBAR_TEXT_ALIGN_RIGHT, "Align right", wxArtProvider::GetBitmap("format-justify-right", wxART_TOOLBAR), "Right align text");
  242. ToolbarText->Realize();
  243. wxAuiToolBar* ToolbarZoom=new wxAuiToolBar(this, wxID_ANY);
  244. ToolbarZoom->AddTool(ID_TOOLBAR_ZOOM_IN, "Zoom in", wxArtProvider::GetBitmap("zoom-in", wxART_TOOLBAR), "Zoom in");
  245. ToolbarZoom->AddTool(ID_TOOLBAR_ZOOM_OUT, "Zoom out", wxArtProvider::GetBitmap("zoom-out", wxART_TOOLBAR), "Zoom out");
  246. ToolbarZoom->AddTool(ID_TOOLBAR_ZOOM_FIT, "Best fit", wxArtProvider::GetBitmap("zoom-fit-best", wxART_TOOLBAR), "Best fit");
  247. ToolbarZoom->AddTool(ID_TOOLBAR_ZOOM_100, "Set zoom 100%", wxArtProvider::GetBitmap("zoom-original", wxART_TOOLBAR), "Set zoom to 100%");
  248. ToolbarZoom->AddSeparator();
  249. ToolbarZoom->AddTool(ID_TOOLBAR_DOC_PREVIEW, "Live preview", wxArtProvider::GetBitmap("x-office-presentation", wxART_TOOLBAR), "Live preview");
  250. ToolbarZoom->Realize();
  251. m_AUIManager.AddPane(ToolbarDocument, wxAuiPaneInfo().Name("ToolbarDocument").
  252. Caption("Toolbar Document").ToolbarPane().Top().Row(0).Position(0).
  253. LeftDockable(false).RightDockable(false));
  254. m_AUIManager.AddPane(m_ToolbarTools, wxAuiPaneInfo().Name("ToolbarTools").
  255. Caption("Toolbar Tools").ToolbarPane().Top().Row(0).Position(1).
  256. LeftDockable(false).RightDockable(false));
  257. m_AUIManager.AddPane(ToolbarWindow, wxAuiPaneInfo().Name("ToolbarWindow").
  258. Caption("Toolbar Window").ToolbarPane().Top().Row(0).Position(2).
  259. LeftDockable(false).RightDockable(false));
  260. m_AUIManager.AddPane(ToolbarText, wxAuiPaneInfo().Name("ToolbarText").
  261. Caption("Toolbar Text").ToolbarPane().Top().Row(0).Position(3).
  262. LeftDockable(false).RightDockable(false));
  263. m_AUIManager.AddPane(ToolbarZoom, wxAuiPaneInfo().Name("ToolbarZoom").
  264. Caption("Toolbar Zoom").ToolbarPane().Top().Row(0).Position(4).
  265. LeftDockable(false).RightDockable(false));
  266. // Set default perspective if not yet set.
  267. if (AUIDefaultPerspective.IsEmpty()) AUIDefaultPerspective=m_AUIManager.SavePerspective();
  268. // Load user perspective (calls m_AUIManager.Update() automatically).
  269. m_AUIManager.LoadPerspective(wxConfigBase::Get()->Read("GuiEditorUserLayout", m_AUIManager.SavePerspective()));
  270. // Register observers.
  271. m_GuiDocument->RegisterObserver(m_RenderWindow);
  272. m_GuiDocument->RegisterObserver(m_WindowHierarchy);
  273. m_GuiDocument->RegisterObserver(m_WindowInspector);
  274. m_GuiDocument->RegisterObserver(m_GuiInspector);
  275. if (!IsMaximized()) Maximize(true); // Also have wxMAXIMIZE set as frame style.
  276. Show(true);
  277. // Initial update of the gui documents observers.
  278. m_RenderWindow->Refresh(false);
  279. m_WindowHierarchy->RefreshTree();
  280. m_WindowInspector->RefreshPropGrid();
  281. m_GuiInspector->RefreshPropGrid();
  282. }
  283. GuiEditor::ChildFrameT::~ChildFrameT()
  284. {
  285. m_Parent->m_FileHistory.RemoveMenu(m_FileMenu);
  286. // Unregister us from the parents list of children.
  287. const int Index=m_Parent->m_GuiChildFrames.Find(this);
  288. m_Parent->m_GuiChildFrames.RemoveAt(Index);
  289. m_AUIManager.UnInit();
  290. delete m_GuiDocument;
  291. }
  292. float GuiEditor::ChildFrameT::SnapToGrid(float Value) const
  293. {
  294. if (!m_SnapToGrid) return cf::math::round(Value);
  295. return cf::math::round(Value/m_GridSpacing)*m_GridSpacing;
  296. }
  297. Vector2fT GuiEditor::ChildFrameT::SnapToGrid(const Vector2fT& Position) const
  298. {
  299. const float GridSpacing=m_SnapToGrid ? m_GridSpacing : 1.0f;
  300. Vector2fT NewPosition;
  301. NewPosition.x=cf::math::round(Position.x/GridSpacing)*GridSpacing;
  302. NewPosition.y=cf::math::round(Position.y/GridSpacing)*GridSpacing;
  303. return NewPosition;
  304. }
  305. bool GuiEditor::ChildFrameT::SubmitCommand(CommandT* Command)
  306. {
  307. if (m_History.SubmitCommand(Command))
  308. {
  309. if (Command->SuggestsSave()) SetTitle(m_FileName+"*");
  310. return true;
  311. }
  312. return false;
  313. }
  314. bool GuiEditor::ChildFrameT::Save(bool AskForFileName)
  315. {
  316. wxString FileName=m_FileName;
  317. if (AskForFileName || FileName=="" || FileName=="New GUI" || !FileName.EndsWith("_init.cgui") ||
  318. !wxFileExists(FileName) || !wxFile::Access(FileName, wxFile::write))
  319. {
  320. static wxString LastUsedDir=m_GameConfig->ModDir+"/GUIs";
  321. const wxFileName FN(m_FileName);
  322. wxFileDialog SaveFileDialog(NULL, // parent
  323. "Save Cafu GUI File", // message
  324. (FN.IsOk() && wxDirExists(FN.GetPath())) ? FN.GetPath() : LastUsedDir, // default dir
  325. (FN.IsOk() && FN.GetExt() == "cgui") ? FN.GetFullName() : "", // default file
  326. "Cafu GUI Files (*.cgui)|*.cgui" // wildcard
  327. "|All Files (*.*)|*.*",
  328. wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
  329. if (SaveFileDialog.ShowModal()!=wxID_OK) return false;
  330. LastUsedDir=SaveFileDialog.GetDirectory();
  331. FileName=SaveFileDialog.GetPath(); // directory + filename
  332. }
  333. if (!FileName.EndsWith("_init.cgui"))
  334. {
  335. // Remove extension from filename.
  336. wxFileName Tmp=wxFileName(FileName);
  337. Tmp.ClearExt();
  338. FileName=Tmp.GetFullPath();
  339. FileName=FileName+"_init.cgui";
  340. }
  341. // Backup the previous file before overwriting it.
  342. if (wxFileExists(FileName) && !wxCopyFile(FileName, FileName+"_bak"))
  343. {
  344. wxMessageBox(wxString("I was not able to backup file '")+FileName+"' to '"+FileName+"_bak"+"'.\n"
  345. "Please make sure that there is enough disk space left and that the path still exists,\n"
  346. "or use 'File -> Save As...' to save the current GUI elsewhere.", "File not saved!", wxOK | wxICON_ERROR);
  347. return false;
  348. }
  349. std::ofstream InitFile(FileName.fn_str());
  350. if (!InitFile.is_open())
  351. {
  352. wxMessageBox(wxString("CaWE was unable to open the file \"")+FileName+"\" for writing. Please verify that the file is writable and that the path exists.");
  353. return false;
  354. }
  355. // This sets the cursor to the busy cursor in its ctor, and back to the default cursor in the dtor.
  356. wxBusyCursor BusyCursor;
  357. if (!m_GuiDocument->SaveInit_cgui(InitFile)) return false;
  358. // Create _main.cgui file if not existent.
  359. wxString GuiMainScript;
  360. wxASSERT(FileName.EndsWith("_init.cgui"));
  361. FileName.EndsWith("_init.cgui", &GuiMainScript);
  362. GuiMainScript+="_main.cgui";
  363. if (!wxFileExists(GuiMainScript))
  364. {
  365. std::ofstream MainFile(GuiMainScript.fn_str());
  366. wxFileName RelFileName=FileName;
  367. RelFileName.MakeRelativeTo("."); // Make it relative to the current working directory.
  368. if (MainFile.is_open())
  369. {
  370. MainFile << "local gui = ...\n";
  371. MainFile << "\n";
  372. MainFile << "assert(loadfile(\"" << RelFileName.GetFullPath(wxPATH_UNIX) << "\"))(gui)\n";
  373. }
  374. else wxMessageBox("Unable to create template file\n"+GuiMainScript);
  375. }
  376. // Mark the document as "not modified" only if the save was successful.
  377. m_LastSavedAtCommandNr=m_History.GetLastSaveSuggestedCommandID();
  378. m_FileName=FileName;
  379. SetTitle(m_FileName);
  380. m_Parent->m_FileHistory.AddFileToHistory(m_FileName);
  381. return true;
  382. }
  383. void GuiEditor::ChildFrameT::OnMenuFile(wxCommandEvent& CE)
  384. {
  385. // The events for menu entries that are duplicated from the parents file menu are forwarded to the parent.
  386. // All other events are child frame specific, and handled here.
  387. switch (CE.GetId())
  388. {
  389. case ID_MENU_FILE_CLOSE:
  390. {
  391. // Close() generates a EVT_CLOSE event which is handled by our OnClose() handler.
  392. // See wx Window Deletion Overview for more details.
  393. Close();
  394. break;
  395. }
  396. case ID_MENU_FILE_SAVE:
  397. {
  398. Save();
  399. break;
  400. }
  401. case ID_MENU_FILE_SAVEAS:
  402. {
  403. Save(true);
  404. break;
  405. }
  406. }
  407. }
  408. void GuiEditor::ChildFrameT::OnMenuFileUpdate(wxUpdateUIEvent& UE)
  409. {
  410. switch (UE.GetId())
  411. {
  412. case ID_MENU_FILE_SAVE:
  413. UE.Enable(m_History.GetLastSaveSuggestedCommandID()!=m_LastSavedAtCommandNr);
  414. break;
  415. }
  416. }
  417. void GuiEditor::ChildFrameT::OnMenuUndoRedo(wxCommandEvent& CE)
  418. {
  419. // Step forward or backward in the command history.
  420. if (CE.GetId()==wxID_UNDO) m_History.Undo();
  421. else m_History.Redo();
  422. SetTitle(m_FileName + (m_History.GetLastSaveSuggestedCommandID()==m_LastSavedAtCommandNr ? "" : "*"));
  423. }
  424. void GuiEditor::ChildFrameT::OnUpdateEditUndoRedo(wxUpdateUIEvent& UE)
  425. {
  426. const CommandT* Cmd =(UE.GetId()==wxID_UNDO) ? m_History.GetUndoCommand() : m_History.GetRedoCommand();
  427. wxString Action=(UE.GetId()==wxID_UNDO) ? "Undo" : "Redo";
  428. wxString Hotkey=(UE.GetId()==wxID_UNDO) ? "Ctrl+Z" : "Ctrl+Y";
  429. if (Cmd)
  430. {
  431. UE.SetText(Action+" "+Cmd->GetName()+"\t"+Hotkey);
  432. UE.Enable(true);
  433. }
  434. else
  435. {
  436. UE.SetText(wxString("Cannot ")+Action+"\t"+Hotkey);
  437. UE.Enable(false);
  438. }
  439. }
  440. void GuiEditor::ChildFrameT::OnMenuEditCut(wxCommandEvent& CE)
  441. {
  442. OnMenuEditCopy(CE);
  443. OnMenuEditDelete(CE);
  444. }
  445. void GuiEditor::ChildFrameT::OnMenuEditCopy(wxCommandEvent& CE)
  446. {
  447. m_Parent->m_GuiClipboard.Clear();
  448. const ArrayT< IntrusivePtrT<cf::GuiSys::WindowT> >& Selection=m_GuiDocument->GetSelection();
  449. for (unsigned long SelNr=0; SelNr<Selection.Size(); SelNr++)
  450. m_Parent->m_GuiClipboard.PushBack(new cf::GuiSys::WindowT(*Selection[SelNr], true));
  451. }
  452. void GuiEditor::ChildFrameT::OnMenuEditPaste(wxCommandEvent& CE)
  453. {
  454. SubmitCommand(new CommandPasteT(m_GuiDocument, m_Parent->m_GuiClipboard,
  455. m_GuiDocument->GetSelection().Size()==1 ? m_GuiDocument->GetSelection()[0] : m_GuiDocument->GetRootWindow()));
  456. }
  457. void GuiEditor::ChildFrameT::OnMenuEditDelete(wxCommandEvent& CE)
  458. {
  459. if (m_GuiDocument->GetSelection().Size()>0)
  460. SubmitCommand(new CommandDeleteT(m_GuiDocument, m_GuiDocument->GetSelection()));
  461. }
  462. void GuiEditor::ChildFrameT::OnMenuEditGrid(wxCommandEvent& CE)
  463. {
  464. switch (CE.GetId())
  465. {
  466. case ID_MENU_EDIT_SNAP_TO_GRID:
  467. m_SnapToGrid=!m_SnapToGrid;
  468. break;
  469. case ID_MENU_EDIT_SET_GRID_SIZE:
  470. long NewGridSpacing=wxGetNumberFromUser("Enter a grid spacing between 1 and 100.", "", "Enter new grid spacing", m_GridSpacing, 1, 100);
  471. if (NewGridSpacing!=-1) m_GridSpacing=NewGridSpacing;
  472. break;
  473. }
  474. }
  475. void GuiEditor::ChildFrameT::OnMenuEditUpdate(wxUpdateUIEvent& UE)
  476. {
  477. switch (UE.GetId())
  478. {
  479. case wxID_CUT:
  480. case wxID_COPY:
  481. case ID_MENU_EDIT_DELETE:
  482. UE.Enable(m_GuiDocument->GetSelection().Size()>0);
  483. break;
  484. case wxID_PASTE:
  485. UE.Enable(m_Parent->m_GuiClipboard.Size()>0);
  486. break;
  487. case ID_MENU_EDIT_SNAP_TO_GRID:
  488. UE.Check(m_SnapToGrid);
  489. UE.SetText(wxString::Format("Snap to grid (%lu)\tCtrl+G", m_GridSpacing));
  490. break;
  491. }
  492. }
  493. void GuiEditor::ChildFrameT::OnMenuCreate(wxCommandEvent& CE)
  494. {
  495. if (CE.GetId() == ID_MENU_CREATE_WINDOW)
  496. {
  497. IntrusivePtrT<cf::GuiSys::WindowT> Parent = m_GuiDocument->GetSelection().Size() > 0 ? m_GuiDocument->GetSelection()[0] : m_GuiDocument->GetRootWindow();
  498. SubmitCommand(new CommandCreateT(m_GuiDocument, Parent));
  499. return;
  500. }
  501. const unsigned long Nr = CE.GetId() - ID_MENU_CREATE_COMPONENT_FIRST;
  502. const cf::TypeSys::TypeInfoT* TI = cf::GuiSys::GetComponentTIM().FindTypeInfoByNr(Nr);
  503. if (!TI)
  504. {
  505. wxMessageBox("Could not find a TypeInfo for this type number.", "Add component");
  506. return;
  507. }
  508. if (m_GuiDocument->GetSelection().Size() != 1)
  509. {
  510. wxMessageBox("Please select exactly one window to add the component to.", "Add component");
  511. return;
  512. }
  513. IntrusivePtrT<cf::GuiSys::ComponentBaseT> Comp = static_cast<cf::GuiSys::ComponentBaseT*>(
  514. TI->CreateInstance(
  515. cf::TypeSys::CreateParamsT()));
  516. if (Comp.IsNull())
  517. {
  518. wxMessageBox("Could not instantiate the component.", "Add component");
  519. return;
  520. }
  521. SubmitCommand(new CommandAddComponentT(m_GuiDocument, m_GuiDocument->GetSelection()[0], Comp));
  522. }
  523. void GuiEditor::ChildFrameT::OnMenuView(wxCommandEvent& CE)
  524. {
  525. switch (CE.GetId())
  526. {
  527. case ID_MENU_VIEW_WINDOW_HIERARCHY:
  528. m_AUIManager.GetPane(m_WindowHierarchy).Show(m_ViewMenu->IsChecked(ID_MENU_VIEW_WINDOW_HIERARCHY));
  529. m_AUIManager.Update();
  530. break;
  531. case ID_MENU_VIEW_WINDOWINSPECTOR:
  532. m_AUIManager.GetPane(m_WindowInspector).Show(m_ViewMenu->IsChecked(ID_MENU_VIEW_WINDOWINSPECTOR));
  533. m_AUIManager.Update();
  534. break;
  535. case ID_MENU_VIEW_GUIINSPECTOR:
  536. m_AUIManager.GetPane(m_GuiInspector).Show(m_ViewMenu->IsChecked(ID_MENU_VIEW_GUIINSPECTOR));
  537. m_AUIManager.Update();
  538. break;
  539. case ID_MENU_VIEW_RESTORE_DEFAULT_LAYOUT:
  540. m_AUIManager.LoadPerspective(AUIDefaultPerspective);
  541. break;
  542. case ID_MENU_VIEW_RESTORE_USER_LAYOUT:
  543. m_AUIManager.LoadPerspective(wxConfigBase::Get()->Read("GuiEditorUserLayout", m_AUIManager.SavePerspective()));
  544. break;
  545. case ID_MENU_VIEW_SAVE_USER_LAYOUT:
  546. wxConfigBase::Get()->Write("GuiEditorUserLayout", m_AUIManager.SavePerspective());
  547. break;
  548. default:
  549. break;
  550. }
  551. }
  552. void GuiEditor::ChildFrameT::OnMenuViewUpdate(wxUpdateUIEvent& UE)
  553. {
  554. switch (UE.GetId())
  555. {
  556. case ID_MENU_VIEW_WINDOW_HIERARCHY:
  557. m_ViewMenu->Check(ID_MENU_VIEW_WINDOW_HIERARCHY, m_AUIManager.GetPane(m_WindowHierarchy).IsShown());
  558. break;
  559. case ID_MENU_VIEW_WINDOWINSPECTOR:
  560. m_ViewMenu->Check(ID_MENU_VIEW_WINDOWINSPECTOR, m_AUIManager.GetPane(m_WindowInspector).IsShown());
  561. break;
  562. case ID_MENU_VIEW_GUIINSPECTOR:
  563. m_ViewMenu->Check(ID_MENU_VIEW_GUIINSPECTOR, m_AUIManager.GetPane(m_GuiInspector).IsShown());
  564. break;
  565. default:
  566. break;
  567. }
  568. }
  569. void GuiEditor::ChildFrameT::OnClose(wxCloseEvent& CE)
  570. {
  571. if (!CE.CanVeto())
  572. {
  573. Destroy();
  574. return;
  575. }
  576. if (m_LastSavedAtCommandNr==m_History.GetLastSaveSuggestedCommandID())
  577. {
  578. // Our document has not been modified since the last save - close this window.
  579. Destroy();
  580. return;
  581. }
  582. // This "Save Confirmation Alert" essentially follows the GNOME Human Interface Guidelines,
  583. // see http://developer.gnome.org/hig-book/ for details.
  584. wxMessageDialog Msg(NULL, "Save changes to GUI \"" + m_FileName + "\" before closing?", "CaWE GUI Editor", wxYES_NO | wxCANCEL);
  585. Msg.SetExtendedMessage("If you close without saving, your changes will be discarded.");
  586. Msg.SetYesNoLabels("Save", "Close without Saving");
  587. switch (Msg.ShowModal())
  588. {
  589. case wxID_YES:
  590. if (!Save())
  591. {
  592. // The document could not be saved - keep the window open.
  593. CE.Veto();
  594. return;
  595. }
  596. // The GUI was successfully saved - close the window.
  597. Destroy();
  598. return;
  599. case wxID_NO:
  600. Destroy();
  601. return;
  602. default: // wxID_CANCEL
  603. CE.Veto();
  604. return;
  605. }
  606. }
  607. void GuiEditor::ChildFrameT::OnToolbar(wxCommandEvent& CE)
  608. {
  609. switch (CE.GetId())
  610. {
  611. case ID_TOOLBAR_DOC_PREVIEW:
  612. {
  613. // Activating the live preview requires saving the document first, as this avoids
  614. // a lot of subtle problems with alternatively merging the main script and our "in memory" script.
  615. // For example, we make sure that we experience the exact same errors here than the engine would,
  616. // and we also get proper line numbers in Lua error messages!
  617. if (!Save()) break;
  618. wxString MainScriptFileName;
  619. m_FileName.EndsWith("_init.cgui", &MainScriptFileName);
  620. MainScriptFileName+="_main.cgui";
  621. try
  622. {
  623. cf::UniScriptStateT* ScriptState = new cf::UniScriptStateT();
  624. cf::GuiSys::GuiImplT::InitScriptState(*ScriptState);
  625. IntrusivePtrT<cf::GuiSys::GuiImplT> Gui = new cf::GuiSys::GuiImplT(*ScriptState, m_GameConfig->GetGuiResources());
  626. Gui->LoadScript(std::string(MainScriptFileName));
  627. // Make sure that the Gui is active for the live preview, so that clock tick events are properly propagated to all windows.
  628. Gui->Activate();
  629. LivePreviewT* Preview = new LivePreviewT(this, ScriptState, Gui, MainScriptFileName);
  630. Preview->Show();
  631. }
  632. catch (const cf::GuiSys::GuiImplT::InitErrorT& IE)
  633. {
  634. wxMessageBox(
  635. "There was a problem initializing the live preview.\n\n"
  636. "Loading script " + MainScriptFileName + " finished with an error:\n" + IE.what(),
  637. "Live Preview", wxOK | wxICON_ERROR);
  638. }
  639. break;
  640. }
  641. case ID_TOOLBAR_TOOL_SELECTION:
  642. case ID_TOOLBAR_TOOL_NEW_WINDOW:
  643. {
  644. // Disable all tool buttons then reactivate button according to event ID and set tool.
  645. m_ToolbarTools->ToggleTool(ID_TOOLBAR_TOOL_SELECTION, false);
  646. m_ToolbarTools->ToggleTool(ID_TOOLBAR_TOOL_NEW_WINDOW, false);
  647. m_ToolbarTools->ToggleTool(CE.GetId(), true);
  648. if (CE.GetId()==ID_TOOLBAR_TOOL_SELECTION)
  649. m_ToolManager.SetActiveTool(TOOL_SELECTION);
  650. else if (CE.GetId()==ID_TOOLBAR_TOOL_NEW_WINDOW)
  651. m_ToolManager.SetActiveTool(TOOL_NEW_WINDOW);
  652. break;
  653. }
  654. case ID_TOOLBAR_WINDOW_MOVE_UP:
  655. case ID_TOOLBAR_WINDOW_MOVE_DOWN:
  656. {
  657. const ArrayT< IntrusivePtrT<cf::GuiSys::WindowT> >& Sel=m_GuiDocument->GetSelection();
  658. if (Sel.Size()==0)
  659. {
  660. wxMessageBox("Please select a window first.");
  661. break;
  662. }
  663. if (Sel.Size()>1)
  664. {
  665. wxMessageBox("Sorry, only one window can be moved at a time.");
  666. break;
  667. }
  668. if (Sel[0]->GetParent().IsNull())
  669. {
  670. wxMessageBox("Sorry, the topmost (root) window cannot be moved.");
  671. break;
  672. }
  673. const int NewPos=Sel[0]->GetParent()->GetChildren().Find(Sel[0]) + (CE.GetId()==ID_TOOLBAR_WINDOW_MOVE_UP ? -1 : 1);
  674. if (NewPos<0)
  675. {
  676. wxMessageBox("This window is already the first child of its parent.\n\nUse cut and paste if you would like to assign the window to another parent.");
  677. break;
  678. }
  679. if (NewPos>=int(Sel[0]->GetParent()->GetChildren().Size()))
  680. {
  681. wxMessageBox("This window is already the last child of its parent.\n\nUse cut and paste if you would like to assign the window to another parent.");
  682. break;
  683. }
  684. SubmitCommand(new CommandChangeWindowHierarchyT(m_GuiDocument, Sel[0], Sel[0]->GetParent(), NewPos));
  685. break;
  686. }
  687. case ID_TOOLBAR_WINDOW_ROTATE_CW:
  688. case ID_TOOLBAR_WINDOW_ROTATE_CCW:
  689. {
  690. const ArrayT< IntrusivePtrT<cf::GuiSys::WindowT> >& Sel = m_GuiDocument->GetSelection();
  691. ArrayT<CommandT*> SubCommands;
  692. for (unsigned int SelNr = 0; SelNr < Sel.Size(); SelNr++)
  693. {
  694. cf::TypeSys::VarT<float>* Rotation = dynamic_cast<cf::TypeSys::VarT<float>*>(Sel[SelNr]->GetTransform()->GetMemberVars().Find("Rotation"));
  695. if (Rotation)
  696. {
  697. const float NewRotAngle = Rotation->Get() + (CE.GetId() == ID_TOOLBAR_WINDOW_ROTATE_CW ? 15.0f : 345.0f);
  698. SubCommands.PushBack(new CommandSetCompVarT<float>(m_GuiDocument->GetAdapter(), *Rotation, fmod(NewRotAngle, 360.0f)));
  699. }
  700. }
  701. if (SubCommands.Size() == 1)
  702. {
  703. SubmitCommand(SubCommands[0]);
  704. }
  705. else if (SubCommands.Size() > 1)
  706. {
  707. SubmitCommand(new CommandMacroT(SubCommands, "Rotate windows"));
  708. }
  709. break;
  710. }
  711. case ID_TOOLBAR_TEXT_ALIGN_LEFT:
  712. case ID_TOOLBAR_TEXT_ALIGN_CENTER:
  713. case ID_TOOLBAR_TEXT_ALIGN_RIGHT:
  714. {
  715. const ArrayT< IntrusivePtrT<cf::GuiSys::WindowT> >& Sel = m_GuiDocument->GetSelection();
  716. ArrayT<CommandT*> SubCommands;
  717. for (unsigned int SelNr = 0; SelNr < Sel.Size(); SelNr++)
  718. {
  719. IntrusivePtrT<cf::GuiSys::ComponentBaseT> CompText = Sel[SelNr]->GetComponent("Text");
  720. if (CompText != NULL)
  721. {
  722. cf::GuiSys::ComponentTextT::VarTextAlignHorT* AlignHor = dynamic_cast<cf::GuiSys::ComponentTextT::VarTextAlignHorT*>(CompText->GetMemberVars().Find("horAlign"));
  723. if (AlignHor)
  724. {
  725. const int HOR_ALIGN = (CE.GetId() == ID_TOOLBAR_TEXT_ALIGN_LEFT) ? cf::GuiSys::ComponentTextT::VarTextAlignHorT::LEFT :
  726. (CE.GetId() == ID_TOOLBAR_TEXT_ALIGN_CENTER) ? cf::GuiSys::ComponentTextT::VarTextAlignHorT::CENTER :
  727. cf::GuiSys::ComponentTextT::VarTextAlignHorT::RIGHT;
  728. SubCommands.PushBack(new CommandSetCompVarT<int>(m_GuiDocument->GetAdapter(), *AlignHor, HOR_ALIGN));
  729. }
  730. }
  731. }
  732. if (SubCommands.Size() == 1)
  733. {
  734. SubmitCommand(SubCommands[0]);
  735. }
  736. else if (SubCommands.Size() > 1)
  737. {
  738. SubmitCommand(new CommandMacroT(SubCommands, "Set hor. Align"));
  739. }
  740. break;
  741. }
  742. case ID_TOOLBAR_ZOOM_IN:
  743. m_RenderWindow->ZoomIn();
  744. break;
  745. case ID_TOOLBAR_ZOOM_OUT:
  746. m_RenderWindow->ZoomOut();
  747. break;
  748. case ID_TOOLBAR_ZOOM_FIT:
  749. m_RenderWindow->ZoomFit();
  750. break;
  751. case ID_TOOLBAR_ZOOM_100:
  752. m_RenderWindow->ZoomSet(1.0f);
  753. break;
  754. }
  755. }