/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Author : * Damon Chaplin * * 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 */ /* * EIconBarBgItem - A GnomeCanvasItem which covers the entire EIconBar. * It paints the rectangles around items when the mouse moves over them, and * the lines between items when dragging. */ #include "e-icon-bar-bg-item.h" #include "e-icon-bar.h" /* This is the size of the border around the icons, for the shadow. */ #define E_ICON_BAR_LARGE_ICON_SHADOW_BORDER 2 #define E_ICON_BAR_SMALL_ICON_SHADOW_BORDER 2 /* These are for the horzontal bar when dragging. */ #define E_ICON_BAR_BG_ITEM_BAR_HEIGHT 1 #define E_ICON_BAR_BG_ITEM_BAR_OFFSET 2 #define E_ICON_BAR_BG_ITEM_LARGE_ARROW_HEIGHT 8 #define E_ICON_BAR_BG_ITEM_SMALL_ARROW_HEIGHT 4 static void e_icon_bar_bg_item_class_init (EIconBarBgItemClass *class); static void e_icon_bar_bg_item_init (EIconBarBgItem *ibitem); static void e_icon_bar_bg_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); static void e_icon_bar_bg_item_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); static void e_icon_bar_bg_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height); static double e_icon_bar_bg_item_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item); static gint e_icon_bar_bg_item_event (GnomeCanvasItem *item, GdkEvent *event); static gint e_icon_bar_bg_item_button_press (EIconBarBgItem *ibitem, GdkEvent *event); static gint e_icon_bar_bg_item_button_release (EIconBarBgItem *ibitem, GdkEvent *event); static gint e_icon_bar_bg_item_motion_notify (EIconBarBgItem *ibitem, GdkEvent *event); static GnomeCanvasItemClass *parent_class; /* The arguments we take */ enum { ARG_0, ARG_ICON_BAR }; GtkType e_icon_bar_bg_item_get_type (void) { static GtkType e_icon_bar_bg_item_type = 0; if (!e_icon_bar_bg_item_type) { GtkTypeInfo e_icon_bar_bg_item_info = { "EIconBarBgItem", sizeof (EIconBarBgItem), sizeof (EIconBarBgItemClass), (GtkClassInitFunc) e_icon_bar_bg_item_class_init, (GtkObjectInitFunc) e_icon_bar_bg_item_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL }; e_icon_bar_bg_item_type = gtk_type_unique (gnome_canvas_item_get_type (), &e_icon_bar_bg_item_info); } return e_icon_bar_bg_item_type; } static void e_icon_bar_bg_item_class_init (EIconBarBgItemClass *class) { GtkObjectClass *object_class; GnomeCanvasItemClass *item_class; parent_class = gtk_type_class (gnome_canvas_item_get_type()); object_class = (GtkObjectClass *) class; item_class = (GnomeCanvasItemClass *) class; gtk_object_add_arg_type ("EIconBarBgItem::icon_bar", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_ICON_BAR); object_class->set_arg = e_icon_bar_bg_item_set_arg; /* GnomeCanvasItem method overrides */ item_class->update = e_icon_bar_bg_item_update; item_class->draw = e_icon_bar_bg_item_draw; item_class->point = e_icon_bar_bg_item_point; item_class->event = e_icon_bar_bg_item_event; } static void e_icon_bar_bg_item_init (EIconBarBgItem *ibitem) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (ibitem); ibitem->icon_bar = NULL; item->x1 = 0; item->y1 = 0; item->x2 = 0; item->y2 = 0; } static void e_icon_bar_bg_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) { GnomeCanvasItem *item; EIconBarBgItem *ibitem; item = GNOME_CANVAS_ITEM (o); ibitem = E_ICON_BAR_BG_ITEM (o); switch (arg_id){ case ARG_ICON_BAR: ibitem->icon_bar = GTK_VALUE_POINTER (*arg); break; } } static void e_icon_bar_bg_item_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) { if (GNOME_CANVAS_ITEM_CLASS (parent_class)->update) (* GNOME_CANVAS_ITEM_CLASS (parent_class)->update) (item, affine, clip_path, flags); /* The grid covers the entire canvas area. */ item->x1 = 0; item->y1 = 0; item->x2 = INT_MAX; item->y2 = INT_MAX; } /* * DRAWING ROUTINES - functions to paint the canvas item. */ static void e_icon_bar_bg_item_draw (GnomeCanvasItem *canvas_item, GdkDrawable *drawable, int x, int y, int width, int height) { EIconBar *icon_bar; EIconBarItem *item; EIconBarBgItem *ibitem; GtkStyle *style; GdkGC *gc; GtkShadowType shadow; gint item_num, border, bar_x, bar_y, bar_w, i, arrow_height; ibitem = E_ICON_BAR_BG_ITEM (canvas_item); icon_bar = ibitem->icon_bar; g_return_if_fail (icon_bar != NULL); style = GTK_WIDGET (icon_bar)->style; /* Draw the highlight around the current highlight item. */ item_num = -1; if (icon_bar->editing_item_num == -1) { if (icon_bar->pressed_item_num != -1) { item_num = icon_bar->pressed_item_num; if (icon_bar->pressed_item_num == icon_bar->mouse_over_item_num) shadow = GTK_SHADOW_IN; else shadow = GTK_SHADOW_OUT; } else if (icon_bar->mouse_over_item_num != -1) { item_num = icon_bar->mouse_over_item_num; shadow = GTK_SHADOW_OUT; } } if (item_num != -1) { item = &g_array_index (icon_bar->items, EIconBarItem, item_num); if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) border = E_ICON_BAR_LARGE_ICON_SHADOW_BORDER; else border = E_ICON_BAR_SMALL_ICON_SHADOW_BORDER; gtk_draw_shadow (style, drawable, GTK_STATE_NORMAL, shadow, icon_bar->icon_x - border - x, item->icon_y - border - y, icon_bar->icon_w + border * 2 - 1, icon_bar->icon_h + border * 2 - 1); } /* Draw the bar between items when dragging, if needed. */ if (icon_bar->in_drag && icon_bar->dragging_before_item_num != -1) { if (icon_bar->dragging_before_item_num < icon_bar->items->len) { item = &g_array_index (icon_bar->items, EIconBarItem, icon_bar->dragging_before_item_num); bar_y = 0; } else { /* We need to draw the bar after the last item. */ item = &g_array_index (icon_bar->items, EIconBarItem, icon_bar->items->len - 1); bar_y = item->item_height + icon_bar->spacing; } if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) { bar_y += item->icon_y; } else { bar_y += MIN (item->icon_y, item->text_y); } bar_y -= y + icon_bar->spacing / 2; bar_x = E_ICON_BAR_BG_ITEM_BAR_OFFSET - x; bar_w = GTK_WIDGET (icon_bar)->allocation.width - 2 * E_ICON_BAR_BG_ITEM_BAR_OFFSET - 1; gc = GTK_WIDGET (icon_bar)->style->fg_gc[GTK_STATE_NORMAL]; /* Draw the horizontal bar. */ gdk_draw_rectangle (drawable, gc, TRUE, bar_x, bar_y, bar_w, E_ICON_BAR_BG_ITEM_BAR_HEIGHT); if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) arrow_height = E_ICON_BAR_BG_ITEM_LARGE_ARROW_HEIGHT / 2; else arrow_height = E_ICON_BAR_BG_ITEM_SMALL_ARROW_HEIGHT / 2; /* Draw the arrows at the end of the lines. We use gdk_draw_line() to draw a series of vertical lines, since gdk_draw_polygon() produces odd results. */ i = 0; while (arrow_height > 0) { gdk_draw_line (drawable, gc, bar_x + i, bar_y - arrow_height, bar_x + i, bar_y + arrow_height); gdk_draw_line (drawable, gc, bar_x + bar_w - i - 1, bar_y - arrow_height, bar_x + bar_w - i - 1, bar_y + arrow_height); arrow_height--; i++; } } } /* This is supposed to return the nearest item the the point and the distance. Since we are the only item we just return ourself and 0 for the distance. This is needed so that we get button/motion events. */ static double e_icon_bar_bg_item_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { *actual_item = item; return 0.0; } static gint e_icon_bar_bg_item_event (GnomeCanvasItem *item, GdkEvent *event) { EIconBarBgItem *ibitem; ibitem = E_ICON_BAR_BG_ITEM (item); switch (event->type) { case GDK_BUTTON_PRESS: return e_icon_bar_bg_item_button_press (ibitem, event); case GDK_BUTTON_RELEASE: return e_icon_bar_bg_item_button_release (ibitem, event); case GDK_MOTION_NOTIFY: return e_icon_bar_bg_item_motion_notify (ibitem, event); default: break; } return FALSE; } static gint e_icon_bar_bg_item_button_press (EIconBarBgItem *ibitem, GdkEvent *event) { gint item_num; item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar, event->button.x, event->button.y, NULL); e_icon_bar_item_pressed (ibitem->icon_bar, item_num, event); return TRUE; } static gint e_icon_bar_bg_item_button_release (EIconBarBgItem *ibitem, GdkEvent *event) { gint item_num; item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar, event->button.x, event->button.y, NULL); e_icon_bar_item_released (ibitem->icon_bar, item_num, event); return TRUE; } static gint e_icon_bar_bg_item_motion_notify (EIconBarBgItem *ibitem, GdkEvent *event) { gint item_num; item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar, event->motion.x, event->motion.y, NULL); e_icon_bar_item_motion (ibitem->icon_bar, item_num, event); return TRUE; }