mirror of https://github.com/GNOME/gimp.git
311 lines
8.1 KiB
C
311 lines
8.1 KiB
C
|
/* LIBGIMP - The GIMP Library
|
||
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||
|
*
|
||
|
* Gimp Color Button
|
||
|
* Copyright (C) 1999 Sven Neumann
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Library General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library 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
|
||
|
* Library General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Library General Public
|
||
|
* License along with this library; if not, write to the
|
||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||
|
* Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
/* TODO:
|
||
|
*
|
||
|
* add DND -- this will be trivial as soon as gimpdnd.[ch] is moved into libgimp
|
||
|
*
|
||
|
* handle bytes != 3|4 -- would we have to provide a special color select dialog
|
||
|
* for that case? Another possibility could be to destroy
|
||
|
* all color-related widgets in the gtk colorselector.
|
||
|
*/
|
||
|
|
||
|
#include "gimpcolorbutton.h"
|
||
|
#include "gimplimits.h"
|
||
|
|
||
|
|
||
|
static void gimp_color_button_destroy (GtkObject *object);
|
||
|
static void gimp_color_button_clicked (GtkButton *button);
|
||
|
static void gimp_color_button_paint (GimpColorButton *gcb);
|
||
|
|
||
|
static void gimp_color_button_dialog_ok (GtkWidget *widget, gpointer data);
|
||
|
static void gimp_color_button_dialog_cancel (GtkWidget *widget, gpointer data);
|
||
|
|
||
|
enum {
|
||
|
COLOR_CHANGED,
|
||
|
LAST_SIGNAL
|
||
|
};
|
||
|
|
||
|
static gint gimp_color_button_signals[LAST_SIGNAL] = { 0 };
|
||
|
|
||
|
|
||
|
static GtkWidgetClass *parent_class = NULL;
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_destroy (GtkObject *object)
|
||
|
{
|
||
|
GimpColorButton *gcb;
|
||
|
|
||
|
g_return_if_fail (gcb = GIMP_COLOR_BUTTON (object));
|
||
|
|
||
|
g_free (gcb->title);
|
||
|
|
||
|
if (gcb->dialog)
|
||
|
gtk_widget_destroy (gcb->dialog);
|
||
|
|
||
|
g_free (gcb->dcolor);
|
||
|
g_free (gcb->even);
|
||
|
g_free (gcb->odd);
|
||
|
|
||
|
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
||
|
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_class_init (GimpColorButtonClass *class)
|
||
|
{
|
||
|
GtkObjectClass *object_class;
|
||
|
GtkButtonClass *widget_class;
|
||
|
|
||
|
object_class = (GtkObjectClass*) class;
|
||
|
widget_class = (GtkButtonClass*) class;
|
||
|
|
||
|
parent_class = gtk_type_class (gtk_widget_get_type ());
|
||
|
|
||
|
gimp_color_button_signals[COLOR_CHANGED] =
|
||
|
gtk_signal_new ("color_changed",
|
||
|
GTK_RUN_FIRST,
|
||
|
object_class->type,
|
||
|
GTK_SIGNAL_OFFSET (GimpColorButtonClass,
|
||
|
color_changed),
|
||
|
gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
|
||
|
gtk_object_class_add_signals (object_class, gimp_color_button_signals,
|
||
|
LAST_SIGNAL);
|
||
|
class->color_changed = NULL;
|
||
|
|
||
|
widget_class->clicked = gimp_color_button_clicked;
|
||
|
object_class->destroy = gimp_color_button_destroy;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_init (GimpColorButton *gcb)
|
||
|
{
|
||
|
gcb->title = NULL;
|
||
|
gcb->bpp = 0;
|
||
|
gcb->color = NULL;
|
||
|
|
||
|
gcb->dcolor = NULL;
|
||
|
gcb->preview = NULL;
|
||
|
gcb->dialog = NULL;
|
||
|
|
||
|
gcb->even = NULL;
|
||
|
gcb->odd = NULL;
|
||
|
}
|
||
|
|
||
|
GtkType
|
||
|
gimp_color_button_get_type (void)
|
||
|
{
|
||
|
static guint gcb_type = 0;
|
||
|
|
||
|
if (!gcb_type)
|
||
|
{
|
||
|
GtkTypeInfo gcb_info =
|
||
|
{
|
||
|
"GimpColorButton",
|
||
|
sizeof (GimpColorButton),
|
||
|
sizeof (GimpColorButtonClass),
|
||
|
(GtkClassInitFunc) gimp_color_button_class_init,
|
||
|
(GtkObjectInitFunc) gimp_color_button_init,
|
||
|
/* reserved_1 */ NULL,
|
||
|
/* reserved_2 */ NULL,
|
||
|
(GtkClassInitFunc) NULL
|
||
|
};
|
||
|
|
||
|
gcb_type = gtk_type_unique (gtk_button_get_type (), &gcb_info);
|
||
|
}
|
||
|
|
||
|
return gcb_type;
|
||
|
}
|
||
|
|
||
|
|
||
|
GtkWidget*
|
||
|
gimp_color_button_new (gchar *title,
|
||
|
gint width,
|
||
|
gint height,
|
||
|
guchar *color,
|
||
|
gint bpp)
|
||
|
{
|
||
|
GimpColorButton *gcb;
|
||
|
gint i;
|
||
|
|
||
|
g_return_val_if_fail (width > 0 && height > 0, NULL);
|
||
|
g_return_val_if_fail (bpp == 3 || bpp == 4, NULL);
|
||
|
|
||
|
gcb = gtk_type_new (gimp_color_button_get_type ());
|
||
|
|
||
|
gcb->title = g_strdup (title);
|
||
|
gcb->width = width;
|
||
|
gcb->height = height;
|
||
|
gcb->color = color;
|
||
|
gcb->bpp = bpp;
|
||
|
|
||
|
gcb->dcolor = g_new (gdouble, 4);
|
||
|
gcb->even = g_new (guchar, 3 * width);
|
||
|
gcb->odd = g_new (guchar, 3 * width);
|
||
|
|
||
|
for (i = 0; i < bpp; i++)
|
||
|
gcb->dcolor[i] = (gdouble)color[i] / 255.0;
|
||
|
|
||
|
if (bpp == 3)
|
||
|
gcb->dcolor[3] = 1.0;
|
||
|
|
||
|
gcb->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
|
||
|
gtk_signal_connect (GTK_OBJECT (gcb->preview), "destroy",
|
||
|
gtk_widget_destroyed, &gcb->preview);
|
||
|
gtk_preview_size (GTK_PREVIEW (gcb->preview), width, height);
|
||
|
gtk_container_add (GTK_CONTAINER (gcb), gcb->preview);
|
||
|
gtk_widget_show (gcb->preview);
|
||
|
gimp_color_button_paint (gcb);
|
||
|
|
||
|
return (GTK_WIDGET (gcb));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_clicked (GtkButton *button)
|
||
|
{
|
||
|
GimpColorButton *gcb;
|
||
|
GtkColorSelection *colorsel;
|
||
|
|
||
|
g_return_if_fail (GIMP_IS_COLOR_BUTTON (button));
|
||
|
gcb = GIMP_COLOR_BUTTON (button);
|
||
|
|
||
|
if (!gcb->dialog)
|
||
|
{
|
||
|
gcb->dialog = gtk_color_selection_dialog_new (gcb->title);
|
||
|
colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (gcb->dialog)->colorsel);
|
||
|
gtk_color_selection_set_opacity (colorsel, (gcb->bpp == 4));
|
||
|
gtk_color_selection_set_color (colorsel, gcb->dcolor);
|
||
|
gtk_widget_destroy (GTK_COLOR_SELECTION_DIALOG (gcb->dialog)->help_button);
|
||
|
gtk_signal_connect (GTK_OBJECT (gcb->dialog), "destroy",
|
||
|
(GtkSignalFunc) gtk_widget_destroyed, &gcb->dialog);
|
||
|
gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (gcb->dialog)->ok_button),
|
||
|
"clicked",
|
||
|
(GtkSignalFunc) gimp_color_button_dialog_ok, gcb);
|
||
|
gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (gcb->dialog)->cancel_button),
|
||
|
"clicked",
|
||
|
(GtkSignalFunc) gimp_color_button_dialog_cancel, gcb);
|
||
|
gtk_window_position (GTK_WINDOW (gcb->dialog), GTK_WIN_POS_MOUSE);
|
||
|
}
|
||
|
gtk_widget_show (gcb->dialog);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_paint (GimpColorButton *gcb)
|
||
|
{
|
||
|
gint x, y, i;
|
||
|
gdouble c0, c1;
|
||
|
guchar *p0, *p1;
|
||
|
|
||
|
g_return_if_fail (GIMP_IS_COLOR_BUTTON (gcb));
|
||
|
|
||
|
p0 = gcb->even;
|
||
|
p1 = gcb->odd;
|
||
|
|
||
|
if (gcb->bpp == 3)
|
||
|
{
|
||
|
for (x = 0; x < gcb->width; x++)
|
||
|
{
|
||
|
for (i = 0; i < 3; i++)
|
||
|
*p0++ = gcb->dcolor[i] * 255.999;
|
||
|
}
|
||
|
for (y = 0; y < gcb->height; y++)
|
||
|
gtk_preview_draw_row (GTK_PREVIEW (gcb->preview), gcb->even, 0, y, gcb->width);
|
||
|
}
|
||
|
else /* gcb->bpp == 4 */
|
||
|
{
|
||
|
for (x = 0; x < gcb->width; x++)
|
||
|
{
|
||
|
if ((x / GIMP_CHECK_SIZE_SM) & 1)
|
||
|
{
|
||
|
c0 = GIMP_CHECK_LIGHT;
|
||
|
c1 = GIMP_CHECK_DARK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c0 = GIMP_CHECK_DARK;
|
||
|
c1 = GIMP_CHECK_LIGHT;
|
||
|
}
|
||
|
for (i = 0; i < 3; i++)
|
||
|
{
|
||
|
*p0++ = (c0 + (gcb->dcolor[i] - c0) * gcb->dcolor[3]) * 255.999;
|
||
|
*p1++ = (c1 + (gcb->dcolor[i] - c1) * gcb->dcolor[3]) * 255.999;
|
||
|
}
|
||
|
}
|
||
|
for (y = 0; y < gcb->height; y++)
|
||
|
{
|
||
|
if ((y / GIMP_CHECK_SIZE_SM) & 1)
|
||
|
gtk_preview_draw_row (GTK_PREVIEW (gcb->preview), gcb->odd, 0, y, gcb->width);
|
||
|
else
|
||
|
gtk_preview_draw_row (GTK_PREVIEW (gcb->preview), gcb->even, 0, y, gcb->width);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gtk_widget_queue_draw (gcb->preview);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_dialog_ok (GtkWidget *widget,
|
||
|
gpointer data)
|
||
|
{
|
||
|
GimpColorButton *gcb;
|
||
|
guchar new_color[4];
|
||
|
gboolean color_changed = FALSE;
|
||
|
gint i;
|
||
|
|
||
|
g_return_if_fail (GIMP_IS_COLOR_BUTTON (data));
|
||
|
gcb = GIMP_COLOR_BUTTON (data);
|
||
|
|
||
|
gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (gcb->dialog)->colorsel), gcb->dcolor);
|
||
|
|
||
|
for (i = 0; i < gcb->bpp; i++)
|
||
|
{
|
||
|
new_color[i] = gcb->dcolor[i] * 255.999;
|
||
|
if (new_color[i] != gcb->color[i])
|
||
|
color_changed = TRUE;
|
||
|
gcb->color[i] = new_color[i];
|
||
|
}
|
||
|
|
||
|
gtk_widget_destroy (gcb->dialog);
|
||
|
|
||
|
gimp_color_button_paint (gcb);
|
||
|
|
||
|
if (color_changed)
|
||
|
gtk_signal_emit (GTK_OBJECT (gcb),
|
||
|
gimp_color_button_signals[COLOR_CHANGED]);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gimp_color_button_dialog_cancel (GtkWidget *widget,
|
||
|
gpointer data)
|
||
|
{
|
||
|
GimpColorButton *gcb;
|
||
|
|
||
|
g_return_if_fail (GIMP_IS_COLOR_BUTTON (data));
|
||
|
gcb = GIMP_COLOR_BUTTON (data);
|
||
|
|
||
|
gtk_widget_destroy (gcb->dialog);
|
||
|
}
|
||
|
|
||
|
|
||
|
|