AEPreferences.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. void AEPreferences::DeleteRecentProjects()
  146. {
  147. if (recentProjects_.Size() <= 0) return;
  148. recentProjects_.Clear();
  149. UpdateRecentFiles(true);
  150. }
  151. bool AEPreferences::ReadStartupPrefs(Context *context, StartupPreferences& prefs)
  152. {
  153. FileSystem* fileSystem = context->GetSubsystem<FileSystem>();
  154. String filepath = fileSystem->GetAppPreferencesDir("AtomicEditor", "Preferences");
  155. filepath += "prefs.json";
  156. if (!fileSystem->FileExists(filepath))
  157. return false;
  158. SharedPtr<File> file(new File(context, filepath, FILE_READ));
  159. if (!file->IsOpen())
  160. return false;
  161. String json;
  162. file->ReadText(json);
  163. if (!json.Length())
  164. return false;
  165. rapidjson::Document document;
  166. if (document.Parse<0>(json.CString()).HasParseError())
  167. {
  168. return false;
  169. }
  170. bool success = true;
  171. const Value::Member* imember = document.FindMember("window_pos_x");
  172. if (imember && imember->value.IsInt())
  173. {
  174. prefs.windowPos.x_ = imember->value.GetInt();
  175. }
  176. else
  177. {
  178. success = false;
  179. }
  180. imember = document.FindMember("window_pos_y");
  181. if (imember && imember->value.IsInt())
  182. {
  183. prefs.windowPos.y_ = imember->value.GetInt();
  184. }
  185. else
  186. {
  187. success = false;
  188. }
  189. imember = document.FindMember("window_width");
  190. if (imember && imember->value.IsInt())
  191. {
  192. prefs.windowWidth = imember->value.GetInt();
  193. }
  194. else
  195. {
  196. success = false;
  197. }
  198. imember = document.FindMember("window_height");
  199. if (imember && imember->value.IsInt())
  200. {
  201. prefs.windowHeight = imember->value.GetInt();
  202. }
  203. else
  204. {
  205. success = false;
  206. }
  207. if (prefs.windowHeight < 128 || prefs.windowWidth < 128)
  208. return false;
  209. return success;
  210. }
  211. void AEPreferences::HandleEditorShutdown(StringHash eventType, VariantMap& eventData)
  212. {
  213. context_->RemoveSubsystem(GetType());
  214. }
  215. }