gimp/modules/colorsel_water.c
Michael Natterer 37fe1a885d app/color_notebook.[ch] moved the scales and the toggle butttons out of
2001-01-09  Michael Natterer  <mitch@gimp.org>

	* app/color_notebook.[ch]
	* app/color_select.c: moved the scales and the toggle butttons out
	of the notebook. Added an "Aplha" scale (the opacity is not yet
	shown in the color area). Removed the ColorNotebook structure from
	the header.

	* app/color_area.c: the ColorNotebook struct is no longer public.

	* libgimp/gimpcolorselector.h
	* modules/colorsel_gtk.c
	* modules/colorsel_triangle.c
	* modules/colorsel_water.c: changed the ColorSelector module
	interface again: Pass H, S, V, R, G, B and A in all functions
	and callbacks. Added a "set_channel" method because the channel
	toggles are outside the notebook now. This needs more work...
2001-01-09 01:23:54 +00:00

941 lines
23 KiB
C

/* Watercolor color_select_module, Raph Levien <raph@acm.org>, February 1998
*
* Ported to loadable color-selector, Sven Neumann <sven@gimp.org>, May 1999
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* #define VERBOSE 1 */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <libgimp/gimpcolorselector.h>
#include <libgimp/gimpcolor.h>
#include <libgimp/gimpcolorspace.h>
#include <libgimp/gimpmodule.h>
#include <libgimp/gimpmath.h>
#include "gimpmodregister.h"
#include <libgimp/gimpintl.h>
/* prototypes */
static GtkWidget * colorsel_water_new (gint h,
gint s,
gint v,
gint r,
gint g,
gint b,
gint a,
gboolean show_alpha,
GimpColorSelectorCallback,
gpointer,
gpointer *);
static void colorsel_water_free (gpointer data);
static void colorsel_water_set_color (gpointer data,
gint h,
gint s,
gint v,
gint r,
gint g,
gint b,
gint a);
static void colorsel_water_set_channel (gpointer data,
GimpColorSelectorChannelType channel);
static void colorsel_water_update (void);
static void colorsel_water_drag_begin (GtkWidget *widget,
GdkDragContext *context,
gpointer data);
static void colorsel_water_drag_end (GtkWidget *widget,
GdkDragContext *context,
gpointer data);
static void colorsel_water_drop_handle (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data);
static void colorsel_water_drag_handle (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data);
/* local methods */
static GimpColorSelectorMethods methods =
{
colorsel_water_new,
colorsel_water_free,
colorsel_water_set_color,
colorsel_water_set_channel
};
static GimpModuleInfo info =
{
NULL,
N_("Watercolor style color selector as a pluggable module"),
"Raph Levien <raph@acm.org>, Sven Neumann <sven@gimp.org>",
"v0.3",
"(c) 1998-1999, released under the GPL",
"May, 10 1999"
};
static const GtkTargetEntry targets[] =
{
{ "application/x-color", 0 }
};
/*************************************************************/
/* globaly exported init function */
G_MODULE_EXPORT GimpModuleStatus
module_init (GimpModuleInfo **inforet)
{
GimpColorSelectorID id;
#ifndef __EMX__
id = gimp_color_selector_register (_("Watercolor"), "watercolor.html",
&methods);
#else
id = mod_color_selector_register (_("Watercolor"), "watercolor.html",
&methods);
#endif
if (id)
{
info.shutdown_data = id;
*inforet = &info;
return GIMP_MODULE_OK;
}
else
{
return GIMP_MODULE_UNLOAD;
}
}
G_MODULE_EXPORT void
module_unload (gpointer shutdown_data,
GimpColorSelectorFinishedCB completed_cb,
gpointer completed_data)
{
#ifndef __EMX__
gimp_color_selector_unregister (shutdown_data, completed_cb, completed_data);
#else
mod_color_selector_unregister (shutdown_data, completed_cb, completed_data);
#endif
}
/* definitions and variables */
#define N_BUCKETS 10
#define LAST_BUCKET (N_BUCKETS) /* bucket number 0 is current color */
#define IMAGE_SIZE 200
#define BUCKET_SIZE 20
#define PREVIEW_SIZE 40
typedef struct
{
GimpColorSelectorCallback callback;
gpointer data;
} ColorselWater;
static gdouble bucket[N_BUCKETS + 1][4];
static GtkWidget *color_preview[N_BUCKETS + 1];
static gdouble last_x, last_y, last_pressure;
static gfloat pressure_adjust = 1.0;
static guint32 motion_time;
static gint button_state;
static ColorselWater *coldata;
static void
set_bucket (gint i,
gdouble r,
gdouble g,
gdouble b,
gdouble a)
{
if (i >= 0 && i <= N_BUCKETS)
{
bucket[i][0] = r;
bucket[i][1] = g;
bucket[i][2] = b;
bucket[i][3] = a;
}
}
static gdouble
calc (gdouble x,
gdouble y,
gdouble angle)
{
gdouble s, c;
s = 1.6 * sin (angle * G_PI / 180) * 256.0 / IMAGE_SIZE;
c = 1.6 * cos (angle * G_PI / 180) * 256.0 / IMAGE_SIZE;
return 128 + (x - (IMAGE_SIZE >> 1)) * c - (y - (IMAGE_SIZE >> 1)) * s;
}
static guchar
bucket_to_byte (gdouble val)
{
return CLAMP ((gint) (val * 280 - 25), 0, 255);
}
static void
draw_bucket (gint i)
{
guchar *buf;
gint x, y;
gint width;
gint height;
guchar r, g, b;
g_return_if_fail (i >= 0 && i <= N_BUCKETS);
#ifdef VERBOSE
g_print ("draw_bucket %d\n", i);
#endif
width = (i == 0 ? PREVIEW_SIZE : BUCKET_SIZE);
height = width;
buf = g_new (guchar, 3 * width);
r = bucket_to_byte (bucket[i][0]);
g = bucket_to_byte (bucket[i][1]);
b = bucket_to_byte (bucket[i][2]);
for (x = 0; x < width; x++)
{
buf[x * 3] = r;
buf[x * 3 + 1] = g;
buf[x * 3 + 2] = b;
}
for (y = 0; y < height; y++)
gtk_preview_draw_row (GTK_PREVIEW (color_preview[i]), buf, 0, y, width);
gtk_widget_draw (color_preview[i], NULL);
g_free (buf);
}
static void
draw_all_buckets (void)
{
gint i;
#ifdef VERBOSE
g_print ("drawing all buckets\n");
#endif
for (i = 1; i <= N_BUCKETS; i++)
draw_bucket (i);
}
static void
pick_up_bucket_callback (GtkWidget *widget,
gpointer data)
{
guint i = GPOINTER_TO_UINT (data);
#ifdef VERBOSE
g_print ("pick up bucket %d\n", i);
#endif
if (i > 0 && i <= N_BUCKETS)
{
bucket[0][0] = bucket[i][0];
bucket[0][1] = bucket[i][1];
bucket[0][2] = bucket[i][2];
bucket[0][3] = bucket[i][3];
colorsel_water_update ();
}
}
static void
shift_buckets (void)
{
gint i;
#ifdef VERBOSE
g_print ("shift\n");
#endif
/* to avoid duplication, do nothing if cuurent bucket is already present */
for (i = 1; i <= N_BUCKETS; i++)
{
if (bucket[i][0] == bucket[0][0] &&
bucket[i][1] == bucket[0][1] &&
bucket[i][2] == bucket[0][2] &&
bucket[i][3] == bucket[0][3])
return;
}
/* don't bother storing pure white in buckets */
if (bucket[0][0] == 1.0 &&
bucket[0][1] == 1.0 &&
bucket[0][2] == 1.0)
return;
/* shift all buckets one to the right */
for (i = N_BUCKETS; i > 0; i--)
{
bucket[i][0] = bucket[i-1][0];
bucket[i][1] = bucket[i-1][1];
bucket[i][2] = bucket[i-1][2];
bucket[i][3] = bucket[i-1][3];
}
}
/* Initialize the preview */
static void
select_area_draw (GtkWidget *preview)
{
guchar buf[3 * IMAGE_SIZE];
gint x, y;
gdouble r, g, b;
gdouble dr, dg, db;
for (y = 0; y < IMAGE_SIZE; y++)
{
r = calc (0, y, 0);
g = calc (0, y, 120);
b = calc (0, y, 240);
dr = calc (1, y, 0) - r;
dg = calc (1, y, 120) - g;
db = calc (1, y, 240) - b;
for (x = 0; x < IMAGE_SIZE; x++)
{
buf[x * 3] = CLAMP ((gint) r, 0, 255);
buf[x * 3 + 1] = CLAMP ((gint) g, 0, 255);
buf[x * 3 + 2] = CLAMP ((gint) b, 0, 255);
r += dr;
g += dg;
b += db;
}
gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, y, IMAGE_SIZE);
}
}
static void
add_pigment (gboolean erase,
gdouble x,
gdouble y,
gdouble much)
{
gdouble r, g, b;
much *= (gdouble) pressure_adjust;
#ifdef VERBOSE
g_print ("x: %g, y: %g, much: %g\n", x, y, much);
#endif
if (erase)
{
bucket[0][0] = 1 - (1 - bucket[0][0]) * (1 - much);
bucket[0][1] = 1 - (1 - bucket[0][1]) * (1 - much);
bucket[0][2] = 1 - (1 - bucket[0][2]) * (1 - much);
}
else
{
r = calc (x, y, 0) / 255.0;
if (r < 0) r = 0;
if (r > 1) r = 1;
g = calc (x, y, 120) / 255.0;
if (g < 0) g = 0;
if (g > 1) g = 1;
b = calc (x, y, 240) / 255.0;
if (b < 0) b = 0;
if (b > 1) b = 1;
bucket[0][0] *= (1 - (1 - r) * much);
bucket[0][1] *= (1 - (1 - g) * much);
bucket[0][2] *= (1 - (1 - b) * much);
}
colorsel_water_update ();
}
static void
draw_brush (GtkWidget *widget,
gboolean erase,
gdouble x,
gdouble y,
gdouble pressure)
{
gdouble much; /* how much pigment to mix in */
if (pressure < last_pressure)
last_pressure = pressure;
much = sqrt ((x - last_x) * (x - last_x) +
(y - last_y) * (y - last_y) +
1000 * (pressure - last_pressure) * (pressure - last_pressure));
much *= pressure * 0.05;
add_pigment (erase, x, y, much);
last_x = x;
last_y = y;
last_pressure = pressure;
}
static gint
button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
gboolean erase;
#ifdef VERBOSE
g_print ("button press\n");
#endif
last_x = event->x;
last_y = event->y;
last_pressure = event->pressure;
button_state |= 1 << event->button;
erase = (event->button != 1) ||
(event->source == GDK_SOURCE_ERASER);
add_pigment (erase, event->x, event->y, 0.05);
motion_time = event->time;
return FALSE;
}
static gint
button_release_event (GtkWidget *widget,
GdkEventButton *event)
{
button_state &= ~(1 << event->button);
return TRUE;
}
static gint
motion_notify_event (GtkWidget *widget,
GdkEventMotion *event)
{
GdkTimeCoord *coords;
gint nevents;
gint i;
gboolean erase;
if (event->state & (GDK_BUTTON1_MASK |
GDK_BUTTON2_MASK |
GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK))
{
coords = gdk_input_motion_events (event->window, event->deviceid,
motion_time, event->time,
&nevents);
erase = (event->state &
(GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK)) ||
(event->source == GDK_SOURCE_ERASER);
motion_time = event->time;
if (coords)
{
for (i=0; i<nevents; i++)
draw_brush (widget, erase, coords[i].x, coords[i].y,
coords[i].pressure);
g_free (coords);
}
else
{
if (event->is_hint)
gdk_input_window_get_pointer (event->window, event->deviceid,
#ifdef GTK_HAVE_SIX_VALUATORS
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
#else /* !GTK_HAVE_SIX_VALUATORS */
NULL, NULL, NULL, NULL, NULL, NULL);
#endif /* GTK_HAVE_SIX_VALUATORS */
draw_brush (widget, erase, event->x, event->y,
event->pressure);
}
}
else
{
gdk_input_window_get_pointer (event->window, event->deviceid,
&event->x, &event->y,
#ifdef GTK_HAVE_SIX_VALUATORS
NULL, NULL, NULL, NULL, NULL);
#else /* !GTK_HAVE_SIX_VALUATORS */
NULL, NULL, NULL, NULL);
#endif /* GTK_HAVE_SIX_VALUATORS */
}
return TRUE;
}
static gint
proximity_out_event (GtkWidget *widget,
GdkEventProximity *event)
{
#ifdef VERBOSE
g_print ("proximity out\n");
#endif /* VERBOSE */
return TRUE;
}
static void
new_color_callback (GtkWidget *widget,
gpointer data)
{
#ifdef VERBOSE
g_print ("new color\n");
#endif
shift_buckets ();
/* current bucket becomes white */
bucket[0][0] = 1.0;
bucket[0][1] = 1.0;
bucket[0][2] = 1.0;
bucket[0][3] = 1.0;
draw_all_buckets ();
colorsel_water_update ();
return;
}
static void
reset_color_callback (GtkWidget *widget,
gpointer data)
{
#ifdef VERBOSE
g_print ("reset color\n");
#endif
/* current bucket becomes white */
bucket[0][0] = 1.0;
bucket[0][1] = 1.0;
bucket[0][2] = 1.0;
bucket[0][3] = 1.0;
colorsel_water_update ();
return;
}
static void
pressure_adjust_update (GtkAdjustment *adj,
gpointer data)
{
pressure_adjust = adj->value / 100;
}
/***********/
/* methods */
static GtkWidget*
colorsel_water_new (gint h,
gint s,
gint v,
gint r,
gint g,
gint b,
gint a,
gboolean show_alpha,
GimpColorSelectorCallback callback,
gpointer callback_data,
/* RETURNS: */
gpointer *selector_data)
{
GtkWidget *preview;
GtkWidget *event_box;
GtkWidget *frame;
GtkWidget *hbox;
GtkWidget *hbox2;
GtkWidget *hbox3;
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *vbox3;
GtkWidget *table;
GtkWidget *button;
GtkWidget *bbox;
GtkWidget *label;
GtkObject *adj;
GtkWidget *scale;
guint i;
coldata = g_new (ColorselWater, 1);
coldata->callback = callback;
coldata->data = callback_data;
*selector_data = coldata;
vbox = gtk_vbox_new (FALSE, 0);
hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 4);
/* the event box */
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0);
event_box = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (frame), event_box);
preview = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (preview), IMAGE_SIZE, IMAGE_SIZE);
gtk_container_add (GTK_CONTAINER (event_box), preview);
select_area_draw (preview);
/* Event signals */
gtk_signal_connect (GTK_OBJECT (event_box), "motion_notify_event",
GTK_SIGNAL_FUNC (motion_notify_event),
NULL);
gtk_signal_connect (GTK_OBJECT (event_box), "button_press_event",
GTK_SIGNAL_FUNC (button_press_event),
NULL);
gtk_signal_connect (GTK_OBJECT (event_box), "button_release_event",
GTK_SIGNAL_FUNC (button_release_event),
NULL);
gtk_signal_connect (GTK_OBJECT (event_box), "proximity_out_event",
GTK_SIGNAL_FUNC (proximity_out_event),
NULL);
gtk_widget_set_events (event_box,
GDK_EXPOSURE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_KEY_PRESS_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_PROXIMITY_OUT_MASK);
/* The following call enables tracking and processing of extension
* events for the drawing area
*/
gtk_widget_set_extension_events (event_box, GDK_EXTENSION_EVENTS_ALL);
gtk_widget_grab_focus (event_box);
vbox2 = gtk_vbox_new (FALSE, 0);
gtk_box_pack_end (GTK_BOX (hbox), vbox2, TRUE, FALSE, 0);
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, FALSE, 4);
vbox3 = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox2), vbox3, FALSE, FALSE, 4);
hbox3 = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox3), hbox3, FALSE, FALSE, 4);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (hbox3), frame, TRUE, FALSE, 0);
color_preview[0] = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (color_preview[0]), PREVIEW_SIZE, PREVIEW_SIZE);
gtk_drag_dest_set (color_preview[0],
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
targets, 1,
GDK_ACTION_COPY);
gtk_drag_source_set (color_preview[0],
GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
targets, 1,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_signal_connect (GTK_OBJECT (color_preview[0]), "drag_begin",
GTK_SIGNAL_FUNC (colorsel_water_drag_begin),
bucket[0]);
gtk_signal_connect (GTK_OBJECT (color_preview[0]), "drag_end",
GTK_SIGNAL_FUNC (colorsel_water_drag_end),
bucket[0]);
gtk_signal_connect (GTK_OBJECT (color_preview[0]), "drag_data_get",
GTK_SIGNAL_FUNC (colorsel_water_drag_handle),
bucket[0]);
gtk_signal_connect (GTK_OBJECT (color_preview[0]), "drag_data_received",
GTK_SIGNAL_FUNC (colorsel_water_drop_handle),
bucket[0]);
gtk_container_add (GTK_CONTAINER (frame), color_preview[0]);
bbox = gtk_vbutton_box_new ();
gtk_box_pack_end (GTK_BOX (hbox2), bbox, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("New"));
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (new_color_callback),
NULL);
button = gtk_button_new_with_label (_("Reset"));
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (reset_color_callback),
NULL);
frame = gtk_frame_new (_("Color History"));
gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, FALSE, 0);
table = gtk_table_new (2, 5, TRUE);
gtk_container_set_border_width (GTK_CONTAINER (table), 2);
gtk_container_add (GTK_CONTAINER (frame), table);
for (i = 0; i < N_BUCKETS; i++)
{
button = gtk_button_new ();
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (pick_up_bucket_callback),
GUINT_TO_POINTER (i + 1));
gtk_drag_dest_set (button,
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
targets, 1,
GDK_ACTION_COPY);
gtk_drag_source_set (button,
GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
targets, 1,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_signal_connect (GTK_OBJECT (button), "drag_begin",
GTK_SIGNAL_FUNC (colorsel_water_drag_begin),
bucket[i+1]);
gtk_signal_connect (GTK_OBJECT (button), "drag_end",
GTK_SIGNAL_FUNC (colorsel_water_drag_end),
bucket[i+1]);
gtk_signal_connect (GTK_OBJECT (button), "drag_data_get",
GTK_SIGNAL_FUNC (colorsel_water_drag_handle),
bucket[i+1]);
gtk_signal_connect (GTK_OBJECT (button), "drag_data_received",
GTK_SIGNAL_FUNC (colorsel_water_drop_handle),
bucket[i+1]);
gtk_table_attach_defaults (GTK_TABLE (table),
button,
i % 5, (i % 5) + 1,
i / 5, (i/ 5) + 1);
color_preview[i+1] = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (color_preview[i+1]),
BUCKET_SIZE, BUCKET_SIZE);
gtk_container_add (GTK_CONTAINER (button), color_preview[i+1]);
set_bucket (i + 1, 1.0, 1.0, 1.0, 1.0);
}
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, FALSE, 0);
label = gtk_label_new (_("Pressure:"));
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
adj = gtk_adjustment_new (100.0, 0.0, 200.0, 1.0, 1.0, 0.0);
gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
GTK_SIGNAL_FUNC (pressure_adjust_update), NULL);
scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
gtk_scale_set_digits (GTK_SCALE (scale), 0);
gtk_box_pack_start (GTK_BOX (vbox2), scale, TRUE, TRUE, 0);
gtk_widget_show_all (hbox);
colorsel_water_set_color (coldata, h, s, v, r, g, b, a);
draw_all_buckets ();
return vbox;
}
static void
colorsel_water_free (gpointer selector_data)
{
g_free (selector_data);
}
static void
colorsel_water_set_color (gpointer data,
gint h,
gint s,
gint v,
gint r,
gint g,
gint b,
gint a)
{
set_bucket (0,
((gdouble) r) / 255.999,
((gdouble) g) / 255.999,
((gdouble) b) / 255.999,
((gdouble) a) / 255.999);
draw_bucket (0);
}
static void
colorsel_water_set_channel (gpointer data,
GimpColorSelectorChannelType channel)
{
}
static void
colorsel_water_update (void)
{
gdouble rr;
gdouble gg;
gdouble bb;
gint h;
gint s;
gint v;
gint r;
gint g;
gint b;
gint a;
r = (gint) (bucket[0][0] * 255.999);
g = (gint) (bucket[0][1] * 255.999);
b = (gint) (bucket[0][2] * 255.999);
a = (gint) (bucket[0][3] * 255.999);
rr = bucket[0][0];
gg = bucket[0][1];
bb = bucket[0][2];
gimp_rgb_to_hsv_double (&rr, &gg, &bb);
h = (gint) (rr * 360.99);
s = (gint) (gg * 255.99);
v = (gint) (bb * 255.99);
draw_bucket (0);
coldata->callback (coldata->data, h, s, v, r, g, b, a);
}
static void
colorsel_water_drag_begin (GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
GtkWidget *window;
gdouble *colors;
GdkColor bg;
colors = (gdouble *)data;
window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
gtk_widget_set_usize (window, 32, 32);
gtk_widget_realize (window);
gtk_object_set_data_full (GTK_OBJECT (widget),
"gimp-color-drag-window",
window,
(GtkDestroyNotify) gtk_widget_destroy);
bg.red = 0xffff * colors[0];
bg.green = 0xffff * colors[1];
bg.blue = 0xffff * colors[2];
gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
gdk_window_set_background (window->window, &bg);
gtk_drag_set_icon_widget (context, window, -2, -2);
}
static void
colorsel_water_drag_end (GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
gtk_object_set_data (GTK_OBJECT (widget),
"gimp-color-drag-window", NULL);
}
static void
colorsel_water_drop_handle (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
guint16 *vals;
gdouble *colors;
colors = (gdouble*) data;
if (selection_data->length < 0)
return;
if ((selection_data->format != 16) ||
(selection_data->length != 8))
{
g_warning ("Received invalid color data\n");
return;
}
vals = (guint16 *) selection_data->data;
colors[0] = (gdouble)vals[0] / 0xffff;
colors[1] = (gdouble)vals[1] / 0xffff;
colors[2] = (gdouble)vals[2] / 0xffff;
colors[3] = (gdouble)vals[3] / 0xffff;
draw_all_buckets ();
colorsel_water_update ();
}
static void
colorsel_water_drag_handle (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
guint16 vals[4];
gdouble *colors;
colors = (gdouble*) data;
vals[0] = colors[0] * 0xffff;
vals[1] = colors[1] * 0xffff;
vals[2] = colors[2] * 0xffff;
vals[3] = colors[3] * 0xffff;
gtk_selection_data_set (selection_data,
gdk_atom_intern ("application/x-color", FALSE),
16, (guchar *)vals, 8);
}