1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
5
* Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28
#include "libgimpcolor/gimpcolor.h"
29
#include "libgimpwidgets/gimpwidgets.h"
31
#include "widgets-types.h"
33
#include "core/gimpcontext.h"
34
#include "core/gimpmarshal.h"
37
#include "gimpfgbgeditor.h"
63
static void gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass);
64
static void gimp_fg_bg_editor_init (GimpFgBgEditor *editor);
66
static void gimp_fg_bg_editor_set_property (GObject *object,
70
static void gimp_fg_bg_editor_get_property (GObject *object,
75
static void gimp_fg_bg_editor_destroy (GtkObject *object);
76
static gboolean gimp_fg_bg_editor_expose (GtkWidget *widget,
77
GdkEventExpose *eevent);
78
static gboolean gimp_fg_bg_editor_button_press (GtkWidget *widget,
79
GdkEventButton *bevent);
80
static gboolean gimp_fg_bg_editor_button_release (GtkWidget *widget,
81
GdkEventButton *bevent);
82
static gboolean gimp_fg_bg_editor_drag_motion (GtkWidget *widget,
83
GdkDragContext *context,
88
static void gimp_fg_bg_editor_drag_color (GtkWidget *widget,
91
static void gimp_fg_bg_editor_drop_color (GtkWidget *widget,
96
static guint editor_signals[LAST_SIGNAL] = { 0 };
98
static GtkDrawingAreaClass *parent_class = NULL;
102
gimp_fg_bg_editor_get_type (void)
104
static GType type = 0;
108
static const GTypeInfo info =
110
sizeof (GimpFgBgEditorClass),
111
NULL, /* base_init */
112
NULL, /* base_finalize */
113
(GClassInitFunc) gimp_fg_bg_editor_class_init,
114
NULL, /* class_finalize */
115
NULL, /* class_data */
116
sizeof (GimpFgBgEditor),
118
(GInstanceInitFunc) gimp_fg_bg_editor_init,
121
type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
130
gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass)
132
GObjectClass *object_class = G_OBJECT_CLASS (klass);
133
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
134
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
136
parent_class = g_type_class_peek_parent (klass);
138
editor_signals[COLOR_CLICKED] =
139
g_signal_new ("color-clicked",
140
G_TYPE_FROM_CLASS (klass),
142
G_STRUCT_OFFSET (GimpFgBgEditorClass, color_clicked),
144
gimp_marshal_VOID__ENUM,
146
GIMP_TYPE_ACTIVE_COLOR);
148
object_class->set_property = gimp_fg_bg_editor_set_property;
149
object_class->get_property = gimp_fg_bg_editor_get_property;
151
gtk_object_class->destroy = gimp_fg_bg_editor_destroy;
153
widget_class->expose_event = gimp_fg_bg_editor_expose;
154
widget_class->button_press_event = gimp_fg_bg_editor_button_press;
155
widget_class->button_release_event = gimp_fg_bg_editor_button_release;
156
widget_class->drag_motion = gimp_fg_bg_editor_drag_motion;
158
g_object_class_install_property (object_class, PROP_CONTEXT,
159
g_param_spec_object ("context",
164
g_object_class_install_property (object_class, PROP_ACTIVE_COLOR,
165
g_param_spec_enum ("active-color",
167
GIMP_TYPE_ACTIVE_COLOR,
168
GIMP_ACTIVE_COLOR_FOREGROUND,
173
gimp_fg_bg_editor_init (GimpFgBgEditor *editor)
175
editor->context = NULL;
176
editor->active_color = GIMP_ACTIVE_COLOR_FOREGROUND;
178
gtk_widget_add_events (GTK_WIDGET (editor),
179
GDK_BUTTON_PRESS_MASK |
180
GDK_BUTTON_RELEASE_MASK);
182
gimp_dnd_color_source_add (GTK_WIDGET (editor),
183
gimp_fg_bg_editor_drag_color, NULL);
184
gimp_dnd_color_dest_add (GTK_WIDGET (editor),
185
gimp_fg_bg_editor_drop_color, NULL);
189
gimp_fg_bg_editor_set_property (GObject *object,
194
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object);
199
gimp_fg_bg_editor_set_context (editor, g_value_get_object (value));
201
case PROP_ACTIVE_COLOR:
202
gimp_fg_bg_editor_set_active (editor, g_value_get_enum (value));
205
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
211
gimp_fg_bg_editor_get_property (GObject *object,
216
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object);
221
g_value_set_object (value, editor->context);
223
case PROP_ACTIVE_COLOR:
224
g_value_set_enum (value, editor->active_color);
227
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
233
gimp_fg_bg_editor_destroy (GtkObject *object)
235
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object);
238
gimp_fg_bg_editor_set_context (editor, NULL);
240
if (editor->render_buf)
242
g_free (editor->render_buf);
243
editor->render_buf = NULL;
244
editor->render_buf_size = 0;
247
if (editor->default_icon)
249
g_object_unref (editor->default_icon);
250
editor->default_icon = NULL;
253
if (editor->swap_icon)
255
g_object_unref (editor->swap_icon);
256
editor->swap_icon = NULL;
259
GTK_OBJECT_CLASS (parent_class)->destroy (object);
263
gimp_fg_bg_editor_draw_rect (GimpFgBgEditor *editor,
264
GdkDrawable *drawable,
270
const GimpRGB *color)
277
gimp_rgb_get_uchar (color, &r, &g, &b);
279
rowstride = 3 * ((width + 3) & -4);
281
if (! editor->render_buf || editor->render_buf_size < height * rowstride)
283
editor->render_buf_size = rowstride * height;
285
g_free (editor->render_buf);
286
editor->render_buf = g_malloc (editor->render_buf_size);
289
bp = editor->render_buf;
290
for (xx = 0; xx < width; xx++)
297
bp = editor->render_buf;
299
for (yy = 1; yy < height; yy++)
302
memcpy (bp, editor->render_buf, rowstride);
305
gdk_draw_rgb_image (drawable, gc, x, y, width, height,
312
gimp_fg_bg_editor_expose (GtkWidget *widget,
313
GdkEventExpose *eevent)
315
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
317
gint default_w, default_h;
322
if (! GTK_WIDGET_DRAWABLE (widget))
325
width = widget->allocation.width;
326
height = widget->allocation.height;
328
/* draw the default colors pixbuf */
329
if (! editor->default_icon)
330
editor->default_icon = gtk_widget_render_icon (widget,
331
GIMP_STOCK_DEFAULT_COLORS,
332
GTK_ICON_SIZE_MENU, NULL);
334
default_w = gdk_pixbuf_get_width (editor->default_icon);
335
default_h = gdk_pixbuf_get_height (editor->default_icon);
336
gdk_draw_pixbuf (widget->window, NULL, editor->default_icon,
337
0, 0, 0, height - default_h, default_w, default_h,
338
GDK_RGB_DITHER_NORMAL, 0, 0);
340
/* draw the swap colors pixbuf */
341
if (! editor->swap_icon)
342
editor->swap_icon = gtk_widget_render_icon (widget,
343
GIMP_STOCK_SWAP_COLORS,
344
GTK_ICON_SIZE_MENU, NULL);
346
swap_w = gdk_pixbuf_get_width (editor->swap_icon);
347
swap_h = gdk_pixbuf_get_height (editor->swap_icon);
348
gdk_draw_pixbuf (widget->window, NULL, editor->swap_icon,
349
0, 0, width - swap_w, 0, swap_w, swap_h,
350
GDK_RGB_DITHER_NORMAL, 0, 0);
353
rect_h = height - MAX (default_h, swap_h) - 2;
354
rect_w = width - MAX (default_w, swap_w) - 4;
356
if (rect_h > (height * 3 / 4))
357
rect_w = MAX (rect_w - (rect_h - ((height * 3 / 4))),
360
editor->rect_width = rect_w;
361
editor->rect_height = rect_h;
364
/* draw the background area */
368
gimp_context_get_background (editor->context, &color);
369
gimp_fg_bg_editor_draw_rect (editor,
371
widget->style->fg_gc[0],
378
gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL,
379
editor->active_color == GIMP_ACTIVE_COLOR_FOREGROUND ?
380
GTK_SHADOW_OUT : GTK_SHADOW_IN,
387
/* draw the foreground area */
391
gimp_context_get_foreground (editor->context, &color);
392
gimp_fg_bg_editor_draw_rect (editor,
394
widget->style->fg_gc[0],
400
gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL,
401
editor->active_color == GIMP_ACTIVE_COLOR_BACKGROUND ?
402
GTK_SHADOW_OUT : GTK_SHADOW_IN,
411
gimp_fg_bg_editor_target (GimpFgBgEditor *editor,
415
gint width = GTK_WIDGET (editor)->allocation.width;
416
gint height = GTK_WIDGET (editor)->allocation.height;
417
gint rect_w = editor->rect_width;
418
gint rect_h = editor->rect_height;
420
if (x > 0 && x < rect_w && y > 0 && y < rect_h)
422
else if (x > (width - rect_w) && x < width &&
423
y > (height - rect_h) && y < height)
425
else if (x > 0 && x < (width - rect_w) &&
426
y > rect_h && y < height)
428
else if (x > rect_w && x < width &&
429
y > 0 && y < (height - rect_h))
436
gimp_fg_bg_editor_button_press (GtkWidget *widget,
437
GdkEventButton *bevent)
439
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
441
if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS)
443
FgBgTarget target = gimp_fg_bg_editor_target (editor,
444
bevent->x, bevent->y);
446
editor->click_target = INVALID_AREA;
451
if (editor->active_color != GIMP_ACTIVE_COLOR_FOREGROUND)
452
gimp_fg_bg_editor_set_active (editor,
453
GIMP_ACTIVE_COLOR_FOREGROUND);
455
editor->click_target = FORE_AREA;
459
if (editor->active_color != GIMP_ACTIVE_COLOR_BACKGROUND)
460
gimp_fg_bg_editor_set_active (editor,
461
GIMP_ACTIVE_COLOR_BACKGROUND);
463
editor->click_target = BACK_AREA;
468
gimp_context_swap_colors (editor->context);
473
gimp_context_set_default_colors (editor->context);
485
gimp_fg_bg_editor_button_release (GtkWidget *widget,
486
GdkEventButton *bevent)
488
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
490
if (bevent->button == 1)
492
FgBgTarget target = gimp_fg_bg_editor_target (editor,
493
bevent->x, bevent->y);
495
if (target == editor->click_target)
500
g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0,
501
GIMP_ACTIVE_COLOR_FOREGROUND);
505
g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0,
506
GIMP_ACTIVE_COLOR_BACKGROUND);
514
editor->click_target = INVALID_AREA;
521
gimp_fg_bg_editor_drag_motion (GtkWidget *widget,
522
GdkDragContext *context,
527
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
529
editor->dnd_target = gimp_fg_bg_editor_target (editor, x, y);
531
if (editor->dnd_target == FORE_AREA ||
532
editor->dnd_target == BACK_AREA)
534
gdk_drag_status (context, GDK_ACTION_COPY, time);
539
gdk_drag_status (context, 0, time);
545
/* public functions */
548
gimp_fg_bg_editor_new (GimpContext *context)
550
g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
552
return g_object_new (GIMP_TYPE_FG_BG_EDITOR,
558
gimp_fg_bg_editor_set_context (GimpFgBgEditor *editor,
559
GimpContext *context)
561
g_return_if_fail (GIMP_IS_FG_BG_EDITOR (editor));
562
g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
564
if (context == editor->context)
569
g_signal_handlers_disconnect_by_func (editor->context,
570
gtk_widget_queue_draw,
572
g_object_unref (editor->context);
573
editor->context = NULL;
576
editor->context = context;
580
g_object_ref (context);
582
g_signal_connect_swapped (context, "foreground_changed",
583
G_CALLBACK (gtk_widget_queue_draw),
585
g_signal_connect_swapped (context, "background_changed",
586
G_CALLBACK (gtk_widget_queue_draw),
590
g_object_notify (G_OBJECT (editor), "context");
594
gimp_fg_bg_editor_set_active (GimpFgBgEditor *editor,
595
GimpActiveColor active)
597
g_return_if_fail (GIMP_IS_FG_BG_EDITOR (editor));
599
editor->active_color = active;
600
gtk_widget_queue_draw (GTK_WIDGET (editor));
601
g_object_notify (G_OBJECT (editor), "active-color");
605
/* private functions */
608
gimp_fg_bg_editor_drag_color (GtkWidget *widget,
612
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
616
switch (editor->active_color)
618
case GIMP_ACTIVE_COLOR_FOREGROUND:
619
gimp_context_get_foreground (editor->context, color);
622
case GIMP_ACTIVE_COLOR_BACKGROUND:
623
gimp_context_get_background (editor->context, color);
630
gimp_fg_bg_editor_drop_color (GtkWidget *widget,
631
const GimpRGB *color,
634
GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
638
switch (editor->dnd_target)
641
gimp_context_set_foreground (editor->context, color);
645
gimp_context_set_background (editor->context, color);