1 #include "Precompiled.h"
2 #include "EditorState.h"
3 #include "Common.h"
4 #include "EditorWidgets.h"
5 #include "WidgetTypes.h"
6 #include "UndoManager.h"
7 #include "GroupMessage.h"
8 #include "FileSystemInfo/FileSystemInfo.h"
9 #include "CommandManager.h"
10 #include "SettingsManager.h"
11 #include "WidgetSelectorManager.h"
12 #include "HotKeyManager.h"
13 #include "MessageBoxManager.h"
14 #include "DialogManager.h"
15 #include "StateManager.h"
16 #include "Localise.h"
17 #include "Application.h"
18 #include "RecentFilesManager.h"
19 #include "WidgetCreatorManager.h"
20 #include "FactoryManager.h"
21 
22 namespace tools
23 {
24 
FACTORY_ITEM_ATTRIBUTE(EditorState)25 	FACTORY_ITEM_ATTRIBUTE(EditorState)
26 
27 	EditorState::EditorState() :
28 		mSettingsWindow(nullptr),
29 		mCodeGenerator(nullptr),
30 		mOpenSaveFileDialog(nullptr),
31 		mMainPaneControl(nullptr),
32 		mFileName("unnamed.layout"),
33 		mDefaultFileName("unnamed.layout")
34 	{
35 		CommandManager::getInstance().getEvent("Command_FileLoad")->connect(this, &EditorState::command_Load);
36 		CommandManager::getInstance().getEvent("Command_FileSave")->connect(this, &EditorState::command_Save);
37 		CommandManager::getInstance().getEvent("Command_FileSaveAs")->connect(this, &EditorState::command_SaveAs);
38 		CommandManager::getInstance().getEvent("Command_ClearAll")->connect(this, &EditorState::command_Clear);
39 		CommandManager::getInstance().getEvent("Command_Quit")->connect(this, &EditorState::command_Quit);
40 		CommandManager::getInstance().getEvent("Command_Settings")->connect(this, &EditorState::command_Settings);
41 		CommandManager::getInstance().getEvent("Command_CodeGenerator")->connect(this, &EditorState::command_CodeGenerator);
42 		CommandManager::getInstance().getEvent("Command_OpenRecentFile")->connect(this, &EditorState::command_OpenRecentFile);
43 		CommandManager::getInstance().getEvent("Command_FileDrop")->connect(this, &EditorState::command_FileDrop);
44 		CommandManager::getInstance().getEvent("Command_SaveItemAs")->connect(this, &EditorState::command_SaveItemAs);
45 		CommandManager::getInstance().getEvent("Command_UpdateItemName")->connect(this, &EditorState::command_UpdateItemName);
46 		CommandManager::getInstance().getEvent("Command_UpdateResources")->connect(this, &EditorState::command_UpdateResources);
47 	}
48 
initState()49 	void EditorState::initState()
50 	{
51 		addUserTag("\\n", "\n");
52 		setFileName(mFileName);
53 
54 		mMainPaneControl = new MainPaneControl();
55 
56 		mSettingsWindow = new SettingsWindow();
57 		mSettingsWindow->Initialise(SettingsManager::getInstance().getValue("EditorState/SettingsWindowLayout"));
58 		mSettingsWindow->eventEndDialog.connect(this, &EditorState::notifySettingsWindowEndDialog);
59 
60 		mCodeGenerator = new CodeGenerator();
61 		mCodeGenerator->eventEndDialog.connect(this, &EditorState::notifyEndDialogCodeGenerator);
62 
63 		mOpenSaveFileDialog = new OpenSaveFileDialog();
64 		mOpenSaveFileDialog->Initialise(SettingsManager::getInstance().getValue("EditorState/OpenSaveFileDialogLayout"));
65 		mOpenSaveFileDialog->setFileMask("*.layout");
66 		mOpenSaveFileDialog->eventEndDialog.connect(this, &EditorState::notifyEndDialogOpenSaveFile);
67 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
68 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
69 
70 		updateCaption();
71 
72 		if (!Application::getInstance().getParams().empty())
73 		{
74 			setFileName(Application::getInstance().getParams().front());
75 
76 			load();
77 			updateCaption();
78 		}
79 
80 		UndoManager::getInstance().eventChanges += MyGUI::newDelegate(this, &EditorState::notifyChanges);
81 	}
82 
cleanupState()83 	void EditorState::cleanupState()
84 	{
85 		UndoManager::getInstance().eventChanges -= MyGUI::newDelegate(this, &EditorState::notifyChanges);
86 
87 		delete mSettingsWindow;
88 		mSettingsWindow = nullptr;
89 
90 		delete mCodeGenerator;
91 		mCodeGenerator = nullptr;
92 
93 		delete mOpenSaveFileDialog;
94 		mOpenSaveFileDialog = nullptr;
95 
96 		delete mMainPaneControl;
97 		mMainPaneControl = nullptr;
98 	}
99 
notifySettingsWindowEndDialog(Dialog * _dialog,bool _result)100 	void EditorState::notifySettingsWindowEndDialog(Dialog* _dialog, bool _result)
101 	{
102 		MYGUI_ASSERT(mSettingsWindow == _dialog, "mSettingsWindow == _sender");
103 
104 		if (_result)
105 			mSettingsWindow->SendCommand("Command_SaveSettings");
106 
107 		mSettingsWindow->endModal();
108 	}
109 
command_Settings(const MyGUI::UString & _commandName,bool & _result)110 	void EditorState::command_Settings(const MyGUI::UString& _commandName, bool& _result)
111 	{
112 		if (!checkCommand())
113 			return;
114 
115 		mSettingsWindow->SendCommand("Command_LoadSettings");
116 		mSettingsWindow->doModal();
117 
118 		_result = true;
119 	}
120 
command_CodeGenerator(const MyGUI::UString & _commandName,bool & _result)121 	void EditorState::command_CodeGenerator(const MyGUI::UString& _commandName, bool& _result)
122 	{
123 		if (!checkCommand())
124 			return;
125 
126 		mCodeGenerator->loadTemplate();
127 		mCodeGenerator->doModal();
128 
129 		_result = true;
130 	}
131 
command_OpenRecentFile(const MyGUI::UString & _commandName,bool & _result)132 	void EditorState::command_OpenRecentFile(const MyGUI::UString& _commandName, bool& _result)
133 	{
134 		if (!checkCommand())
135 			return;
136 
137 		command_FileDrop(_commandName, _result);
138 	}
139 
command_Load(const MyGUI::UString & _commandName,bool & _result)140 	void EditorState::command_Load(const MyGUI::UString& _commandName, bool& _result)
141 	{
142 		if (!checkCommand())
143 			return;
144 
145 		if (UndoManager::getInstance().isUnsaved())
146 		{
147 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
148 				replaceTags("Warning"),
149 				replaceTags("MessageUnsavedData"),
150 				MyGUI::MessageBoxStyle::IconQuest
151 					| MyGUI::MessageBoxStyle::Yes
152 					| MyGUI::MessageBoxStyle::No
153 					| MyGUI::MessageBoxStyle::Cancel);
154 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultLoad);
155 		}
156 		else
157 		{
158 			showLoadWindow();
159 		}
160 
161 		_result = true;
162 	}
163 
command_Save(const MyGUI::UString & _commandName,bool & _result)164 	void EditorState::command_Save(const MyGUI::UString& _commandName, bool& _result)
165 	{
166 		if (!checkCommand())
167 			return;
168 
169 		if (UndoManager::getInstance().isUnsaved())
170 		{
171 			if (mFileName == mDefaultFileName)
172 				showSaveAsWindow();
173 			else
174 				save();
175 		}
176 
177 		_result = true;
178 	}
179 
command_SaveAs(const MyGUI::UString & _commandName,bool & _result)180 	void EditorState::command_SaveAs(const MyGUI::UString& _commandName, bool& _result)
181 	{
182 		if (!checkCommand())
183 			return;
184 
185 		showSaveAsWindow();
186 
187 		_result = true;
188 	}
189 
command_Clear(const MyGUI::UString & _commandName,bool & _result)190 	void EditorState::command_Clear(const MyGUI::UString& _commandName, bool& _result)
191 	{
192 		if (!checkCommand())
193 			return;
194 
195 		if (UndoManager::getInstance().isUnsaved())
196 		{
197 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
198 				replaceTags("Warning"),
199 				replaceTags("MessageUnsavedData"),
200 				MyGUI::MessageBoxStyle::IconQuest
201 					| MyGUI::MessageBoxStyle::Yes
202 					| MyGUI::MessageBoxStyle::No
203 					| MyGUI::MessageBoxStyle::Cancel);
204 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultClear);
205 		}
206 		else
207 		{
208 			clear();
209 		}
210 
211 		_result = true;
212 	}
213 
command_Quit(const MyGUI::UString & _commandName,bool & _result)214 	void EditorState::command_Quit(const MyGUI::UString& _commandName, bool& _result)
215 	{
216 		if (!checkCommand())
217 			return;
218 
219 		if (UndoManager::getInstance().isUnsaved())
220 		{
221 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
222 				replaceTags("Warning"),
223 				replaceTags("MessageUnsavedData"),
224 				MyGUI::MessageBoxStyle::IconQuest
225 					| MyGUI::MessageBoxStyle::Yes
226 					| MyGUI::MessageBoxStyle::No
227 					| MyGUI::MessageBoxStyle::Cancel);
228 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultQuit);
229 		}
230 		else
231 		{
232 			StateManager::getInstance().stateEvent(this, "Exit");
233 		}
234 
235 		_result = true;
236 	}
237 
command_FileDrop(const MyGUI::UString & _commandName,bool & _result)238 	void EditorState::command_FileDrop(const MyGUI::UString& _commandName, bool& _result)
239 	{
240 		if (!checkCommand())
241 			return;
242 
243 		mDropFileName = CommandManager::getInstance().getCommandData();
244 		if (mDropFileName.empty())
245 			return;
246 
247 		if (UndoManager::getInstance().isUnsaved())
248 		{
249 			MyGUI::Message* message = MessageBoxManager::getInstance().create(
250 				replaceTags("Warning"),
251 				replaceTags("MessageUnsavedData"),
252 				MyGUI::MessageBoxStyle::IconQuest
253 					| MyGUI::MessageBoxStyle::Yes
254 					| MyGUI::MessageBoxStyle::No
255 					| MyGUI::MessageBoxStyle::Cancel);
256 			message->eventMessageBoxResult += MyGUI::newDelegate(this, &EditorState::notifyMessageBoxResultLoadDropFile);
257 		}
258 		else
259 		{
260 			clear();
261 
262 			loadDropFile();
263 		}
264 
265 		_result = true;
266 	}
267 
command_SaveItemAs(const MyGUI::UString & _commandName,bool & _result)268 	void EditorState::command_SaveItemAs(const MyGUI::UString& _commandName, bool& _result)
269 	{
270 		if (!checkCommand())
271 			return;
272 
273 		setFileName(CommandManager::getInstance().getCommandData());
274 
275 		save();
276 		updateCaption();
277 
278 		_result = true;
279 	}
280 
command_UpdateItemName(const MyGUI::UString & _commandName,bool & _result)281 	void EditorState::command_UpdateItemName(const MyGUI::UString& _commandName, bool& _result)
282 	{
283 		if (!checkCommand())
284 			return;
285 
286 		setFileName(mFileName);
287 		updateCaption();
288 
289 		_result = true;
290 	}
291 
clear()292 	void EditorState::clear()
293 	{
294 		WidgetCreatorManager::getInstance().resetCreatorInfo();
295 		EditorWidgets::getInstance().clear();
296 
297 		WidgetSelectorManager::getInstance().setSelectedWidget(nullptr);
298 
299 		UndoManager::getInstance().shutdown();
300 		UndoManager::getInstance().initialise(EditorWidgets::getInstancePtr());
301 
302 		setFileName(mDefaultFileName);
303 
304 		updateCaption();
305 	}
306 
load()307 	void EditorState::load()
308 	{
309 		if (EditorWidgets::getInstance().load(mFileName))
310 		{
311 			if (mFileName != mDefaultFileName && !isProjectFile(mFileName))
312 				RecentFilesManager::getInstance().addRecentFile(mFileName);
313 
314 			UndoManager::getInstance().addValue();
315 			UndoManager::getInstance().setUnsaved(false);
316 		}
317 		else
318 		{
319 			/*MyGUI::Message* message = */MessageBoxManager::getInstance().create(
320 				replaceTags("Error"),
321 				replaceTags("MessageFailedLoadFile"),
322 				MyGUI::MessageBoxStyle::IconError | MyGUI::MessageBoxStyle::Ok
323 			);
324 
325 			setFileName(mDefaultFileName);
326 
327 			updateCaption();
328 		}
329 	}
330 
save()331 	bool EditorState::save()
332 	{
333 		if (EditorWidgets::getInstance().save(mFileName))
334 		{
335 			if (mFileName != mDefaultFileName && !isProjectFile(mFileName))
336 				RecentFilesManager::getInstance().addRecentFile(mFileName);
337 
338 			UndoManager::getInstance().addValue();
339 			UndoManager::getInstance().setUnsaved(false);
340 			return true;
341 		}
342 		else
343 		{
344 			/*MyGUI::Message* message = */MessageBoxManager::getInstance().create(
345 				replaceTags("Error"),
346 				replaceTags("MessageFailedSaveFile"),
347 				MyGUI::MessageBoxStyle::IconError | MyGUI::MessageBoxStyle::Ok
348 			);
349 		}
350 		return false;
351 	}
352 
updateCaption()353 	void EditorState::updateCaption()
354 	{
355 		addUserTag("HasChanged", UndoManager::getInstance().isUnsaved() ? "*" : "");
356 
357 		CommandManager::getInstance().executeCommand("Command_UpdateAppCaption");
358 	}
359 
notifyMessageBoxResultLoad(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)360 	void EditorState::notifyMessageBoxResultLoad(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
361 	{
362 		if (_result == MyGUI::MessageBoxStyle::Yes)
363 		{
364 			if (save())
365 			{
366 				clear();
367 
368 				showLoadWindow();
369 			}
370 		}
371 		else if (_result == MyGUI::MessageBoxStyle::No)
372 		{
373 			clear();
374 
375 			showLoadWindow();
376 		}
377 	}
378 
notifyMessageBoxResultLoadDropFile(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)379 	void EditorState::notifyMessageBoxResultLoadDropFile(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
380 	{
381 		if (_result == MyGUI::MessageBoxStyle::Yes)
382 		{
383 			if (save())
384 			{
385 				clear();
386 
387 				loadDropFile();
388 			}
389 		}
390 		else if (_result == MyGUI::MessageBoxStyle::No)
391 		{
392 			clear();
393 
394 			loadDropFile();
395 		}
396 	}
397 
loadDropFile()398 	void EditorState::loadDropFile()
399 	{
400 		setFileName(mDropFileName);
401 
402 		load();
403 		updateCaption();
404 	}
405 
showLoadWindow()406 	void EditorState::showLoadWindow()
407 	{
408 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
409 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
410 		mOpenSaveFileDialog->setDialogInfo(replaceTags("CaptionOpenFile"), replaceTags("ButtonOpenFile"));
411 		mOpenSaveFileDialog->setMode("Load");
412 		mOpenSaveFileDialog->doModal();
413 	}
414 
notifyEndDialogOpenSaveFile(Dialog * _sender,bool _result)415 	void EditorState::notifyEndDialogOpenSaveFile(Dialog* _sender, bool _result)
416 	{
417 		if (_result)
418 		{
419 			if (mOpenSaveFileDialog->getMode() == "SaveAs")
420 			{
421 				RecentFilesManager::getInstance().setRecentFolder(mOpenSaveFileDialog->getCurrentFolder());
422 				setFileName(common::concatenatePath(mOpenSaveFileDialog->getCurrentFolder(), mOpenSaveFileDialog->getFileName()));
423 
424 				save();
425 				updateCaption();
426 			}
427 			else if (mOpenSaveFileDialog->getMode() == "Load")
428 			{
429 				clear();
430 
431 				RecentFilesManager::getInstance().setRecentFolder(mOpenSaveFileDialog->getCurrentFolder());
432 				setFileName(common::concatenatePath(mOpenSaveFileDialog->getCurrentFolder(), mOpenSaveFileDialog->getFileName()));
433 
434 				load();
435 				updateCaption();
436 			}
437 		}
438 
439 		mOpenSaveFileDialog->endModal();
440 	}
441 
notifyMessageBoxResultClear(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)442 	void EditorState::notifyMessageBoxResultClear(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
443 	{
444 		if (_result == MyGUI::MessageBoxStyle::Yes)
445 		{
446 			if (save())
447 			{
448 				clear();
449 			}
450 		}
451 		else if (_result == MyGUI::MessageBoxStyle::No)
452 		{
453 			clear();
454 		}
455 	}
456 
showSaveAsWindow()457 	void EditorState::showSaveAsWindow()
458 	{
459 		mOpenSaveFileDialog->setCurrentFolder(RecentFilesManager::getInstance().getRecentFolder());
460 		mOpenSaveFileDialog->setRecentFolders(RecentFilesManager::getInstance().getRecentFolders());
461 		mOpenSaveFileDialog->setDialogInfo(replaceTags("CaptionSaveFile"), replaceTags("ButtonSaveFile"));
462 		mOpenSaveFileDialog->setMode("SaveAs");
463 		mOpenSaveFileDialog->doModal();
464 	}
465 
notifyMessageBoxResultQuit(MyGUI::Message * _sender,MyGUI::MessageBoxStyle _result)466 	void EditorState::notifyMessageBoxResultQuit(MyGUI::Message* _sender, MyGUI::MessageBoxStyle _result)
467 	{
468 		if (_result == MyGUI::MessageBoxStyle::Yes)
469 		{
470 			if (mFileName == mDefaultFileName)
471 			{
472 				showSaveAsWindow();
473 			}
474 			else
475 			{
476 				if (save())
477 				{
478 					StateManager::getInstance().stateEvent(this, "Exit");
479 				}
480 			}
481 		}
482 		else if (_result == MyGUI::MessageBoxStyle::No)
483 		{
484 			StateManager::getInstance().stateEvent(this, "Exit");
485 		}
486 	}
487 
checkCommand()488 	bool EditorState::checkCommand()
489 	{
490 		if (DialogManager::getInstance().getAnyDialog())
491 			return false;
492 
493 		if (MessageBoxManager::getInstance().hasAny())
494 			return false;
495 
496 		if (!StateManager::getInstance().getStateActivate(this))
497 			return false;
498 
499 		return true;
500 	}
501 
notifyChanges(bool _changes)502 	void EditorState::notifyChanges(bool _changes)
503 	{
504 		updateCaption();
505 	}
506 
notifyEndDialogCodeGenerator(Dialog * _dialog,bool _result)507 	void EditorState::notifyEndDialogCodeGenerator(Dialog* _dialog, bool _result)
508 	{
509 		mCodeGenerator->endModal();
510 		if (_result)
511 			mCodeGenerator->saveTemplate();
512 	}
513 
pauseState()514 	void EditorState::pauseState()
515 	{
516 		mMainPaneControl->setVisible(false);
517 	}
518 
resumeState()519 	void EditorState::resumeState()
520 	{
521 		mMainPaneControl->setVisible(true);
522 	}
523 
setFileName(const MyGUI::UString & _fileName)524 	void EditorState::setFileName(const MyGUI::UString& _fileName)
525 	{
526 		mFileName = _fileName;
527 		addUserTag("CurrentFileName", convertProjectName(mFileName));
528 	}
529 
convertProjectName(const MyGUI::UString & _fileName)530 	MyGUI::UString EditorState::convertProjectName(const MyGUI::UString& _fileName)
531 	{
532 		size_t pos = mFileName.find_last_of("\\/");
533 		MyGUI::UString shortName = pos == MyGUI::UString::npos ? mFileName : mFileName.substr(pos + 1);
534 		addUserTag("ResourceName", shortName);
535 
536 		size_t index = _fileName.find("|");
537 		if (index == MyGUI::UString::npos)
538 			return _fileName;
539 
540 		MyGUI::UString fileName = _fileName.substr(0, index);
541 		MyGUI::UString itemIndexName = _fileName.substr(index + 1);
542 		size_t itemIndex = MyGUI::utility::parseValue<size_t>(itemIndexName);
543 
544 		MyGUI::xml::Document doc;
545 		if (!doc.open(fileName))
546 			return _fileName;
547 
548 		MyGUI::xml::ElementPtr root = doc.getRoot();
549 		if ((nullptr == root) || (root->getName() != "MyGUI"))
550 			return _fileName;
551 
552 		if (root->findAttribute("type") == "Resource")
553 		{
554 			// берем детей и крутимся
555 			MyGUI::xml::ElementEnumerator element = root->getElementEnumerator();
556 			while (element.next("Resource"))
557 			{
558 				if (element->findAttribute("type") == "ResourceLayout")
559 				{
560 					if (itemIndex == 0)
561 					{
562 						// поменять на теги
563 						std::string resourceName = element->findAttribute("name");
564 						addUserTag("ResourceName", resourceName);
565 						return MyGUI::utility::toString(fileName, " [", resourceName, "]");
566 					}
567 					else
568 					{
569 						itemIndex --;
570 					}
571 				}
572 			}
573 		}
574 
575 		return _fileName;
576 	}
577 
isProjectFile(const MyGUI::UString & _fileName)578 	bool EditorState::isProjectFile(const MyGUI::UString& _fileName)
579 	{
580 		size_t index = _fileName.find("|");
581 		return (index != MyGUI::UString::npos);
582 	}
583 
command_UpdateResources(const MyGUI::UString & _commandName,bool & _result)584 	void EditorState::command_UpdateResources(const MyGUI::UString& _commandName, bool& _result)
585 	{
586 		if (!checkCommand())
587 			return;
588 
589 		SettingsManager::VectorString resources = SettingsManager::getInstance().getValueList("Resources/UpdateResource.List");
590 		if (resources.empty())
591 			return;
592 
593 		for (SettingsManager::VectorString::iterator resource = resources.begin(); resource != resources.end(); ++resource)
594 			MyGUI::ResourceManager::getInstance().load(*resource);
595 
596 		MyGUI::xml::Document* savedDoc = EditorWidgets::getInstance().savexmlDocument();
597 		EditorWidgets::getInstance().clear();
598 		EditorWidgets::getInstance().loadxmlDocument(savedDoc);
599 		delete savedDoc;
600 		WidgetSelectorManager::getInstance().setSelectedWidget(nullptr);
601 
602 		_result = true;
603 	}
604 
605 }
606