/* 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 using namespace std; #include "gui_flags.h" #include "gui_exec.h" extern GuiFlags* flags; char* executable; /** \brief Initializes the Guis GTK-stuff. \param argc the argument count. \param argv The Argument strings. */ bool initGUI(int argc, char *argv[]) { executable = new char[strlen(argv[0])+1]; strcpy(executable, argv[0]); #ifdef HAVE_GTK2 gtk_init(&argc, &argv); #include "rc" gtk_rc_parse_string( rc_string ); #endif /* HAVE_GTK2 */ } /** \brief enters the GUI's main-loop */ bool mainloopGUI(void) { #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 */ //////////// /** \brief constructs a Widget */ Widget::Widget(void) { next = NULL; this->title = NULL; } /** \brief deletes any given Widget This is still pretty crappy. */ Widget::~Widget(void) { 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); } /** \brief 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); } /** \brief makes the widget visible. */ void Widget::show(void) { #ifdef HAVE_GTK2 gtk_widget_show(this->widget); #endif /* HAVE_GTK2 */ } /** \brief hides the widget. */ void Widget::hide(void) { #ifdef HAVE_GTK2 gtk_widget_hide(this->widget); #endif /* HAVE_GTK2 */ } /** \brief 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 */ } /** \brief 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->isOption < 0 && 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; } /** \brief 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->isOption < 0) { static_cast(this)->down->walkThrough(function, depth+1); } if (this->next && depth != 0) this->next->walkThrough(function, depth); } /** \brief 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->isOption < 0) { static_cast(this)->down->walkThrough(function, data, depth+1); } if (this->next && depth != 0) this->next->walkThrough(function, data, depth); } /** \brief This is for listing the options of "widget" \param widget specifies the widget that should be listed */ void Widget::listOptionsAndGroups(Widget* widget) { if (widget->isOption < 0 && static_cast(widget)->groupName) PRINT(0)("[%s]\n", static_cast(widget)->groupName); if (widget->isOption >= 1) { Widget::listOptions(widget); } } /** \brief This is for listing the options of "widget" \param widget specifies the widget that should be listed */ void Widget::listOptions(Widget* widget) { if(widget->isOption >= 1) PRINT(0)(" %s is %s\n", static_cast(widget)->title, static_cast(widget)->save()); } /** \brief 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->isOption >= 1) { int* count =(int*)data; *count = *count +1; PRINT(0)(" %d:%s is %s\n", *count, static_cast(widget)->title, static_cast(widget)->save()); } } /** \brief 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 (isOption > 0) { --*number; if (*number <= 0) { return this; } } if (this->isOption < 0 && 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; } /** \brief This is for listing the groups of "widget" \param widget specifies the widget that should be listed */ void Widget::listGroups(Widget* widget) { if (widget->isOption < 0 && static_cast(widget)->groupName) PRINT(0)("[%s]\n", static_cast(widget)->groupName); } /** \brief 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->isOption < 0 && static_cast(widget)->groupName) PRINT(0)("%d: [%s]\n", ++*count, static_cast(widget)->groupName); } /** \brief 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 (isOption < 0 && static_cast(this)->groupName) { --*number; if (*number <= 0) { return this; } } if (this->isOption < 0 && 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; } /** \brief This is for setting the option of "widget" \param widget specifies the widget that should be set. */ void Widget::setOptions(Widget* widget) { if (widget->isOption >= 1) static_cast(widget)->redraw(); } /** \brief redraws all the Widgets down from widget \param widget The topmost Widget \param data ... */ void Widget::redrawOptions(Widget* widget) { if (widget->isOption >= 1) static_cast(widget)->redraw(); } /** \brief Walks through all the Flags given at startuptime. */ void Widget::flagCheck(Widget* widget, void* flagName) { if (widget->isOption>=1) { 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 /** \brief 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); } /** \brief 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); } /** \brief 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); } /** \brief 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); } /** \brief 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); } /** \brief 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 */ ///////////// /** \brief Constructs a Packer */ Packer::Packer(void) { this->down = NULL; this->groupName = NULL; } /** \brief Destroys a Packer. */ Packer::~Packer(void) { PRINTF(5)("deleting the Packer part.\n"); if (this->groupName) delete []this->groupName; //deleting recursively. if (this->down) delete this->down; } /** \brief 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 */ //////////////// /** \brief Initializes a Container. sets the Container-Specific defaults. */ Container::Container(void) { this->isOption = -1; } /** \brief Destroys a Container. */ Container::~Container(void) { PRINTF(5)("deleting the Container part.\n"); } /** \briefFills 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(1)("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 */ //////////// /** \brief The main Window of Th Gui */ Window* Window::mainWindow = NULL; /** \brief 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); } /** \brief Destructs a Window. */ Window::~Window(void) { PRINTF(5)("deleting the Window: %s\n", this->title); } /** \brief 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; } /** \brief Shows all Widgets that are included within this->widget. */ void Window::showall(void) { #ifdef HAVE_GTK2 if (!this->isOpen) gtk_widget_show_all(this->widget); else gtk_widget_show(this->widget); #endif /* HAVE_GTK2 */ } /** \brief 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 */ } /** \brief opens up a Window and fixes the Focus to it */ void Window::open(void) { if (this != mainWindow) { isOpen = true; #ifdef HAVE_GTK2 gtk_widget_show_all(this->widget); gtk_grab_add(this->widget); #endif /* HAVE_GTK2 */ } } /** \brief closes up a Window and removes the Focus from it */ void Window::close(void) { if (this != mainWindow) { this->isOpen = false; #ifdef HAVE_GTK2 gtk_grab_remove(this->widget); gtk_widget_hide(this->widget); #endif /* HAVE_GTK2 */ } } /** \brief 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 */ /** \brief 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 */ /////////// /** \brief Creates a new Frame with name title */ Frame::Frame(char* frameName) { #ifdef HAVE_GTK2 this->widget = gtk_frame_new(""); gtk_container_set_border_width(GTK_CONTAINER(this->widget), 3); #endif /* HAVE_GTK2 */ if (title) this->setTitle(frameName); } /** \brief destrcucts a Frame */ Frame::~Frame(void) { PRINTF(5)("deleting the Frame: %s\n", this->title); } /** \brief 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), title); #endif /* HAVE_GTK2 */ } ////////////// /* EVENTBOX */ ////////////// /** \brief Creates a new EventBox with name title \param eventBoxName title the Eventbox should get(only data-structure-internal) */ EventBox::EventBox(const char* eventBoxName) { this->isOption = -1; #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); } /** \brief destructs an EventBox. */ EventBox::~EventBox(void) { PRINTF(5)("deleting the EventBox: %s\n", this->title); } ///////// /* BOX */ ///////// /** \brief 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->isOption = -2; #ifdef HAVE_GTK2 if (boxtype == 'v') this->widget = gtk_vbox_new(FALSE, 0); else this->widget = gtk_hbox_new(FALSE, 0); #endif /* HAVE_GTK2 */ } /** \brief destructs a Box. */ Box::~Box(void) { PRINTF(5)("deleting the Box: %s\n", this->title); } /** \brief 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 */ //////////// /** \brief Initializes a new Option. sets all Option-Specific-Values to their defaults. */ Option::Option(void) { this->value = 0; this->flagName = NULL; this->flagNameShort = NULL; this->shortDescription = NULL; this->longDescription = NULL; this->saveable = false; this->defaultValue = 0; } /** \brief Destroys an Option. */ Option::~Option(void) { 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; } /** \brief 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; } /** \brief 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; } /** \brief Sets the saveable-state of the option. \param isSaveable the saveable-state to set. */ void Option::saveability(bool isSaveable) { this->saveable = isSaveable; } /** \brief saves an Option \returns the String that should be saved. (this string __should__ be deleted) this is a default Option save */ char* Option::save(void) { char* value = new char [30]; sprintf (value, "%d", this->value); return value; } /** \brief loads an Option from of its loadString \param loadString the string from which to load the data from */ void Option::load(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(void) { return this->saveable; } #ifdef HAVE_GTK2 /** \brief Signal OptionChange writes the Value from the Slider to its Object-Database. \param widget The widget(Slider) that has a changed Value \param slider the Slider-Object that should receive the change. */ gint Option::OptionChange(GtkWidget *widget, Widget* option) { static_cast(option)->changeOption(); flags->setTextFromFlags(Window::mainWindow); //// must be different !!! } #endif /* HAVE_GTK2 */ //////////// /* BUTTON */ //////////// /** \brief Creates a new Button with a buttonname \param buttonName sets the Name of the Button */ Button::Button(char* buttonName) { isOption = 0; #ifdef HAVE_GTK2 widget = gtk_button_new_with_label(""); #endif /* HAVE_GTK2 */ if (buttonName) this->setTitle(buttonName); } /** \brief destructs a Button. */ Button::~Button(void) { PRINTF(5)("deleting the Label: %s\n", this->title); } /** \brief 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 */ } /** \brief redraws the Button \todo not implemented yet */ void Button::redraw(void) { } /** \brief Button can not be changed, optionChange is empty) \todo Actions for non-GTK-mode */ void Button::changeOption(void) { // This will possibly be used for ACTIONS ! } ///////////////// /* CHECKBUTTON */ ///////////////// /** \brief Creates a new CheckButton with an ame \param buttonName The name the CheckButton should display. */ CheckButton::CheckButton(const char* buttonName) { this->isOption = 1; #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 */ } /** \brief destructs a CheckButton. */ CheckButton::~CheckButton(void) { if (this->title) PRINTF(5)("deleting the CheckButton: %s\n", this->title); else PRINTF(5)("deleting the CheckButton.\n"); } /** \brief 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(void) { #ifdef HAVE_GTK2 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); #endif /* HAVE_GTK2 */ } /** \brief Changed the Option, call this Function */ void CheckButton::changeOption(void) { #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; #endif /* HAVE_GTK2 */ PRINT(0)("%s set to: %d\n", this->title, this->value); } /** \brief 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(void) { #ifdef HAVE_GTK2 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->widget), value); #endif /* HAVE_GTK2 */ } //////////// /* SLIDER */ //////////// /** \brief 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, int start, int end) { this->isOption = 2; 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 */ } /** \brief destructs a Slider. */ Slider::~Slider(void) { PRINTF(5)("deleting the Slider: %s\n", this->title); } /** \brief Setting a new value to the Slider. Maybe you also require a Slider::redraw() for this to display */ void Slider::setValue(int value) { this->value = value; } /** \brief Redraws the widget Example: see void CheckButton::redraw(void) */ void Slider::redraw(void) { #ifdef HAVE_GTK2 gtk_range_set_value(GTK_RANGE(this->widget), this->value); #endif /* HAVE_GTK2 */ } /** \brief Changed the Option, call this Function */ void Slider::changeOption(void) { #ifdef HAVE_GTK2 this->value =(int)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->value = atoi(tmpChar))> this->end) this->value = this->end; if (this->value <= this->start) this->value = this->start; #endif /* HAVE_GTK2 */ PRINT(0)("%s set to: %d\n",this->title, this->value); } ////////// /* MENU */ ////////// /** \brief 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); } /** \brief 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); } /** \brief destructs a Menu. */ Menu::~Menu(void) { 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; } } /** \brief Initializes a new Menu with no items */ void Menu::init(void) { this->isOption = 2; 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 */ } /** \brief saves the Label of the Menu \returns the name of the selected Menu-Item */ char* Menu::save(void) { MenuItem* tmpItem = this->firstItem; for (int i = 0; ivalue; i++) tmpItem = tmpItem->next; return tmpItem->name; } /** \brief loads a Menu from of its loadString \param loadString the string from which to load the data from */ void Menu::load(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)("Sorry, but %s has not been found in the Itemlist of %s\n", loadString, this->title); } PRINTF(4)( "Loading %s: setting to %d\n", this->title, this->value); this->redraw(); } /** \brief 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; } /** \brief Redraws the widget Example: see void CheckButton::redraw(void) */ void Menu::redraw(void) { #ifdef HAVE_GTK2 gtk_option_menu_set_history(GTK_OPTION_MENU(this->widget), this->value); #endif /* HAVE_GTK2 */ } /** \brief Changed the Option, call this Function */ void Menu::changeOption(void) { #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 */ /** \brief 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->isOption = 5; cValue = NULL; #ifdef HAVE_GTK2 this->widget = gtk_label_new(""); #endif /* HAVE_GTK2 */ this->setTitle(label); this->setValue(value); } /** \brief destructs an OptionLabel. */ OptionLabel::~OptionLabel(void) { PRINTF(5)("deleting the OptionLabel: %s\n", this->title); if (this->cValue) delete []this->cValue; } /** \brief 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); #ifdef HAVE_GTK2 gtk_label_set_text(GTK_LABEL(this->widget), this->cValue); #endif /* HAVE_GTK2 */ } /** \brief Redraws an OptionLabel(not implemented yet, but it works). */ void OptionLabel::redraw(void) { #ifdef HAVE_GTK2 gtk_label_set_text(GTK_LABEL(widget), title); #endif /* HAVE_GTK2 */ } /** \brief Changed the Option, call this Function */ void OptionLabel::changeOption(void) { #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); } /** \brief creates the Optionlabel save-string \returns the String to save. */ char* OptionLabel::save(void) { return cValue; } /** \brief loads an Option from of its loadString \param loadString the string from which to load the data from */ void OptionLabel::load(char* loadString) { PRINTF(4)("Loading %s: setting to %s\n", this->title, loadString); this->setValue(loadString); } /////////// /* LABEL */ /////////// /** \brief Creates a new Label with a Text. \param text The text to be displayed. */ Label:: Label(const char* text) { this->isOption = 0; #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); } /** \brief destructs a Label. */ Label::~Label(void) { PRINTF(5)("deleting the Label: %s\n", this->title); } /** \brief 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 */ } /** \brief ereases the Text of a Label */ void Label::ereaseText(void) { this->setTitle(""); } /** \brief 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 */ } /** \brief 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); } /** \brief get the Text of a Label \return The Text the Label holds. */ const char* Label::getText(void) { return this->title; } ////////////////// /* PROGRESS-BAR */ ////////////////// /** \brief Creates a new ProgressBar. \param label The name you want to get the ProgressBar. */ ProgressBar::ProgressBar(const char* label) { this->isOption = 0; 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); } /** \brief destructs a ProgressBar */ ProgressBar::~ProgressBar(void) { PRINTF(5)("deleting the ProgressBar: %s\n", this->title); } /** \brief Sets the Total size of the Bar.(ex. The maximum one can download) */ void ProgressBar::setTotalSize(double totalSize) { this->totalSize = totalSize; } /** \brief 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(4)("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 */ } /** \brief returns the Progress Status */ double ProgressBar::getProgress(void) { return this->progress; } /////////// /* IMAGE */ /////////// /** \brief 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 */ } /** \brief 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 */ } /** \brief destructs an Image. */ Image::~Image(void) { PRINTF(5)("deleting the Image: %s\n", this->title); } /** \brief Initializes a new Image \param name the name to set to the Image */ void Image::init(const char* name) { isOption = 0; if (this->title) delete []this->title; this->title = new char[strlen(name)+1]; strcpy(this->title, name); }