1 /*
2 * preferences.h
3 * Copyright 2007-2014 Tomasz Moń, Ariadne Conill, and John Lindgren
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions, and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions, and the following disclaimer in the documentation
13 * provided with the distribution.
14 *
15 * This software is provided "as is" and without any warranty, express or
16 * implied. In no event shall the authors be liable for any damages arising from
17 * the use of this software.
18 */
19
20 #ifndef LIBAUDCORE_PREFERENCES_H
21 #define LIBAUDCORE_PREFERENCES_H
22
23 #include <libaudcore/objects.h>
24
25 struct PreferencesWidget;
26
27 enum class FileSelectMode
28 {
29 File,
30 Folder
31 };
32
33 struct ComboItem
34 {
35 const char * label;
36 const char * str;
37 int num;
38
ComboItemComboItem39 constexpr ComboItem(const char * label, const char * str)
40 : label(label), str(str), num(-1)
41 {
42 }
43
ComboItemComboItem44 constexpr ComboItem(const char * label, int num)
45 : label(label), str(nullptr), num(num)
46 {
47 }
48 };
49
50 struct WidgetVButton
51 {
52 void (*callback)();
53 const char * icon;
54 };
55
56 struct WidgetVRadio
57 {
58 int value;
59 };
60
61 struct WidgetVSpin
62 {
63 double min, max, step;
64 const char * right_label; /* text right to widget */
65 };
66
67 struct WidgetVTable
68 {
69 ArrayRef<PreferencesWidget> widgets;
70 };
71
72 struct WidgetVFonts
73 {
74 const char * title;
75 };
76
77 struct WidgetVEntry
78 {
79 bool password;
80 };
81
82 struct WidgetVFileEntry
83 {
84 FileSelectMode mode;
85 };
86
87 struct WidgetVCombo
88 {
89 /* static init */
90 ArrayRef<ComboItem> elems;
91
92 /* runtime init */
93 ArrayRef<ComboItem> (*fill)();
94 };
95
96 struct WidgetVBox
97 {
98 ArrayRef<PreferencesWidget> widgets;
99
100 bool horizontal; /* false gives vertical, true gives horizontal alignment of
101 child widgets */
102 bool frame; /* whether to draw frame around box */
103 };
104
105 struct NotebookTab
106 {
107 const char * name;
108 ArrayRef<PreferencesWidget> widgets;
109 };
110
111 struct WidgetVNotebook
112 {
113 ArrayRef<NotebookTab> tabs;
114 };
115
116 struct WidgetVSeparator
117 {
118 bool horizontal; /* false gives vertical, true gives horizontal separator */
119 };
120
121 union WidgetVariant {
122 WidgetVButton button;
123 WidgetVRadio radio_btn;
124 WidgetVSpin spin_btn;
125 WidgetVTable table;
126 WidgetVFonts font_btn;
127 WidgetVEntry entry;
128 WidgetVFileEntry file_entry;
129 WidgetVCombo combo;
130 WidgetVBox box;
131 WidgetVNotebook notebook;
132 WidgetVSeparator separator;
133
134 /* for custom GTK or Qt widgets */
135 /* GtkWidget * (* populate) (); */
136 /* QWidget * (* populate) (); */
137 void * (*populate)();
138
WidgetVariant(WidgetVButton button)139 constexpr WidgetVariant(WidgetVButton button) : button(button) {}
WidgetVariant(WidgetVRadio radio)140 constexpr WidgetVariant(WidgetVRadio radio) : radio_btn(radio) {}
WidgetVariant(WidgetVSpin spin)141 constexpr WidgetVariant(WidgetVSpin spin) : spin_btn(spin) {}
WidgetVariant(WidgetVTable table)142 constexpr WidgetVariant(WidgetVTable table) : table(table) {}
WidgetVariant(WidgetVFonts fonts)143 constexpr WidgetVariant(WidgetVFonts fonts) : font_btn(fonts) {}
WidgetVariant(WidgetVEntry entry)144 constexpr WidgetVariant(WidgetVEntry entry) : entry(entry) {}
WidgetVariant(WidgetVFileEntry file_entry)145 constexpr WidgetVariant(WidgetVFileEntry file_entry)
146 : file_entry(file_entry)
147 {
148 }
WidgetVariant(WidgetVCombo combo)149 constexpr WidgetVariant(WidgetVCombo combo) : combo(combo) {}
WidgetVariant(WidgetVBox box)150 constexpr WidgetVariant(WidgetVBox box) : box(box) {}
WidgetVariant(WidgetVNotebook notebook)151 constexpr WidgetVariant(WidgetVNotebook notebook) : notebook(notebook) {}
WidgetVariant(WidgetVSeparator separator)152 constexpr WidgetVariant(WidgetVSeparator separator) : separator(separator)
153 {
154 }
155
156 /* also serves as default constructor */
populate(populate)157 constexpr WidgetVariant(void * (*populate)() = 0) : populate(populate) {}
158 };
159
160 struct WidgetConfig
161 {
162 enum Type
163 {
164 None,
165 Bool,
166 Int,
167 Float,
168 String
169 };
170
171 Type type;
172
173 /* pointer to immediate value */
174 void * value;
175 /* identifier for configuration value */
176 const char *section, *name;
177 /* called when value is changed */
178 void (*callback)();
179 /* widget updates when this hook is called */
180 const char * hook;
181
WidgetConfigWidgetConfig182 constexpr WidgetConfig()
183 : type(None), value(nullptr), section(nullptr), name(nullptr),
184 callback(nullptr), hook(nullptr)
185 {
186 }
187
WidgetConfigWidgetConfig188 constexpr WidgetConfig(Type type, void * value, const char * section,
189 const char * name, void (*callback)(),
190 const char * hook)
191 : type(type), value(value), section(section), name(name),
192 callback(callback), hook(hook)
193 {
194 }
195
196 bool get_bool() const;
197 void set_bool(bool val) const;
198 int get_int() const;
199 void set_int(int val) const;
200 double get_float() const;
201 void set_float(double val) const;
202 ::String get_string() const;
203 void set_string(const char * val) const;
204 };
205
206 constexpr WidgetConfig WidgetBool(bool & value, void (*callback)() = nullptr,
207 const char * hook = nullptr)
208 {
209 return WidgetConfig(WidgetConfig::Bool, (void *)&value, 0, 0, callback,
210 hook);
211 }
212 constexpr WidgetConfig WidgetInt(int & value, void (*callback)() = nullptr,
213 const char * hook = nullptr)
214 {
215 return WidgetConfig(WidgetConfig::Int, (void *)&value, 0, 0, callback,
216 hook);
217 }
218 constexpr WidgetConfig WidgetFloat(double & value, void (*callback)() = nullptr,
219 const char * hook = nullptr)
220 {
221 return WidgetConfig(WidgetConfig::Float, (void *)&value, 0, 0, callback,
222 hook);
223 }
224 constexpr WidgetConfig WidgetString(String & value,
225 void (*callback)() = nullptr,
226 const char * hook = nullptr)
227 {
228 return WidgetConfig(WidgetConfig::String, (void *)&value, 0, 0, callback,
229 hook);
230 }
231
232 constexpr WidgetConfig WidgetBool(const char * section, const char * name,
233 void (*callback)() = nullptr,
234 const char * hook = nullptr)
235 {
236 return WidgetConfig(WidgetConfig::Bool, 0, section, name, callback, hook);
237 }
238 constexpr WidgetConfig WidgetInt(const char * section, const char * name,
239 void (*callback)() = nullptr,
240 const char * hook = nullptr)
241 {
242 return WidgetConfig(WidgetConfig::Int, 0, section, name, callback, hook);
243 }
244 constexpr WidgetConfig WidgetFloat(const char * section, const char * name,
245 void (*callback)() = nullptr,
246 const char * hook = nullptr)
247 {
248 return WidgetConfig(WidgetConfig::Float, 0, section, name, callback, hook);
249 }
250 constexpr WidgetConfig WidgetString(const char * section, const char * name,
251 void (*callback)() = nullptr,
252 const char * hook = nullptr)
253 {
254 return WidgetConfig(WidgetConfig::String, 0, section, name, callback, hook);
255 }
256
257 struct PreferencesWidget
258 {
259 enum Type
260 {
261 Label,
262 Button,
263 CheckButton,
264 RadioButton,
265 SpinButton,
266 Entry,
267 FileEntry,
268 ComboBox,
269 FontButton,
270 Box,
271 Table,
272 Notebook,
273 Separator,
274 CustomGTK,
275 CustomQt
276 };
277
278 Type type;
279 const char *
280 label; /* widget title (for SPIN_BTN it's text left to widget) */
281 bool child;
282
283 WidgetConfig cfg;
284 WidgetVariant data;
285 };
286
287 enum WidgetIsChild
288 {
289 WIDGET_NOT_CHILD,
290 WIDGET_CHILD
291 };
292
293 constexpr PreferencesWidget WidgetLabel(const char * label,
294 WidgetIsChild child = WIDGET_NOT_CHILD)
295 {
296 return {PreferencesWidget::Label, label, (child == WIDGET_CHILD)};
297 }
298
299 constexpr PreferencesWidget WidgetButton(const char * label,
300 WidgetVButton button,
301 WidgetIsChild child = WIDGET_NOT_CHILD)
302 {
303 return {
304 PreferencesWidget::Button, label, (child == WIDGET_CHILD), {}, button};
305 }
306
307 constexpr PreferencesWidget WidgetCheck(const char * label, WidgetConfig cfg,
308 WidgetIsChild child = WIDGET_NOT_CHILD)
309 {
310 return {PreferencesWidget::CheckButton, label, (child == WIDGET_CHILD),
311 cfg};
312 }
313
314 constexpr PreferencesWidget WidgetRadio(const char * label, WidgetConfig cfg,
315 WidgetVRadio radio,
316 WidgetIsChild child = WIDGET_NOT_CHILD)
317 {
318 return {PreferencesWidget::RadioButton, label, (child == WIDGET_CHILD), cfg,
319 radio};
320 }
321
322 constexpr PreferencesWidget WidgetSpin(const char * label, WidgetConfig cfg,
323 WidgetVSpin spin,
324 WidgetIsChild child = WIDGET_NOT_CHILD)
325 {
326 return {PreferencesWidget::SpinButton, label, (child == WIDGET_CHILD), cfg,
327 spin};
328 }
329
330 constexpr PreferencesWidget WidgetEntry(const char * label, WidgetConfig cfg,
331 WidgetVEntry entry = WidgetVEntry(),
332 WidgetIsChild child = WIDGET_NOT_CHILD)
333 {
334 return {PreferencesWidget::Entry, label, (child == WIDGET_CHILD), cfg,
335 entry};
336 }
337
338 constexpr PreferencesWidget
339 WidgetFileEntry(const char * label, WidgetConfig cfg,
340 WidgetVFileEntry file_entry = WidgetVFileEntry(),
341 WidgetIsChild child = WIDGET_NOT_CHILD)
342 {
343 return {PreferencesWidget::FileEntry, label, (child == WIDGET_CHILD), cfg,
344 file_entry};
345 }
346
347 constexpr PreferencesWidget WidgetCombo(const char * label, WidgetConfig cfg,
348 WidgetVCombo combo,
349 WidgetIsChild child = WIDGET_NOT_CHILD)
350 {
351 return {PreferencesWidget::ComboBox, label, (child == WIDGET_CHILD), cfg,
352 combo};
353 }
354
355 constexpr PreferencesWidget WidgetFonts(const char * label, WidgetConfig cfg,
356 WidgetVFonts fonts,
357 WidgetIsChild child = WIDGET_NOT_CHILD)
358 {
359 return {PreferencesWidget::FontButton, label, (child == WIDGET_CHILD), cfg,
360 fonts};
361 }
362
363 constexpr PreferencesWidget WidgetBox(WidgetVBox box,
364 WidgetIsChild child = WIDGET_NOT_CHILD)
365 {
366 return {PreferencesWidget::Box, 0, (child == WIDGET_CHILD), {}, box};
367 }
368
369 constexpr PreferencesWidget WidgetTable(WidgetVTable table,
370 WidgetIsChild child = WIDGET_NOT_CHILD)
371 {
372 return {PreferencesWidget::Table, 0, (child == WIDGET_CHILD), {}, table};
373 }
374
WidgetNotebook(WidgetVNotebook notebook)375 constexpr PreferencesWidget WidgetNotebook(WidgetVNotebook notebook)
376 {
377 return {PreferencesWidget::Notebook, 0, 0, {}, notebook};
378 }
379
380 constexpr PreferencesWidget
381 WidgetSeparator(WidgetVSeparator separator = WidgetVSeparator())
382 {
383 return {PreferencesWidget::Separator, 0, 0, {}, separator};
384 }
385
386 constexpr PreferencesWidget
387 WidgetCustomGTK(void * (*populate)(), WidgetIsChild child = WIDGET_NOT_CHILD)
388 {
389 return {
390 PreferencesWidget::CustomGTK, 0, (child == WIDGET_CHILD), {}, populate};
391 }
392
393 constexpr PreferencesWidget
394 WidgetCustomQt(void * (*populate)(), WidgetIsChild child = WIDGET_NOT_CHILD)
395 {
396 return {
397 PreferencesWidget::CustomQt, 0, (child == WIDGET_CHILD), {}, populate};
398 }
399
400 struct PluginPreferences
401 {
402 ArrayRef<PreferencesWidget> widgets;
403
404 void (*init)();
405 void (*apply)();
406 void (*cleanup)();
407 };
408
409 #endif /* LIBAUDCORE_PREFERENCES_H */
410