/* 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_gtk.h" #include #include #include #include using namespace std; #include "gui_flags.h" #include "gui_exec.h" extern GuiFlags* flags; char* executable; /** * Initializes the Guis GTK-stuff. * @param argc the argument count. * @param argv The Argument strings. */ bool initGUI(int argc, char *argv[]) { if (argv) { executable = new char[strlen(argv[0])+1]; strcpy(executable, argv[0]); } else executable = NULL; #ifdef HAVE_GTK2 gtk_init(&argc, &argv); #include "rc" gtk_rc_parse_string( rc_string ); #endif /* HAVE_GTK2 */ } /** * enters the GUI's main-loop */ bool mainloopGUI() { #ifdef HAVE_GTK2 gtk_main(); #else /* HAVE_GTK2 */ char boolAns = 'y'; char ans[1000]; PRINT(0)("================================\n"); PRINT(0)("= ORXONOX CONFIGURATION WIZARD =\n"); PRINT(0)("================================ - v." PACKAGE_VERSION "\n"); while(true) { PRINT(0)("\n Listing all the Orxonox Options: \n"); PRINT(0)(" #############################\n"); Window::mainWindow->walkThrough(Widget::listOptionsAndGroups, 1); PRINT(0)("\nDo you want change any of the above values now? [Yn] "); scanf("%s", ans); if (ans[0] =='n' || ans[0]=='N') break; PRINT(0)("\n Listing all groups\n"); PRINT(0)(" #################\n"); int groupCount = 0; Window::mainWindow->walkThrough(Widget::listGroups, &groupCount, 1); PRINT(0)("\nIn which Group? [1-%d] ", groupCount); Packer* group; while(true) { scanf("%s", ans); int ansIp = atoi(ans); if (ansIp <= groupCount) { group = static_cast(Window::mainWindow->findGroupByNumber(&ansIp, 1)); break; } else PRINT(0)("\nChoose a smaller Number please: [1-%d] ", groupCount); } PRINT(0)("\n\nGroup: [%s]\n\n", group->groupName); int optionCount = 0; group->walkThrough(Widget::listOptions, &optionCount, 0); PRINT(0)("\nWhich Option? [1-%d] ", optionCount); Option* option; while(true) { scanf("%s", ans); int ansIp = atoi(ans); if (ansIp <= groupCount) { option = static_cast(group->findOptionByNumber(&ansIp, 0)); break; } else PRINT(0)("\nChoose a smaler Number please: [1-%d] ", optionCount); } PRINT(0)("\n\n:: %s ::\n", option->title); option->changeOption(); // here follows the rest.... this will be nasty. //! @todo finish it. //! @todo memory leek at save(); and save is a BAD word, use saveString instead, or something like it. } #endif /* HAVE_GTK2 */ } ////////////////////////////// /// DEFINING WIDGET-CLASES /// ////////////////////////////// //////////// /* WIDGET */ //////////// /** * constructs a Widget */ Widget::Widget() { next = NULL; this->title = NULL; } /** * deletes any given Widget This is still pretty crappy. */ Widget::~Widget() { if (this->title) { delete []this->title; } PRINTF(5)("deleting the Widget part.\n"); // deleting next item if existent if (this->next) delete this->next; this->next = NULL; //! @todo not hiding widget, deleting. // this->hide(); // gtk_destroy_widget(this->widget); } /** * sets a new Title to a Widget * @param title The new Title to set to the Widget */ void Widget::setTitle(const char* title) { if (this->title) delete []this->title; this->title = new char[strlen(title)+1]; strcpy(this->title, title); } /** * makes the widget visible. */ void Widget::show() { #ifdef HAVE_GTK2 gtk_widget_show(this->widget); #endif /* HAVE_GTK2 */ } /** * hides the widget. */ void Widget::hide() { #ifdef HAVE_GTK2 gtk_widget_hide(this->widget); #endif /* HAVE_GTK2 */ } /** * Sets the resolution of a specific widget to the given size. * @param width the width of the widget to set. * @param height the height of the widget to set. */ void Widget::setSize(int width, int height) { #ifdef HAVE_GTK2 gtk_widget_set_usize(this->widget, width, height); #endif /* HAVE_GTK2 */ } /** * searches through widgets for a Name. */ Widget* Widget::findWidgetByName(char* name, unsigned int depth) { if (this->title && !strcmp(this->title, name)) return this; if (this->optionType < GUI_NOTHING && static_cast(this)->down) { Widget* tmp = static_cast(this)->down->findWidgetByName(name, depth+1); if (tmp) return tmp; } if (depth>0 && this->next) return this->next->findWidgetByName(name, depth); return NULL; } /** * Moves through all the Widgets downwards from this and executes the function on them. * @param function must be of type void and takes a Widget* as an Input. * @param depth the current depth. if > 0 then the next Widget will also be walked through. */ void Widget::walkThrough(void(*function)(Widget*), unsigned int depth) { function(this); if (this->optionType < GUI_NOTHING) { static_cast(this)->down->walkThrough(function, depth+1); } if (this->next && depth != 0) this->next->walkThrough(function, depth); } /** * Moves through all the Widgets downwards from this and executes the function on them. * @param function must be of type void and takes a Widget* as an Input. * @param data Additional Data you want to pass to the function. * @param depth the current depth. if > 0 then the next Widget will also be walked through. */ void Widget::walkThrough(void(*function)(Widget*, void*), void* data, unsigned int depth) { function(this, data); if (this->optionType < GUI_NOTHING) { static_cast(this)->down->walkThrough(function, data, depth+1); } if (this->next && depth != 0) this->next->walkThrough(function, data, depth); } /** * This is for listing the options of "widget" * @param widget specifies the widget that should be listed */ void Widget::listOptionsAndGroups(Widget* widget) { if (widget->optionType < GUI_NOTHING && static_cast(widget)->groupName) PRINT(0)("[%s]\n", static_cast(widget)->groupName); if (widget->optionType > GUI_NOTHING) { Widget::listOptions(widget); } } /** * This is for listing the options of "widget" * @param widget specifies the widget that should be listed */ void Widget::listOptions(Widget* widget) { if(widget->optionType > GUI_NOTHING) PRINT(0)(" %s is %s\n", static_cast(widget)->title, static_cast(widget)->save()); } /** * This is for listing the options of "widget" * @param widget specifies the widget that should be listed * @param data A Counter, that always knows how many Options have been found yet. */ void Widget::listOptions(Widget* widget, void* data) { if (widget->optionType > GUI_NOTHING) { int* count =(int*)data; *count = *count +1; PRINT(0)(" %d:%s is %s\n", *count, static_cast(widget)->title, static_cast(widget)->save()); } } /** * This is for listing the options of "widget" * @param widget specifies the widget that should be listed * @param data A Counter, that always knows how many Options have been found yet. */ void Widget::printHelp(Widget* widget) { int helpLen=0; if (widget->optionType > GUI_NOTHING) { Option* option = (Option*)widget; if (option->flagName || option->flagNameShort) { PRINT(0)(" "); if (option->flagNameShort) { PRINT(0)("-%s", option->flagNameShort); helpLen += strlen(option->flagNameShort)+1; } if (option->flagName) { if (helpLen > 0) { PRINT(0)("|"); helpLen++; } PRINT(0)("--%s:", option->flagName); helpLen += strlen(option->flagName)+2; } while ((helpLen ++) < 29) PRINT(0)(" "); if (option->shortDescription) PRINT(0)("%s\n", option->shortDescription); else PRINT(0)("\n"); } } } /** * Finds an Option by a given number(the n'th option found away from this Widget) * @param number The Count of options to wait(by reference) * @param depth The depth of the sarch. if 0 it will not search next pointer @todo should return Option* would be much sexier. */ Widget* Widget::findOptionByNumber(int* number, unsigned int depth) { if (optionType > GUI_NOTHING) { --*number; if (*number <= 0) { return this; } } if (this->optionType < GUI_NOTHING && static_cast(this)->down) { Widget* tmp = static_cast(this)->down->findOptionByNumber(number, depth+1); if (tmp) return tmp; } if (depth>0 && this->next) return this->next->findOptionByNumber(number, depth); return NULL; } /** * This is for listing the groups of "widget" * @param widget specifies the widget that should be listed */ void Widget::listGroups(Widget* widget) { if (widget->optionType < GUI_NOTHING && static_cast(widget)->groupName) PRINT(0)("[%s]\n", static_cast(widget)->groupName); } /** * This is for listing the Groups of "widget". It also displays the n'th number found. * @param widget specifies the widget that should be listed * @param data the Counter, that will show the number(this function will raise it by one if a Group is fount. */ void Widget::listGroups(Widget* widget, void* data) { int* count = (int*)data; if (widget->optionType < GUI_NOTHING && static_cast(widget)->groupName) PRINT(0)("%d: [%s]\n", ++*count, static_cast(widget)->groupName); } /** * Finds a Group by a given number(the n'th Group found away from this Widget) * @param number The Count of options to wait(by reference) * @param depth The depth of the sarch. if 0 it will not search next pointer */ Widget* Widget::findGroupByNumber(int* number, unsigned int depth) { if (optionType < GUI_NOTHING && static_cast(this)->groupName) { --*number; if (*number <= 0) { return this; } } if (this->optionType < GUI_NOTHING && static_cast(this)->down) { Widget* tmp = static_cast(this)->down->findGroupByNumber(number, depth+1); if (tmp) return tmp; } if (depth>0 && this->next) return this->next->findGroupByNumber(number, depth); return NULL; } /** * This is for setting the option of "widget" * @param widget specifies the widget that should be set. */ void Widget::setOptions(Widget* widget) { if (widget->optionType > GUI_NOTHING) static_cast(widget)->redraw(); } /** * redraws all the Widgets down from widget * @param widget The topmost Widget * @param data ... */ void Widget::redrawOptions(Widget* widget) { if (widget->optionType > GUI_NOTHING) static_cast(widget)->redraw(); } /** * Walks through all the Flags given at startuptime. */ void Widget::flagCheck(Widget* widget, void* flagName) { if (widget->optionType > GUI_NOTHING) { Option* option =(Option*)widget; char* name =(char*)flagName; char* value = NULL; bool found = false; // check if long flag matches if ((option->flagName && strlen(name) > 2 && !strncmp(name+2, option->flagName, strlen(option->flagName)) && (name[strlen(option->flagName)+2] == '\0' || name[strlen(option->flagName)+2] == '=') )) { found = true; if (name[strlen(option->flagName)+2] == '=') { value = name+strlen(option->flagName)+3; } } // check if short flag matches else if (option->flagNameShort && strlen(name)>1 && !strncmp(name+1, option->flagNameShort, strlen(option->flagNameShort)) && (name[strlen(option->flagNameShort)+1] == '\0' || name[strlen(option->flagNameShort)+1] == '=')) { found = true; if (name[strlen(option->flagNameShort)+1] == '=') { value = name+strlen(option->flagNameShort)+2; } } if (found) { PRINT(4)("found matching Flag %s\n", name); if (value) { PRINT(4)("with Value %s\n", value); option->value = atoi(value); } else { option->value = !option->defaultValue; } option->redraw(); } } } #ifdef HAVE_GTK2 /** * Connect any signal to any given Sub-widget */ gulong Widget::connectSignal(char* event, gint(*signal)(GtkWidget*, GdkEvent*, void *)) { return g_signal_connect(G_OBJECT(this->widget), event, G_CALLBACK(signal), NULL); } /** * Connect a signal with additionally passing the whole Object */ gulong Widget::connectSignal(char* event, gint(*signal)( GtkWidget*, Widget *)) { return g_signal_connect(G_OBJECT(this->widget), event, G_CALLBACK(signal), this); } /** * Connect a signal with additionally passing a whole external Object */ gulong Widget::connectSignal(char* event, void* extObj, gint(*signal)(GtkWidget*, GdkEvent*, void *)) { return g_signal_connect(G_OBJECT(this->widget), event, G_CALLBACK(signal), extObj); } /** * Connect a signal with additionally passing a whole external Object */ gulong Widget::connectSignal(char* event, void* extObj, gint(*signal)(GtkWidget*, void *)) { return g_signal_connect(G_OBJECT(this->widget), event, G_CALLBACK(signal), extObj); } /** * Connect a signal with additionally passing a whole external Object */ gulong Widget::connectSignal(char* event, void* extObj, gint(*signal)(GtkWidget*, GdkEventKey*, void *)) { return g_signal_connect(G_OBJECT(this->widget), event, G_CALLBACK(signal), extObj); } void Widget::disconnectSignal(gulong signalID) { g_signal_handler_disconnect(G_OBJECT(this->widget), signalID); } /** * Signal that does absolutely nothing * @param widget The widget that initiated the Signal * @param event The event-type. * @param nothing nothin. */ gint Widget::doNothingSignal(GtkWidget *widget, GdkEvent* event, void* nothing) { } #endif /* HAVE_GTK2 */ ///////////// /* PACKERS */ ///////////// /** * Constructs a Packer */ Packer::Packer() { this->down = NULL; this->groupName = NULL; } /** * Destroys a Packer. */ Packer::~Packer() { PRINTF(5)("deleting the Packer part.\n"); if (this->groupName) delete []this->groupName; //deleting recursively. if (this->down) delete this->down; } /** * Sets the group name under which all the lower widgets of this will be saved. * @param name The name of the group. */ void Packer::setGroupName(const char* name) { if (this->groupName) delete []this->groupName; this->groupName = new char[strlen(name)+1]; strcpy(this->groupName, name); } //////////////// /* CONTAINERS */ //////////////// /** * Initializes a Container. sets the Container-Specific defaults. */ Container::Container() { this->optionType = GUI_CONTAINER; } /** * Destroys a Container. */ Container::~Container() { PRINTF(5)("deleting the Container part.\n"); } /** * Fills a Container with lowerWidget. * @param lowerWidget the Widget that should be filled into the Container. It does this by filling up the down pointer only if down points to NULL. */ void Container::fill(Widget* lowerWidget) { if (this->down == NULL) { #ifdef HAVE_GTK2 gtk_container_add(GTK_CONTAINER(this->widget), lowerWidget->widget); #endif /* HAVE_GTK2 */ this->down = lowerWidget; } else PRINTF(2)("You tried to put more than one Widget into a Container. \nNot including this item.\nThis is only possible with Boxes.\n"); } /** * @param borderwidth sets the Width of the border */ void Container::setBorderWidth(int borderwidth) { this->borderwidth = borderwidth; #ifdef HAVE_GTK2 gtk_container_set_border_width(GTK_CONTAINER(widget), borderwidth); #endif /* HAVE_GTK2 */ } //////////// /* WINDOW */ //////////// /** * The main Window of Th Gui */ Window* Window::mainWindow = NULL; /** * Creating a Window with a name * @param windowName the name the window should get. */ Window::Window(const char* windowName) { if (!mainWindow) { mainWindow = this; this->isOpen = true; } isOpen = false; #ifdef HAVE_GTK2 widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_policy(GTK_WINDOW(widget), TRUE, TRUE, TRUE); #if !defined(__WIN32__) // gtk_window_set_decorated(GTK_WINDOW(widget), FALSE); #endif gtk_container_set_border_width(GTK_CONTAINER(widget), 3); #endif /* HAVE_GTK2 */ if (windowName) this->setTitle(windowName); } /** * Destructs a Window. */ Window::~Window() { PRINTF(5)("deleting the Window: %s\n", this->title); } /** * Adds a new Window Windows to the List of Windows. * @param windowToAdd The Windows that should be added to the List @todo this instead of windowToAdd(possibly) */ void Window::addWindow(Window* windowToAdd) { if (!mainWindow) { mainWindow = windowToAdd; windowToAdd->isOpen = true; } else { Widget* tmpWindow = mainWindow; while(tmpWindow->next) tmpWindow = tmpWindow->next; tmpWindow->next = windowToAdd; windowToAdd->isOpen = false; } return; } /** * Shows all Widgets that are included within this->widget. */ void Window::showall() { #ifdef HAVE_GTK2 if (!this->isOpen) gtk_widget_show_all(this->widget); else gtk_widget_show(this->widget); #endif /* HAVE_GTK2 */ } /** * Set The Window-title to title * @param title title the Window should get. */ void Window::setTitle(const char* title) { if (this->title) delete []this->title; this->title = new char[strlen(title)+1]; strcpy(this->title, title); #ifdef HAVE_GTK2 gtk_window_set_title(GTK_WINDOW(widget), title); #endif /* HAVE_GTK2 */ } /** * opens up a Window and fixes the Focus to it */ void Window::open() { if (this != mainWindow) { isOpen = true; #ifdef HAVE_GTK2 gtk_widget_show_all(this->widget); gtk_grab_add(this->widget); #endif /* HAVE_GTK2 */ } } /** * closes up a Window and removes the Focus from it */ void Window::close() { if (this != mainWindow) { this->isOpen = false; #ifdef HAVE_GTK2 gtk_grab_remove(this->widget); gtk_widget_hide(this->widget); #endif /* HAVE_GTK2 */ } } /** * opens up a window(not topmost Window). this is the Signal that does it. !!SIGNALS ARE STATIC!! * @param widget the widget that did it. * @param event the event that did it. * @param window the Window that should be opened */ #ifdef HAVE_GTK2 gint Window::windowOpen(GtkWidget* widget, GdkEvent* event, void* window) { static_cast(window)->open(); } #else /* HAVE_GTK2 */ int Window::windowOpen(void* widget, void* event, void* window){} #endif /* HAVE_GTK2 */ /** * closes a window(not topmost Window). this is the Signal that does it. !!SIGNALS ARE STATIC!! * @param widget the widget that did it! * @param event the event that did it! * @param window the Window that should be closed */ #ifdef HAVE_GTK2 gint Window::windowClose(GtkWidget* widget, GdkEvent* event, void* window) { static_cast(window)->close(); } #else /* HAVE_GTK2 */ int Window::windowClose(void* widget, void* event, void* window){} #endif /* HAVE_GTK2 */ /////////// /* FRAME */ /////////// /** * Creates a new Frame with name title */ Frame::Frame(const char* frameName) { #ifdef HAVE_GTK2 this->widget = gtk_frame_new(""); gtk_container_set_border_width(GTK_CONTAINER(this->widget), 3); #endif /* HAVE_GTK2 */ if (frameName) this->setTitle(frameName); } /** * destrcucts a Frame */ Frame::~Frame() { PRINTF(5)("deleting the Frame: %s\n", this->title); } /** * Sets the Frames name to title * @param title The title the Frame should get. */ void Frame::setTitle(const char* title) { if (this->title) delete []this->title; this->title = new char[strlen(title)+1]; strcpy(this->title, title); #ifdef HAVE_GTK2 gtk_frame_set_label(GTK_FRAME(widget), this->title); #endif /* HAVE_GTK2 */ } ////////////// /* EVENTBOX */ ////////////// /** * Creates a new EventBox with name title * @param eventBoxName title the Eventbox should get(only data-structure-internal) */ EventBox::EventBox(const char* eventBoxName) { #ifdef HAVE_GTK2 this->widget = gtk_event_box_new(); gtk_container_set_border_width(GTK_CONTAINER(this->widget), 3); #endif /* HAVE_GTK2 */ if (eventBoxName) this->setTitle(eventBoxName); } /** * destructs an EventBox. */ EventBox::~EventBox() { PRINTF(5)("deleting the EventBox: %s\n", this->title); } ///////// /* BOX */ ///////// /** * Creates a new Box of type boxtype * @param boxtype if 'v' the Box will be vertically, if 'h' the Box will be horizontally */ Box::Box(char boxtype) { this->optionType = GUI_BOX; #ifdef HAVE_GTK2 if (boxtype == 'v') this->widget = gtk_vbox_new(FALSE, 0); else this->widget = gtk_hbox_new(FALSE, 0); #endif /* HAVE_GTK2 */ } /** * destructs a Box. */ Box::~Box() { PRINTF(5)("deleting the Box: %s\n", this->title); } /** * Fills a box with a given Widget. * @param lowerWidget the next Widget that should be appendet to this Box It does this by apending the first one to its down-pointer and all its following ones to the preceding next-pointer. The last one will receive a NULL pointer as Next */ void Box::fill(Widget* lowerWidget) { #ifdef HAVE_GTK2 gtk_box_pack_start(GTK_BOX(this->widget), lowerWidget->widget, TRUE, TRUE, 0); #endif /* HAVE_GTK2 */ if (this->down == NULL) this->down = lowerWidget; else { Widget* tmp; tmp = this->down; while(tmp->next != NULL) tmp = tmp->next; tmp->next = lowerWidget; } } //////////// /* OPTION */ //////////// /** * Initializes a new Option. sets all Option-Specific-Values to their defaults. */ Option::Option() { this->value = 0; this->flagName = NULL; this->flagNameShort = NULL; this->shortDescription = NULL; this->longDescription = NULL; this->saveable = false; this->defaultValue = 0; } /** * Destroys an Option. */ Option::~Option() { PRINTF(5)("deleting the Option Part.\n"); if (this->flagName) delete []this->flagName; if (this->flagNameShort) delete []this->flagNameShort; if (this->shortDescription) delete []this->shortDescription; if (this->longDescription) delete []this->longDescription; } /** * @param defaultValue new defaultValue for this option */ void Option::setDefaultValue(int defaultValue) { this->value = this->defaultValue = defaultValue; } /** * This sets The FlagName of an Option and defines its default Values !! Options will be saved if flagname is different from NULL !! * @param flagname the Name that will be displayed in the output * @param defaultvalue the default Value for this Option(see definition of defaultvalue */ void Option::setFlagName(const char* flagname, int defaultvalue) { if (this->flagName) delete this->flagName; this->flagName = new char [strlen(flagname)+1]; strcpy(this->flagName, flagname); this->setDefaultValue(defaultvalue); if (this->flagNameShort) { delete this->flagNameShort; this->flagNameShort = NULL; } // cout << "Set Flagname of " << this->title << " to " << flagname << endl; } /** * see Option::setFlagName(char* flagname, int defaultvalue) * @param flagname the Name that will be displayed in the output * @param defaultvalue the default Value for this Option(see definition of defaultvalue * @param flagnameshort a short flagname to be displayed in the output */ void Option::setFlagName(const char* flagname, const char* flagnameshort, int defaultvalue) { if (this->flagName) delete []this->flagName; this->flagName = new char [strlen(flagname)+1]; strcpy(this->flagName, flagname); if (this->flagNameShort) delete []this->flagNameShort; this->flagNameShort = new char [strlen(flagnameshort)+1]; strcpy(this->flagNameShort, flagnameshort); this->setDefaultValue(defaultvalue); // cout << "Set Flagname of " << this->title << " to " << flagname << endl; } void Option::setDescription(const char* shortDescription, const char* longDescription) { // setting up the short description if (this->shortDescription) delete []this->shortDescription; this->shortDescription = new char [strlen(shortDescription)+1]; strcpy(this->shortDescription, shortDescription); //setting up the long description if (this->longDescription) delete []this->longDescription; if (longDescription) { this->longDescription = new char [strlen(longDescription)+1]; strcpy(this->longDescription, longDescription); } else this->longDescription = NULL; } /** * Sets the saveable-state of the option. * @param isSaveable the saveable-state to set. */ void Option::saveability(bool isSaveable) { this->saveable = isSaveable; } /** * saves an Option * @returns the String that should be saved. (this string __should__ be deleted) this is a default Option save */ char* Option::save() { char* value = new char [30]; sprintf (value, "%d", this->value); return value; } /** * loads an Option from of its loadString * @param loadString the string from which to load the data from */ void Option::load(const char* loadString) { this->value = atoi(loadString); PRINT(5)("Loading %s: %s %d\n", this->title, loadString, value); this->redraw(); } /** * @returns The saveable-state. */ bool Option::isSaveable() { return this->saveable; } #ifdef HAVE_GTK2 /** * Signal OptionChange writes the Value from the Option to its Object-Database. * @param widget The widget(Option) that has a changed Value * @param option the Option-Object that should receive the change. */ gint Option::OptionChange(GtkWidget *widget, Widget* option) { static_cast(option)->changeOption(); #ifdef BUILD_ORXONOX flags->setTextFromFlags(Window::mainWindow); #endif } #endif /* HAVE_GTK2 */ //////////// /* BUTTON */ //////////// /** * Creates a new Button with a buttonname * @param buttonName sets the Name of the Button */ Button::Button(const char* buttonName) { this->optionType = GUI_NOTHING; #ifdef HAVE_GTK2 widget = gtk_button_new_with_label(""); #endif /* HAVE_GTK2 */ if (buttonName) this->setTitle(buttonName); } /** * destructs a Button. */ Button::~Button() { PRINTF(5)("deleting the Label: %s\n", this->title); } /** * Sets a new name to the Button * @param title The name the Button should get */ void Button::setTitle(const char *title) { if (this->title) delete []this->title; this->title = new char[strlen(title)+1]; strcpy(this->title, title); #ifdef HAVE_GTK2 gtk_button_set_label(GTK_BUTTON(widget), title); #endif /* HAVE_GTK2 */ } /** * redraws the Button @todo not implemented yet */ void Button::redraw() { } /** * Button can not be changed, optionChange is empty) @todo Actions for non-GTK-mode */ void Button::changeOption() { // This will possibly be used for ACTIONS ! } ///////////////// /* CHECKBUTTON */ ///////////////// /** * Creates a new CheckButton with an ame * @param buttonName The name the CheckButton should display. */ CheckButton::CheckButton(const char* buttonName) { this->optionType = GUI_BOOL; #ifdef HAVE_GTK2 this->widget = gtk_check_button_new_with_label(""); #endif /* HAVE_GTK2 */ if (buttonName) this->setTitle(buttonName); #ifdef HAVE_GTK2 this->connectSignal("clicked", this->OptionChange); #endif /* HAVE_GTK2 */ } /** * destructs a CheckButton. */ CheckButton::~CheckButton() { if (this->title) PRINTF(5)("deleting the CheckButton: %s\n", this->title); else PRINTF(5)("deleting the CheckButton.\n"); } /** * Sets a new Title to a CheckButton * @param title The new Name the CheckButton should display. */ void CheckButton::setTitle(const char* title) { if (this->title) delete []this->title; this->title = new char[strlen(title)+1]; strcpy(this->title, title); #ifdef HAVE_GTK2 gtk_button_set_label(GTK_BUTTON(widget), title); #endif /* HAVE_GTK2 */ } /** * @returns the Active state of the checkButton */ bool CheckButton::isActive() { #ifdef HAVE_GTK2 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); #endif /* HAVE_GTK2 */ } /** * Changed the Option, call this Function */ void CheckButton::changeOption() { #ifdef HAVE_GTK2 this->value =(int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->widget)); #else /* HAVE_GTK2 */ char tmpChar[200]; PRINT(0)("\nPlease give me a new value for %s [0,1](default:%d): ",this->title, this->defaultValue); scanf("%s", tmpChar); if ((this->value = atoi(tmpChar))=!0) this->value = 1; PRINT(0)("%s set to: %d\n", this->title, this->value); #endif /* HAVE_GTK2 */ } /** * Redraws the CheckButton(if option has changed). Example: if new settings are loaded the Button must be redrawn for the GUI to display that Change */ void CheckButton::redraw() { #ifdef HAVE_GTK2 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->widget), value); #endif /* HAVE_GTK2 */ } //////////// /* SLIDER */ //////////// /** * Creates a new Slider * @param slidername The data-structure-name of the slider. * @param start The minimal Value of the slider. * @param end The maximal Value of the slider. */ Slider::Slider(const char* slidername, float start, float end) { this->optionType = GUI_FLOAT; this->start = start; this->end = end; #ifdef HAVE_GTK2 widget = gtk_hscale_new_with_range(this->start, this->end, 5); #endif /* HAVE_GTK2 */ this->setValue(start); this->setTitle(slidername); #ifdef HAVE_GTK2 this->connectSignal("value_changed", this->OptionChange); #endif /* HAVE_GTK2 */ } /** * destructs a Slider. */ Slider::~Slider() { PRINTF(5)("deleting the Slider: %s\n", this->title); } /** * sets the exactness of the widget * @param exactness count of digits after the dot */ void Slider::setExactness(int exactness) { #ifdef HAVE_GTK2 gtk_scale_set_digits(GTK_SCALE(this->widget), exactness); gtk_range_set_increments(GTK_RANGE(this->widget), pow(.1, exactness), pow(.1, exactness-1)); #endif /* HAVE_GTK2 */ } /** * Setting a new value to the Slider. Maybe you also require a Slider::redraw() for this to display */ void Slider::setValue(float value) { this->fValue = value; } /** * Redraws the widget Example: see void CheckButton::redraw() */ void Slider::redraw() { #ifdef HAVE_GTK2 gtk_range_set_value(GTK_RANGE(this->widget), this->fValue); #endif /* HAVE_GTK2 */ } /** * Changed the Option, call this Function */ void Slider::changeOption() { #ifdef HAVE_GTK2 this->fValue = gtk_range_get_value(GTK_RANGE(this->widget)); #else /* HAVE_GTK2 */ char tmpChar[20]; PRINT(0)("\nPlease give me a new value for %s [%d-%d] (default:%d): ", this->title, this->start, this->end, this->defaultValue); scanf("%s", tmpChar); if ((this->fValue = atof(tmpChar))> this->end) this->fValue = this->end; if (this->fValue <= this->start) this->fValue = this->start; PRINT(0)("%s set to: %d\n",this->title, this->fValue); #endif /* HAVE_GTK2 */ } char* Slider::save() { char* value = new char [30]; sprintf (value, "%f", this->fValue); return value; } void Slider::load(const char* loadString) { this->fValue = atof(loadString); PRINT(5)("Loading %s: %s %f\n", this->title, loadString, fValue); this->redraw(); } ////////// /* MENU */ ////////// /** * constructs a new Menu, without adding any items to it. * @param menuName the Name the Menu gets. */ Menu::Menu(const char* menuName) { this->init(); this->setTitle(menuName); } /** * Creates a Menu-Item-list out of multiple input. !! Consider, that the last input argument has to be "lastItem" for this to work!! * @param menuname The Database-Name of this Menu * @param ... items to be added to this Menu. !! Consider, that the last input argument has to be "lastItem" for this to work!! */ Menu::Menu(char* menuname, ...) { this->init(); this->setTitle(menuname); va_list itemlist; //!< The list to readin multiple Options. char *itemName; va_start(itemlist, menuname); while(strcmp(itemName = va_arg(itemlist, char*), "lastItem")) { this->addItem(itemName); } va_end(itemlist); } /** * destructs a Menu. */ Menu::~Menu() { PRINTF(5)("deleting the Menu: %s\n", this->title); this->currItem = this->firstItem; while(this->currItem) { delete []this->currItem->name; //! @todo destroy menu /* #ifdef HAVE_GTK2 gtk_widget_destroy(this->currItem->item); #endif /* HAVE_GTK2 */ MenuItem* tmpItem = this->currItem; this->currItem = this->currItem->next; delete tmpItem; } } /** * Initializes a new Menu with no items */ void Menu::init() { this->optionType = GUI_INT; this->firstItem = NULL; #ifdef HAVE_GTK2 this->widget = gtk_option_menu_new(); this->menu = gtk_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(this->widget), menu); this->connectSignal("changed", this->OptionChange); #endif /* HAVE_GTK2 */ } /** * saves the Label of the Menu * @returns the name of the selected Menu-Item */ char* Menu::save() { MenuItem* tmpItem = this->firstItem; for (int i = 0; i < this->value; i++) if (tmpItem) tmpItem = tmpItem->next; else break; if (tmpItem) { char* tmpName = new char[strlen(tmpItem->name)+1]; strcpy(tmpName, tmpItem->name); return tmpName; } else return NULL; } /** * loads a Menu from of its loadString * @param loadString the string from which to load the data from */ void Menu::load(const char* loadString) { MenuItem* tmpItem = firstItem; bool foundItem = false; while (tmpItem) { if (!strcmp(loadString, tmpItem->name)) {foundItem = true; break;} tmpItem = tmpItem->next; } if (foundItem) this->value = tmpItem->itemNumber; else { this->value = 0; PRINTF(2)("%s has not been found in the Itemlist of %s\n", loadString, this->title); } PRINTF(5)( "Loading %s: setting to %d\n", this->title, this->value); this->redraw(); } /** * appends a new Item to the Menu-List. * @param itemName the itemName to be appendet. */ void Menu::addItem(char* itemName) { if (!this->firstItem) { this->firstItem = this->currItem = new MenuItem; this->currItem->itemNumber = 0; } else { int tmpI = this->currItem->itemNumber; this->currItem = this->currItem->next = new MenuItem; this->currItem->itemNumber = tmpI+1; } this->currItem->name = new char[strlen(itemName)+1]; strcpy(this->currItem->name, itemName); #ifdef HAVE_GTK2 this->currItem->item = gtk_menu_item_new_with_label(itemName); gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), this->currItem->item); #endif /* HAVE_GTK2 */ this->currItem->next = NULL; } /** * Redraws the widget Example: see void CheckButton::redraw() */ void Menu::redraw() { #ifdef HAVE_GTK2 gtk_option_menu_set_history(GTK_OPTION_MENU(this->widget), this->value); #endif /* HAVE_GTK2 */ } /** * Changed the Option, call this Function */ void Menu::changeOption() { #ifdef HAVE_GTK2 this->value =(int)gtk_option_menu_get_history(GTK_OPTION_MENU(this->widget)); #else /* HAVE_GTK2 */ char tmpChar[20]; PRINT(0)("\nPlease give me a new value for %s (default: %d): ", this->title, this->defaultValue); scanf("%s",tmpChar); this->value = atoi(tmpChar); #endif /* HAVE_GTK2 */ PRINT(4)("%s set to: %d\n", this->title, this->value); } /* OPTION LABEL */ /** * Creates a new OptionLabel with a LabelName and a Value. * @param label The name of the OptionLabel. * @param value The Value of the OptionLabel(what will be displayed). */ OptionLabel::OptionLabel(const char* label, const char* value) { this->optionType = GUI_CHAR_ARRAY; cValue = NULL; #ifdef HAVE_GTK2 this->widget = gtk_label_new(""); #endif /* HAVE_GTK2 */ this->setTitle(label); this->setValue(value); } /** * destructs an OptionLabel. */ OptionLabel::~OptionLabel() { PRINTF(5)("deleting the OptionLabel: %s\n", this->title); if (this->cValue) delete []this->cValue; } /** * Updates the value of an OptionLabel * @param newValue The new Name that should be displayed. */ void OptionLabel::setValue(const char* newValue) { if (this->cValue) delete []this->cValue; this->cValue = new char [strlen(newValue)+1]; strcpy(this->cValue, newValue); this->redraw(); } /** * Redraws an OptionLabel(not implemented yet, but it works). */ void OptionLabel::redraw() { #ifdef HAVE_GTK2 gtk_label_set_text(GTK_LABEL(widget), cValue); #endif /* HAVE_GTK2 */ } /** * Changed the Option, call this Function */ void OptionLabel::changeOption() { #ifdef HAVE_GTK2 this->cValue = (char*)gtk_label_get_text(GTK_LABEL(this->widget)); #else /* HAVE_GTK2 */ PRINT(0)("\nPlease give me a new input for %s: ", this->title); char tmpChar[100]; scanf("%s",tmpChar); this->setValue(tmpChar); #endif /* HAVE_GTK2 */ PRINT(4)("%s set to: %s\n", this->title, this->cValue); } /** * creates the Optionlabel save-string * @returns the String to save. */ char* OptionLabel::save() { return cValue; } /** * loads an Option from of its loadString * @param loadString the string from which to load the data from */ void OptionLabel::load(const char* loadString) { PRINTF(5)("Loading %s: setting to %s\n", this->title, loadString); this->setValue(loadString); } /////////// /* LABEL */ /////////// /** * Creates a new Label with a Text. * @param text The text to be displayed. */ Label:: Label(const char* text) { this->optionType = GUI_NOTHING; #ifdef HAVE_GTK2 this->widget = gtk_label_new(""); gtk_label_set_line_wrap(GTK_LABEL(this->widget), TRUE); #endif /* HAVE_GTK2 */ if (text) this->setTitle(text); } /** * destructs a Label. */ Label::~Label() { PRINTF(5)("deleting the Label: %s\n", this->title); } /** * Sets a new Text to a Label. * @param text The text to be inserted into the Label. */ void Label::setTitle(const char* text) { if (this->title) delete []this->title; this->title = new char[strlen(text)+1]; strcpy(this->title, text); #ifdef HAVE_GTK2 gtk_label_set_text(GTK_LABEL(this->widget), this->title); #endif /* HAVE_GTK2 */ } /** * ereases the Text of a Label */ void Label::ereaseText() { this->setTitle(""); } /** * appends some Text to a Label * @param textToAppend The text that will be appended to this Label */ void Label::appendText(char* textToAppend) { if (this->title) { char* tmpTitle = new char[strlen(this->title)+strlen(textToAppend)+1]; strcpy(tmpTitle, title); strcat(tmpTitle, textToAppend); delete []this->title; this->title = tmpTitle; } else this->title = new char[strlen(textToAppend)]; #ifdef HAVE_GTK2 gtk_label_set_text(GTK_LABEL(this->widget), title); #endif /* HAVE_GTK2 */ } /** * Appends some integer to the Label * @param intToAppend The Int that will be added. it does this by just converting the int into a char* and send it to appendText */ void Label::appendInt(int intToAppend) { char append [32]; sprintf(append, "%d", intToAppend); this->appendText(append); } /** * get the Text of a Label * @return The Text the Label holds. */ const char* Label::getText() { return this->title; } ////////////////// /* PROGRESS-BAR */ ////////////////// /** * Creates a new ProgressBar. * @param label The name you want to get the ProgressBar. */ ProgressBar::ProgressBar(const char* label) { this->optionType = GUI_NOTHING; this->progress = 0.0; this->totalSize = 0.0; #ifdef HAVE_GTK2 this->adjustment =(GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0); this->widget = gtk_progress_bar_new_with_adjustment(this->adjustment); #endif /* HAVE_GTK2 */ if (label) this->setTitle(label); } /** * destructs a ProgressBar */ ProgressBar::~ProgressBar() { PRINTF(5)("deleting the ProgressBar: %s\n", this->title); } /** * Sets the Total size of the Bar.(ex. The maximum one can download) */ void ProgressBar::setTotalSize(double totalSize) { this->totalSize = totalSize; } /** * Sets the progress maximum is this->totalSize */ void ProgressBar::setProgress(double progress) { this->progress = progress; if (this->progress > this->totalSize) this->progress = this->totalSize; #ifdef HAVE_GTK2 gtk_progress_set_value(GTK_PROGRESS(widget), this->progress*100.0/this->totalSize); PRINTF(5)("Progress: %f%%\n", this->progress*100.0/this->totalSize); #else /* HVE_GTK2 */ PRINT(0)("Progress: %f%%\n", this->progress*100.0/this->totalSize); #endif /* HAVE_GTK2 */ } /** * returns the Progress Status */ double ProgressBar::getProgress() { return this->progress; } /////////// /* IMAGE */ /////////// /** * Creates a new Image * @param imageName the location of the Image on the Hard Disc */ Image::Image(const char* imageName) { this->init(imageName); #ifdef HAVE_GTK2 widget = gtk_image_new_from_file(imageName); #endif /* HAVE_GTK2 */ } /** * Creates a new Image * @param imageData data to the PixBuff */ Image::Image(char** imageData) { this->init("pixBuffImage"); #ifdef HAVE_GTK2 widget = gtk_image_new_from_pixbuf(gdk_pixbuf_new_from_xpm_data((const char**)imageData)); #endif /* HAVE_GTK2 */ } /** * destructs an Image. */ Image::~Image() { PRINTF(5)("deleting the Image: %s\n", this->title); } /** * Initializes a new Image * @param name the name to set to the Image */ void Image::init(const char* name) { optionType = GUI_NOTHING; if (this->title) delete []this->title; this->title = new char[strlen(name)+1]; strcpy(this->title, name); } ///////////////// /* FILE DIALOG */ ///////////////// /** * Creates a new FileDialog * @param fileDialogName a Name for the Dialog */ FileDialog::FileDialog(const char* fileDialogName) { this->optionType = GUI_NOTHING; this->isOpen = false; this->changeOption = NULL; this->openUpButton = NULL; this->okObject = NULL; this->okFunc = NULL; #ifdef HAVE_GTK2 this->widget = gtk_file_selection_new(fileDialogName); gtk_file_selection_set_select_multiple(GTK_FILE_SELECTION (this->widget), FALSE); g_signal_connect(GTK_FILE_SELECTION (this->widget)->cancel_button, "button_release_event", G_CALLBACK (FileDialog::dialogClose), this); g_signal_connect(GTK_FILE_SELECTION (this->widget), "delete_event", G_CALLBACK (FileDialog::dialogClose), this); g_signal_connect(GTK_FILE_SELECTION (this->widget)->ok_button, "button_release_event", G_CALLBACK (FileDialog::dialogOK), this); #endif /* HAVE_GTK2 */ if (fileDialogName) this->setTitle(fileDialogName); } /** * destructs a FileDialog */ FileDialog::~FileDialog() { PRINTF(5)("deleting FileDialog %s\n", this->title); } void FileDialog::setChangeOption(OptionLabel* changeOption) { this->changeOption = changeOption; } void FileDialog::setOKFunc(void* okObject, bool(*function)(const char* , void*)) { this->okObject = okObject; this->okFunc = function; } void FileDialog::setOpenUpButton(Button* openUpButton) { this->openUpButton = openUpButton; openUpButton->connectSignal("button_release_event", this, FileDialog::dialogOpen); } void FileDialog::setDefaultFileName(const char* defaultFileName) { #ifdef HAVE_GTK2 gtk_file_selection_set_filename (GTK_FILE_SELECTION(this->widget), defaultFileName); #endif /* HAVE_GTK2 */ } void FileDialog::setMask(const char* mask) { #ifdef HAVE_GTK2 gtk_file_selection_complete(GTK_FILE_SELECTION(this->widget), mask); #endif /* HAVE_GTK2 */ } /** * disables the File Operator Buttons */ void FileDialog::disableFileOpts() { #ifdef HAVE_GTK2 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(this->widget)); #endif /* HAVE_GTK2 */ } /** * The ok-button has been pressed */ void FileDialog::okEvent() { if (this->okFunc) { #ifdef HAVE_GTK2 if(this->okFunc((const char*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(this->widget)), this->okObject)) this->close(); #endif /* HAVE_GTK2 */ } else if (this->changeOption) { #ifdef HAVE_GTK2 changeOption->setValue(gtk_file_selection_get_filename(GTK_FILE_SELECTION(this->widget))); #endif /* HAVE_GTK2 */ this->close(); } else this->close(); } /** \biref opens up the FileDialog-Window */ void FileDialog::open() { isOpen = true; #ifdef HAVE_GTK2 gtk_widget_show_all(this->widget); gtk_grab_add(this->widget); #endif /* HAVE_GTK2 */ } /** \closes the FileDialog-Window */ void FileDialog::close() { this->isOpen = false; #ifdef HAVE_GTK2 gtk_grab_remove(this->widget); gtk_widget_hide(this->widget); #endif /* HAVE_GTK2 */ } #ifdef HAVE_GTK2 gint FileDialog::dialogOK(GtkWidget* widget, GdkEvent* event, void* dialog) { static_cast(dialog)->okEvent(); } #else /* HAVE_GTK2 */ int FileDialog::dialogOK(void* widget, void* event, void* dialog){} #endif /* HAVE_GTK2 */ #ifdef HAVE_GTK2 gint FileDialog::dialogOpen(GtkWidget* widget, GdkEvent* event, void* dialog) { static_cast(dialog)->open(); } #else /* HAVE_GTK2 */ int FileDialog::dialogOpen(void* widget, void* event, void* dialog){} #endif /* HAVE_GTK2 */ #ifdef HAVE_GTK2 gint FileDialog::dialogClose(GtkWidget* widget, GdkEvent* event, void* dialog) { static_cast(dialog)->close(); } #else /* HAVE_GTK2 */ int FileDialog::dialogClose(void* widget, void* event, void* dialog){} #endif /* HAVE_GTK2 */