diff --git a/app/display/Makefile.am b/app/display/Makefile.am index acb2a8493bf99aee1fb35391dfe8c35a0a54344e..ecac2b1a86efd2b76db1add2d5a3b6592a2fe9ed 100644 --- a/app/display/Makefile.am +++ b/app/display/Makefile.am @@ -25,6 +25,8 @@ libappdisplay_a_sources = \ gimpcanvasboundary.h \ gimpcanvascorner.c \ gimpcanvascorner.h \ + gimpcanvascursor.c \ + gimpcanvascursor.h \ gimpcanvasgrid.c \ gimpcanvasgrid.h \ gimpcanvasgroup.c \ diff --git a/app/display/gimpcanvascursor.c b/app/display/gimpcanvascursor.c new file mode 100644 index 0000000000000000000000000000000000000000..6386c1cdde0a3ec18debb813c367269d60c5174d --- /dev/null +++ b/app/display/gimpcanvascursor.c @@ -0,0 +1,235 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcanvascursor.c + * Copyright (C) 2010 Michael Natterer + * + * 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 3 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, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpmath/gimpmath.h" + +#include "display-types.h" + +#include "widgets/gimpcairo.h" + +#include "gimpcanvascursor.h" +#include "gimpdisplayshell.h" +#include "gimpdisplayshell-transform.h" + + +#define GIMP_CURSOR_SIZE 7 + + +enum +{ + PROP_0, + PROP_X, + PROP_Y +}; + + +typedef struct _GimpCanvasCursorPrivate GimpCanvasCursorPrivate; + +struct _GimpCanvasCursorPrivate +{ + gdouble x; + gdouble y; +}; + +#define GET_PRIVATE(cursor) \ + G_TYPE_INSTANCE_GET_PRIVATE (cursor, \ + GIMP_TYPE_CANVAS_CURSOR, \ + GimpCanvasCursorPrivate) + + +/* local function prototypes */ + +static void gimp_canvas_cursor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_canvas_cursor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_canvas_cursor_draw (GimpCanvasItem *item, + GimpDisplayShell *shell, + cairo_t *cr); +static GdkRegion * gimp_canvas_cursor_get_extents (GimpCanvasItem *item, + GimpDisplayShell *shell); + + +G_DEFINE_TYPE (GimpCanvasCursor, gimp_canvas_cursor, + GIMP_TYPE_CANVAS_ITEM) + +#define parent_class gimp_canvas_cursor_parent_class + + +static void +gimp_canvas_cursor_class_init (GimpCanvasCursorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpCanvasItemClass *item_class = GIMP_CANVAS_ITEM_CLASS (klass); + + object_class->set_property = gimp_canvas_cursor_set_property; + object_class->get_property = gimp_canvas_cursor_get_property; + + item_class->draw = gimp_canvas_cursor_draw; + item_class->get_extents = gimp_canvas_cursor_get_extents; + + g_object_class_install_property (object_class, PROP_X, + g_param_spec_double ("x", NULL, NULL, + -GIMP_MAX_IMAGE_SIZE, + GIMP_MAX_IMAGE_SIZE, 0, + GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_Y, + g_param_spec_double ("y", NULL, NULL, + -GIMP_MAX_IMAGE_SIZE, + GIMP_MAX_IMAGE_SIZE, 0, + GIMP_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GimpCanvasCursorPrivate)); +} + +static void +gimp_canvas_cursor_init (GimpCanvasCursor *cursor) +{ + gimp_canvas_item_set_line_cap (GIMP_CANVAS_ITEM (cursor), + CAIRO_LINE_CAP_SQUARE); +} + +static void +gimp_canvas_cursor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpCanvasCursorPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_X: + private->x = g_value_get_double (value); + break; + case PROP_Y: + private->y = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_canvas_cursor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpCanvasCursorPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_X: + g_value_set_double (value, private->x); + break; + case PROP_Y: + g_value_set_double (value, private->y); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_canvas_cursor_draw (GimpCanvasItem *item, + GimpDisplayShell *shell, + cairo_t *cr) +{ + GimpCanvasCursorPrivate *private = GET_PRIVATE (item); + gdouble x, y; + + x = floor (private->x) + 0.5; + y = floor (private->y) + 0.5; + + cairo_move_to (cr, x - GIMP_CURSOR_SIZE, y); + cairo_line_to (cr, x + GIMP_CURSOR_SIZE, y); + + cairo_move_to (cr, x, y - GIMP_CURSOR_SIZE); + cairo_line_to (cr, x, y + GIMP_CURSOR_SIZE); + + _gimp_canvas_item_stroke (item, cr); +} + +static GdkRegion * +gimp_canvas_cursor_get_extents (GimpCanvasItem *item, + GimpDisplayShell *shell) +{ + GimpCanvasCursorPrivate *private = GET_PRIVATE (item); + GdkRectangle rectangle; + gdouble x, y; + + x = floor (private->x) + 0.5; + y = floor (private->y) + 0.5; + + rectangle.x = floor (x - GIMP_CURSOR_SIZE - 1.5); + rectangle.y = floor (y - GIMP_CURSOR_SIZE - 1.5); + rectangle.width = ceil (x + GIMP_CURSOR_SIZE + 1.5) - rectangle.x; + rectangle.height = ceil (y + GIMP_CURSOR_SIZE + 1.5) - rectangle.y; + + return gdk_region_rectangle (&rectangle); +} + +GimpCanvasItem * +gimp_canvas_cursor_new (GimpDisplayShell *shell) +{ + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); + + return g_object_new (GIMP_TYPE_CANVAS_CURSOR, + "shell", shell, + NULL); +} + +void +gimp_canvas_cursor_set_coords (GimpCanvasCursor *cursor, + gdouble x, + gdouble y) +{ + GimpCanvasCursorPrivate *private; + + g_return_if_fail (GIMP_IS_CANVAS_CURSOR (cursor)); + + private = GET_PRIVATE (cursor); + + if (private->x != x || private->y != y) + { + gimp_canvas_item_begin_change (GIMP_CANVAS_ITEM (cursor)); + g_object_set (cursor, + "x", x, + "y", y, + NULL); + gimp_canvas_item_end_change (GIMP_CANVAS_ITEM (cursor)); + } +} diff --git a/app/display/gimpcanvascursor.h b/app/display/gimpcanvascursor.h new file mode 100644 index 0000000000000000000000000000000000000000..aacf9ee74f004f1627b7c0bcf033a1754f6a8690 --- /dev/null +++ b/app/display/gimpcanvascursor.h @@ -0,0 +1,59 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcanvascursor.h + * Copyright (C) 2010 Michael Natterer + * + * 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 3 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, see . + */ + +#ifndef __GIMP_CANVAS_CURSOR_H__ +#define __GIMP_CANVAS_CURSOR_H__ + + +#include "gimpcanvasitem.h" + + +#define GIMP_TYPE_CANVAS_CURSOR (gimp_canvas_cursor_get_type ()) +#define GIMP_CANVAS_CURSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CANVAS_CURSOR, GimpCanvasCursor)) +#define GIMP_CANVAS_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CANVAS_CURSOR, GimpCanvasCursorClass)) +#define GIMP_IS_CANVAS_CURSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CANVAS_CURSOR)) +#define GIMP_IS_CANVAS_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CANVAS_CURSOR)) +#define GIMP_CANVAS_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_CURSOR, GimpCanvasCursorClass)) + + +typedef struct _GimpCanvasCursor GimpCanvasCursor; +typedef struct _GimpCanvasCursorClass GimpCanvasCursorClass; + +struct _GimpCanvasCursor +{ + GimpCanvasItem parent_instance; +}; + +struct _GimpCanvasCursorClass +{ + GimpCanvasItemClass parent_class; +}; + + +GType gimp_canvas_cursor_get_type (void) G_GNUC_CONST; + +GimpCanvasItem * gimp_canvas_cursor_new (GimpDisplayShell *shell); + +void gimp_canvas_cursor_set_coords (GimpCanvasCursor *cursor, + gdouble x, + gdouble y); + + +#endif /* __GIMP_CANVAS_CURSOR_H__ */ diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index f8ba60c8eb707c216fb153e64632a75755549201..fff22f6cf3b0cb54d5b9e62972f7e401be03bd45 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -2340,11 +2340,6 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell, gimp_canvas_item_draw (shell->canvas_item, cr); cairo_restore (cr); - /* and the cursor (if we have a software cursor) */ - cairo_save (cr); - gimp_display_shell_draw_cursor (shell, cr); - cairo_restore (cr); - /* restart (and recalculate) the selection boundaries */ gimp_display_shell_selection_control (shell, GIMP_SELECTION_ON); } diff --git a/app/display/gimpdisplayshell-cursor.c b/app/display/gimpdisplayshell-cursor.c index 30544a76cdec3ba69fb1303b0ebaa9ddf5215f85..d3346499f4fcc8b4f621908f1b982e63e80bb8d0 100644 --- a/app/display/gimpdisplayshell-cursor.c +++ b/app/display/gimpdisplayshell-cursor.c @@ -31,11 +31,11 @@ #include "widgets/gimpdialogfactory.h" #include "widgets/gimpsessioninfo.h" +#include "gimpcanvascursor.h" #include "gimpdisplay.h" #include "gimpcursorview.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-cursor.h" -#include "gimpdisplayshell-expose.h" #include "gimpdisplayshell-transform.h" #include "gimpstatusbar.h" @@ -125,44 +125,31 @@ gimp_display_shell_update_cursor (GimpDisplayShell *shell, gdouble image_x, gdouble image_y) { - GimpStatusbar *statusbar; - GimpSessionInfo *session_info; - GimpImage *image; - gboolean new_cursor; + GimpStatusbar *statusbar; + GimpSessionInfo *session_info; + GimpImage *image; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); image = gimp_display_get_image (shell->display); - new_cursor = (shell->draw_cursor && - shell->proximity && - display_x >= 0 && - display_y >= 0); - - /* Erase old cursor, if necessary */ - - if (shell->have_cursor && (! new_cursor || - display_x != shell->cursor_x || - display_y != shell->cursor_y)) + if (shell->draw_cursor && + shell->proximity && + display_x >= 0 && + display_y >= 0) { - gimp_display_shell_expose_area (shell, - shell->cursor_x - GIMP_CURSOR_SIZE, - shell->cursor_y - GIMP_CURSOR_SIZE, - 2 * GIMP_CURSOR_SIZE + 1, - 2 * GIMP_CURSOR_SIZE + 1); - } + gimp_canvas_item_begin_change (shell->cursor); - shell->have_cursor = new_cursor; - shell->cursor_x = display_x; - shell->cursor_y = display_y; + gimp_canvas_cursor_set_coords (GIMP_CANVAS_CURSOR (shell->cursor), + display_x, + display_y); + gimp_canvas_item_set_visible (shell->cursor, TRUE); - if (shell->have_cursor) + gimp_canvas_item_end_change (shell->cursor); + } + else { - gimp_display_shell_expose_area (shell, - shell->cursor_x - GIMP_CURSOR_SIZE, - shell->cursor_y - GIMP_CURSOR_SIZE, - 2 * GIMP_CURSOR_SIZE + 1, - 2 * GIMP_CURSOR_SIZE + 1); + gimp_canvas_item_set_visible (shell->cursor, FALSE); } /* use the passed image_coords for the statusbar because they are @@ -205,6 +192,8 @@ gimp_display_shell_clear_cursor (GimpDisplayShell *shell) g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + gimp_canvas_item_set_visible (shell->cursor, FALSE); + statusbar = gimp_display_shell_get_statusbar (shell); gimp_statusbar_clear_cursor (statusbar); diff --git a/app/display/gimpdisplayshell-cursor.h b/app/display/gimpdisplayshell-cursor.h index eeef566f6fe2f25a7ae3402d40000e1a1bd42641..18bf8716db7d6c6e29b6d7297c5d5489dd9dca8d 100644 --- a/app/display/gimpdisplayshell-cursor.h +++ b/app/display/gimpdisplayshell-cursor.h @@ -19,9 +19,6 @@ #define __GIMP_DISPLAY_SHELL_CURSOR_H__ -#define GIMP_CURSOR_SIZE 7 - - void gimp_display_shell_set_cursor (GimpDisplayShell *shell, GimpCursorType cursor_type, GimpToolCursorType tool_cursor, diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 6cf4ca7b8a7b413b80b5b97f46a7fa02521043c8..362e0ad695a5a955ffd2089f85521d5a65141795 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -44,7 +44,6 @@ #include "gimpdisplay.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-appearance.h" -#include "gimpdisplayshell-cursor.h" #include "gimpdisplayshell-draw.h" #include "gimpdisplayshell-render.h" #include "gimpdisplayshell-scale.h" @@ -289,54 +288,6 @@ gimp_display_shell_draw_vectors (GimpDisplayShell *shell, } } -void -gimp_display_shell_draw_cursor (GimpDisplayShell *shell, - cairo_t *cr) -{ - g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); - g_return_if_fail (cr != NULL); - - if (shell->have_cursor) - { - gimp_display_shell_set_cursor_style (shell, cr); - cairo_translate (cr, 0.5, 0.5); - - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - - cairo_move_to (cr, - shell->cursor_x - GIMP_CURSOR_SIZE, shell->cursor_y - 1); - cairo_line_to (cr, - shell->cursor_x + GIMP_CURSOR_SIZE, shell->cursor_y - 1); - - cairo_move_to (cr, - shell->cursor_x - GIMP_CURSOR_SIZE, shell->cursor_y + 1); - cairo_line_to (cr, - shell->cursor_x + GIMP_CURSOR_SIZE, shell->cursor_y + 1); - - cairo_move_to (cr, - shell->cursor_x - 1, shell->cursor_y - GIMP_CURSOR_SIZE); - cairo_line_to (cr, - shell->cursor_x - 1, shell->cursor_y + GIMP_CURSOR_SIZE); - - cairo_move_to (cr, - shell->cursor_x + 1, shell->cursor_y - GIMP_CURSOR_SIZE); - cairo_line_to (cr, - shell->cursor_x + 1, shell->cursor_y + GIMP_CURSOR_SIZE); - - cairo_stroke (cr); - - cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); - - cairo_move_to (cr, shell->cursor_x - GIMP_CURSOR_SIZE, shell->cursor_y); - cairo_line_to (cr, shell->cursor_x + GIMP_CURSOR_SIZE, shell->cursor_y); - - cairo_move_to (cr, shell->cursor_x, shell->cursor_y - GIMP_CURSOR_SIZE); - cairo_line_to (cr, shell->cursor_x, shell->cursor_y + GIMP_CURSOR_SIZE); - - cairo_stroke (cr); - } -} - void gimp_display_shell_draw_image (GimpDisplayShell *shell, cairo_t *cr, diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h index 8f6ef7f7f4ab70cd8958e3aa86b1c774d726bbf6..e328b7962658defe3b1a92abc00d0d14c4a4bc5b 100644 --- a/app/display/gimpdisplayshell-draw.h +++ b/app/display/gimpdisplayshell-draw.h @@ -50,8 +50,6 @@ void gimp_display_shell_draw_selection_in (GimpDisplayShell *shell, gint index); void gimp_display_shell_draw_vectors (GimpDisplayShell *shell, cairo_t *cr); -void gimp_display_shell_draw_cursor (GimpDisplayShell *shell, - cairo_t *cr); void gimp_display_shell_draw_image (GimpDisplayShell *shell, cairo_t *cr, gint x, diff --git a/app/display/gimpdisplayshell-items.c b/app/display/gimpdisplayshell-items.c index 6b4f488a4c5b5f8979d7661536c9ffc5c783906e..15d50417c65a149b32124bf1692e10873d2b96d7 100644 --- a/app/display/gimpdisplayshell-items.c +++ b/app/display/gimpdisplayshell-items.c @@ -24,6 +24,7 @@ #include "display-types.h" +#include "gimpcanvascursor.h" #include "gimpcanvasgrid.h" #include "gimpcanvasproxygroup.h" #include "gimpdisplayshell.h" @@ -60,6 +61,11 @@ gimp_display_shell_items_init (GimpDisplayShell *shell) gimp_display_shell_add_item (shell, shell->sample_points); g_object_unref (shell->sample_points); + shell->cursor = gimp_canvas_cursor_new (shell); + gimp_canvas_item_set_visible (shell->cursor, FALSE); + gimp_display_shell_add_item (shell, shell->cursor); + g_object_unref (shell->cursor); + g_signal_connect (shell->canvas_item, "update", G_CALLBACK (gimp_display_shell_item_update), shell); @@ -82,6 +88,7 @@ gimp_display_shell_items_free (GimpDisplayShell *shell) shell->grid = NULL; shell->guides = NULL; shell->sample_points = NULL; + shell->cursor = NULL; } } diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h index e72cb6a1eb695483b7618db29fb6e80233a54d06..7edab2118d6a6c6237898290fa4d464267ff95e7 100644 --- a/app/display/gimpdisplayshell.h +++ b/app/display/gimpdisplayshell.h @@ -139,6 +139,7 @@ struct _GimpDisplayShell GimpCanvasItem *grid; /* item proxy of the grid */ GimpCanvasItem *guides; /* item proxies of guides */ GimpCanvasItem *sample_points; /* item proxies of sample points */ + GimpCanvasItem *cursor; /* item for the software cursor */ guint title_idle_id; /* title update idle ID */ gchar *title; /* current title */ @@ -158,9 +159,6 @@ struct _GimpDisplayShell GimpCursorType override_cursor; /* Overriding cursor */ gboolean using_override_cursor; gboolean draw_cursor; /* should we draw software cursor ? */ - gboolean have_cursor; /* is cursor currently drawn ? */ - gint cursor_x; /* software cursor X value */ - gint cursor_y; /* software cursor Y value */ GtkWidget *close_dialog; /* close dialog */ GtkWidget *scale_dialog; /* scale (zoom) dialog */