]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/preferences.h
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / radiant / preferences.h
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 /*
23    The following source code is licensed by Id Software and subject to the terms of
24    its LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with
25    GtkRadiant. If you did not receive a LIMITED USE SOFTWARE LICENSE AGREEMENT,
26    please contact Id Software immediately at info@idsoftware.com.
27  */
28
29 #if !defined( INCLUDED_PREFERENCES_H )
30 #define INCLUDED_PREFERENCES_H
31
32 #include "libxml/parser.h"
33 #include "dialog.h"
34 #include <list>
35 #include <map>
36 #include "property.h"
37
38 void Widget_connectToggleDependency(ui::Widget self, ui::Widget toggleButton);
39
40 class PreferencesPage {
41     Dialog &m_dialog;
42     ui::VBox m_vbox;
43 public:
44     PreferencesPage(Dialog &dialog, ui::VBox vbox) : m_dialog(dialog), m_vbox(vbox)
45     {
46     }
47
48     ui::CheckButton appendCheckBox(const char *name, const char *flag, bool &data)
49     {
50         return m_dialog.addCheckBox(m_vbox, name, flag, data);
51     }
52
53     ui::CheckButton appendCheckBox(const char *name, const char *flag, Property<bool> const &cb)
54     {
55         return m_dialog.addCheckBox(m_vbox, name, flag, cb);
56     }
57
58     void appendCombo(const char *name, StringArrayRange values, Property<int> const &cb)
59     {
60         m_dialog.addCombo(m_vbox, name, values, cb);
61     }
62
63     void appendCombo(const char *name, int &data, StringArrayRange values)
64     {
65         m_dialog.addCombo(m_vbox, name, data, values);
66     }
67
68     void appendSlider(const char *name, int &data, gboolean draw_value, const char *low, const char *high, double value,
69                       double lower, double upper, double step_increment, double page_increment)
70     {
71         m_dialog.addSlider(m_vbox, name, data, draw_value, low, high, value, lower, upper, step_increment,
72                            page_increment);
73     }
74
75     void appendRadio(const char *name, StringArrayRange names, Property<int> const &cb)
76     {
77         m_dialog.addRadio(m_vbox, name, names, cb);
78     }
79
80     void appendRadio(const char *name, int &data, StringArrayRange names)
81     {
82         m_dialog.addRadio(m_vbox, name, data, names);
83     }
84
85     void appendRadioIcons(const char *name, StringArrayRange icons, Property<int> const &cb)
86     {
87         m_dialog.addRadioIcons(m_vbox, name, icons, cb);
88     }
89
90     void appendRadioIcons(const char *name, int &data, StringArrayRange icons)
91     {
92         m_dialog.addRadioIcons(m_vbox, name, data, icons);
93     }
94
95     ui::Widget appendEntry(const char *name, Property<int> const &cb)
96     {
97         return m_dialog.addIntEntry(m_vbox, name, cb);
98     }
99
100     ui::Widget appendEntry(const char *name, int &data)
101     {
102         return m_dialog.addEntry(m_vbox, name, data);
103     }
104
105     ui::Widget appendEntry(const char *name, Property<std::size_t> const &cb)
106     {
107         return m_dialog.addSizeEntry(m_vbox, name, cb);
108     }
109
110     ui::Widget appendEntry(const char *name, std::size_t &data)
111     {
112         return m_dialog.addEntry(m_vbox, name, data);
113     }
114
115     ui::Widget appendEntry(const char *name, Property<float> const &cb)
116     {
117         return m_dialog.addFloatEntry(m_vbox, name, cb);
118     }
119
120     ui::Widget appendEntry(const char *name, float &data)
121     {
122         return m_dialog.addEntry(m_vbox, name, data);
123     }
124
125     ui::Widget appendPathEntry(const char *name, bool browse_directory, Property<const char *> const &cb)
126     {
127         return m_dialog.addPathEntry(m_vbox, name, browse_directory, cb);
128     }
129
130     ui::Widget appendPathEntry(const char *name, CopiedString &data, bool directory)
131     {
132         return m_dialog.addPathEntry(m_vbox, name, data, directory);
133     }
134
135     ui::SpinButton appendSpinner(const char *name, int &data, double value, double lower, double upper)
136     {
137         return m_dialog.addSpinner(m_vbox, name, data, value, lower, upper);
138     }
139
140     ui::SpinButton appendSpinner(const char *name, double value, double lower, double upper, Property<int> const &cb)
141     {
142         return m_dialog.addSpinner(m_vbox, name, value, lower, upper, cb);
143     }
144
145     ui::SpinButton appendSpinner(const char *name, double value, double lower, double upper, Property<float> const &cb)
146     {
147         return m_dialog.addSpinner(m_vbox, name, value, lower, upper, cb);
148     }
149 };
150
151 typedef Callback<void(PreferencesPage &)> PreferencesPageCallback;
152
153 class PreferenceGroup {
154 public:
155     virtual PreferencesPage createPage(const char *treeName, const char *frameName) = 0;
156 };
157
158 typedef Callback<void(PreferenceGroup &)> PreferenceGroupCallback;
159
160 void PreferencesDialog_addInterfacePreferences(const PreferencesPageCallback &callback);
161
162 void PreferencesDialog_addInterfacePage(const PreferenceGroupCallback &callback);
163
164 void PreferencesDialog_addDisplayPreferences(const PreferencesPageCallback &callback);
165
166 void PreferencesDialog_addDisplayPage(const PreferenceGroupCallback &callback);
167
168 void PreferencesDialog_addSettingsPreferences(const PreferencesPageCallback &callback);
169
170 void PreferencesDialog_addSettingsPage(const PreferenceGroupCallback &callback);
171
172 void PreferencesDialog_restartRequired(const char *staticName);
173
174 template<typename Value>
175 class LatchedValue {
176 public:
177     Value m_value;
178     Value m_latched;
179     const char *m_description;
180
181     LatchedValue(Value value, const char *description) : m_latched(value), m_description(description)
182     {
183     }
184
185     void useLatched()
186     {
187         m_value = m_latched;
188     }
189 };
190
191 template<class T>
192 struct PropertyImpl<LatchedValue<T>, T> {
193     static void Export(const LatchedValue<T> &self, const Callback<void(T)> &returnz)
194     {
195         returnz(self.m_latched);
196     }
197
198     static void Import(LatchedValue<T> &self, T value)
199     {
200         self.m_latched = value;
201         if (value != self.m_value) {
202             PreferencesDialog_restartRequired(self.m_description);
203         }
204     }
205 };
206
207 template<class T>
208 Property<T> make_property(LatchedValue<T> &self)
209 {
210     return make_property<LatchedValue<T>, T>(self);
211 }
212
213 /*!
214    holds information for a given game
215    I'm a bit unclear on that still
216    it holds game specific configuration stuff
217    such as base names, engine names, some game specific features to activate in the various modules
218    it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
219    support for a new game)
220
221    what we do now is fully generate the information for this during the setup. We might want to
222    generate a piece that just says "the game pack is there", but put the rest of the config somwhere
223    else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
224  */
225 class CGameDescription {
226     typedef std::map<CopiedString, CopiedString> GameDescription;
227
228 public:
229     CopiedString mGameFile;   ///< the .game file that describes this game
230     GameDescription m_gameDescription;
231
232     CopiedString mGameToolsPath;   ///< the explicit path to the game-dependent modules
233     CopiedString mGameType;   ///< the type of the engine
234
235     const char *getKeyValue(const char *key) const
236     {
237         GameDescription::const_iterator i = m_gameDescription.find(key);
238         if (i != m_gameDescription.end()) {
239             return (*i).second.c_str();
240         }
241         return "";
242     }
243
244     const char *getRequiredKeyValue(const char *key) const
245     {
246         GameDescription::const_iterator i = m_gameDescription.find(key);
247         if (i != m_gameDescription.end()) {
248             return (*i).second.c_str();
249         }
250         ERROR_MESSAGE("game attribute " << makeQuoted(key) << " not found in " << makeQuoted(mGameFile.c_str()));
251         return "";
252     }
253
254     CGameDescription(xmlDocPtr pDoc, const CopiedString &GameFile);
255
256     void Dump();
257 };
258
259 extern CGameDescription *g_pGameDescription;
260
261 class PrefsDlg;
262
263 class PreferencesPage;
264
265 class StringOutputStream;
266
267 /*!
268    standalone dialog for games selection, and more generally global settings
269  */
270 class CGameDialog : public Dialog {
271 protected:
272
273     mutable int m_nComboSelect;   ///< intermediate int value for combo in dialog box
274
275 public:
276
277 /*!
278    those settings are saved in the global prefs file
279    I'm too lazy to wrap behind protected access, not sure this needs to be public
280    NOTE: those are preference settings. if you change them it is likely that you would
281    have to restart the editor for them to take effect
282  */
283 /*@{*/
284 /*!
285    what game has been selected
286    this is the name of the .game file
287  */
288     CopiedString m_sGameFile;
289 /*!
290    prompt which game to load on startup
291  */
292     bool m_bGamePrompt;
293 /*!
294    log console to radiant.log
295    m_bForceLogConsole is an obscure forced latching situation
296  */
297     bool m_bForceLogConsole;
298 /*@}*/
299
300 /*!
301    the list of game descriptions we scanned from the game/ dir
302  */
303     std::list<CGameDescription *> mGames;
304
305     CGameDialog() :
306             m_sGameFile(""),
307             m_bGamePrompt(true),
308             m_bForceLogConsole(false)
309     {
310     }
311
312     virtual ~CGameDialog();
313
314 /*!
315    intialize the game dialog, called at CPrefsDlg::Init
316    will scan for games, load prefs, and do game selection dialog if needed
317  */
318     void Init();
319
320 /*!
321    reset the global settings by removing the file
322  */
323     void Reset();
324
325 /*!
326    run the dialog UI for the list of games
327  */
328     void DoGameDialog();
329
330 /*!
331    Dialog API
332    this is only called when the dialog is built at startup for main engine select
333  */
334     ui::Window BuildDialog();
335
336     void GameFileImport(int value);
337
338     void GameFileExport(const Callback<void(int)> &importCallback) const;
339
340 /*!
341    construction of the dialog frame
342    this is the part to be re-used in prefs dialog
343    for the standalone dialog, we include this in a modal box
344    for prefs, we hook the frame in the main notebook
345    build the frame on-demand (only once)
346  */
347     void CreateGlobalFrame(PreferencesPage &page);
348
349 /*!
350    global preferences subsystem
351    XML-based this time, hopefully this will generalize to other prefs
352    LoadPrefs has hardcoded defaults
353    NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
354    could have named the class differently I guess
355  */
356 /*@{*/
357     void LoadPrefs();   ///< load from file into variables
358     void SavePrefs();   ///< save pref variables to file
359 /*@}*/
360
361 private:
362 /*!
363    scan for .game files, load them
364  */
365     void ScanForGames();
366
367 /*!
368    inits g_Preferences.m_global_rc_path
369  */
370     void InitGlobalPrefPath();
371
372 /*!
373    uses m_nComboItem to find the right mGames
374  */
375     CGameDescription *GameDescriptionForComboItem();
376 };
377
378 /*!
379    this holds global level preferences
380  */
381 extern CGameDialog g_GamesDialog;
382
383
384 class texdef_t;
385
386 class PrefsDlg : public Dialog {
387 public:
388 protected:
389     std::list<CGameDescription *> mGames;
390
391 public:
392
393     ui::Widget m_notebook{ui::null};
394
395     virtual ~PrefsDlg()
396     {
397         g_string_free(m_rc_path, true);
398         g_string_free(m_inipath, true);
399     }
400
401 /*!
402    path for global settings
403    win32: AppPath
404    linux: ~/.radiant/[version]/
405  */
406     GString *m_global_rc_path;
407
408 /*!
409    path to per-game settings
410    used for various game dependant storage
411    win32: GameToolsPath
412    linux: ~/.radiant/[version]/[gamename]/
413  */
414     GString *m_rc_path;
415
416 /*!
417    holds per-game settings
418    m_rc_path+"local.pref"
419    \todo FIXME at some point this should become XML property bag code too
420  */
421     GString *m_inipath;
422
423 // initialize the above paths
424     void Init();
425
426 /*! Utility function for swapping notebook pages for tree list selections */
427     void showPrefPage(ui::Widget prefpage);
428
429 protected:
430
431 /*! Dialog API */
432     ui::Window BuildDialog();
433
434     void PostModal(EMessageBoxReturn code);
435 };
436
437 extern PrefsDlg g_Preferences;
438
439 struct preferences_globals_t {
440     // disabled all INI / registry read write .. used when shutting down after registry cleanup
441     bool disable_ini;
442
443     preferences_globals_t() : disable_ini(false)
444     {
445     }
446 };
447
448 extern preferences_globals_t g_preferences_globals;
449
450 void PreferencesDialog_constructWindow(ui::Window main_window);
451
452 void PreferencesDialog_destroyWindow();
453
454 void PreferencesDialog_showDialog();
455
456 void GlobalPreferences_Init();
457
458 void Preferences_Init();
459
460 void Preferences_Load();
461
462 void Preferences_Save();
463
464 void Preferences_Reset();
465
466
467 #endif