AEPreferences.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #include <rapidjson/document.h>
  5. #include "rapidjson/prettywriter.h"
  6. #include "rapidjson/filestream.h"
  7. #include <Atomic/Core/Context.h>
  8. #include <Atomic/IO/FileSystem.h>
  9. #include <Atomic/IO/Log.h>
  10. #include <Atomic/IO/File.h>
  11. #include <Atomic/Graphics/Graphics.h>
  12. #include "../EditorMode/AEEditorEvents.h"
  13. #include "AEPreferences.h"
  14. using namespace rapidjson;
  15. namespace AtomicEditor
  16. {
  17. AEPreferences::AEPreferences(Context* context) :
  18. Object(context)
  19. {
  20. context->RegisterSubsystem(this);
  21. SubscribeToEvent(E_EDITORSHUTDOWN, HANDLER(AEPreferences, HandleEditorShutdown));
  22. Read();
  23. }
  24. AEPreferences::~AEPreferences()
  25. {
  26. }
  27. String AEPreferences::GetPreferencesFullPath()
  28. {
  29. FileSystem* fs = GetSubsystem<FileSystem>();
  30. String filepath = fs->GetAppPreferencesDir("AtomicEditor", "Preferences");
  31. filepath += "prefs.json";
  32. return filepath;
  33. }
  34. void AEPreferences::Clear()
  35. {
  36. recentProjects_.Clear();
  37. }
  38. void AEPreferences::Read()
  39. {
  40. rapidjson::Document document;
  41. String filepath = GetPreferencesFullPath();
  42. File jsonFile(context_, filepath);
  43. if (!jsonFile.IsOpen())
  44. return;
  45. String json;
  46. jsonFile.ReadText(json);
  47. if (!json.Length())
  48. return;
  49. if (document.Parse<0>(json.CString()).HasParseError())
  50. {
  51. LOGERRORF("Could not parse JSON data from %s", filepath.CString());
  52. return;
  53. }
  54. Clear();
  55. const Value::Member* recent_files = document.FindMember("recent_files");
  56. if (recent_files && recent_files->value.IsArray())
  57. {
  58. for (Value::ConstValueIterator itr = recent_files->value.Begin(); itr != recent_files->value.End(); itr++)
  59. {
  60. if (!(*itr).IsString())
  61. continue;
  62. String path(itr->GetString());
  63. recentProjects_.Push(path.CString());
  64. }
  65. }
  66. const Value::Member* android_sdk_path = document.FindMember("android_sdk_path");
  67. if (android_sdk_path && android_sdk_path->value.IsString())
  68. androidSDKPath_ = android_sdk_path->value.GetString();
  69. const Value::Member* jdk_root_path = document.FindMember("jdk_root_path");
  70. if (jdk_root_path && jdk_root_path->value.IsString())
  71. jdkRootPath_ = jdk_root_path->value.GetString();
  72. const Value::Member* ant_path = document.FindMember("ant_path");
  73. if (ant_path && ant_path->value.IsString())
  74. antPath_ = ant_path->value.GetString();
  75. UpdateRecentFiles(false);
  76. }
  77. void AEPreferences::Write()
  78. {
  79. String filepath = GetPreferencesFullPath();
  80. FILE* file = fopen(filepath.CString(), "w");
  81. if (!file)
  82. return;
  83. Graphics* graphics = GetSubsystem<Graphics>();
  84. IntVector2 pos(-1, -1);
  85. int width = -1;
  86. int height = -1;
  87. if (graphics && !graphics->GetFullscreen())
  88. {
  89. pos = graphics->GetWindowPosition();
  90. width = graphics->GetWidth();
  91. height = graphics->GetHeight();
  92. }
  93. rapidjson::FileStream s(file);
  94. rapidjson::PrettyWriter<rapidjson::FileStream> writer(s);
  95. writer.StartObject();
  96. // recent files
  97. writer.String("recent_files");
  98. writer.StartArray();
  99. for (unsigned i = 0; i < recentProjects_.Size(); i++)
  100. writer.String(recentProjects_[i].CString());
  101. writer.EndArray();
  102. writer.String("android_sdk_path");
  103. writer.String(androidSDKPath_.CString());
  104. writer.String("jdk_root_path");
  105. writer.String(jdkRootPath_.CString());
  106. writer.String("ant_path");
  107. writer.String(antPath_.CString());
  108. writer.String("window_pos_x");
  109. writer.Int(pos.x_);
  110. writer.String("window_pos_y");
  111. writer.Int(pos.y_);
  112. writer.String("window_width");
  113. writer.Int(width);
  114. writer.String("window_height");
  115. writer.Int(height);
  116. writer.EndObject();
  117. fclose(file);
  118. }
  119. void AEPreferences::UpdateRecentFiles(bool write)
  120. {
  121. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  122. Vector<String> recentProjects;
  123. for (unsigned i = 0; i < recentProjects_.Size(); i++)
  124. {
  125. String path = recentProjects_[i];
  126. if (!fileSystem->FileExists(path))
  127. continue;
  128. recentProjects.Push(path);
  129. if (recentProjects.Size() == 10)
  130. break;
  131. }
  132. recentProjects_ = recentProjects;
  133. if (write)
  134. Write();
  135. }
  136. void AEPreferences::RegisterRecentProject(const String& fullpath)
  137. {
  138. if (recentProjects_.Contains(fullpath))
  139. {
  140. recentProjects_.Remove(fullpath);
  141. }
  142. recentProjects_.Insert(0, fullpath);
  143. UpdateRecentFiles();
  144. }
  145. bool AEPreferences::ReadStartupPrefs(Context *context, StartupPreferences& prefs)
  146. {
  147. FileSystem* fileSystem = context->GetSubsystem<FileSystem>();
  148. String filepath = fileSystem->GetAppPreferencesDir("AtomicEditor", "Preferences");
  149. filepath += "prefs.json";
  150. if (!fileSystem->FileExists(filepath))
  151. return false;
  152. SharedPtr<File> file(new File(context, filepath, FILE_READ));
  153. if (!file->IsOpen())
  154. return false;
  155. String json;
  156. file->ReadText(json);
  157. if (!json.Length())
  158. return false;
  159. rapidjson::Document document;
  160. if (document.Parse<0>(json.CString()).HasParseError())
  161. {
  162. return false;
  163. }
  164. bool success = true;
  165. const Value::Member* imember = document.FindMember("window_pos_x");
  166. if (imember && imember->value.IsInt())
  167. {
  168. prefs.windowPos.x_ = imember->value.GetInt();
  169. }
  170. else
  171. {
  172. success = false;
  173. }
  174. imember = document.FindMember("window_pos_y");
  175. if (imember && imember->value.IsInt())
  176. {
  177. prefs.windowPos.y_ = imember->value.GetInt();
  178. }
  179. else
  180. {
  181. success = false;
  182. }
  183. imember = document.FindMember("window_width");
  184. if (imember && imember->value.IsInt())
  185. {
  186. prefs.windowWidth = imember->value.GetInt();
  187. }
  188. else
  189. {
  190. success = false;
  191. }
  192. imember = document.FindMember("window_height");
  193. if (imember && imember->value.IsInt())
  194. {
  195. prefs.windowHeight = imember->value.GetInt();
  196. }
  197. else
  198. {
  199. success = false;
  200. }
  201. if (prefs.windowHeight < 128 || prefs.windowWidth < 128)
  202. return false;
  203. return success;
  204. }
  205. void AEPreferences::HandleEditorShutdown(StringHash eventType, VariantMap& eventData)
  206. {
  207. context_->RemoveSubsystem(GetType());
  208. }
  209. }