/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program 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, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ### File Specific: main-programmer: Benjamin Grauer */ #include "gui_exec.h" #include "resource_manager.h" #include "parser/ini_parser/ini_parser.h" #include #include #include #include #ifdef __WIN32__ #include #endif /* __WIN32__ */ HashTable* orxonoxFlagHash; /** * Creates the Exec-Frame */ GuiExec::GuiExec() { Frame* execFrame; //!< The Frame that holds the ExecutionOptions. this->confFile = NULL; this->confDir = NULL; execFrame = new Frame("Execute-Tags:"); { Box* execBox; //!< The Box that holds the ExecutionOptions. execBox = new Box('v'); execFrame->setGroupName(CONFIG_SECTION_MISC); { Button* start; //!< The start Button of orxonox. Menu* verboseMode; //!< A Menu for setting the verbose-Mode. @todo setting up a verbose-class. CheckButton* alwaysShow; //!< A CheckButton, for if orxonox should start with or without gui. Button* quit; //!< A Button to quit the Gui without starting orxonox. start = new Button("Start"); #ifdef HAVE_GTK2 start->connectSignal("clicked", this, startOrxonox); #endif /* HAVE_GTK2 */ execBox->fill(start); this->saveSettings = new CheckButton(CONFIG_NAME_SAVE_SETTINGS); this->saveSettings->value = 1; this->saveSettings->saveability(); execBox->fill(this->saveSettings); #ifdef DEBUG verboseMode = new Menu(CONFIG_NAME_VERBOSE_MODE, "nothing", #if DEBUG >=1 "error", #endif #if DEBUG >=2 "warning", #endif #if DEBUG >=3 "info", #endif #if DEBUG >=4 "debug", #endif #if DEBUG >=5 "heavydebug", #endif "lastItem"); verboseMode->setFlagName("verbose", "v", 2); verboseMode->setDescription("Sets the Output Mode", "This Enables Outbug messages\n" "0: nothing will be displayed, but stuff one cannot do without (eg.GUI)\n" #if DEBUG >=1 "1: error: outputs all the above and errors" #endif #if DEBUG >=2 "2: warning: outputs all the above plus warnings" #endif #if DEBUG >=3 "3: info: outputs all the above plus Information" #endif #if DEBUG >=4 "4: debug: displays all the above plus debug information" #endif #if DEBUG >=5 "5: heavydebug: displays all the above plus heavy debug information: WARNING: the game will run very slow with this." #endif ); verboseMode->saveability(); execBox->fill(verboseMode); #endif alwaysShow = new CheckButton(CONFIG_NAME_ALWAYS_SHOW_GUI); alwaysShow->setFlagName("gui", "g", 0); alwaysShow->setDescription("shows the gui when starting orxonox"); alwaysShow->saveability(); execBox->fill(alwaysShow); quit = new Button("Quit"); #ifdef HAVE_GTK2 quit->connectSignal("clicked", this, GuiExec::quitGui); // Window::mainWindow->connectSignal("remove", this, GuiExec::quitGui); Window::mainWindow->connectSignal("destroy", this, GuiExec::quitGui); #endif /* HAVE_GTK2 */ execBox->fill(quit); } execFrame->fill(execBox); } setMainWidget(execFrame); } /** * Destructs the Execution-stuff */ GuiExec::~GuiExec() { if(this->confFile) delete []this->confFile; if(this->confDir) delete []this->confDir; } /* FILE HANDLING */ /** * sets the Directory of the configuration files * @param confDir the Directory for the configuration files */ void GuiExec::setConfDir(const char* confDir) { this->confDir = ResourceManager::homeDirCheck(confDir); PRINTF(5)("Config Directory is: %s.\n", this->confDir); //! @todo F** Windows-support #ifndef __WIN32__ mkdir(this->confDir, 0755); #else /* __WiN32__ */ mkdir(this->confDir); #endif /* __WIN32__ */ } /** * Sets the location of the configuration File. * @param fileName the location of the configFile The name will be parsed from ~/ to /home/[username] on unix and c:/Documents and Settings/username/Settings/ on Windows */ void GuiExec::setConfFile(const char* fileName) { if (!this->confDir) this->setConfDir("~/"); this->confFile = new char[strlen(this->confDir)+strlen(fileName)+2]; sprintf(this->confFile, "%s/%s", this->confDir, fileName); PRINTF(5)("ConfigurationFile is %s.\n", this->confFile); } /** * @returns The name of the Configuration-File */ const char* GuiExec::getConfigFile() const { return this->confFile; } /** * checks if a option should be saved. * @return 1 if it should 0 if not/ */ int GuiExec::shouldsave() { return(static_cast(this->saveSettings)->value); } /** * Saves the configuration-file to the Disk.\n * @param widget from which Widget on should be saved. this Function only opens and closes the file, in between GuiExec::writeFileText(Widget* widget) will execute the real writing process. */ void GuiExec::writeToFile(Widget* widget) { IniParser iniParser; this->writeFileText(widget, &iniParser, 0); char* fileName = ResourceManager::homeDirCheck(confFile); iniParser.writeFile(fileName); delete[] fileName; } /** * Actually writes into the configuration file to the disk. * @param widget from which Widget on should be saved. * @param parser the IniParser to write to. * @param depth initially "0", and grows higher, while new Groups are bundeled. */ void GuiExec::writeFileText(Widget* widget, IniParser* parser, int depth) { // int counter = 0; // while(counter < depth &&((widget->optionType > GUI_NOTHING // &&(static_cast(widget)->isSaveable())) // ||(widget->optionType < GUI_NOTHING // && static_cast(widget)->getGroupName()))) // { // fprintf(this->CONFIG_FILE, " ", depth); // counter++; // } // check if it is a Packer, and if it is, check if it has a name and if there is something in it. if(widget->optionType < GUI_NOTHING) { if(static_cast(widget)->getGroupName()) { parser->addSection(static_cast(widget)->getGroupName()); this->writeFileText(static_cast(widget)->down, parser, depth+1); } else { this->writeFileText(static_cast(widget)->down, parser, depth); } } if(widget->optionType > GUI_NOTHING) if (static_cast(widget)->isSaveable()) { char* saveName = static_cast(widget)->save(); parser->addVar(static_cast(widget)->title, saveName); delete[] saveName; } if(widget->next != NULL) this->writeFileText(widget->next, parser, depth); } /** * @brief Reads in Configuration Data. * @param widget from which Widget on should be saved. */ void GuiExec::readFromFile(Widget* widget) { char* fileName = ResourceManager::homeDirCheck(confFile); IniParser iniParser(fileName); delete[] fileName; if (!iniParser.isOpen()) return; iniParser.firstSection(); Widget* groupWidget = widget; const char* groupName; const char* widgetName; VarInfo varInfo; while (groupName = iniParser.getCurrentSection()) { printf("GROUP:::%s\n", groupName); if((groupWidget = locateGroup(widget, groupName, 1))==NULL) { PRINTF(2)("!!There is no group called %s in this GUI.\n First best Widget will get the Infos assigned.\n Config-File will be updated in next Save\n", groupName); groupWidget = widget; continue; } else PRINT(4)("Group %s located.\n", static_cast(groupWidget)->groupName); const char* entryName; iniParser.firstVar(); while(entryName = iniParser.getCurrentName()) { PRINTF(4)("ENTRY:::%s = %s\n", entryName, iniParser.getCurrentValue()); varInfo.variableName = entryName; varInfo.variableValue = iniParser.getCurrentValue(); groupWidget->walkThrough(this->readFileText, &varInfo, 0); iniParser.nextVar(); } iniParser.nextSection(); } widget->walkThrough(widget->setOptions, 0); } /** * Maps Confugurations to the Options. * @param widget which widget downwards * @param varInfo Information about the Variable to read */ void GuiExec::readFileText(Widget* widget, void* varInfo) { VarInfo* info =(VarInfo*)varInfo; if (info == NULL || info->variableName == NULL) return; if(widget->title && !strcmp(widget->title, info->variableName)) { PRINT(5)("Located Option %s.\n", widget->title); if(widget->optionType > GUI_NOTHING) if (info->variableValue != NULL) static_cast(widget)->load(info->variableValue); } } /** * Locates a Group. * @param widget The Widget from where to search from * @param groupName The GroupName for which to search. * @param depth The Depth of the search seen from the first widget we searched from. * @returns The Widget that holds the Group, or the NULL if the Group wasn't found. @todo do this in gui-gtk. */ Widget* GuiExec::locateGroup(Widget* widget, const char* groupName, int depth) { Widget* tmp; if (widget == NULL || groupName == NULL) return NULL; if(widget->optionType < GUI_NOTHING) { if(static_cast(widget)->getGroupName() != NULL && !strcmp(groupName, static_cast(widget)->getGroupName())) return widget; else { if((tmp = locateGroup(static_cast(widget)->down, groupName, depth+1)) != NULL) return tmp; } } if(widget->next != NULL && depth != 0) { if((tmp = locateGroup(widget->next, groupName, depth)) != NULL) return tmp; } return NULL; } /** * Starts ORXONOX.(not really implemented yet, but the function is there.\n * @param widget the widget that executed the start command * @param data additional data This is a Signal and can be executed through Widget::signal_connect */ #ifdef HAVE_GTK2 int GuiExec::startOrxonox(GtkWidget* widget, void* data) #else /* HAVE_GTK2 */ int GuiExec::startOrxonox(void* widget, void* data) #endif /* HAVE_GTK2 */ { Window::mainWindow->hide(); #ifdef HAVE_GTK2 gtk_widget_destroy(Window::mainWindow->widget); #else quitGui(widget, data); #endif /* HAVE_GTK2 */ PRINT(3)("Starting Orxonox\n"); Gui::startOrxonox = true; } /** * Starts ORXONOX.(not really implemented yet, but the function is there.\n * @param widget the widget that executed the start command * @param data additional data This is a Signal and can be executed through Widget::signal_connect */ #ifdef HAVE_GTK2 int GuiExec::quitGui(GtkWidget* widget, void* data) #else /* HAVE_GTK2 */ int GuiExec::quitGui(void* widget, void* data) #endif /* HAVE_GTK2 */ { GuiExec* exec = (GuiExec*)data; if(exec->shouldsave()) exec->writeToFile(Window::mainWindow); #ifdef HAVE_GTK2 gtk_main_quit(); while(gtk_events_pending()) gtk_main_iteration(); #endif /* HAVE_GTK2 */ }