PIKApp/app/display/pikatoolwidget.c

1138 lines
34 KiB
C

/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* pikatoolwidget.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 "libpikabase/pikabase.h"
#include "display-types.h"
#include "core/pikamarshal.h"
#include "pikacanvasarc.h"
#include "pikacanvascorner.h"
#include "pikacanvasgroup.h"
#include "pikacanvashandle.h"
#include "pikacanvaslimit.h"
#include "pikacanvasline.h"
#include "pikacanvaspath.h"
#include "pikacanvaspolygon.h"
#include "pikacanvasrectangle.h"
#include "pikacanvasrectangleguides.h"
#include "pikacanvastransformguides.h"
#include "pikadisplayshell.h"
#include "pikatoolwidget.h"
enum
{
PROP_0,
PROP_SHELL,
PROP_ITEM
};
enum
{
CHANGED,
RESPONSE,
SNAP_OFFSETS,
STATUS,
STATUS_COORDS,
MESSAGE,
FOCUS_CHANGED,
LAST_SIGNAL
};
struct _PikaToolWidgetPrivate
{
PikaDisplayShell *shell;
PikaCanvasItem *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 pika_tool_widget_finalize (GObject *object);
static void pika_tool_widget_constructed (GObject *object);
static void pika_tool_widget_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void pika_tool_widget_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void pika_tool_widget_properties_changed (GObject *object,
guint n_pspecs,
GParamSpec **pspecs);
static void pika_tool_widget_real_leave_notify (PikaToolWidget *widget);
static gboolean pika_tool_widget_real_key_press (PikaToolWidget *widget,
GdkEventKey *kevent);
G_DEFINE_TYPE_WITH_PRIVATE (PikaToolWidget, pika_tool_widget, PIKA_TYPE_OBJECT)
#define parent_class pika_tool_widget_parent_class
static guint widget_signals[LAST_SIGNAL] = { 0 };
static void
pika_tool_widget_class_init (PikaToolWidgetClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = pika_tool_widget_finalize;
object_class->constructed = pika_tool_widget_constructed;
object_class->set_property = pika_tool_widget_set_property;
object_class->get_property = pika_tool_widget_get_property;
object_class->dispatch_properties_changed = pika_tool_widget_properties_changed;
klass->leave_notify = pika_tool_widget_real_leave_notify;
klass->key_press = pika_tool_widget_real_key_press;
widget_signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (PikaToolWidgetClass, changed),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
widget_signals[RESPONSE] =
g_signal_new ("response",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (PikaToolWidgetClass, response),
NULL, NULL, NULL,
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 (PikaToolWidgetClass, snap_offsets),
NULL, NULL,
pika_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 (PikaToolWidgetClass, status),
NULL, NULL, NULL,
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 (PikaToolWidgetClass, status_coords),
NULL, NULL,
pika_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 (PikaToolWidgetClass, message),
NULL, NULL, NULL,
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 (PikaToolWidgetClass, focus_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class, PROP_SHELL,
g_param_spec_object ("shell",
NULL, NULL,
PIKA_TYPE_DISPLAY_SHELL,
PIKA_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_ITEM,
g_param_spec_object ("item",
NULL, NULL,
PIKA_TYPE_CANVAS_ITEM,
PIKA_PARAM_READABLE));
}
static void
pika_tool_widget_init (PikaToolWidget *widget)
{
widget->private = pika_tool_widget_get_instance_private (widget);
widget->private->visible = TRUE;
}
static void
pika_tool_widget_constructed (GObject *object)
{
PikaToolWidget *widget = PIKA_TOOL_WIDGET (object);
PikaToolWidgetPrivate *private = widget->private;
PikaToolWidgetClass *klass = PIKA_TOOL_WIDGET_GET_CLASS (widget);
G_OBJECT_CLASS (parent_class)->constructed (object);
pika_assert (PIKA_IS_DISPLAY_SHELL (private->shell));
private->item = pika_canvas_group_new (private->shell);
pika_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
pika_tool_widget_finalize (GObject *object)
{
PikaToolWidget *widget = PIKA_TOOL_WIDGET (object);
PikaToolWidgetPrivate *private = widget->private;
g_clear_object (&private->item);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
pika_tool_widget_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
PikaToolWidget *widget = PIKA_TOOL_WIDGET (object);
PikaToolWidgetPrivate *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
pika_tool_widget_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
PikaToolWidget *widget = PIKA_TOOL_WIDGET (object);
PikaToolWidgetPrivate *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
pika_tool_widget_properties_changed (GObject *object,
guint n_pspecs,
GParamSpec **pspecs)
{
PikaToolWidget *widget = PIKA_TOOL_WIDGET (object);
G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
n_pspecs,
pspecs);
pika_tool_widget_changed (widget);
}
static void
pika_tool_widget_real_leave_notify (PikaToolWidget *widget)
{
pika_tool_widget_set_status (widget, NULL);
}
static gboolean
pika_tool_widget_real_key_press (PikaToolWidget *widget,
GdkEventKey *kevent)
{
switch (kevent->keyval)
{
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
pika_tool_widget_response (widget, PIKA_TOOL_WIDGET_RESPONSE_CONFIRM);
return TRUE;
case GDK_KEY_Escape:
pika_tool_widget_response (widget, PIKA_TOOL_WIDGET_RESPONSE_CANCEL);
return TRUE;
case GDK_KEY_BackSpace:
pika_tool_widget_response (widget, PIKA_TOOL_WIDGET_RESPONSE_RESET);
return TRUE;
default:
break;
}
return FALSE;
}
/* public functions */
PikaDisplayShell *
pika_tool_widget_get_shell (PikaToolWidget *widget)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
return widget->private->shell;
}
PikaCanvasItem *
pika_tool_widget_get_item (PikaToolWidget *widget)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
return widget->private->item;
}
void
pika_tool_widget_set_visible (PikaToolWidget *widget,
gboolean visible)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
if (visible != widget->private->visible)
{
widget->private->visible = visible;
if (widget->private->item)
pika_canvas_item_set_visible (widget->private->item, visible);
if (! visible)
pika_tool_widget_set_status (widget, NULL);
}
}
gboolean
pika_tool_widget_get_visible (PikaToolWidget *widget)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), FALSE);
return widget->private->visible;
}
void
pika_tool_widget_set_focus (PikaToolWidget *widget,
gboolean focus)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
if (focus != widget->private->focus)
{
widget->private->focus = focus;
g_signal_emit (widget, widget_signals[FOCUS_CHANGED], 0);
}
}
gboolean
pika_tool_widget_get_focus (PikaToolWidget *widget)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), FALSE);
return widget->private->focus;
}
void
pika_tool_widget_changed (PikaToolWidget *widget)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_signal_emit (widget, widget_signals[CHANGED], 0);
}
void
pika_tool_widget_response (PikaToolWidget *widget,
gint response_id)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_signal_emit (widget, widget_signals[RESPONSE], 0,
response_id);
}
void
pika_tool_widget_set_snap_offsets (PikaToolWidget *widget,
gint offset_x,
gint offset_y,
gint width,
gint height)
{
PikaToolWidgetPrivate *private;
g_return_if_fail (PIKA_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
pika_tool_widget_get_snap_offsets (PikaToolWidget *widget,
gint *offset_x,
gint *offset_y,
gint *width,
gint *height)
{
PikaToolWidgetPrivate *private;
g_return_if_fail (PIKA_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
pika_tool_widget_set_status (PikaToolWidget *widget,
const gchar *status)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_signal_emit (widget, widget_signals[STATUS], 0,
status);
}
void
pika_tool_widget_set_status_coords (PikaToolWidget *widget,
const gchar *title,
gdouble x,
const gchar *separator,
gdouble y,
const gchar *help)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_signal_emit (widget, widget_signals[STATUS_COORDS], 0,
title, x, separator, y, help);
}
void
pika_tool_widget_message (PikaToolWidget *widget,
const gchar *format,
...)
{
va_list args;
gchar *message;
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (format != NULL);
va_start (args, format);
message = g_strdup_vprintf (format, args);
va_end (args);
pika_tool_widget_message_literal (widget, message);
g_free (message);
}
void
pika_tool_widget_message_literal (PikaToolWidget *widget,
const gchar *message)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (message != NULL);
g_signal_emit (widget, widget_signals[MESSAGE], 0,
message);
}
void
pika_tool_widget_add_item (PikaToolWidget *widget,
PikaCanvasItem *item)
{
PikaCanvasGroup *group;
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (PIKA_IS_CANVAS_ITEM (item));
group = PIKA_CANVAS_GROUP (widget->private->item);
if (widget->private->group_stack)
group = widget->private->group_stack->data;
pika_canvas_group_add_item (group, item);
}
void
pika_tool_widget_remove_item (PikaToolWidget *widget,
PikaCanvasItem *item)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (PIKA_IS_CANVAS_ITEM (item));
pika_canvas_group_remove_item (PIKA_CANVAS_GROUP (widget->private->item),
item);
}
PikaCanvasGroup *
pika_tool_widget_add_group (PikaToolWidget *widget)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_group_new (widget->private->shell);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return PIKA_CANVAS_GROUP (item);
}
PikaCanvasGroup *
pika_tool_widget_add_stroke_group (PikaToolWidget *widget)
{
PikaCanvasGroup *group;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
group = pika_tool_widget_add_group (widget);
pika_canvas_group_set_group_stroking (group, TRUE);
return group;
}
PikaCanvasGroup *
pika_tool_widget_add_fill_group (PikaToolWidget *widget)
{
PikaCanvasGroup *group;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
group = pika_tool_widget_add_group (widget);
pika_canvas_group_set_group_filling (group, TRUE);
return group;
}
void
pika_tool_widget_push_group (PikaToolWidget *widget,
PikaCanvasGroup *group)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (PIKA_IS_CANVAS_GROUP (group));
widget->private->group_stack = g_list_prepend (widget->private->group_stack,
group);
}
void
pika_tool_widget_pop_group (PikaToolWidget *widget)
{
g_return_if_fail (PIKA_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);
}
/**
* pika_tool_widget_add_line:
* @widget: the #PikaToolWidget
* @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 #PikaCanvasLine to @widget.
**/
PikaCanvasItem *
pika_tool_widget_add_line (PikaToolWidget *widget,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_line_new (widget->private->shell,
x1, y1, x2, y2);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_rectangle (PikaToolWidget *widget,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
gboolean filled)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_rectangle_new (widget->private->shell,
x, y, width, height, filled);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_arc (PikaToolWidget *widget,
gdouble center_x,
gdouble center_y,
gdouble radius_x,
gdouble radius_y,
gdouble start_angle,
gdouble slice_angle,
gboolean filled)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_arc_new (widget->private->shell,
center_x, center_y,
radius_x, radius_y,
start_angle, slice_angle,
filled);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_limit (PikaToolWidget *widget,
PikaLimitType type,
gdouble x,
gdouble y,
gdouble radius,
gdouble aspect_ratio,
gdouble angle,
gboolean dashed)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_limit_new (widget->private->shell,
type,
x, y,
radius,
aspect_ratio,
angle,
dashed);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_polygon (PikaToolWidget *widget,
PikaMatrix3 *transform,
const PikaVector2 *points,
gint n_points,
gboolean filled)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
g_return_val_if_fail (points == NULL || n_points > 0, NULL);
item = pika_canvas_polygon_new (widget->private->shell,
points, n_points,
transform, filled);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_polygon_from_coords (PikaToolWidget *widget,
PikaMatrix3 *transform,
const PikaCoords *points,
gint n_points,
gboolean filled)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
g_return_val_if_fail (points == NULL || n_points > 0, NULL);
item = pika_canvas_polygon_new_from_coords (widget->private->shell,
points, n_points,
transform, filled);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_path (PikaToolWidget *widget,
const PikaBezierDesc *desc)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_path_new (widget->private->shell,
desc, 0, 0, FALSE, PIKA_PATH_STYLE_DEFAULT);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_handle (PikaToolWidget *widget,
PikaHandleType type,
gdouble x,
gdouble y,
gint width,
gint height,
PikaHandleAnchor anchor)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_handle_new (widget->private->shell,
type, anchor, x, y, width, height);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_corner (PikaToolWidget *widget,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
PikaHandleAnchor anchor,
gint corner_width,
gint corner_height,
gboolean outside)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_corner_new (widget->private->shell,
x, y, width, height,
anchor, corner_width, corner_height,
outside);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_rectangle_guides (PikaToolWidget *widget,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
PikaGuidesType type)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_rectangle_guides_new (widget->private->shell,
x, y, width, height, type, 4);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
PikaCanvasItem *
pika_tool_widget_add_transform_guides (PikaToolWidget *widget,
const PikaMatrix3 *transform,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
PikaGuidesType type,
gint n_guides,
gboolean clip)
{
PikaCanvasItem *item;
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
item = pika_canvas_transform_guides_new (widget->private->shell,
transform, x1, y1, x2, y2,
type, n_guides, clip);
pika_tool_widget_add_item (widget, item);
g_object_unref (item);
return item;
}
gint
pika_tool_widget_button_press (PikaToolWidget *widget,
const PikaCoords *coords,
guint32 time,
GdkModifierType state,
PikaButtonPressType press_type)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), 0);
g_return_val_if_fail (coords != NULL, 0);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->button_press)
{
return PIKA_TOOL_WIDGET_GET_CLASS (widget)->button_press (widget,
coords, time,
state,
press_type);
}
return 0;
}
void
pika_tool_widget_button_release (PikaToolWidget *widget,
const PikaCoords *coords,
guint32 time,
GdkModifierType state,
PikaButtonReleaseType release_type)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (coords != NULL);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->button_release)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->button_release (widget,
coords, time, state,
release_type);
}
}
void
pika_tool_widget_motion (PikaToolWidget *widget,
const PikaCoords *coords,
guint32 time,
GdkModifierType state)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (coords != NULL);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->motion)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->motion (widget,
coords, time, state);
}
}
PikaHit
pika_tool_widget_hit (PikaToolWidget *widget,
const PikaCoords *coords,
GdkModifierType state,
gboolean proximity)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), PIKA_HIT_NONE);
g_return_val_if_fail (coords != NULL, PIKA_HIT_NONE);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->hit)
{
return PIKA_TOOL_WIDGET_GET_CLASS (widget)->hit (widget,
coords, state,
proximity);
}
return PIKA_HIT_NONE;
}
void
pika_tool_widget_hover (PikaToolWidget *widget,
const PikaCoords *coords,
GdkModifierType state,
gboolean proximity)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
g_return_if_fail (coords != NULL);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->hover)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->hover (widget,
coords, state, proximity);
}
}
void
pika_tool_widget_leave_notify (PikaToolWidget *widget)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->leave_notify)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->leave_notify (widget);
}
}
gboolean
pika_tool_widget_key_press (PikaToolWidget *widget,
GdkEventKey *kevent)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), FALSE);
g_return_val_if_fail (kevent != NULL, FALSE);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->key_press)
{
return PIKA_TOOL_WIDGET_GET_CLASS (widget)->key_press (widget, kevent);
}
return FALSE;
}
gboolean
pika_tool_widget_key_release (PikaToolWidget *widget,
GdkEventKey *kevent)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), FALSE);
g_return_val_if_fail (kevent != NULL, FALSE);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->key_release)
{
return PIKA_TOOL_WIDGET_GET_CLASS (widget)->key_release (widget, kevent);
}
return FALSE;
}
void
pika_tool_widget_motion_modifier (PikaToolWidget *widget,
GdkModifierType key,
gboolean press,
GdkModifierType state)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier (widget,
key, press, state);
}
}
void
pika_tool_widget_hover_modifier (PikaToolWidget *widget,
GdkModifierType key,
gboolean press,
GdkModifierType state)
{
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier)
{
PIKA_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier (widget,
key, press, state);
}
}
gboolean
pika_tool_widget_get_cursor (PikaToolWidget *widget,
const PikaCoords *coords,
GdkModifierType state,
PikaCursorType *cursor,
PikaToolCursorType *tool_cursor,
PikaCursorModifier *modifier)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), FALSE);
g_return_val_if_fail (coords != NULL, FALSE);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->get_cursor)
{
PikaCursorType my_cursor;
PikaToolCursorType my_tool_cursor;
PikaCursorModifier my_modifier;
if (cursor) my_cursor = *cursor;
if (tool_cursor) my_tool_cursor = *tool_cursor;
if (modifier) my_modifier = *modifier;
if (PIKA_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;
}
PikaUIManager *
pika_tool_widget_get_popup (PikaToolWidget *widget,
const PikaCoords *coords,
GdkModifierType state,
const gchar **ui_path)
{
g_return_val_if_fail (PIKA_IS_TOOL_WIDGET (widget), NULL);
g_return_val_if_fail (coords != NULL, NULL);
if (widget->private->visible &&
PIKA_TOOL_WIDGET_GET_CLASS (widget)->get_popup)
{
return PIKA_TOOL_WIDGET_GET_CLASS (widget)->get_popup (widget, coords,
state, ui_path);
}
return NULL;
}