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