2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
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.
29 #if !defined( INCLUDED_PREFERENCES_H )
30 #define INCLUDED_PREFERENCES_H
32 #include "libxml/parser.h"
38 void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton );
45 PreferencesPage( Dialog& dialog, ui::VBox vbox ) : m_dialog( dialog ), m_vbox( vbox ){
47 ui::CheckButton appendCheckBox( const char* name, const char* flag, bool& data ){
48 return m_dialog.addCheckBox( m_vbox, name, flag, data );
50 ui::CheckButton appendCheckBox( const char* name, const char* flag, Property<bool> const &cb ){
51 return m_dialog.addCheckBox( m_vbox, name, flag, cb );
53 void appendCombo( const char* name, StringArrayRange values, Property<int> const &cb ){
54 m_dialog.addCombo( m_vbox, name, values, cb );
56 void appendCombo( const char* name, int& data, StringArrayRange values ){
57 m_dialog.addCombo( m_vbox, name, data, values );
59 void appendSlider( const char* name, int& data, gboolean draw_value, const char* low, const char* high, double value, double lower, double upper, double step_increment, double page_increment ){
60 m_dialog.addSlider( m_vbox, name, data, draw_value, low, high, value, lower, upper, step_increment, page_increment );
62 void appendRadio( const char* name, StringArrayRange names, Property<int> const &cb ){
63 m_dialog.addRadio( m_vbox, name, names, cb );
65 void appendRadio( const char* name, int& data, StringArrayRange names ){
66 m_dialog.addRadio( m_vbox, name, data, names );
68 void appendRadioIcons( const char* name, StringArrayRange icons, Property<int> const &cb ){
69 m_dialog.addRadioIcons( m_vbox, name, icons, cb );
71 void appendRadioIcons( const char* name, int& data, StringArrayRange icons ){
72 m_dialog.addRadioIcons( m_vbox, name, data, icons );
74 ui::Widget appendSpacer( int dimension ){
75 return m_dialog.addSpacer( m_vbox, dimension );
77 ui::Widget appendLabel( const char* name, const char* text ){
78 return m_dialog.addLabel( m_vbox, name, text );
80 ui::Widget appendEntry( const char* name, Property<int> const &cb ){
81 return m_dialog.addIntEntry( m_vbox, name, cb );
83 ui::Widget appendEntry( const char* name, int& data ){
84 return m_dialog.addEntry( m_vbox, name, data );
86 ui::Widget appendEntry( const char* name, Property<std::size_t> const &cb){
87 return m_dialog.addSizeEntry( m_vbox, name, cb );
89 ui::Widget appendEntry( const char* name, std::size_t& data ){
90 return m_dialog.addEntry( m_vbox, name, data );
92 ui::Widget appendEntry( const char* name, Property<float> const &cb ){
93 return m_dialog.addFloatEntry( m_vbox, name, cb );
95 ui::Widget appendEntry( const char* name, float& data ){
96 return m_dialog.addEntry( m_vbox, name, data );
98 ui::Widget appendPathEntry( const char* name, bool browse_directory, Property<const char *> const &cb ){
99 return m_dialog.addPathEntry( m_vbox, name, browse_directory, cb );
101 ui::Widget appendPathEntry( const char* name, CopiedString& data, bool directory ){
102 return m_dialog.addPathEntry( m_vbox, name, data, directory );
104 ui::SpinButton appendSpinner( const char* name, int& data, double value, double lower, double upper ){
105 return m_dialog.addSpinner( m_vbox, name, data, value, lower, upper );
107 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property<int> const &cb ){
108 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
110 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property<float> const &cb ){
111 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
115 typedef Callback<void(PreferencesPage&)> PreferencesPageCallback;
117 class PreferenceGroup
120 virtual PreferencesPage createPage( const char* treeName, const char* frameName ) = 0;
123 typedef Callback<void(PreferenceGroup&)> PreferenceGroupCallback;
125 void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback );
126 void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback );
127 void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback );
128 void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback );
129 void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback );
130 void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback );
132 bool PreferencesDialog_isRestartRequired();
133 void PreferencesDialog_restartRequired( const char* staticName );
135 template<typename Value>
140 const char *m_description;
142 LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) {
151 struct PropertyImpl<LatchedValue<T>, T> {
152 static void Export(const LatchedValue<T> &self, const Callback<void(T)> &returnz) {
153 returnz(self.m_latched);
156 static void Import(LatchedValue<T> &self, T value) {
157 self.m_latched = value;
158 if (value != self.m_value) {
159 PreferencesDialog_restartRequired(self.m_description);
165 Property<T> make_property(LatchedValue<T> &self) {
166 return make_property<LatchedValue<T>, T>(self);
170 holds information for a given game
171 I'm a bit unclear on that still
172 it holds game specific configuration stuff
173 such as base names, engine names, some game specific features to activate in the various modules
174 it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
175 support for a new game)
177 what we do now is fully generate the information for this during the setup. We might want to
178 generate a piece that just says "the game pack is there", but put the rest of the config somwhere
179 else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
181 class CGameDescription
183 typedef std::map<CopiedString, CopiedString> GameDescription;
186 CopiedString mGameFile; ///< the .game file that describes this game
187 GameDescription m_gameDescription;
189 CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules
190 CopiedString mGameType; ///< the type of the engine
192 const char* getKeyValue( const char* key ) const {
193 GameDescription::const_iterator i = m_gameDescription.find( key );
194 if ( i != m_gameDescription.end() ) {
195 return ( *i ).second.c_str();
199 const char* getRequiredKeyValue( const char* key ) const {
200 GameDescription::const_iterator i = m_gameDescription.find( key );
201 if ( i != m_gameDescription.end() ) {
202 return ( *i ).second.c_str();
204 ERROR_MESSAGE( "game attribute " << makeQuoted( key ) << " not found in " << makeQuoted( mGameFile.c_str() ) );
208 CGameDescription( xmlDocPtr pDoc, const CopiedString &GameFile );
213 extern CGameDescription *g_pGameDescription;
217 class PreferencesPage;
219 class StringOutputStream;
222 standalone dialog for games selection, and more generally global settings
224 class CGameDialog : public Dialog
228 mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box
233 used to no ask for restart when switching game from Gobal Preferences window displayed on startup
238 those settings are saved in the global prefs file
239 I'm too lazy to wrap behind protected access, not sure this needs to be public
240 NOTE: those are preference settings. if you change them it is likely that you would
241 have to restart the editor for them to take effect
245 what game has been selected
246 this is the name of the .game file
248 CopiedString m_sGameFile;
250 prompt which game to load on startup
254 when if m_bGamePrompt is true
255 do not prompt at startup which game to load this time, but prompt the next times
256 this is used to not uselessly prompt game after having restarted because user switched game
258 bool m_bSkipGamePromptOnce;
260 log console to radiant.log
261 m_bForceLogConsole is an obscure forced latching situation
263 bool m_bForceLogConsole;
267 the list of game descriptions we scanned from the game/ dir
269 std::list<CGameDescription*> mGames;
273 m_bGamePrompt( true ),
274 m_bSkipGamePromptOnce( false ),
275 m_bForceLogConsole( false ){
277 virtual ~CGameDialog();
280 intialize the game dialog, called at CPrefsDlg::Init
281 will scan for games, load prefs, and do game selection dialog if needed
286 reset the global settings by removing the file
291 run the dialog UI for the list of games
297 this is only called when the dialog is built at startup for main engine select
299 ui::Window BuildDialog();
301 void GameFileImport( int value );
302 void GameFileExport( const Callback<void(int)> & importCallback ) const;
305 construction of the dialog frame
306 this is the part to be re-used in prefs dialog
307 for the standalone dialog, we include this in a modal box
308 for prefs, we hook the frame in the main notebook
309 build the frame on-demand (only once)
311 void CreateGlobalFrame( PreferencesPage& page );
314 global preferences subsystem
315 XML-based this time, hopefully this will generalize to other prefs
316 LoadPrefs has hardcoded defaults
317 NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
318 could have named the class differently I guess
321 void LoadPrefs(); ///< load from file into variables
322 void SavePrefs(); ///< save pref variables to file
327 scan for .game files, load them
332 inits g_Preferences.m_global_rc_path
334 void InitGlobalPrefPath();
337 uses m_nComboItem to find the right mGames
339 CGameDescription *GameDescriptionForComboItem();
343 this holds global level preferences
345 extern CGameDialog g_GamesDialog;
350 class PrefsDlg : public Dialog
354 std::list<CGameDescription *> mGames;
358 ui::Widget m_notebook{ui::null};
361 g_string_free( m_rc_path, true );
362 g_string_free( m_inipath, true );
366 path for global settings
368 linux: ~/.radiant/[version]/
370 GString *m_global_rc_path;
373 path to per-game settings
374 used for various game dependant storage
376 linux: ~/.radiant/[version]/[gamename]/
381 holds per-game settings
382 m_rc_path+"local.pref"
383 \todo FIXME at some point this should become XML property bag code too
387 // initialize the above paths
390 /*! Utility function for swapping notebook pages for tree list selections */
391 void showPrefPage( ui::Widget prefpage );
396 ui::Window BuildDialog();
397 void PostModal( EMessageBoxReturn code );
400 extern PrefsDlg g_Preferences;
402 struct preferences_globals_t
404 // disabled all INI / registry read write .. used when shutting down after registry cleanup
406 preferences_globals_t() : disable_ini( false ){
409 extern preferences_globals_t g_preferences_globals;
411 void PreferencesDialog_constructWindow( ui::Window main_window );
412 void PreferencesDialog_destroyWindow();
415 void PreferencesDialog_restartIfRequired();
416 void PreferencesDialog_showDialog();
418 void GlobalPreferences_Init();
419 void Preferences_Init();
421 void Preferences_Load();
422 void Preferences_Save();
424 void Preferences_Reset();