core/vgui/impl/gtk/vgui_gtk_utils.cxx
Go to the documentation of this file.
00001 // This is core/vgui/impl/gtk/vgui_gtk_utils.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Philip C. Pritchett, RRG, University of Oxford
00008 // \date   19 Dec 99
00009 // \brief  See vgui_gtk_utils.h for a description of this file.
00010 
00011 #include "vgui_gtk_utils.h"
00012 
00013 #include <vcl_iostream.h>
00014 #include <vcl_cstdlib.h> // for vcl_abort()
00015 
00016 #include <vgui/vgui_gl.h>
00017 #include <gdk/gdkkeysyms.h>
00018 #include <gtk/gtk.h>
00019 #include <gtkgl/gtkglarea.h>
00020 
00021 #include <vgui/vgui_command.h>
00022 #include <vgui/vgui_menu.h>
00023 
00024 static bool debug = false;
00025 GtkAccelGroup *vgui_gtk_utils::accel_group = NULL;
00026 
00027 vgui_button vgui_gtk_utils::translate_button(int button)
00028 {
00029   if (button == 1)
00030     return vgui_LEFT;
00031   else if (button == 2)
00032     return vgui_MIDDLE;
00033   else if (button == 3)
00034     return vgui_RIGHT;
00035 #if 1
00036   // spinning the wheel generates button events no 4 and 5 -- fsm
00037   else if (button == 4)
00038     return vgui_MIDDLE;
00039   else if (button == 5)
00040     return vgui_MIDDLE;
00041 #endif
00042   else
00043     vcl_abort();
00044   return vgui_BUTTON_NULL;
00045 }
00046 
00047 vgui_key vgui_gtk_utils::translate_key(GdkEventKey const *gev)
00048 {
00049   if (gev->length == 1)
00050     return vgui_key( *(gev->string) );
00051 
00052   switch (gev->keyval)
00053   {
00054    case GDK_Page_Up:
00055     return vgui_PAGE_UP;
00056    case GDK_Page_Down:
00057     return vgui_PAGE_DOWN;
00058    case GDK_Home:
00059     return vgui_HOME;
00060    case GDK_End:
00061     return vgui_END;
00062    case GDK_Delete:
00063     return vgui_DELETE;
00064    case GDK_Insert:
00065     return vgui_INSERT;
00066    case GDK_Up:
00067     return vgui_CURSOR_UP;
00068    case GDK_Down:
00069     return vgui_CURSOR_DOWN;
00070    case GDK_Left:
00071     return vgui_CURSOR_LEFT;
00072    case GDK_Right:
00073     return vgui_CURSOR_RIGHT;
00074   }
00075 
00076   return vgui_KEY_NULL;
00077 }
00078 
00079 void vgui_gtk_utils::set_coordinates(vgui_event &e, const gdouble x, const gdouble y)
00080 {
00081   GLint vp[4];
00082   glGetIntegerv(GL_VIEWPORT, vp);
00083   // FIXME : the size of the current glViewport settings is not
00084   // really what we want -- we want the size of the _window_.
00085   e.wx = (int)x;
00086   e.wy = vp[3]-1-(int)y;
00087 }
00088 
00089 void vgui_gtk_utils::set_modifiers(vgui_event &e, const guint state)
00090 {
00091   e.modifier = vgui_modifier( ((state & 4)?vgui_CTRL:0) |
00092                               ((state & 8)?vgui_ALT:0) |
00093                               ((state & 1)?vgui_SHIFT:0) );
00094 }
00095 
00096 
00097 bool vgui_gtk_utils::is_modifier(GdkEvent const *gev)
00098 {
00099   if (gev->type != GDK_KEY_PRESS &&
00100       gev->type != GDK_KEY_RELEASE)
00101     return false;
00102 
00103   GdkEventKey *e = (GdkEventKey*)(const_cast<GdkEvent*>(gev));
00104   // cannot use static_cast<> here since GdkEventKey and GdkEvent are unrelated
00105 
00106 #if 0
00107   // This code would only return 'true' if any of the modifier keys is solely
00108   // pressed. However we want to return 'true' so long as any of the modifier
00109   // keys is pressed simultaneously with some other key. This is a must
00110   // if we want to allow menu accelerator keys. - u97mb
00111 
00112   return e->keyval & GDK_Shift_L ||
00113          e->keyval & GDK_Shift_R ||
00114          e->keyval & GDK_Control_L ||
00115          e->keyval & GDK_Control_R ||
00116          e->keyval & GDK_Meta_L ||
00117          e->keyval & GDK_Meta_R ||
00118          e->keyval & GDK_Alt_L ||
00119          e->keyval & GDK_Alt_R;
00120 #endif // 0
00121   // - u97mb
00122   // GDK_MOD1_MASK corresponds to META key(at least on Sun Solaris)
00123   return e->state & GDK_CONTROL_MASK ||
00124          e->state & GDK_SHIFT_MASK ||
00125          e->state & GDK_MOD1_MASK;
00126 }
00127 
00128 
00129 static void execute_command(GtkWidget*, gpointer c)
00130 {
00131   vgui_command *cmnd = static_cast<vgui_command*>(c);
00132   cmnd->execute();
00133 }
00134 
00135 
00136 void vgui_gtk_utils::add_submenu(GtkWidget *widget, const vgui_menu& menu)
00137 {
00138   for (unsigned i=0;i<menu.size();i++)
00139   {
00140     if (menu[i].is_separator())
00141     {
00142       if (debug) vcl_cerr << " <separator>\n";
00143       GtkWidget* item = gtk_menu_item_new();
00144       gtk_menu_append(GTK_MENU(widget), item);
00145       gtk_widget_show(item);
00146     }
00147 
00148     else if (menu[i].is_command())
00149     {
00150       if (debug) vcl_cerr << " <command>\n";
00151       GtkWidget* item = gtk_menu_item_new_with_label(menu[i].name.c_str());
00152       gtk_signal_connect(GTK_OBJECT(item), "activate",
00153                          GTK_SIGNAL_FUNC(execute_command),
00154                          (void*)menu[i].cmnd.as_pointer());
00155 
00156       gtk_menu_append(GTK_MENU(widget), item);
00157 
00158       gtk_widget_show(item);
00159       if (menu[i].short_cut.mod!=vgui_MODIFIER_NULL ||
00160           menu[i].short_cut.key!=vgui_KEY_NULL)
00161       {
00162         gint mask = 0;
00163         // Health warning - It seems that GDK_MOD1_MASK corresponds
00164         // to META on Solaris and ALT has no correspondance
00165         if (menu[i].short_cut.mod & vgui_CTRL)
00166           mask|=GDK_CONTROL_MASK;
00167         if (menu[i].short_cut.mod & vgui_META)
00168           mask|=GDK_MOD1_MASK;
00169         if (menu[i].short_cut.mod & vgui_SHIFT)
00170           mask|=GDK_SHIFT_MASK;
00171         if (menu[i].short_cut.mod & vgui_ALT)
00172           mask|=GDK_MOD2_MASK;
00173         gtk_widget_add_accelerator (item,
00174                                     "activate",
00175                                     accel_group,
00176                                     char(menu[i].short_cut.key),
00177                                     mask,
00178                                     GtkAccelFlags(GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED));
00179       }
00180     }
00181     else if (menu[i].is_submenu())
00182     {
00183       if (debug) vcl_cerr << " <submenu>\n";
00184       GtkWidget* item = gtk_menu_item_new_with_label(menu[i].name.c_str());
00185       GtkWidget* submenu = gtk_menu_new();
00186 
00187       gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
00188       gtk_menu_append(GTK_MENU(widget), item);
00189       gtk_widget_show(item);
00190 
00191       add_submenu(submenu, *menu[i].menu);
00192     }
00193   }
00194 }
00195 
00196 void vgui_gtk_utils::set_menu(GtkWidget *widget, const vgui_menu& menu, bool is_menubar)
00197 {
00198   for (unsigned i=0;i<menu.size();i++)
00199   {
00200     if (menu[i].is_separator())
00201     {
00202       if (debug) vcl_cerr << " <separator>\n";
00203       GtkWidget* item = gtk_menu_item_new();
00204       if (!is_menubar)
00205         gtk_menu_append(GTK_MENU(widget), item);
00206       gtk_widget_show(item);
00207     }
00208     else if (menu[i].is_command())
00209     {
00210       if (debug) vcl_cerr << " <command> " << menu[i].name << vcl_endl;
00211       GtkWidget* item = gtk_menu_item_new_with_label(menu[i].name.c_str());
00212 
00213       if (is_menubar)
00214         gtk_menu_bar_append(GTK_MENU_BAR(widget), item);
00215       else
00216       {
00217         if (menu[i].short_cut.mod!=vgui_MODIFIER_NULL ||
00218             menu[i].short_cut.key!=vgui_KEY_NULL)
00219         {
00220           gint mask = 0;
00221           // Health warning - It seems that GDK_MOD1_MASK corresponds
00222           // to META on Solaris and ALT has no correspondance
00223           if (menu[i].short_cut.mod & vgui_CTRL)
00224             mask|=GDK_CONTROL_MASK;
00225           if (menu[i].short_cut.mod & vgui_META)
00226             mask|=GDK_MOD1_MASK;
00227           if (menu[i].short_cut.mod & vgui_SHIFT)
00228             mask|=GDK_SHIFT_MASK;
00229           if (menu[i].short_cut.mod & vgui_ALT)
00230             mask|=GDK_MOD2_MASK;
00231           gtk_widget_add_accelerator (item,
00232                                       "activate",
00233                                       accel_group,
00234                                       char(menu[i].short_cut.key),
00235                                       mask,
00236                                       GtkAccelFlags(GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED));
00237         }
00238         gtk_menu_append(GTK_MENU(widget), item);
00239       }
00240 
00241       gtk_signal_connect(GTK_OBJECT(item), "activate",
00242                          GTK_SIGNAL_FUNC(execute_command),
00243                          (void*)menu[i].cmnd.as_pointer());
00244 
00245       gtk_widget_show(item);
00246     }
00247     else if (menu[i].is_submenu())
00248     {
00249       if (debug) vcl_cerr << " <submenu> " << menu[i].name << vcl_endl;
00250 
00251       GtkWidget* item = gtk_menu_item_new_with_label(menu[i].name.c_str());
00252       GtkWidget* submenu = gtk_menu_new();
00253 
00254       gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
00255 
00256       if (is_menubar)
00257         gtk_menu_bar_append(GTK_MENU_BAR(widget), item);
00258       else
00259         gtk_menu_append(GTK_MENU(widget), item);
00260 
00261       gtk_widget_show(item);
00262 
00263       add_submenu(submenu, *menu[i].menu);
00264     }
00265   }
00266 }