summaryrefslogtreecommitdiffstats
path: root/app/display/gimptoolwidget.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--app/display/gimptoolwidget.c1117
1 files changed, 1117 insertions, 0 deletions
diff --git a/app/display/gimptoolwidget.c b/app/display/gimptoolwidget.c
new file mode 100644
index 0000000..516f366
--- /dev/null
+++ b/app/display/gimptoolwidget.c
@@ -0,0 +1,1117 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptoolwidget.c
+ * Copyright (C) 2017 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "display-types.h"
+
+#include "core/gimpmarshal.h"
+
+#include "gimpcanvasarc.h"
+#include "gimpcanvascorner.h"
+#include "gimpcanvasgroup.h"
+#include "gimpcanvashandle.h"
+#include "gimpcanvaslimit.h"
+#include "gimpcanvasline.h"
+#include "gimpcanvaspath.h"
+#include "gimpcanvaspolygon.h"
+#include "gimpcanvasrectangle.h"
+#include "gimpcanvasrectangleguides.h"
+#include "gimpcanvastransformguides.h"
+#include "gimpdisplayshell.h"
+#include "gimptoolwidget.h"
+
+
+enum
+{
+ PROP_0,
+ PROP_SHELL,
+ PROP_ITEM
+};
+
+enum
+{
+ CHANGED,
+ RESPONSE,
+ SNAP_OFFSETS,
+ STATUS,
+ STATUS_COORDS,
+ MESSAGE,
+ FOCUS_CHANGED,
+ LAST_SIGNAL
+};
+
+struct _GimpToolWidgetPrivate
+{
+ GimpDisplayShell *shell;
+ GimpCanvasItem *item;
+ GList *group_stack;
+
+ gint snap_offset_x;
+ gint snap_offset_y;
+ gint snap_width;
+ gint snap_height;
+
+ gboolean visible;
+ gboolean focus;
+};
+
+
+/* local function prototypes */
+
+static void gimp_tool_widget_finalize (GObject *object);
+static void gimp_tool_widget_constructed (GObject *object);
+static void gimp_tool_widget_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_tool_widget_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gimp_tool_widget_properties_changed (GObject *object,
+ guint n_pspecs,
+ GParamSpec **pspecs);
+
+static void gimp_tool_widget_real_leave_notify (GimpToolWidget *widget);
+static gboolean gimp_tool_widget_real_key_press (GimpToolWidget *widget,
+ GdkEventKey *kevent);
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpToolWidget, gimp_tool_widget, GIMP_TYPE_OBJECT)
+
+#define parent_class gimp_tool_widget_parent_class
+
+static guint widget_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gimp_tool_widget_class_init (GimpToolWidgetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gimp_tool_widget_finalize;
+ object_class->constructed = gimp_tool_widget_constructed;
+ object_class->set_property = gimp_tool_widget_set_property;
+ object_class->get_property = gimp_tool_widget_get_property;
+ object_class->dispatch_properties_changed = gimp_tool_widget_properties_changed;
+
+ klass->leave_notify = gimp_tool_widget_real_leave_notify;
+ klass->key_press = gimp_tool_widget_real_key_press;
+
+ widget_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ widget_signals[RESPONSE] =
+ g_signal_new ("response",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, response),
+ NULL, NULL,
+ gimp_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+
+ widget_signals[SNAP_OFFSETS] =
+ g_signal_new ("snap-offsets",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, snap_offsets),
+ NULL, NULL,
+ gimp_marshal_VOID__INT_INT_INT_INT,
+ G_TYPE_NONE, 4,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ widget_signals[STATUS] =
+ g_signal_new ("status",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, status),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ widget_signals[STATUS_COORDS] =
+ g_signal_new ("status-coords",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, status_coords),
+ NULL, NULL,
+ gimp_marshal_VOID__STRING_DOUBLE_STRING_DOUBLE_STRING,
+ G_TYPE_NONE, 5,
+ G_TYPE_STRING,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING);
+
+ widget_signals[MESSAGE] =
+ g_signal_new ("message",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, message),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ widget_signals[FOCUS_CHANGED] =
+ g_signal_new ("focus-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpToolWidgetClass, focus_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (object_class, PROP_SHELL,
+ g_param_spec_object ("shell",
+ NULL, NULL,
+ GIMP_TYPE_DISPLAY_SHELL,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_ITEM,
+ g_param_spec_object ("item",
+ NULL, NULL,
+ GIMP_TYPE_CANVAS_ITEM,
+ GIMP_PARAM_READABLE));
+}
+
+static void
+gimp_tool_widget_init (GimpToolWidget *widget)
+{
+ widget->private = gimp_tool_widget_get_instance_private (widget);
+
+ widget->private->visible = TRUE;
+}
+
+static void
+gimp_tool_widget_constructed (GObject *object)
+{
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+ GimpToolWidgetPrivate *private = widget->private;
+ GimpToolWidgetClass *klass = GIMP_TOOL_WIDGET_GET_CLASS (widget);
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ gimp_assert (GIMP_IS_DISPLAY_SHELL (private->shell));
+
+ private->item = gimp_canvas_group_new (private->shell);
+
+ gimp_canvas_item_set_visible (private->item, private->visible);
+
+ if (klass->changed)
+ {
+ if (klass->update_on_scale)
+ {
+ g_signal_connect_object (private->shell, "scaled",
+ G_CALLBACK (klass->changed),
+ widget,
+ G_CONNECT_SWAPPED);
+ }
+
+ if (klass->update_on_scroll)
+ {
+ g_signal_connect_object (private->shell, "scrolled",
+ G_CALLBACK (klass->changed),
+ widget,
+ G_CONNECT_SWAPPED);
+ }
+
+ if (klass->update_on_rotate)
+ {
+ g_signal_connect_object (private->shell, "rotated",
+ G_CALLBACK (klass->changed),
+ widget,
+ G_CONNECT_SWAPPED);
+ }
+ }
+}
+
+static void
+gimp_tool_widget_finalize (GObject *object)
+{
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+ GimpToolWidgetPrivate *private = widget->private;
+
+ g_clear_object (&private->item);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_tool_widget_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+ GimpToolWidgetPrivate *private = widget->private;
+
+ switch (property_id)
+ {
+ case PROP_SHELL:
+ private->shell = g_value_get_object (value); /* don't ref */
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_tool_widget_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+ GimpToolWidgetPrivate *private = widget->private;
+
+ switch (property_id)
+ {
+ case PROP_SHELL:
+ g_value_set_object (value, private->shell);
+ break;
+
+ case PROP_ITEM:
+ g_value_set_object (value, private->item);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_tool_widget_properties_changed (GObject *object,
+ guint n_pspecs,
+ GParamSpec **pspecs)
+{
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+
+ G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
+ n_pspecs,
+ pspecs);
+
+ gimp_tool_widget_changed (widget);
+}
+
+static void
+gimp_tool_widget_real_leave_notify (GimpToolWidget *widget)
+{
+ gimp_tool_widget_set_status (widget, NULL);
+}
+
+static gboolean
+gimp_tool_widget_real_key_press (GimpToolWidget *widget,
+ GdkEventKey *kevent)
+{
+ switch (kevent->keyval)
+ {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_ISO_Enter:
+ gimp_tool_widget_response (widget, GIMP_TOOL_WIDGET_RESPONSE_CONFIRM);
+ return TRUE;
+
+ case GDK_KEY_Escape:
+ gimp_tool_widget_response (widget, GIMP_TOOL_WIDGET_RESPONSE_CANCEL);
+ return TRUE;
+
+ case GDK_KEY_BackSpace:
+ gimp_tool_widget_response (widget, GIMP_TOOL_WIDGET_RESPONSE_RESET);
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/* public functions */
+
+GimpDisplayShell *
+gimp_tool_widget_get_shell (GimpToolWidget *widget)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ return widget->private->shell;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_get_item (GimpToolWidget *widget)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ return widget->private->item;
+}
+
+void
+gimp_tool_widget_set_visible (GimpToolWidget *widget,
+ gboolean visible)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ if (visible != widget->private->visible)
+ {
+ widget->private->visible = visible;
+
+ if (widget->private->item)
+ gimp_canvas_item_set_visible (widget->private->item, visible);
+
+ if (! visible)
+ gimp_tool_widget_set_status (widget, NULL);
+ }
+}
+
+gboolean
+gimp_tool_widget_get_visible (GimpToolWidget *widget)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE);
+
+ return widget->private->visible;
+}
+
+void
+gimp_tool_widget_set_focus (GimpToolWidget *widget,
+ gboolean focus)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ if (focus != widget->private->focus)
+ {
+ widget->private->focus = focus;
+
+ g_signal_emit (widget, widget_signals[FOCUS_CHANGED], 0);
+ }
+}
+
+gboolean
+gimp_tool_widget_get_focus (GimpToolWidget *widget)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE);
+
+ return widget->private->focus;
+}
+
+void
+gimp_tool_widget_changed (GimpToolWidget *widget)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ g_signal_emit (widget, widget_signals[CHANGED], 0);
+}
+
+void
+gimp_tool_widget_response (GimpToolWidget *widget,
+ gint response_id)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ g_signal_emit (widget, widget_signals[RESPONSE], 0,
+ response_id);
+}
+
+void
+gimp_tool_widget_set_snap_offsets (GimpToolWidget *widget,
+ gint offset_x,
+ gint offset_y,
+ gint width,
+ gint height)
+{
+ GimpToolWidgetPrivate *private;
+
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ private = widget->private;
+
+ if (offset_x != private->snap_offset_x ||
+ offset_y != private->snap_offset_y ||
+ width != private->snap_width ||
+ height != private->snap_height)
+ {
+ private->snap_offset_x = offset_x;
+ private->snap_offset_y = offset_y;
+ private->snap_width = width;
+ private->snap_height = height;
+
+ g_signal_emit (widget, widget_signals[SNAP_OFFSETS], 0,
+ offset_x, offset_y, width, height);
+ }
+}
+
+void
+gimp_tool_widget_get_snap_offsets (GimpToolWidget *widget,
+ gint *offset_x,
+ gint *offset_y,
+ gint *width,
+ gint *height)
+{
+ GimpToolWidgetPrivate *private;
+
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ private = widget->private;
+
+ if (offset_x) *offset_x = private->snap_offset_x;
+ if (offset_y) *offset_y = private->snap_offset_y;
+ if (width) *width = private->snap_width;
+ if (height) *height = private->snap_height;
+}
+
+void
+gimp_tool_widget_set_status (GimpToolWidget *widget,
+ const gchar *status)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ g_signal_emit (widget, widget_signals[STATUS], 0,
+ status);
+}
+
+void
+gimp_tool_widget_set_status_coords (GimpToolWidget *widget,
+ const gchar *title,
+ gdouble x,
+ const gchar *separator,
+ gdouble y,
+ const gchar *help)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ g_signal_emit (widget, widget_signals[STATUS_COORDS], 0,
+ title, x, separator, y, help);
+}
+
+void
+gimp_tool_widget_message (GimpToolWidget *widget,
+ const gchar *format,
+ ...)
+{
+ va_list args;
+ gchar *message;
+
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (format != NULL);
+
+ va_start (args, format);
+
+ message = g_strdup_vprintf (format, args);
+
+ va_end (args);
+
+ gimp_tool_widget_message_literal (widget, message);
+
+ g_free (message);
+}
+
+void
+gimp_tool_widget_message_literal (GimpToolWidget *widget,
+ const gchar *message)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (message != NULL);
+
+ g_signal_emit (widget, widget_signals[MESSAGE], 0,
+ message);
+}
+
+void
+gimp_tool_widget_add_item (GimpToolWidget *widget,
+ GimpCanvasItem *item)
+{
+ GimpCanvasGroup *group;
+
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+ group = GIMP_CANVAS_GROUP (widget->private->item);
+
+ if (widget->private->group_stack)
+ group = widget->private->group_stack->data;
+
+ gimp_canvas_group_add_item (group, item);
+}
+
+void
+gimp_tool_widget_remove_item (GimpToolWidget *widget,
+ GimpCanvasItem *item)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+ gimp_canvas_group_remove_item (GIMP_CANVAS_GROUP (widget->private->item),
+ item);
+}
+
+GimpCanvasGroup *
+gimp_tool_widget_add_group (GimpToolWidget *widget)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_group_new (widget->private->shell);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return GIMP_CANVAS_GROUP (item);
+}
+
+GimpCanvasGroup *
+gimp_tool_widget_add_stroke_group (GimpToolWidget *widget)
+{
+ GimpCanvasGroup *group;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ group = gimp_tool_widget_add_group (widget);
+ gimp_canvas_group_set_group_stroking (group, TRUE);
+
+ return group;
+}
+
+GimpCanvasGroup *
+gimp_tool_widget_add_fill_group (GimpToolWidget *widget)
+{
+ GimpCanvasGroup *group;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ group = gimp_tool_widget_add_group (widget);
+ gimp_canvas_group_set_group_filling (group, TRUE);
+
+ return group;
+}
+
+void
+gimp_tool_widget_push_group (GimpToolWidget *widget,
+ GimpCanvasGroup *group)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
+
+ widget->private->group_stack = g_list_prepend (widget->private->group_stack,
+ group);
+}
+
+void
+gimp_tool_widget_pop_group (GimpToolWidget *widget)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (widget->private->group_stack != NULL);
+
+ widget->private->group_stack = g_list_remove (widget->private->group_stack,
+ widget->private->group_stack->data);
+}
+
+/**
+ * gimp_tool_widget_add_line:
+ * @widget: the #GimpToolWidget
+ * @x1: start point X in image coordinates
+ * @y1: start point Y in image coordinates
+ * @x2: end point X in image coordinates
+ * @y2: end point Y in image coordinates
+ *
+ * This function adds a #GimpCanvasLine to @widget.
+ **/
+GimpCanvasItem *
+gimp_tool_widget_add_line (GimpToolWidget *widget,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_line_new (widget->private->shell,
+ x1, y1, x2, y2);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_rectangle (GimpToolWidget *widget,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ gboolean filled)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_rectangle_new (widget->private->shell,
+ x, y, width, height, filled);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_arc (GimpToolWidget *widget,
+ gdouble center_x,
+ gdouble center_y,
+ gdouble radius_x,
+ gdouble radius_y,
+ gdouble start_angle,
+ gdouble slice_angle,
+ gboolean filled)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_arc_new (widget->private->shell,
+ center_x, center_y,
+ radius_x, radius_y,
+ start_angle, slice_angle,
+ filled);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_limit (GimpToolWidget *widget,
+ GimpLimitType type,
+ gdouble x,
+ gdouble y,
+ gdouble radius,
+ gdouble aspect_ratio,
+ gdouble angle,
+ gboolean dashed)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_limit_new (widget->private->shell,
+ type,
+ x, y,
+ radius,
+ aspect_ratio,
+ angle,
+ dashed);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_polygon (GimpToolWidget *widget,
+ GimpMatrix3 *transform,
+ const GimpVector2 *points,
+ gint n_points,
+ gboolean filled)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+ g_return_val_if_fail (points == NULL || n_points > 0, NULL);
+
+ item = gimp_canvas_polygon_new (widget->private->shell,
+ points, n_points,
+ transform, filled);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_polygon_from_coords (GimpToolWidget *widget,
+ GimpMatrix3 *transform,
+ const GimpCoords *points,
+ gint n_points,
+ gboolean filled)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+ g_return_val_if_fail (points == NULL || n_points > 0, NULL);
+
+ item = gimp_canvas_polygon_new_from_coords (widget->private->shell,
+ points, n_points,
+ transform, filled);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_path (GimpToolWidget *widget,
+ const GimpBezierDesc *desc)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_path_new (widget->private->shell,
+ desc, 0, 0, FALSE, GIMP_PATH_STYLE_DEFAULT);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_handle (GimpToolWidget *widget,
+ GimpHandleType type,
+ gdouble x,
+ gdouble y,
+ gint width,
+ gint height,
+ GimpHandleAnchor anchor)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_handle_new (widget->private->shell,
+ type, anchor, x, y, width, height);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_corner (GimpToolWidget *widget,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ GimpHandleAnchor anchor,
+ gint corner_width,
+ gint corner_height,
+ gboolean outside)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_corner_new (widget->private->shell,
+ x, y, width, height,
+ anchor, corner_width, corner_height,
+ outside);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_rectangle_guides (GimpToolWidget *widget,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ GimpGuidesType type)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_rectangle_guides_new (widget->private->shell,
+ x, y, width, height, type, 4);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+GimpCanvasItem *
+gimp_tool_widget_add_transform_guides (GimpToolWidget *widget,
+ const GimpMatrix3 *transform,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ GimpGuidesType type,
+ gint n_guides,
+ gboolean clip)
+{
+ GimpCanvasItem *item;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), NULL);
+
+ item = gimp_canvas_transform_guides_new (widget->private->shell,
+ transform, x1, y1, x2, y2,
+ type, n_guides, clip);
+
+ gimp_tool_widget_add_item (widget, item);
+ g_object_unref (item);
+
+ return item;
+}
+
+gint
+gimp_tool_widget_button_press (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), 0);
+ g_return_val_if_fail (coords != NULL, 0);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press)
+ {
+ return GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press (widget,
+ coords, time,
+ state,
+ press_type);
+ }
+
+ return 0;
+}
+
+void
+gimp_tool_widget_button_release (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (coords != NULL);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release (widget,
+ coords, time, state,
+ release_type);
+ }
+}
+
+void
+gimp_tool_widget_motion (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (coords != NULL);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion (widget,
+ coords, time, state);
+ }
+}
+
+GimpHit
+gimp_tool_widget_hit (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), GIMP_HIT_NONE);
+ g_return_val_if_fail (coords != NULL, GIMP_HIT_NONE);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit)
+ {
+ return GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit (widget,
+ coords, state,
+ proximity);
+ }
+
+ return GIMP_HIT_NONE;
+}
+
+void
+gimp_tool_widget_hover (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+ g_return_if_fail (coords != NULL);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover (widget,
+ coords, state, proximity);
+ }
+}
+
+void
+gimp_tool_widget_leave_notify (GimpToolWidget *widget)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify (widget);
+ }
+}
+
+gboolean
+gimp_tool_widget_key_press (GimpToolWidget *widget,
+ GdkEventKey *kevent)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE);
+ g_return_val_if_fail (kevent != NULL, FALSE);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press)
+ {
+ return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press (widget, kevent);
+ }
+
+ return FALSE;
+}
+
+gboolean
+gimp_tool_widget_key_release (GimpToolWidget *widget,
+ GdkEventKey *kevent)
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE);
+ g_return_val_if_fail (kevent != NULL, FALSE);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release)
+ {
+ return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release (widget, kevent);
+ }
+
+ return FALSE;
+}
+
+void
+gimp_tool_widget_motion_modifier (GimpToolWidget *widget,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier (widget,
+ key, press, state);
+ }
+}
+
+void
+gimp_tool_widget_hover_modifier (GimpToolWidget *widget,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state)
+{
+ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier)
+ {
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier (widget,
+ key, press, state);
+ }
+}
+
+gboolean
+gimp_tool_widget_get_cursor (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ GimpCursorType *cursor,
+ GimpToolCursorType *tool_cursor,
+ GimpCursorModifier *modifier)
+
+{
+ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE);
+ g_return_val_if_fail (coords != NULL, FALSE);
+
+ if (widget->private->visible &&
+ GIMP_TOOL_WIDGET_GET_CLASS (widget)->get_cursor)
+ {
+ GimpCursorType my_cursor;
+ GimpToolCursorType my_tool_cursor;
+ GimpCursorModifier my_modifier;
+
+ if (cursor) my_cursor = *cursor;
+ if (tool_cursor) my_tool_cursor = *tool_cursor;
+ if (modifier) my_modifier = *modifier;
+
+ if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->get_cursor (widget, coords,
+ state,
+ &my_cursor,
+ &my_tool_cursor,
+ &my_modifier))
+ {
+ if (cursor) *cursor = my_cursor;
+ if (tool_cursor) *tool_cursor = my_tool_cursor;
+ if (modifier) *modifier = my_modifier;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}