Commit 1d45f629 authored by Michael Natterer's avatar Michael Natterer 😴

app: add a software cursor canvas item

and use it to draw the sw cursor. Almost every aspect of the old code
was ugly and hard to read, this is so much nicer...
parent cfa17dc7
......@@ -25,6 +25,8 @@ libappdisplay_a_sources = \
gimpcanvasboundary.h \
gimpcanvascorner.c \
gimpcanvascorner.h \
gimpcanvascursor.c \
gimpcanvascursor.h \
gimpcanvasgrid.c \
gimpcanvasgrid.h \
gimpcanvasgroup.c \
......
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpcanvascursor.c
* Copyright (C) 2010 Michael Natterer <mitch@gimp.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#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));
}
}
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpcanvascursor.h
* Copyright (C) 2010 Michael Natterer <mitch@gimp.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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__ */
......@@ -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);
}
......
......@@ -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);
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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;
}
}
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment