mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 20:41:43 +00:00
37fe1a885d
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...
941 lines
23 KiB
C
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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|