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 appendEntry( const char* name, Property<int> const &cb ){
75 return m_dialog.addIntEntry( m_vbox, name, cb );
77 ui::Widget appendEntry( const char* name, int& data ){
78 return m_dialog.addEntry( m_vbox, name, data );
80 ui::Widget appendEntry( const char* name, Property<std::size_t> const &cb){
81 return m_dialog.addSizeEntry( m_vbox, name, cb );
83 ui::Widget appendEntry( const char* name, std::size_t& data ){
84 return m_dialog.addEntry( m_vbox, name, data );
86 ui::Widget appendEntry( const char* name, Property<float> const &cb ){
87 return m_dialog.addFloatEntry( m_vbox, name, cb );
89 ui::Widget appendEntry( const char* name, float& data ){
90 return m_dialog.addEntry( m_vbox, name, data );
92 ui::Widget appendPathEntry( const char* name, bool browse_directory, Property<const char *> const &cb ){
93 return m_dialog.addPathEntry( m_vbox, name, browse_directory, cb );
95 ui::Widget appendPathEntry( const char* name, CopiedString& data, bool directory ){
96 return m_dialog.addPathEntry( m_vbox, name, data, directory );
98 ui::SpinButton appendSpinner( const char* name, int& data, double value, double lower, double upper ){
99 return m_dialog.addSpinner( m_vbox, name, data, value, lower, upper );
101 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property<int> const &cb ){
102 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
104 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property<float> const &cb ){
105 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
109 typedef Callback<void(PreferencesPage&)> PreferencesPageCallback;
111 class PreferenceGroup
114 virtual PreferencesPage createPage( const char* treeName, const char* frameName ) = 0;
117 typedef Callback<void(PreferenceGroup&)> PreferenceGroupCallback;
119 void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback );
120 void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback );
121 void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback );
122 void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback );
123 void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback );
124 void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback );
126 void PreferencesDialog_restartRequired( const char* staticName );
128 template<typename Value>
133 const char *m_description;
135 LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) {
144 struct PropertyImpl<LatchedValue<T>, T> {
145 static void Export(const LatchedValue<T> &self, const Callback<void(T)> &returnz) {
146 returnz(self.m_latched);
149 static void Import(LatchedValue<T> &self, T value) {
150 self.m_latched = value;
151 if (value != self.m_value) {
152 PreferencesDialog_restartRequired(self.m_description);
158 Property<T> make_property(LatchedValue<T> &self) {
159 return make_property<LatchedValue<T>, T>(self);
163 holds information for a given game
164 I'm a bit unclear on that still
165 it holds game specific configuration stuff
166 such as base names, engine names, some game specific features to activate in the various modules
167 it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
168 support for a new game)
170 what we do now is fully generate the information for this during the setup. We might want to
171 generate a piece that just says "the game pack is there", but put the rest of the config somwhere
172 else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
174 class CGameDescription
176 typedef std::map<CopiedString, CopiedString> GameDescription;
179 CopiedString mGameFile; ///< the .game file that describes this game
180 GameDescription m_gameDescription;
182 CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules
183 CopiedString mGameType; ///< the type of the engine
185 const char* getKeyValue( const char* key ) const {
186 GameDescription::const_iterator i = m_gameDescription.find( key );
187 if ( i != m_gameDescription.end() ) {
188 return ( *i ).second.c_str();
192 const char* getRequiredKeyValue( 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();
197 ERROR_MESSAGE( "game attribute " << makeQuoted( key ) << " not found in " << makeQuoted( mGameFile.c_str() ) );
201 CGameDescription( xmlDocPtr pDoc, const CopiedString &GameFile );
206 extern CGameDescription *g_pGameDescription;
210 class PreferencesPage;
212 class StringOutputStream;
215 standalone dialog for games selection, and more generally global settings
217 class CGameDialog : public Dialog
221 mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box
226 used to no ask for restart when switching game from Gobal Preferences window displayed on startup
231 those settings are saved in the global prefs file
232 I'm too lazy to wrap behind protected access, not sure this needs to be public
233 NOTE: those are preference settings. if you change them it is likely that you would
234 have to restart the editor for them to take effect
238 what game has been selected
239 this is the name of the .game file
241 CopiedString m_sGameFile;
243 prompt which game to load on startup
247 when if m_bGamePrompt is true
248 do not prompt at startup which game to load this time, but prompt the next times
249 this is used to not uselessly prompt game after having restarted because user switched game
251 bool m_bSkipGamePromptOnce;
253 log console to radiant.log
254 m_bForceLogConsole is an obscure forced latching situation
256 bool m_bForceLogConsole;
260 the list of game descriptions we scanned from the game/ dir
262 std::list<CGameDescription*> mGames;
266 m_bGamePrompt( true ),
267 m_bSkipGamePromptOnce( false ),
268 m_bForceLogConsole( false ){
270 virtual ~CGameDialog();
273 intialize the game dialog, called at CPrefsDlg::Init
274 will scan for games, load prefs, and do game selection dialog if needed
279 reset the global settings by removing the file
284 run the dialog UI for the list of games
290 this is only called when the dialog is built at startup for main engine select
292 ui::Window BuildDialog();
294 void GameFileImport( int value );
295 void GameFileExport( const Callback<void(int)> & importCallback ) const;
298 construction of the dialog frame
299 this is the part to be re-used in prefs dialog
300 for the standalone dialog, we include this in a modal box
301 for prefs, we hook the frame in the main notebook
302 build the frame on-demand (only once)
304 void CreateGlobalFrame( PreferencesPage& page );
307 global preferences subsystem
308 XML-based this time, hopefully this will generalize to other prefs
309 LoadPrefs has hardcoded defaults
310 NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
311 could have named the class differently I guess
314 void LoadPrefs(); ///< load from file into variables
315 void SavePrefs(); ///< save pref variables to file
320 scan for .game files, load them
325 inits g_Preferences.m_global_rc_path
327 void InitGlobalPrefPath();
330 uses m_nComboItem to find the right mGames
332 CGameDescription *GameDescriptionForComboItem();
336 this holds global level preferences
338 extern CGameDialog g_GamesDialog;
343 class PrefsDlg : public Dialog
347 std::list<CGameDescription *> mGames;
351 ui::Widget m_notebook{ui::null};
354 g_string_free( m_rc_path, true );
355 g_string_free( m_inipath, true );
359 path for global settings
361 linux: ~/.radiant/[version]/
363 GString *m_global_rc_path;
366 path to per-game settings
367 used for various game dependant storage
369 linux: ~/.radiant/[version]/[gamename]/
374 holds per-game settings
375 m_rc_path+"local.pref"
376 \todo FIXME at some point this should become XML property bag code too
380 // initialize the above paths
383 /*! Utility function for swapping notebook pages for tree list selections */
384 void showPrefPage( ui::Widget prefpage );
389 ui::Window BuildDialog();
390 void PostModal( EMessageBoxReturn code );
393 extern PrefsDlg g_Preferences;
395 struct preferences_globals_t
397 // disabled all INI / registry read write .. used when shutting down after registry cleanup
399 preferences_globals_t() : disable_ini( false ){
402 extern preferences_globals_t g_preferences_globals;
404 void PreferencesDialog_constructWindow( ui::Window main_window );
405 void PreferencesDialog_destroyWindow();
407 void PreferencesDialog_showDialog();
409 void GlobalPreferences_Init();
410 void Preferences_Init();
412 void Preferences_Load();
413 void Preferences_Save();
415 void Preferences_Reset();