24
23
#include <gdk/gdkkeysyms.h>
26
25
#include "libgimpmath/gimpmath.h"
26
#include "libgimpcolor/gimpcolor.h"
27
#include "libgimpconfig/gimpconfig.h"
28
#include "libgimpwidgets/gimpwidgets.h"
28
30
#include "widgets-types.h"
32
#include "core/gimp.h"
30
33
#include "core/gimpcurve.h"
31
34
#include "core/gimpcurve-map.h"
32
35
#include "core/gimpmarshal.h"
37
#include "gimpclipboard.h"
34
38
#include "gimpcurveview.h"
46
static void gimp_curve_view_finalize (GObject *object);
47
static void gimp_curve_view_dispose (GObject *object);
48
static void gimp_curve_view_set_property (GObject *object,
52
static void gimp_curve_view_get_property (GObject *object,
57
static void gimp_curve_view_style_set (GtkWidget *widget,
58
GtkStyle *prev_style);
59
static gboolean gimp_curve_view_expose (GtkWidget *widget,
60
GdkEventExpose *event);
61
static gboolean gimp_curve_view_button_press (GtkWidget *widget,
62
GdkEventButton *bevent);
63
static gboolean gimp_curve_view_button_release (GtkWidget *widget,
64
GdkEventButton *bevent);
65
static gboolean gimp_curve_view_motion_notify (GtkWidget *widget,
66
GdkEventMotion *bevent);
67
static gboolean gimp_curve_view_leave_notify (GtkWidget *widget,
68
GdkEventCrossing *cevent);
69
static gboolean gimp_curve_view_key_press (GtkWidget *widget,
72
static void gimp_curve_view_set_cursor (GimpCurveView *view,
75
static void gimp_curve_view_unset_cursor (GimpCurveView *view);
68
static void gimp_curve_view_finalize (GObject *object);
69
static void gimp_curve_view_dispose (GObject *object);
70
static void gimp_curve_view_set_property (GObject *object,
74
static void gimp_curve_view_get_property (GObject *object,
79
static void gimp_curve_view_style_set (GtkWidget *widget,
80
GtkStyle *prev_style);
81
static gboolean gimp_curve_view_expose (GtkWidget *widget,
82
GdkEventExpose *event);
83
static gboolean gimp_curve_view_button_press (GtkWidget *widget,
84
GdkEventButton *bevent);
85
static gboolean gimp_curve_view_button_release (GtkWidget *widget,
86
GdkEventButton *bevent);
87
static gboolean gimp_curve_view_motion_notify (GtkWidget *widget,
88
GdkEventMotion *bevent);
89
static gboolean gimp_curve_view_leave_notify (GtkWidget *widget,
90
GdkEventCrossing *cevent);
91
static gboolean gimp_curve_view_key_press (GtkWidget *widget,
94
static void gimp_curve_view_cut_clipboard (GimpCurveView *view);
95
static void gimp_curve_view_copy_clipboard (GimpCurveView *view);
96
static void gimp_curve_view_paste_clipboard (GimpCurveView *view);
98
static void gimp_curve_view_set_cursor (GimpCurveView *view,
101
static void gimp_curve_view_unset_cursor (GimpCurveView *view);
78
104
G_DEFINE_TYPE (GimpCurveView, gimp_curve_view,
100
129
widget_class->leave_notify_event = gimp_curve_view_leave_notify;
101
130
widget_class->key_press_event = gimp_curve_view_key_press;
132
klass->cut_clipboard = gimp_curve_view_cut_clipboard;
133
klass->copy_clipboard = gimp_curve_view_copy_clipboard;
134
klass->paste_clipboard = gimp_curve_view_paste_clipboard;
136
g_object_class_install_property (object_class, PROP_GIMP,
137
g_param_spec_object ("gimp",
140
GIMP_PARAM_READWRITE));
103
142
g_object_class_install_property (object_class, PROP_BASE_LINE,
104
143
g_param_spec_boolean ("base-line",
107
146
GIMP_PARAM_READWRITE |
108
147
G_PARAM_CONSTRUCT_ONLY));
109
149
g_object_class_install_property (object_class, PROP_GRID_ROWS,
110
150
g_param_spec_int ("grid-rows", NULL, NULL,
112
152
GIMP_PARAM_READWRITE |
113
153
G_PARAM_CONSTRUCT_ONLY));
114
155
g_object_class_install_property (object_class, PROP_GRID_COLUMNS,
115
156
g_param_spec_int ("grid-columns", NULL, NULL,
117
158
GIMP_PARAM_READWRITE |
118
159
G_PARAM_CONSTRUCT_ONLY));
161
g_object_class_install_property (object_class, PROP_X_AXIS_LABEL,
162
g_param_spec_string ("x-axis-label", NULL, NULL,
164
GIMP_PARAM_READWRITE));
166
g_object_class_install_property (object_class, PROP_Y_AXIS_LABEL,
167
g_param_spec_string ("y-axis-label", NULL, NULL,
169
GIMP_PARAM_READWRITE));
171
curve_view_signals[CUT_CLIPBOARD] =
172
g_signal_new ("cut-clipboard",
173
G_TYPE_FROM_CLASS (klass),
174
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
175
G_STRUCT_OFFSET (GimpCurveViewClass, cut_clipboard),
177
gimp_marshal_VOID__VOID,
180
curve_view_signals[COPY_CLIPBOARD] =
181
g_signal_new ("copy-clipboard",
182
G_TYPE_FROM_CLASS (klass),
183
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
184
G_STRUCT_OFFSET (GimpCurveViewClass, copy_clipboard),
186
gimp_marshal_VOID__VOID,
189
curve_view_signals[PASTE_CLIPBOARD] =
190
g_signal_new ("paste-clipboard",
191
G_TYPE_FROM_CLASS (klass),
192
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
193
G_STRUCT_OFFSET (GimpCurveViewClass, paste_clipboard),
195
gimp_marshal_VOID__VOID,
198
binding_set = gtk_binding_set_by_class (klass);
200
gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
202
gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
203
"copy-clipboard", 0);
204
gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
205
"paste-clipboard", 0);
327
450
cairo_move_to (cr,
328
border + (gdouble) width * x + RADIUS,
329
border + (gdouble) height * y);
451
border + (gdouble) (width - 1) * x + RADIUS,
452
border + (gdouble) (height - 1) * y);
331
border + (gdouble) width * x,
332
border + (gdouble) height * y,
454
border + (gdouble) (width - 1) * x,
455
border + (gdouble) (height - 1) * y,
461
gimp_curve_view_draw_curve (GimpCurveView *view,
472
y = 1.0 - gimp_curve_map_value (curve, 0.0);
475
border + (gdouble) (width - 1) * x,
476
border + (gdouble) (height - 1)* y);
478
for (i = 1; i < 256; i++)
480
x = (gdouble) i / 255.0;
481
y = 1.0 - gimp_curve_map_value (curve, x);
484
border + (gdouble) (width - 1) * x,
485
border + (gdouble) (height - 1) * y);
338
492
gimp_curve_view_expose (GtkWidget *widget,
339
493
GdkEventExpose *event)
341
GimpCurveView *view = GIMP_CURVE_VIEW (widget);
342
GtkStyle *style = gtk_widget_get_style (widget);
495
GimpCurveView *view = GIMP_CURVE_VIEW (widget);
496
GdkWindow *window = gtk_widget_get_window (widget);
497
GtkStyle *style = gtk_widget_get_style (widget);
498
GtkAllocation allocation;
352
511
if (! view->curve)
514
gtk_widget_get_allocation (widget, &allocation);
355
516
border = GIMP_HISTOGRAM_VIEW (view)->border_width;
357
width = widget->allocation.width - 2 * border - 1;
358
height = widget->allocation.height - 2 * border - 1;
360
cr = gdk_cairo_create (widget->window);
517
width = allocation.width - 2 * border;
518
height = allocation.height - 2 * border;
520
cr = gdk_cairo_create (gtk_widget_get_window (widget));
362
522
gdk_cairo_region (cr, event->region);
525
if (gtk_widget_has_focus (widget))
527
gtk_paint_focus (style, window,
528
gtk_widget_get_state (widget),
529
&event->area, widget, NULL,
530
border - 2, border - 2,
531
width + 4, height + 4);
534
cairo_set_line_width (cr, 1.0);
535
cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
365
536
cairo_translate (cr, 0.5, 0.5);
367
538
/* Draw the grid lines */
368
gimp_curve_view_draw_grid (view, style, cr, width, height, border);
539
gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_NORMAL]);
541
gimp_curve_view_draw_grid (view, cr, width, height, border);
543
/* Draw the axis labels */
545
if (view->x_axis_label)
548
view->layout = gtk_widget_create_pango_layout (widget, NULL);
550
pango_layout_set_text (view->layout, view->x_axis_label, -1);
551
pango_layout_get_pixel_size (view->layout, &layout_x, &layout_y);
554
width - border - layout_x,
555
height - border - layout_y);
557
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
558
pango_cairo_show_layout (cr, view->layout);
561
if (view->y_axis_label)
564
view->layout = gtk_widget_create_pango_layout (widget, NULL);
566
pango_layout_set_text (view->layout, view->y_axis_label, -1);
567
pango_layout_get_pixel_size (view->layout, &layout_x, &layout_y);
573
2 * border + layout_x);
574
cairo_rotate (cr, - G_PI / 2);
576
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
577
pango_cairo_show_layout (cr, view->layout);
583
/* Draw the background curves */
584
for (list = view->bg_curves; list; list = g_list_next (list))
586
BGCurve *bg = list->data;
588
cairo_set_source_rgba (cr,
594
gimp_curve_view_draw_curve (view, cr, bg->curve,
595
width, height, border);
370
598
/* Draw the curve */
371
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
374
y = 1.0 - gimp_curve_map_value (view->curve, 0.0);
377
border + (gdouble) width * x,
378
border + (gdouble) height * y);
380
for (i = 1; i < 256; i++)
382
x = (gdouble) i / 255.0;
383
y = 1.0 - gimp_curve_map_value (view->curve, x);
386
border + (gdouble) width * x,
387
border + (gdouble) height * y);
599
if (view->curve_color)
600
gimp_cairo_set_source_rgb (cr, view->curve_color);
602
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
604
gimp_curve_view_draw_curve (view, cr, view->curve,
605
width, height, border);
607
/* Draw the points */
392
608
if (gimp_curve_get_curve_type (view->curve) == GIMP_CURVE_SMOOTH)
394
610
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
416
632
if (view->xpos >= 0.0)
422
636
gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_NORMAL]);
424
638
/* draw the color line */
425
639
cairo_move_to (cr,
426
border + ROUND ((gdouble) width * view->xpos),
640
border + ROUND ((gdouble) (width - 1) * view->xpos),
428
642
cairo_line_to (cr,
429
border + ROUND ((gdouble) width * view->xpos),
643
border + ROUND ((gdouble) (width - 1) * view->xpos),
430
644
border + height - 1);
431
645
cairo_stroke (cr);
433
647
/* and xpos indicator */
434
648
g_snprintf (buf, sizeof (buf), "x:%d", (gint) (view->xpos * 255.999));
436
if (! view->xpos_layout)
437
view->xpos_layout = gtk_widget_create_pango_layout (widget, NULL);
651
view->layout = gtk_widget_create_pango_layout (widget, NULL);
439
pango_layout_set_text (view->xpos_layout, buf, -1);
440
pango_layout_get_pixel_size (view->xpos_layout, &layout_x, &layout_y);
653
pango_layout_set_text (view->layout, buf, -1);
654
pango_layout_get_pixel_size (view->layout, &layout_x, &layout_y);
442
656
if (view->xpos < 0.5)
443
657
layout_x = border;
480
707
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
481
708
cairo_stroke (cr);
483
g_snprintf (buf, sizeof (buf), "x:%3d y:%3d",
484
(gint) (view->cursor_x * 255.999),
485
(gint) ((1.0 - view->cursor_y) * 255.999));
710
/* stupid heuristic: special-case for 0..255 */
711
if (view->range_x_max == 255.0 &&
712
view->range_y_max == 255.0)
714
g_snprintf (buf, sizeof (buf), "x:%3d y:%3d",
715
(gint) (view->cursor_x *
716
(view->range_x_max - view->range_x_min) +
718
(gint) ((1.0 - view->cursor_y) *
719
(view->range_y_max - view->range_y_min) +
724
g_snprintf (buf, sizeof (buf), "x:%0.3f y:%0.3f",
726
(view->range_x_max - view->range_x_min) +
728
(1.0 - view->cursor_y) *
729
(view->range_y_max - view->range_y_min) +
486
733
pango_layout_set_text (view->cursor_layout, buf, -1);
488
735
gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_NORMAL]);
490
737
cairo_move_to (cr, x, y);
491
738
pango_cairo_show_layout (cr, view->cursor_layout);
494
740
cairo_pop_group_to_source (cr);
495
741
cairo_paint_with_alpha (cr, 0.6);
761
1016
gimp_curve_view_key_press (GtkWidget *widget,
762
1017
GdkEventKey *kevent)
764
GimpCurveView *view = GIMP_CURVE_VIEW (widget);
765
GimpCurve *curve = view->curve;
766
gint i = view->selected;
768
gboolean retval = FALSE;
770
if (view->grabbed || ! curve ||
771
gimp_curve_get_curve_type (curve) == GIMP_CURVE_FREE)
774
gimp_curve_get_point (curve, i, NULL, &y);
776
switch (kevent->keyval)
779
for (i = i - 1; i >= 0 && ! retval; i--)
781
gimp_curve_get_point (curve, i, &x, NULL);
785
gimp_curve_view_set_selected (view, i);
793
for (i = i + 1; i < curve->n_points && ! retval; i++)
795
gimp_curve_get_point (curve, i, &x, NULL);
799
gimp_curve_view_set_selected (view, i);
809
y = y + (kevent->state & GDK_SHIFT_MASK ?
810
(16.0 / 255.0) : (1.0 / 255.0));
812
gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
821
y = y - (kevent->state & GDK_SHIFT_MASK ?
822
(16.0 / 255.0) : (1.0 / 255.0));
824
gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
835
set_cursor (view, GDK_TCROSS);
1019
GimpCurveView *view = GIMP_CURVE_VIEW (widget);
1020
GimpCurve *curve = view->curve;
1021
gboolean handled = FALSE;
1023
if (! view->grabbed && curve &&
1024
gimp_curve_get_curve_type (curve) == GIMP_CURVE_SMOOTH)
1026
gint i = view->selected;
1029
gimp_curve_get_point (curve, i, NULL, &y);
1031
switch (kevent->keyval)
1034
for (i = i - 1; i >= 0 && ! handled; i--)
1036
gimp_curve_get_point (curve, i, &x, NULL);
1040
gimp_curve_view_set_selected (view, i);
1048
for (i = i + 1; i < curve->n_points && ! handled; i++)
1050
gimp_curve_get_point (curve, i, &x, NULL);
1054
gimp_curve_view_set_selected (view, i);
1064
y = y + (kevent->state & GDK_SHIFT_MASK ?
1065
(16.0 / 255.0) : (1.0 / 255.0));
1067
gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
1076
y = y - (kevent->state & GDK_SHIFT_MASK ?
1077
(16.0 / 255.0) : (1.0 / 255.0));
1079
gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
1085
case GDK_KEY_Delete:
1086
gimp_curve_delete_point (curve, i);
1096
set_cursor (view, GDK_TCROSS);
1101
return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, kevent);
1105
gimp_curve_view_cut_clipboard (GimpCurveView *view)
1107
g_printerr ("%s\n", G_STRFUNC);
1109
if (! view->curve || ! view->gimp)
1111
gtk_widget_error_bell (GTK_WIDGET (view));
1115
gimp_curve_view_copy_clipboard (view);
1117
gimp_curve_reset (view->curve, FALSE);
1121
gimp_curve_view_copy_clipboard (GimpCurveView *view)
1125
g_printerr ("%s\n", G_STRFUNC);
1127
if (! view->curve || ! view->gimp)
1129
gtk_widget_error_bell (GTK_WIDGET (view));
1133
copy = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (view->curve)));
1134
gimp_clipboard_set_curve (view->gimp, copy);
1135
g_object_unref (copy);
1139
gimp_curve_view_paste_clipboard (GimpCurveView *view)
1143
g_printerr ("%s\n", G_STRFUNC);
1145
if (! view->curve || ! view->gimp)
1147
gtk_widget_error_bell (GTK_WIDGET (view));
1151
copy = gimp_clipboard_get_curve (view->gimp);
1155
gimp_config_copy (GIMP_CONFIG (copy),
1156
GIMP_CONFIG (view->curve), 0);
1157
g_object_unref (copy);
1162
/* public functions */
841
1165
gimp_curve_view_new (void)
1226
gimp_curve_view_add_background (GimpCurveView *view,
1228
const GimpRGB *color)
1233
g_return_if_fail (GIMP_IS_CURVE_VIEW (view));
1234
g_return_if_fail (GIMP_IS_CURVE (curve));
1235
g_return_if_fail (color != NULL);
1237
for (list = view->bg_curves; list; list = g_list_next (list))
1241
g_return_if_fail (curve != bg->curve);
1244
bg = g_slice_new0 (BGCurve);
1246
bg->curve = g_object_ref (curve);
1249
g_signal_connect (bg->curve, "dirty",
1250
G_CALLBACK (gimp_curve_view_curve_dirty),
1253
view->bg_curves = g_list_append (view->bg_curves, bg);
1255
gtk_widget_queue_draw (GTK_WIDGET (view));
1259
gimp_curve_view_remove_background (GimpCurveView *view,
1264
g_return_if_fail (GIMP_IS_CURVE_VIEW (view));
1265
g_return_if_fail (GIMP_IS_CURVE (curve));
1267
for (list = view->bg_curves; list; list = g_list_next (list))
1269
BGCurve *bg = list->data;
1271
if (bg->curve == curve)
1273
g_signal_handlers_disconnect_by_func (bg->curve,
1274
gimp_curve_view_curve_dirty,
1276
g_object_unref (bg->curve);
1278
view->bg_curves = g_list_remove (view->bg_curves, bg);
1280
g_slice_free (BGCurve, bg);
1282
gtk_widget_queue_draw (GTK_WIDGET (view));
1289
g_return_if_reached ();
1293
gimp_curve_view_remove_all_backgrounds (GimpCurveView *view)
1295
g_return_if_fail (GIMP_IS_CURVE_VIEW (view));
1297
while (view->bg_curves)
1299
BGCurve *bg = view->bg_curves->data;
1301
g_signal_handlers_disconnect_by_func (bg->curve,
1302
gimp_curve_view_curve_dirty,
1304
g_object_unref (bg->curve);
1306
view->bg_curves = g_list_remove (view->bg_curves, bg);
1308
g_slice_free (BGCurve, bg);
1311
gtk_widget_queue_draw (GTK_WIDGET (view));
891
1315
gimp_curve_view_set_selected (GimpCurveView *view,
909
1355
gtk_widget_queue_draw (GTK_WIDGET (view));
1359
gimp_curve_view_set_x_axis_label (GimpCurveView *view,
1362
g_return_if_fail (GIMP_IS_CURVE_VIEW (view));
1364
if (view->x_axis_label)
1365
g_free (view->x_axis_label);
1367
view->x_axis_label = g_strdup (label);
1369
g_object_notify (G_OBJECT (view), "x-axis-label");
1371
gtk_widget_queue_draw (GTK_WIDGET (view));
1375
gimp_curve_view_set_y_axis_label (GimpCurveView *view,
1378
g_return_if_fail (GIMP_IS_CURVE_VIEW (view));
1380
if (view->y_axis_label)
1381
g_free (view->y_axis_label);
1383
view->y_axis_label = g_strdup (label);
1385
g_object_notify (G_OBJECT (view), "y-axis-label");
1387
gtk_widget_queue_draw (GTK_WIDGET (view));
913
1391
/* private functions */