X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=radiant%2Fpreferences.cpp;h=e57380eb1f3a32e071501d901b365762cb4fb417;hp=44f8bfbfc0486ef7d8a279bdc2910667b7281319;hb=832101b1611ef0ae21f2b0bc9854ee8481727b89;hpb=9aa5e96c6320c921a7b1ec69c6315a76a36e228a diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 44f8bfbf..e57380eb 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -1,23 +1,23 @@ /* -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. + Copyright (C) 1999-2006 Id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ // // User preferences @@ -25,3596 +25,972 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Leonardo Zide (leo@lokigames.com) // -#include "stdafx.h" -#include -#include -#include -#if defined (__linux__) || defined (__APPLE__) -#include -#include -#include -#include -#include -#endif -#include "missing.h" -#include "gtkmisc.h" - -#ifdef _WIN32 - // sanity check - some gtk2 win32 runtimes replace sprintf - #if defined( sprintf ) - #error sprintf is a macro. are you sure? - #endif -#endif +#include "preferences.h" +#include "globaldefs.h" -#ifdef _WIN32 -#include -#define X_OK 0 -#include -#endif +#include +#include "environment.h" -#define PREF_SECTION "Prefs" -#define INTERNAL_SECTION "Internals" -#define MOUSE_KEY "MouseButtons" -#define WINDOW_KEY "QE4StyleWindows" -#define LAYOUT_KEY "WindowLayout" -#define RUNQ2_KEY "RunQuake2Run" -#define TLOCK_KEY "TextureLock" -#define RLOCK_KEY "RotateLock" -#define LOADLAST_KEY "LoadLast" -#define LOADLASTMAP_KEY "LoadLastMap" -#define LASTPROJ_KEY "LastProject" -#define LASTPROJVER_KEY "LastProjectKey" -#define LASTMAP_KEY "LastMap" -#define FACE_KEY "NewFaceGrab" -#define BSP_KEY "InternalBSP" -#define RCLICK_KEY "NewRightClick" -#define VERTEX_KEY "NewVertex" -#define AUTOSAVE_KEY "Autosave" -#define AUTOSAVETIME_KEY "AutosaveMinutes" -#define PAK_KEY "UsePAK" -#define NEWAPPLY_KEY "ApplyDismissesSurface" -#define HACK_KEY "Gatewayescapehack" -#define TEXTURE_KEY "NewTextureWindowStuff" -#define TINYBRUSH_KEY "CleanTinyBrushes" -#define TINYSIZE_KEY "CleanTinyBrusheSize" -#define SNAPSHOT_KEY "Snapshots" -#define MOVESPEED_KEY "MoveSpeed" -#define ANGLESPEED_KEY "AngleSpeed" -#define SETGAME_KEY "UseSetGame" -#define CAMXYUPDATE_KEY "CamXYUpdate" -#define CAMDRAGMULTISELECT_KEY "CamDragMultiSelect" -#define CAMFREELOOK_KEY "CamFreeLook" -#define CAMINVERSEMOUSE_KEY "CamInverseMouse" -#define CAMDISCRETE_KEY "CamDiscrete" -#define LIGHTDRAW_KEY "NewLightStyle" -#define WHATGAME_KEY "WhichGame" -#define CUBICCLIP_KEY "CubicClipping" -#define CUBICSCALE_KEY "CubicScale" -#define ALTEDGE_KEY "ALTEdgeDrag" -#define FACECOLORS_KEY "FaceColors" -#define SNAPT_KEY "SnapT" -#define XZVIS_KEY "XZVIS" -#define YZVIS_KEY "YZVIS" -#define ZVIS_KEY "ZVIS" -#define SIZEPAINT_KEY "SizePainting" -#define DLLENTITIES_KEY "DLLEntities" -#define DETACHABLEMENUS_KEY "DetachableMenus" -#define PATCHTOOLBAR_KEY "PatchToolBar" -#define WIDETOOLBAR_KEY "WideToolBar" -#define PLUGINTOOLBAR_KEY "PluginToolBar" -#define NOCLAMP_KEY "NoClamp" -#define SNAP_KEY "Snap" -#define PREFAB_KEY "PrefabPath" -#define USERINI_KEY "UserINIPath" -#define ROTATION_KEY "Rotation" -#define BUGGYICD_KEY "BuggyICD" -#define CHASEMOUSE_KEY "ChaseMouse" -#define ENTITYSHOW_KEY "EntityShow" -#define TEXTURESCALE_KEY "TextureScale" -#define TEXTURESCROLLBAR_KEY "TextureScrollbar" -#define DISPLAYLISTS_KEY "UseDisplayLists" -#define ANTIALIASEDLINES_KEY "UseAntialiasedPointsAndLines" // Fishman - Add antialiazed points and lines support. 09/03/00 -#define NORMALIZECOLORS_KEY "NormalizeColors" -#define SHADERS_KEY "UseShaders" -#define SWITCHCLIP_KEY "SwitchClipKey" -#define SELWHOLEENTS_KEY "SelectWholeEntitiesKey" -#define TEXTURESUBSET_KEY "UseTextureSubsetLoading" -#define TEXTUREQUALITY_KEY "TextureQuality" -#define SHOWSHADERS_KEY "ShowShaders" -#define SHADERTEST_KEY "ShaderTest" -#define GLLIGHTING_KEY "UseGLLighting" -#define LOADSHADERS_KEY "LoadShaders" -#define NOSTIPPLE_KEY "NoStipple" -#define UNDOLEVELS_KEY "UndoLevels" -#define VERTEXMODE_KEY "VertexSplit" -#define ENGINEPATH_KEY "EnginePath" -#define ENGINE_KEY "Engine" -#define LOGCONSOLE_KEY "LogConsole" -#define SELECTCURVES_KEY "SelectCurves" -#define SELECTMODELS_KEY "SelectModels" -#define SHADERLISTONLY_KEY "ShowShaderlistOnly" -#define WATCHBSP_KEY "WatchBSP" -#define LEAKSTOP_KEY "LeakStop" -#define DOSLEEP_KEY "SleepMode" -#define SUBDIVISIONS_KEY "Subdivisions" -#define DEFAULTTEXURESCALE_KEY "DefaultTextureScale" -#define CLIPCAULK_KEY "ClipCaulk" -#define PATCHSHOWBOUNDS_KEY "PatchShowBounds" -#define NATIVEGUI_KEY "NativeGUI" -#define STARTONPRIMMON_KEY "StartOnPrimMon" -#define NOSYSMENUPOPUPS_KEY "NoSysMenuPopups" -#define SNAPTTOGRID_KEY "SnapTToGrid" -#define FLOATINGZ_KEY "FloatingZ" -#define TARGETFIX_KEY "TargetFix" -#define GLPOINTWORKAROUND_KEY "GlPointWorkaround" // Gef: Workaround for broken Kyro * gl driver 25-aug-2001 -#define WHEELINC_KEY "WheelMouseInc" -#define PATCHBBOXSEL_KEY "PatchBBoxSel" -#define LASTLIGHTINTENSITY_KEY "LastLightIntensity" -#define CUSTOMSHADEREDITOR_KEY "UseCustomShaderEditor" -#define CUSTOMSHADEREDITORCOMMAND_KEY "CustomShaderEditorCommand" -#define TEXTURECOMPRESSIONFORMAT_KEY "TextureCompressionFormat" -#define LIGHTRADIUS_KEY "LightRadiuses" -#define Q3MAP2TEX_KEY "Q3Map2Tex" -#define ATIHACK_KEY "ATIHack" - -// window stuff -#define ENTITYSPLIT1_KEY "EntitySplit1" -#define ENTITYSPLIT2_KEY "EntitySplit2" -#define POSITIONX_KEY "PositionX" -#define POSITIONY_KEY "PositionY" -#define ENTITYWND_KEY "EntityWnd" -#define MAPINFOWND_KEY "MapInfoDlg" -#define CAMWND_KEY "CamWnd" -#define ZWND_KEY "ZWnd" -#define XYWND_KEY "XYWnd" -#define XZWND_KEY "XZWnd" -#define YZWND_KEY "YZWnd" -#define PATCHWND_KEY "PatchWnd" -#define SURFACEWND_KEY "SurfaceWnd" -#define ENTITYINFOWND_KEY "EntityInfoDlg" -#define WIDTH_KEY "Width" -#define HEIGHT_KEY "Height" -#define ZWIDTH_KEY "ZWidth" -#define XYHEIGHT_KEY "XYHeight" -#define XYWIDTH_KEY "XYWidth" -#define CAMWIDTH_KEY "CamWidth" -#define CAMHEIGHT_KEY "CamHeight" -#define ZFLOATWIDTH_KEY "ZWidthFloating" -#define STATE_KEY "State" - -// menu stuff -#define COUNT_KEY "Count" -#define FILE_KEY "File" - -//saved info -#define SI_TEXMENU_KEY "SI_TexMenu" -#define SI_GAMMA_KEY "SI_Gamma" -#define SI_COLORS_KEY "SI_Colors" -#define SI_EXCLUDE_KEY "SI_Exclude" -#define SI_INCLUDE_KEY "SI_Include" -#define SI_SURFACE_TEXDEF_KEY "SI_SurfaceTexdef" -#define SI_PATCH_TEXDEF_KEY "SI_PatchTexdef" -#define SI_AXISCOLORS_KEY "SI_AxisColors" -#define SI_SHOWNAMES_KEY "SI_ShowNames" -#define SI_SHOWCOORDS_KEY "SI_ShowCoords" -#define SI_SHOWANGLES_KEY "SI_ShowAngles" -#define SI_SHOWOUTLINES_KEY "SI_ShowOutlines" -#define SI_SHOWAXIS_KEY "SI_ShowAxis" -#define SI_NOSELOUTLINES_KEY "SI_NoSelectedOutlines" -#define SI_OUTLINESTYLE_KEY "SI_OutLineStyle" - -//for texdefs -#define TD_SCALE1_KEY "_Scale1" -#define TD_SCALE2_KEY "_Scale2" -#define TD_SHIFT1_KEY "_Shift1" -#define TD_SHIFT2_KEY "_Shift2" -#define TD_ROTATE_KEY "_Rotate" - -#define MOUSE_DEF 1 -#define WINDOW_DEF 0 -#define RUNQ2_DEF 0 -#define WATCHBSP_DEF 1 -#define TLOCK_DEF 1 -#define LOADLAST_DEF 1 -#define RUN_DEF 0 -#define SUBDIVISIONS_DEF 4 - -void WindowPosition_Parse(window_position_t& m_value, const CString& value) -{ - if(sscanf(value.GetBuffer(), "%d %d %d %d", &m_value.x, &m_value.y, &m_value.w, &m_value.h) != 4) - m_value.x = m_value.y = m_value.w = m_value.h = -1; -} +#include "debugging/debugging.h" -void WindowPosition_Write(const window_position_t& m_value, CString& value) -{ - char buffer[64]; - sprintf(buffer, "%d %d %d %d", m_value.x, m_value.y, m_value.w, m_value.h); - value = buffer; -} +#include "generic/callback.h" +#include "math/vector.h" +#include "string/string.h" +#include "stream/stringstream.h" +#include "os/file.h" +#include "os/path.h" +#include "os/dir.h" +#include "gtkutil/filechooser.h" +#include "gtkutil/messagebox.h" +#include "cmdlib.h" +#include "error.h" +#include "console.h" +#include "xywindow.h" +#include "mainframe.h" +#include "qe3.h" +#include "gtkdlgs.h" -CXMLPropertyBag::CXMLPropertyBag() { - mStrFilename = ""; - mpDoc = NULL; - mbEmpty = false; -} -// generic preference functions -void CXMLPropertyBag::PushAssignment(const char *name, PrefTypes_t type, void *pV) -{ - list::iterator iAssign; - for(iAssign=mPrefAssignments.begin(); iAssign!=mPrefAssignments.end(); iAssign++) - { - if ((*iAssign).mName == name) - { - // we have it already, check anyway - if (pV != (*iAssign).mVal) - { - Sys_FPrintf(SYS_ERR, "PushAssignment, '%s' has different mVal\n", name); - return; - } - } - } - // ok, it's not in our list yet - mPrefAssignments.push_front(CPrefAssignment(name, type, pV)); -} - -xmlNodePtr CXMLPropertyBag::EpairForName(const char *name) -{ - xmlNodePtr ret = NULL; - - xmlNodePtr pNode = mpDocNode->children; - while (pNode != NULL) - { - if(pNode->type == XML_ELEMENT_NODE) - { - xmlAttrPtr tmp_attr_ptr = xmlHasProp(pNode, (xmlChar *)"name"); - if (tmp_attr_ptr != NULL && !strcmp(name, (char *)tmp_attr_ptr->children->content)) - { - if ( ret ) { - Sys_FPrintf( SYS_WRN, "WARNING: dupe property in CXMLPropertyBag::EpairForName '%s'\n", name ); - } else { - ret = pNode; - } - } - } - pNode = pNode->next; - } - return ret; -} - -void CXMLPropertyBag::GetPref(const char *name, Str *pV, const char *V) -{ - xmlNodePtr pNode = EpairForName( name ); - if ( pNode ) - { - if ( pNode->children && pNode->children->content ) { - *pV = pNode->children->content; - } else { - // means the pref exists, and that the value is "" - *pV = ""; - } - } - else - { - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)V); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - } - // push the pref assignment if needed - PushAssignment(name, PREF_STR, pV); -} - -void CXMLPropertyBag::GetPref(const char *name, int *pV, int V) -{ - xmlNodePtr pNode; - if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) - { - *pV = atoi((char *)pNode->children->content); - } - else - { - char s[10]; - sprintf(s, "%d", V); - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - *pV=V; - } - // push the pref assignment if needed - PushAssignment(name, PREF_INT, pV); -} - -void CXMLPropertyBag::GetPref(const char *name, bool *pV, bool V) -{ - xmlNodePtr pNode; - if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) - { - if (!strcmp((char *)pNode->children->content, "true")) - { - *pV = true; - } - else - { - *pV = false; - } - } - else - { - char s[10]; - V ? strcpy(s, "true") : strcpy(s, "false"); - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - *pV=V; - } - // push the pref assignment - PushAssignment(name, PREF_BOOL, pV); -} - -void CXMLPropertyBag::GetPref(const char *name, float *pV, float V) -{ - xmlNodePtr pNode; - if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) - { - *pV = atof((char *)pNode->children->content); - } - else - { - char s[10]; - sprintf(s, "%f", V); - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - *pV=V; - } - // push the pref assignment if needed - PushAssignment(name, PREF_FLOAT, pV); -} - -void CXMLPropertyBag::GetPref(const char *name, float* pV, float* V) -{ - xmlNodePtr pNode; - if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) - { - sscanf((char *)pNode->children->content, "%f %f %f", &pV[0], &pV[1], &pV[2]); - } - else - { - char s[128]; - sprintf(s, "%f %f %f", V[0], V[1], V[2]); - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - pV[0] = V[0]; - pV[1] = V[1]; - pV[2] = V[2]; - } - // push the pref assignment if needed - PushAssignment(name, PREF_VEC3, pV); -} - -void CXMLPropertyBag::GetPref(const char *name, window_position_t* pV, window_position_t V) -{ - xmlNodePtr pNode; - if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) - { - WindowPosition_Parse(*pV, CString((xmlChar *)pNode->children->content)); - } - else - { - CString str; - WindowPosition_Write(V, str); - pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)str.GetBuffer()); - xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); - *pV = V; - } - // push the pref assignment if needed - PushAssignment(name, PREF_WNDPOS, pV); -} - -void CXMLPropertyBag::UpdatePrefTree() -{ - // read the assignments and update the tree - list::iterator iPref; - for(iPref = mPrefAssignments.begin(); iPref != mPrefAssignments.end(); iPref++) - { - CPrefAssignment *pPref = &(*iPref); - // look for the node - xmlNodePtr pNode; - char s[64]; - - pNode = EpairForName(pPref->mName.GetBuffer()); - // we never expect that the node could not be found, because this is supposed to happen - // after the tree was built with GetPref calls, never on a blank tree - if (!pNode) - { - Sys_FPrintf(SYS_ERR, "Unexpected EpairForName '%s' not found in UpdatePrefTree\n", pPref->mName.GetBuffer()); - return; - } - switch ((*iPref).mType) - { - case PREF_STR: - xmlNodeSetContent(pNode, (const xmlChar *)((Str *)pPref->mVal)->GetBuffer()); - break; - case PREF_INT: - sprintf(s, "%d", *(int *)pPref->mVal); - xmlNodeSetContent(pNode, (xmlChar *)s); - break; - case PREF_FLOAT: - sprintf(s, "%f", *(float *)pPref->mVal); - xmlNodeSetContent(pNode, (xmlChar *)s); - break; - case PREF_BOOL: - *(bool *)pPref->mVal ? strcpy(s, "true") : strcpy(s, "false"); - xmlNodeSetContent(pNode, (xmlChar *)s); - break; - case PREF_VEC3: - { - float* v = (float*)pPref->mVal; - sprintf(s, "%f %f %f", v[0], v[1], v[2]); - xmlNodeSetContent(pNode, (xmlChar *)s); - } - break; - case PREF_WNDPOS: - { - CString str; - WindowPosition_Write(*(window_position_t*)pPref->mVal, str); - xmlNodeSetContent(pNode, (xmlChar*)str.GetBuffer()); - } - break; - } - } -} - -void CXMLPropertyBag::Clear() -{ - if(!InUse()) - return; - - xmlFreeDoc(mpDoc); - mpDoc = NULL; - mpDocNode = NULL; - mbEmpty = false; +void Global_constructPreferences( PreferencesPage& page ){ + page.appendCheckBox( "Console", "Enable Logging", g_Console_enableLogging ); } -void CXMLPropertyBag::ReadXMLFile(const char* pFilename) -{ - mpDoc = xmlParseFile(pFilename); - - // basic checks - if (mpDoc) - { - mpDocNode = mpDoc->children; - xmlAttrPtr tmp_attr_ptr = xmlHasProp(mpDocNode, (xmlChar *)"version"); - if (strcmp((char *)mpDocNode->name, "qpref")) - { - Sys_FPrintf(SYS_ERR, "Unrecognized node '%s' in '%s'\n", mpDocNode->name, mpDoc->URL); - xmlFreeDoc(mpDoc); - mpDoc = NULL; - } - else if (tmp_attr_ptr != NULL && strcmp((char*)tmp_attr_ptr->children->content, "1")) - { - Sys_FPrintf(SYS_ERR, "Wrong version '%s' in node for '%s'\n", (char*)tmp_attr_ptr->children->content, mpDoc->URL); - xmlFreeDoc(mpDoc); - mpDoc = NULL; - } - Sys_Printf("Opened XML property file: '%s'\n", pFilename); - } - - if (!mpDoc) - { - mbEmpty = true; - // no document, create one - mpDoc = xmlNewDoc((xmlChar *)"1.0"); - mpDocNode = xmlNewDocNode(mpDoc, NULL, (xmlChar *)"qpref", NULL); - xmlDocSetRootElement(mpDoc, mpDocNode); - xmlSetProp(mpDocNode, (xmlChar *)"version", (xmlChar *)"1"); - Sys_Printf("XML property file '%s' invalid/not found, creating blank properties tree\n", pFilename); - } -} - -qboolean CXMLPropertyBag::WriteXMLFile(const char* pFilename) -{ - int res = xmlSaveFormatFile(pFilename, mpDoc, 1); - - if(res == -1) - return false; +void Interface_constructPreferences( PreferencesPage& page ){ +#if GDEF_OS_WINDOWS + page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor ); +#else + { + ui::CheckButton use_custom = page.appendCheckBox( "Text Editor", "Custom", g_TextEditor_useCustomEditor ); + ui::Widget custom_editor = page.appendPathEntry( "Text Editor Command", g_TextEditor_editorCommand, true ); + Widget_connectToggleDependency( custom_editor, use_custom ); + } +#endif +} - Sys_Printf("Wrote XML property file '%s'\n", pFilename); - return true; +void Mouse_constructPreferences( PreferencesPage& page ){ + { + const char* buttons[] = { "2 button", "3 button", }; + page.appendRadio( "Mouse Type", g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE( buttons ) ); + } + page.appendCheckBox( "Right Button", "Activates Context Menu", g_xywindow_globals.m_bRightClick ); +} +void Mouse_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Mouse", "Mouse Preferences" ) ); + Mouse_constructPreferences( page ); +} +void Mouse_registerPreferencesPage(){ + PreferencesDialog_addInterfacePage( makeCallbackF(Mouse_constructPage) ); } -// ============================================================================= -// Widget callbacks for PrefsDlg -#if !defined(WIN32) -// browse for custom editor executable -static void OnBtnBrowseEditor (GtkWidget *widget, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; +/*! + ========================================================= + Games selection dialog + ========================================================= + */ - const char *filename = file_dialog(g_PrefsDlg.GetWidget(), TRUE, _("Executable for Custom Editor")); +#include +#include - if(filename != NULL) - { - dlg->m_strEditorCommand = filename; - dlg->UpdateData(FALSE); - } +inline const char* xmlAttr_getName( xmlAttrPtr attr ){ + return reinterpret_cast( attr->name ); } -#endif -static void OnBtnBrowseprefab (GtkWidget *widget, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; - char *path = dlg->m_strPrefabPath; - if (strlen (path) == 0) - path = g_strGameToolsPath; - char *dir = dir_dialog (g_PrefsDlg.GetWidget (), _("Set prefab path"), path); - dlg->UpdateData(TRUE); - - if (dir != NULL) - { - CString strPath; - strPath = dir; - AddSlash(strPath); - dlg->m_strPrefabPath = strPath; - dlg->UpdateData(FALSE); - free (dir); - } -} - -static void OnBtnBrowseuserini (GtkWidget *widget, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; - char *path = dlg->m_strUserPath; - if (strlen (path) == 0) - path = g_strGameToolsPath; - // TODO: INI filter? - const char *filename = file_dialog (g_PrefsDlg.GetWidget(), TRUE, _("Find INI file"), path); - - if (filename != NULL) - { - dlg->UpdateData(TRUE); - dlg->m_strUserPath = filename; - dlg->UpdateData(FALSE); - } -} - -static void OnButtonClean (GtkWidget *widget, gpointer data) -{ - // make sure this is what the user wants - if (gtk_MessageBox (g_PrefsDlg.GetWidget (), _("This will close Radiant and clean the corresponding registry entries.\n" - "Next time you start Radiant it will be good as new. Do you wish to continue?"), - _("Reset Registry"), MB_YESNO) == IDYES) - { - PrefsDlg *dlg = (PrefsDlg*)data; - dlg->EndModal (IDCANCEL); - - g_qeglobals.disable_ini = true; - remove (dlg->m_inipath->str); - char buf[PATH_MAX]; - sprintf(buf, "%sSavedInfo.bin", dlg->m_rc_path->str); - remove(buf); - HandleCommand (NULL, GINT_TO_POINTER (ID_FILE_EXIT)); - _exit (0); - } +inline const char* xmlAttr_getValue( xmlAttrPtr attr ){ + return reinterpret_cast( attr->children->content ); } -// ============================================================================= -// PrefsDlg class +CGameDescription::CGameDescription( xmlDocPtr pDoc, const CopiedString& gameFile ){ + // read the user-friendly game name + xmlNodePtr pNode = pDoc->children; -// IMPORTANT NOTE: the values here don't matter very much -// the actual intialization if you start with an empty .ini is done when loading the prefs for the first time -// profile_load_int takes an argument to use if the value is not found -PrefsDlg::PrefsDlg () -{ - m_bWarn = TRUE; - m_nMouse = 1; - m_nView = MainFrame::eRegular; - m_bLoadLast = FALSE; - m_bInternalBSP = FALSE; - m_bRightClick = FALSE; - m_bSetGame = FALSE; - m_bAutoSave = TRUE; - m_nAutoSave = 5; - m_bLoadLastMap = FALSE; - m_bTextureWindow = FALSE; - m_bSnapShots = FALSE; - m_fTinySize = 0.5; - m_bCleanTiny = FALSE; - m_bCamXYUpdate = TRUE; - m_bCamDragMultiSelect = FALSE; - m_bCamFreeLook = TRUE; - m_bCamFreeLookStrafe = FALSE; - m_bCamInverseMouse = FALSE; - m_bCamDiscrete = TRUE; - m_bNewLightDraw = FALSE; - m_strPrefabPath = ""; - m_nWhatGame = 0; - m_bALTEdge = FALSE; - m_bFaceColors = FALSE; - m_bXZVis = FALSE; - m_bYZVis = FALSE; - m_bZVis = FALSE; - m_bSizePaint = FALSE; - m_bDLLEntities = FALSE; -#ifdef _WIN32 - m_bDetachableMenus = FALSE; // Most win32 users will find detachable menus annoying -#else - m_bDetachableMenus = TRUE; // Linux/Apple users are used to them... -#endif - m_bPatchToolbar = TRUE; - m_bWideToolbar = TRUE; - m_bPluginToolbar = TRUE; - m_bNoClamp = FALSE; - m_bSnap = TRUE; - m_strUserPath = ""; - m_nRotation = 0; - m_bChaseMouse = FALSE; - m_bTextureScrollbar = TRUE; - m_bDisplayLists = TRUE; - m_bAntialiasedPointsAndLines = FALSE; // Fishman - Add antialiazed points and lines support. 09/03/00 - m_bShowShaders = FALSE; - m_nShader = -1; - m_bNoStipple = FALSE; - m_bVertexSplit = FALSE; - m_bSelectCurves = TRUE; - m_bSelectModels = TRUE; - m_nEntityShowState = ENTITY_SKINNED_BOXED; - m_nTextureScale = 2; - m_bSwitchClip = FALSE; - m_bSelectWholeEntities = TRUE; - m_nTextureQuality = 3; - m_bShowShaders = TRUE; - m_bGLLighting = FALSE; - m_nShader = 0; - m_nUndoLevels = 30; - m_bTexturesShaderlistOnly = FALSE; - // paths to ini files - m_rc_path = NULL; - m_inipath = NULL; - m_bWatchBSP = TRUE; - m_bLeakStop = TRUE; - m_iTimeout = 15; - m_bRunQuake = TRUE; - m_bDoSleep = FALSE; - m_nSubdivisions = 4; - // not prefs - m_bFloatingZ = FALSE; - m_bGlPtWorkaround = FALSE; // Gef: Kyro/GL_POINTS workaround 25-aug-2001 -#ifdef _WIN32 - m_bNativeGUI = FALSE; - m_bStartOnPrimMon = FALSE; -#endif - m_global_rc_path = NULL; -#ifdef _WIN32 - m_bUseWin32Editor = TRUE; -#else - // custom shader editor options - m_bUseCustomEditor = FALSE; - m_strEditorCommand = ""; -#endif - m_nLightRadiuses = 1; - m_bQ3Map2Texturing = TRUE; -#ifdef ATIHACK_812 - m_bGlATIHack = FALSE; -#endif -} - -/*! -========================================================= -Games selection dialog -========================================================= -*/ - -#if defined(WIN32) -#define TOOLS_ATTRIBUTE "gametools_win32" -#define ENGINE_ATTRIBUTE "engine_win32" -#define ENGINEPATH_ATTRIBUTE "enginepath_win32" -#define MP_ENGINE_ATTRIBUTE "mp_engine_win32" -#elif defined(__linux__) || defined (__FreeBSD__) -#define TOOLS_ATTRIBUTE "gametools_linux" -#define ENGINE_ATTRIBUTE "engine_linux" -#define ENGINEPATH_ATTRIBUTE "enginepath_linux" -#define MP_ENGINE_ATTRIBUTE "mp_engine_linux" -#elif defined(__APPLE__) -#define TOOLS_ATTRIBUTE "gametools_macos" -#define ENGINE_ATTRIBUTE "engine_macos" -#define ENGINEPATH_ATTRIBUTE "enginepath_macos" -#define MP_ENGINE_ATTRIBUTE "mp_engine_macos" -#else -#error "unsupported platform" -#endif - -CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile) -{ - char *p, *prop; - mpDoc = pDoc; - // read the user-friendly game name - xmlNodePtr pNode = mpDoc->children; - - while (strcmp((const char*)pNode->name, "game") && pNode != NULL) pNode=pNode->next; - if (!pNode) - { - ///< \todo add the file name (this node and gametools should all be part of CGameDescription anyway) - Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL); - } - // on win32, game tools path can now be specified relative to the exe's cwd - prop = (char*)xmlGetProp( pNode, (xmlChar*)TOOLS_ATTRIBUTE); - if ( prop == NULL ) { - Error( "Didn't find '"TOOLS_ATTRIBUTE"' node in the game description file '%s'\n", pDoc->URL ); - } - { - char full[PATH_MAX]; -#ifdef _WIN32 - _fullpath( full, prop, PATH_MAX ); -#else - strncpy( full, prop, PATH_MAX ); -#endif - xmlFree( prop ); - prop = NULL; - for ( p = full; *p != '\0'; p++ ) { - if ( *p == '\\' ) { - *p = '/'; - } - mGameToolsPath = full; - if ( p != full && *(p-1) != '/' ) { - mGameToolsPath += "/"; - } - } - } - - prop = (char*)xmlGetProp(pNode, (xmlChar*)"name"); - if (prop == NULL) - { - Sys_FPrintf(SYS_WRN, "Warning, 'name' attribute not found in '%s'\n", pDoc->URL); - mGameName = pDoc->URL; - } - else - { - mGameName = prop; - xmlFree(prop); - } - - mGameFile = GameFile; - - prop = (char*)xmlGetProp(pNode, (xmlChar*)"quake2"); - if (prop == NULL) - { - // default - quake2 = false; - } - else - { - quake2 = true; - xmlFree(prop); - } - - // if this is set, the open maps dialoge will open the engine path not the - // home dir for map loading and saving - prop = (char*)xmlGetProp(pNode, (xmlChar*)"no_maps_in_home"); - if (prop == NULL) - { - // default - noMapsInHome = false; - } - else - { - noMapsInHome = true; - xmlFree(prop); - } - - prop = (char*)xmlGetProp(pNode, (xmlChar*)"basegame"); - if (prop == NULL) - { - // default - mBaseGame = "baseq3"; - } - else - { - mBaseGame = prop; - xmlFree(prop); - } - - - prop = (char*)xmlGetProp(pNode, (const xmlChar*)ENGINE_ATTRIBUTE); - if (prop == NULL) + while ( strcmp( (const char*)pNode->name, "game" ) && pNode != 0 ) { -#ifdef _WIN32 - mEngine = "quake3.exe"; -#elif __linux__ - mEngine = "quake3"; -#elif __APPLE__ - mEngine = "Quake3.app"; -#endif + pNode = pNode->next; } - else - { - mEngine = prop; - xmlFree(prop); + if ( !pNode ) { + Error( "Didn't find 'game' node in the game description file '%s'\n", pDoc->URL ); } - prop = (char*)xmlGetProp(pNode, (const xmlChar*)MP_ENGINE_ATTRIBUTE); - if (prop == NULL) + for ( xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next ) { -#ifdef _WIN32 - mMultiplayerEngine = "quake3.exe"; -#elif __linux__ - mMultiplayerEngine = "quake3"; -#elif __APPLE__ - mMultiplayerEngine = "Quake3.app"; -#endif + m_gameDescription.insert( GameDescription::value_type( xmlAttr_getName( attr ), xmlAttr_getValue( attr ) ) ); } - else + { - mMultiplayerEngine = prop; - xmlFree(prop); + StringOutputStream path( 256 ); + path << DataPath_get() << "gamepacks/" << gameFile.c_str() << "/"; + mGameToolsPath = path.c_str(); } + ASSERT_MESSAGE( file_exists( mGameToolsPath.c_str() ), "game directory not found: " << makeQuoted( mGameToolsPath.c_str() ) ); + + mGameFile = gameFile; + { - // on win32, engine path can now be specified relative to the exe's cwd - prop = (char*)xmlGetProp(pNode, (const xmlChar *)ENGINEPATH_ATTRIBUTE); - if ( prop != NULL ) { - char full[PATH_MAX]; - #ifdef _WIN32 - _fullpath( full, prop, PATH_MAX ); - #else - strncpy( full, prop, PATH_MAX ); - #endif - xmlFree( prop ); - prop = NULL; - // process seperators - for ( p = full; *p != '\0'; p++ ) { - if ( *p == '\\' ) { - *p = '/'; - } - } - mEnginePath = full; - if ( p != full && *(p-1) != '/' ) { - mEnginePath += "/"; - } + GameDescription::iterator i = m_gameDescription.find( "type" ); + if ( i == m_gameDescription.end() ) { + globalErrorStream() << "Warning, 'type' attribute not found in '" << reinterpret_cast( pDoc->URL ) << "'\n"; + // default + mGameType = "q3"; } else { - // if engine path was not specified in the .game, it implies we can guess it from the gametools path - // on win32, and for most game package, the gametools are installed with the game - char aux_path[PATH_MAX]; // aux - strcpy( aux_path, mGameToolsPath.GetBuffer() ); - if ( ( aux_path[ strlen(aux_path)-1 ] == '/' ) || ( aux_path[ strlen(aux_path)-1 ] == '\\' ) ) { - aux_path[strlen(aux_path)-1] = '\0'; // strip ending '/' if any + mGameType = ( *i ).second.c_str(); + } + } +} + +void CGameDescription::Dump(){ + globalOutputStream() << "game description file: " << makeQuoted( mGameFile.c_str() ) << "\n"; + for ( GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i ) + { + globalOutputStream() << ( *i ).first.c_str() << " = " << makeQuoted( ( *i ).second.c_str() ) << "\n"; + } +} + +CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentDescription + + +#include "warnings.h" +#include "stream/textfilestream.h" +#include "container/array.h" +#include "xml/ixml.h" +#include "xml/xmlparser.h" +#include "xml/xmlwriter.h" + +#include "preferencedictionary.h" +#include "stringio.h" + +const char* const PREFERENCES_VERSION = "1.0"; + +bool Preferences_Load( PreferenceDictionary& preferences, const char* filename, const char *cmdline_prefix ){ + bool ret = false; + TextFileInputStream file( filename ); + if ( !file.failed() ) { + XMLStreamParser parser( file ); + XMLPreferenceDictionaryImporter importer( preferences, PREFERENCES_VERSION ); + parser.exportXML( importer ); + ret = true; + } + + int l = strlen( cmdline_prefix ); + for ( int i = 1; i < g_argc - 1; ++i ) + { + if ( g_argv[i][0] == '-' ) { + if ( !strncmp( g_argv[i] + 1, cmdline_prefix, l ) ) { + if ( g_argv[i][l + 1] == '-' ) { + preferences.importPref( g_argv[i] + l + 2, g_argv[i + 1] ); + } } - char up_path[PATH_MAX]; // up one level - ExtractFilePath( aux_path, up_path ); - mEnginePath = up_path; + ++i; } } -#if defined (__linux__) || defined (__APPLE__) - // *nix specific - prop = (char*)xmlGetProp(pNode, (const xmlChar *)"prefix"); - if(prop != NULL) - { - mUserPathPrefix = prop; - xmlFree(prop); - } -#endif - mShaderPath = xmlGetProp(pNode, (const xmlChar *)"shaderpath"); - if (!mShaderPath.GetLength()) - { - mShaderPath = "scripts/"; - mShaderlist = "scripts/shaderlist.txt"; - } - else - { - AddSlash(mShaderPath); - mShaderlist = mShaderPath; - mShaderlist += "shaderlist.txt"; - } - xmlChar* default_scale = xmlGetProp(pNode, (const xmlChar *)"default_scale"); - if (default_scale) - { - mTextureDefaultScale = atof((const char *)default_scale); - xmlFree(default_scale); - } - else - mTextureDefaultScale = 0.5f; - xmlChar* eclass_singleload = xmlGetProp(pNode, (const xmlChar*)"eclass_singleload"); - if (eclass_singleload) - { - mEClassSingleLoad = true; - xmlFree(eclass_singleload); - } - else - mEClassSingleLoad = false; - xmlChar* no_patch = xmlGetProp(pNode, (const xmlChar *)"no_patch"); - if (no_patch) - { - mNoPatch = true; - xmlFree(no_patch); - } - else - mNoPatch = false; - xmlChar* caulk_shader = xmlGetProp(pNode, (const xmlChar *)"caulk_shader"); - if (caulk_shader) - { - mCaulkShader = caulk_shader; - xmlFree(caulk_shader); - } - else - mCaulkShader = "textures/common/caulk"; -} - -void CGameDescription::Dump() -{ -#ifdef _WIN32 - if (CGameDialog::GetNetrun()) - Sys_Printf("Running in network mode, prefs path set to '%s'\n", g_strTempPath.GetBuffer()); -#endif - Sys_Printf("game name : '%s'\n", mGameName.GetBuffer()); - Sys_Printf("game file : '%s'\n", mGameFile.GetBuffer()); - Sys_Printf("game path : '%s'\n", mGameToolsPath.GetBuffer()); - Sys_Printf("base game : '%s'\n", mBaseGame.GetBuffer()); - Sys_Printf("engine path : '%s'\n", mEnginePath.GetBuffer()); - Sys_Printf("engine : '%s'\n", mEngine.GetBuffer()); - Sys_Printf("shaderlist : '%s'\n", mShaderlist.GetBuffer()); - Sys_Printf("caulk shader: '%s'\n", mCaulkShader.GetBuffer()); -#if defined (__linux__) || defined (__APPLE__) - Sys_Printf("prefix : '%s'\n", mUserPathPrefix.GetBuffer()); -#endif - Sys_Printf("default texture scale: %g\n", mTextureDefaultScale); - Sys_Printf("single eclass load : %s\n", mEClassSingleLoad ? "Yes" : "No"); - Sys_Printf("patches supported : %s\n", mNoPatch ? "No" : "Yes"); + return ret; } -CPrefAssignment& CPrefAssignment::operator = (const CPrefAssignment& ass) -{ - if (&ass != this) - { - mName = ass.mName; - mType = ass.mType; - mVal = ass.mVal; - } - return *this; +bool Preferences_Save( PreferenceDictionary& preferences, const char* filename ){ + TextFileOutputStream file( filename ); + if ( !file.failed() ) { + XMLStreamWriter writer( file ); + XMLPreferenceDictionaryExporter exporter( preferences, PREFERENCES_VERSION ); + exporter.exportXML( writer ); + return true; + } + return false; } -CPrefAssignment::CPrefAssignment(const CPrefAssignment& ass) -{ - *this = ass; +bool Preferences_Save_Safe( PreferenceDictionary& preferences, const char* filename ){ + std::string tmpName( filename ); + tmpName += "TMP"; + + return Preferences_Save( preferences, tmpName.c_str() ) + && ( !file_exists( filename ) || file_remove( filename ) ) + && file_move( tmpName.data(), filename ); } -void CGameDialog::LoadPrefs() -{ - // if we already have a document loaded, we will free and reload from file - if (mGlobalPrefs.InUse()) - { - Sys_Printf("Reloading global prefs from file\n"); - mGlobalPrefs.Clear(); - } - - // load global .pref file - CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; - strGlobalPref += "global.pref"; - - mGlobalPrefs.ReadXMLFile(strGlobalPref.GetBuffer()); - - mGlobalPrefs.GetPref("gamefile", &m_sGameFile, ""); // NOTE: there's no default, user HAS to select something - mGlobalPrefs.GetPref("autoload", &m_bAutoLoadGame, false); - mGlobalPrefs.GetPref("log console", &m_bLogConsole, false); - // in a very particular post-.pid startup - // we may have the console turned on and want to keep it that way - // so we use a latching system - if (m_bForceLogConsole) - { - m_bLogConsole = true; - Sys_Printf("console logging has been latched on, saving prefs\n"); - SavePrefs(); - m_bForceLogConsole = false; - } - - // console logging: call Sys_LogConsole to check console logging status - // it is important that we would log console as early as possible to make it useful - Sys_LogFile(); - - if (mGlobalPrefs.mbEmpty) - { - Sys_Printf("Saving global.pref with default pref values\n"); - SavePrefs(); - } -} - -void CGameDialog::SavePrefs() -{ - // update the tree and save it - mGlobalPrefs.UpdatePrefTree(); - CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; - strGlobalPref += "global.pref"; +struct LogConsole { + static void Export(const Callback &returnz) { + returnz(g_Console_enableLogging); + } + + static void Import(bool value) { + g_Console_enableLogging = value; + Sys_LogFile(g_Console_enableLogging); + } +}; + - if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) { - Sys_FPrintf(SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer()); - } +void RegisterGlobalPreferences( PreferenceSystem& preferences ){ + preferences.registerPreference( "gamefile", make_property_string( g_GamesDialog.m_sGameFile ) ); + preferences.registerPreference( "gamePrompt", make_property_string( g_GamesDialog.m_bGamePrompt ) ); + preferences.registerPreference( "skipGamePromptOnce", make_property_string( g_GamesDialog.m_bSkipGamePromptOnce ) ); + preferences.registerPreference( "log console", make_property_string() ); } -void CGameDialog::DoGameInstall() { - // make sure console logging is on whenever we enter the installation loop - g_PrefsDlg.mGamesDialog.m_bLogConsole = true; - Sys_LogFile(); - mGameInstall.Run(); + +PreferenceDictionary g_global_preferences; + +void GlobalPreferences_Init(){ + RegisterGlobalPreferences( g_global_preferences ); } -void CGameDialog::DoGameDialog() { - // allow looping the game selection dialog with calls to the game configure dialog in between - while ( m_bDoGameInstall ) { +void CGameDialog::LoadPrefs(){ + // load global .pref file + StringOutputStream strGlobalPref( 256 ); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; - m_bDoGameInstall = false; + globalOutputStream() << "loading global preferences from " << makeQuoted( strGlobalPref.c_str() ) << "\n"; - if ( DoModal() == IDCANCEL ) { - Error( "game selection dialog canceled, cannot continue" ); - return; - } + if ( !Preferences_Load( g_global_preferences, strGlobalPref.c_str(), "global" ) ) { + globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n"; + } +} - if ( m_bDoGameInstall ) { - DoGameInstall(); - ScanForGames(); - // and we will loop to do another DoModal dialog - } +void CGameDialog::SavePrefs(){ + StringOutputStream strGlobalPref( 256 ); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; + + globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n"; + + if ( !Preferences_Save_Safe( g_global_preferences, strGlobalPref.c_str() ) ) { + globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n"; } +} - // unhook so we can use in other places - // we manually incref'ed it when creating, it won't be freed (destructor) - gtk_container_remove( GTK_CONTAINER( mTopBox ), GetGlobalFrame() ); +void CGameDialog::DoGameDialog(){ + // show the UI + DoModal(); // we save the prefs file SavePrefs(); } -GtkWidget* CGameDialog::GetGlobalFrame() -{ - GtkWidget *vbox, *text, *combo, *check; - - if ( mFrame != NULL ) { - return mFrame; - } - - mFrame = gtk_frame_new( NULL ); - gtk_container_set_border_width( GTK_CONTAINER( mFrame ), 5 ); - gtk_widget_show( mFrame ); - - vbox = gtk_vbox_new( FALSE, 6 ); - gtk_widget_show( vbox ); - gtk_container_add( GTK_CONTAINER( mFrame ), vbox ); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - text = gtk_label_new( _("Select the game:") ); - gtk_widget_show( text ); - gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 ); - - combo = gtk_combo_box_new_text(); - gtk_widget_show( combo ); - gtk_box_pack_start( GTK_BOX( vbox ), combo, FALSE, FALSE, 0 ); - AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT ); - mGameCombo = GTK_COMBO_BOX( combo ); - - UpdateGameCombo(); - - check = gtk_check_button_new_with_label( _("Auto load selected game on startup") ); - gtk_widget_show(check); - gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bAutoLoadGame, DLG_CHECK_BOOL); - - text = gtk_label_new(_("(this frame is available in the prefs menu if you set auto-select)")); - gtk_widget_show(text); - gtk_box_pack_start (GTK_BOX(vbox), text, FALSE, FALSE, 0); - -#ifdef _WIN32 - check = gtk_check_button_new_with_label( _("Networked install - per-user settings") ); - gtk_widget_show( check ); - gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); - AddDialogData( check, &m_bNetRun, DLG_CHECK_BOOL ); -#endif +void CGameDialog::GameFileImport( int value ){ + m_nComboSelect = value; + // use value to set m_sGameFile + std::list::iterator iGame = mGames.begin(); + int i; + for ( i = 0; i < value; i++ ) + { + ++iGame; + } - check = gtk_check_button_new_with_label( _("Log the console to radiant.log") ); - gtk_widget_show( check ); - gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); - AddDialogData( check, &m_bLogConsole, DLG_CHECK_BOOL ); - - // incref it so we can pass it around - gtk_widget_ref( GTK_WIDGET( mFrame ) ); - - return mFrame; -} - -void CGameDialog::UpdateData( bool retrieve ) { - if (!retrieve) - { - // use m_sGameFile to set m_nComboSelect - list::iterator iGame; - int i = 0; - for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) - { - if ((*iGame)->mGameFile == m_sGameFile) - { - m_nComboSelect = i; - break; - } - i++; - } -#ifdef _WIN32 - UpdateNetrun(false); -#endif - } - Dialog::UpdateData(retrieve); - if (retrieve) - { - // use m_nComboSelect to set m_sGameFile - list::iterator iGame = mGames.begin(); - int i; - for(i=0; imGameFile; -#ifdef _WIN32 - UpdateNetrun(true); -#endif - } -} + if ( ( *iGame )->mGameFile != m_sGameFile ) { + m_sGameFile = ( *iGame )->mGameFile; + + // do not trigger radiant restart when switching game on startup using Global Preferences dialog + if ( !onStartup ) { + PreferencesDialog_restartRequired( "Selected Game" ); + } + } -void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) { - CGameDialog *d = static_cast< CGameDialog* >( data ); - d->m_bDoGameInstall = true; - d->EndModal( 0 ); + // onStartup can only be true once, when Global Preferences are displayed at startup + onStartup = false; } -void CGameDialog::BuildDialog() { - GtkWidget *dlg, *vbox1, *button, *setup_button; +void CGameDialog::GameFileExport( const Callback & importCallback ) const { + // use m_sGameFile to set value + std::list::const_iterator iGame; + int i = 0; + for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) + { + if ( ( *iGame )->mGameFile == m_sGameFile ) { + m_nComboSelect = i; + break; + } + i++; + } + importCallback( m_nComboSelect ); +} - dlg = m_pWidget; - gtk_window_set_title( GTK_WINDOW( dlg ), _("Select Game") ); +struct CGameDialog_GameFile { + static void Export(const CGameDialog &self, const Callback &returnz) { + self.GameFileExport(returnz); + } - vbox1 = gtk_vbox_new( FALSE, 0 ); - gtk_widget_show( vbox1 ); - gtk_container_add( GTK_CONTAINER( dlg ), vbox1 ); + static void Import(CGameDialog &self, int value) { + self.GameFileImport(value); + } +}; - gtk_container_add( GTK_CONTAINER( vbox1 ), GetGlobalFrame() ); - mTopBox = vbox1; +void CGameDialog::CreateGlobalFrame( PreferencesPage& page ){ + std::vector games; + games.reserve( mGames.size() ); + for ( std::list::iterator i = mGames.begin(); i != mGames.end(); ++i ) + { + games.push_back( ( *i )->getRequiredKeyValue( "name" ) ); + } + page.appendCombo( + "Select the game", + StringArrayRange( &( *games.begin() ), &( *games.end() ) ), + make_property(*this) + ); + page.appendCheckBox( "Startup", "Show Global Preferences", m_bGamePrompt ); +} - setup_button = gtk_button_new_with_label( _("Configure more games") ); - gtk_widget_show( setup_button ); - gtk_box_pack_start( GTK_BOX( vbox1 ), setup_button, FALSE, FALSE, 0 ); - gtk_signal_connect( GTK_OBJECT( setup_button ), "clicked", - GTK_SIGNAL_FUNC( SInstallCallback ), this ); +ui::Window CGameDialog::BuildDialog(){ + auto frame = create_dialog_frame( "Game settings", ui::Shadow::ETCHED_IN ); - button = gtk_button_new_with_label( _("OK") ); - gtk_widget_show( button ); - gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); - AddModalButton( button, IDOK ); + auto vbox2 = create_dialog_vbox( 0, 4 ); + frame.add(vbox2); - button = gtk_button_new_with_label( _("Cancel") ); - gtk_widget_show( button ); - gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); - AddModalButton( button, IDCANCEL ); + { + PreferencesPage preferencesPage( *this, vbox2 ); + Global_constructPreferences( preferencesPage ); + CreateGlobalFrame( preferencesPage ); + } - gtk_widget_set_usize( button, 60, -2 ); + return create_simple_modal_dialog_window( "Global Preferences", m_modal, frame ); } -void CGameDialog::UpdateGameCombo() { - // fill in with the game descriptions - list::iterator iGame; +void CGameDialog::ScanForGames(){ + StringOutputStream strGamesPath( 256 ); + strGamesPath << DataPath_get() << "gamepacks/games/"; + const char *path = strGamesPath.c_str(); - if ( mGameCombo == NULL ) { - Sys_Printf( "mGameCombo == NULL\n" ); - return; - } + globalOutputStream() << "Scanning for game description files: " << path << '\n'; - // clear whatever is in - wtf no way to know how many text entries? - // use set/get active to track - gtk_combo_box_set_active( mGameCombo, 0 ); - while ( gtk_combo_box_get_active( mGameCombo ) == 0 ) { - gtk_combo_box_remove_text( mGameCombo, 0 ); - gtk_combo_box_set_active( mGameCombo, 0 ); - } + /*! + \todo FIXME LINUX: + do we put game description files below AppPath, or in ~/.radiant + i.e. read only or read/write? + my guess .. readonly cause it's an install + we will probably want to add ~/.radiant//games/ scanning on top of that for developers + (if that's really needed) + */ - for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { - gtk_combo_box_append_text( mGameCombo, (*iGame)->mGameName.GetBuffer() ); - } - gtk_combo_box_set_active( mGameCombo, 0 ); + Directory_forEach(path, [&](const char *name) { + if (!extension_equal(path_get_extension(name), "game")) { + return; + } + StringOutputStream strPath(256); + strPath << path << name; + globalOutputStream() << strPath.c_str() << '\n'; + + xmlDocPtr pDoc = xmlParseFile(strPath.c_str()); + if (pDoc) { + mGames.push_front(new CGameDescription(pDoc, name)); + xmlFreeDoc(pDoc); + } else { + globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n"; + } + }); } -void CGameDialog::ScanForGames() -{ - CString strPath; - char *dirlist; - GDir *dir; - CString strGamesPath = g_strAppPath.GetBuffer(); - strGamesPath += "games"; - const char *path = strGamesPath.GetBuffer(); - - if ( !mGames.empty() ) { - Sys_Printf( "Clearing game list\n" ); - list::iterator iGame; - for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { - delete (*iGame); - } - mGames.clear(); - } - - Sys_Printf( "Scanning for game description files: %s\n", path ); - - /*! - \todo FIXME LINUX: - do we put game description files below g_strAppPath, or in ~/.radiant - i.e. read only or read/write? - my guess .. readonly cause it's an install - we will probably want to add ~/.radiant//games/ scanning on top of that for developers - (if that's really needed) - */ - - // FIXME need to catch the 'no game description' situation and exit with a clean error - - dir = g_dir_open(path, 0, NULL); - - if (dir != NULL) - { - while (1) - { - const gchar* name = g_dir_read_name(dir); - if(name == NULL) - break; - - dirlist = g_strdup(name); -#ifdef _WIN32 - strlwr (dirlist); -#endif - char *ext = strrchr (dirlist, '.'); - if ((ext == NULL) || (strcmp (ext, ".game") != 0)) - continue; - strPath.Format("%s/%s", path, dirlist); - Sys_Printf("%s\n", strPath.GetBuffer()); - // got one, load it - xmlDocPtr pDoc = xmlParseFile(strPath.GetBuffer()); - if (pDoc) - { - mGames.push_front( new CGameDescription( pDoc, dirlist ) ); - } - else - { - Sys_FPrintf(SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer()); - } - - g_free( dirlist ); - } - g_dir_close( dir ); - } - - // entries in the combo need to be updated - UpdateGameCombo(); -} - -CGameDescription* CGameDialog::GameDescriptionForComboItem() -{ - list::iterator iGame; - int i=0; - for( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) { - if ( i == m_nComboSelect ) { - return (*iGame); - } - } - return NULL; // not found +CGameDescription* CGameDialog::GameDescriptionForComboItem(){ + std::list::iterator iGame; + int i = 0; + for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame,i++ ) + { + if ( i == m_nComboSelect ) { + return ( *iGame ); + } + } + return 0; // not found } -void CGameDialog::InitGlobalPrefPath() -{ - GString *global_rc_path; - // configure m_global_rc_path - // this is the g_strTempPath, and it has already been mkdir'ed - global_rc_path = g_string_new(g_strTempPath.GetBuffer()); - g_PrefsDlg.m_global_rc_path = global_rc_path; +void CGameDialog::InitGlobalPrefPath(){ + g_Preferences.m_global_rc_path = g_string_new( SettingsPath_get() ); } -void CGameDialog::Reset() -{ - if (!g_PrefsDlg.m_global_rc_path) - InitGlobalPrefPath(); - CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; - strGlobalPref += "global.pref"; - remove(strGlobalPref.GetBuffer()); +void CGameDialog::Reset(){ + if ( !g_Preferences.m_global_rc_path ) { + InitGlobalPrefPath(); + } + StringOutputStream strGlobalPref( 256 ); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; + file_remove( strGlobalPref.c_str() ); } -void CGameDialog::Init() -{ - InitGlobalPrefPath(); - ScanForGames(); - if ( mGames.empty() ) { - DoGameInstall(); - ScanForGames(); - if ( mGames.empty() ) { - Error( "No games setup, aborting\n" ); - } - } - LoadPrefs(); - if ( m_bAutoLoadGame ) { - // search by .game name - list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) - { - if ((*iGame)->mGameFile == m_sGameFile) - { - m_pCurrentGameDescription = (*iGame); - break; - } - } - } - if ( !m_bAutoLoadGame || !m_pCurrentGameDescription ) { - DoGameDialog(); - // use m_nComboSelect to identify the game to run as and set the globals - m_pCurrentGameDescription = GameDescriptionForComboItem(); - if ( !m_pCurrentGameDescription ) { - Error("Lookup of game description object failed, can't continue\n"); +void CGameDialog::Init(){ + bool gamePrompt = false; + + InitGlobalPrefPath(); + LoadPrefs(); + ScanForGames(); + + if ( mGames.empty() ) { + Error( "Didn't find any valid game file descriptions, aborting\n" ); } - } - g_pGameDescription = m_pCurrentGameDescription; - - g_strGameToolsPath = g_pGameDescription->mGameToolsPath; - - // NOTE TTimo: this is moved from QE_LoadProject in 1.2 - // (probably broken) - // NOTE Hydra: was broken for win32, we don't use m_strHomeGame or m_strFSBasePath -#if defined (__linux__) || defined (__APPLE__) - g_qeglobals.m_strHomeGame = g_get_home_dir(); - g_qeglobals.m_strHomeGame += "/"; - g_qeglobals.m_strHomeGame += m_pCurrentGameDescription->mUserPathPrefix.GetBuffer(); - g_qeglobals.m_strHomeGame += "/"; -#else - g_qeglobals.m_strHomeGame = g_pGameDescription->mEnginePath.GetBuffer(); -#endif + else + { + std::list::iterator iGame, iPrevGame; + for ( iGame = mGames.begin(), iPrevGame = mGames.end(); iGame != mGames.end(); iPrevGame = iGame, ++iGame ) + { + if ( iPrevGame != mGames.end() ) { + if ( strcmp( ( *iGame )->getRequiredKeyValue( "name" ), ( *iPrevGame )->getRequiredKeyValue( "name" ) ) < 0 ) { + CGameDescription *h = *iGame; + *iGame = *iPrevGame; + *iPrevGame = h; + } + } + } + } + + CGameDescription* currentGameDescription = 0; + + // m_bSkipGamePromptOnce is used to not prompt for game on restart, only on fresh startup + if ( m_bGamePrompt && !m_bSkipGamePromptOnce ) { + gamePrompt = true; + } + + m_bSkipGamePromptOnce = false; + g_GamesDialog.SavePrefs(); - g_pGameDescription->Dump(); + if ( !gamePrompt ) { + // search by .game name + std::list::iterator iGame; + for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) + { + if ( ( *iGame )->mGameFile == m_sGameFile ) { + currentGameDescription = ( *iGame ); + break; + } + } + } + + if ( gamePrompt || !currentGameDescription ) { + onStartup = true; + Create(); + DoGameDialog(); + // use m_nComboSelect to identify the game to run as and set the globals + currentGameDescription = GameDescriptionForComboItem(); + ASSERT_NOTNULL( currentGameDescription ); + } + else { + onStartup = false; + } + + g_pGameDescription = currentGameDescription; + + g_pGameDescription->Dump(); } -CGameDialog::~CGameDialog() -{ - if (mFrame) - { - // NOTE I'm not too sure how reliable this is - gtk_widget_unref(GTK_WIDGET(mFrame)); - } - // free all the game descriptions - list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) - { - delete (*iGame); - *iGame = NULL; - } -} - -void CGameDialog::AddPacksURL(Str &URL) -{ - // add the URLs for the list of game packs installed - // FIXME: this is kinda hardcoded for now.. - list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) - { - if ((*iGame)->mGameFile == "q3.game") - URL += "&Games_dlup%5B%5D=1"; - else if ((*iGame)->mGameFile == "wolf.game") - URL += "&Games_dlup%5B%5D=2"; - // FIXME: double entry - else if ((*iGame)->mGameFile == "wolf.game") - URL += "&Games_dlup%5B%5D=3"; - else if ((*iGame)->mGameFile == "jk2.game") - URL += "&Games_dlup%5B%5D=4"; - else if ((*iGame)->mGameFile == "stvef.game") - URL += "&Games_dlup%5B%5D=5"; - else if ((*iGame)->mGameFile == "sof2.game") - URL += "&Games_dlup%5B%5D=6"; - else if ((*iGame)->mGameFile == "ja.game") - URL += "&Games_dlup%5B%5D=7"; - } -} - -#ifdef _WIN32 - -#define NETRUN_FILENAME "netrun.conf" - -bool CGameDialog::m_bNetRun; - -void CGameDialog::UpdateNetrun(bool retrieve) -{ - FILE *f_netrun; - CString strNetrun; - strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME; - if (!retrieve) - { - // now check if we are running from a network installation - // use a dummy file as the flag - f_netrun = fopen(strNetrun.GetBuffer(), "r"); - if (f_netrun) - { - fclose(f_netrun); - m_bNetRun = true; - } - else - m_bNetRun = false; - } - else - { - if (m_bNetRun) - { - f_netrun = fopen(strNetrun.GetBuffer(), "w"); - if (!f_netrun) - { - Sys_FPrintf(SYS_ERR, "ERROR: Failed to create netrun file '%s'\n", strNetrun.GetBuffer()); - m_bNetRun = false; - } - else - { - fclose(f_netrun); - Sys_Printf("Created/Checked '%s'\n", strNetrun.GetBuffer()); - } - } - else - { - if (remove(strNetrun.GetBuffer()) == -1) - { - if (errno != ENOENT) - Sys_FPrintf(SYS_ERR, "Failed to remove netrun file '%s'\n", strNetrun.GetBuffer()); - m_bNetRun = true; - } - else - { - Sys_Printf("Netrun mode is disabled\n"); - } - } - } -} - -bool CGameDialog::GetNetrun() -{ - return m_bNetRun; +CGameDialog::~CGameDialog(){ + // free all the game descriptions + std::list::iterator iGame; + for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) + { + delete ( *iGame ); + *iGame = 0; + } + if ( GetWidget() ) { + Destroy(); + } } -#endif + +inline const char* GameDescription_getIdentifier( const CGameDescription& gameDescription ){ + const char* identifier = gameDescription.getKeyValue( "index" ); + if ( string_empty( identifier ) ) { + identifier = "1"; + } + return identifier; +} + + +CGameDialog g_GamesDialog; + + +// ============================================================================= +// Widget callbacks for PrefsDlg + +static void OnButtonClean( ui::Widget widget, gpointer data ){ + // make sure this is what the user wants + if ( ui::alert( g_Preferences.GetWidget(), "This will close " RADIANT_NAME " and clean the corresponding registry entries.\n" + "Next time you start " RADIANT_NAME " it will be good as new. Do you wish to continue?", + "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk ) == ui::alert_response::YES ) { + PrefsDlg *dlg = (PrefsDlg*)data; + dlg->EndModal( eIDCANCEL ); + + g_preferences_globals.disable_ini = true; + Preferences_Reset(); + gtk_main_quit(); + } +} + +// ============================================================================= +// PrefsDlg class /* -======== + ======== -very first prefs init deals with selecting the game and the game tools path -then we can load .ini stuff + very first prefs init deals with selecting the game and the game tools path + then we can load .ini stuff -using prefs / ini settings: -those are per-game + using prefs / ini settings: + those are per-game -win32: -look in g_strGameToolsPath for .ini + look in ~/.radiant//gamename + ======== + */ -linux: -look in ~/.radiant//gamename -======== -*/ +const char *PREFS_LOCAL_FILENAME = "local.pref"; -#define PREFS_LOCAL_FILENAME "local.pref" +void PrefsDlg::Init(){ + // m_global_rc_path has been set above + // m_rc_path is for game specific preferences + // takes the form: global-pref-path/gamename/prefs-file -void PrefsDlg::Init() -{ - mGamesDialog.Init(); - - // m_global_rc_path has been set above, do m_rc_path with game specific stuff now - // the win32 and linux versions have been unified for network mode -#ifdef _WIN32 - if (!CGameDialog::GetNetrun()) - { - // legacy prefs settings, this goes where the game pack is installed - m_rc_path = g_string_new (g_strGameToolsPath.GetBuffer() ); - m_inipath = g_string_new (m_rc_path->str); - g_string_append (m_inipath, PREFS_LOCAL_FILENAME); - return; - } -#endif - // this is common to win32 and Linux init now - m_rc_path = g_string_new (m_global_rc_path->str); + // this is common to win32 and Linux init now + m_rc_path = g_string_new( m_global_rc_path->str ); - // game sub-dir - g_string_append (m_rc_path, g_pGameDescription->mGameFile.GetBuffer()); - g_string_append (m_rc_path, "/"); - Q_mkdir (m_rc_path->str, 0775); + // game sub-dir + g_string_append( m_rc_path, g_pGameDescription->mGameFile.c_str() ); + g_string_append( m_rc_path, "/" ); + Q_mkdir( m_rc_path->str ); - // then the ini file - m_inipath = g_string_new (m_rc_path->str); - g_string_append (m_inipath, PREFS_LOCAL_FILENAME); + // then the ini file + m_inipath = g_string_new( m_rc_path->str ); + g_string_append( m_inipath, PREFS_LOCAL_FILENAME ); +} +void notebook_set_page( ui::Widget notebook, ui::Widget page ){ + int pagenum = gtk_notebook_page_num( GTK_NOTEBOOK( notebook ), page ); + if ( gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) != pagenum ) { + gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), pagenum ); + } } -void PrefsDlg::UpdateData (bool retrieve) -{ - // leo: the "changed" signal confuses the update function - if (m_pWidget == NULL) - return; - mGamesDialog.UpdateData (retrieve); - Dialog::UpdateData (retrieve); +void PrefsDlg::showPrefPage( ui::Widget prefpage ){ + notebook_set_page( m_notebook, prefpage ); + return; } -#ifdef _WIN32 -#define PREFSHSPACE 5 -#else -#define PREFSHSPACE 0 -#endif +static void treeSelection( ui::TreeSelection selection, gpointer data ){ + PrefsDlg *dlg = (PrefsDlg*)data; -static void UpdateSensitivity( GtkWidget *widget, gpointer data ) -{ - PrefsDlg *dlg = (PrefsDlg*)data; - dlg->DoSensitivity(); + GtkTreeModel* model; + GtkTreeIter selected; + if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { + ui::Widget prefpage{ui::null}; + gtk_tree_model_get( model, &selected, 1, (gpointer*)&prefpage, -1 ); + dlg->showPrefPage( prefpage ); + } } -static void UpdateEditorSensitivity(GtkWidget *widget, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; - dlg->DoEditorSensitivity(); +typedef std::list PreferenceGroupCallbacks; + +inline void PreferenceGroupCallbacks_constructGroup( const PreferenceGroupCallbacks& callbacks, PreferenceGroup& group ){ + for ( PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i ) + { + ( *i )( group ); + } } -// start new prefs dialog -/*! Utility function for swapping notebook pages for tree list selections */ -void PrefsDlg::showPrefPage(int prefpage) -{ - if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != prefpage) - gtk_notebook_set_page(GTK_NOTEBOOK(notebook), prefpage); +inline void PreferenceGroupCallbacks_pushBack( PreferenceGroupCallbacks& callbacks, const PreferenceGroupCallback& callback ){ + callbacks.push_back( callback ); +} - return; +typedef std::list PreferencesPageCallbacks; + +inline void PreferencesPageCallbacks_constructPage( const PreferencesPageCallbacks& callbacks, PreferencesPage& page ){ + for ( PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i ) + { + ( *i )( page ); + } } -static void treeSelection(GtkTreeSelection* selection, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; +inline void PreferencesPageCallbacks_pushBack( PreferencesPageCallbacks& callbacks, const PreferencesPageCallback& callback ){ + callbacks.push_back( callback ); +} - GtkTreeModel* model; - GtkTreeIter selected; - if(gtk_tree_selection_get_selected(selection, &model, &selected)) - { - int prefpage; - gtk_tree_model_get(model, &selected, 1, (gpointer*)&prefpage, -1); - dlg->showPrefPage(prefpage); - } +PreferencesPageCallbacks g_interfacePreferences; +void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback ){ + PreferencesPageCallbacks_pushBack( g_interfacePreferences, callback ); +} +PreferenceGroupCallbacks g_interfaceCallbacks; +void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback ){ + PreferenceGroupCallbacks_pushBack( g_interfaceCallbacks, callback ); } -void PrefsDlg::BuildDialog () -{ - // Main Preferences dialog - GtkWidget *dialog, *mainvbox, *hbox, *sc_win, *preflabel; - - // Widgets on notebook pages - GtkWidget *check, *label, *scale, *hbox2, *combo, - *table, *spin, *entry, *pixmap, - *radio, *button, *pageframe, *vbox; - - GList *combo_list = (GList*)NULL; - - GtkObject *adj; - - dialog = m_pWidget; - gtk_window_set_title(GTK_WINDOW(dialog), _("GtkRadiant Preferences")); - gtk_widget_realize(dialog); - - mainvbox = gtk_vbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(dialog), mainvbox); - gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5); - gtk_widget_show(mainvbox); - - hbox = gtk_hbox_new(FALSE, 5); - gtk_widget_show(hbox); - gtk_box_pack_end(GTK_BOX(mainvbox), hbox, FALSE, TRUE, 0); - - button = gtk_button_new_with_label(_("OK")); - gtk_widget_show(button); - gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_widget_set_usize(button, 60, -2); - AddModalButton(button, IDOK); - - button = gtk_button_new_with_label(_("Cancel")); - gtk_widget_show(button); - gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_widget_set_usize(button, 60, -2); - AddModalButton(button, IDCANCEL); - - button = gtk_button_new_with_label (_("Clean")); - gtk_widget_show(button); - gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(OnButtonClean), this); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_widget_set_usize (button, 60, -2); - - hbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 0); - gtk_widget_show(hbox); - - sc_win = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(hbox), sc_win, FALSE, FALSE, 0); - gtk_widget_show(sc_win); - - // prefs pages notebook - notebook = gtk_notebook_new(); - // hide the notebook tabs since its not supposed to look like a notebook - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE); - gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 0); - gtk_widget_show(notebook); - - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN); - - { - GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - - GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); - - { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(_("Preferences"), renderer, "text", 0, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); - } - - { - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(treeSelection), this); - } - - gtk_widget_show(view); - - gtk_container_add(GTK_CONTAINER (sc_win), view); - - { - /********************************************************************/ - /* Add preference tree options */ - /********************************************************************/ - { - GtkTreeIter group; - gtk_tree_store_append(store, &group, NULL); - gtk_tree_store_set(store, &group, 0, _("Globals"), 1, PTAB_FRONT, -1); - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Game settings"), 1, (gpointer)PTAB_GAME_SETTINGS, -1); - } - } - - { - GtkTreeIter group; - gtk_tree_store_append(store, &group, NULL); - gtk_tree_store_set(store, &group, 0, _("Display"), 1, PTAB_FRONT, -1); - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("2D Display/Rendering"), 1, (gpointer)PTAB_2D, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("3D View"), 1, (gpointer)PTAB_CAMERA, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Texture Settings"), 1, (gpointer)PTAB_TEXTURE, -1); - } - } - - { - GtkTreeIter group; - gtk_tree_store_append(store, &group, NULL); - gtk_tree_store_set(store, &group, 0, _("Interface"), 1, PTAB_FRONT, -1); - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Layout"), 1, (gpointer)PTAB_LAYOUT, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Mouse"), 1, (gpointer)PTAB_MOUSE, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Editing"), 1, (gpointer)PTAB_EDITING, -1); - } - } - - { - GtkTreeIter group; - gtk_tree_store_append(store, &group, NULL); - gtk_tree_store_set(store, &group, 0, _("Other"), 1, PTAB_FRONT, -1); - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Startup/Auto save"), 1, (gpointer)PTAB_STARTUP, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Paths"), 1, (gpointer)PTAB_PATHS, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Brush"), 1, (gpointer)PTAB_BRUSH, -1); - } - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("Misc"), 1, (gpointer)PTAB_MISC, -1); - } - if (!g_qeglobals.bBSPFrontendPlugin) - { - GtkTreeIter tab; - gtk_tree_store_append(store, &tab, &group); - gtk_tree_store_set(store, &tab, 0, _("BSP Monitoring"), 1, (gpointer)PTAB_BSPMONITOR, -1); - } - } - } - - gtk_tree_view_expand_all(GTK_TREE_VIEW(view)); - - g_object_unref(G_OBJECT(store)); - } - - /**********************************************************************/ - /* build the prefs pages */ - /**********************************************************************/ - - // Front page... - // todo : add something interesting here - // NOTE TTimo: tip of the day? or a logo? - preflabel = gtk_label_new(_("Front Page")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(NULL); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_widget_set_usize(GTK_WIDGET(vbox), 350, -2); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** global preferences group ****************************/ - preflabel = gtk_label_new(_("Globals")); - gtk_widget_show(preflabel); - - pageframe = mGamesDialog.GetGlobalFrame(); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** 2D prefs group (xy views/rendering options) *********/ - preflabel = gtk_label_new(_("2D Display")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("2D Display")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // OpenGL Display Lists - check = gtk_check_button_new_with_label(_("OpenGL Display Lists")); - gtk_widget_show(check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData(check, &m_bDisplayLists, DLG_CHECK_BOOL); - - // Antialiased points & lines - // Fishman - Add antialiazed points and lines support. 09/03/00 - check = gtk_check_button_new_with_label (_("OpenGL antialiased points and lines")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bAntialiasedPointsAndLines, DLG_CHECK_BOOL); - - // Solid selection boxes - check = gtk_check_button_new_with_label (_("Solid selection boxes")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bNoStipple, DLG_CHECK_BOOL); - - // Display size info - check = gtk_check_button_new_with_label (_("Display size info")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bSizePaint, DLG_CHECK_BOOL); - - // Alternate vertex/edge handles - // Gef: Kyro GL_POINT work around 25-aug-2001 - check = gtk_check_button_new_with_label (_("Alternate vertex/edge handles")); - gtk_widget_show(check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData(check, &m_bGlPtWorkaround, DLG_CHECK_BOOL); - - g_list_free (combo_list); - -#ifdef ATIHACK_812 - // ATI bugs - check = gtk_check_button_new_with_label (_("ATI cards with broken drivers - bug #802")); - gtk_widget_show(check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL); -#endif +PreferencesPageCallbacks g_displayPreferences; +void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback ){ + PreferencesPageCallbacks_pushBack( g_displayPreferences, callback ); +} +PreferenceGroupCallbacks g_displayCallbacks; +void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback ){ + PreferenceGroupCallbacks_pushBack( g_displayCallbacks, callback ); +} - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** 3D Camera view group *********/ - preflabel = gtk_label_new(_("3D View")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("3D View")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Directional velocity (Movement Velocity) - // label container - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox2); - gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); - - // label - label = gtk_label_new(_("Movement Velocity")); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - - // adjustment - adj = gtk_adjustment_new(100, 50, 300, 1, 10, 10); - AddDialogData(adj, &m_nMoveSpeed, DLG_ADJ_INT); - - // scale - scale = gtk_hscale_new(GTK_ADJUSTMENT(adj)); - gtk_widget_show(scale); - gtk_box_pack_start(GTK_BOX (vbox), scale, FALSE, TRUE, 2); - - gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); - - // Angular velocity (Rotational Velocity) - // label container - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox2); - gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); - - // label - label = gtk_label_new (_("Rotational Velocity")); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_widget_show (label); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - - // adjustment - adj = gtk_adjustment_new (3, 1, 180, 1, 10, 10); // value, low, high, step, page_step, page_size - AddDialogData (adj, &m_nAngleSpeed, DLG_ADJ_INT); - - // scale - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj)); - gtk_widget_show (scale); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 2); - gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); - - // Text under the velocity sliders - // container - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox2); - gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); - - // label - label = gtk_label_new (_("slow")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - - // label - label = gtk_label_new (_("fast")); - gtk_widget_show (label); - gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - - // Allow drag to select multiple faces/brushes - // container - table = gtk_table_new(2, 1, FALSE); - gtk_widget_show(table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - label = gtk_label_new (_("Use paint-select in camera view:")); - gtk_widget_show (label); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - combo_list = NULL; - combo_list = g_list_append (combo_list, (void *)_("No")); - combo_list = g_list_append (combo_list, (void *)_("Yes")); - combo_list = g_list_append (combo_list, (void *)_("Yes (Classic Key Setup)")); - - combo = gtk_combo_new (); - gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); - gtk_widget_show (combo); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); - AddDialogData (combo, &m_nCamDragMultiSelect, DLG_COMBO_INT); - - // Freelook in Camera view - check = gtk_check_button_new_with_label (_("Freelook in Camera view")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); - AddDialogData (check, &m_bCamFreeLook, DLG_CHECK_BOOL); - - // Freelook in Camera view w/ forward & back strafing instead of up and down looking - check = gtk_check_button_new_with_label (_("Freelook strafes Forward and Back")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); - AddDialogData (check, &m_bCamFreeLookStrafe, DLG_CHECK_BOOL); - - // Invert mouse in freelook - check = gtk_check_button_new_with_label (_("Invert mouse in freelook")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); - AddDialogData (check, &m_bCamInverseMouse, DLG_CHECK_BOOL); - - // Discrete movement - check = gtk_check_button_new_with_label (_("Discrete movement")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); - AddDialogData (check, &m_bCamDiscrete, DLG_CHECK_BOOL); - - // Update XY views on camera move - check = gtk_check_button_new_with_label (_("Update XY views on camera move")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); - AddDialogData (check, &m_bCamXYUpdate, DLG_CHECK_BOOL); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Texture group *********/ - preflabel = gtk_label_new(_("Textures")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Textures")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 6); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Texture quality slider - // label - label = gtk_label_new (_("Texture quality")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - - // adjustment - adj = gtk_adjustment_new (0, 0, 4, 1, 1, 1); - AddDialogData (adj, &m_nLatchedTextureQuality, DLG_ADJ_INT); - - // scale - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj)); - gtk_widget_show (scale); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0); - gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); - - // text under the texture slider - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox2); - gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); - label = gtk_label_new (_("low")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - label = gtk_label_new (_("high")); - gtk_widget_show (label); - gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - - // texture subsets - check = gtk_check_button_new_with_label (_("Texture subsets")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bTextureWindow, DLG_CHECK_BOOL); - - // texture scrollbar - check = gtk_check_button_new_with_label (_("Texture scrollbar")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bTextureScrollbar, DLG_CHECK_BOOL); - - // texture increment matches grid - check = gtk_check_button_new_with_label (_("Tex increment matches grid")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bSnapTToGrid, DLG_CHECK_BOOL); - - // RIANT - // Texture compression choice label - // container - table = gtk_table_new(2, 1, FALSE); - gtk_widget_show(table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - label = gtk_label_new (_("Texture Compression (if available):")); - gtk_widget_show (label); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - // Texture compression choice label - combo_list = NULL; - // NONE will always be in pos 0 - combo_list = g_list_append (combo_list, (void *)_("None")); - - // if OpenGL compression is enabled it will always be - // in pos 1 - if (g_qeglobals.m_bOpenGLCompressionSupported) - { - combo_list = g_list_append (combo_list, (void *)_("OpenGL ARB")); - } - - // If S3 is enabled offer all 3 valid compression schemes in RGBA - if (g_qeglobals.m_bS3CompressionSupported) - { - combo_list = g_list_append (combo_list, (void *)_("S3TC DXT1")); - combo_list = g_list_append (combo_list, (void *)_("S3TC DXT3")); - combo_list = g_list_append (combo_list, (void *)_("S3TC DXT5")); - } - - combo = gtk_combo_new (); - gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); - gtk_widget_show (combo); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); - AddDialogData (combo, &m_nTextureCompressionFormat, DLG_COMBO_INT); - g_list_free (combo_list); - - // container - table = gtk_table_new(2, 1, FALSE); - gtk_widget_show(table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - // Startup shaders - // label - label = gtk_label_new (_("Startup Shaders:")); - gtk_widget_show (label); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - // combo list - combo_list = NULL; - combo_list = g_list_append (combo_list, (void *)_("None")); - if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game") - combo_list = g_list_append (combo_list, (void *)_("System")); - else if (g_pGameDescription->mGameFile == "sof2.game") - combo_list = g_list_append (combo_list, (void *)("Tools")); - else - combo_list = g_list_append (combo_list, (void *)_("Common")); - combo_list = g_list_append (combo_list, (void *)_("All")); - combo = gtk_combo_new (); - gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); - gtk_widget_show (combo); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); - AddDialogData (combo, &m_nLatchedShader, DLG_COMBO_INT); - g_list_free (combo_list); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Layout group *********/ - preflabel = gtk_label_new(_("Layout")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Layout")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // View types - // table - table = gtk_table_new (2, 4, FALSE); - gtk_widget_show (table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - // view type 1 - pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window1.bmp"); - gtk_widget_show (pixmap); - gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 2 - pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window2.bmp"); - gtk_widget_show (pixmap); - gtk_table_attach (GTK_TABLE (table), pixmap, 1, 2, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 3 - pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window3.bmp"); - gtk_widget_show (pixmap); - gtk_table_attach (GTK_TABLE (table), pixmap, 2, 3, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 4 - pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window4.bmp"); - gtk_widget_show (pixmap); - gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 1 selector - radio = gtk_radio_button_new (NULL); - gtk_widget_show (radio); - gtk_table_attach (GTK_TABLE (table), radio, 0, 1, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 2 selector - radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); - gtk_widget_show (radio); - gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 3 selector - radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); - gtk_widget_show (radio); - gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // view type 4 selector - radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); - gtk_widget_show (radio); - gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - AddDialogData (radio, &m_nLatchedView, DLG_RADIO_INT); - - // Floating Z window - check = gtk_check_button_new_with_label (_("Floating Z Window")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLatchedFloatingZ, DLG_CHECK_BOOL); - - // show menu tear-off seperators - check = gtk_check_button_new_with_label (_("Detachable Menus")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLatchedDetachableMenus, DLG_CHECK_BOOL); - - if (!g_pGameDescription->mNoPatch) - { - // show patch toolbar - check = gtk_check_button_new_with_label (_("Patch Toolbar")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_patchtoolbar", check); // Allow to be disabled for Q1/Q2 - AddDialogData (check, &m_bLatchedPatchToolbar, DLG_CHECK_BOOL); - } - - // use wide toolbar - check = gtk_check_button_new_with_label (_("Wide Toolbar")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLatchedWideToolbar, DLG_CHECK_BOOL); - - // use plugin toolbar - check = gtk_check_button_new_with_label (_("Plugin Toolbar")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLatchedPluginToolbar, DLG_CHECK_BOOL); - -#ifdef _WIN32 - // win32 file dialog - check = gtk_check_button_new_with_label (_("Use win32 file dialog (hacky)")); - gtk_widget_show (check); - // gtk_container_add (GTK_CONTAINER (vbox), check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bNativeGUI, DLG_CHECK_BOOL); - - // position on primary monitor - check = gtk_check_button_new_with_label (_("Start on Primary Monitor")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_startonprimary", check); - gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); - AddDialogData (check, &m_bStartOnPrimMon, DLG_CHECK_BOOL); -#endif +PreferencesPageCallbacks g_settingsPreferences; +void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback ){ + PreferencesPageCallbacks_pushBack( g_settingsPreferences, callback ); +} +PreferenceGroupCallbacks g_settingsCallbacks; +void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback ){ + PreferenceGroupCallbacks_pushBack( g_settingsCallbacks, callback ); +} - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Mouse group *********/ - preflabel = gtk_label_new(_("Mouse")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Mouse")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Buttons - // container - hbox2 = gtk_hbox_new (FALSE, 5); - gtk_widget_show (hbox2); - gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); - - // 2 button radio - radio = gtk_radio_button_new_with_label (NULL, _("2 button")); - gtk_widget_show (radio); - gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0); - - // 3 button radio - radio = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), _("3 button")); - gtk_widget_show (radio); - gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0); - AddDialogData (radio, &m_nMouse, DLG_RADIO_INT); - - // right click to drop entity - check = gtk_check_button_new_with_label (_("Right click to drop entities")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bRightClick, DLG_CHECK_BOOL); - - // Mouse chaser (and this does what?) - check = gtk_check_button_new_with_label (_("Mouse chaser")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bChaseMouse, DLG_CHECK_BOOL); - - // Alt + multi-drag - check = gtk_check_button_new_with_label (_("ALT + multi-drag")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bALTEdge, DLG_CHECK_BOOL); - - // Mouse wheel increments - // container - hbox2 = gtk_hbox_new (FALSE, 5); - gtk_widget_show (hbox2); - gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); - - // label - label = gtk_label_new (_("Wheel Mouse inc:")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - - // entry - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_widget_set_usize (entry, 40, -2); - gtk_box_pack_start (GTK_BOX (hbox2), entry, FALSE, FALSE, 0); - AddDialogData (entry, &m_nWheelInc, DLG_ENTRY_INT); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Editing group *********/ - preflabel = gtk_label_new(_("Editing")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Editing")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Vertex editing splits faces - check = gtk_check_button_new_with_label (_("Vertex editing splits face")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bVertexSplit, DLG_CHECK_BOOL); - - // Fix target/targetname collisions - check = gtk_check_button_new_with_label (_("Fix target/targetname collisions")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bDoTargetFix, DLG_CHECK_BOOL); - - // Clipper tool uses caulk - check = gtk_check_button_new_with_label (_("Clipper tool uses caulk")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bClipCaulk, DLG_CHECK_BOOL); - - // Don't clamp plane points - check = gtk_check_button_new_with_label (_("Don't clamp plane points")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bNoClamp, DLG_CHECK_BOOL); - - // Snap to grid - check = gtk_check_button_new_with_label (_("Snap to grid")); - gtk_widget_show (check); - gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bSnap, DLG_CHECK_BOOL); - - // Select patch by bounding box - check = gtk_check_button_new_with_label (_("Select patches by bounding box")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bPatchBBoxSelect, DLG_CHECK_BOOL); - - // Rotation increment - // container - table = gtk_table_new (2, 3, FALSE); - gtk_widget_show (table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - // label - label = gtk_label_new (_("Rotation increment:")); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // entry - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_widget_set_usize (entry, 60, -2); - gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - AddDialogData (entry, &m_nRotation, DLG_ENTRY_INT); - - // Undo levels - // label - label = gtk_label_new (_("Undo Levels:")); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // spinner (allows undo levels to be set to zero) - spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 0, 64, 1, 10, 10)), 1, 0); - gtk_widget_show (spin); - gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_widget_set_usize (spin, 60, -2); - AddDialogData (spin, &m_nUndoLevels, DLG_SPIN_INT); - - // Patch subdivisions - // label - label = gtk_label_new (_("Patch subdivisions:")); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // entry (spinner perhaps? [2-16]) - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_widget_set_usize (entry, 60, -2); - gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - AddDialogData (entry, &m_nSubdivisions, DLG_ENTRY_INT); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Save/Load group *********/ - preflabel = gtk_label_new(_("Startup/Auto save")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Startup/Auto save")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Snapshots - check = gtk_check_button_new_with_label (_("Snapshots")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bSnapShots, DLG_CHECK_BOOL); - - // load last project on open - check = gtk_check_button_new_with_label (_("Load last project on open")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLoadLast, DLG_CHECK_BOOL); - - // load last map on open - check = gtk_check_button_new_with_label (_("Load last map on open")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bLoadLastMap, DLG_CHECK_BOOL); - - // Auto save.. - // container - hbox2 = gtk_hbox_new (FALSE, 5); - gtk_widget_show (hbox2); - gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (hbox2), 0); - - // label - check = gtk_check_button_new_with_label (_("Auto save every")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (hbox2), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bAutoSave, DLG_CHECK_BOOL); - - // spinner - spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 60, 1, 10, 10)), 1, 0); - gtk_widget_show (spin); - gtk_box_pack_start (GTK_BOX (hbox2), spin, FALSE, FALSE, 0); - gtk_widget_set_usize (spin, 60, -2); - AddDialogData (spin, &m_nAutoSave, DLG_SPIN_INT); - - // label - label = gtk_label_new (_("minutes")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Paths group *********/ - preflabel = gtk_label_new(_("Paths")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Paths")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // prefab path - // table - table = gtk_table_new (3, 3, FALSE); - gtk_widget_show (table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - // label - label = gtk_label_new (_("Prefab path:")); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); - - // path entry - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2); - gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 1, 0); - AddDialogData (entry, &m_strPrefabPath, DLG_ENTRY_TEXT); - -#if 0 - // browse button - button = gtk_button_new_with_label ("..."); - gtk_widget_show (button); - gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseprefab), this); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); -#endif +void Widget_updateDependency( ui::Widget self, ui::Widget toggleButton ){ + gtk_widget_set_sensitive( self, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggleButton ) ) && gtk_widget_is_sensitive( toggleButton ) ); +} - // User ini path - // label - label = gtk_label_new (_("User INI path:")); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); - - // user ini path entry - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 1, 0); - AddDialogData (entry, &m_strUserPath, DLG_ENTRY_TEXT); - - // user ini browse button - button = gtk_button_new_with_label ("..."); - gtk_widget_show (button); - gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseuserini), this); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Brush group ********/ - preflabel = gtk_label_new(_("Brush")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Brush")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // default texture scale - // table - table = gtk_table_new(2, 1, FALSE); // I believe that the 2 and 1 are switched here, and this is - // intentional to be consistent with other calls to gtk_table_new() - // [that are probably also switched]. - gtk_widget_show(table); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings(GTK_TABLE(table), 5); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - - // label - label = gtk_label_new(_("Default texture scale:")); - gtk_widget_show(label); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - // scale entry - entry = gtk_entry_new(); - gtk_widget_show(entry); - gtk_widget_set_usize(GTK_WIDGET(entry), 60, -2); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - AddDialogData(entry, &m_fDefTextureScale, DLG_ENTRY_FLOAT); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** Misc group *********/ - preflabel = gtk_label_new(_("Misc")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("Misc")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Light drawing - check = gtk_check_button_new_with_label (_("Light drawing")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &m_bNewLightDraw, DLG_CHECK_BOOL); - - // Light radiuses - // container - table = gtk_table_new(2, 1, FALSE); - gtk_widget_show(table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - label = gtk_label_new (_("Light radiuses:")); - gtk_widget_show (label); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - - combo_list = NULL; - combo_list = g_list_append (combo_list, (void *)_("Disabled")); - combo_list = g_list_append (combo_list, (void *)_("True Q3Map2 Style")); - combo_list = g_list_append (combo_list, (void *)_("Classic Style")); - - combo = gtk_combo_new (); - gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); - gtk_widget_show (combo); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); - AddDialogData (combo, &m_nLightRadiuses, DLG_COMBO_INT); - -#ifdef _WIN32 - check = gtk_check_button_new_with_label (_("Use win32 file associations to open text files instead of builtin editor")); - gtk_widget_show(check); - gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0); - AddDialogData (check, &g_PrefsDlg.m_bUseWin32Editor, DLG_CHECK_BOOL); -#else - // use custom shader editor - check = gtk_check_button_new_with_label (_("Use Custom Shader Editor")); - gtk_widget_show(check); - gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0); - gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateEditorSensitivity), this); - g_object_set_data (G_OBJECT(dialog), "check_customeditor", check); - AddDialogData (check, &g_PrefsDlg.m_bUseCustomEditor, DLG_CHECK_BOOL); - - // custom shader editor executable - // table - table = gtk_table_new (3, 1, FALSE); - gtk_widget_show (table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_table_set_row_spacings (GTK_TABLE (table), 5); - gtk_table_set_col_spacings (GTK_TABLE (table), 5); - - // label - label = gtk_label_new(_("Custom Editor Command")); - gtk_widget_show(label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); - g_object_set_data (G_OBJECT(dialog), "label_customeditor", label); - gtk_widget_set_sensitive (label, g_PrefsDlg.m_bUseCustomEditor); - - // custom editor command entry - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2); - gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 1, 0); - AddDialogData (entry, &m_strEditorCommand, DLG_ENTRY_TEXT); - gtk_widget_set_sensitive (entry, g_PrefsDlg.m_bUseCustomEditor); - g_object_set_data (G_OBJECT(dialog), "entry_customeditor", entry); - - // browse button - button = gtk_button_new_with_label (_("...")); - gtk_widget_show (button); - gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseEditor), this); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, - (GtkAttachOptions) (0), - (GtkAttachOptions) (0), 0, 0); - g_object_set_data (G_OBJECT(dialog), "button_customeditor", button); - gtk_widget_set_sensitive (button, g_PrefsDlg.m_bUseCustomEditor); -#endif +void ToggleButton_toggled_Widget_updateDependency( ui::Widget toggleButton, ui::Widget self ){ + Widget_updateDependency( self, toggleButton ); +} + +void ToggleButton_state_changed_Widget_updateDependency( ui::Widget toggleButton, GtkStateType state, ui::Widget self ){ + if ( state == GTK_STATE_INSENSITIVE ) { + Widget_updateDependency( self, toggleButton ); + } +} + +void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton ){ + toggleButton.connect( "state_changed", G_CALLBACK( ToggleButton_state_changed_Widget_updateDependency ), self ); + toggleButton.connect( "toggled", G_CALLBACK( ToggleButton_toggled_Widget_updateDependency ), self ); + Widget_updateDependency( self, toggleButton ); +} - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - /******** BSP Monitoring group *********/ - // this is never displayed if the plugin isn't available - preflabel = gtk_label_new(_("BSP Monitoring")); - gtk_widget_show(preflabel); - pageframe = gtk_frame_new(_("BSP Monitoring")); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); - gtk_widget_show(pageframe); - vbox = gtk_vbox_new(FALSE, 5); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); - - // Enable BSP process monitoring - check = gtk_check_button_new_with_label (_("Enable BSP process monitoring")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_monitorbsp", check); - gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); - AddDialogData (check, &g_PrefsDlg.m_bWatchBSP, DLG_CHECK_BOOL); - - // Stop on leak - check = gtk_check_button_new_with_label (_("Stop compilation on leak")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_leakstop", check); - AddDialogData (check, &g_PrefsDlg.m_bLeakStop, DLG_CHECK_BOOL); - - // engine after compile - check = gtk_check_button_new_with_label (_("Run engine after compile")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_runengine", check); - gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); - AddDialogData( check, &g_PrefsDlg.m_bRunQuake, DLG_CHECK_BOOL ); - - // sleep mode when running engine - check = gtk_check_button_new_with_label (_("Activate sleep mode when running the engine")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_sleep", check); - AddDialogData( check, &g_PrefsDlg.m_bDoSleep, DLG_CHECK_BOOL ); - - // use q3map2's texture projection - check = gtk_check_button_new_with_label (_("Texturing compatible with q3map2")); - gtk_widget_show (check); - gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (dialog), "check_q3map2", check); - AddDialogData( check, &g_PrefsDlg.m_bQ3Map2Texturing, DLG_CHECK_BOOL ); - - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - - gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PTAB_FRONT); - - return; -} - -// end new prefs dialog - -void PrefsDlg::LoadTexdefPref(texdef_t* pTexdef, char* pName) -{ - char buffer[256]; - memset(pTexdef, 0, sizeof(texdef_t)); +inline ui::VBox getVBox( ui::Bin page ){ + return ui::VBox::from(gtk_bin_get_child(page)); +} + +GtkTreeIter PreferenceTree_appendPage( ui::TreeStore store, GtkTreeIter* parent, const char* name, ui::Widget page ){ + GtkTreeIter group; + gtk_tree_store_append( store, &group, parent ); + gtk_tree_store_set( store, &group, 0, name, 1, page, -1 ); + return group; +} - sprintf(buffer, "%s%s", pName, TD_SCALE1_KEY); - mLocalPrefs.GetPref(buffer, &pTexdef->scale[0], 0.5f); +ui::Bin PreferencePages_addPage( ui::Widget notebook, const char* name ){ + ui::Widget preflabel = ui::Label( name ); + preflabel.show(); - sprintf(buffer, "%s%s", pName, TD_SCALE2_KEY); - mLocalPrefs.GetPref(buffer, &pTexdef->scale[1], 0.5f); + auto pageframe = ui::Frame( name ); + gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 4 ); + pageframe.show(); - sprintf(buffer, "%s%s", pName, TD_SHIFT1_KEY); - mLocalPrefs.GetPref(buffer, &pTexdef->shift[0], 8.f); + ui::Widget vbox = ui::VBox( FALSE, 4 ); + vbox.show(); + gtk_container_set_border_width( GTK_CONTAINER( vbox ), 4 ); + pageframe.add(vbox); - sprintf(buffer, "%s%s", pName, TD_SHIFT2_KEY); - mLocalPrefs.GetPref(buffer, &pTexdef->shift[1], 8.f); + // Add the page to the notebook + gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); - sprintf(buffer, "%s%s", pName, TD_ROTATE_KEY); - mLocalPrefs.GetPref(buffer, &pTexdef->rotate, 45); + return pageframe; } -void PrefsDlg::UpdateTextureCompression() +class PreferenceTreeGroup : public PreferenceGroup { - // if OpenGL is not ready yet, don't do anything - if (!g_qeglobals.m_bOpenGLReady) { - Sys_Printf("OpenGL not ready - postpone texture compression capability check\n"); - return; - } - - if (g_qeglobals.bTextureCompressionSupported) - { - if (m_nTextureCompressionFormat >= 2 && !g_qeglobals.m_bS3CompressionSupported) - { - Sys_Printf("Inconsistant pref setting for texture compression (%d), rolling back\n", m_nTextureCompressionFormat); - m_nTextureCompressionFormat = 1; // if this is not supported either, see below - } - if (m_nTextureCompressionFormat == 1 && !g_qeglobals.m_bOpenGLCompressionSupported) - { - Sys_Printf("Inconsistant pref setting for texture compression (GL_COMPRESSED_RGBA), rolling back\n"); - m_nTextureCompressionFormat = 0; - } - switch (m_nTextureCompressionFormat) - { - case (0): - { - g_qeglobals.texture_components = GL_RGBA; - Sys_Printf("texture compression disabled by preferences settings\n"); - break; - } - case (1): - { - g_qeglobals.texture_components = GL_COMPRESSED_RGBA; - Sys_Printf("OpenGL texture compression enabled\n"); - break; - } - case (2): - { - g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - Sys_Printf("S3TC DXT1 texture compression enabled\n"); - break; - } - case (3): - { - g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - Sys_Printf("S3TC DXT3 texture compression enabled\n"); - break; - } - case (4): - { - g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - Sys_Printf("S3TC DXT5 texture compression enabled\n"); - break; - } - } - } - else - { - Sys_Printf("texture compression is not supported by your current graphic card/drivers\n"); - g_qeglobals.texture_components = GL_RGBA; - m_nTextureCompressionFormat = 0; - } -} - -#ifdef ATIHACK_812 -void PrefsDlg::UpdateATIHack() { - // if OpenGL is not ready yet, don't do anything - if (!g_qeglobals.m_bOpenGLReady) { - Sys_Printf("OpenGL not ready - postpone ATI bug workaround setup\n"); - return; - } - - if (m_bGlATIHack) { - qglCullFace = &qglCullFace_ATIHack; - qglDisable = &qglDisable_ATIHack; - qglEnable = &qglEnable_ATIHack; - qglPolygonMode = &qglPolygonMode_ATIHack; - Sys_Printf("ATI bug workaround enabled\n"); - } else { - qglCullFace = qglCullFace_real; - qglDisable = qglDisable_real; - qglEnable = qglEnable_real; - qglPolygonMode = qglPolygonMode_real; - Sys_Printf("ATI bug workaround disabled\n"); - } +Dialog& m_dialog; +ui::Widget m_notebook; +ui::TreeStore m_store; +GtkTreeIter m_group; +public: +PreferenceTreeGroup( Dialog& dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group ) : + m_dialog( dialog ), + m_notebook( notebook ), + m_store( store ), + m_group( group ){ } -#endif +PreferencesPage createPage( const char* treeName, const char* frameName ){ + auto page = PreferencePages_addPage( m_notebook, frameName ); + PreferenceTree_appendPage( m_store, &m_group, treeName, page ); + return PreferencesPage( m_dialog, getVBox( page ) ); +} +}; -// TTimo: m_strEnginePath has a special status, if not found in registry we need to -// initiliaze it for sure. It is not totally failsafe but we can use the same -// code than in q3map, expecting to find some "quake" above us. If not, we prompt -// for the engine executable path -void PrefsDlg::LoadPrefs () -{ - int i; - - // first things first, load prefs from global prefs - mGamesDialog.LoadPrefs(); - - // if we already have a document loaded, we will free and reload from file - if (mLocalPrefs.InUse()) { - mLocalPrefs.Clear(); - } - - // load local.pref file - mLocalPrefs.ReadXMLFile(m_inipath->str); - - mLocalPrefs.GetPref(PATCHSHOWBOUNDS_KEY, &g_bPatchShowBounds, FALSE); - mLocalPrefs.GetPref(MOUSE_KEY, &m_nMouse, MOUSE_DEF); - m_nMouseButtons = m_nMouse ? 3 : 2; - - // project file - // if it's not found here, mainframe.cpp will take care of finding one - mLocalPrefs.GetPref(LASTPROJ_KEY, &m_strLastProject, ""); - mLocalPrefs.GetPref(LASTPROJVER_KEY, &m_nLastProjectVer, -1); - - // prefab path - // NOTE TTimo: I'm not sure why this is in prefs - // should probably be a project setting - // and I'm not sure that we really have a way to set this reliably either - CString strPrefab; - strPrefab = g_qeglobals.m_strHomeGame.GetBuffer(); - strPrefab += g_pGameDescription->mBaseGame.GetBuffer(); - strPrefab += "/prefabs/"; - mLocalPrefs.GetPref(PREFAB_KEY, &m_strPrefabPath, strPrefab); - - mLocalPrefs.GetPref(LASTLIGHTINTENSITY_KEY, &m_iLastLightIntensity, 300); - mLocalPrefs.GetPref(TLOCK_KEY, &m_bTextureLock, TLOCK_DEF); - mLocalPrefs.GetPref(RLOCK_KEY, &m_bRotateLock, TLOCK_DEF); - mLocalPrefs.GetPref(LASTMAP_KEY, &m_strLastMap, ""); - mLocalPrefs.GetPref(LOADLAST_KEY, &m_bLoadLast, LOADLAST_DEF); - mLocalPrefs.GetPref(BSP_KEY, &m_bInternalBSP, FALSE); - mLocalPrefs.GetPref(RCLICK_KEY, &m_bRightClick, TRUE); - mLocalPrefs.GetPref(AUTOSAVE_KEY, &m_bAutoSave, TRUE); - mLocalPrefs.GetPref(LOADLASTMAP_KEY, &m_bLoadLastMap, FALSE); - mLocalPrefs.GetPref(TINYBRUSH_KEY, &m_bCleanTiny, FALSE); - mLocalPrefs.GetPref(TINYSIZE_KEY, &m_fTinySize, 0.5f); - mLocalPrefs.GetPref(AUTOSAVETIME_KEY, &m_nAutoSave, 5); - mLocalPrefs.GetPref(SNAPSHOT_KEY, &m_bSnapShots, FALSE); - mLocalPrefs.GetPref(MOVESPEED_KEY, &m_nMoveSpeed, 100); - mLocalPrefs.GetPref(ANGLESPEED_KEY, &m_nAngleSpeed, 3); - mLocalPrefs.GetPref(SETGAME_KEY, &m_bSetGame, FALSE); - mLocalPrefs.GetPref(CAMXYUPDATE_KEY, &m_bCamXYUpdate, TRUE); - mLocalPrefs.GetPref(CAMDRAGMULTISELECT_KEY, &m_nCamDragMultiSelect, TRUE); - mLocalPrefs.GetPref(CAMFREELOOK_KEY, &m_bCamFreeLook, TRUE); - mLocalPrefs.GetPref(CAMINVERSEMOUSE_KEY, &m_bCamInverseMouse, FALSE); - mLocalPrefs.GetPref(CAMDISCRETE_KEY, &m_bCamDiscrete, TRUE); - mLocalPrefs.GetPref(LIGHTDRAW_KEY, &m_bNewLightDraw, TRUE); - mLocalPrefs.GetPref(CUBICCLIP_KEY, &m_bCubicClipping, TRUE); - mLocalPrefs.GetPref(CUBICSCALE_KEY, &m_nCubicScale, 13); - mLocalPrefs.GetPref(ALTEDGE_KEY, &m_bALTEdge, FALSE); - mLocalPrefs.GetPref(FACECOLORS_KEY, &m_bFaceColors, FALSE); - mLocalPrefs.GetPref(XZVIS_KEY, &m_bXZVis, FALSE); - mLocalPrefs.GetPref(YZVIS_KEY, &m_bYZVis, FALSE); - mLocalPrefs.GetPref(ZVIS_KEY, &m_bZVis, FALSE); - mLocalPrefs.GetPref(SIZEPAINT_KEY, &m_bSizePaint, FALSE); - mLocalPrefs.GetPref(DLLENTITIES_KEY, &m_bDLLEntities, FALSE); - - mLocalPrefs.GetPref(DETACHABLEMENUS_KEY, &m_bLatchedDetachableMenus, TRUE); - m_bDetachableMenus = m_bLatchedDetachableMenus; - - if (g_pGameDescription->mNoPatch) - { - m_bPatchToolbar = false; - } - else - { - mLocalPrefs.GetPref(PATCHTOOLBAR_KEY, &m_bLatchedPatchToolbar, TRUE); - m_bPatchToolbar = m_bLatchedPatchToolbar; - } - - mLocalPrefs.GetPref(WIDETOOLBAR_KEY, &m_bLatchedWideToolbar, TRUE); - m_bWideToolbar = m_bLatchedWideToolbar; - - mLocalPrefs.GetPref(PLUGINTOOLBAR_KEY, &m_bLatchedPluginToolbar, TRUE); - m_bPluginToolbar = m_bLatchedPluginToolbar; - - mLocalPrefs.GetPref(WINDOW_KEY, (int*)&m_nLatchedView, WINDOW_DEF); - m_nView = m_nLatchedView; - - mLocalPrefs.GetPref(FLOATINGZ_KEY, &m_bLatchedFloatingZ, FALSE); - m_bFloatingZ = m_bLatchedFloatingZ; - - mLocalPrefs.GetPref(TEXTUREQUALITY_KEY, &m_nLatchedTextureQuality, 3); - m_nTextureQuality = m_nLatchedTextureQuality; - - mLocalPrefs.GetPref(LOADSHADERS_KEY, &m_nLatchedShader, 0); - m_nShader = m_nLatchedShader; - - mLocalPrefs.GetPref(NOCLAMP_KEY, &m_bNoClamp, FALSE); - mLocalPrefs.GetPref(SNAP_KEY, &m_bSnap, TRUE); - mLocalPrefs.GetPref(USERINI_KEY, &m_strUserPath, ""); - mLocalPrefs.GetPref(ROTATION_KEY, &m_nRotation, 45); - mLocalPrefs.GetPref(CHASEMOUSE_KEY, &m_bChaseMouse, TRUE); - mLocalPrefs.GetPref(ENTITYSHOW_KEY, &m_nEntityShowState, ENTITY_SKINNED_BOXED); - - // this will probably need to be 75 or 100 for Q1. - mLocalPrefs.GetPref(TEXTURESCALE_KEY, &m_nTextureScale, 50); - - // FIXME: Hydra - actually, this stuff is Q1,Q2 and HL specific. - if ( (g_pGameDescription->mGameFile == "hl.game") ) - { - // No BSP monitoring in the default compiler tools for Half-life (yet) - mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, FALSE); - - // Texture subset on by default (HL specific really, because of halflife.wad's size) - mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, TRUE); - } - else if (g_pGameDescription->quake2) - { - // BSP monitoring is implemented in Quake2 and Heretic2 tools - mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, TRUE); - - // Texture subset on by default (HL specific really, because of halflife.wad's size) - mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, TRUE); - } - else - { - mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, WATCHBSP_DEF); - mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, FALSE); - } - - - mLocalPrefs.GetPref(TEXTURESCROLLBAR_KEY, &m_bTextureScrollbar, TRUE); - mLocalPrefs.GetPref(DISPLAYLISTS_KEY, &m_bDisplayLists, TRUE); - mLocalPrefs.GetPref(ANTIALIASEDLINES_KEY, &m_bAntialiasedPointsAndLines, FALSE); - mLocalPrefs.GetPref(SWITCHCLIP_KEY, &m_bSwitchClip, TRUE); - mLocalPrefs.GetPref(SELWHOLEENTS_KEY, &m_bSelectWholeEntities, TRUE); - mLocalPrefs.GetPref(SHOWSHADERS_KEY, &m_bShowShaders, TRUE); - mLocalPrefs.GetPref(GLLIGHTING_KEY, &m_bGLLighting, FALSE); - mLocalPrefs.GetPref(NOSTIPPLE_KEY, &m_bNoStipple, FALSE); - mLocalPrefs.GetPref(UNDOLEVELS_KEY, &m_nUndoLevels, 30); - mLocalPrefs.GetPref(VERTEXMODE_KEY, &m_bVertexSplit, TRUE); - mLocalPrefs.GetPref(RUNQ2_KEY, &m_bRunQuake, RUNQ2_DEF); - mLocalPrefs.GetPref(LEAKSTOP_KEY, &m_bLeakStop, TRUE); - mLocalPrefs.GetPref(DOSLEEP_KEY, &m_bDoSleep, FALSE); - mLocalPrefs.GetPref(SELECTCURVES_KEY, &m_bSelectCurves, TRUE); - mLocalPrefs.GetPref(SELECTMODELS_KEY, &m_bSelectModels, TRUE); - mLocalPrefs.GetPref(SHADERLISTONLY_KEY, &m_bTexturesShaderlistOnly, FALSE); - mLocalPrefs.GetPref(DEFAULTTEXURESCALE_KEY, &m_fDefTextureScale, g_pGameDescription->mTextureDefaultScale); - mLocalPrefs.GetPref(SUBDIVISIONS_KEY, &m_nSubdivisions, SUBDIVISIONS_DEF); - mLocalPrefs.GetPref(CLIPCAULK_KEY, &m_bClipCaulk, FALSE); - mLocalPrefs.GetPref(SNAPTTOGRID_KEY, &m_bSnapTToGrid, FALSE); - mLocalPrefs.GetPref(TARGETFIX_KEY, &m_bDoTargetFix, TRUE); - mLocalPrefs.GetPref(WHEELINC_KEY, &m_nWheelInc, 64); - mLocalPrefs.GetPref(PATCHBBOXSEL_KEY, &m_bPatchBBoxSelect, FALSE); - - // Gef: Kyro GL_POINT workaround - mLocalPrefs.GetPref(GLPOINTWORKAROUND_KEY, &m_bGlPtWorkaround, FALSE); - - // window positioning - mLocalPrefs.GetPref(ENTITYSPLIT1_KEY, &mWindowInfo.nEntitySplit1, -1); - mLocalPrefs.GetPref(ENTITYSPLIT2_KEY, &mWindowInfo.nEntitySplit2, -1); - - mLocalPrefs.GetPref(POSITIONX_KEY, &mWindowInfo.position.x, -1); - mLocalPrefs.GetPref(POSITIONY_KEY, &mWindowInfo.position.y, -1); - mLocalPrefs.GetPref(WIDTH_KEY, &mWindowInfo.position.w, -1); - mLocalPrefs.GetPref(HEIGHT_KEY, &mWindowInfo.position.h, 450); - - const window_position_t default_window_pos = { 0, 0, 200, 200, }; - - mLocalPrefs.GetPref(ENTITYWND_KEY, &mWindowInfo.posEntityWnd, default_window_pos); - mLocalPrefs.GetPref(MAPINFOWND_KEY, &mWindowInfo.posMapInfoWnd, default_window_pos); - mLocalPrefs.GetPref(CAMWND_KEY, &mWindowInfo.posCamWnd, default_window_pos); - mLocalPrefs.GetPref(ZWND_KEY, &mWindowInfo.posZWnd, default_window_pos); - mLocalPrefs.GetPref(XYWND_KEY, &mWindowInfo.posXYWnd, default_window_pos); - mLocalPrefs.GetPref(YZWND_KEY, &mWindowInfo.posYZWnd, default_window_pos); - mLocalPrefs.GetPref(XZWND_KEY, &mWindowInfo.posXZWnd, default_window_pos); - mLocalPrefs.GetPref(PATCHWND_KEY, &mWindowInfo.posPatchWnd, default_window_pos); - mLocalPrefs.GetPref(SURFACEWND_KEY, &mWindowInfo.posSurfaceWnd, default_window_pos); - mLocalPrefs.GetPref(ENTITYINFOWND_KEY, &mWindowInfo.posEntityInfoWnd, default_window_pos); - - mLocalPrefs.GetPref(ZWIDTH_KEY, &mWindowInfo.nZWidth, 30); - mLocalPrefs.GetPref(XYHEIGHT_KEY, &mWindowInfo.nXYHeight, 300); - mLocalPrefs.GetPref(XYWIDTH_KEY, &mWindowInfo.nXYWidth, 300); - mLocalPrefs.GetPref(CAMWIDTH_KEY, &mWindowInfo.nCamWidth, 200); - mLocalPrefs.GetPref(CAMHEIGHT_KEY, &mWindowInfo.nCamHeight, 200); - mLocalPrefs.GetPref(ZFLOATWIDTH_KEY, &mWindowInfo.nZFloatWidth, 300); -#ifdef _WIN32 - mLocalPrefs.GetPref(STATE_KEY, &mWindowInfo.nState, SW_SHOW); -#endif +ui::Window PrefsDlg::BuildDialog(){ + PreferencesDialog_addInterfacePreferences( makeCallbackF(Interface_constructPreferences) ); + Mouse_registerPreferencesPage(); - // menu stuff - mLocalPrefs.GetPref(COUNT_KEY, &m_nMRUCount, 0); - for(i = 0; i < 4; i++) - { - char buf[64]; - sprintf (buf, "%s%d", FILE_KEY, i); - mLocalPrefs.GetPref(buf, &m_strMRUFiles[i], ""); - } - - // some platform specific prefs -#ifdef _WIN32 - mLocalPrefs.GetPref(NATIVEGUI_KEY, &m_bNativeGUI, TRUE); - mLocalPrefs.GetPref(STARTONPRIMMON_KEY, &m_bStartOnPrimMon, FALSE); -#endif + ui::Window dialog = ui::Window(create_floating_window( RADIANT_NAME " Preferences", m_parent )); - mLocalPrefs.GetPref(SI_TEXMENU_KEY, &g_qeglobals.d_savedinfo.iTexMenu, ID_VIEW_BILINEARMIPMAP); - mLocalPrefs.GetPref(SI_GAMMA_KEY, &g_qeglobals.d_savedinfo.fGamma, 1.0f); - mLocalPrefs.GetPref(SI_EXCLUDE_KEY, &g_qeglobals.d_savedinfo.exclude, 0); // nothing filtered by default - mLocalPrefs.GetPref(SI_INCLUDE_KEY, &g_qeglobals.d_savedinfo.include, INCLUDE_NAMES | INCLUDE_COORDS | INCLUDE_ANGLES | INCLUDE_CAMERATINT); - mLocalPrefs.GetPref(SI_SHOWNAMES_KEY, &g_qeglobals.d_savedinfo.show_names, FALSE); - mLocalPrefs.GetPref(SI_SHOWCOORDS_KEY, &g_qeglobals.d_savedinfo.show_coordinates, TRUE); - mLocalPrefs.GetPref(SI_SHOWANGLES_KEY, &g_qeglobals.d_savedinfo.show_angles, TRUE); - mLocalPrefs.GetPref(SI_SHOWOUTLINES_KEY, &g_qeglobals.d_savedinfo.show_outline, FALSE); - mLocalPrefs.GetPref(SI_SHOWAXIS_KEY, &g_qeglobals.d_savedinfo.show_axis, TRUE); - mLocalPrefs.GetPref(SI_NOSELOUTLINES_KEY, &g_qeglobals.d_savedinfo.bNoSelectedOutlines, FALSE); - - mLocalPrefs.GetPref(SI_OUTLINESTYLE_KEY, &g_qeglobals.d_savedinfo.iSelectedOutlinesStyle, OUTLINE_ZBUF|OUTLINE_BSEL); - - LoadTexdefPref(&g_qeglobals.d_savedinfo.m_SIIncrement, SI_SURFACE_TEXDEF_KEY); - LoadTexdefPref(&g_qeglobals.d_savedinfo.m_PIIncrement, SI_PATCH_TEXDEF_KEY); - - // text editor binding -#ifdef _WIN32 - mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseWin32Editor, TRUE); -#else - mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseCustomEditor, FALSE); - mLocalPrefs.GetPref(CUSTOMSHADEREDITORCOMMAND_KEY, &m_strEditorCommand, ""); -#endif + gtk_window_set_transient_for( dialog, m_parent ); + gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT ); + { + auto mainvbox = ui::VBox( FALSE, 5 ); + dialog.add(mainvbox); + gtk_container_set_border_width( GTK_CONTAINER( mainvbox ), 5 ); + mainvbox.show(); - vec3_t vDefaultAxisColours[3] = { - {0.f, 0.5f, 0.f}, - {0.f, 0.f, 1.f}, - {1.f, 0.f, 0.f}, - }; - - for(i = 0; i < 3; i++) { - char buf[64]; - sprintf(buf, "%s%d", SI_AXISCOLORS_KEY, i); - mLocalPrefs.GetPref(buf, g_qeglobals.d_savedinfo.AxisColors[i], vDefaultAxisColours[i]); - } - - vec3_t vDefaultColours[COLOR_LAST] = { - {0.25f, 0.25f, 0.25f}, - {1.f, 1.f, 1.f}, - {0.75f, 0.75f, 0.75f}, - {0.5f, 0.5f, 0.5f}, - {0.25f, 0.25f, 0.25f}, - {0.0f, 0.0f, 0.0f}, - {0.f, 0.f, 1.f}, - {0.f, 0.f, 0.f}, - {0.f, 0.f, 0.f}, - {1.f, 0.f, 0.f}, - {0.f, 0.f, 1.f}, - {0.5f, 0.f, 0.75f}, - {1.0f, 0.f, 0.f}, - {0.f, 0.f, 0.f}, - {0.f, 0.f, 0.f}, - }; - - for(i = 0; i < COLOR_LAST; i++) { - char buf[64]; - sprintf(buf, "%s%d", SI_COLORS_KEY, i); - mLocalPrefs.GetPref(buf, g_qeglobals.d_savedinfo.colors[i], vDefaultColours[i]); - } - - mLocalPrefs.GetPref(TEXTURECOMPRESSIONFORMAT_KEY, &m_nTextureCompressionFormat, 1); - - mLocalPrefs.GetPref(LIGHTRADIUS_KEY, &m_nLightRadiuses, TRUE); - - mLocalPrefs.GetPref(Q3MAP2TEX_KEY, &m_bQ3Map2Texturing, TRUE); - -#ifdef ATIHACK_812 - mLocalPrefs.GetPref(ATIHACK_KEY, &m_bGlATIHack, FALSE); -#endif + { + auto hbox = ui::HBox( FALSE, 5 ); + hbox.show(); + mainvbox.pack_end(hbox, FALSE, TRUE, 0); - Undo_SetMaxSize(m_nUndoLevels); // set it internally as well / FIXME: why not just have one global value? + { + auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &m_modal ); + hbox.pack_end(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &m_modal ); + hbox.pack_end(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button( "Clean", G_CALLBACK( OnButtonClean ), this ); + hbox.pack_end(button, FALSE, FALSE, 0); + } + } - UpdateTextureCompression(); + { + auto hbox = ui::HBox( FALSE, 5 ); + mainvbox.pack_start( hbox, TRUE, TRUE, 0 ); + hbox.show(); + + { + auto sc_win = ui::ScrolledWindow(ui::New); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sc_win ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); + hbox.pack_start( sc_win, FALSE, FALSE, 0 ); + sc_win.show(); + gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sc_win ), GTK_SHADOW_IN ); + + // prefs pages notebook + m_notebook = ui::Widget::from(gtk_notebook_new()); + // hide the notebook tabs since its not supposed to look like a notebook + gtk_notebook_set_show_tabs( GTK_NOTEBOOK( m_notebook ), FALSE ); + hbox.pack_start( m_notebook, TRUE, TRUE, 0 ); + m_notebook.show(); + + + { + auto store = ui::TreeStore::from(gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER )); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_visible(view, FALSE ); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn( "Preferences", renderer, {{"text", 0}} ); + gtk_tree_view_append_column(view, column ); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect( "changed", G_CALLBACK( treeSelection ), this ); + } + + view.show(); + + sc_win.add(view); + + { + /********************************************************************/ + /* Add preference tree options */ + /********************************************************************/ + // Front page... + //GtkWidget* front = + PreferencePages_addPage( m_notebook, "Front Page" ); + + { + auto global = PreferencePages_addPage( m_notebook, "Global Preferences" ); + { + PreferencesPage preferencesPage( *this, getVBox( global ) ); + Global_constructPreferences( preferencesPage ); + } + auto group = PreferenceTree_appendPage( store, 0, "Global", global ); + { + auto game = PreferencePages_addPage( m_notebook, "Game" ); + PreferencesPage preferencesPage( *this, getVBox( game ) ); + g_GamesDialog.CreateGlobalFrame( preferencesPage ); + + PreferenceTree_appendPage( store, &group, "Game", game ); + } + } + + { + auto interfacePage = PreferencePages_addPage( m_notebook, "Interface Preferences" ); + { + PreferencesPage preferencesPage( *this, getVBox( interfacePage ) ); + PreferencesPageCallbacks_constructPage( g_interfacePreferences, preferencesPage ); + } + + auto group = PreferenceTree_appendPage( store, 0, "Interface", interfacePage ); + PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); + + PreferenceGroupCallbacks_constructGroup( g_interfaceCallbacks, preferenceGroup ); + } + + { + auto display = PreferencePages_addPage( m_notebook, "Display Preferences" ); + { + PreferencesPage preferencesPage( *this, getVBox( display ) ); + PreferencesPageCallbacks_constructPage( g_displayPreferences, preferencesPage ); + } + auto group = PreferenceTree_appendPage( store, 0, "Display", display ); + PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); + + PreferenceGroupCallbacks_constructGroup( g_displayCallbacks, preferenceGroup ); + } + + { + auto settings = PreferencePages_addPage( m_notebook, "General Settings" ); + { + PreferencesPage preferencesPage( *this, getVBox( settings ) ); + PreferencesPageCallbacks_constructPage( g_settingsPreferences, preferencesPage ); + } + + auto group = PreferenceTree_appendPage( store, 0, "Settings", settings ); + PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); + + PreferenceGroupCallbacks_constructGroup( g_settingsCallbacks, preferenceGroup ); + } + } + + gtk_tree_view_expand_all(view ); + + g_object_unref( G_OBJECT( store ) ); + } + } + } + } -#ifdef ATIHACK_812 - UpdateATIHack(); -#endif + gtk_notebook_set_current_page( GTK_NOTEBOOK( m_notebook ), 0 ); - if (mLocalPrefs.mbEmpty) - { - mLocalPrefs.mbEmpty = false; - Sys_Printf("Saving local.pref with default pref values\n"); - SavePrefs(); - } + return dialog; } -void PrefsDlg::SavePrefs () -{ - if (g_qeglobals.disable_ini) - return; +preferences_globals_t g_preferences_globals; -#ifdef _DEBUG - Sys_Printf("PrefsDlg::SavePrefs\n"); -#endif +PrefsDlg g_Preferences; // global prefs instance - // this will take care of copying back from the dialog to the variables - // NOTE: it may be overkill to call systematically before a SavePrefs, but it's safer - // this will also cause an UpdateData for the mGamesDialog - UpdateData(TRUE); - mGamesDialog.SavePrefs(); +void PreferencesDialog_constructWindow( ui::Window main_window ){ + g_Preferences.m_parent = main_window; + g_Preferences.Create(); +} +void PreferencesDialog_destroyWindow(){ + g_Preferences.Destroy(); +} - // update the tree and save it - mLocalPrefs.UpdatePrefTree(); - if (!mLocalPrefs.WriteXMLFile(m_inipath->str)) - Sys_FPrintf(SYS_ERR, "Error occured while saving local prefs file '%s'\n", m_inipath->str); - if ( m_nMouse == 0 ) { - m_nMouseButtons = 2; - } else { - m_nMouseButtons = 3; - } +PreferenceDictionary g_preferences; +PreferenceSystem& GetPreferenceSystem(){ + return g_preferences; } -void PrefsDlg::PostModal (int code) -{ - if (code == IDOK) - { - SavePrefs(); - // make sure the logfile is ok - Sys_LogFile(); - #ifdef ATIHACK_812 - UpdateATIHack(); - #endif - if (g_pParentWnd) - g_pParentWnd->SetGridStatus(); - Sys_UpdateWindows(W_ALL); - if (m_nUndoLevels != 0) - Undo_SetMaxSize(m_nUndoLevels); - } -} - -void PrefsDlg::DoEditorSensitivity() +class PreferenceSystemAPI { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data (G_OBJECT(m_pWidget), "check_customeditor")))) - { - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), TRUE); - } - else - { - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), FALSE); - } -} - -void PrefsDlg::DoSensitivity() -{ -#if 0 - // first, look at the project file version ... will monitoring work? - // project files now XML, guaranteed to be at least version 2 - if (0)//IntForKey( g_qeglobals.d_project_entity, "version" ) < 2) - { - if (m_bWarn) - { - Str Msg; - Msg = "The current project file ("; - Msg += g_PrefsDlg.m_strLastProject; - Msg += ") is not at least version 2.\nI need version 2 or above to setup BSP monitoring correctly."; - gtk_MessageBox(m_pWidget, Msg.GetBuffer(), MB_OK ); - - m_bWarn = false; - } - - // go ahead, disable everybuddy - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), FALSE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE ); - } - else - { -#endif -// m_bWarn = true; - - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), TRUE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), TRUE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), TRUE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), TRUE ); +PreferenceSystem* m_preferencesystem; +public: +typedef PreferenceSystem Type; +STRING_CONSTANT( Name, "*" ); - if ( ! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" ) ) ) ) - { - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE ); - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE ); - } else if (! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" ) ) ) ) - { - gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE ); - } +PreferenceSystemAPI(){ + m_preferencesystem = &GetPreferenceSystem(); } +PreferenceSystem* getTable(){ + return m_preferencesystem; +} +}; -/* -============================================================ -CGameInstall -============================================================ -*/ +#include "modulesystem/singletonmodule.h" +#include "modulesystem/moduleregistry.h" -CGameInstall::CGameInstall() { - memset( m_availGames, 0, sizeof( m_availGames ) ); +typedef SingletonModule PreferenceSystemModule; +typedef Static StaticPreferenceSystemModule; +StaticRegisterModule staticRegisterPreferenceSystem( StaticPreferenceSystemModule::instance() ); + +void Preferences_Load(){ + g_GamesDialog.LoadPrefs(); + + globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n"; + + if ( !Preferences_Load( g_preferences, g_Preferences.m_inipath->str, g_GamesDialog.m_sGameFile.c_str() ) ) { + globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n"; + } } -void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) { - Sys_Printf( "OnBtnBrowseEngine\n" ); +void Preferences_Save(){ + if ( g_preferences_globals.disable_ini ) { + return; + } - CGameInstall* i = static_cast( data ); - char *dir = dir_dialog( i->m_pWidget, _("Select game directory"), NULL ); + // save global preferences + g_GamesDialog.SavePrefs(); - i->UpdateData( TRUE ); + globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n"; - if ( dir != NULL ) { - i->m_strEngine = dir; - i->UpdateData( FALSE ); - g_free( dir ); + if ( !Preferences_Save_Safe( g_preferences, g_Preferences.m_inipath->str ) ) { + globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n"; } } -void CGameInstall::OnGameSelectChanged( GtkWidget *widget, gpointer data ) { - Sys_Printf( "OnGameSelectChanged\n" ); - - CGameInstall* i = static_cast( data ); - i->UpdateData( TRUE ); - i->m_strName = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ) ); - i->UpdateData( FALSE ); +void Preferences_Reset(){ + file_remove( g_Preferences.m_inipath->str ); } -void CGameInstall::BuildDialog() { - GtkWidget *dlg, *vbox1, *button, *text, *combo, *entry, *hbox; - dlg = m_pWidget; - gtk_window_set_title( GTK_WINDOW( dlg ), _("Configure games") ); +void PrefsDlg::PostModal( EMessageBoxReturn code ){ + if ( code == eIDOK ) { + Preferences_Save(); + UpdateAllWindows(); + } +} - vbox1 = gtk_vbox_new( FALSE, 0 ); - gtk_widget_show( vbox1 ); - gtk_container_add( GTK_CONTAINER( dlg ), vbox1 ); +std::vector g_restart_required; - text = gtk_label_new( _("Select the game to configure") ); - gtk_widget_show( text ); - gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); +void PreferencesDialog_restartRequired( const char* staticName ){ + g_restart_required.push_back( staticName ); +} - combo = gtk_combo_box_new_text(); - gtk_widget_show( combo ); - gtk_box_pack_start( GTK_BOX( vbox1 ), combo, FALSE, FALSE, 0 ); +void PreferencesDialog_showDialog(){ + if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) { + if ( !g_restart_required.empty() ) { + StringOutputStream message( 256 ); + message << "Preference changes require a restart:\n\n"; - // GList *combo_list = NULL; - int iGame = 0; - while ( m_availGames[ iGame ] != GAME_NONE ) { - switch ( m_availGames[ iGame ] ) { - case GAME_Q2: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Quake II") ); - break; - case GAME_Q3: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Quake III Arena and mods") ); - break; - case GAME_URT: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Urban Terror (standalone)") ); - break; - case GAME_UFOAI: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("UFO: Alien Invasion") ); - break; - case GAME_Q2W: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Quake2World") ); - break; - case GAME_WARSOW: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Warsow") ); - break; - case GAME_NEXUIZ: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Nexuiz") ); - break; - case GAME_TREMULOUS: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Tremulous") ); - break; - case GAME_JA: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Jedi Academy and mods") ); - break; - case GAME_REACTION: - gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Reaction Quake 3") ); - break; - } - iGame++; - } - AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT ); - gtk_signal_connect( GTK_OBJECT( combo ), "changed", G_CALLBACK( OnGameSelectChanged ), this ); - gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 ); // NOTE: will trigger signal - - text = gtk_label_new( _("Name:") ); - gtk_widget_show( text ); - gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); - - entry = gtk_entry_new(); - gtk_widget_show( entry ); - gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 ); - AddDialogData( entry, &m_strName, DLG_ENTRY_TEXT ); - - text = gtk_label_new( _("Engine directory:") ); - gtk_widget_show( text ); - gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); - - hbox = gtk_hbox_new( FALSE, 0 ); - gtk_widget_show( hbox ); - gtk_box_pack_start( GTK_BOX( vbox1 ), hbox, FALSE, FALSE, 0 ); - - entry = gtk_entry_new(); - gtk_widget_show( entry ); - gtk_box_pack_start( GTK_BOX( hbox ), entry, FALSE, FALSE, 0 ); - AddDialogData( entry, &m_strEngine, DLG_ENTRY_TEXT ); - - button = gtk_button_new_with_label (_("...")); - gtk_widget_show( button ); - gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEngine ), this ); - gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 ); - - // this gets done in the project stuff atm -#if 0 - text = gtk_label_new( _("Mod subdirectory:") ); - gtk_widget_show( text ); - gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); - - entry = gtk_entry_new(); - gtk_widget_show( entry ); - gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 ); - AddDialogData( entry, &m_strMod, DLG_ENTRY_TEXT ); -#endif + for ( std::vector::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i ) + { + message << ( *i ) << '\n'; + } - button = gtk_button_new_with_label( _("OK") ); - gtk_widget_show( button ); - gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); - AddModalButton( button, IDOK ); + message << "\nRestart now?"; - button = gtk_button_new_with_label( _("Cancel") ); - gtk_widget_show( button ); - gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); - AddModalButton( button, IDCANCEL ); + auto ret = ui::alert( MainFrame_getWindow(), message.c_str(), "Restart " RADIANT_NAME "?", ui::alert_type::YESNO, ui::alert_icon::Question ); - gtk_widget_set_usize( button, 60, -2 ); -} + g_restart_required.clear(); -void CGameInstall::Run() { - ScanGames(); - if ( m_availGames[0] == GAME_NONE ) { - return; - } - if ( DoModal() == IDCANCEL ) { - Sys_Printf( "game dialog cancelled\n" ); - return; - } - Sys_Printf( "combo: %d name: %s engine: %s mod: %s\n", m_nComboSelect, m_strName.GetBuffer(), m_strEngine.GetBuffer(), m_strMod.GetBuffer() ); - - // write out the game file - Str gameFilePath = g_strAppPath.GetBuffer(); - gameFilePath += "games/"; - gameFilePath += m_strName.GetBuffer(); - gameFilePath += ".game"; - Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() ); - - FILE * fg = fopen( gameFilePath.GetBuffer(), "w" ); - if ( fg == NULL ) { - Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() ); - } - fprintf( fg, "\n &returnz) { + returnz(gamename_get()); } - case GAME_REACTION: { - fprintf( fg, " "TOOLS_ATTRIBUTE"=\"%sinstalls/"REACTION_PACK"/game\"\n", g_strAppPath.GetBuffer() ); - fprintf( fg, " prefix=\".Reaction\"\n" ); - Str source = g_strAppPath.GetBuffer(); - source += "installs/"; - source += REACTION_PACK; - source += "/install/"; - Str dest = m_strEngine.GetBuffer(); - CopyTree( source.GetBuffer(), dest.GetBuffer() ); - fprintf( fg, " basegame=\"Boomstick\"\n" ); - fprintf( fg, " default_scale=\"0.5\"\n" ); // Superfluous because the default is already 0.5, - // but demonstrates how to set the default texture scale - // for a specific game. - break; + + static void Import(const char *value) { + gamename_set(value); } +}; + +struct GameMode { + static void Export(const Callback &returnz) { + returnz(gamemode_get()); } - fprintf( fg, "/>\n" ); - fclose( fg ); -} -/* -=============== -CGameInstall::ScanGames -scan for active games that can be installed, based on the presence -=============== -*/ -void CGameInstall::ScanGames() { - Str pakPaths = g_strAppPath.GetBuffer(); - int iGame = 0; - const char *dirname; - - pakPaths += "installs/"; - FindFiles fileScan( pakPaths.GetBuffer() ); - while ( ( dirname = fileScan.NextFile() ) != NULL ) { - if ( stricmp( dirname, Q3_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_Q3; - } - if ( stricmp( dirname, URT_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_URT; - } - if ( stricmp( dirname, UFOAI_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_UFOAI; - } - if ( stricmp( dirname, Q2W_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_Q2W; - } - if ( stricmp( dirname, WARSOW_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_WARSOW; - } - if ( stricmp( dirname, NEXUIZ_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_NEXUIZ; - } - if ( stricmp( dirname, Q2_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_Q2; - } - if ( stricmp( dirname, TREMULOUS_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_TREMULOUS; - } - if ( stricmp( dirname, JA_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_JA; - } - if ( stricmp( dirname, REACTION_PACK ) == 0 ) { - m_availGames[ iGame++ ] = GAME_REACTION; - } + static void Import(const char *value) { + gamemode_set(value); } - Sys_Printf("No installable games found in: %s\n", - pakPaths.GetBuffer() ); +}; + +void RegisterPreferences( PreferenceSystem& preferences ){ +#if GDEF_OS_WINDOWS + preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) ); +#else + preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useCustomEditor ) ); + preferences.registerPreference( "CustomShaderEditorCommand", make_property_string( g_TextEditor_editorCommand ) ); +#endif + + preferences.registerPreference( "GameName", make_property() ); + preferences.registerPreference( "GameMode", make_property() ); } +void Preferences_Init(){ + RegisterPreferences( GetPreferenceSystem() ); +}