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"
37 void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton );
44 PreferencesPage( Dialog& dialog, ui::VBox vbox ) : m_dialog( dialog ), m_vbox( vbox ){
46 ui::CheckButton appendCheckBox( const char* name, const char* flag, bool& data ){
47 return m_dialog.addCheckBox( m_vbox, name, flag, data );
49 ui::CheckButton appendCheckBox( const char* name, const char* flag, ImportExportCallback<bool> const &cb ){
50 return m_dialog.addCheckBox( m_vbox, name, flag, cb );
52 void appendCombo( const char* name, StringArrayRange values, ImportExportCallback<int> const &cb ){
53 m_dialog.addCombo( m_vbox, name, values, cb );
55 void appendCombo( const char* name, int& data, StringArrayRange values ){
56 m_dialog.addCombo( m_vbox, name, data, values );
58 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 ){
59 m_dialog.addSlider( m_vbox, name, data, draw_value, low, high, value, lower, upper, step_increment, page_increment );
61 void appendRadio( const char* name, StringArrayRange names, ImportExportCallback<int> const &cb ){
62 m_dialog.addRadio( m_vbox, name, names, cb );
64 void appendRadio( const char* name, int& data, StringArrayRange names ){
65 m_dialog.addRadio( m_vbox, name, data, names );
67 void appendRadioIcons( const char* name, StringArrayRange icons, ImportExportCallback<int> const &cb ){
68 m_dialog.addRadioIcons( m_vbox, name, icons, cb );
70 void appendRadioIcons( const char* name, int& data, StringArrayRange icons ){
71 m_dialog.addRadioIcons( m_vbox, name, data, icons );
73 ui::Widget appendEntry( const char* name, ImportExportCallback<int> const &cb ){
74 return m_dialog.addIntEntry( m_vbox, name, cb );
76 ui::Widget appendEntry( const char* name, int& data ){
77 return m_dialog.addEntry( m_vbox, name, data );
79 ui::Widget appendEntry( const char* name, ImportExportCallback<std::size_t> const &cb){
80 return m_dialog.addSizeEntry( m_vbox, name, cb );
82 ui::Widget appendEntry( const char* name, std::size_t& data ){
83 return m_dialog.addEntry( m_vbox, name, data );
85 ui::Widget appendEntry( const char* name, ImportExportCallback<float> const &cb ){
86 return m_dialog.addFloatEntry( m_vbox, name, cb );
88 ui::Widget appendEntry( const char* name, float& data ){
89 return m_dialog.addEntry( m_vbox, name, data );
91 ui::Widget appendPathEntry( const char* name, bool browse_directory, ImportExportCallback<const char *> const &cb ){
92 return m_dialog.addPathEntry( m_vbox, name, browse_directory, cb );
94 ui::Widget appendPathEntry( const char* name, CopiedString& data, bool directory ){
95 return m_dialog.addPathEntry( m_vbox, name, data, directory );
97 ui::SpinButton appendSpinner( const char* name, int& data, double value, double lower, double upper ){
98 return m_dialog.addSpinner( m_vbox, name, data, value, lower, upper );
100 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, ImportExportCallback<int> const &cb ){
101 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
103 ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, ImportExportCallback<float> const &cb ){
104 return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb );
108 typedef Callback<void(PreferencesPage&)> PreferencesPageCallback;
110 class PreferenceGroup
113 virtual PreferencesPage createPage( const char* treeName, const char* frameName ) = 0;
116 typedef Callback<void(PreferenceGroup&)> PreferenceGroupCallback;
118 void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback );
119 void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback );
120 void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback );
121 void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback );
122 void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback );
123 void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback );
125 void PreferencesDialog_restartRequired( const char* staticName );
127 template<typename Value>
132 const char *m_description;
134 LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) {
141 void import(Value value) {
143 if (m_latched != m_value) {
144 PreferencesDialog_restartRequired(m_description);
149 template<class Self, class T = Self>
150 ImportExportCallback<T> mkImportExportCallback(LatchedValue<Self> &self) {
152 MemberCaller<LatchedValue<Self>, void(T), &LatchedValue<Self>::import>(self),
153 ReferenceCaller<Self, void(const Callback<void(T)> &), impexp<Self, T>::Export>(self.m_latched)
158 holds information for a given game
159 I'm a bit unclear on that still
160 it holds game specific configuration stuff
161 such as base names, engine names, some game specific features to activate in the various modules
162 it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
163 support for a new game)
165 what we do now is fully generate the information for this during the setup. We might want to
166 generate a piece that just says "the game pack is there", but put the rest of the config somwhere
167 else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
169 class CGameDescription
171 typedef std::map<CopiedString, CopiedString> GameDescription;
174 CopiedString mGameFile; ///< the .game file that describes this game
175 GameDescription m_gameDescription;
177 CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules
178 CopiedString mGameType; ///< the type of the engine
180 const char* getKeyValue( const char* key ) const {
181 GameDescription::const_iterator i = m_gameDescription.find( key );
182 if ( i != m_gameDescription.end() ) {
183 return ( *i ).second.c_str();
187 const char* getRequiredKeyValue( const char* key ) const {
188 GameDescription::const_iterator i = m_gameDescription.find( key );
189 if ( i != m_gameDescription.end() ) {
190 return ( *i ).second.c_str();
192 ERROR_MESSAGE( "game attribute " << makeQuoted( key ) << " not found in " << makeQuoted( mGameFile.c_str() ) );
196 CGameDescription( xmlDocPtr pDoc, const CopiedString &GameFile );
201 extern CGameDescription *g_pGameDescription;
205 class PreferencesPage;
207 class StringOutputStream;
210 standalone dialog for games selection, and more generally global settings
212 class CGameDialog : public Dialog
216 mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box
221 those settings are saved in the global prefs file
222 I'm too lazy to wrap behind protected access, not sure this needs to be public
223 NOTE: those are preference settings. if you change them it is likely that you would
224 have to restart the editor for them to take effect
228 what game has been selected
229 this is the name of the .game file
231 CopiedString m_sGameFile;
233 prompt which game to load on startup
237 log console to radiant.log
238 m_bForceLogConsole is an obscure forced latching situation
240 bool m_bForceLogConsole;
244 the list of game descriptions we scanned from the game/ dir
246 std::list<CGameDescription*> mGames;
250 m_bGamePrompt( true ),
251 m_bForceLogConsole( false ){
253 virtual ~CGameDialog();
256 intialize the game dialog, called at CPrefsDlg::Init
257 will scan for games, load prefs, and do game selection dialog if needed
262 reset the global settings by removing the file
267 run the dialog UI for the list of games
273 this is only called when the dialog is built at startup for main engine select
275 ui::Window BuildDialog();
277 void GameFileImport( int value );
278 void GameFileExport( const ImportExportCallback<int>::Import_t& importCallback ) const;
281 construction of the dialog frame
282 this is the part to be re-used in prefs dialog
283 for the standalone dialog, we include this in a modal box
284 for prefs, we hook the frame in the main notebook
285 build the frame on-demand (only once)
287 void CreateGlobalFrame( PreferencesPage& page );
290 global preferences subsystem
291 XML-based this time, hopefully this will generalize to other prefs
292 LoadPrefs has hardcoded defaults
293 NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
294 could have named the class differently I guess
297 void LoadPrefs(); ///< load from file into variables
298 void SavePrefs(); ///< save pref variables to file
303 scan for .game files, load them
308 inits g_Preferences.m_global_rc_path
310 void InitGlobalPrefPath();
313 uses m_nComboItem to find the right mGames
315 CGameDescription *GameDescriptionForComboItem();
319 this holds global level preferences
321 extern CGameDialog g_GamesDialog;
326 class PrefsDlg : public Dialog
330 std::list<CGameDescription *> mGames;
334 ui::Widget m_notebook{ui::null};
337 g_string_free( m_rc_path, true );
338 g_string_free( m_inipath, true );
342 path for global settings
344 linux: ~/.radiant/[version]/
346 GString *m_global_rc_path;
349 path to per-game settings
350 used for various game dependant storage
352 linux: ~/.radiant/[version]/[gamename]/
357 holds per-game settings
358 m_rc_path+"local.pref"
359 \todo FIXME at some point this should become XML property bag code too
363 // initialize the above paths
366 /*! Utility function for swapping notebook pages for tree list selections */
367 void showPrefPage( ui::Widget prefpage );
372 ui::Window BuildDialog();
373 void PostModal( EMessageBoxReturn code );
376 extern PrefsDlg g_Preferences;
378 struct preferences_globals_t
380 // disabled all INI / registry read write .. used when shutting down after registry cleanup
382 preferences_globals_t() : disable_ini( false ){
385 extern preferences_globals_t g_preferences_globals;
387 void PreferencesDialog_constructWindow( ui::Window main_window );
388 void PreferencesDialog_destroyWindow();
390 void PreferencesDialog_showDialog();
392 void GlobalPreferences_Init();
393 void Preferences_Init();
395 void Preferences_Load();
396 void Preferences_Save();
398 void Preferences_Reset();