AEPreferences.cpp 6.4 KB

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