1 module dlangide.workspace.workspacesettings;
2 
3 import dlangui.core.settings;
4 import dlangui.core.i18n;
5 import ddebug.common.debugger;
6 import dlangide.workspace.project;
7 
8 import std.array : empty;
9 import std.algorithm : equal;
10 
11 /// local settings for workspace (not supposed to put under source control)
12 class WorkspaceSettings : SettingsFile {
13 
14     this(string filename) {
15         super(filename);
16     }
17 
18     private Breakpoint[] _breakpoints;
19     private EditorBookmark[] _bookmarks;
20     /// Last opened files in workspace
21     private WorkspaceFile[] _files;
22 
23     private string _startupProjectName;
24     private int _buildConfiguration;
25 
26     @property int buildConfiguration() {
27         return _buildConfiguration;
28     }
29     @property void buildConfiguration(int config) {
30         _setting.setInteger("buildConfiguration", config);
31         _buildConfiguration = config;
32         save();
33     }
34 
35     @property string startupProjectName() {
36         return _startupProjectName;
37     }
38     @property void startupProjectName(string s) {
39         if (!s.equal(_startupProjectName)) {
40             _startupProjectName = s;
41             _setting["startupProject"] = s;
42             save();
43         }
44     }
45 
46     /// Last opened files in workspace    
47     @property WorkspaceFile[] files() {
48         return _files;
49     }
50     
51     /// Last opened files in workspace
52     @property void files(WorkspaceFile[] fs) {
53         _files = fs;
54         // Save to settings file
55         Setting obj = _setting.settingByPath("files", SettingType.ARRAY);
56         obj.clear(SettingType.ARRAY);
57         int index = 0;
58         foreach(file; fs) {
59             Setting single = new Setting();
60             single.setString("file", file.filename);
61             single.setInteger("column", file.column);
62             single.setInteger("row", file.row);
63             obj[index++] = single;
64         }
65     }
66 
67     /// list of expanded workspace explorer items
68     @property string[] expandedItems() {
69         Setting obj = _setting.settingByPath("expandedItems", SettingType.ARRAY);
70         return obj.strArray;
71     }
72 
73     /// update list of expanded workspace explorer items
74     @property void expandedItems(string[] items) {
75         Setting obj = _setting.settingByPath("expandedItems", SettingType.ARRAY);
76         obj.strArray = items;
77     }
78 
79     /// last selected workspace item in workspace explorer
80     @property string selectedWorkspaceItem() {
81         Setting obj = _setting.settingByPath("selectedWorkspaceItem", SettingType.STRING);
82         return obj.str;
83     }
84 
85     /// update last selected workspace item in workspace explorer
86     @property void selectedWorkspaceItem(string item) {
87         Setting obj = _setting.settingByPath("selectedWorkspaceItem", SettingType.STRING);
88         obj.str = item;
89     }
90 
91     /// get all breakpoints for project (for specified source file only, if specified)
92     Breakpoint[] getProjectBreakpoints(string projectName, string projectFilePath) {
93         Breakpoint[] res;
94         for (int i = cast(int)_breakpoints.length - 1; i >= 0; i--) {
95             Breakpoint bp = _breakpoints[i];
96             if (!bp.projectName.equal(projectName))
97                 continue;
98             if (!projectFilePath.empty && !bp.projectFilePath.equal(projectFilePath))
99                 continue;
100             res ~= bp;
101         }
102         return res;
103     }
104 
105     /// get all breakpoints for project (for specified source file only, if specified)
106     void setProjectBreakpoints(string projectName, string projectFilePath, Breakpoint[] bps) {
107         bool changed = false;
108         for (int i = cast(int)_breakpoints.length - 1; i >= 0; i--) {
109             Breakpoint bp = _breakpoints[i];
110             if (!bp.projectName.equal(projectName))
111                 continue;
112             if (!projectFilePath.empty && !bp.projectFilePath.equal(projectFilePath))
113                 continue;
114             for (auto j = i; j < _breakpoints.length - 1; j++)
115                 _breakpoints[j] = _breakpoints[j + 1];
116             _breakpoints.length--;
117             changed = true;
118         }
119         if (bps.length) {
120             changed = true;
121             foreach(bp; bps)
122                 _breakpoints ~= bp;
123         }
124         if (changed) {
125             setBreakpoints(_breakpoints);
126         }
127     }
128 
129     void setBreakpoints(Breakpoint[] bps) {
130         Setting obj = _setting.settingByPath("breakpoints", SettingType.ARRAY);
131         obj.clear(SettingType.ARRAY);
132         int index = 0;
133         foreach(bp; bps) {
134             Setting bpObj = new Setting();
135             bpObj.setInteger("id", bp.id);
136             bpObj.setString("file", bp.file);
137             bpObj.setInteger("line", bp.line);
138             bpObj.setBoolean("enabled", bp.enabled);
139             bpObj.setString("projectName", bp.projectName);
140             bpObj.setString("projectFilePath", bp.projectFilePath);
141             obj[index++] = bpObj;
142         }
143         _breakpoints = bps;
144         //save();
145     }
146 
147     /// get all bookmarks for project (for specified source file only, if specified)
148     EditorBookmark[] getProjectBookmarks(string projectName, string projectFilePath) {
149         EditorBookmark[] res;
150         for (int i = cast(int)_bookmarks.length - 1; i >= 0; i--) {
151             EditorBookmark bp = _bookmarks[i];
152             if (!bp.projectName.equal(projectName))
153                 continue;
154             if (!projectFilePath.empty && !bp.projectFilePath.equal(projectFilePath))
155                 continue;
156             res ~= bp;
157         }
158         return res;
159     }
160 
161     /// get all bookmarks for project (for specified source file only, if specified)
162     void setProjectBookmarks(string projectName, string projectFilePath, EditorBookmark[] bps) {
163         bool changed = false;
164         for (int i = cast(int)_bookmarks.length - 1; i >= 0; i--) {
165             EditorBookmark bp = _bookmarks[i];
166             if (!bp.projectName.equal(projectName))
167                 continue;
168             if (!projectFilePath.empty && !bp.projectFilePath.equal(projectFilePath))
169                 continue;
170             for (auto j = i; j < _bookmarks.length - 1; j++)
171                 _bookmarks[j] = _bookmarks[j + 1];
172             _bookmarks.length--;
173             changed = true;
174         }
175         if (bps.length) {
176             changed = true;
177             foreach(bp; bps)
178                 _bookmarks ~= bp;
179         }
180         if (changed) {
181             setBookmarks(_bookmarks);
182         }
183     }
184 
185     void setBookmarks(EditorBookmark[] bps) {
186         Setting obj = _setting.settingByPath("bookmarks", SettingType.ARRAY);
187         obj.clear(SettingType.ARRAY);
188         int index = 0;
189         foreach(bp; bps) {
190             Setting bpObj = new Setting();
191             bpObj.setString("file", bp.file);
192             bpObj.setInteger("line", bp.line);
193             bpObj.setString("projectName", bp.projectName);
194             bpObj.setString("projectFilePath", bp.projectFilePath);
195             obj[index++] = bpObj;
196         }
197         _bookmarks = bps;
198         //save();
199     }
200 
201     Breakpoint[] getBreakpoints() {
202         return _breakpoints;
203     }
204 
205     EditorBookmark[] getBookmarks() {
206         return _bookmarks;
207     }
208 
209     /// override to do something after loading - e.g. set defaults
210     override void afterLoad() {
211         _startupProjectName = _setting.getString("startupProject");
212         // Loading breakpoints
213         Setting obj = _setting.settingByPath("breakpoints", SettingType.ARRAY);
214         _breakpoints = null;
215         int maxBreakpointId = 0;
216         for (int i = 0; i < obj.length; i++) {
217             Breakpoint bp = new Breakpoint();
218             Setting item = obj[i];
219             bp.id = cast(int)item.getInteger("id");
220             bp.file = item.getString("file");
221             bp.projectName = item.getString("projectName");
222             bp.projectFilePath = item.getString("projectFilePath");
223             bp.line = cast(int)item.getInteger("line");
224             bp.enabled = item.getBoolean("enabled");
225             if (bp.id > maxBreakpointId)
226                 maxBreakpointId = bp.id;
227             _breakpoints ~= bp;
228         }
229         _nextBreakpointId = maxBreakpointId + 1;
230         // Loading bookmarks
231         obj = _setting.settingByPath("bookmarks", SettingType.ARRAY);
232         _bookmarks = null;
233         for (int i = 0; i < obj.length; i++) {
234             EditorBookmark bp = new EditorBookmark();
235             Setting item = obj[i];
236             bp.file = item.getString("file");
237             bp.projectName = item.getString("projectName");
238             bp.projectFilePath = item.getString("projectFilePath");
239             bp.line = cast(int)item.getInteger("line");
240             _bookmarks ~= bp;
241         }
242         // Loading files
243         _files = null;
244         obj = _setting.settingByPath("files", SettingType.ARRAY);
245         for (int i = 0; i < obj.length; i++) {
246             Setting item = obj[i];
247             WorkspaceFile file = new WorkspaceFile;
248             file.filename(item.getString("file"));
249             file.column(cast(int)item.getInteger("column"));
250             file.row(cast(int)item.getInteger("row"));
251             _files ~= file;
252         }
253         _buildConfiguration = cast(int)_setting.getInteger("buildConfiguration", 0);
254         if (_buildConfiguration < 0)
255             _buildConfiguration = 0;
256         if (_buildConfiguration > 2)
257             _buildConfiguration = 2;
258     }
259 
260     override void updateDefaults() {
261     }
262 
263 }
264 
265 /// Description for workspace file
266 class WorkspaceFile {
267     /// File name with full path
268     private string _filename;
269     /// Cursor position column
270     private int _column;
271     /// Cursor position row
272     private int _row;
273     
274     @property string filename() {
275         return _filename;
276     }
277     @property void filename(string _fn) {
278         this._filename = _fn;
279     }
280     
281     @property int column() {
282         return _column;
283     }
284     @property void column(int col) {
285         _column = col;
286     }
287      
288     @property int row() {
289         return _row;
290     }
291     @property void row(int r) {
292         _row = r;
293     }
294 }