ide/dialogs/FontPicker: Tweak for better font row height
[sdk] / extras / gui / GuiConfigData.ec
1 #ifdef ECERE_STATIC
2 public import static "ecere"
3 #else
4 public import "ecere"
5 #endif
6
7 class GuiConfigData
8 {
9    virtual bool onSave();
10    virtual void onModified()
11    {
12       modified = true;
13    }
14
15 public:
16
17    Map<String, GuiDataWindow> windows;
18    Map<String, GuiDataPaneSplitter> paneSplitters;
19
20    void saveWindowInit(const char * configId, Window window)
21    {
22       applyWindowConfig(configId, window);
23       {
24          bool isNew = false;
25          GuiDataWindow guiData = insertWindowConfig(configId, true, &isNew);
26          if(guiData && isNew)
27          {
28             if(window.state != minimized)
29                guiData.state = window.state;
30             recordWindowPosition(guiData, window);
31             recordWindowSize(guiData, window);
32             onModified();
33             onSave();
34          }
35       }
36    }
37
38    void saveWindowState(const char * configId, Window window, WindowState state)
39    {
40       GuiDataWindow guiData = insertWindowConfig(configId, true, null);
41       if(guiData)
42       {
43          if(state != minimized)
44             guiData.state = state;
45          onModified();
46       }
47    }
48
49    void saveWindowPosition(const char * configId, Window window, Point position, Size size)
50    {
51       GuiDataWindow guiData = insertWindowConfig(configId, true, null);
52       if(guiData && window.state == normal)
53       {
54          recordWindowPosition(guiData, window);
55          recordWindowSize(guiData, window);
56          onModified();
57       }
58    }
59
60    void saveWindowSize(const char * configId, Window window, Size size)
61    {
62       GuiDataWindow guiData = insertWindowConfig(configId, true, null);
63       if(guiData && window.state == normal)
64       {
65          recordWindowSize(guiData, window);
66          onModified();
67       }
68    }
69
70    void saveWindowClose(const char * configId)
71    {
72       GuiDataWindow guiData = getWindowConfig(configId);
73       if(guiData)
74          guiData.saving = false;
75       if(modified)
76          onSave();
77    }
78
79    void savePaneSplitterSize(const char * configId, double scaleSplit)
80    {
81       GuiDataPaneSplitter guiData = null;
82       if(!paneSplitters)
83          paneSplitters = { };
84       if(!(guiData = paneSplitters[configId]))
85          paneSplitters[configId] = guiData = { };
86       if(!guiData.loading)
87       {
88          guiData.scaleSplit = scaleSplit;
89          onModified();
90       }
91    }
92
93 private:
94    bool modified;
95
96    ~GuiConfigData()
97    {
98       timer.Stop();
99
100       if(windows)
101       {
102          windows.Free();
103          delete windows;
104       }
105       if(paneSplitters)
106       {
107          paneSplitters.Free();
108          delete paneSplitters;
109       }
110    }
111
112    Timer timer
113    {
114       userData = this, delay = 2.5;
115       bool DelayExpired()
116       {
117          if(modified)
118          {
119             if(onSave())
120                modified = false;
121          }
122          return true;
123       }
124    };
125
126    GuiDataWindow getWindowConfig(const char * configId)
127    {
128       GuiDataWindow guiData = null;
129       if(windows)
130          guiData = windows[configId];
131       return guiData;
132    }
133
134    GuiDataWindow insertWindowConfig(const char * configId, bool startSaving, bool *isNew)
135    {
136       GuiDataWindow guiData = null;
137       if(startSaving)
138       {
139          if(!windows)
140             windows = { };
141          if(!(guiData = windows[configId]))
142          {
143             windows[configId] = guiData = { };
144             if(isNew)
145                *isNew = true;
146          }
147          guiData.saving = true;
148       }
149       else
150          guiData = getWindowConfig(configId);
151       if(/*!startSaving && */guiData && (!guiData.saving || guiData.loading))
152          guiData = null;
153       return guiData;
154    }
155
156    void recordWindowPosition(GuiDataWindow guiData, Window window)
157    {
158       guiData.position = window.position;
159    }
160
161    void recordWindowSize(GuiDataWindow guiData, Window window)
162    {
163       guiData.size = window.size;
164    }
165
166    void applyWindowConfig(const char * configId, Window window)
167    {
168       GuiDataWindow guiData = getWindowConfig(configId);
169       if(guiData)
170       {
171          guiData.loading = true;
172          window.state = normal;
173          applyWindowPosition(window, guiData);
174          applyWindowSize(window, guiData);
175          window.Move(guiData.position.x, guiData.position.y, guiData.size.w, guiData.size.h);
176          window.state = guiData.state;
177          guiData.loading = false;
178       }
179    }
180
181    void applyWindowPosition(Window window, GuiDataWindow guiData)
182    {
183       window.position = guiData.position;
184    }
185
186    void applyWindowSize(Window window, GuiDataWindow guiData)
187    {
188       window.size = guiData.size;
189    }
190
191    void applyPaneSplitterConfig(const char * configId, PaneSplitter paneSplitter)
192    {
193       GuiDataPaneSplitter guiData = paneSplitters[configId];
194       if(guiData)
195       {
196          guiData.loading = true;
197          paneSplitter.scaleSplit = guiData.scaleSplit;
198          guiData.loading = false;
199       }
200    }
201 }
202
203 // TODO: Make this a WindowController (Note: it's currently missing OnStateChange)
204 class SavedConfigWindow : Window
205 {
206    virtual GuiConfigData getGuiConfigData() { return null; }
207    virtual const char * getGuiConfigInstanceId() { return _class.name; }
208
209    bool OnCreate()
210    {
211       bool result = Window::OnCreate();
212       if(result)
213       {
214          GuiConfigData data = getGuiConfigData();
215          if(data) data.saveWindowInit(getGuiConfigInstanceId(), this);
216       }
217       return result;
218    }
219
220    bool OnPostCreate()
221    {
222       bool result = Window::OnPostCreate();
223       if(result)
224       {
225          GuiConfigData data = getGuiConfigData();
226          if(data)
227             data.timer.Start();
228       }
229       return result;
230    }
231
232    bool OnStateChange(WindowState state, Modifiers mods)
233    {
234       GuiConfigData data = getGuiConfigData();
235       if(data) data.saveWindowState(getGuiConfigInstanceId(), this, state);
236       return true;
237    }
238
239    void OnPosition(int x, int y, int width, int height)
240    {
241       GuiConfigData data = getGuiConfigData();
242       if(data) data.saveWindowPosition(getGuiConfigInstanceId(), this, { x, y }, clientSize);
243    }
244
245    void OnResize(int width, int height)
246    {
247       GuiConfigData data = getGuiConfigData();
248       if(data) data.saveWindowSize(getGuiConfigInstanceId(), this, clientSize);
249    }
250
251    bool OnClose(bool parentClosing)
252    {
253       GuiConfigData data = getGuiConfigData();
254       if(data) data.saveWindowClose(getGuiConfigInstanceId());
255       return true;
256    }
257 }
258
259 class GuiDataWindow : struct
260 {
261 public:
262    WindowState state;
263    Point position;
264    Size size;
265 private:
266    bool saving;
267    bool loading;
268 }
269
270 class SavedConfigPaneSplitter : PaneSplitter
271 {
272    virtual GuiConfigData getGuiConfigData() { return null; }
273    virtual const char * getGuiConfigInstanceId() { return _class.name; }
274
275    bool OnPostCreate()
276    {
277       GuiConfigData data = getGuiConfigData();
278       if(data) data.applyPaneSplitterConfig(getGuiConfigInstanceId(), this);
279       return true;
280    }
281
282    bool NotifyResized(SavedConfigPaneSplitter splitter)
283    {
284       GuiConfigData data = splitter.getGuiConfigData();
285       if(data) data.savePaneSplitterSize(splitter.getGuiConfigInstanceId(), splitter.scaleSplit);
286       return true;
287    }
288 }
289
290 class GuiDataPaneSplitter : struct
291 {
292 public:
293    double scaleSplit;
294 private:
295    bool loading;
296 }