diff options
-rw-r--r-- | eel/Makefile.am | 2 | ||||
-rw-r--r-- | eel/eel-canvas-rect-ellipse.c | 1102 | ||||
-rw-r--r-- | eel/eel-canvas-rect-ellipse.h | 167 | ||||
-rw-r--r-- | libnautilus-private/Makefile.am | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-container.c | 7 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-dnd.c | 5 | ||||
-rw-r--r-- | libnautilus-private/nautilus-selection-canvas-item.c | 708 | ||||
-rw-r--r-- | libnautilus-private/nautilus-selection-canvas-item.h | 63 |
8 files changed, 779 insertions, 1277 deletions
diff --git a/eel/Makefile.am b/eel/Makefile.am index 457e33601..9b3dea4a1 100644 --- a/eel/Makefile.am +++ b/eel/Makefile.am @@ -35,7 +35,6 @@ eel_headers = \ eel-art-extensions.h \ eel-canvas.h \ eel-canvas-util.h \ - eel-canvas-rect-ellipse.h \ eel-debug.h \ eel-editable-label.h \ eel-gdk-extensions.h \ @@ -56,7 +55,6 @@ libeel_2_la_SOURCES = \ eel-art-extensions.c \ eel-canvas.c \ eel-canvas-util.c \ - eel-canvas-rect-ellipse.c \ eel-debug.c \ eel-editable-label.c \ eel-gdk-extensions.c \ diff --git a/eel/eel-canvas-rect-ellipse.c b/eel/eel-canvas-rect-ellipse.c deleted file mode 100644 index 65e43c945..000000000 --- a/eel/eel-canvas-rect-ellipse.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ -/* Rectangle and ellipse item types for EelCanvas widget - * - * EelCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - */ - -#include <config.h> -#include <math.h> -#include "eel-canvas-rect-ellipse.h" -#include "eel-canvas-util.h" -#include <string.h> - -#ifdef HAVE_RENDER -#include <gdk/gdkx.h> -#include <X11/extensions/Xrender.h> -#endif - -/* Base class for rectangle and ellipse item types */ - -#define noVERBOSE - -enum { - PROP_0, - PROP_X1, - PROP_Y1, - PROP_X2, - PROP_Y2, - PROP_FILL_COLOR_RGBA, - PROP_OUTLINE_COLOR_RGBA, - PROP_OUTLINE_STIPPLING, - PROP_WIDTH_PIXELS, - PROP_WIDTH_UNITS -}; - - -static void eel_canvas_re_class_init (EelCanvasREClass *klass); -static void eel_canvas_re_init (EelCanvasRE *re); -static void eel_canvas_re_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void eel_canvas_re_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -static void eel_canvas_re_update_shared (EelCanvasItem *item, - double i2w_dx, double i2w_dy, int flags); -static void eel_canvas_re_realize (EelCanvasItem *item); -static void eel_canvas_re_unrealize (EelCanvasItem *item); -static void eel_canvas_re_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2); -static void eel_canvas_re_translate (EelCanvasItem *item, double dx, double dy); -static void eel_canvas_rect_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags); -static void eel_canvas_ellipse_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags); - -typedef struct { - /*< public >*/ - int x0, y0, x1, y1; -} Rect; - -static Rect make_rect (int x0, int y0, int x1, int y1); -static void diff_rects (Rect r1, Rect r2, int *count, Rect result[4]); - -static EelCanvasItemClass *re_parent_class; -static EelCanvasREClass *rect_parent_class; - - -GType -eel_canvas_re_get_type (void) -{ - static GType re_type = 0; - - if (!re_type) { - GTypeInfo re_info = { - sizeof (EelCanvasREClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) eel_canvas_re_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EelCanvasRE), - 0, /* n_preallocs */ - (GInstanceInitFunc) eel_canvas_re_init - }; - - re_type = g_type_register_static (eel_canvas_item_get_type (), - "EelCanvasRE", - &re_info, - 0); - } - - return re_type; -} - -static void -eel_canvas_re_class_init (EelCanvasREClass *klass) -{ - GObjectClass *gobject_class; - EelCanvasItemClass *item_class; - - gobject_class = (GObjectClass *) klass; - item_class = (EelCanvasItemClass *) klass; - - re_parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = eel_canvas_re_set_property; - gobject_class->get_property = eel_canvas_re_get_property; - - g_object_class_install_property - (gobject_class, - PROP_X1, - g_param_spec_double ("x1", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_Y1, - g_param_spec_double ("y1", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_X2, - g_param_spec_double ("x2", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_Y2, - g_param_spec_double ("y2", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_FILL_COLOR_RGBA, - g_param_spec_boxed ("fill-color-rgba", NULL, NULL, - GDK_TYPE_RGBA, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_OUTLINE_COLOR_RGBA, - g_param_spec_boxed ("outline-color-rgba", NULL, NULL, - GDK_TYPE_RGBA, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_OUTLINE_STIPPLING, - g_param_spec_boolean ("outline-stippling", NULL, NULL, - FALSE, G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_PIXELS, - g_param_spec_uint ("width-pixels", NULL, NULL, - 0, G_MAXUINT, 0, - G_PARAM_READWRITE)); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_UNITS, - g_param_spec_double ("width-units", NULL, NULL, - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - item_class->realize = eel_canvas_re_realize; - item_class->unrealize = eel_canvas_re_unrealize; - item_class->translate = eel_canvas_re_translate; - item_class->bounds = eel_canvas_re_bounds; -} - -static void -eel_canvas_re_init (EelCanvasRE *re) -{ - re->x1 = 0.0; - re->y1 = 0.0; - re->x2 = 0.0; - re->y2 = 0.0; - re->width = 0.0; -} - -static void get_bounds (EelCanvasRE *re, double *px1, double *py1, double *px2, double *py2) -{ - EelCanvasItem *item; - double x1, y1, x2, y2; - int cx1, cy1, cx2, cy2; - double hwidth; - -#ifdef VERBOSE - g_print ("re get_bounds\n"); -#endif - item = EEL_CANVAS_ITEM (re); - - if (re->width_pixels) - hwidth = (re->width / item->canvas->pixels_per_unit) / 2.0; - else - hwidth = re->width / 2.0; - - x1 = re->x1; - y1 = re->y1; - x2 = re->x2; - y2 = re->y2; - - eel_canvas_item_i2w (item, &x1, &y1); - eel_canvas_item_i2w (item, &x2, &y2); - eel_canvas_w2c (item->canvas, x1 - hwidth, y1 - hwidth, &cx1, &cy1); - eel_canvas_w2c (item->canvas, x2 + hwidth, y2 + hwidth, &cx2, &cy2); - *px1 = cx1; - *py1 = cy1; - *px2 = cx2; - *py2 = cy2; - - /* Some safety fudging */ - - *px1 -= 2; - *py1 -= 2; - *px2 += 2; - *py2 += 2; -} - -static void -eel_canvas_re_set_fill (EelCanvasRE *re, gboolean fill_set) -{ - if (re->fill_set != fill_set) { - re->fill_set = fill_set; - eel_canvas_item_request_update (EEL_CANVAS_ITEM (re)); - } -} - -static void -eel_canvas_re_set_outline (EelCanvasRE *re, gboolean outline_set) -{ - if (re->outline_set != outline_set) { - re->outline_set = outline_set; - eel_canvas_item_request_update (EEL_CANVAS_ITEM (re)); - } -} - -static void -eel_canvas_re_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - EelCanvasItem *item; - EelCanvasRE *re; - - g_return_if_fail (object != NULL); - g_return_if_fail (EEL_IS_CANVAS_RE (object)); - - item = EEL_CANVAS_ITEM (object); - re = EEL_CANVAS_RE (object); - - switch (param_id) { - case PROP_X1: - re->x1 = g_value_get_double (value); - - eel_canvas_item_request_update (item); - break; - - case PROP_Y1: - re->y1 = g_value_get_double (value); - - eel_canvas_item_request_update (item); - break; - - case PROP_X2: - re->x2 = g_value_get_double (value); - - eel_canvas_item_request_update (item); - break; - - case PROP_Y2: - re->y2 = g_value_get_double (value); - - eel_canvas_item_request_update (item); - break; - - case PROP_FILL_COLOR_RGBA: { - GdkRGBA *color; - - color = g_value_get_boxed (value); - - eel_canvas_re_set_fill (re, color != NULL); - - if (color != NULL) { - re->fill_color = *color; - } - - eel_canvas_item_request_redraw (item); - break; - } - - case PROP_OUTLINE_COLOR_RGBA: { - GdkRGBA *color; - - color = g_value_get_boxed (value); - - eel_canvas_re_set_outline (re, color != NULL); - - if (color != NULL) { - re->outline_color = *color; - } - - eel_canvas_item_request_redraw (item); - break; - } - - case PROP_OUTLINE_STIPPLING: - re->outline_stippling = g_value_get_boolean (value); - - eel_canvas_item_request_redraw (item); - break; - - case PROP_WIDTH_PIXELS: - re->width = g_value_get_uint (value); - re->width_pixels = TRUE; - - eel_canvas_item_request_update (item); - break; - - case PROP_WIDTH_UNITS: - re->width = fabs (g_value_get_double (value)); - re->width_pixels = FALSE; - - eel_canvas_item_request_update (item); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -eel_canvas_re_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - EelCanvasRE *re; - - g_return_if_fail (object != NULL); - g_return_if_fail (EEL_IS_CANVAS_RE (object)); - - re = EEL_CANVAS_RE (object); - - switch (param_id) { - case PROP_X1: - g_value_set_double (value, re->x1); - break; - - case PROP_Y1: - g_value_set_double (value, re->y1); - break; - - case PROP_X2: - g_value_set_double (value, re->x2); - break; - - case PROP_Y2: - g_value_set_double (value, re->y2); - break; - - case PROP_FILL_COLOR_RGBA: - g_value_set_boxed (value, &re->fill_color); - break; - - case PROP_OUTLINE_COLOR_RGBA: - g_value_set_boxed (value, &re->outline_color); - break; - - case PROP_OUTLINE_STIPPLING: - g_value_set_boolean (value, re->outline_stippling); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -eel_canvas_re_update_shared (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags) -{ -#ifdef VERBOSE - g_print ("eel_canvas_re_update_shared\n"); -#endif - if (re_parent_class->update) - (* re_parent_class->update) (item, i2w_dx, i2w_dy, flags); -} - -static void -eel_canvas_re_realize (EelCanvasItem *item) -{ -#ifdef VERBOSE - g_print ("eel_canvas_re_realize\n"); -#endif - if (re_parent_class->realize) - (* re_parent_class->realize) (item); -} - -static void -eel_canvas_re_unrealize (EelCanvasItem *item) -{ - if (re_parent_class->unrealize) - (* re_parent_class->unrealize) (item); -} - -static void -eel_canvas_re_translate (EelCanvasItem *item, double dx, double dy) -{ - EelCanvasRE *re; - -#ifdef VERBOSE - g_print ("eel_canvas_re_translate\n"); -#endif - re = EEL_CANVAS_RE (item); - - re->x1 += dx; - re->y1 += dy; - re->x2 += dx; - re->y2 += dy; -} - - -static void -eel_canvas_re_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2) -{ - EelCanvasRE *re; - double hwidth; - -#ifdef VERBOSE - g_print ("eel_canvas_re_bounds\n"); -#endif - re = EEL_CANVAS_RE (item); - - if (re->width_pixels) - hwidth = (re->width / item->canvas->pixels_per_unit) / 2.0; - else - hwidth = re->width / 2.0; - - *x1 = re->x1 - hwidth; - *y1 = re->y1 - hwidth; - *x2 = re->x2 + hwidth; - *y2 = re->y2 + hwidth; -} - -/* Rectangle item */ - - -static void eel_canvas_rect_class_init (EelCanvasRectClass *klass); -static void eel_canvas_rect_init (EelCanvasRect *rect); -static void eel_canvas_rect_finalize (GObject *object); -static void eel_canvas_rect_realize (EelCanvasItem *item); - -static void eel_canvas_rect_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region); -static double eel_canvas_rect_point (EelCanvasItem *item, double x, double y, int cx, int cy, - EelCanvasItem **actual_item); - -struct _EelCanvasRectPrivate { - Rect last_update_rect; - Rect last_outline_update_rect; - int last_outline_update_width; - -#ifdef HAVE_RENDER - gboolean use_render; - XRenderPictFormat *format; -#endif -}; - -GType -eel_canvas_rect_get_type (void) -{ - static GType rect_type = 0; - - if (!rect_type) { - GTypeInfo rect_info = { - sizeof (EelCanvasRectClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) eel_canvas_rect_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EelCanvasRect), - 0, /* n_preallocs */ - (GInstanceInitFunc) eel_canvas_rect_init - }; - - rect_type = g_type_register_static (eel_canvas_re_get_type (), - "EelCanvasRect", - &rect_info, - 0); - } - - return rect_type; -} - -static void -eel_canvas_rect_class_init (EelCanvasRectClass *klass) -{ - EelCanvasItemClass *item_class; - - rect_parent_class = g_type_class_peek_parent (klass); - - item_class = (EelCanvasItemClass *) klass; - - item_class->draw = eel_canvas_rect_draw; - item_class->point = eel_canvas_rect_point; - item_class->update = eel_canvas_rect_update; - item_class->realize = eel_canvas_rect_realize; - - G_OBJECT_CLASS (klass)->finalize = eel_canvas_rect_finalize; - -} - -static void -eel_canvas_rect_init (EelCanvasRect *rect) -{ - rect->priv = g_new0 (EelCanvasRectPrivate, 1); -} - -static void -eel_canvas_rect_finalize (GObject *object) -{ - EelCanvasRect *rect = EEL_CANVAS_RECT (object); - - if (rect->priv) { - g_free (rect->priv); - } - - G_OBJECT_CLASS (rect_parent_class)->finalize (object); -} - -static void -eel_canvas_rect_realize (EelCanvasItem *item) -{ -#ifdef HAVE_RENDER - EelCanvasRectPrivate *priv; - int event_base, error_base; - Display *dpy; - - priv = EEL_CANVAS_RECT (item)->priv; - - dpy = GDK_WINDOW_XDISPLAY (gtk_widget_get_window (GTK_WIDGET (item->canvas))); - priv->use_render = XRenderQueryExtension (dpy, &event_base, &error_base); - - if (priv->use_render) { - GdkVisual *gdk_visual; - Visual *visual; - - gdk_visual = gtk_widget_get_visual (GTK_WIDGET (item->canvas)); - visual = gdk_x11_visual_get_xvisual (gdk_visual); - - priv->format = XRenderFindVisualFormat (dpy, visual); - } -#endif - - if (EEL_CANVAS_ITEM_CLASS (rect_parent_class)->realize) { - (* EEL_CANVAS_ITEM_CLASS (rect_parent_class)->realize) (item); - } -} - -static void -eel_canvas_set_source_color (cairo_t *cr, - GdkRGBA *rgba) -{ - gdk_cairo_set_source_rgba (cr, rgba); -} - -#define DASH_ON 0.8 -#define DASH_OFF 1.7 -static void -eel_canvas_rect_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region) -{ - EelCanvasRE *re; - double x1, y1, x2, y2; - int cx1, cy1, cx2, cy2; - double i2w_dx, i2w_dy; - - re = EEL_CANVAS_RE (item); - - /* Get canvas pixel coordinates */ - i2w_dx = 0.0; - i2w_dy = 0.0; - eel_canvas_item_i2w (item, &i2w_dx, &i2w_dy); - - x1 = re->x1 + i2w_dx; - y1 = re->y1 + i2w_dy; - x2 = re->x2 + i2w_dx; - y2 = re->y2 + i2w_dy; - - eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); - eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); - - if (cx2 <= cx1 || cy2 <= cy1 ) { - return; - } - - cairo_save (cr); - - if (re->fill_set) { - eel_canvas_set_source_color (cr, &re->fill_color); - cairo_rectangle (cr, - cx1, cy1, - cx2 - cx1 + 1, - cy2 - cy1 + 1); - cairo_fill (cr); - } - - if (re->outline_set) { - eel_canvas_set_source_color (cr, &re->outline_color); - if (re->width_pixels) { - cairo_set_line_width (cr, (int) re->width); - } else { - cairo_set_line_width (cr, (int) (re->width * re->item.canvas->pixels_per_unit + 0.5)); - } - - if (re->outline_stippling) { - double dash[2] = { DASH_ON, DASH_OFF }; - - cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0); - } - - cairo_rectangle (cr, - cx1 + 0.5, cy1 + 0.5, - cx2 - cx1, - cy2 - cy1); - cairo_stroke (cr); - } - - cairo_restore (cr); -} - -static double -eel_canvas_rect_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) -{ - EelCanvasRE *re; - double x1, y1, x2, y2; - double hwidth; - double dx, dy; - double tmp; - -#ifdef VERBOSE - g_print ("eel_canvas_rect_point\n"); -#endif - re = EEL_CANVAS_RE (item); - - *actual_item = item; - - /* Find the bounds for the rectangle plus its outline width */ - - x1 = re->x1; - y1 = re->y1; - x2 = re->x2; - y2 = re->y2; - - if (re->outline_set) { - if (re->width_pixels) - hwidth = (re->width / item->canvas->pixels_per_unit) / 2.0; - else - hwidth = re->width / 2.0; - - x1 -= hwidth; - y1 -= hwidth; - x2 += hwidth; - y2 += hwidth; - } else - hwidth = 0.0; - - /* Is point inside rectangle (which can be hollow if it has no fill set)? */ - - if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { - if (re->fill_set || !re->outline_set) - return 0.0; - - dx = x - x1; - tmp = x2 - x; - if (tmp < dx) - dx = tmp; - - dy = y - y1; - tmp = y2 - y; - if (tmp < dy) - dy = tmp; - - if (dy < dx) - dx = dy; - - dx -= 2.0 * hwidth; - - if (dx < 0.0) - return 0.0; - else - return dx; - } - - /* Point is outside rectangle */ - - if (x < x1) - dx = x1 - x; - else if (x > x2) - dx = x - x2; - else - dx = 0.0; - - if (y < y1) - dy = y1 - y; - else if (y > y2) - dy = y - y2; - else - dy = 0.0; - - return sqrt (dx * dx + dy * dy); -} - -static void -request_redraw_borders (EelCanvas *canvas, - Rect *update_rect, - int width) -{ - eel_canvas_request_redraw (canvas, - update_rect->x0, update_rect->y0, - update_rect->x1, update_rect->y0 + width); - eel_canvas_request_redraw (canvas, - update_rect->x0, update_rect->y1-width, - update_rect->x1, update_rect->y1); - eel_canvas_request_redraw (canvas, - update_rect->x0, update_rect->y0, - update_rect->x0+width, update_rect->y1); - eel_canvas_request_redraw (canvas, - update_rect->x1-width, update_rect->y0, - update_rect->x1, update_rect->y1); -} - - -static void -eel_canvas_rect_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, gint flags) -{ - EelCanvasRE *re; - double x1, y1, x2, y2; - int cx1, cy1, cx2, cy2; - int repaint_rects_count, i; - int width_pixels; - int width_lt, width_rb; - Rect update_rect, repaint_rects[4]; - EelCanvasRectPrivate *priv; - - eel_canvas_re_update_shared (item, i2w_dx, i2w_dy, flags); - - re = EEL_CANVAS_RE (item); - priv = EEL_CANVAS_RECT (item)->priv; - - x1 = re->x1 + i2w_dx; - y1 = re->y1 + i2w_dy; - x2 = re->x2 + i2w_dx; - y2 = re->y2 + i2w_dy; - - eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); - eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); - - update_rect = make_rect (cx1, cy1, cx2+1, cy2+1); -#if 0 - eel_canvas_request_redraw (item->canvas, - update_rect.x0, update_rect.y0, - update_rect.x1, update_rect.y1); - eel_canvas_request_redraw (item->canvas, - priv->last_update_rect.x0, priv->last_update_rect.y0, - priv->last_update_rect.x1, priv->last_update_rect.y1); -#else - diff_rects (update_rect, priv->last_update_rect, - &repaint_rects_count, repaint_rects); - for (i = 0; i < repaint_rects_count; i++) { - eel_canvas_request_redraw (item->canvas, - repaint_rects[i].x0, repaint_rects[i].y0, - repaint_rects[i].x1, repaint_rects[i].y1); - } -#endif - priv->last_update_rect = update_rect; - - if (re->outline_set) { - /* Outline and bounding box */ - if (re->width_pixels) - width_pixels = (int) re->width; - else - width_pixels = (int) floor (re->width * re->item.canvas->pixels_per_unit + 0.5); - - width_lt = width_pixels / 2; - width_rb = (width_pixels + 1) / 2; - - cx1 -= width_lt; - cy1 -= width_lt; - cx2 += width_rb; - cy2 += width_rb; - - update_rect = make_rect (cx1, cy1, cx2, cy2); - request_redraw_borders (item->canvas, &update_rect, - (width_lt + width_rb)); - request_redraw_borders (item->canvas, &priv->last_outline_update_rect, - priv->last_outline_update_width); - priv->last_outline_update_rect = update_rect; - priv->last_outline_update_width = width_lt + width_rb; - - item->x1 = cx1; - item->y1 = cy1; - item->x2 = cx2+1; - item->y2 = cy2+1; - } else { - item->x1 = cx1; - item->y1 = cy1; - item->x2 = cx2+1; - item->y2 = cy2+1; - } -} - -/* Ellipse item */ - - -static void eel_canvas_ellipse_class_init (EelCanvasEllipseClass *klass); - -static void eel_canvas_ellipse_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region); -static double eel_canvas_ellipse_point (EelCanvasItem *item, double x, double y, int cx, int cy, - EelCanvasItem **actual_item); - - -GType -eel_canvas_ellipse_get_type (void) -{ - static GType ellipse_type = 0; - - if (!ellipse_type) { - GTypeInfo ellipse_info = { - sizeof (EelCanvasEllipseClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) eel_canvas_ellipse_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EelCanvasEllipse), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL - - }; - - ellipse_type = g_type_register_static (eel_canvas_re_get_type (), - "EelCanvasEllipse", - &ellipse_info, - 0); - } - - return ellipse_type; -} - -static void -eel_canvas_ellipse_class_init (EelCanvasEllipseClass *klass) -{ - EelCanvasItemClass *item_class; - - item_class = (EelCanvasItemClass *) klass; - - item_class->draw = eel_canvas_ellipse_draw; - item_class->point = eel_canvas_ellipse_point; - item_class->update = eel_canvas_ellipse_update; -} - -static void -eel_canvas_ellipse_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region) -{ - EelCanvasRE *re; - int x1, y1, x2, y2; - double i2w_dx, i2w_dy; - - re = EEL_CANVAS_RE (item); - - /* Get canvas pixel coordinates */ - - i2w_dx = 0.0; - i2w_dy = 0.0; - eel_canvas_item_i2w (item, &i2w_dx, &i2w_dy); - - eel_canvas_w2c (item->canvas, - re->x1 + i2w_dx, - re->y1 + i2w_dy, - &x1, &y1); - eel_canvas_w2c (item->canvas, - re->x2 + i2w_dx, - re->y2 + i2w_dy, - &x2, &y2); - - cairo_save (cr); - - cairo_save (cr); - cairo_translate (cr, (x1 + x2) / 2., (y1 + y2) / 2.); - cairo_scale (cr, (x2 - x1), (y2 - y1)); - cairo_arc (cr, 0, 0, 1, 0, 2 * G_PI); - cairo_restore (cr); - - if (re->fill_set) { - eel_canvas_set_source_color (cr, &re->fill_color); - cairo_fill_preserve (cr); - } - - if (re->outline_set) { - eel_canvas_set_source_color (cr, &re->outline_color); - if (re->width_pixels) { - cairo_set_line_width (cr, (int) re->width); - } else { - cairo_set_line_width (cr, (int) (re->width * re->item.canvas->pixels_per_unit + 0.5)); - } - - cairo_stroke_preserve (cr); - } - - cairo_restore (cr); -} - -static double -eel_canvas_ellipse_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) -{ - EelCanvasRE *re; - double dx, dy; - double scaled_dist; - double outline_dist; - double center_dist; - double width; - double a, b; - double diamx, diamy; - - re = EEL_CANVAS_RE (item); - - *actual_item = item; - - if (re->outline_set) { - if (re->width_pixels) - width = re->width / item->canvas->pixels_per_unit; - else - width = re->width; - } else - width = 0.0; - - /* Compute the distance between the center of the ellipse and the point, with the ellipse - * considered as being scaled to a circle. - */ - - dx = x - (re->x1 + re->x2) / 2.0; - dy = y - (re->y1 + re->y2) / 2.0; - center_dist = sqrt (dx * dx + dy * dy); - - a = dx / ((re->x2 + width - re->x1) / 2.0); - b = dy / ((re->y2 + width - re->y1) / 2.0); - scaled_dist = sqrt (a * a + b * b); - - /* If the scaled distance is greater than 1, then we are outside. Compute the distance from - * the point to the edge of the circle, then scale back to the original un-scaled coordinate - * system. - */ - - if (scaled_dist > 1.0) - return (center_dist / scaled_dist) * (scaled_dist - 1.0); - - /* We are inside the outer edge of the ellipse. If it is filled, then we are "inside". - * Otherwise, do the same computation as above, but also check whether we are inside the - * outline. - */ - - if (re->fill_set) - return 0.0; - - if (scaled_dist > EEL_CANVAS_EPSILON) - outline_dist = (center_dist / scaled_dist) * (1.0 - scaled_dist) - width; - else { - /* Handle very small distance */ - - diamx = re->x2 - re->x1; - diamy = re->y2 - re->y1; - - if (diamx < diamy) - outline_dist = (diamx - width) / 2.0; - else - outline_dist = (diamy - width) / 2.0; - } - - if (outline_dist < 0.0) - return 0.0; - - return outline_dist; -} - -static void -eel_canvas_ellipse_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, gint flags) -{ - EelCanvasRE *re; - double x0, y0, x1, y1; - -#ifdef VERBOSE - g_print ("eel_canvas_sllipse_update item %x\n", item); -#endif - - eel_canvas_re_update_shared (item, i2w_dx, i2w_dy, flags); - re = EEL_CANVAS_RE (item); - - get_bounds (re, &x0, &y0, &x1, &y1); - eel_canvas_update_bbox (item, x0, y0, x1, y1); -} - -static int -rect_empty (const Rect *src) { - return (src->x1 <= src->x0 || src->y1 <= src->y0); -} - -static Rect -make_rect (int x0, int y0, int x1, int y1) -{ - Rect r; - - r.x0 = x0; - r.y0 = y0; - r.x1 = x1; - r.y1 = y1; - return r; -} - -static gboolean -rects_intersect (Rect r1, Rect r2) -{ - if (r1.x0 >= r2.x1) { - return FALSE; - } - if (r2.x0 >= r1.x1) { - return FALSE; - } - if (r1.y0 >= r2.y1) { - return FALSE; - } - if (r2.y0 >= r1.y1) { - return FALSE; - } - return TRUE; -} - -static void -diff_rects_guts (Rect ra, Rect rb, int *count, Rect result[4]) -{ - if (ra.x0 < rb.x0) { - result[(*count)++] = make_rect (ra.x0, ra.y0, rb.x0, ra.y1); - } - if (ra.y0 < rb.y0) { - result[(*count)++] = make_rect (ra.x0, ra.y0, ra.x1, rb.y0); - } - if (ra.x1 < rb.x1) { - result[(*count)++] = make_rect (ra.x1, rb.y0, rb.x1, rb.y1); - } - if (ra.y1 < rb.y1) { - result[(*count)++] = make_rect (rb.x0, ra.y1, rb.x1, rb.y1); - } -} - -static void -diff_rects (Rect r1, Rect r2, int *count, Rect result[4]) -{ - g_assert (count != NULL); - g_assert (result != NULL); - - *count = 0; - - if (rects_intersect (r1, r2)) { - diff_rects_guts (r1, r2, count, result); - diff_rects_guts (r2, r1, count, result); - } else { - if (!rect_empty (&r1)) { - result[(*count)++] = r1; - } - if (!rect_empty (&r2)) { - result[(*count)++] = r2; - } - } -} diff --git a/eel/eel-canvas-rect-ellipse.h b/eel/eel-canvas-rect-ellipse.h deleted file mode 100644 index 0df2c9934..000000000 --- a/eel/eel-canvas-rect-ellipse.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ -/* Rectangle and ellipse item types for EelCanvas widget - * - * EelCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - */ - -#ifndef EEL_CANVAS_RECT_ELLIPSE_H -#define EEL_CANVAS_RECT_ELLIPSE_H - - -#include <eel/eel-canvas.h> - -G_BEGIN_DECLS - - -/* Base class for rectangle and ellipse item types. These are defined by their top-left and - * bottom-right corners. Rectangles and ellipses share the following arguments: - * - * name type read/write description - * ------------------------------------------------------------------------------------------ - * x1 double RW Leftmost coordinate of rectangle or ellipse - * y1 double RW Topmost coordinate of rectangle or ellipse - * x2 double RW Rightmost coordinate of rectangle or ellipse - * y2 double RW Bottommost coordinate of rectangle or ellipse - * fill_color string W X color specification for fill color, - * or NULL pointer for no color (transparent) - * fill_color_gdk GdkColor* RW Allocated GdkColor for fill - * outline_color string W X color specification for outline color, - * or NULL pointer for no color (transparent) - * outline_color_gdk GdkColor* RW Allocated GdkColor for outline - * fill_stipple GdkBitmap* RW Stipple pattern for fill - * outline_stipple GdkBitmap* RW Stipple pattern for outline - * width_pixels uint RW Width of the outline in pixels. The outline will - * not be scaled when the canvas zoom factor is changed. - * width_units double RW Width of the outline in canvas units. The outline - * will be scaled when the canvas zoom factor is changed. - */ - - -#define EEL_TYPE_CANVAS_RE (eel_canvas_re_get_type ()) -#define EEL_CANVAS_RE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_RE, EelCanvasRE)) -#define EEL_CANVAS_RE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_RE, EelCanvasREClass)) -#define EEL_IS_CANVAS_RE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_RE)) -#define EEL_IS_CANVAS_RE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_RE)) -#define EEL_CANVAS_RE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_RE, EelCanvasREClass)) - - -typedef struct _EelCanvasRE EelCanvasRE; -typedef struct _EelCanvasREClass EelCanvasREClass; - -struct _EelCanvasRE { - EelCanvasItem item; - - double x1, y1, x2, y2; /* Corners of item */ - double width; /* Outline width */ - - GdkRGBA fill_color; - GdkRGBA outline_color; - - gboolean outline_stippling; - - /* Configuration flags */ - - unsigned int fill_set : 1; /* Is fill color set? */ - unsigned int outline_set : 1; /* Is outline color set? */ - unsigned int width_pixels : 1; /* Is outline width specified in pixels or units? */ -}; - -struct _EelCanvasREClass { - EelCanvasItemClass parent_class; -}; - - -/* Standard Gtk function */ -GType eel_canvas_re_get_type (void) G_GNUC_CONST; - - -/* Rectangle item. No configurable or queryable arguments are available (use those in - * EelCanvasRE). - */ - - -#define EEL_TYPE_CANVAS_RECT (eel_canvas_rect_get_type ()) -#define EEL_CANVAS_RECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_RECT, EelCanvasRect)) -#define EEL_CANVAS_RECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_RECT, EelCanvasRectClass)) -#define EEL_IS_CANVAS_RECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_RECT)) -#define EEL_IS_CANVAS_RECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_RECT)) -#define EEL_CANVAS_RECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_RECT, EelCanvasRectClass)) - - -typedef struct _EelCanvasRect EelCanvasRect; -typedef struct _EelCanvasRectPrivate EelCanvasRectPrivate; -typedef struct _EelCanvasRectClass EelCanvasRectClass; - -struct _EelCanvasRect { - EelCanvasRE re; - EelCanvasRectPrivate *priv; -}; - -struct _EelCanvasRectClass { - EelCanvasREClass parent_class; -}; - - -/* Standard Gtk function */ -GType eel_canvas_rect_get_type (void) G_GNUC_CONST; - - -/* Ellipse item. No configurable or queryable arguments are available (use those in - * EelCanvasRE). - */ - - -#define EEL_TYPE_CANVAS_ELLIPSE (eel_canvas_ellipse_get_type ()) -#define EEL_CANVAS_ELLIPSE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_ELLIPSE, EelCanvasEllipse)) -#define EEL_CANVAS_ELLIPSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_ELLIPSE, EelCanvasEllipseClass)) -#define EEL_IS_CANVAS_ELLIPSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_ELLIPSE)) -#define EEL_IS_CANVAS_ELLIPSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_ELLIPSE)) -#define EEL_CANVAS_ELLIPSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_ELLIPSE, EelCanvasEllipseClass)) - - -typedef struct _EelCanvasEllipse EelCanvasEllipse; -typedef struct _EelCanvasEllipseClass EelCanvasEllipseClass; - -struct _EelCanvasEllipse { - EelCanvasRE re; -}; - -struct _EelCanvasEllipseClass { - EelCanvasREClass parent_class; -}; - - -/* Standard Gtk function */ -GType eel_canvas_ellipse_get_type (void) G_GNUC_CONST; - - -G_END_DECLS - -#endif diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index cee6fd2be..4312ffba4 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -146,6 +146,8 @@ libnautilus_private_la_SOURCES = \ nautilus-search-engine-simple.h \ nautilus-search-engine-tracker.c \ nautilus-search-engine-tracker.h \ + nautilus-selection-canvas-item.c \ + nautilus-selection-canvas-item.h \ nautilus-signaller.h \ nautilus-signaller.c \ nautilus-query.c \ diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c index 0bc057718..421b02bb2 100644 --- a/libnautilus-private/nautilus-icon-container.c +++ b/libnautilus-private/nautilus-icon-container.c @@ -32,6 +32,7 @@ #include "nautilus-global-preferences.h" #include "nautilus-icon-private.h" #include "nautilus-lib-self-check-functions.h" +#include "nautilus-selection-canvas-item.h" #include "nautilus-marshal.h" #include <atk/atkaction.h> #include <eel/eel-accessibility.h> @@ -39,7 +40,7 @@ #include <eel/eel-gtk-extensions.h> #include <eel/eel-art-extensions.h> #include <eel/eel-editable-label.h> -#include <eel/eel-canvas-rect-ellipse.h> + #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> #include <gdk/gdkx.h> @@ -2515,8 +2516,6 @@ rubberband_timeout_callback (gpointer data) band_info = &container->details->rubberband_info; g_assert (band_info->timer_id != 0); - g_assert (EEL_IS_CANVAS_RECT (band_info->selection_rectangle) || - EEL_IS_CANVAS_RECT (band_info->selection_rectangle)); adj_changed = FALSE; gtk_widget_get_allocation (widget, &allocation); @@ -2663,7 +2662,7 @@ start_rubberbanding (NautilusIconContainer *container, band_info->selection_rectangle = eel_canvas_item_new (eel_canvas_root (EEL_CANVAS (container)), - EEL_TYPE_CANVAS_RECT, + NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, "x1", band_info->start_x, "y1", band_info->start_y, "x2", band_info->start_x, diff --git a/libnautilus-private/nautilus-icon-dnd.c b/libnautilus-private/nautilus-icon-dnd.c index ee01a1237..3009709a8 100644 --- a/libnautilus-private/nautilus-icon-dnd.c +++ b/libnautilus-private/nautilus-icon-dnd.c @@ -39,6 +39,7 @@ #include "nautilus-icon-private.h" #include "nautilus-link.h" #include "nautilus-metadata.h" +#include "nautilus-selection-canvas-item.h" #include <eel/eel-glib-extensions.h> #include <eel/eel-gnome-extensions.h> #include <eel/eel-graphic-effects.h> @@ -51,7 +52,7 @@ #include <gdk/gdkx.h> #include <gtk/gtk.h> #include <glib/gi18n.h> -#include <eel/eel-canvas-rect-ellipse.h> + #include <libnautilus-private/nautilus-desktop-background.h> #include <libnautilus-private/nautilus-file-utilities.h> #include <libnautilus-private/nautilus-file-changes-queue.h> @@ -146,7 +147,7 @@ create_selection_shadow (NautilusIconContainer *container, if (x2 >= min_x && x1 <= max_x && y2 >= min_y && y1 <= max_y) eel_canvas_item_new (group, - eel_canvas_rect_get_type (), + NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, "x1", (double) x1, "y1", (double) y1, "x2", (double) x2, diff --git a/libnautilus-private/nautilus-selection-canvas-item.c b/libnautilus-private/nautilus-selection-canvas-item.c new file mode 100644 index 000000000..e821af52c --- /dev/null +++ b/libnautilus-private/nautilus-selection-canvas-item.c @@ -0,0 +1,708 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* Nautilus - Canvas item for rubberband selection. + * + * Copyright (C) 2000 Eazel, Inc. + * + * Author: Andy Hertzfeld <andy@eazel.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include "nautilus-selection-canvas-item.h" + +#include <math.h> + +#ifdef HAVE_RENDER +#include <gdk/gdkx.h> +#include <X11/extensions/Xrender.h> +#endif + +enum { + PROP_0, + PROP_X1, + PROP_Y1, + PROP_X2, + PROP_Y2, + PROP_FILL_COLOR_RGBA, + PROP_OUTLINE_COLOR_RGBA, + PROP_OUTLINE_STIPPLING, + PROP_WIDTH_PIXELS, + PROP_WIDTH_UNITS +}; + +typedef struct { + /*< public >*/ + int x0, y0, x1, y1; +} Rect; + +struct _NautilusSelectionCanvasItemDetails { + Rect last_update_rect; + Rect last_outline_update_rect; + int last_outline_update_width; + +#ifdef HAVE_RENDER + gboolean use_render; + XRenderPictFormat *format; +#endif + + double x1, y1, x2, y2; /* Corners of item */ + double width; /* Outline width */ + + GdkRGBA fill_color; + GdkRGBA outline_color; + + gboolean outline_stippling; + + /* Configuration flags */ + + unsigned int fill_set : 1; /* Is fill color set? */ + unsigned int outline_set : 1; /* Is outline color set? */ + unsigned int width_pixels : 1; /* Is outline width specified in pixels or units? */ +}; + +G_DEFINE_TYPE (NautilusSelectionCanvasItem, nautilus_selection_canvas_item, EEL_TYPE_CANVAS_ITEM); + +#define DASH_ON 0.8 +#define DASH_OFF 1.7 +static void +nautilus_selection_canvas_item_draw (EelCanvasItem *item, + cairo_t *cr, + cairo_region_t *region) +{ + NautilusSelectionCanvasItem *self; + double x1, y1, x2, y2; + int cx1, cy1, cx2, cy2; + double i2w_dx, i2w_dy; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (item); + + /* Get canvas pixel coordinates */ + i2w_dx = 0.0; + i2w_dy = 0.0; + eel_canvas_item_i2w (item, &i2w_dx, &i2w_dy); + + x1 = self->priv->x1 + i2w_dx; + y1 = self->priv->y1 + i2w_dy; + x2 = self->priv->x2 + i2w_dx; + y2 = self->priv->y2 + i2w_dy; + + eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); + eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); + + if (cx2 <= cx1 || cy2 <= cy1 ) { + return; + } + + cairo_save (cr); + + if (self->priv->fill_set) { + gdk_cairo_set_source_rgba (cr, &self->priv->fill_color); + cairo_rectangle (cr, + cx1, cy1, + cx2 - cx1 + 1, + cy2 - cy1 + 1); + cairo_fill (cr); + } + + if (self->priv->outline_set) { + gdk_cairo_set_source_rgba (cr, &self->priv->outline_color); + if (self->priv->width_pixels) { + cairo_set_line_width (cr, (int) self->priv->width); + } else { + cairo_set_line_width (cr, (int) (self->priv->width * item->canvas->pixels_per_unit + 0.5)); + } + + if (self->priv->outline_stippling) { + double dash[2] = { DASH_ON, DASH_OFF }; + + cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0); + } + + cairo_rectangle (cr, + cx1 + 0.5, cy1 + 0.5, + cx2 - cx1, + cy2 - cy1); + cairo_stroke (cr); + } + + cairo_restore (cr); +} + +static double +nautilus_selection_canvas_item_point (EelCanvasItem *item, + double x, + double y, + int cx, + int cy, + EelCanvasItem **actual_item) +{ + NautilusSelectionCanvasItem *self; + double x1, y1, x2, y2; + double hwidth; + double dx, dy; + double tmp; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (item); + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + x1 = self->priv->x1; + y1 = self->priv->y1; + x2 = self->priv->x2; + y2 = self->priv->y2; + + if (self->priv->outline_set) { + if (self->priv->width_pixels) + hwidth = (self->priv->width / item->canvas->pixels_per_unit) / 2.0; + else + hwidth = self->priv->width / 2.0; + + x1 -= hwidth; + y1 -= hwidth; + x2 += hwidth; + y2 += hwidth; + } else + hwidth = 0.0; + + /* Is point inside rectangle (which can be hollow if it has no fill set)? */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + if (self->priv->fill_set || !self->priv->outline_set) + return 0.0; + + dx = x - x1; + tmp = x2 - x; + if (tmp < dx) + dx = tmp; + + dy = y - y1; + tmp = y2 - y; + if (tmp < dy) + dy = tmp; + + if (dy < dx) + dx = dy; + + dx -= 2.0 * hwidth; + + if (dx < 0.0) + return 0.0; + else + return dx; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +} + +static void +request_redraw_borders (EelCanvas *canvas, + Rect *update_rect, + int width) +{ + eel_canvas_request_redraw (canvas, + update_rect->x0, update_rect->y0, + update_rect->x1, update_rect->y0 + width); + eel_canvas_request_redraw (canvas, + update_rect->x0, update_rect->y1-width, + update_rect->x1, update_rect->y1); + eel_canvas_request_redraw (canvas, + update_rect->x0, update_rect->y0, + update_rect->x0+width, update_rect->y1); + eel_canvas_request_redraw (canvas, + update_rect->x1-width, update_rect->y0, + update_rect->x1, update_rect->y1); +} + +static Rect make_rect (int x0, int y0, int x1, int y1); + +static int +rect_empty (const Rect *src) { + return (src->x1 <= src->x0 || src->y1 <= src->y0); +} + +static gboolean +rects_intersect (Rect r1, Rect r2) +{ + if (r1.x0 >= r2.x1) { + return FALSE; + } + if (r2.x0 >= r1.x1) { + return FALSE; + } + if (r1.y0 >= r2.y1) { + return FALSE; + } + if (r2.y0 >= r1.y1) { + return FALSE; + } + return TRUE; +} + +static void +diff_rects_guts (Rect ra, Rect rb, int *count, Rect result[4]) +{ + if (ra.x0 < rb.x0) { + result[(*count)++] = make_rect (ra.x0, ra.y0, rb.x0, ra.y1); + } + if (ra.y0 < rb.y0) { + result[(*count)++] = make_rect (ra.x0, ra.y0, ra.x1, rb.y0); + } + if (ra.x1 < rb.x1) { + result[(*count)++] = make_rect (ra.x1, rb.y0, rb.x1, rb.y1); + } + if (ra.y1 < rb.y1) { + result[(*count)++] = make_rect (rb.x0, ra.y1, rb.x1, rb.y1); + } +} + +static void +diff_rects (Rect r1, Rect r2, int *count, Rect result[4]) +{ + g_assert (count != NULL); + g_assert (result != NULL); + + *count = 0; + + if (rects_intersect (r1, r2)) { + diff_rects_guts (r1, r2, count, result); + diff_rects_guts (r2, r1, count, result); + } else { + if (!rect_empty (&r1)) { + result[(*count)++] = r1; + } + if (!rect_empty (&r2)) { + result[(*count)++] = r2; + } + } +} + +static Rect +make_rect (int x0, int y0, int x1, int y1) +{ + Rect r; + + r.x0 = x0; + r.y0 = y0; + r.x1 = x1; + r.y1 = y1; + return r; +} + +static void +nautilus_selection_canvas_item_update (EelCanvasItem *item, + double i2w_dx, + double i2w_dy, + gint flags) +{ + NautilusSelectionCanvasItem *self; + NautilusSelectionCanvasItemDetails *priv; + double x1, y1, x2, y2; + int cx1, cy1, cx2, cy2; + int repaint_rects_count, i; + int width_pixels; + int width_lt, width_rb; + Rect update_rect, repaint_rects[4]; + + if (EEL_CANVAS_ITEM_CLASS (nautilus_selection_canvas_item_parent_class)->update) + (* EEL_CANVAS_ITEM_CLASS (nautilus_selection_canvas_item_parent_class)->update) (item, i2w_dx, i2w_dy, flags); + + self = NAUTILUS_SELECTION_CANVAS_ITEM (item); + priv = self->priv; + + x1 = priv->x1 + i2w_dx; + y1 = priv->y1 + i2w_dy; + x2 = priv->x2 + i2w_dx; + y2 = priv->y2 + i2w_dy; + + eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); + eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); + + update_rect = make_rect (cx1, cy1, cx2+1, cy2+1); + diff_rects (update_rect, priv->last_update_rect, + &repaint_rects_count, repaint_rects); + for (i = 0; i < repaint_rects_count; i++) { + eel_canvas_request_redraw (item->canvas, + repaint_rects[i].x0, repaint_rects[i].y0, + repaint_rects[i].x1, repaint_rects[i].y1); + } + + priv->last_update_rect = update_rect; + + if (priv->outline_set) { + /* Outline and bounding box */ + if (priv->width_pixels) + width_pixels = (int) priv->width; + else + width_pixels = (int) floor (priv->width * item->canvas->pixels_per_unit + 0.5); + + width_lt = width_pixels / 2; + width_rb = (width_pixels + 1) / 2; + + cx1 -= width_lt; + cy1 -= width_lt; + cx2 += width_rb; + cy2 += width_rb; + + update_rect = make_rect (cx1, cy1, cx2, cy2); + request_redraw_borders (item->canvas, &update_rect, + (width_lt + width_rb)); + request_redraw_borders (item->canvas, &priv->last_outline_update_rect, + priv->last_outline_update_width); + priv->last_outline_update_rect = update_rect; + priv->last_outline_update_width = width_lt + width_rb; + + item->x1 = cx1; + item->y1 = cy1; + item->x2 = cx2+1; + item->y2 = cy2+1; + } else { + item->x1 = cx1; + item->y1 = cy1; + item->x2 = cx2+1; + item->y2 = cy2+1; + } +} + +static void +nautilus_selection_canvas_item_realize (EelCanvasItem *item) +{ +#ifdef HAVE_RENDER + NautilusSelectionCanvasItemDetails *priv; + int event_base, error_base; + Display *dpy; + + priv = NAUTILUS_SELECTION_CANVAS_ITEM (item)->priv; + + dpy = GDK_WINDOW_XDISPLAY (gtk_widget_get_window (GTK_WIDGET (item->canvas))); + priv->use_render = XRenderQueryExtension (dpy, &event_base, &error_base); + + if (priv->use_render) { + GdkVisual *gdk_visual; + Visual *visual; + + gdk_visual = gtk_widget_get_visual (GTK_WIDGET (item->canvas)); + visual = gdk_x11_visual_get_xvisual (gdk_visual); + + priv->format = XRenderFindVisualFormat (dpy, visual); + } +#endif + + if (EEL_CANVAS_ITEM_CLASS (nautilus_selection_canvas_item_parent_class)->realize) { + (* EEL_CANVAS_ITEM_CLASS (nautilus_selection_canvas_item_parent_class)->realize) (item); + } +} + +static void +nautilus_selection_canvas_item_translate (EelCanvasItem *item, + double dx, + double dy) +{ + NautilusSelectionCanvasItem *self; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (item); + + self->priv->x1 += dx; + self->priv->y1 += dy; + self->priv->x2 += dx; + self->priv->y2 += dy; +} + +static void +nautilus_selection_canvas_item_bounds (EelCanvasItem *item, + double *x1, + double *y1, + double *x2, + double *y2) +{ + NautilusSelectionCanvasItem *self; + double hwidth; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (item); + + if (self->priv->width_pixels) + hwidth = (self->priv->width / item->canvas->pixels_per_unit) / 2.0; + else + hwidth = self->priv->width / 2.0; + + *x1 = self->priv->x1 - hwidth; + *y1 = self->priv->y1 - hwidth; + *x2 = self->priv->x2 + hwidth; + *y2 = self->priv->y2 + hwidth; +} + +static void +do_set_fill (NautilusSelectionCanvasItem *self, + gboolean fill_set) +{ + if (self->priv->fill_set != fill_set) { + self->priv->fill_set = fill_set; + eel_canvas_item_request_update (EEL_CANVAS_ITEM (self)); + } +} + +static void +do_set_outline (NautilusSelectionCanvasItem *self, + gboolean outline_set) +{ + if (self->priv->outline_set != outline_set) { + self->priv->outline_set = outline_set; + eel_canvas_item_request_update (EEL_CANVAS_ITEM (self)); + } +} + +static void +nautilus_selection_canvas_item_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + EelCanvasItem *item; + NautilusSelectionCanvasItem *self; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (object); + item = EEL_CANVAS_ITEM (object); + + switch (param_id) { + case PROP_X1: + self->priv->x1 = g_value_get_double (value); + + eel_canvas_item_request_update (item); + break; + + case PROP_Y1: + self->priv->y1 = g_value_get_double (value); + + eel_canvas_item_request_update (item); + break; + + case PROP_X2: + self->priv->x2 = g_value_get_double (value); + + eel_canvas_item_request_update (item); + break; + + case PROP_Y2: + self->priv->y2 = g_value_get_double (value); + + eel_canvas_item_request_update (item); + break; + + case PROP_FILL_COLOR_RGBA: { + GdkRGBA *color; + + color = g_value_get_boxed (value); + + do_set_fill (self, color != NULL); + + if (color != NULL) { + self->priv->fill_color = *color; + } + + eel_canvas_item_request_redraw (item); + break; + } + + case PROP_OUTLINE_COLOR_RGBA: { + GdkRGBA *color; + + color = g_value_get_boxed (value); + + do_set_outline (self, color != NULL); + + if (color != NULL) { + self->priv->outline_color = *color; + } + + eel_canvas_item_request_redraw (item); + break; + } + + case PROP_OUTLINE_STIPPLING: + self->priv->outline_stippling = g_value_get_boolean (value); + + eel_canvas_item_request_redraw (item); + break; + + case PROP_WIDTH_PIXELS: + self->priv->width = g_value_get_uint (value); + self->priv->width_pixels = TRUE; + + eel_canvas_item_request_update (item); + break; + + case PROP_WIDTH_UNITS: + self->priv->width = fabs (g_value_get_double (value)); + self->priv->width_pixels = FALSE; + + eel_canvas_item_request_update (item); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +nautilus_selection_canvas_item_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + NautilusSelectionCanvasItem *self; + + self = NAUTILUS_SELECTION_CANVAS_ITEM (object); + + switch (param_id) { + case PROP_X1: + g_value_set_double (value, self->priv->x1); + break; + + case PROP_Y1: + g_value_set_double (value, self->priv->y1); + break; + + case PROP_X2: + g_value_set_double (value, self->priv->x2); + break; + + case PROP_Y2: + g_value_set_double (value, self->priv->y2); + break; + + case PROP_FILL_COLOR_RGBA: + g_value_set_boxed (value, &self->priv->fill_color); + break; + + case PROP_OUTLINE_COLOR_RGBA: + g_value_set_boxed (value, &self->priv->outline_color); + break; + + case PROP_OUTLINE_STIPPLING: + g_value_set_boolean (value, self->priv->outline_stippling); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +nautilus_selection_canvas_item_class_init (NautilusSelectionCanvasItemClass *klass) +{ + EelCanvasItemClass *item_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + item_class = EEL_CANVAS_ITEM_CLASS (klass); + + gobject_class->set_property = nautilus_selection_canvas_item_set_property; + gobject_class->get_property = nautilus_selection_canvas_item_get_property; + + item_class->draw = nautilus_selection_canvas_item_draw; + item_class->point = nautilus_selection_canvas_item_point; + item_class->update = nautilus_selection_canvas_item_update; + item_class->realize = nautilus_selection_canvas_item_realize; + item_class->bounds = nautilus_selection_canvas_item_bounds; + item_class->translate = nautilus_selection_canvas_item_translate; + + g_object_class_install_property + (gobject_class, + PROP_X1, + g_param_spec_double ("x1", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_Y1, + g_param_spec_double ("y1", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_X2, + g_param_spec_double ("x2", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_Y2, + g_param_spec_double ("y2", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_FILL_COLOR_RGBA, + g_param_spec_boxed ("fill-color-rgba", NULL, NULL, + GDK_TYPE_RGBA, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_OUTLINE_COLOR_RGBA, + g_param_spec_boxed ("outline-color-rgba", NULL, NULL, + GDK_TYPE_RGBA, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_OUTLINE_STIPPLING, + g_param_spec_boolean ("outline-stippling", NULL, NULL, + FALSE, G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_WIDTH_PIXELS, + g_param_spec_uint ("width-pixels", NULL, NULL, + 0, G_MAXUINT, 0, + G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_WIDTH_UNITS, + g_param_spec_double ("width-units", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (NautilusSelectionCanvasItemDetails)); +} + +static void +nautilus_selection_canvas_item_init (NautilusSelectionCanvasItem *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, + NautilusSelectionCanvasItemDetails); +} + + + diff --git a/libnautilus-private/nautilus-selection-canvas-item.h b/libnautilus-private/nautilus-selection-canvas-item.h new file mode 100644 index 000000000..889a3737b --- /dev/null +++ b/libnautilus-private/nautilus-selection-canvas-item.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* Nautilus - Canvas item for rubberband selection. + * + * Copyright (C) 2000 Eazel, Inc. + * + * Author: Andy Hertzfeld <andy@eazel.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __NAUTILUS_SELECTION_CANVAS_ITEM_H__ +#define __NAUTILUS_SELECTION_CANVAS_ITEM_H__ + +#include <eel/eel-canvas.h> + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_SELECTION_CANVAS_ITEM nautilus_selection_canvas_item_get_type() +#define NAUTILUS_SELECTION_CANVAS_ITEM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, NautilusSelectionCanvasItem)) +#define NAUTILUS_SELECTION_CANVAS_ITEM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, NautilusSelectionCanvasItemClass)) +#define NAUTILUS_IS_SELECTION_CANVAS_ITEM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_SELECTION_CANVAS_ITEM)) +#define NAUTILUS_IS_SELECTION_CANVAS_ITEM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_SELECTION_CANVAS_ITEM)) +#define NAUTILUS_SELECTION_CANVAS_ITEM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_SELECTION_CANVAS_ITEM, NautilusSelectionCanvasItemClass)) + +typedef struct _NautilusSelectionCanvasItem NautilusSelectionCanvasItem; +typedef struct _NautilusSelectionCanvasItemClass NautilusSelectionCanvasItemClass; +typedef struct _NautilusSelectionCanvasItemDetails NautilusSelectionCanvasItemDetails; + +struct _NautilusSelectionCanvasItem { + EelCanvasItem item; + NautilusSelectionCanvasItemDetails *priv; + gpointer user_data; +}; + +struct _NautilusSelectionCanvasItemClass { + EelCanvasItemClass parent_class; +}; + +/* GObject */ +GType nautilus_selection_canvas_item_get_type (void); + +G_END_DECLS + +#endif /* __NAUTILUS_SELECTION_CANVAS_ITEM_H__ */ |