aboutsummaryrefslogblamecommitdiffstats
path: root/widgets/shortcut-bar/e-icon-bar-bg-item.c
blob: 025bd6f4670c0c05cb92dc792b716f2ecc9620fb (plain) (tree)
1
2
3
4
5



                                                                           
                                       




























































































































































































                                                                                                                    
                                 

































































































































                                                                                                        


                                                                   




































                                                                      
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* 
 * Author : 
 *  Damon Chaplin <damon@helixcode.com>
 *
 * 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;
    shadow = GTK_SHADOW_NONE;

    /* 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;

    if (event->button.button == 4 || event->button.button == 5)
        return FALSE;

    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;
}