summaryrefslogtreecommitdiff
path: root/mate-dictionary/src/gdict-applet.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-dictionary/src/gdict-applet.c')
-rw-r--r--mate-dictionary/src/gdict-applet.c1333
1 files changed, 1333 insertions, 0 deletions
diff --git a/mate-dictionary/src/gdict-applet.c b/mate-dictionary/src/gdict-applet.c
new file mode 100644
index 00000000..442381a6
--- /dev/null
+++ b/mate-dictionary/src/gdict-applet.c
@@ -0,0 +1,1333 @@
+/* gdict-applet.c - MATE Dictionary Applet
+ *
+ * Copyright (c) 2005 Emmanuele Bassi <[email protected]>
+ *
+ * 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 of the
+ * License, 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "gdict-applet.h"
+#include "gdict-about.h"
+#include "gdict-pref-dialog.h"
+#include "gdict-print.h"
+#include "gdict-common.h"
+#include "gdict-aligned-window.h"
+
+#define GDICT_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDICT_TYPE_APPLET, GdictAppletClass))
+#define GDICT_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDICT_TYPE_APPLET, GdictAppletClass))
+
+struct _GdictAppletClass
+{
+ MatePanelAppletClass parent_class;
+};
+
+#define GDICT_APPLET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDICT_TYPE_APPLET, GdictAppletPrivate))
+
+struct _GdictAppletPrivate
+{
+ guint size;
+ GtkOrientation orient;
+
+ MateConfClient *mateconf_client;
+ guint notify_id;
+ guint font_notify_id;
+
+ gchar *database;
+ gchar *strategy;
+ gchar *source_name;
+ gchar *print_font;
+ gchar *defbox_font;
+
+ gchar *word;
+ GdictContext *context;
+ guint lookup_start_id;
+ guint lookup_end_id;
+ guint error_id;
+
+ GdictSourceLoader *loader;
+
+ GtkWidget *box;
+ GtkWidget *toggle;
+ GtkWidget *image;
+ GtkWidget *entry;
+ GtkWidget *window;
+ GtkWidget *frame;
+ GtkWidget *defbox;
+
+ guint idle_draw_id;
+
+ GdkPixbuf *icon;
+
+ gint window_width;
+ gint window_height;
+
+ guint is_window_showing : 1;
+};
+
+#define WINDOW_MIN_WIDTH 300
+#define WINDOW_MIN_HEIGHT 200
+#define WINDOW_NUM_COLUMNS 47
+#define WINDOW_NUM_ROWS 20
+
+G_DEFINE_TYPE (GdictApplet, gdict_applet, PANEL_TYPE_APPLET);
+
+
+static const GtkTargetEntry drop_types[] =
+{
+ { "text/plain", 0, 0 },
+ { "TEXT", 0, 0 },
+ { "STRING", 0, 0 },
+ { "UTF8_STRING", 0, 0 },
+};
+static const guint n_drop_types = G_N_ELEMENTS (drop_types);
+
+
+static void
+set_atk_name_description (GtkWidget *widget,
+ const char *name,
+ const char *description)
+{
+ AtkObject *aobj;
+
+ aobj = gtk_widget_get_accessible (widget);
+ if (!GTK_IS_ACCESSIBLE (aobj))
+ return;
+
+ atk_object_set_name (aobj, name);
+ atk_object_set_description (aobj, description);
+}
+
+static void
+set_window_default_size (GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GtkWidget *widget, *defbox;
+ gint width, height;
+ gint font_size;
+ GdkScreen *screen;
+ gint monitor_num;
+ GtkRequisition req;
+ GdkRectangle monitor;
+
+ if (!priv->window)
+ return;
+
+ widget = priv->window;
+ defbox = priv->defbox;
+
+ /* Size based on the font size */
+ font_size = pango_font_description_get_size (gtk_widget_get_style (defbox)->font_desc);
+ font_size = PANGO_PIXELS (font_size);
+
+ width = font_size * WINDOW_NUM_COLUMNS;
+ height = font_size * WINDOW_NUM_ROWS;
+
+ /* Use at least the requisition size of the window... */
+ gtk_widget_size_request (widget, &req);
+ width = MAX (width, req.width);
+ height = MAX (height, req.height);
+
+ /* ... but make it no larger than half the monitor size */
+ screen = gtk_widget_get_screen (widget);
+ monitor_num = gdk_screen_get_monitor_at_window (screen,
+ gtk_widget_get_window (widget));
+
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+ width = MIN (width, monitor.width / 2);
+ height = MIN (height, monitor.height / 2);
+
+ /* Set size */
+ gtk_widget_set_size_request (priv->frame, width, height);
+}
+
+static void
+clear_cb (GtkWidget *widget,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
+
+ if (!priv->defbox)
+ return;
+
+ gdict_defbox_clear (GDICT_DEFBOX (priv->defbox));
+}
+
+static void
+print_cb (GtkWidget *widget,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ if (!priv->defbox)
+ return;
+
+ gdict_show_print_dialog (GTK_WINDOW (priv->window),
+ GDICT_DEFBOX (priv->defbox));
+}
+
+static void
+save_cb (GtkWidget *widget,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GtkWidget *dialog;
+
+ if (!priv->defbox)
+ return;
+
+ dialog = gtk_file_chooser_dialog_new (_("Save a Copy"),
+ GTK_WINDOW (priv->window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ /* default to user's $HOME */
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), _("Untitled document"));
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ gchar *filename;
+ gchar *text;
+ gsize len;
+ GError *write_error = NULL;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ text = gdict_defbox_get_text (GDICT_DEFBOX (priv->defbox), &len);
+
+ g_file_set_contents (filename,
+ text,
+ len,
+ &write_error);
+ if (write_error)
+ {
+ gchar *message;
+
+ message = g_strdup_printf (_("Error while writing to '%s'"), filename);
+
+ gdict_show_error_dialog (GTK_WINDOW (priv->window),
+ message,
+ write_error->message);
+
+ g_error_free (write_error);
+ g_free (message);
+ }
+
+ g_free (text);
+ g_free (filename);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+gdict_applet_set_menu_items_sensitive (GdictApplet *applet,
+ gboolean is_sensitive)
+{
+ MateComponentUIComponent *popup_component;
+
+ popup_component = mate_panel_applet_get_popup_component (MATE_PANEL_APPLET (applet));
+ if (!MATECOMPONENT_IS_UI_COMPONENT (popup_component))
+ return;
+
+ matecomponent_ui_component_set_prop (popup_component,
+ "/commands/Clear",
+ "sensitive", (is_sensitive ? "1" : "0"),
+ NULL);
+ matecomponent_ui_component_set_prop (popup_component,
+ "/commands/Print",
+ "sensitive", (is_sensitive ? "1" : "0"),
+ NULL);
+ matecomponent_ui_component_set_prop (popup_component,
+ "/commands/Save",
+ "sensitive", (is_sensitive ? "1" : "0"),
+ NULL);
+}
+
+static gboolean
+window_key_press_event_cb (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ GdictApplet *applet = GDICT_APPLET (user_data);
+
+ if (event->keyval == GDK_Escape)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (applet->priv->toggle), FALSE);
+ gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (applet->priv->toggle));
+
+ return TRUE;
+ }
+ else if ((event->keyval == GDK_l) &&
+ (event->state & GDK_CONTROL_MASK))
+ {
+ gtk_widget_grab_focus (applet->priv->entry);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+window_show_cb (GtkWidget *window,
+ GdictApplet *applet)
+{
+ set_window_default_size (applet);
+}
+
+static void
+gdict_applet_build_window (GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GtkWidget *window;
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *bbox;
+ GtkWidget *button;
+
+ if (!priv->entry)
+ {
+ g_warning ("No entry widget defined");
+
+ return;
+ }
+
+ window = gdict_aligned_window_new (priv->toggle);
+ g_signal_connect (window, "key-press-event",
+ G_CALLBACK (window_key_press_event_cb),
+ applet);
+ g_signal_connect (window, "show",
+ G_CALLBACK (window_show_cb),
+ applet);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (window), frame);
+ gtk_widget_show (frame);
+ priv->frame = frame;
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_widget_show (vbox);
+
+ priv->defbox = gdict_defbox_new ();
+ if (priv->context)
+ gdict_defbox_set_context (GDICT_DEFBOX (priv->defbox), priv->context);
+
+ gtk_box_pack_start (GTK_BOX (vbox), priv->defbox, TRUE, TRUE, 0);
+ gtk_widget_show (priv->defbox);
+ gtk_widget_set_can_focus (priv->defbox, TRUE);
+ gtk_widget_set_can_default (priv->defbox, TRUE);
+
+ bbox = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing (GTK_BOX (bbox), 6);
+ gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
+ gtk_widget_show (bbox);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
+ gtk_widget_set_tooltip_text (button, _("Clear the definitions found"));
+ set_atk_name_description (button,
+ _("Clear definition"),
+ _("Clear the text of the definition"));
+
+ g_signal_connect (button, "clicked", G_CALLBACK (clear_cb), applet);
+ gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_PRINT);
+ gtk_widget_set_tooltip_text (button, _("Print the definitions found"));
+ set_atk_name_description (button,
+ _("Print definition"),
+ _("Print the text of the definition"));
+
+ g_signal_connect (button, "clicked", G_CALLBACK (print_cb), applet);
+ gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
+ gtk_widget_set_tooltip_text (button, _("Save the definitions found"));
+ set_atk_name_description (button,
+ _("Save definition"),
+ _("Save the text of the definition to a file"));
+
+ g_signal_connect (button, "clicked", G_CALLBACK (save_cb), applet);
+ gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ gtk_window_set_default (GTK_WINDOW (window), priv->defbox);
+
+ priv->window = window;
+ priv->is_window_showing = FALSE;
+}
+
+static gboolean
+gdict_applet_icon_toggled_cb (GtkWidget *widget,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ if (!priv->window)
+ gdict_applet_build_window (applet);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ {
+ gtk_window_set_screen (GTK_WINDOW (priv->window),
+ gtk_widget_get_screen (GTK_WIDGET (applet)));
+ gtk_window_present (GTK_WINDOW (priv->window));
+ gtk_widget_grab_focus (priv->defbox);
+
+ priv->is_window_showing = TRUE;
+ }
+ else
+ {
+ /* force hiding the find pane */
+ gdict_defbox_set_show_find (GDICT_DEFBOX (priv->defbox), FALSE);
+
+ gtk_widget_grab_focus (priv->entry);
+ gtk_widget_hide (priv->window);
+
+ priv->is_window_showing = FALSE;
+ }
+
+ return FALSE;
+}
+
+static void
+gdict_applet_entry_activate_cb (GtkWidget *widget,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ gchar *text;
+
+ text = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
+ if (!text)
+ return;
+
+ g_free (priv->word);
+ priv->word = text;
+
+ if (!priv->window)
+ gdict_applet_build_window (applet);
+
+ gdict_defbox_lookup (GDICT_DEFBOX (priv->defbox), priv->word);
+}
+
+static gboolean
+gdict_applet_entry_key_press_cb (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ GdictAppletPrivate *priv = GDICT_APPLET (user_data)->priv;
+
+ if (event->keyval == GDK_Escape)
+ {
+ if (priv->is_window_showing)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->toggle), FALSE);
+ gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (priv->toggle));
+
+ return TRUE;
+ }
+ }
+ else if (event->keyval == GDK_Tab)
+ {
+ if (priv->is_window_showing)
+ gtk_widget_grab_focus (priv->defbox);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gdict_applet_icon_button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ /* we don't want to block the applet's popup menu unless the
+ * user is toggling the button
+ */
+ if (event->button != 1)
+ g_signal_stop_emission_by_name (priv->toggle, "button-press-event");
+
+ return FALSE;
+}
+
+static gboolean
+gdict_applet_entry_button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ GdictApplet *applet)
+{
+ mate_panel_applet_request_focus (MATE_PANEL_APPLET (applet), event->time);
+
+ return FALSE;
+}
+
+static gboolean
+gdict_applet_draw (GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GtkWidget *box;
+ GtkWidget *hbox;
+ gchar *text = NULL;
+
+ if (priv->entry)
+ text = gtk_editable_get_chars (GTK_EDITABLE (priv->entry), 0, -1);
+
+ if (priv->box)
+ gtk_widget_destroy (priv->box);
+
+ switch (priv->orient)
+ {
+ case GTK_ORIENTATION_VERTICAL:
+ box = gtk_vbox_new (FALSE, 0);
+ break;
+ case GTK_ORIENTATION_HORIZONTAL:
+ box = gtk_hbox_new (FALSE, 0);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_container_add (GTK_CONTAINER (applet), box);
+ gtk_widget_show (box);
+
+ /* toggle button */
+ priv->toggle = gtk_toggle_button_new ();
+ gtk_widget_set_tooltip_text (priv->toggle, _("Click to view the dictionary window"));
+ set_atk_name_description (priv->toggle,
+ _("Toggle dictionary window"),
+ _("Show or hide the definition window"));
+
+ gtk_button_set_relief (GTK_BUTTON (priv->toggle),
+ GTK_RELIEF_NONE);
+ g_signal_connect (priv->toggle, "toggled",
+ G_CALLBACK (gdict_applet_icon_toggled_cb),
+ applet);
+ g_signal_connect (priv->toggle, "button-press-event",
+ G_CALLBACK (gdict_applet_icon_button_press_event_cb),
+ applet);
+ gtk_box_pack_start (GTK_BOX (box), priv->toggle, FALSE, FALSE, 0);
+ gtk_widget_show (priv->toggle);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
+ gtk_container_add (GTK_CONTAINER (priv->toggle), hbox);
+ gtk_widget_show (hbox);
+
+ if (priv->icon)
+ {
+ GdkPixbuf *scaled;
+
+ priv->image = gtk_image_new ();
+ gtk_image_set_pixel_size (GTK_IMAGE (priv->image), priv->size - 10);
+
+ scaled = gdk_pixbuf_scale_simple (priv->icon,
+ priv->size - 5,
+ priv->size - 5,
+ GDK_INTERP_BILINEAR);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
+ g_object_unref (scaled);
+
+ gtk_box_pack_start (GTK_BOX (hbox), priv->image, FALSE, FALSE, 0);
+
+ gtk_widget_show (priv->image);
+ }
+ else
+ {
+ priv->image = gtk_image_new ();
+
+ gtk_image_set_pixel_size (GTK_IMAGE (priv->image), priv->size - 10);
+ gtk_image_set_from_stock (GTK_IMAGE (priv->image),
+ GTK_STOCK_MISSING_IMAGE,
+ -1);
+
+ gtk_box_pack_start (GTK_BOX (hbox), priv->image, FALSE, FALSE, 0);
+ gtk_widget_show (priv->image);
+ }
+
+ /* entry */
+ priv->entry = gtk_entry_new ();
+ gtk_widget_set_tooltip_text (priv->entry, _("Type the word you want to look up"));
+ set_atk_name_description (priv->entry,
+ _("Dictionary entry"),
+ _("Look up words in dictionaries"));
+
+ gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE);
+ gtk_entry_set_width_chars (GTK_ENTRY (priv->entry), 12);
+ g_signal_connect (priv->entry, "activate",
+ G_CALLBACK (gdict_applet_entry_activate_cb),
+ applet);
+ g_signal_connect (priv->entry, "button-press-event",
+ G_CALLBACK (gdict_applet_entry_button_press_event_cb),
+ applet);
+ g_signal_connect (priv->entry, "key-press-event",
+ G_CALLBACK (gdict_applet_entry_key_press_cb),
+ applet);
+ gtk_box_pack_end (GTK_BOX (box), priv->entry, FALSE, FALSE, 0);
+ gtk_widget_show (priv->entry);
+
+ if (text)
+ {
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
+
+ g_free (text);
+ }
+
+ priv->box = box;
+
+#if 0
+ gtk_widget_grab_focus (priv->entry);
+#endif
+
+ gtk_widget_show_all (GTK_WIDGET (applet));
+
+ return FALSE;
+}
+
+static void
+gdict_applet_queue_draw (GdictApplet *applet)
+{
+ if (!applet->priv->idle_draw_id)
+ applet->priv->idle_draw_id = g_idle_add ((GSourceFunc) gdict_applet_draw,
+ applet);
+}
+
+static void
+gdict_applet_lookup_start_cb (GdictContext *context,
+ GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ if (!priv->window)
+ gdict_applet_build_window (applet);
+
+ if (!priv->is_window_showing)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->toggle), TRUE);
+
+ gtk_window_present (GTK_WINDOW (priv->window));
+ gtk_widget_grab_focus (priv->defbox);
+
+ priv->is_window_showing = TRUE;
+ }
+
+ gdict_applet_set_menu_items_sensitive (applet, FALSE);
+}
+
+static void
+gdict_applet_lookup_end_cb (GdictContext *context,
+ GdictApplet *applet)
+{
+ gdict_applet_set_menu_items_sensitive (applet, TRUE);
+
+ gtk_window_present (GTK_WINDOW (applet->priv->window));
+}
+
+static void
+gdict_applet_error_cb (GdictContext *context,
+ const GError *error,
+ GdictApplet *applet)
+{
+ /* disable menu items */
+ gdict_applet_set_menu_items_sensitive (applet, FALSE);
+}
+
+static void
+gdict_applet_cmd_lookup (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ gchar *text = NULL;;
+
+ text = gtk_editable_get_chars (GTK_EDITABLE (priv->entry), 0, -1);
+ if (!text)
+ return;
+
+ g_free (priv->word);
+ priv->word = text;
+
+ if (!priv->window)
+ gdict_applet_build_window (applet);
+
+ gdict_defbox_lookup (GDICT_DEFBOX (priv->defbox), priv->word);
+}
+
+static void
+gdict_applet_cmd_clear (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ clear_cb (NULL, applet);
+}
+
+static void
+gdict_applet_cmd_print (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ print_cb (NULL, applet);
+}
+
+static void
+gdict_applet_cmd_preferences (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ gdict_show_pref_dialog (GTK_WIDGET (applet),
+ _("Dictionary Preferences"),
+ applet->priv->loader);
+}
+
+static void
+gdict_applet_cmd_about (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ gdict_show_about_dialog (GTK_WIDGET (applet));
+}
+
+static void
+gdict_applet_cmd_help (MateComponentUIComponent *component,
+ GdictApplet *applet,
+ const gchar *cname)
+{
+ GError *err = NULL;
+
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (applet)),
+ "ghelp:mate-dictionary#mate-dictionary-applet",
+ gtk_get_current_event_time (), &err);
+
+ if (err)
+ {
+ gdict_show_error_dialog (NULL,
+ _("There was an error while displaying help"),
+ err->message);
+ g_error_free (err);
+ }
+}
+
+static void
+gdict_applet_change_background (MatePanelApplet *applet,
+ MatePanelAppletBackgroundType type,
+ GdkColor *color,
+ GdkPixmap *pixmap)
+{
+ if (MATE_PANEL_APPLET_CLASS (gdict_applet_parent_class)->change_background)
+ MATE_PANEL_APPLET_CLASS (gdict_applet_parent_class)->change_background (applet,
+ type,
+ color,
+ pixmap);
+}
+
+static void
+gdict_applet_change_orient (MatePanelApplet *applet,
+ MatePanelAppletOrient orient)
+{
+ GdictAppletPrivate *priv = GDICT_APPLET (applet)->priv;
+ guint new_size;
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (applet), &allocation);
+ switch (orient)
+ {
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ priv->orient = GTK_ORIENTATION_VERTICAL;
+ new_size = allocation.width;
+ break;
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ priv->orient = GTK_ORIENTATION_HORIZONTAL;
+ new_size = allocation.height;
+ break;
+ }
+
+ if (new_size != priv->size)
+ priv->size = new_size;
+
+ gdict_applet_queue_draw (GDICT_APPLET (applet));
+
+ if (MATE_PANEL_APPLET_CLASS (gdict_applet_parent_class)->change_orient)
+ MATE_PANEL_APPLET_CLASS (gdict_applet_parent_class)->change_orient (applet,
+ orient);
+}
+
+static void
+gdict_applet_size_allocate (GtkWidget *widget,
+ GdkRectangle *allocation)
+{
+ GdictApplet *applet = GDICT_APPLET (widget);
+ GdictAppletPrivate *priv = applet->priv;
+ guint new_size;
+
+ if (priv->orient == GTK_ORIENTATION_HORIZONTAL)
+ new_size = allocation->height;
+ else
+ new_size = allocation->width;
+
+ if (priv->size != new_size)
+ {
+ priv->size = new_size;
+
+ gtk_image_set_pixel_size (GTK_IMAGE (priv->image), priv->size - 10);
+
+ /* re-scale the icon, if it was found */
+ if (priv->icon)
+ {
+ GdkPixbuf *scaled;
+
+ scaled = gdk_pixbuf_scale_simple (priv->icon,
+ priv->size - 5,
+ priv->size - 5,
+ GDK_INTERP_BILINEAR);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
+ g_object_unref (scaled);
+ }
+ }
+
+ if (GTK_WIDGET_CLASS (gdict_applet_parent_class)->size_allocate)
+ GTK_WIDGET_CLASS (gdict_applet_parent_class)->size_allocate (widget,
+ allocation);
+}
+
+static void
+gdict_applet_style_set (GtkWidget *widget,
+ GtkStyle *old_style)
+{
+ if (GTK_WIDGET_CLASS (gdict_applet_parent_class)->style_set)
+ GTK_WIDGET_CLASS (gdict_applet_parent_class)->style_set (widget,
+ old_style);
+#if 0
+ set_window_default_size (GDICT_APPLET (widget));
+#endif
+}
+
+static void
+gdict_applet_set_database (GdictApplet *applet,
+ const gchar *database)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ g_free (priv->database);
+
+ if (database)
+ priv->database = g_strdup (database);
+ else
+ priv->database = gdict_mateconf_get_string_with_default (priv->mateconf_client,
+ GDICT_MATECONF_DATABASE_KEY,
+ GDICT_DEFAULT_DATABASE);
+ if (priv->defbox)
+ gdict_defbox_set_database (GDICT_DEFBOX (priv->defbox),
+ priv->database);
+}
+
+static void
+gdict_applet_set_strategy (GdictApplet *applet,
+ const gchar *strategy)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ g_free (priv->strategy);
+
+ if (strategy)
+ priv->strategy = g_strdup (strategy);
+ else
+ priv->strategy = gdict_mateconf_get_string_with_default (priv->mateconf_client,
+ GDICT_MATECONF_STRATEGY_KEY,
+ GDICT_DEFAULT_STRATEGY);
+}
+
+static GdictContext *
+get_context_from_loader (GdictApplet *applet)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GdictSource *source;
+ GdictContext *retval;
+
+ if (!priv->source_name)
+ priv->source_name = g_strdup (GDICT_DEFAULT_SOURCE_NAME);
+
+ source = gdict_source_loader_get_source (priv->loader,
+ priv->source_name);
+ if (!source)
+ {
+ gchar *detail;
+
+ detail = g_strdup_printf (_("No dictionary source available with name '%s'"),
+ priv->source_name);
+
+ gdict_show_error_dialog (NULL,
+ _("Unable to find dictionary source"),
+ NULL);
+
+ g_free (detail);
+
+ return NULL;
+ }
+
+ gdict_applet_set_database (applet, gdict_source_get_database (source));
+ gdict_applet_set_strategy (applet, gdict_source_get_strategy (source));
+
+ retval = gdict_source_get_context (source);
+ if (!retval)
+ {
+ gchar *detail;
+
+ detail = g_strdup_printf (_("No context available for source '%s'"),
+ gdict_source_get_description (source));
+
+ gdict_show_error_dialog (NULL,
+ _("Unable to create a context"),
+ detail);
+
+ g_free (detail);
+ g_object_unref (source);
+
+ return NULL;
+ }
+
+ g_object_unref (source);
+
+ return retval;
+}
+
+static void
+gdict_applet_set_print_font (GdictApplet *applet,
+ const gchar *print_font)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ g_free (priv->print_font);
+
+ if (print_font)
+ priv->print_font = g_strdup (print_font);
+ else
+ priv->print_font = gdict_mateconf_get_string_with_default (priv->mateconf_client,
+ GDICT_MATECONF_PRINT_FONT_KEY,
+ GDICT_DEFAULT_PRINT_FONT);
+}
+
+static void
+gdict_applet_set_defbox_font (GdictApplet *applet,
+ const gchar *defbox_font)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ g_free (priv->defbox_font);
+
+ if (defbox_font)
+ priv->defbox_font = g_strdup (defbox_font);
+ else
+ priv->defbox_font = gdict_mateconf_get_string_with_default (priv->mateconf_client,
+ DOCUMENT_FONT_KEY,
+ GDICT_DEFAULT_DEFBOX_FONT);
+
+ if (priv->defbox)
+ gdict_defbox_set_font_name (GDICT_DEFBOX (priv->defbox),
+ priv->defbox_font);
+}
+
+static void
+gdict_applet_set_context (GdictApplet *applet,
+ GdictContext *context)
+{
+ GdictAppletPrivate *priv = applet->priv;
+
+ if (priv->context)
+ {
+ g_signal_handler_disconnect (priv->context, priv->lookup_start_id);
+ g_signal_handler_disconnect (priv->context, priv->lookup_end_id);
+ g_signal_handler_disconnect (priv->context, priv->error_id);
+
+ priv->lookup_start_id = 0;
+ priv->lookup_end_id = 0;
+ priv->error_id = 0;
+
+ g_object_unref (priv->context);
+ priv->context = NULL;
+ }
+
+ if (priv->defbox)
+ gdict_defbox_set_context (GDICT_DEFBOX (priv->defbox), context);
+
+ if (!context)
+ return;
+
+ /* attach our callbacks */
+ priv->lookup_start_id = g_signal_connect (context, "lookup-start",
+ G_CALLBACK (gdict_applet_lookup_start_cb),
+ applet);
+ priv->lookup_end_id = g_signal_connect (context, "lookup-end",
+ G_CALLBACK (gdict_applet_lookup_end_cb),
+ applet);
+ priv->error_id = g_signal_connect (context, "error",
+ G_CALLBACK (gdict_applet_error_cb),
+ applet);
+
+ priv->context = context;
+}
+
+static void
+gdict_applet_set_source_name (GdictApplet *applet,
+ const gchar *source_name)
+{
+ GdictAppletPrivate *priv = applet->priv;
+ GdictContext *context;
+
+ g_free (priv->source_name);
+
+ if (source_name)
+ priv->source_name = g_strdup (source_name);
+ else
+ priv->source_name = gdict_mateconf_get_string_with_default (priv->mateconf_client,
+ GDICT_MATECONF_SOURCE_KEY,
+ GDICT_DEFAULT_SOURCE_NAME);
+
+ context = get_context_from_loader (applet);
+ gdict_applet_set_context (applet, context);
+}
+
+static void
+gdict_applet_mateconf_notify_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ GdictApplet *applet = GDICT_APPLET (user_data);
+
+ if (strcmp (entry->key, GDICT_MATECONF_PRINT_FONT_KEY) == 0)
+ {
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING))
+ gdict_applet_set_print_font (applet, mateconf_value_get_string (entry->value));
+ else
+ gdict_applet_set_print_font (applet, GDICT_DEFAULT_PRINT_FONT);
+ }
+ else if (strcmp (entry->key, GDICT_MATECONF_SOURCE_KEY) == 0)
+ {
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING))
+ gdict_applet_set_source_name (applet, mateconf_value_get_string (entry->value));
+ else
+ gdict_applet_set_source_name (applet, GDICT_DEFAULT_SOURCE_NAME);
+ }
+ else if (strcmp (entry->key, GDICT_MATECONF_DATABASE_KEY) == 0)
+ {
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING))
+ gdict_applet_set_database (applet, mateconf_value_get_string (entry->value));
+ else
+ gdict_applet_set_database (applet, GDICT_DEFAULT_DATABASE);
+ }
+ else if (strcmp (entry->key, GDICT_MATECONF_STRATEGY_KEY) == 0)
+ {
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING))
+ gdict_applet_set_strategy (applet, mateconf_value_get_string (entry->value));
+ else
+ gdict_applet_set_strategy (applet, GDICT_DEFAULT_STRATEGY);
+ }
+ else if (strcmp (entry->key, DOCUMENT_FONT_KEY) == 0)
+ {
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING))
+ gdict_applet_set_defbox_font (applet, mateconf_value_get_string (entry->value));
+ else
+ gdict_applet_set_defbox_font (applet, GDICT_DEFAULT_DEFBOX_FONT);
+ }
+}
+
+static void
+gdict_applet_finalize (GObject *object)
+{
+ GdictApplet *applet = GDICT_APPLET (object);
+ GdictAppletPrivate *priv = applet->priv;
+
+ if (priv->idle_draw_id)
+ g_source_remove (priv->idle_draw_id);
+
+ if (priv->notify_id)
+ mateconf_client_notify_remove (priv->mateconf_client, priv->notify_id);
+
+ if (priv->font_notify_id)
+ mateconf_client_notify_remove (priv->mateconf_client, priv->font_notify_id);
+
+ if (priv->mateconf_client)
+ g_object_unref (priv->mateconf_client);
+
+ if (priv->context)
+ {
+ if (priv->lookup_start_id)
+ {
+ g_signal_handler_disconnect (priv->context, priv->lookup_start_id);
+ g_signal_handler_disconnect (priv->context, priv->lookup_end_id);
+ g_signal_handler_disconnect (priv->context, priv->error_id);
+ }
+
+ g_object_unref (priv->context);
+ }
+
+ if (priv->loader)
+ g_object_unref (priv->loader);
+
+ if (priv->icon)
+ g_object_unref (priv->icon);
+
+ g_free (priv->source_name);
+ g_free (priv->print_font);
+ g_free (priv->defbox_font);
+ g_free (priv->word);
+
+ G_OBJECT_CLASS (gdict_applet_parent_class)->finalize (object);
+}
+
+static void
+gdict_applet_class_init (GdictAppletClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ MatePanelAppletClass *applet_class = MATE_PANEL_APPLET_CLASS (klass);
+
+ gobject_class->finalize = gdict_applet_finalize;
+
+ widget_class->size_allocate = gdict_applet_size_allocate;
+ widget_class->style_set = gdict_applet_style_set;
+
+ applet_class->change_background = gdict_applet_change_background;
+ applet_class->change_orient = gdict_applet_change_orient;
+
+ g_type_class_add_private (gobject_class, sizeof (GdictAppletPrivate));
+}
+
+static void
+gdict_applet_init (GdictApplet *applet)
+{
+ GdictAppletPrivate *priv;
+ gchar *data_dir;
+ GError *mateconf_error;
+
+ priv = GDICT_APPLET_GET_PRIVATE (applet);
+ applet->priv = priv;
+
+ if (!priv->loader)
+ priv->loader = gdict_source_loader_new ();
+
+ /* add our data dir inside $HOME to the loader's search paths */
+ data_dir = gdict_get_data_dir ();
+ gdict_source_loader_add_search_path (priv->loader, data_dir);
+ g_free (data_dir);
+
+ gtk_window_set_default_icon_name ("accessories-dictionary");
+
+ mate_panel_applet_set_flags (MATE_PANEL_APPLET (applet),
+ MATE_PANEL_APPLET_EXPAND_MINOR);
+
+ /* get the default mateconf client */
+ if (!priv->mateconf_client)
+ priv->mateconf_client = mateconf_client_get_default ();
+
+ mateconf_error = NULL;
+ mateconf_client_add_dir (priv->mateconf_client,
+ GDICT_MATECONF_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ &mateconf_error);
+ if (mateconf_error)
+ {
+ gdict_show_gerror_dialog (NULL,
+ _("Unable to connect to MateConf"),
+ mateconf_error);
+ mateconf_error = NULL;
+ }
+
+ priv->notify_id = mateconf_client_notify_add (priv->mateconf_client,
+ GDICT_MATECONF_DIR,
+ gdict_applet_mateconf_notify_cb,
+ applet, NULL,
+ &mateconf_error);
+ if (mateconf_error)
+ {
+ gdict_show_gerror_dialog (NULL,
+ _("Unable to get notification for preferences"),
+ mateconf_error);
+
+ mateconf_error = NULL;
+ }
+
+ priv->font_notify_id = mateconf_client_notify_add (priv->mateconf_client,
+ DOCUMENT_FONT_KEY,
+ gdict_applet_mateconf_notify_cb,
+ applet, NULL,
+ &mateconf_error);
+ if (mateconf_error)
+ {
+ gdict_show_gerror_dialog (NULL,
+ _("Unable to get notification for the document font"),
+ mateconf_error);
+
+ mateconf_error = NULL;
+ }
+
+#ifndef GDICT_APPLET_STAND_ALONE
+ mate_panel_applet_set_background_widget (MATE_PANEL_APPLET (applet),
+ GTK_WIDGET (applet));
+
+ priv->size = mate_panel_applet_get_size (MATE_PANEL_APPLET (applet));
+
+ switch (mate_panel_applet_get_orient (MATE_PANEL_APPLET (applet)))
+ {
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ priv->orient = GTK_ORIENTATION_VERTICAL;
+ break;
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ priv->orient = GTK_ORIENTATION_HORIZONTAL;
+ break;
+ }
+#else
+ priv->size = 24;
+ priv->orient = GTK_ORIENTATION_HORIZONTAL;
+ g_message ("(in %s) applet { size = %d, orient = %s }",
+ G_STRFUNC,
+ priv->size,
+ (priv->orient == GTK_ORIENTATION_HORIZONTAL ? "H" : "V"));
+#endif /* !GDICT_APPLET_STAND_ALONE */
+
+ priv->icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ "accessories-dictionary",
+ 48,
+ 0,
+ NULL);
+
+ /* force first draw */
+ gdict_applet_draw (applet);
+
+ /* force retrieval of the configuration from MateConf */
+ gdict_applet_set_source_name (applet, NULL);
+ gdict_applet_set_defbox_font (applet, NULL);
+ gdict_applet_set_print_font (applet, NULL);
+}
+
+#ifndef GDICT_APPLET_STAND_ALONE
+static const MateComponentUIVerb gdict_applet_menu_verbs[] =
+{
+ MATECOMPONENT_UI_UNSAFE_VERB ("LookUp", gdict_applet_cmd_lookup),
+
+ MATECOMPONENT_UI_UNSAFE_VERB ("Clear", gdict_applet_cmd_clear),
+ MATECOMPONENT_UI_UNSAFE_VERB ("Print", gdict_applet_cmd_print),
+
+ MATECOMPONENT_UI_UNSAFE_VERB ("Preferences", gdict_applet_cmd_preferences),
+ MATECOMPONENT_UI_UNSAFE_VERB ("Help", gdict_applet_cmd_help),
+ MATECOMPONENT_UI_UNSAFE_VERB ("About", gdict_applet_cmd_about),
+
+ MATECOMPONENT_UI_VERB_END
+};
+
+static gboolean
+gdict_applet_factory (MatePanelApplet *applet,
+ const gchar *iid,
+ gpointer data)
+{
+ gboolean retval = FALSE;
+
+ if (((!strcmp (iid, "OAFIID:MATE_DictionaryApplet")) ||
+ (!strcmp (iid, "OAFIID:MATE_GDictApplet"))) &&
+ gdict_create_data_dir ())
+ {
+ /* Set up the menu */
+ mate_panel_applet_setup_menu_from_file (applet, UIDATADIR,
+ "MATE_DictionaryApplet.xml",
+ NULL,
+ gdict_applet_menu_verbs,
+ applet);
+
+ gtk_widget_show (GTK_WIDGET (applet));
+
+ /* set the menu items insensitive */
+ gdict_applet_set_menu_items_sensitive (GDICT_APPLET (applet), FALSE);
+
+ retval = TRUE;
+ }
+
+ return retval;
+}
+
+/* this defines the main () for the applet */
+MATE_PANEL_APPLET_MATECOMPONENT_FACTORY ("OAFIID:MATE_DictionaryApplet_Factory",
+ GDICT_TYPE_APPLET,
+ "mate-dictionary-applet",
+ VERSION,
+ gdict_applet_factory,
+ NULL);
+
+#else /* GDICT_APPLET_STAND_ALONE */
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *applet;
+
+ /* gettext stuff */
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ applet = GTK_WIDGET (g_object_new (GDICT_TYPE_APPLET, NULL));
+ g_message ("(in %s) typeof(applet) = '%s'",
+ G_STRFUNC,
+ g_type_name (G_OBJECT_TYPE (applet)));
+
+ gdict_applet_queue_draw (GDICT_APPLET (applet));
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+ gtk_container_add (GTK_CONTAINER (window), applet);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
+#endif /* !GDICT_APPLET_STAND_ALONE */