diff options
Diffstat (limited to 'widgets/shortcut-bar/e-shortcut-bar.c')
-rw-r--r-- | widgets/shortcut-bar/e-shortcut-bar.c | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/widgets/shortcut-bar/e-shortcut-bar.c b/widgets/shortcut-bar/e-shortcut-bar.c new file mode 100644 index 0000000000..7ad00feb78 --- /dev/null +++ b/widgets/shortcut-bar/e-shortcut-bar.c @@ -0,0 +1,563 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Author : + * Damon Chaplin <damon@gtk.org> + * + * Copyright 1999, Helix Code, Inc. + * + * 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 + */ + +/* + * ShortcutBar displays a vertical bar with a number of Groups, each of which + * contains any number of icons. It is used on the left of the main application + * window so users can easily access items such as folders and files. + */ + +#include <string.h> +#include <gnome.h> + +#include "e-shortcut-bar.h" +#include "e-clipped-label.h" +#include "e-vscrolled-bar.h" + +/* Drag and Drop stuff. */ +enum { + TARGET_SHORTCUT +}; +static GtkTargetEntry target_table[] = { + { "E-SHORTCUT", 0, TARGET_SHORTCUT } +}; +static guint n_targets = sizeof(target_table) / sizeof(target_table[0]); + +typedef struct _EShortcutBarBuiltinType EShortcutBarBuiltinType; +struct _EShortcutBarBuiltinType { + gchar *name; + gchar *filename; + GdkImlibImage *image; +}; + +EShortcutBarBuiltinType e_shortcut_bar_builtin_types[] = { + { "folder:", "gnome-word.png", NULL }, + { "calendar:", "gnome-calendar.png", NULL }, + { "todo:", "gnome-cromagnon.png", NULL }, + { "contacts:", "gnome-ccthemes.png", NULL } +}; +static gint e_shortcut_bar_num_builtin_types = sizeof (e_shortcut_bar_builtin_types) / sizeof (EShortcutBarBuiltinType); + +gboolean e_shortcut_bar_default_type_image_loaded = FALSE; +GdkImlibImage *e_shortcut_bar_default_type_image = NULL; +gchar *e_shortcut_bar_default_type_filename = "gnome-balsa2.png"; + +static void e_shortcut_bar_class_init (EShortcutBarClass *class); +static void e_shortcut_bar_init (EShortcutBar *shortcut_bar); +static void e_shortcut_bar_destroy (GtkObject *object); +static void e_shortcut_bar_set_canvas_style (EShortcutBar *shortcut_bar, + GtkWidget *canvas); +static void e_shortcut_bar_item_selected (EIconBar *icon_bar, + GdkEvent *event, + gint item_num, + EShortcutBar *shortcut_bar); +static void e_shortcut_bar_item_dragged (EIconBar *icon_bar, + GdkEvent *event, + gint item_num, + EShortcutBar *shortcut_bar); +static void e_shortcut_bar_on_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + EShortcutBar *shortcut_bar); +static void e_shortcut_bar_on_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + EShortcutBar *shortcut_bar); +static void e_shortcut_bar_on_drag_data_delete (GtkWidget *widget, + GdkDragContext *context, + EShortcutBar *shortcut_bar); +static void e_shortcut_bar_stop_editing (GtkWidget *button, + EShortcutBar *shortcut_bar); +static GdkImlibImage* e_shortcut_bar_get_image_from_url (EShortcutBar *shortcut_bar, + gchar *item_url); +static GdkImlibImage* e_shortcut_bar_load_image (gchar *filename); + + +enum +{ + ITEM_SELECTED, + LAST_SIGNAL +}; + +static guint e_shortcut_bar_signals[LAST_SIGNAL] = {0}; + +static EGroupBarClass *parent_class; + + +GtkType +e_shortcut_bar_get_type (void) +{ + static GtkType e_shortcut_bar_type = 0; + + if (!e_shortcut_bar_type){ + GtkTypeInfo e_shortcut_bar_info = { + "EShortcutBar", + sizeof (EShortcutBar), + sizeof (EShortcutBarClass), + (GtkClassInitFunc) e_shortcut_bar_class_init, + (GtkObjectInitFunc) e_shortcut_bar_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + parent_class = gtk_type_class (e_group_bar_get_type ()); + e_shortcut_bar_type = gtk_type_unique (e_group_bar_get_type (), + &e_shortcut_bar_info); + } + + return e_shortcut_bar_type; +} + + +static void +e_shortcut_bar_class_init (EShortcutBarClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + + e_shortcut_bar_signals[ITEM_SELECTED] = + gtk_signal_new ("item_selected", + GTK_RUN_LAST | GTK_RUN_ACTION, + object_class->type, + GTK_SIGNAL_OFFSET (EShortcutBarClass, + selected_item), + gtk_marshal_NONE__POINTER_INT_INT, + GTK_TYPE_NONE, 3, GTK_TYPE_GDK_EVENT, + GTK_TYPE_INT, GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, e_shortcut_bar_signals, + LAST_SIGNAL); + + /* Method override */ + object_class->destroy = e_shortcut_bar_destroy; +} + + +static void +e_shortcut_bar_init (EShortcutBar *shortcut_bar) +{ + shortcut_bar->groups = g_array_new (FALSE, FALSE, + sizeof (EShortcutBarGroup)); +} + + +GtkWidget * +e_shortcut_bar_new (void) +{ + GtkWidget *shortcut_bar; + + shortcut_bar = GTK_WIDGET (gtk_type_new (e_shortcut_bar_get_type ())); + + return shortcut_bar; +} + + +static void +e_shortcut_bar_destroy (GtkObject *object) +{ + EShortcutBar *shortcut_bar; + + shortcut_bar = E_SHORTCUT_BAR (object); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); + + g_array_free (shortcut_bar->groups, TRUE); +} + + +gint +e_shortcut_bar_add_group (EShortcutBar *shortcut_bar, gchar *group_name) +{ + EShortcutBarGroup *group, tmp_group; + gint group_num; + GtkWidget *button, *label; + + g_return_val_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar), -1); + g_return_val_if_fail (group_name != NULL, -1); + + group_num = shortcut_bar->groups->len; + g_array_append_val (shortcut_bar->groups, tmp_group); + + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + group->vscrolled_bar = e_vscrolled_bar_new (NULL); + gtk_widget_show (group->vscrolled_bar); + gtk_signal_connect (GTK_OBJECT (E_VSCROLLED_BAR (group->vscrolled_bar)->up_button), "pressed", GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing), shortcut_bar); + gtk_signal_connect (GTK_OBJECT (E_VSCROLLED_BAR (group->vscrolled_bar)->down_button), "pressed", GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing), shortcut_bar); + + group->icon_bar = e_icon_bar_new (); + gtk_widget_show (group->icon_bar); + gtk_container_add (GTK_CONTAINER (group->vscrolled_bar), + group->icon_bar); + gtk_signal_connect (GTK_OBJECT (group->icon_bar), "item_selected", + GTK_SIGNAL_FUNC (e_shortcut_bar_item_selected), + shortcut_bar); + gtk_signal_connect (GTK_OBJECT (group->icon_bar), "item_dragged", + GTK_SIGNAL_FUNC (e_shortcut_bar_item_dragged), + shortcut_bar); + gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_get", + GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_get), + shortcut_bar); + gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_received", + GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_received), + shortcut_bar); + gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_delete", + GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_delete), + shortcut_bar); + + e_shortcut_bar_set_canvas_style (shortcut_bar, group->icon_bar); + + button = gtk_button_new (); + label = e_clipped_label_new (group_name); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_widget_show (label); + gtk_container_add (GTK_CONTAINER (button), label); + gtk_widget_show (button); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing), + shortcut_bar); + + gtk_drag_dest_set (GTK_WIDGET (group->icon_bar), + GTK_DEST_DEFAULT_ALL, + target_table, n_targets, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + gtk_drag_dest_set (GTK_WIDGET (button), + GTK_DEST_DEFAULT_ALL, + target_table, n_targets, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + e_group_bar_add_group (E_GROUP_BAR (shortcut_bar), + group->vscrolled_bar, button, -1); + + + return group_num; +} + + +void +e_shortcut_bar_remove_group (EShortcutBar *shortcut_bar, + gint group_num) +{ + e_group_bar_remove_group (E_GROUP_BAR (shortcut_bar), group_num); + g_array_remove_index (shortcut_bar->groups, group_num); +} + + +gint +e_shortcut_bar_add_item (EShortcutBar *shortcut_bar, gint group_num, + gchar *item_url, gchar *item_name) +{ + EShortcutBarGroup *group; + GdkImlibImage *image; + gint item_num; + + g_return_val_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar), -1); + g_return_val_if_fail (group_num >= 0, -1); + g_return_val_if_fail (group_num < shortcut_bar->groups->len, -1); + g_return_val_if_fail (item_url != NULL, -1); + g_return_val_if_fail (item_name != NULL, -1); + + image = e_shortcut_bar_get_image_from_url (shortcut_bar, item_url); + + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + item_num = e_icon_bar_add_item (E_ICON_BAR (group->icon_bar), + image, item_name, -1); + e_icon_bar_set_item_data_full (E_ICON_BAR (group->icon_bar), item_num, + g_strdup (item_url), g_free); + return item_num; +} + + +void +e_shortcut_bar_remove_item (EShortcutBar *shortcut_bar, + gint group_num, + gint item_num) +{ + EShortcutBarGroup *group; + + g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar)); + g_return_if_fail (group_num >= 0); + g_return_if_fail (group_num < shortcut_bar->groups->len); + + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + e_icon_bar_remove_item (E_ICON_BAR (group->icon_bar), item_num); +} + + +static void +e_shortcut_bar_set_canvas_style (EShortcutBar *shortcut_bar, + GtkWidget *canvas) +{ + GtkRcStyle *rc_style; + + rc_style = gtk_rc_style_new (); + + rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG; + rc_style->fg[GTK_STATE_NORMAL].red = 65535; + rc_style->fg[GTK_STATE_NORMAL].green = 65535; + rc_style->fg[GTK_STATE_NORMAL].blue = 65535; + + rc_style->bg[GTK_STATE_NORMAL].red = 32512; + rc_style->bg[GTK_STATE_NORMAL].green = 32512; + rc_style->bg[GTK_STATE_NORMAL].blue = 32512; + + gtk_widget_modify_style (GTK_WIDGET (canvas), rc_style); + gtk_rc_style_unref (rc_style); +} + + +void +e_shortcut_bar_set_view_type (EShortcutBar *shortcut_bar, + gint group_num, + EIconBarViewType view_type) +{ + EShortcutBarGroup *group; + + g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar)); + g_return_if_fail (group_num >= 0); + g_return_if_fail (group_num < shortcut_bar->groups->len); + + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + e_icon_bar_set_view_type (E_ICON_BAR (group->icon_bar), view_type); +} + + +static void +e_shortcut_bar_item_selected (EIconBar *icon_bar, + GdkEvent *event, + gint item_num, + EShortcutBar *shortcut_bar) +{ + gint group_num; + + group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar), + GTK_WIDGET (icon_bar)->parent); + + gtk_signal_emit (GTK_OBJECT (shortcut_bar), + e_shortcut_bar_signals[ITEM_SELECTED], + event, group_num, item_num); +} + + +static void +e_shortcut_bar_item_dragged (EIconBar *icon_bar, + GdkEvent *event, + gint item_num, + EShortcutBar *shortcut_bar) +{ + GtkTargetList *target_list; + gint group_num; + + group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar), + GTK_WIDGET (icon_bar)->parent); + + /* FIXME: free somewhere - drag_end? */ + shortcut_bar->dragged_url = g_strdup (e_icon_bar_get_item_data (icon_bar, item_num)); + shortcut_bar->dragged_name = g_strdup (e_icon_bar_get_item_text (icon_bar, item_num)); + + target_list = gtk_target_list_new (target_table, n_targets); + gtk_drag_begin (GTK_WIDGET (icon_bar), target_list, + GDK_ACTION_COPY | GDK_ACTION_MOVE, + 1, event); + gtk_target_list_unref (target_list); +} + + +static void +e_shortcut_bar_on_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + EShortcutBar *shortcut_bar) +{ + gchar *data; + + if (info == TARGET_SHORTCUT) { + data = g_strdup_printf ("%s%c%s", shortcut_bar->dragged_name, + '\0', shortcut_bar->dragged_url); + gtk_selection_data_set (selection_data, selection_data->target, + 8, data, + strlen (shortcut_bar->dragged_name) + + strlen (shortcut_bar->dragged_url) + + 2); + g_free (data); + } +} + + +static void +e_shortcut_bar_on_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + EShortcutBar *shortcut_bar) +{ + EShortcutBarGroup *group; + gchar *item_name, *item_url; + EIconBar *icon_bar; + GdkImlibImage *image; + gint group_num, item_num; + + icon_bar = E_ICON_BAR (widget); + + if ((data->length >= 0) && (data->format == 8) + && icon_bar->dragging_before_item_num != -1) { + item_name = data->data; + item_url = item_name + strlen (item_name) + 1; + + image = e_shortcut_bar_get_image_from_url (shortcut_bar, + item_url); + + group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar), + GTK_WIDGET (icon_bar)->parent); + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + item_num = e_icon_bar_add_item (E_ICON_BAR (group->icon_bar), image, item_name, icon_bar->dragging_before_item_num); + e_icon_bar_set_item_data_full (E_ICON_BAR (group->icon_bar), + item_num, g_strdup (item_url), + g_free); + + gtk_drag_finish (context, TRUE, TRUE, time); + return; + } + + gtk_drag_finish (context, FALSE, FALSE, time); +} + + +static void +e_shortcut_bar_on_drag_data_delete (GtkWidget *widget, + GdkDragContext *context, + EShortcutBar *shortcut_bar) +{ + EIconBar *icon_bar; + + icon_bar = E_ICON_BAR (widget); + + e_icon_bar_remove_item (icon_bar, icon_bar->dragged_item_num); +} + + +void +e_shortcut_bar_start_editing_item (EShortcutBar *shortcut_bar, + gint group_num, + gint item_num) +{ + EShortcutBarGroup *group; + + g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar)); + g_return_if_fail (group_num >= 0); + g_return_if_fail (group_num < shortcut_bar->groups->len); + + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + + e_icon_bar_start_editing_item (E_ICON_BAR (group->icon_bar), item_num); +} + + +/* We stop editing any item when a scroll button is pressed. */ +static void +e_shortcut_bar_stop_editing (GtkWidget *button, + EShortcutBar *shortcut_bar) +{ + EShortcutBarGroup *group; + gint group_num; + + for (group_num = 0; + group_num < shortcut_bar->groups->len; + group_num++) { + group = &g_array_index (shortcut_bar->groups, + EShortcutBarGroup, group_num); + e_icon_bar_stop_editing_item (E_ICON_BAR (group->icon_bar), + TRUE); + } +} + + +static GdkImlibImage* +e_shortcut_bar_get_image_from_url (EShortcutBar *shortcut_bar, + gchar *item_url) +{ + gchar *method_terminator; + gint method_len, i; + + method_terminator = strchr (item_url, ':'); + if (method_terminator) { + method_len = method_terminator - item_url + 1; + + /* Check if it is a builtin type. */ + for (i = 0; i < e_shortcut_bar_num_builtin_types; i++) { + if (!strncmp (item_url, e_shortcut_bar_builtin_types[i].name, method_len)) { + if (!e_shortcut_bar_builtin_types[i].image) + e_shortcut_bar_builtin_types[i].image = e_shortcut_bar_load_image (e_shortcut_bar_builtin_types[i].filename); + return e_shortcut_bar_builtin_types[i].image; + } + } + } + + if (!e_shortcut_bar_default_type_image_loaded) { + e_shortcut_bar_default_type_image_loaded = TRUE; + e_shortcut_bar_default_type_image = e_shortcut_bar_load_image (e_shortcut_bar_default_type_filename); + } + return e_shortcut_bar_default_type_image; +} + + +static GdkImlibImage* +e_shortcut_bar_load_image (gchar *filename) +{ + gchar *pathname; + GdkImlibImage *image = NULL; + + pathname = gnome_pixmap_file (filename); + if (pathname) + image = gdk_imlib_load_image (pathname); + else + g_warning ("Couldn't find pixmap: %s", filename); + + return image; +} |