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 void PreferencesDialog_restartRequired( const char* staticName );
134 template<typename Value>
139 const char *m_description;
141 LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) {
150 struct PropertyImpl<LatchedValue<T>, T> {
151 static void Export(const LatchedValue<T> &self, const Callback<void(T)> &returnz) {
152 returnz(self.m_latched);
155 static void Import(LatchedValue<T> &self, T value) {
156 self.m_latched = value;
157 if (value != self.m_value) {
158 PreferencesDialog_restartRequired(self.m_description);
164 Property<T> make_property(LatchedValue<T> &self) {
165 return make_property<LatchedValue<T>, T>(self);
169 holds information for a given game
170 I'm a bit unclear on that still
171 it holds game specific configuration stuff
172 such as base names, engine names, some game specific features to activate in the various modules
173 it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
174 support for a new game)
176 what we do now is fully generate the information for this during the setup. We might want to
177 generate a piece that just says "the game pack is there", but put the rest of the config somwhere
178 else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
180 class CGameDescription
182 typedef std::map<CopiedString, CopiedString> GameDescription;
185 CopiedString mGameFile; ///< the .game file that describes this game
186 GameDescription m_gameDescription;
188 CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules
189 CopiedString mGameType; ///< the type of the engine
191 const char* getKeyValue( const char* key ) const {
192 GameDescription::const_iterator i = m_gameDescription.find( key );
193 if ( i != m_gameDescription.end() ) {
194 return ( *i ).second.c_str();
198 const char* getRequiredKeyValue( const char* key ) const {
199 GameDescription::const_iterator i = m_gameDescription.find( key );
200 if ( i != m_gameDescription.end() ) {
201 return ( *i ).second.c_str();
203 ERROR_MESSAGE( "game attribute " << makeQuoted( key ) << " not found in " << makeQuoted( mGameFile.c_str() ) );
207 CGameDescription( xmlDocPtr pDoc, const CopiedString &GameFile );
212 extern CGameDescription *g_pGameDescription;
216 class PreferencesPage;
218 class StringOutputStream;
221 standalone dialog for games selection, and more generally global settings
223 class CGameDialog : public Dialog
227 mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box
232 used to no ask for restart when switching game from Gobal Preferences window displayed on startup
237 those settings are saved in the global prefs file
238 I'm too lazy to wrap behind protected access, not sure this needs to be public
239 NOTE: those are preference settings. if you change them it is likely that you would
240 have to restart the editor for them to take effect
244 what game has been selected
245 this is the name of the .game file
247 CopiedString m_sGameFile;
249 prompt which game to load on startup
253 when if m_bGamePrompt is true
254 do not prompt at startup which game to load this time, but prompt the next times
255 this is used to not uselessly prompt game after having restarted because user switched game
257 bool m_bSkipGamePromptOnce;
259 log console to radiant.log
260 m_bForceLogConsole is an obscure forced latching situation
262 bool m_bForceLogConsole;
266 the list of game descriptions we scanned from the game/ dir
268 std::list<CGameDescription*> mGames;
272 m_bGamePrompt( true ),
273 m_bSkipGamePromptOnce( false ),
274 m_bForceLogConsole( false ){
276 virtual ~CGameDialog();
279 intialize the game dialog, called at CPrefsDlg::Init
280 will scan for games, load prefs, and do game selection dialog if needed
285 reset the global settings by removing the file
290 run the dialog UI for the list of games
296 this is only called when the dialog is built at startup for main engine select
298 ui::Window BuildDialog();
300 void GameFileImport( int value );
301 void GameFileExport( const Callback<void(int)> & importCallback ) const;
304 construction of the dialog frame
305 this is the part to be re-used in prefs dialog
306 for the standalone dialog, we include this in a modal box
307 for prefs, we hook the frame in the main notebook
308 build the frame on-demand (only once)
310 void CreateGlobalFrame( PreferencesPage& page );
313 global preferences subsystem
314 XML-based this time, hopefully this will generalize to other prefs
315 LoadPrefs has hardcoded defaults
316 NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
317 could have named the class differently I guess
320 void LoadPrefs(); ///< load from file into variables
321 void SavePrefs(); ///< save pref variables to file
326 scan for .game files, load them
331 inits g_Preferences.m_global_rc_path
333 void InitGlobalPrefPath();
336 uses m_nComboItem to find the right mGames
338 CGameDescription *GameDescriptionForComboItem();
342 this holds global level preferences
344 extern CGameDialog g_GamesDialog;
349 class PrefsDlg : public Dialog
353 std::list<CGameDescription *> mGames;
357 ui::Widget m_notebook{ui::null};
360 g_string_free( m_rc_path, true );
361 g_string_free( m_inipath, true );
365 path for global settings
367 linux: ~/.radiant/[version]/
369 GString *m_global_rc_path;
372 path to per-game settings
373 used for various game dependant storage
375 linux: ~/.radiant/[version]/[gamename]/
380 holds per-game settings
381 m_rc_path+"local.pref"
382 \todo FIXME at some point this should become XML property bag code too
386 // initialize the above paths
389 /*! Utility function for swapping notebook pages for tree list selections */
390 void showPrefPage( ui::Widget prefpage );
395 ui::Window BuildDialog();
396 void PostModal( EMessageBoxReturn code );
399 extern PrefsDlg g_Preferences;
401 struct preferences_globals_t
403 // disabled all INI / registry read write .. used when shutting down after registry cleanup
405 preferences_globals_t() : disable_ini( false ){
408 extern preferences_globals_t g_preferences_globals;
410 void PreferencesDialog_constructWindow( ui::Window main_window );
411 void PreferencesDialog_destroyWindow();
413 void PreferencesDialog_showDialog();
415 void GlobalPreferences_Init();
416 void Preferences_Init();
418 void Preferences_Load();
419 void Preferences_Save();
421 void Preferences_Reset();