Preferences.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //
  2. // Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. class Preferences {
  23. private static Ctor = (() => {
  24. new Preferences();
  25. })();
  26. private fileSystem: Atomic.FileSystem;
  27. private static instance: Preferences;
  28. private _prefs: PreferencesFormat;
  29. private cachedProjectPreferences: Object = null;
  30. constructor() {
  31. this.fileSystem = Atomic.getFileSystem();
  32. Preferences.instance = this;
  33. }
  34. registerRecentProject(path: string): void {
  35. var index = this._prefs.recentProjects.indexOf(path);
  36. if (index >= 0) {
  37. this._prefs.recentProjects.splice(index, 1);
  38. }
  39. this._prefs.recentProjects.unshift(path);
  40. this.updateRecentProjects(true);
  41. }
  42. updateRecentProjects(write: boolean = false): void {
  43. for (var i = 0; i < this._prefs.recentProjects.length; i++) {
  44. var path = this._prefs.recentProjects[i];
  45. if (!this.fileSystem.exists(path)) {
  46. this._prefs.recentProjects.splice(i, 1);
  47. write = true;
  48. }
  49. }
  50. if (write)
  51. this.write();
  52. }
  53. deleteRecentProjects(): void {
  54. this._prefs.recentProjects.length = 0;
  55. this.write();
  56. }
  57. getPreferencesFullPath(): string {
  58. var filePath = this.fileSystem.getAppPreferencesDir("AtomicEditor", "Preferences");
  59. filePath += "prefs.json";
  60. return filePath;
  61. }
  62. read(): void {
  63. var filePath = this.getPreferencesFullPath();
  64. var jsonFile;
  65. //check if file doesn't exist, create default json
  66. if (!this.fileSystem.fileExists(filePath)) {
  67. this.useDefaultConfig();
  68. this.write();
  69. return;
  70. }
  71. //Read file
  72. jsonFile = new Atomic.File(filePath, Atomic.FILE_READ);
  73. var prefs = null;
  74. try {
  75. if (jsonFile.isOpen())
  76. prefs = <PreferencesFormat>JSON.parse(jsonFile.readText());
  77. } catch (e) {
  78. prefs = null;
  79. }
  80. if (prefs && (!prefs.editorWindow || !prefs.playerWindow || !prefs.recentProjects)) {
  81. prefs = null;
  82. }
  83. if (prefs) {
  84. this._prefs = prefs;
  85. } else {
  86. console.log("Editor preference file invalid, regenerating default configuration");
  87. this.useDefaultConfig();
  88. this.write();
  89. }
  90. }
  91. write(): boolean {
  92. var filePath = this.getPreferencesFullPath();
  93. var jsonFile = new Atomic.File(filePath, Atomic.FILE_WRITE);
  94. if (!jsonFile.isOpen()) return false;
  95. jsonFile.writeString(JSON.stringify(this._prefs, null, 2));
  96. }
  97. saveEditorWindowData(windowData: WindowData) {
  98. this._prefs.editorWindow = windowData;
  99. this.write();
  100. }
  101. savePlayerWindowData(windowData: WindowData) {
  102. this._prefs.playerWindow = windowData;
  103. this.write();
  104. }
  105. useDefaultConfig(): void {
  106. this._prefs = new PreferencesFormat();
  107. }
  108. get editorWindow(): WindowData {
  109. return this._prefs.editorWindow;
  110. }
  111. get playerWindow(): WindowData {
  112. return this._prefs.playerWindow;
  113. }
  114. get recentProjects(): string[] {
  115. return this._prefs.recentProjects;
  116. }
  117. static getInstance(): Preferences {
  118. return Preferences.instance;
  119. }
  120. /**
  121. * Return a preference value or the provided default from the user settings file located in the project
  122. * @param {string} settingsGroup name of the group these settings should fall under
  123. * @param {string} preferenceName name of the preference to retrieve
  124. * @param {number | boolean | string} defaultValue value to return if pref doesn't exist
  125. * @return {number|boolean|string}
  126. */
  127. getUserPreference(settingsGroup: string, preferenceName: string, defaultValue?: number): number;
  128. getUserPreference(settingsGroup: string, preferenceName: string, defaultValue?: string): string;
  129. getUserPreference(settingsGroup: string, preferenceName: string, defaultValue?: boolean): boolean;
  130. getUserPreference(settingsGroup: string, preferenceName: string, defaultValue?: any): any {
  131. // Cache the settings so we don't keep going out to the file
  132. if (this.cachedProjectPreferences == null) {
  133. const prefsFileLoc = ToolCore.toolSystem.project.userPrefsFullPath;
  134. if (Atomic.fileSystem.fileExists(prefsFileLoc)) {
  135. let prefsFile = new Atomic.File(prefsFileLoc, Atomic.FILE_READ);
  136. try {
  137. let prefs = JSON.parse(prefsFile.readText());
  138. this.cachedProjectPreferences = prefs;
  139. } finally {
  140. prefsFile.close();
  141. }
  142. }
  143. }
  144. if (this.cachedProjectPreferences && this.cachedProjectPreferences[settingsGroup]) {
  145. return this.cachedProjectPreferences[settingsGroup][preferenceName] || defaultValue;
  146. }
  147. // if all else fails
  148. return defaultValue;
  149. }
  150. /**
  151. * Sets a user preference value in the user settings file located in the project
  152. * @param {string} settingsGroup name of the group the preference lives under
  153. * @param {string} preferenceName name of the preference to set
  154. * @param {number | boolean | string} value value to set
  155. */
  156. setUserPreference(settingsGroup: string, preferenceName: string, value: number | boolean | string) {
  157. const prefsFileLoc = ToolCore.toolSystem.project.userPrefsFullPath;
  158. let prefs = {};
  159. if (Atomic.fileSystem.fileExists(prefsFileLoc)) {
  160. let prefsFile = new Atomic.File(prefsFileLoc, Atomic.FILE_READ);
  161. try {
  162. prefs = JSON.parse(prefsFile.readText());
  163. } finally {
  164. prefsFile.close();
  165. }
  166. }
  167. prefs[settingsGroup] = prefs[settingsGroup] || {};
  168. prefs[settingsGroup][preferenceName] = value;
  169. let saveFile = new Atomic.File(prefsFileLoc, Atomic.FILE_WRITE);
  170. try {
  171. saveFile.writeString(JSON.stringify(prefs, null, " "));
  172. } finally {
  173. saveFile.flush();
  174. saveFile.close();
  175. }
  176. // Cache the update
  177. this.cachedProjectPreferences = prefs;
  178. }
  179. /**
  180. * Sets a group of user preference values in the user settings file located in the project. Elements in the
  181. * group will merge in with existing group preferences. Use this method if setting a bunch of settings
  182. * at once.
  183. * @param {string} settingsGroup name of the group the preference lives under
  184. * @param {string} groupPreferenceValues an object literal containing all of the preferences for the group.
  185. */
  186. setUserPreferenceGroup(settingsGroup: string, groupPreferenceValues: Object) {
  187. const prefsFileLoc = ToolCore.toolSystem.project.userPrefsFullPath;
  188. let prefs = {};
  189. if (Atomic.fileSystem.fileExists(prefsFileLoc)) {
  190. let prefsFile = new Atomic.File(prefsFileLoc, Atomic.FILE_READ);
  191. try {
  192. prefs = JSON.parse(prefsFile.readText());
  193. } finally {
  194. prefsFile.close();
  195. }
  196. }
  197. prefs[settingsGroup] = prefs[settingsGroup] || {};
  198. for (let preferenceName in groupPreferenceValues) {
  199. prefs[settingsGroup][preferenceName] = groupPreferenceValues[preferenceName];
  200. }
  201. let saveFile = new Atomic.File(prefsFileLoc, Atomic.FILE_WRITE);
  202. try {
  203. saveFile.writeString(JSON.stringify(prefs, null, " "));
  204. } finally {
  205. saveFile.flush();
  206. saveFile.close();
  207. }
  208. // Cache the update
  209. this.cachedProjectPreferences = prefs;
  210. }
  211. }
  212. interface WindowData {
  213. x: number;
  214. y: number;
  215. width: number;
  216. height: number;
  217. monitor: number;
  218. maximized: boolean;
  219. }
  220. class PreferencesFormat {
  221. constructor() {
  222. this.setDefault();
  223. }
  224. setDefault() {
  225. this.recentProjects = [];
  226. this.editorWindow = {
  227. x: 0,
  228. y: 0,
  229. width: 0,
  230. height: 0,
  231. monitor: 0,
  232. maximized: true
  233. };
  234. this.playerWindow = {
  235. x: 0,
  236. y: 0,
  237. width: 0,
  238. height: 0,
  239. monitor: 0,
  240. maximized: false
  241. };
  242. }
  243. recentProjects: string[];
  244. editorWindow: WindowData;
  245. playerWindow: WindowData;
  246. }
  247. export = Preferences;