Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/gui/orxonox_gui_gtk.cc @ 3153

Last change on this file since 3153 was 3153, checked in by bensch, 19 years ago

orxonox/trunk/gui: more modular.

File size: 20.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software Foundation,
18   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
19
20
21   ### File Specific:
22   main-programmer: Benjamin Grauer
23
24*/
25
26
27#include <iostream>
28
29#include "orxonox_gui_gtk.h"
30
31
32using namespace std;
33
34// temporarily.
35#include "orxonox_gui_flags.h"
36#include "orxonox_gui_exec.h"
37extern Window* orxonoxGUI;
38extern OrxonoxGuiFlags* flags;
39extern OrxonoxGuiExec* exec;
40
41/* WIDGET */
42
43/**
44   \brief deletes any given Widget
45   This is still pretty crappy.
46*/
47Widget::~Widget()
48{
49  //  cout << "hiding: " <<this->label <<"\n";
50  this->hide();
51  //  cout << "check if Packer: "<<this->label <<"\n";
52  if (this->isOption < 0)
53    {
54      //  cout << "get Down "<<this->label <<"\n";
55      static_cast<Packer*>(this)->down->~Widget();
56    }
57  //  cout << "next != NULL?: " <<this->label <<"\n";
58  if (this->next != NULL)
59    this->next->~Widget();
60  cout << "delete Widget: " <<this->label <<"\n";
61  //  delete widget;
62}
63
64/**
65   \brief Initializes a widget.
66   Initializes the next Pointer and the other Widget-specific Defaults.
67*/
68void Widget::init()
69{
70  next = NULL;
71  label = "";
72  return;
73}
74
75/**
76   \brief makes the widget visible.
77*/
78void Widget::show()
79{
80  gtk_widget_show (this->widget);
81}
82
83/**
84   \brief hides the widget.
85*/
86void Widget::hide()
87{
88  gtk_widget_hide (this->widget);
89}
90
91/**
92   \brief Sets the resolution of a specific widget to the given size.
93   \param width the width of the widget to set.
94   \param height the height of the widget to set.
95*/
96void Widget::setSize(int width, int height)
97{
98  gtk_widget_set_usize (this->widget, width, height);
99}
100
101/**
102    \brief Connect any signal to any given Sub-widget
103*/
104void Widget::connectSignal (char* event, gint (*signal)(GtkWidget*, GdkEvent*, void *))
105{
106  g_signal_connect (G_OBJECT (this->widget), event, G_CALLBACK (signal), NULL);
107}
108
109/**
110   \brief Connect a signal with additionally passing the whole Object
111*/
112void Widget::connectSignal (char* event, gint (*signal)( GtkWidget*, Widget *))
113{
114g_signal_connect (G_OBJECT (this->widget), event, G_CALLBACK (signal), this);
115}
116
117/**
118   \brief Connect a signal with additionally passing a whole external Object
119*/
120void Widget::connectSignal (char* event, void* extObj, gint (*signal)(GtkWidget*, GdkEvent*, void *))
121{
122  g_signal_connect (G_OBJECT (this->widget), event, G_CALLBACK (signal), extObj);
123}
124
125/**
126   \brief Connect a signal with additionally passing a whole external Object
127*/
128void Widget::connectSignal (char* event, void* extObj, gint (*signal)(GtkWidget*, GdkEventKey*, void *))
129{
130  g_signal_connect (G_OBJECT (this->widget), event, G_CALLBACK (signal), extObj);
131}
132
133/**
134   \brief Moves through all the Widgets downwards from this and executes the function on them.
135   \param function must be of type void and takes a Widget* as an Input.
136*/
137void Widget::walkThrough (void (*function)(Widget*))
138{
139  function(this);
140  if (this->isOption < 0)
141    {
142      static_cast<Packer*>(this)->down->walkThrough (function);
143    } 
144
145  if (this->next != NULL)
146    this->next->walkThrough(function);
147}
148
149/**
150    \brief This is for listing the option of "widget"
151    \param widget specifies the widget that should be listed
152*/
153void Widget::listOptions (Widget* widget)
154{
155  if (widget->isOption >= 1)
156    cout << static_cast<Option*>(widget)->label <<" is : " << static_cast<Option*>(widget)->value <<endl;
157}
158
159/**
160    \brief This is for setting the option of "widget"
161    \param widget specifies the widget that should be set.
162*/
163void Widget::setOptions (Widget* widget)
164{
165  if (widget->isOption >= 1)
166    static_cast<Option*>(widget)->redraw();// <<" is : " << static_cast<Option*>(this)->value <<endl;
167}
168
169//void deleteWidget(Widget* lastWidget)
170
171
172/* PACKERS */
173
174/**
175   \brief Initializes a Packer.
176   Sets the down-pinter to NULL and other PackerSpecific-values to their defaults.
177*/
178void Packer::init (void)
179{
180  down = NULL;
181  this->setGroupName ("");
182
183
184  static_cast<Widget*>(this)->init();
185  return;
186}
187
188/**
189   \brief Sets the group name under which all the lower widgets of this will be saved.
190   \param name The name of the group.
191*/
192void Packer::setGroupName (char* name)
193{
194  groupName = name;
195}
196
197/**
198   \brief Retrieves the group name under which all the lower widgets of this will be saved.
199   \returns name The name of the group.
200*/
201char* Packer::getGroupName (void)
202{
203  return groupName;
204}
205
206/* CONTAINERS */
207
208/**
209   \brief Initializes a Container.
210   sets the Container-Specific defaults.
211*/
212void Container::init (void)
213{
214  isOption = -1;
215
216  static_cast<Packer*>(this)->init();
217
218  return;
219}
220
221/**
222   \briefFills a Container with lowerWidget.
223   It does this by filling up the down pointer only if down points to NULL.
224   \param lowerWidget the Widget that should be filled into the Container.
225*/
226void Container::fill (Widget *lowerWidget)
227{
228  if (this->down == NULL)
229    {
230      gtk_container_add (GTK_CONTAINER (this->widget), lowerWidget->widget);
231      this->down = lowerWidget;
232    }
233  else
234    cout << "!!error!! You try to put more than one Widget into a Container. \nNot including this item.\nThis is only possible with Boxes.\n"<<endl;
235}
236
237// gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
238
239/* WINDOW */
240
241Window* Window::mainWindow = NULL;
242
243void Window::addWindow(Window* windowToAdd)
244{
245  if (!mainWindow)
246    {
247      mainWindow = windowToAdd;
248      return;
249    }
250
251  Widget* tmpWindow = mainWindow;
252  while (tmpWindow->next)
253    tmpWindow = tmpWindow->next;
254  tmpWindow->next = windowToAdd;
255 
256  return;
257}
258     
259
260
261/**
262   \brief Creating a new Window without a Name
263*/
264Window::Window (void)
265{
266  this->init();
267}
268
269/**
270   \brief Creating a Window with a name
271   \param windowName the name the window should get.
272*/
273Window::Window (char* windowName)
274{
275  this->init();
276  this->setTitle (windowName);
277}
278
279/**
280   \brief initializes a new Window
281*/
282void Window::init()
283{
284  if (!mainWindow)
285    mainWindow = this;
286 
287  isOpen = false;
288
289  static_cast<Container*>(this)->init();
290
291  widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
292  gtk_window_set_policy (GTK_WINDOW(widget), TRUE, TRUE, TRUE);
293#if !defined(__WIN32__)
294  gtk_window_set_decorated (GTK_WINDOW (widget), FALSE);
295#endif
296  gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
297
298}
299
300/**
301   \brief Shows all Widgets that are included within this->widget.
302*/
303void Window::showall ()
304{
305  if (!isOpen)
306    {
307      printf ("showall\n");
308      gtk_widget_show_all  (widget);
309      isOpen = true;
310    }
311  else
312    {
313      printf ("showone\n");
314      gtk_widget_show (widget);
315    }
316}
317
318/**
319   \brief Set The Window-title to title
320   \param title title the Window should get.
321*/
322void Window::setTitle (char* title)
323{
324  label=title;
325  gtk_window_set_title (GTK_WINDOW (widget), title);
326}
327
328/**
329   \brief opens up a Window and fixes the Focus to it
330*/
331void Window::open()
332{
333  if (this != mainWindow)
334    {
335      isOpen = true;
336      gtk_widget_show_all(widget);
337      gtk_grab_add(widget);
338    }
339}
340
341/**
342   \brief closes up a Window and removes the Focus from it
343*/
344void Window::close()
345{
346  if (this != mainWindow)
347    {
348      isOpen = false;
349      gtk_grab_remove(widget);
350      gtk_widget_hide (widget);
351    }
352}
353
354/**
355   \brief opens up a window (not topmost Window).
356   this is the Signal that does it. !!SIGNALS ARE STATIC!!
357   \param widget the widget that did it!
358   \param event the event that did it!
359   \param window the Window that should be opened
360*/
361gint Window::windowOpen (GtkWidget *widget, GdkEvent* event, void* window)
362{
363  static_cast<Window*>(window)->open();
364}
365
366/**
367   \brief closes a window (not topmost Window).
368   this is the Signal that does it. !!SIGNALS ARE STATIC!!
369   \param widget the widget that did it!
370   \param event the event that did it!
371   \param window the Window that should be closed
372*/
373gint Window::windowClose (GtkWidget *widget, GdkEvent* event, void* window)
374{
375  static_cast<Window*>(window)->close();
376 
377}
378/**
379 * Quits the orxonox_GUI.
380 * This can be called as a Signal and is therefor static
381 \param widget The widget that called this function
382 \param event the event that happened to execute this function
383 \param data some data passed with the Signal
384 */
385gint Window::orxonox_gui_quit (GtkWidget *widget, GdkEvent *event, gpointer data)
386{
387  if (exec->shouldsave())
388    exec->writeToFile (orxonoxGUI);
389
390  gtk_main_quit();
391  return FALSE;
392}
393
394
395/* FRAME */
396
397/**
398    \brief Creates a new Frame without a name
399*/
400Frame::Frame (void)
401{
402  this->init();
403}
404
405/**
406   \brief Creates a new Frame with name title
407*/
408Frame::Frame (char* title)
409{
410  this->init();
411  this->setTitle(title);
412}
413
414/**
415    \brief Initializes a new Frame with default settings
416*/
417void Frame::init()
418{
419  static_cast<Container*>(this)->init();
420 
421  widget = gtk_frame_new ("");
422  gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
423}
424
425/**
426   \brief Sets the Frames name to title
427   \param title The title the Frame should get.
428*/
429void Frame::setTitle (char* title)
430{
431  label = title;
432  gtk_frame_set_label (GTK_FRAME (widget), title);
433}
434
435// EVENTBOX //
436
437/**
438   \brief Creates a new EventBox with default settings.
439*/
440EventBox::EventBox ()
441{
442  this->init();
443}
444/**
445   \brief Creates a new EventBox with name title
446   \param title title the Eventbox should get (only data-structure-internal)
447*/
448EventBox::EventBox (char* title)
449{
450  this->init();
451  this->setTitle(title);
452}
453
454/**
455   \brief Initializes a new EventBox
456*/
457void EventBox::init(void)
458{
459  isOption = -1;
460
461  static_cast<Container*>(this)->init();
462
463  widget = gtk_event_box_new ();
464  gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
465 
466}
467
468/**
469   \brief Sets the Title of the EventBox (not implemented)
470   \param title Name the EventBox should get (only datastructure-internal).
471*/
472void EventBox::setTitle (char* title)
473{
474  label = title;
475}
476
477/* BOX */
478
479/**
480   \brief Creates a new horizontal Box
481*/
482Box::Box (void)
483{
484  this->init('h');
485}
486
487/**
488   \brief Creates a new Box of type boxtype
489   \param boxtype if 'v' the Box will be vertically, if 'h' the Box will be horizontally
490*/
491Box::Box (char boxtype)
492{
493  this->init(boxtype);
494}
495
496/**
497   \brief Initializes a new Box with type boxtype
498   \param boxtype see Box(char boxtype)
499*/
500void Box::init(char boxtype)
501{
502  isOption = -2;
503
504  static_cast<Packer*>(this)->init();
505  if (boxtype == 'v')
506    {
507      widget = gtk_vbox_new (FALSE, 0);
508    }
509  else
510    {
511      widget = gtk_hbox_new (FALSE, 0);
512    }
513}
514
515/**
516    \brief Fills a box with a given Widget.
517    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
518    \param lowerWidget the next Widget that should be appendet to this Box
519*/
520void Box::fill (Widget *lowerWidget)
521{
522  gtk_box_pack_start (GTK_BOX (this->widget), lowerWidget->widget, TRUE, TRUE, 0);
523  if (this->down == NULL)
524    this->down = lowerWidget;
525  else
526    {
527      Widget* tmp;
528      tmp = this->down;
529      while (tmp->next != NULL)
530        {
531          tmp = tmp->next;
532        }
533      tmp->next = lowerWidget;
534    }
535}
536
537/* IMAGE */
538
539/**
540   \brief Creates a new Image
541   \param imagename the location of the Image on the Hard Disc
542*/
543Image::Image (char* imagename)
544{
545  this->init();
546  widget = gtk_image_new_from_file (imagename);
547  label = imagename;
548}
549
550/**
551    \brief Initializes a new Image
552*/
553void Image::init()
554{
555  isOption = 0;
556
557  static_cast<Widget*>(this)->init();
558}
559
560
561/* OPTION */
562
563/**
564   \brief Initializes a new Option.
565   sets all Option-Specific-Values to their defaults.
566*/
567void Option::init()
568{
569  value = 0;
570  flag_name = "";
571  flag_name_short = "";
572  saveable = false;
573  default_value = 0;
574
575  static_cast<Widget*>(this)->init();
576
577  return;
578}
579
580/**
581   \brief This sets The FlagName of an Option and defines its default Values
582   !! Options will be saved if flagname is different from "" !!
583   \param flagname the Name that will be displayed in the output
584   \param defaultvalue the default Value for this Option (see definition of defaultvalue
585*/
586void Option::setFlagName (char* flagname, int defaultvalue)
587{
588  flag_name = flagname;
589  default_value = defaultvalue;
590  cout << "Set Flagname of " << label << " to " << flagname << endl;
591}
592
593/**
594    \brief see Option::setFlagName (char* flagname, int defaultvalue)
595    \param flagname the Name that will be displayed in the output
596    \param defaultvalue the default Value for this Option (see definition of defaultvalue
597    \param flagnameshort a short flagname to be displayed in the output
598*/
599void Option::setFlagName (char* flagname, char* flagnameshort,  int defaultvalue)
600{
601  flag_name = flagname;
602  flag_name_short = flagnameshort;
603  default_value = defaultvalue;
604  cout << "Set Flagname of " << label << " to " << flagname << endl;
605}
606
607
608/* BUTTON */
609
610/**
611   \brief Creates a new Button with a buttonname
612   \param buttonname sets the Name of the Button
613*/
614Button::Button(char* buttonname)
615{
616  this->init();
617  this->setTitle(buttonname);
618}
619
620/**
621   \brief Initializes a new Button
622*/
623void Button::init(void)
624{
625  isOption = 0;
626
627  static_cast<Option*>(this)->init();
628
629  widget = gtk_button_new_with_label ("");
630}
631
632/**
633   \brief Sets a new name to the Button
634   \param title The name the Button should get
635*/
636void Button::setTitle (char *title)
637{
638  label = title;
639  gtk_button_set_label (GTK_BUTTON(widget), title);
640}
641
642/**
643   \brief redraws the Button
644   not implemented yet
645*/
646void Button::redraw ()
647{
648}
649
650/* CHECKBUTTON */
651
652/**
653   \brief Creates a new CheckButton with an ame
654   \param buttonname The name the CheckButton should display.
655*/
656CheckButton::CheckButton (char* buttonname)
657{
658  this->init();
659  this->setTitle(buttonname);
660
661  this->connectSignal ("clicked", this->OptionChange);
662}
663
664/**
665   \brief Initialize a new CheckButton with default settings
666*/
667void CheckButton::init(void)
668{
669  isOption = 1;
670
671  static_cast<Option*>(this)->init();
672
673  widget = gtk_check_button_new_with_label ("");
674}
675
676/**
677   \brief Sets a new Title to a CheckButton
678   \param title The new Name the CheckButton should display.
679*/
680void CheckButton::setTitle(char* title)
681{
682  label = title;
683  gtk_button_set_label(GTK_BUTTON(widget), title);
684}
685
686bool CheckButton::isActive()
687{
688  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
689}
690
691/**
692    \brief Signal OptionChange writes the Value from the CheckButton to its Object-Database.
693    \param widget The widget(CheckButton) that has a changed Value
694    \param checkbutton the CheckButton-Object that should receive the change.
695*/
696gint CheckButton::OptionChange (GtkWidget *widget, Widget* checkbutton)
697{
698  static_cast<CheckButton*>(checkbutton)->value = (int)gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ((CheckButton*)checkbutton->widget));
699  flags->setTextFromFlags(orxonoxGUI);   ////// must be different!!!
700  cout << static_cast<CheckButton*>(checkbutton)->label << " set to: " << static_cast<CheckButton*>(checkbutton)->value << endl;
701}
702
703/**
704   \brief Redraws the CheckButton (if option has changed).
705   Example: if new settings are loaded the Button must be redrawn for the GUI to display that Change
706*/
707void CheckButton::redraw ()
708{
709  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
710}
711
712/* SLIDER */
713
714/**
715   \brief Creates a new Slider
716   \param slidername The data-structure-name of the slider.
717   \param start The minimal Value of the slider.
718   \param end The maximal Value of the slider.
719*/
720Slider::Slider (char* slidername, int start, int end)
721{
722  this->init(start, end);
723  this->setValue(start);
724  this->setTitle(slidername);
725  this->connectSignal ("value_changed", this->OptionChange);
726}
727
728/**
729   \brief Initializes a Slider with start and end Values
730   params: see Slider::Slider (char* slidername, int start, int end)
731*/
732void Slider::init(int start, int end)
733{
734  isOption = 2;
735
736  static_cast<Option*>(this)->init();
737
738  widget = gtk_hscale_new_with_range (start, end, 5);
739}
740
741/**
742   \brief Sets a new Title to the Slider
743   \param title The new Name of the slider
744*/
745void Slider::setTitle(char* title)
746{
747  label = title;
748}
749
750/**
751   \brief Setting a new value to the Slider.
752   Maybe you also require a Slider::redraw() for this to display
753*/
754void Slider::setValue(int value)
755{
756  this->value = value;
757}
758
759/**
760    \brief Signal OptionChange writes the Value from the Slider to its Object-Database.
761    \param widget The widget(Slider) that has a changed Value
762    \param slider the Slider-Object that should receive the change.
763*/
764gint Slider::OptionChange (GtkWidget *widget, Widget* slider)
765{
766  static_cast<Slider*>(slider)->value = (int)gtk_range_get_value (GTK_RANGE ((Slider*)slider->widget));
767  flags->setTextFromFlags(orxonoxGUI);  //// must be different !!!
768  cout << static_cast<Slider*>(slider)->label << " set to: "<< static_cast<Slider*>(slider)->value << endl;
769}
770
771/**
772   \brief Redraws the widget
773   Example: see void CheckButton::redraw ()
774*/
775void Slider::redraw ()
776{
777  gtk_range_set_value (GTK_RANGE (widget), value);
778}
779
780/* MENU */
781
782/**
783    \brief Creates a Menu-Item-list out of multiple input.
784    !! Consider, that the last input argument has to be "lastItem" for this to work!!
785    \param menuname The Database-Name of this Menu
786    \param ... items to be added to this Menu. !! Consider, that the last input argument has to be "lastItem" for this to work!!
787*/
788Menu::Menu (char* menuname, ...)
789{
790  this->init();
791  this->setTitle(menuname);
792   
793  char *itemName;
794 
795  va_start (itemlist, menuname);
796  while (strcmp (itemName = va_arg (itemlist, char*), "lastItem"))
797    {
798      this->addItem(itemName);
799    }
800  va_end(itemlist);
801
802  gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu);
803  this->connectSignal ("changed", this->OptionChange);
804}
805
806/**
807   \brief Initializes a new Menu with no items
808*/
809void Menu::init(void)
810{
811  isOption = 2;
812
813  static_cast<Option*>(this)->init();
814
815  widget = gtk_option_menu_new ();
816  menu = gtk_menu_new ();
817
818}
819
820/**
821 * Sets the Database-Name of this Menu
822 \param title Database-Name to be set.
823*/
824void Menu::setTitle(char* title)
825{
826  label = title;
827}
828
829/**
830   \brief appends a new Item to the Menu-List.
831   \param itemName the itemName to be appendet.
832*/
833void Menu::addItem (char* itemName)
834{
835  item = gtk_menu_item_new_with_label (itemName);
836  gtk_menu_shell_append(GTK_MENU_SHELL (menu), item);
837}
838
839/**
840    \brief Signal OptionChange writes the Value from the Menu to its Object-Database.
841    \param widget The widget(Menu) that has a changed Value
842    \param menu the Menu-Object that should receive the change.
843*/
844gint Menu::OptionChange (GtkWidget *widget, Widget* menu)
845{
846  static_cast<Menu*>(menu)->value = (int)gtk_option_menu_get_history (GTK_OPTION_MENU (menu->widget));
847  flags->setTextFromFlags(orxonoxGUI); //// must be different !!!
848  cout << static_cast<Menu*>(menu)->label << " changed to : " << static_cast<Menu*>(menu)->value << endl;
849}
850
851/**
852   \brief Redraws the widget
853   Example: see void CheckButton::redraw ()
854 */
855void Menu::redraw ()
856{
857  gtk_option_menu_set_history (GTK_OPTION_MENU (widget), value);
858}
859
860/**
861   \brief Creates a new default Label with no Text.
862   You migth consider adding Label::setTitle with this.
863*/
864Label:: Label ()
865{
866  this->init();
867}
868
869/**
870   \brief Creates a new Label with a Text.
871   \param text The text to be displayed.
872*/
873Label:: Label (char* text)
874{
875  this->init();
876  this->setText(text);
877}
878
879/**
880   \brief initializes a new Label
881*/
882void Label::init(void)
883{
884  isOption = 0;
885
886  static_cast<Widget*>(this)->init();
887
888  widget = gtk_label_new ("");
889  gtk_label_set_line_wrap (GTK_LABEL(widget), TRUE);
890}
891
892/**
893   \brief Sets a new Text to a Label.
894   \param text The text to be inserted into the Label.
895*/
896void Label::setText (char* text)
897{
898  label = text;
899  gtk_label_set_text (GTK_LABEL (this->widget), text);
900}
901
902/**
903   \brief get the Text of a Label
904   \return The Text the Label holds.
905*/
906char* Label::getText ()
907{
908  return ((char*)gtk_label_get_text (GTK_LABEL (this->widget)));
909}
Note: See TracBrowser for help on using the repository browser.