Back to index

im-sdk  12.3.91
widgets.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/gtkdrawingarea.h>
00025 #include <gtk/gtkbutton.h>
00026 #include <gtk/gtksignal.h>
00027 #include <libart_lgpl/libart.h>
00028 #include <panel-applet.h>
00029 #include <gnome.h>
00030 
00031 #include <signal.h>
00032 #include <wait.h>
00033 
00034 #include "gnome-im-switcher.h"
00035 #include "iiim-interface.h"
00036 #include "language.h"
00037 #include "preference.h"
00038 #include "quick-access-menu.h"
00039 #include "utils.h"
00040 #include "widgets.h"
00041 
00042 static void
00043 help_verb_cb (BonoboUIComponent *uic,
00044              GimletWindow *gimlet,
00045              const gchar *verbname)
00046 {
00047        gimlet_util_show_help ("index", GTK_WINDOW (gimlet->applet));
00048 }
00049 
00050 static void
00051 edit_preferences_destroyed_cb (GtkWidget   *new_profile_dialog,
00052                             GimletWindow *gimlet)
00053 {
00054   gimlet->edit_preferences_dialog = NULL;
00055 }
00056 
00057 static void
00058 show_preferences_dialog (BonoboUIComponent *uic,
00059                       GimletWindow *gimlet,
00060                       const gchar       *verbname)
00061 {
00062   GtkWindow *transient_parent;
00063   GtkWindow *old_transient_parent;
00064 
00065   transient_parent = GTK_WINDOW (gimlet->applet);
00066   if (gimlet->edit_preferences_dialog == NULL)
00067     {
00068       old_transient_parent = NULL;
00069       /* passing in transient_parent here purely for the
00070        * glade error dialog
00071        */
00072       gimlet->edit_preferences_dialog =
00073        gimlet_preference_dialog_new (transient_parent, gimlet);
00074       if (gimlet->edit_preferences_dialog == NULL)
00075         return; /* glade file missing */
00076       
00077       g_signal_connect (G_OBJECT (gimlet->edit_preferences_dialog),
00078                         "destroy",
00079                         G_CALLBACK (edit_preferences_destroyed_cb),
00080                         gimlet);
00081     }
00082   else
00083     {
00084       old_transient_parent = gtk_window_get_transient_for (GTK_WINDOW (gimlet->edit_preferences_dialog));
00085     }
00086   if (old_transient_parent != transient_parent)
00087     {
00088       gtk_window_set_transient_for (GTK_WINDOW (gimlet->edit_preferences_dialog),
00089                                     transient_parent);
00090       gtk_widget_hide (gimlet->edit_preferences_dialog); /* re-show the window on its new parent */
00091     }
00092   
00093   gtk_widget_show_all (gimlet->edit_preferences_dialog);
00094   gtk_window_present (GTK_WINDOW (gimlet->edit_preferences_dialog));
00095   return;
00096 }
00097 
00098 static void
00099 about_verb_cb (BonoboUIComponent *uic,
00100               GimletWindow *gimlet,
00101               const gchar *verbname)
00102 {
00103   gchar **authors;
00104   const gchar *documenters[] = {
00105     NULL
00106   };
00107   const char *translator_credits = _("translator_credits");
00108 
00109   authors = g_new (gchar*, 3);
00110   authors[0] = g_strdup(_("Hidetoshi Tajima <hidetoshi.tajima@sun.com>"));
00111   authors[1] = g_strdup("Jens Petersen <petersen@redhat.com>");
00112   authors[2] = NULL;
00113 
00114   if (gimlet->about_dialog != NULL) {
00115     gtk_window_present (GTK_WINDOW (gimlet->about_dialog));
00116     return;
00117   }
00118 
00119   gimlet->about_dialog = gnome_about_new (_("Gnome Input Method Switcher"),
00120                                      VERSION,
00121                                      "Copyright \xc2\xa9 2002-2004 Sun Microsystems, Inc.\nCopyright \xc2\xa9 2002,2004 Red Hat, Inc.",
00122                                      _("Switch Input Languages on the panel."),
00123                                      (const gchar**)authors,
00124                                      documenters,
00125                                      strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
00126                                      NULL);
00127   gtk_signal_connect (GTK_OBJECT(gimlet->about_dialog),
00128                     "destroy",
00129                       GTK_SIGNAL_FUNC(gtk_widget_destroyed),
00130                     &gimlet->about_dialog);
00131 
00132   g_strfreev (authors);
00133   gtk_widget_show (gimlet->about_dialog);
00134 }
00135 
00136 static const BonoboUIVerb menu_verbs [] = {
00137   BONOBO_UI_UNSAFE_VERB ("Props",  show_preferences_dialog),
00138   BONOBO_UI_UNSAFE_VERB ("Help",        help_verb_cb),
00139   BONOBO_UI_UNSAFE_VERB ("About",  about_verb_cb),
00140   BONOBO_UI_VERB_END
00141 };
00142 
00143 static gboolean 
00144 key_press_cb (GtkWidget *widget, GdkEventKey *event,
00145              GimletWindow *gimlet)
00146 {
00147   switch (event->keyval)
00148     {
00149     case GDK_KP_Enter:
00150     case GDK_ISO_Enter:
00151     case GDK_3270_Enter:
00152     case GDK_Return:
00153     case GDK_space:
00154     case GDK_KP_Space:
00155       gimlet_quick_access_menu_show (gimlet);
00156       return TRUE;
00157       break;
00158     default:
00159       break;
00160     }
00161   return FALSE;
00162 }
00163 
00164 static gboolean 
00165 handle_button_release (GimletWindow *gimlet,
00166                      GdkEventButton *event)
00167 {
00168   if (event->button != 1)
00169     return FALSE; 
00170 
00171   gimlet_quick_access_menu_show (gimlet);
00172   return TRUE;
00173 }
00174 
00175 static GdkPixbuf *
00176 init_pixbuf (const gchar *name)
00177 {
00178   GdkPixbuf *pixbuf;
00179   GError    *error = NULL;
00180   char      *path = NULL;
00181 
00182   path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
00183                                 name, FALSE, NULL);
00184   if (!path)
00185     path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
00186                                   name, FALSE, NULL);
00187   if (!path)
00188         return NULL;
00189 
00190   pixbuf = gdk_pixbuf_new_from_file (path, &error);
00191 
00192   if (error)
00193     {
00194       g_warning ("Cannot load '%s': %s", path, error->message);
00195       g_error_free (error);
00196     }
00197   g_free (path);
00198   return pixbuf;
00199  }
00200 
00201 static GdkPixbuf *on_pixbuf;
00202 static GdkPixbuf *off_pixbuf;
00203 static GdkPixbuf *disabled_pixbuf;
00204 
00205 void
00206 icon_set_text (GimletWindow *gimlet)
00207 {
00208   GdkPixbuf *pixbuf;
00209   if (gimlet->im_enabled)
00210     if (gimlet->conversion_mode)
00211       pixbuf = on_pixbuf;
00212     else
00213       pixbuf = off_pixbuf;
00214   else
00215     pixbuf = disabled_pixbuf;
00216 
00217   GtkWidget *drawing = gimlet->drawing_area;
00218   GdkGC *gc = gdk_gc_new(GDK_WINDOW(drawing->window));
00219   gdk_draw_pixbuf(GDK_WINDOW(drawing->window),
00220                 gc,
00221                 pixbuf,
00222                 0,0,0,0,-1,-1,
00223                 GDK_RGB_DITHER_NONE,
00224                 0,0);
00225   if (gimlet->im_enabled)
00226     {
00227       gchar *text = gimlet_language_find_short (gimlet->current_iiim_lang);
00228       PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(drawing), text);
00229 
00230       int height = gdk_pixbuf_get_height(pixbuf);
00231       int width = gdk_pixbuf_get_width(pixbuf);
00232       int pango_width, pango_height, x_pos;
00233       pango_layout_get_pixel_size (layout, &pango_width, &pango_height);
00234       if (width > pango_width)
00235        x_pos = (width-pango_width)/2;
00236       else
00237        x_pos = 0;
00238       gdk_draw_layout (GDK_WINDOW(drawing->window),
00239                      gc,
00240                      x_pos,
00241                      ((height-pango_height)/2),
00242                      layout);
00243       g_free (text);
00244     }
00245 }
00246 
00247 void
00248 set_default_window_icon (void)
00249 {
00250     char *file;
00251 
00252     file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
00253                                   _("gnome-settings-im.png"),
00254                                   TRUE, NULL);
00255     if (file) {
00256        GdkPixbuf *pixbuf = NULL;
00257        GList *list = NULL;
00258 
00259        pixbuf = gdk_pixbuf_new_from_file (file, NULL);
00260        list = g_list_prepend (list, pixbuf);
00261        gtk_window_set_default_icon_list (list);
00262        g_list_free (list);
00263        g_object_unref (pixbuf);
00264        g_free (file);
00265     }
00266 }
00267 
00268 void
00269 update_tooltips (GimletWindow *gimlet)
00270 {
00271   gchar *lang;
00272   gchar *name;
00273   gchar *descr;
00274   gchar *text;
00275 
00276   lang = gimlet->current_iiim_lang;
00277 
00278   if (lang)
00279     {
00280       name = gimlet_language_find_name (lang);
00281       descr = _(gimlet_language_find_description (lang));
00282       if (name && descr && strcmp (name, descr) == 0)
00283        text = g_strdup (name);
00284       else
00285        text = g_strconcat (name, " - ", descr, NULL);
00286       gtk_tooltips_set_tip (gimlet->tooltips, GTK_WIDGET(gimlet->applet), text, NULL);
00287       g_free(text);
00288     }
00289 }
00290 
00291 gboolean
00292 drawing_area_expose_cb (GtkWidget *widget,
00293                      GdkEventExpose *event,
00294                      GimletWindow *gimlet)
00295 {
00296   icon_set_text (gimlet);
00297   update_tooltips (gimlet);
00298   return TRUE;
00299 }
00300 
00301 static void
00302 place_widgets (GimletWindow *gimlet)
00303 {
00304   GtkWidget *box = NULL;
00305   GtkWidget *lang_box = NULL;
00306 
00307   switch (panel_applet_get_orient (PANEL_APPLET (gimlet->applet))) {
00308   case PANEL_APPLET_ORIENT_DOWN:
00309   case PANEL_APPLET_ORIENT_UP:
00310     box = gtk_hbox_new (FALSE, 3);
00311     lang_box = gtk_vbox_new (FALSE, 3);
00312     break;
00313   case PANEL_APPLET_ORIENT_LEFT:
00314   case PANEL_APPLET_ORIENT_RIGHT:
00315     box = gtk_vbox_new (FALSE, 3);
00316     lang_box = gtk_hbox_new (FALSE, 3);
00317     break;
00318   }
00319 
00320   gtk_container_add (GTK_CONTAINER (gimlet->applet), box);
00321   gtk_widget_show (box);
00322   gtk_box_pack_end_defaults (GTK_BOX(box), GTK_WIDGET(lang_box));
00323   gtk_widget_show (GTK_WIDGET (lang_box));
00324 
00325   /* initialize language by guessing from locale */
00326   gchar *locale = getenv ("LC_CTYPE");
00327   if (! locale)
00328     locale = getenv ("LANG");
00329   gchar *lang;
00330 
00331   if (locale)
00332     {
00333       lang = g_strndup (locale, 5);
00334       if (! gimlet_language_find_short (lang))
00335        {
00336          lang = g_strndup (locale, 2);
00337          if (! gimlet_language_find_short (lang))
00338                lang = g_strdup ("en");
00339        }
00340     }
00341   if (! lang)
00342     lang = g_strdup ("en");
00343   
00344   gimlet->current_iiim_lang = lang;
00345 
00346   on_pixbuf = init_pixbuf ("gimlet-on.png");
00347   off_pixbuf = init_pixbuf ("gimlet-off.png");
00348   disabled_pixbuf = init_pixbuf ("gimlet-disable.png");
00349 
00350   gimlet->drawing_area = gtk_drawing_area_new ();
00351   int width = gdk_pixbuf_get_width(off_pixbuf);
00352   int height = gdk_pixbuf_get_height(off_pixbuf);
00353   gtk_widget_set_size_request (GTK_WIDGET(gimlet->drawing_area), width, height);
00354   g_signal_connect (G_OBJECT (gimlet->drawing_area), "expose_event",  
00355                     G_CALLBACK (drawing_area_expose_cb), gimlet);
00356   gtk_widget_show (gimlet->drawing_area);
00357   
00358   gtk_box_pack_start (GTK_BOX(lang_box), GTK_WIDGET(gimlet->drawing_area),
00359                     TRUE, FALSE, 0);
00360 
00361   gimlet->tooltips = gtk_tooltips_new();
00362   gimlet_update_lang (gimlet);
00363 
00364   gimlet->status_label = gtk_label_new (NULL);
00365   gtk_box_pack_start_defaults (GTK_BOX (box),
00366                             GTK_WIDGET(gimlet->status_label));
00367   gimlet_status_set_text (gimlet, "");
00368 
00369   g_signal_connect_swapped (G_OBJECT(gimlet->applet), "button_release_event",
00370                          G_CALLBACK (handle_button_release), gimlet);
00371 
00372   gtk_container_set_border_width (GTK_CONTAINER (gimlet->applet), 0);
00373 
00374   gtk_widget_show (GTK_WIDGET (gimlet->applet));
00375 }
00376 
00377 /* public */
00378 void
00379 gimlet_init (GimletWindow *gimlet)
00380 {
00381   panel_applet_set_flags (gimlet->applet, PANEL_APPLET_EXPAND_MINOR);
00382 
00383   g_signal_connect (G_OBJECT(gimlet->applet), "key_press_event",
00384                   G_CALLBACK(key_press_cb), gimlet);
00385                      
00386   panel_applet_setup_menu_from_file (gimlet->applet,
00387                                  NULL,
00388                                  "GNOME_InputMethodSwitcherApplet.xml",
00389                                  NULL,
00390                                  menu_verbs,
00391                                  gimlet);
00392 #ifdef GNOME_PANEL_APPLET_2_4
00393   if (panel_applet_get_locked_down (gimlet->applet))
00394     {
00395       BonoboUIComponent *popup_component;
00396 
00397       popup_component = panel_applet_get_popup_component (gimlet->applet);
00398 
00399       bonobo_ui_component_set_prop (popup_component,
00400                                 "/commands/Props",
00401                                 "hidden", "1",
00402                                 NULL);
00403     }
00404 #endif
00405 
00406   place_widgets (gimlet);
00407 
00408   gimlet_language_init (gimlet);
00409 
00410   set_default_window_icon ();
00411 
00412   return;
00413 }
00414 
00415 void
00416 gimlet_update_lang (GimletWindow *gimlet)
00417 {
00418   gtk_widget_queue_draw (gimlet->drawing_area);
00419 }
00420 
00421 void
00422 gimlet_status_show_or_hide (GimletWindow *gimlet)
00423 {
00424   if (gimlet->conversion_mode && gimlet->im_enabled &&
00425       gimlet->status_enabled &&
00426       gimlet->status_placement == ON_DESKTOP_PANEL)
00427     gtk_widget_show (GTK_WIDGET (gimlet->status_label));
00428   else
00429     gtk_widget_hide (GTK_WIDGET (gimlet->status_label));
00430 }
00431 
00432 void
00433 gimlet_status_set_text (GimletWindow *gimlet, gchar *text)
00434 {
00435   gtk_label_set_text (GTK_LABEL(gimlet->status_label), text);
00436   gimlet_status_show_or_hide (gimlet);
00437 }