Back to index

im-sdk  12.3.91
quick-access-menu.c
Go to the documentation of this file.
00001 /* GIMLET: GNOME Input Method Language Enabing Tool
00002  *
00003  * Copyright 2003 Sun Microsystems Inc.
00004  *
00005  * This is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <gtk/gtkmain.h>
00024 #include <gtk/gtksignal.h>
00025 #include <panel-applet.h>
00026 #include <gnome.h>
00027 #include <gtk/gtkdialog.h>
00028 #include <gtk/gtkradiomenuitem.h>
00029 
00030 #include "gnome-im-switcher.h"
00031 #include "quick-access-menu.h"
00032 #include "language.h"
00033 #include "iiim-interface.h"
00034 #include "widgets.h"
00035 
00036 static void
00037 get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
00038 {
00039   GimletWindow *curr_data = data;
00040   GtkRequisition  reqmenu;
00041   gint tempx, tempy, width, height;
00042   gint screen_width, screen_height;
00043        
00044   gtk_widget_size_request (GTK_WIDGET (menu), &reqmenu);
00045   gdk_window_get_origin (GTK_WIDGET (curr_data->applet)->window, &tempx, &tempy);
00046   gdk_window_get_geometry (GTK_WIDGET (curr_data->applet)->window, NULL, NULL,
00047                         &width, &height, NULL);
00048                            
00049   switch (panel_applet_get_orient (PANEL_APPLET (curr_data->applet))) {
00050   case PANEL_APPLET_ORIENT_DOWN:
00051     tempy += height;
00052     break;
00053   case PANEL_APPLET_ORIENT_UP:
00054     tempy -= reqmenu.height;
00055     break;
00056   case PANEL_APPLET_ORIENT_LEFT:
00057     tempx -= reqmenu.width;
00058     break;
00059   case PANEL_APPLET_ORIENT_RIGHT:
00060     tempx += width;
00061     break;
00062   }
00063   screen_width = gdk_screen_width ();
00064   screen_height = gdk_screen_height ();
00065   *x = CLAMP (tempx, 0, MAX (0, screen_width - reqmenu.width));
00066   *y = CLAMP (tempy, 0, MAX (0, screen_height - reqmenu.height));
00067 }
00068 
00069 static void
00070 edit_languages_destroyed_callback (GtkWidget   *new_profile_dialog,
00071                                    GimletWindow *gimlet)
00072 {
00073   gimlet->edit_languages_dialog = NULL;
00074 }
00075 
00076 static void
00077 update_langmenu_cb (GtkWidget *menuitem, GimletWindow *gimlet)
00078 {
00079   GtkWindow *transient_parent;
00080   GtkWindow *old_transient_parent;
00081 
00082   transient_parent = GTK_WINDOW (gimlet->applet);
00083   if (gimlet->edit_languages_dialog == NULL)
00084     {
00085       old_transient_parent = NULL;
00086       /* passing in transient_parent here purely for the
00087        * glade error dialog
00088        */
00089       gimlet->edit_languages_dialog =
00090        gimlet_langmenu_dialog_new (transient_parent, gimlet);
00091       if (gimlet->edit_languages_dialog == NULL)
00092         return; /* glade file missing */
00093       
00094       g_signal_connect (G_OBJECT (gimlet->edit_languages_dialog),
00095                         "destroy",
00096                         G_CALLBACK (edit_languages_destroyed_callback),
00097                         gimlet);
00098     }
00099   else 
00100     {
00101       old_transient_parent = gtk_window_get_transient_for (GTK_WINDOW (gimlet->edit_languages_dialog));
00102     }
00103   
00104   if (old_transient_parent != transient_parent)
00105     {
00106       gtk_window_set_transient_for (GTK_WINDOW (gimlet->edit_languages_dialog),
00107                                     transient_parent);
00108       gtk_widget_hide (gimlet->edit_languages_dialog); /* re-show the window on its new parent */
00109     }
00110   
00111   gtk_widget_show_all (gimlet->edit_languages_dialog);
00112   gtk_window_present (GTK_WINDOW (gimlet->edit_languages_dialog));
00113 }
00114 
00115 static void
00116 activate_cb (GtkWidget *menuitem, GimletWindow *gimlet)
00117 {
00118   if (GTK_MENU_ITEM (menuitem))
00119     {
00120       gchar *iiim_lang;
00121       gchar *lename, *lang_le, *imename;
00122       gchar *conversion_mode;
00123       gchar *le_delimiter = ":";
00124 
00125       iiim_lang = g_strdup(g_object_get_data (G_OBJECT (menuitem), "iiim-lang-name"));
00126       lename = g_strdup(g_object_get_data (G_OBJECT (menuitem), "iiim-lename"));
00127 
00128       if (lename)
00129        lang_le = g_strconcat (iiim_lang, le_delimiter, lename, NULL);
00130       else
00131        lang_le = g_strdup (iiim_lang);
00132 
00133       gimlet_iiim_language_set (gimlet, lang_le);
00134 
00135       free(lang_le);
00136 
00137       if (gimlet->current_iiim_lang)
00138        g_free (gimlet->current_iiim_lang);
00139       gimlet->current_iiim_lang = g_strdup (iiim_lang);
00140 
00141       gimlet_update_lang (gimlet);
00142 
00143       /* set initial conversion mode */
00144       if (gimlet->conversion_on_start == FALSE)
00145        conversion_mode = "off";
00146       else
00147        conversion_mode = gimlet_language_get_conversion_mode (iiim_lang);
00148 
00149       gimlet_iiim_conversion_mode_set (gimlet, conversion_mode);
00150     }
00151 }
00152 
00153 static void
00154 edit_hotkey_destroyed_callback (GtkWidget *dialog,
00155                             GimletWindow *gimlet)
00156 {
00157   gimlet->edit_hotkey_dialog = NULL;
00158 }
00159 
00160 static void
00161 hotkey_cb (GtkWidget *menuitem, GimletWindow *gimlet)
00162 {
00163   GtkWindow *transient_parent;
00164   GtkWindow *old_transient_parent;
00165 
00166   transient_parent = GTK_WINDOW (gimlet->applet);
00167   if (gimlet->edit_hotkey_dialog == NULL)
00168     {
00169       old_transient_parent = NULL;
00170       /* passing in transient_parent here purely for the
00171        * glade error dialog
00172        */
00173       gimlet->edit_hotkey_dialog =
00174        gimlet_hotkey_dialog_new (transient_parent, gimlet);
00175       if (gimlet->edit_hotkey_dialog == NULL)
00176        return; /* glade file missing */
00177 
00178       g_signal_connect (G_OBJECT (gimlet->edit_hotkey_dialog),
00179                      "destroy",
00180                      G_CALLBACK (edit_hotkey_destroyed_callback),
00181                      gimlet);
00182     }
00183   else
00184     {
00185       old_transient_parent = gtk_window_get_transient_for (
00186                                GTK_WINDOW (gimlet->edit_hotkey_dialog));
00187     }
00188 
00189   if (old_transient_parent != transient_parent)
00190     {
00191       gtk_window_set_transient_for (GTK_WINDOW (gimlet->edit_hotkey_dialog),
00192                                 transient_parent);
00193       gtk_widget_hide (gimlet->edit_hotkey_dialog);
00194     }
00195 
00196   gtk_widget_show_all (gimlet->edit_hotkey_dialog);
00197   gtk_window_present (GTK_WINDOW (gimlet->edit_hotkey_dialog));
00198 }
00199 
00200 static void
00201 turn_off_cb (GtkWidget *menuitem, GimletWindow *gimlet)
00202 {
00203   gimlet_iiim_conversion_mode_set (gimlet, "off");
00204 }
00205 
00206 static
00207 gint string_comp(gconstpointer a, gconstpointer b)
00208 {
00209   return g_strcasecmp (a, b);
00210 }
00211 
00212 GSList*
00213 get_iiimf_lang_le_list (GimletWindow *gimlet, gchar *iiim_lang_name, gchar ***imelist)
00214 {
00215   const gchar *im_delimiter = ";";
00216   gchar **input_method_list = NULL;
00217   GSList *lelist = NULL;
00218 
00219   if (gimlet->le_list == NULL)
00220     return NULL;
00221 
00222   *imelist = NULL;
00223 
00224   input_method_list = g_strsplit (gimlet->le_list, im_delimiter, -1);
00225 
00226   if (input_method_list)
00227     {
00228       gchar **p;
00229       const gchar *le_delimiter = ":";
00230       const gchar ime_delimiter = '-';
00231       gchar **le = NULL;
00232       gchar **list = g_new0 (char *, 10); /* impossible that one language has more than ten LEs */
00233       int num_of_le = 0;
00234 
00235       for (p = input_method_list; *p; p++)
00236        {
00237          char *pime;
00238 
00239          le = g_strsplit (*p, le_delimiter, -1);
00240 
00241          /* probably 'le' consists of lename and imename which are separated by ime_delimiter */
00242          pime = le[1];
00243          while (*pime && *pime != ime_delimiter) ++pime;
00244          if (*pime == ime_delimiter)  *pime++ = 0x0;
00245 
00246          if ((strcmp ((gchar*)le[0], iiim_lang_name) == 0) &&
00247              !(g_slist_find_custom (lelist, le[1], (GCompareFunc)string_comp)))
00248             {
00249               lelist = g_slist_append (lelist, le[1]);
00250               if (*pime) list[num_of_le++] = pime;
00251             }
00252        }
00253 
00254        if (num_of_le)
00255          {
00256            int i;
00257 
00258            *imelist = g_new0 (gchar *, num_of_le + 1);
00259 
00260            for (i = 0; i < num_of_le; ++i)
00261               if (list[i]) *imelist[i] = g_strdup (list[i]);
00262          }
00263 
00264        g_free (list);
00265     }
00266   g_strfreev (input_method_list);
00267   return lelist;
00268 }
00269 
00270 static void
00271 quick_lang_menu_init (GimletWindow *gimlet)
00272 {
00273   GtkWidget *menu;
00274   GtkWidget *menuitem;
00275   GSList *active_languages;
00276   GSList *tmp;
00277   gchar key_navi[2];
00278   /*
00279     Added underlined access keys 'A' - 'Y' for all the language items on the
00280     language menu for key navigation. 'Z' is used for Add or Remove...
00281   */
00282   menu = gtk_menu_new ();
00283   active_languages = gimlet_language_get_active_languages ();
00284 
00285   key_navi[0] = 'A';
00286   key_navi[1] = '\0';
00287 
00288   for (tmp = active_languages; tmp; tmp = g_slist_next (tmp))
00289     {
00290       char *name;
00291       char *mnemonic_label;
00292       char *iiim_lang_name;
00293       char **imelist;
00294       gchar *ime_seperator = ",";
00295       int i, len;
00296       GSList *lelist;
00297 
00298       name = gimlet_language_get_name (tmp->data);
00299       if (strcmp (name, "ASCII") == 0)
00300        continue;
00301 
00302       iiim_lang_name = gimlet_language_get_iiim_lang_name (tmp->data);
00303       lelist = get_iiimf_lang_le_list (gimlet, iiim_lang_name, &imelist);
00304       if (!lelist)
00305        continue;
00306 
00307       /* add keynav */
00308       mnemonic_label = g_strconcat (name, "(_", key_navi, ")", NULL);
00309       menuitem = gtk_menu_item_new_with_mnemonic (mnemonic_label);
00310       g_free (mnemonic_label);
00311       if (key_navi[0] == 'Y')
00312        key_navi[0] = 'A';
00313       else
00314        key_navi[0] += 1;
00315 
00316       len = g_slist_length (lelist);
00317       if (len == 1 && !imelist)
00318        {
00319             g_object_set_data (G_OBJECT (menuitem), "iiim-lang-name",
00320                              iiim_lang_name);
00321             g_object_set_data (G_OBJECT (menuitem), "iiim-display-name",
00322                              name);
00323              g_object_set_data (G_OBJECT (menuitem), "iiim-lename",
00324                                 lelist->data);
00325             g_signal_connect (GTK_MENU_ITEM (menuitem), "activate",
00326                              G_CALLBACK (activate_cb), gimlet);
00327        }
00328       else
00329        {
00330          GtkWidget *le_submenu;
00331          GtkWidget *le_submenu_item;
00332          GSList *le;
00333 
00334          le_submenu = gtk_menu_new ();
00335 
00336          for (i = 0, le = lelist; le; le = g_slist_next (le), ++i)
00337            {
00338              if (imelist && imelist[i])
00339               {
00340                 gchar **p, **ime_array = g_strsplit (imelist[i], ime_seperator, -1);
00341 
00342                 for (p = ime_array; *p; ++p)
00343                  {
00344                     gchar *lename = g_new0 (char, strlen (le->data) + strlen (*p) + 2);
00345                     gchar *ime_delimiter = "-";
00346 
00347                     g_sprintf (lename, "%s%s%s", (char *)le->data, ime_delimiter, *p);
00348 
00349                      /* here 'p' refers to the name of input method engine in UTF8 */
00350                            le_submenu_item = gtk_menu_item_new_with_label (*p);
00351                       g_object_set_data (G_OBJECT (le_submenu_item), "iiim-lang-name",
00352                                    iiim_lang_name);
00353                            g_object_set_data (G_OBJECT (le_submenu_item), "iiim-display-name",
00354                                    name);
00355                       g_object_set_data (G_OBJECT (le_submenu_item), "iiim-lename",
00356                                    lename);
00357 
00358                       gtk_menu_shell_append (GTK_MENU_SHELL (le_submenu), le_submenu_item);
00359                       g_signal_connect (le_submenu_item, "activate",
00360                                    G_CALLBACK (activate_cb), gimlet);
00361                            gtk_widget_show (le_submenu_item);
00362                  }
00363               }
00364              else
00365               {
00366                   /* le->data stands for the name of LE */
00367                    le_submenu_item = gtk_menu_item_new_with_label (le->data);
00368                    g_object_set_data (G_OBJECT (le_submenu_item), "iiim-lang-name",
00369                                    iiim_lang_name);
00370                    g_object_set_data (G_OBJECT (le_submenu_item), "iiim-display-name",
00371                                    name);
00372                     g_object_set_data (G_OBJECT (le_submenu_item), "iiim-lename",
00373                                    le->data);
00374                    gtk_menu_shell_append (GTK_MENU_SHELL (le_submenu), le_submenu_item);
00375                    g_signal_connect (le_submenu_item, "activate",
00376                                    G_CALLBACK (activate_cb), gimlet);
00377                   gtk_widget_show (le_submenu_item);
00378               }
00379            }
00380 
00381          gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), le_submenu);
00382          gtk_widget_show (le_submenu);
00383        }
00384 
00385       g_slist_free (lelist);
00386 
00387       if (imelist)
00388        {
00389          for (i=0; i < len; ++i) if (imelist[i]) g_free (imelist[i]);
00390 
00391         g_free (imelist);
00392        }
00393 
00394       gtk_widget_show (menuitem);
00395       gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
00396     }
00397 
00398   /* add separator */
00399   menuitem = gtk_separator_menu_item_new ();
00400   gtk_widget_show (menuitem);
00401   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
00402 
00403   /* off item */
00404   char *name;
00405   char *mnemonic_label;
00406   char *iiim_lang_name;
00407   name = gimlet_language_get_name (active_languages->data);
00408   iiim_lang_name = gimlet_language_get_iiim_lang_name (active_languages->data);
00409   mnemonic_label = g_strconcat (_(name), "(_0)", NULL);
00410   menuitem = gtk_menu_item_new_with_mnemonic (mnemonic_label);
00411   gtk_widget_show (menuitem);
00412   gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
00413   g_object_set_data (G_OBJECT (menuitem), "iiim-lang-name",
00414                    iiim_lang_name);
00415   g_object_set_data (G_OBJECT (menuitem), "iiim-display-name",
00416                    name);
00417   g_signal_connect (menuitem, "activate",
00418                   G_CALLBACK (turn_off_cb), gimlet);
00419 
00420   menuitem = gtk_menu_item_new_with_mnemonic (_("Add or Remove...(_Z)"));
00421   gtk_widget_show (menuitem);
00422   gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
00423   g_signal_connect (menuitem, "activate",
00424                   G_CALLBACK (update_langmenu_cb), gimlet);
00425 
00426 // #ifdef CONFIG_HOTKEY
00427 #if 1
00428   /* add separator */
00429   menuitem = gtk_separator_menu_item_new ();
00430   gtk_widget_show (menuitem);
00431   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
00432 
00433   menuitem = gtk_menu_item_new_with_mnemonic (_("Configure hotkey..."));
00434   gtk_widget_show (menuitem);
00435   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
00436   g_signal_connect (menuitem, "activate",
00437                   G_CALLBACK (hotkey_cb), gimlet);
00438 #endif
00439 
00440   gimlet->quick_access_menu->widget = menu;
00441   gimlet->quick_access_menu->active_languages = active_languages;
00442   
00443   return;
00444 }
00445 
00446 void
00447 quick_access_menu_destroy (GimletWindow *gimlet)
00448 {
00449   if (gimlet->quick_access_menu->widget)
00450     {
00451       gtk_widget_destroy (gimlet->quick_access_menu->widget);
00452       gimlet->quick_access_menu->widget = NULL;
00453     }
00454   if (gimlet->quick_access_menu->active_languages)
00455     {
00456       g_slist_foreach (gimlet->quick_access_menu->active_languages,
00457                      (GFunc) gimlet_language_free,
00458                      NULL);
00459       g_slist_free (gimlet->quick_access_menu->active_languages);
00460       gimlet->quick_access_menu->active_languages = NULL;
00461     }
00462 }
00463 
00464 
00465 /* public */
00466 void
00467 gimlet_quick_access_menu_init (GimletWindow *gimlet)
00468 {
00469   if (gimlet->quick_access_menu == NULL)
00470     gimlet->quick_access_menu = g_new0 (QuickAccessMenu, 1);
00471 
00472   quick_access_menu_destroy (gimlet);
00473   quick_lang_menu_init (gimlet);
00474 }
00475 
00476 void
00477 gimlet_quick_access_menu_show (GimletWindow *gimlet)
00478 {
00479   gimlet_quick_access_menu_init (gimlet);
00480   gtk_menu_popup (GTK_MENU (gimlet->quick_access_menu->widget), NULL, NULL,
00481                 get_menu_pos, gimlet,
00482                 0, 0);
00483   return;
00484 }
00485 void
00486 gimlet_quick_access_menu_hide (GimletWindow *gimlet)
00487 {
00488   quick_access_menu_destroy (gimlet);
00489 
00490   if (gimlet->quick_access_menu)
00491     g_free (gimlet->quick_access_menu);
00492   gimlet->quick_access_menu = NULL;
00493 }