1 /*!
2 	@file
3 	@author		Albert Semenov
4 	@date		08/2010
5 */
6 
7 #include "Precompiled.h"
8 #include "EditorState.h"
9 #include "Application.h"
10 #include "FileSystemInfo/FileSystemInfo.h"
11 #include "Localise.h"
12 #include "CommandManager.h"
13 #include "ActionManager.h"
14 #include "MessageBoxManager.h"
15 #include "DialogManager.h"
16 #include "StateManager.h"
17 #include "RecentFilesManager.h"
18 #include "ExportManager.h"
19 #include "DataManager.h"
20 #include "DataSelectorManager.h"
21 #include "FactoryManager.h"
22 #include "SettingsManager.h"
23 #include "FontExportSerializer.h"
24 
25 namespace tools
26 {
27 
FACTORY_ITEM_ATTRIBUTE(EditorState)28 	FACTORY_ITEM_ATTRIBUTE(EditorState)
29 
30 	EditorState::EditorState() :
31 		mMainPane(nullptr),
32 		mOpenSaveFileDialog(nullptr),
33 		mSettingsWindow(nullptr)
34 	{
35 		CommandManager::getInstance().getEvent("Command_FileDrop")->connect(this, &EditorState::commandFileDrop);
36 		CommandManager::getInstance().getEvent("Command_FileLoad")->connect(this, &EditorState::commandLoad);
37 		CommandManager::getInstance().getEvent("Command_FileSave")->connect(this, &EditorState::commandSave);
38 		CommandManager::getInstance().getEvent("Command_FileSaveAs")->connect(this, &EditorState::commandSaveAs);
39 		CommandManager::getInstance().getEvent("Command_Export")->connect(this, &EditorState::commandExport);
40 		CommandManager::getInstance().getEvent("Command_ClearAll")->connect(this, &EditorState::commandClear);
41 		CommandManager::getInstance().getEvent("Command_Settings")->connect(this, &EditorState::commandSettings);
42 		CommandManager::getInstance().getEvent("Command_RecentFiles")->connect(this, &EditorState::commandRecentFiles);
43 		CommandManager::getInstance().getEvent("Command_Quit")->connect(this, &EditorState::commandQuit);
44 		CommandManager::getInstance().getEvent("Command_Undo")->connect(this, &EditorState::commandUndo);
45 		CommandManager::getInstance().getEvent("Command_Redo")->connect(this, &EditorState::commandRedo);
46 
47 		if (!SettingsManager::getInstance().tryGetValue("EditorState/DefaultFileName", mDefaultFileName))
48 			mDefaultFileName = "unnamed.xml";
49 		mFileName = mDefaultFileName;
50 	}
51 
initState()52 	void EditorState::initState()
53 	{
54 		addUserTag("\\n", "\n");
55 		addUserTag("CurrentFileName", mFileName);
56 
57 		mMainPane = new Control();
58 		mMainPane->Initialise(SettingsManager::getInstance().getValue("EditorState/MainPaneLayout"));
59 
60 		mSettingsWindow = new SettingsWindow();
61 		mSettingsWindow->Initialise(SettingsManager::getInstance().getValue("EditorState/SettingsWindowLayout"));
62 		mSettingsWindow->eventEndDialog.connect(this, &EditorState::notifySettingsWindowEndDialog);
63 
64 		mOpenSaveFileDialog = new OpenSaveFileDialog();
65 		mOpenSaveFileDialog->Initialise(SettingsManager::getInstance().getValue("EditorState/OpenSaveFileDialogLayout"));
66 		mOpenSaveFileDialog->eventEndDialog.connect(this, &EditorState::notifyEndDialog);
67 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
68 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
69 
70 		std::string fileMask;
71 		if (!SettingsManager::getInstance().tryGetValue("EditorState/DefaultFileMask", fileMask))
72 			fileMask = "*.xml";
73 		mOpenSaveFileDialog->setFileMask(fileMask);
74 
75 		ActionManager::getInstance().eventChanges.connect(this, &EditorState::notifyChanges);
76 
77 		updateCaption();
78 
79 		if (!Application::getInstance().getParams().empty())
80 		{
81 			mFileName = Application::getInstance().getParams().front();
82 			addUserTag("CurrentFileName", mFileName);
83 
84 			load();
85 			updateCaption();
86 		}
87 	}
88 
cleanupState()89 	void EditorState::cleanupState()
90 	{
91 		ActionManager::getInstance().eventChanges.disconnect(this);
92 
93 		mOpenSaveFileDialog->eventEndDialog.disconnect(this);
94 		delete mOpenSaveFileDialog;
95 		mOpenSaveFileDialog = nullptr;
96 
97 		delete mSettingsWindow;
98 		mSettingsWindow = nullptr;
99 
100 		delete mMainPane;
101 		mMainPane = nullptr;
102 	}
103 
pauseState()104 	void EditorState::pauseState()
105 	{
106 		mMainPane->getRoot()->setVisible(false);
107 	}
108 
resumeState()109 	void EditorState::resumeState()
110 	{
111 		mMainPane->getRoot()->setVisible(true);
112 	}
113 
updateCaption()114 	void EditorState::updateCaption()
115 	{
116 		addUserTag("HasChanged", ActionManager::getInstance().getChanges() ? "*" : "");
117 
118 		CommandManager::getInstance().executeCommand("Command_UpdateAppCaption");
119 	}
120 
commandLoad(const MyGUI::UString & _commandName,bool & _result)121 	void EditorState::commandLoad(const MyGUI::UString& _commandName, bool& _result)
122 	{
123 		if (!checkCommand())
124 			return;
125 
126 		if (ActionManager::getInstance().getChanges())
127 		{
128 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
129 				replaceTags("Warning"),
130 				replaceTags("MessageUnsavedData"),
131 				MyGUI::MessageBoxStyle::IconQuest
132 					| MyGUI::MessageBoxStyle::Yes
133 					| MyGUI::MessageBoxStyle::No
134 					| MyGUI::MessageBoxStyle::Cancel);
135 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultLoad);
136 		}
137 		else
138 		{
139 			showLoadWindow();
140 		}
141 
142 		_result = true;
143 	}
144 
commandSave(const MyGUI::UString & _commandName,bool & _result)145 	void EditorState::commandSave(const MyGUI::UString& _commandName, bool& _result)
146 	{
147 		if (!checkCommand())
148 			return;
149 
150 		if (ActionManager::getInstance().getChanges())
151 		{
152 			if (mFileName == mDefaultFileName)
153 				showSaveAsWindow();
154 			else
155 				save();
156 		}
157 
158 		_result = true;
159 	}
160 
commandSaveAs(const MyGUI::UString & _commandName,bool & _result)161 	void EditorState::commandSaveAs(const MyGUI::UString& _commandName, bool& _result)
162 	{
163 		if (!checkCommand())
164 			return;
165 
166 		showSaveAsWindow();
167 
168 		_result = true;
169 	}
170 
commandExport(const MyGUI::UString & _commandName,bool & _result)171 	void EditorState::commandExport(const MyGUI::UString& _commandName, bool& _result)
172 	{
173 		if (!checkCommand())
174 			return;
175 
176 		showExportWindow();
177 
178 		_result = true;
179 	}
180 
commandClear(const MyGUI::UString & _commandName,bool & _result)181 	void EditorState::commandClear(const MyGUI::UString& _commandName, bool& _result)
182 	{
183 		if (!checkCommand())
184 			return;
185 
186 		if (ActionManager::getInstance().getChanges())
187 		{
188 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
189 				replaceTags("Warning"),
190 				replaceTags("MessageUnsavedData"),
191 				MyGUI::MessageBoxStyle::IconQuest
192 					| MyGUI::MessageBoxStyle::Yes
193 					| MyGUI::MessageBoxStyle::No
194 					| MyGUI::MessageBoxStyle::Cancel);
195 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultClear);
196 		}
197 		else
198 		{
199 			clear();
200 		}
201 
202 		_result = true;
203 	}
204 
commandQuit(const MyGUI::UString & _commandName,bool & _result)205 	void EditorState::commandQuit(const MyGUI::UString& _commandName, bool& _result)
206 	{
207 		if (!checkCommand())
208 			return;
209 
210 		if (ActionManager::getInstance().getChanges())
211 		{
212 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
213 				replaceTags("Warning"),
214 				replaceTags("MessageUnsavedData"),
215 				MyGUI::MessageBoxStyle::IconQuest
216 					| MyGUI::MessageBoxStyle::Yes
217 					| MyGUI::MessageBoxStyle::No
218 					| MyGUI::MessageBoxStyle::Cancel);
219 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultQuit);
220 		}
221 		else
222 		{
223 			StateManager::getInstance().stateEvent(this, "Exit");
224 		}
225 
226 		_result = true;
227 	}
228 
commandFileDrop(const MyGUI::UString & _commandName,bool & _result)229 	void EditorState::commandFileDrop(const MyGUI::UString& _commandName, bool& _result)
230 	{
231 		if (!checkCommand())
232 			return;
233 
234 		mDropFileName = CommandManager::getInstance().getCommandData();
235 		if (mDropFileName.empty())
236 			return;
237 
238 		if (ActionManager::getInstance().getChanges())
239 		{
240 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
241 				replaceTags("Warning"),
242 				replaceTags("MessageUnsavedData"),
243 				MyGUI::MessageBoxStyle::IconQuest
244 					| MyGUI::MessageBoxStyle::Yes
245 					| MyGUI::MessageBoxStyle::No
246 					| MyGUI::MessageBoxStyle::Cancel);
247 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultLoadDropFile);
248 		}
249 		else
250 		{
251 			clear();
252 
253 			loadDropFile();
254 		}
255 
256 		_result = true;
257 	}
258 
notifyMessageBoxResultLoad(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)259 	void EditorState::notifyMessageBoxResultLoad(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
260 	{
261 		if (_result == MyGUI::MessageBoxStyle::Yes)
262 		{
263 			save();
264 			clear();
265 
266 			showLoadWindow();
267 		}
268 		else if (_result == MyGUI::MessageBoxStyle::No)
269 		{
270 			clear();
271 
272 			showLoadWindow();
273 		}
274 	}
275 
notifyMessageBoxResultLoadDropFile(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)276 	void EditorState::notifyMessageBoxResultLoadDropFile(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
277 	{
278 		if (_result == MyGUI::MessageBoxStyle::Yes)
279 		{
280 			save();
281 			clear();
282 
283 			loadDropFile();
284 		}
285 		else if (_result == MyGUI::MessageBoxStyle::No)
286 		{
287 			clear();
288 
289 			loadDropFile();
290 		}
291 	}
292 
loadDropFile()293 	void EditorState::loadDropFile()
294 	{
295 		mFileName = mDropFileName;
296 		addUserTag("CurrentFileName", mFileName);
297 
298 		load();
299 		updateCaption();
300 	}
301 
showLoadWindow()302 	void EditorState::showLoadWindow()
303 	{
304 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
305 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
306 		mOpenSaveFileDialog->setDialogInfo(replaceTags("CaptionOpenFile"), replaceTags("ButtonOpenFile"));
307 		mOpenSaveFileDialog->setMode("Load");
308 		mOpenSaveFileDialog->doModal();
309 	}
310 
notifyEndDialog(Dialog * _sender,bool _result)311 	void EditorState::notifyEndDialog(Dialog* _sender, bool _result)
312 	{
313 		if (_result)
314 		{
315 			if (mOpenSaveFileDialog->getMode() == "SaveAs")
316 			{
317 				RecentFilesManager::getInstance().setRecentFolder(mOpenSaveFileDialog->getCurrentFolder());
318 				mFileName = common::concatenatePath(mOpenSaveFileDialog->getCurrentFolder(), mOpenSaveFileDialog->getFileName());
319 				addUserTag("CurrentFileName", mFileName);
320 
321 				save();
322 				updateCaption();
323 			}
324 			else if (mOpenSaveFileDialog->getMode() == "Export")
325 			{
326 				FontExportSerializer::exportData(mOpenSaveFileDialog->getCurrentFolder(), mOpenSaveFileDialog->getFileName());
327 			}
328 			else if (mOpenSaveFileDialog->getMode() == "Load")
329 			{
330 				RecentFilesManager::getInstance().setRecentFolder(mOpenSaveFileDialog->getCurrentFolder());
331 				mFileName = common::concatenatePath(mOpenSaveFileDialog->getCurrentFolder(), mOpenSaveFileDialog->getFileName());
332 				addUserTag("CurrentFileName", mFileName);
333 
334 				load();
335 				updateCaption();
336 			}
337 		}
338 
339 		mOpenSaveFileDialog->endModal();
340 	}
341 
notifyMessageBoxResultClear(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)342 	void EditorState::notifyMessageBoxResultClear(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
343 	{
344 		if (_result == MyGUI::MessageBoxStyle::Yes)
345 		{
346 			save();
347 			clear();
348 		}
349 		else if (_result == MyGUI::MessageBoxStyle::No)
350 		{
351 			clear();
352 		}
353 	}
354 
showSaveAsWindow()355 	void EditorState::showSaveAsWindow()
356 	{
357 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
358 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
359 		mOpenSaveFileDialog->setDialogInfo(replaceTags("CaptionSaveFile"), replaceTags("ButtonSaveFile"));
360 		mOpenSaveFileDialog->setMode("SaveAs");
361 		mOpenSaveFileDialog->doModal();
362 	}
363 
showExportWindow()364 	void EditorState::showExportWindow()
365 	{
366 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
367 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
368 		mOpenSaveFileDialog->setDialogInfo(replaceTags("CaptionSaveFile"), replaceTags("ButtonSaveFile"));
369 		mOpenSaveFileDialog->setMode("Export");
370 		mOpenSaveFileDialog->doModal();
371 	}
372 
notifyMessageBoxResultQuit(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)373 	void EditorState::notifyMessageBoxResultQuit(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
374 	{
375 		if (_result == MyGUI::MessageBoxStyle::Yes)
376 		{
377 			if (mFileName == mDefaultFileName)
378 			{
379 				showSaveAsWindow();
380 			}
381 			else
382 			{
383 				save();
384 				StateManager::getInstance().stateEvent(this, "Exit");
385 			}
386 		}
387 		else if (_result == MyGUI::MessageBoxStyle::No)
388 		{
389 			StateManager::getInstance().stateEvent(this, "Exit");
390 		}
391 	}
392 
notifyChanges()393 	void EditorState::notifyChanges()
394 	{
395 		updateCaption();
396 	}
397 
checkCommand()398 	bool EditorState::checkCommand()
399 	{
400 		if (DialogManager::getInstance().getAnyDialog())
401 			return false;
402 
403 		if (MessageBoxManager::getInstance().hasAny())
404 			return false;
405 
406 		if (!StateManager::getInstance().getStateActivate(this))
407 			return false;
408 
409 		return true;
410 	}
411 
clear()412 	void EditorState::clear()
413 	{
414 		DataManager::getInstance().clear();
415 		ActionManager::getInstance().reset();
416 		DataSelectorManager::getInstance().changeParent(DataManager::getInstance().getRoot());
417 
418 		mFileName = mDefaultFileName;
419 		addUserTag("CurrentFileName", mFileName);
420 
421 		updateCaption();
422 	}
423 
load()424 	void EditorState::load()
425 	{
426 		DataManager::getInstance().clear();
427 		ActionManager::getInstance().reset();
428 		DataSelectorManager::getInstance().changeParent(DataManager::getInstance().getRoot());
429 
430 		pugi::xml_document doc;
431 		pugi::xml_parse_result result = doc.load_file(mFileName.asWStr_c_str());
432 		if (result)
433 		{
434 			bool success = ExportManager::getInstance().deserialization(doc);
435 			if (success)
436 			{
437 				if (mFileName != mDefaultFileName)
438 					RecentFilesManager::getInstance().addRecentFile(mFileName);
439 
440 				DataSelectorManager::getInstance().changeParent(DataManager::getInstance().getRoot());
441 			}
442 			else
443 			{
444 				/*MyGUI::Message* message =*/ MessageBoxManager::getInstance().create(
445 					replaceTags("Error"),
446 					replaceTags("MessageIncorrectFileFormat"),
447 					MyGUI::MessageBoxStyle::IconError
448 						| MyGUI::MessageBoxStyle::Yes);
449 
450 				mFileName = mDefaultFileName;
451 				addUserTag("CurrentFileName", mFileName);
452 
453 				updateCaption();
454 			}
455 		}
456 		else
457 		{
458 			/*MyGUI::Message* message =*/ MessageBoxManager::getInstance().create(
459 				replaceTags("Error"),
460 				result.description(),
461 				MyGUI::MessageBoxStyle::IconError
462 					| MyGUI::MessageBoxStyle::Yes);
463 		}
464 	}
465 
save()466 	bool EditorState::save()
467 	{
468 		pugi::xml_document doc;
469 		pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
470 		decl.append_attribute("version") = "1.0";
471 		decl.append_attribute("encoding") = "UTF-8";
472 
473 		ExportManager::getInstance().serialization(doc);
474 
475 		bool result = doc.save_file(mFileName.asWStr_c_str(), "\t", (pugi::format_indent | pugi::format_write_bom | pugi::format_win_new_line) & (~pugi::format_space_before_slash));
476 
477 		if (result)
478 		{
479 			if (mFileName != mDefaultFileName)
480 				RecentFilesManager::getInstance().addRecentFile(mFileName);
481 
482 			ActionManager::getInstance().saveChanges();
483 			return true;
484 		}
485 
486 		/*MyGUI::Message* message =*/ MessageBoxManager::getInstance().create(
487 			replaceTags("Error"),
488 			"Error save file",
489 			MyGUI::MessageBoxStyle::IconError
490 				| MyGUI::MessageBoxStyle::Yes);
491 
492 		return false;
493 	}
494 
commandRecentFiles(const MyGUI::UString & _commandName,bool & _result)495 	void EditorState::commandRecentFiles(const MyGUI::UString& _commandName, bool& _result)
496 	{
497 		commandFileDrop(_commandName, _result);
498 	}
499 
commandSettings(const MyGUI::UString & _commandName,bool & _result)500 	void EditorState::commandSettings(const MyGUI::UString& _commandName, bool& _result)
501 	{
502 		mSettingsWindow->SendCommand("Command_LoadSettings");
503 		mSettingsWindow->doModal();
504 
505 		_result = true;
506 	}
507 
notifySettingsWindowEndDialog(Dialog * _dialog,bool _result)508 	void EditorState::notifySettingsWindowEndDialog(Dialog* _dialog, bool _result)
509 	{
510 		MYGUI_ASSERT(mSettingsWindow == _dialog, "mSettingsWindow == _sender");
511 
512 		if (_result)
513 			mSettingsWindow->SendCommand("Command_SaveSettings");
514 
515 		mSettingsWindow->endModal();
516 	}
517 
commandUndo(const MyGUI::UString & _commandName,bool & _result)518 	void EditorState::commandUndo(const MyGUI::UString& _commandName, bool& _result)
519 	{
520 		if (!checkCommand())
521 			return;
522 
523 		ActionManager::getInstance().undoAction();
524 
525 		_result = true;
526 	}
527 
commandRedo(const MyGUI::UString & _commandName,bool & _result)528 	void EditorState::commandRedo(const MyGUI::UString& _commandName, bool& _result)
529 	{
530 		if (!checkCommand())
531 			return;
532 
533 		ActionManager::getInstance().redoAction();
534 
535 		_result = true;
536 	}
537 
538 }
539