1 module dlangide.workspace.idesettings;
2 
3 import dlangui.core.settings;
4 import dlangui.core.i18n;
5 import dlangui.graphics.fonts;
6 
7 import std.algorithm : equal;
8 
9 const AVAILABLE_THEMES = ["ide_theme_default", "ide_theme_dark"];
10 const AVAILABLE_LANGUAGES = ["en", "ru", "es", "cs"];
11 
12 class IDESettings : SettingsFile {
13 
14     this(string filename) {
15         super(filename);
16     }
17 
18     override void updateDefaults() {
19         Setting ed = editorSettings();
20         ed.setBooleanDef("useSpacesForTabs", true);
21         ed.setIntegerDef("tabSize", 4);
22         ed.setBooleanDef("smartIndents", true);
23         ed.setBooleanDef("smartIndentsAfterPaste", true);
24         ed.setBooleanDef("showWhiteSpaceMarks", true);
25         ed.setBooleanDef("showTabPositionMarks", true);
26         ed.setStringDef("fontFace", "Default");
27         ed.setIntegerDef("fontSize", 11);
28         Setting ui = uiSettings();
29         ui.setStringDef("theme", "ide_theme_default");
30         ui.setStringDef("language", "en");
31         ui.setIntegerDef("hintingMode", 1);
32         ui.setIntegerDef("minAntialiasedFontSize", 0);
33         ui.setFloatingDef("fontGamma", 0.8);
34         ui.setStringDef("uiFontFace", "Default");
35         ui.setIntegerDef("uiFontSize", 11);
36         ui.setBooleanDef("showToolbar", true);
37         ui.setBooleanDef("showStatusbar", true);
38         ui.setIntegerDef("screenDpiOverride", 0);
39         version (Windows) {
40             debuggerSettings.setStringDef("executable", "mago-mi");
41         } else {
42             debuggerSettings.setStringDef("executable", "gdb");
43         }
44         terminalSettings.setStringDef("executable", "xterm");
45         dubSettings.setStringDef("executable", "dub");
46         dubSettings.setStringDef("additional_params", "");
47         rdmdSettings.setStringDef("executable", "rdmd");
48         rdmdSettings.setStringDef("additional_params", "");
49         dmdToolchainSettings.setStringDef("executable", "dmd");
50         dmdToolchainSettings.setStringDef("dub_additional_params", "");
51         ldcToolchainSettings.setStringDef("executable", "ldc2");
52         ldcToolchainSettings.setStringDef("dub_additional_params", "");
53         ldmdToolchainSettings.setStringDef("executable", "ldmd2");
54         ldmdToolchainSettings.setStringDef("dub_additional_params", "");
55         gdcToolchainSettings.setStringDef("executable", "gdc");
56         gdcToolchainSettings.setStringDef("dub_additional_params", "");
57     }
58 
59     /// override to do something after loading - e.g. set defaults
60     override void afterLoad() {
61     }
62     
63     @property Setting editorSettings() {
64         Setting res = _setting.objectByPath("editors/textEditor", true);
65         return res;
66     }
67 
68     @property Setting uiSettings() {
69         Setting res = _setting.objectByPath("interface", true);
70         return res;
71     }
72 
73     @property Setting debuggerSettings() {
74         Setting res = _setting.objectByPath("dlang/debugger", true);
75         return res;
76     }
77 
78     @property Setting terminalSettings() {
79         Setting res = _setting.objectByPath("dlang/terminal", true);
80         return res;
81     }
82 
83     @property Setting dubSettings() {
84         Setting res = _setting.objectByPath("dlang/dub", true);
85         return res;
86     }
87 
88     @property Setting rdmdSettings() {
89         Setting res = _setting.objectByPath("dlang/rdmd", true);
90         return res;
91     }
92 
93     @property Setting dmdToolchainSettings() {
94         Setting res = _setting.objectByPath("dlang/toolchains/dmd", true);
95         return res;
96     }
97 
98     @property Setting ldcToolchainSettings() {
99         Setting res = _setting.objectByPath("dlang/toolchains/ldc", true);
100         return res;
101     }
102 
103     @property Setting ldmdToolchainSettings() {
104         Setting res = _setting.objectByPath("dlang/toolchains/ldmd", true);
105         return res;
106     }
107 
108     @property Setting gdcToolchainSettings() {
109         Setting res = _setting.objectByPath("dlang/toolchains/gdc", true);
110         return res;
111     }
112 
113     /// theme
114     @property string uiTheme() {
115         return limitString(uiSettings.getString("theme", "ide_theme_default"), AVAILABLE_THEMES);
116     }
117     /// theme
118     @property IDESettings uiTheme(string v) {
119         uiSettings.setString("theme", limitString(v, AVAILABLE_THEMES));
120         return this;
121     }
122 
123     /// language
124     @property string uiLanguage() {
125         return limitString(uiSettings.getString("language", "en"), AVAILABLE_LANGUAGES);
126     }
127     /// language
128     @property IDESettings uiLanguage(string v) {
129         uiSettings.setString("language", limitString(v, AVAILABLE_LANGUAGES));
130         return this;
131     }
132 
133     /// to allow overriding detected screen DPI
134     @property int screenDpiOverride() {
135         return cast(int)uiSettings.getInteger("screenDpiOverride", 0);
136     }
137 
138     /// to allow overriding detected screen DPI
139     @property IDESettings screenDpiOverride(int newDpi) {
140         uiSettings.setInteger("screenDpiOverride", newDpi);
141         return this;
142     }
143 
144     /// UI font face
145     @property string uiFontFace() {
146         return uiSettings.getString("uiFontFace", "Default");
147     }
148 
149     /// UI font size
150     @property int uiFontSize() {
151         return pointsToPixels(cast(int)uiSettings.getInteger("uiFontSize", 10));
152     }
153 
154     /// text editor setting, true if need to insert spaces instead of tabs
155     @property bool useSpacesForTabs() {
156         return editorSettings.getBoolean("useSpacesForTabs", true);
157     }
158     /// text editor setting, true if need to insert spaces instead of tabs
159     @property IDESettings useSpacesForTabs(bool v) {
160         editorSettings.setBoolean("useSpacesForTabs", v);
161         return this;
162     }
163 
164     /// text editor setting, true if need to insert spaces instead of tabs
165     @property int tabSize() {
166         return limitInt(editorSettings.getInteger("tabSize", 4), 1, 16);
167     }
168     /// text editor setting, true if need to insert spaces instead of tabs
169     @property IDESettings tabSize(int v) {
170         editorSettings.setInteger("tabSize", limitInt(v, 1, 16));
171         return this;
172     }
173 
174     /// true if smart indents are enabled
175     @property bool smartIndents() { return editorSettings.getBoolean("smartIndents", true); }
176     /// set smart indents enabled flag
177     @property IDESettings smartIndents(bool enabled) { editorSettings.setBoolean("smartIndents", enabled); return this; }
178 
179     /// true if white space marks are enabled
180     @property bool showWhiteSpaceMarks() { return editorSettings.getBoolean("showWhiteSpaceMarks", true); }
181     /// set white space marks enabled flag
182     @property IDESettings showWhiteSpaceMarks(bool enabled) { editorSettings.setBoolean("showWhiteSpaceMarks", enabled); return this; }
183 
184     /// true if tab position marks are enabled
185     @property bool showTabPositionMarks() { return editorSettings.getBoolean("showTabPositionMarks", true); }
186     /// set tab position marks enabled flag
187     @property IDESettings showTabPositionMarks(bool enabled) { editorSettings.setBoolean("showTabPositionMarks", enabled); return this; }
188 
189     /// when true, toolbar is visible
190     @property bool showToolbar() { return uiSettings.getBoolean("showToolbar", true); }
191     /// when true, toolbar is visible
192     @property IDESettings showToolbar(bool enabled) { uiSettings.setBoolean("showToolbar", enabled); return this; }
193 
194     /// when true, statusbar is visible
195     @property bool showStatusbar() { return uiSettings.getBoolean("showStatusbar", true); }
196     /// when true, statusbar is visible
197     @property IDESettings showStatusbar(bool enabled) { uiSettings.setBoolean("showStatusbar", enabled); return this; }
198 
199     /// string value of font face in text editors
200     @property string editorFontFace() { return editorSettings.getString("fontFace", "Default"); }
201     /// int value of font size in text editors
202     @property int editorFontSize() { return cast(int)editorSettings.getInteger("fontSize", 11); }
203 
204     /// true if smart indents are enabled
205     @property bool smartIndentsAfterPaste() { return editorSettings.getBoolean("smartIndentsAfterPaste", true); }
206     /// set smart indents enabled flag
207     @property IDESettings smartIndentsAfterPaste(bool enabled) { editorSettings.setBoolean("smartIndentsAfterPaste", enabled); return this; }
208 
209     @property double fontGamma() {
210         double gamma = uiSettings.getFloating("fontGamma", 1.0);
211         if (gamma >= 0.5 && gamma <= 2.0)
212             return gamma;
213         return 1.0;
214     }
215 
216     @property HintingMode hintingMode() {
217         long mode = uiSettings.getInteger("hintingMode", HintingMode.Normal);
218         if (mode >= HintingMode.Normal && mode <= HintingMode.Light)
219             return cast(HintingMode)mode;
220         return HintingMode.Normal;
221     }
222 
223     @property int minAntialiasedFontSize() {
224         long sz = uiSettings.getInteger("minAntialiasedFontSize", 0);
225         if (sz >= 0)
226             return cast(int)sz;
227         return 0;
228     }
229 
230     @property string debuggerExecutable() {
231         version (Windows) {
232             return debuggerSettings.getString("executable", "mago-mi");
233         } else {
234             return debuggerSettings.getString("executable", "gdb");
235         }
236     }
237 
238     @property string terminalExecutable() {
239         return terminalSettings.getString("executable", "xterm");
240     }
241 
242     @property string dubExecutable() {
243         return dubSettings.getString("executable", "dub");
244     }
245 
246     @property string dubAdditionalParams() {
247         return dubSettings.getString("additional_params", "");
248     }
249 
250     @property string rdmdExecutable() {
251         return rdmdSettings.getString("executable", "rdmd");
252     }
253 
254     @property string rdmdAdditionalParams() {
255         return rdmdSettings.getString("additional_params", "");
256     }
257 
258     string getToolchainCompilerExecutable(string toolchainName) {
259         if (toolchainName.equal("dmd"))
260             return dmdToolchainSettings.getString("executable", "dmd");
261         if (toolchainName.equal("gdc"))
262             return gdcToolchainSettings.getString("executable", "gdc");
263         if (toolchainName.equal("ldc"))
264             return ldcToolchainSettings.getString("executable", "ldc2");
265         if (toolchainName.equal("ldmd"))
266             return ldmdToolchainSettings.getString("executable", "ldmd2");
267         return null;
268     }
269 
270     string getToolchainAdditionalDubParams(string toolchainName) {
271         if (toolchainName.equal("dmd"))
272             return dmdToolchainSettings.getString("dub_additional_params", "");
273         if (toolchainName.equal("gdc"))
274             return gdcToolchainSettings.getString("dub_additional_params", "");
275         if (toolchainName.equal("ldc"))
276             return ldcToolchainSettings.getString("dub_additional_params", "");
277         if (toolchainName.equal("ldmd"))
278             return ldmdToolchainSettings.getString("dub_additional_params", "");
279         return null;
280     }
281 
282     /// get recent path for category name, returns null if not found
283     @property string getRecentPath(string category = "FILE_OPEN_DLG_PATH") {
284         Setting obj = _setting.objectByPath("pathHistory", true);
285         return obj.getString(category, null);
286     }
287 
288     /// set recent path for category name
289     @property void setRecentPath(string value, string category = "FILE_OPEN_DLG_PATH") {
290         Setting obj = _setting.objectByPath("pathHistory", true);
291         obj.setString(category, value);
292         save();
293     }
294 
295     @property string[] recentWorkspaces() {
296         import std.file;
297         Setting obj = _setting.objectByPath("history", true);
298         string[] list = obj.getStringArray("recentWorkspaces");
299         string[] res;
300         foreach(fn; list) {
301             if (exists(fn) && isFile(fn))
302                 res ~= fn;
303         }
304         return res;
305     }
306 
307     void updateRecentWorkspace(string ws) {
308         import std.file;
309         string[] list;
310         list ~= ws;
311         string[] existing = recentWorkspaces;
312         foreach(fn; existing) {
313             if (exists(fn) && isFile(fn) && !ws.equal(fn))
314                 list ~= fn;
315         }
316         Setting obj = _setting.objectByPath("history", true);
317         obj["recentWorkspaces"] = list;
318         save();
319     }
320     
321     @property bool autoOpenLastProject() {
322         Setting obj =_setting.objectByPath("common", true);
323         return obj.getBoolean("autoOpenLastProject", false);
324     }
325 
326     @property void autoOpenLastProject(bool value) {
327         Setting obj =_setting.objectByPath("common", true);
328         obj.setBoolean("autoOpenLastProject", value);
329     }
330 
331     /// for saving window state, position, and other UI states
332     @property Setting uiState() {
333         return _setting.objectByPath("uiState", true);
334     }
335 }
336