mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-21 20:12:30 +00:00
ab014f8b3a
2001-01-07 Michael Natterer <mitch@gimp.org> * app/by_color_select.c * app/channels_dialog.c * app/color_area.c * app/color_notebook.[ch] * app/color_panel.[ch] * app/color_picker.c * app/color_select.c * app/colormap_dialog.i.c * app/devices.c * app/disp_callbacks.[ch] * app/gimpdnd.[ch] * app/palette.c * app/qmask.c * libgimp/gimpcolorselector.h * modules/colorsel_gtk.c * modules/colorsel_triangle.c * modules/colorsel_water.c: made the color_notebook, the color_area and DND speak in terms of RGBA instead of GRB. The alpha value is not used yet, only the API changed. Everything should work exactly as before.
903 lines
22 KiB
C
903 lines
22 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/gimpmodule.h>
|
|
#include <libgimp/gimpmath.h>
|
|
|
|
#include "gimpmodregister.h"
|
|
|
|
#include <libgimp/gimpintl.h>
|
|
|
|
/* prototypes */
|
|
static GtkWidget * colorsel_water_new (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_setcolor (gpointer data,
|
|
gint r,
|
|
gint g,
|
|
gint b,
|
|
gint a,
|
|
gboolean set_current);
|
|
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_setcolor
|
|
};
|
|
|
|
|
|
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 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_setcolor (coldata, r, g, b, a, 0);
|
|
draw_all_buckets ();
|
|
|
|
return vbox;
|
|
}
|
|
|
|
|
|
static void
|
|
colorsel_water_free (gpointer selector_data)
|
|
{
|
|
g_free (selector_data);
|
|
}
|
|
|
|
static void
|
|
colorsel_water_setcolor (gpointer data,
|
|
gint r,
|
|
gint g,
|
|
gint b,
|
|
gint a,
|
|
gboolean set_current)
|
|
{
|
|
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_update (void)
|
|
{
|
|
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);
|
|
|
|
draw_bucket (0);
|
|
|
|
coldata->callback (coldata->data, 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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|