mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 20:41:43 +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.
397 lines
11 KiB
C
397 lines
11 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "apptypes.h"
|
|
|
|
#include "appenv.h"
|
|
#include "channel.h"
|
|
#include "color_panel.h"
|
|
#include "drawable.h"
|
|
#include "floating_sel.h"
|
|
#include "gdisplay.h"
|
|
#include "gimage_mask.h"
|
|
#include "gimpimage.h"
|
|
#include "gimpcontext.h"
|
|
#include "gimpui.h"
|
|
#include "global_edit.h"
|
|
#include "qmask.h"
|
|
#include "undo.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
struct _EditQmaskOptions
|
|
{
|
|
GtkWidget *query_box;
|
|
GtkWidget *name_entry;
|
|
|
|
GimpImage *gimage;
|
|
ColorPanel *color_panel;
|
|
gdouble opacity;
|
|
};
|
|
|
|
typedef struct _EditQmaskOptions EditQmaskOptions;
|
|
|
|
/* Global variables */
|
|
/* Static variables */
|
|
/* Prototypes */
|
|
static void edit_qmask_channel_query (GDisplay *gdisp);
|
|
static void edit_qmask_query_ok_callback (GtkWidget *widget,
|
|
gpointer client_data);
|
|
static void edit_qmask_query_cancel_callback (GtkWidget *widget,
|
|
gpointer client_data);
|
|
static void qmask_query_scale_update (GtkAdjustment *adjustment,
|
|
gdouble *scale_val);
|
|
static void qmask_removed_callback (GtkObject *qmask,
|
|
gpointer data);
|
|
|
|
/* Actual code */
|
|
|
|
static void
|
|
qmask_query_scale_update (GtkAdjustment *adjustment,
|
|
gdouble *scale_val)
|
|
{
|
|
*scale_val = adjustment->value;
|
|
}
|
|
|
|
static void
|
|
qmask_removed_callback (GtkObject *qmask,
|
|
gpointer data)
|
|
{
|
|
GDisplay *gdisp = (GDisplay*) data;
|
|
|
|
if (!gdisp->gimage)
|
|
return;
|
|
|
|
gdisp->gimage->qmask_state = FALSE;
|
|
|
|
qmask_buttons_update (gdisp);
|
|
}
|
|
|
|
|
|
void
|
|
qmask_buttons_update (GDisplay *gdisp)
|
|
{
|
|
g_assert (gdisp);
|
|
g_assert (gdisp->gimage);
|
|
|
|
if (gdisp->gimage->qmask_state != GTK_TOGGLE_BUTTON (gdisp->qmaskon)->active)
|
|
{
|
|
/* Disable toggle from doing anything */
|
|
gtk_signal_handler_block_by_func(GTK_OBJECT(gdisp->qmaskoff),
|
|
(GtkSignalFunc) qmask_deactivate,
|
|
gdisp);
|
|
gtk_signal_handler_block_by_func(GTK_OBJECT(gdisp->qmaskon),
|
|
(GtkSignalFunc) qmask_activate,
|
|
gdisp);
|
|
|
|
/* Change the state of the buttons */
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdisp->qmaskon),
|
|
gdisp->gimage->qmask_state);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdisp->qmaskoff),
|
|
!gdisp->gimage->qmask_state);
|
|
|
|
/* Enable toggle again */
|
|
gtk_signal_handler_unblock_by_func(GTK_OBJECT(gdisp->qmaskoff),
|
|
(GtkSignalFunc) qmask_deactivate,
|
|
gdisp);
|
|
gtk_signal_handler_unblock_by_func(GTK_OBJECT(gdisp->qmaskon),
|
|
(GtkSignalFunc) qmask_activate,
|
|
gdisp);
|
|
}
|
|
}
|
|
|
|
void
|
|
qmask_click_handler (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer data)
|
|
{
|
|
GDisplay *gdisp;
|
|
gdisp = (GDisplay *)data;
|
|
|
|
if ((event->type == GDK_2BUTTON_PRESS) &&
|
|
(event->button == 1))
|
|
{
|
|
edit_qmask_channel_query(gdisp);
|
|
}
|
|
}
|
|
|
|
void
|
|
qmask_deactivate (GtkWidget *widget,
|
|
GDisplay *gdisp)
|
|
{
|
|
GimpImage *gimg;
|
|
GimpChannel *gmask;
|
|
|
|
if (gdisp)
|
|
{
|
|
gimg = gdisp->gimage;
|
|
if (!gimg)
|
|
return;
|
|
|
|
if (!gdisp->gimage->qmask_state)
|
|
return; /* if already set do nothing */
|
|
|
|
if ( (gmask = gimp_image_get_channel_by_name (gimg, "Qmask")) )
|
|
{
|
|
undo_push_group_start (gimg, QMASK_UNDO);
|
|
/* push the undo here since removing the mask will
|
|
call the qmask_removed_callback() which will set
|
|
the qmask_state to FALSE */
|
|
undo_push_qmask (gimg);
|
|
gimage_mask_load (gimg, gmask);
|
|
gimp_image_remove_channel (gimg, gmask);
|
|
undo_push_group_end (gimg);
|
|
}
|
|
|
|
gdisp->gimage->qmask_state = FALSE;
|
|
|
|
if (gmask)
|
|
gdisplays_flush ();
|
|
}
|
|
}
|
|
|
|
void
|
|
qmask_activate (GtkWidget *widget,
|
|
GDisplay *gdisp)
|
|
{
|
|
GimpImage *gimg;
|
|
GimpChannel *gmask;
|
|
GimpLayer *layer;
|
|
|
|
gdouble opacity;
|
|
guchar *color;
|
|
|
|
if (gdisp)
|
|
{
|
|
gimg = gdisp->gimage;
|
|
if (!gimg)
|
|
return;
|
|
|
|
if (gdisp->gimage->qmask_state)
|
|
return; /* If already set, do nothing */
|
|
|
|
/* Set the defaults */
|
|
opacity = (gdouble) gimg->qmask_opacity;
|
|
color = gimg->qmask_color;
|
|
|
|
if ( (gmask = gimp_image_get_channel_by_name (gimg, "Qmask")) )
|
|
{
|
|
gimg->qmask_state = TRUE;
|
|
/* if the user was clever and created his own */
|
|
return;
|
|
}
|
|
|
|
undo_push_group_start (gimg, QMASK_UNDO);
|
|
|
|
if (gimage_mask_is_empty (gimg))
|
|
{
|
|
if ((layer = gimp_image_floating_sel (gimg)))
|
|
{
|
|
floating_sel_to_layer (layer);
|
|
}
|
|
/* if no selection */
|
|
gmask = channel_new (gimg,
|
|
gimg->width,
|
|
gimg->height,
|
|
"Qmask",
|
|
(gint)(255*opacity)/100,
|
|
color);
|
|
gimp_image_add_channel (gimg, gmask, 0);
|
|
gimp_drawable_fill (GIMP_DRAWABLE (gmask), 0, 0, 0, 0);
|
|
}
|
|
else
|
|
{ /* if selection */
|
|
gmask = channel_copy (gimp_image_get_mask (gimg));
|
|
gimp_image_add_channel (gimg, gmask, 0);
|
|
channel_set_color (gmask, color);
|
|
drawable_set_name (GIMP_DRAWABLE (gmask), "Qmask");
|
|
channel_set_opacity (gmask, opacity);
|
|
gimage_mask_none (gimg); /* Clear the selection */
|
|
}
|
|
|
|
undo_push_qmask (gimg);
|
|
undo_push_group_end (gimg);
|
|
gdisp->gimage->qmask_state = TRUE;
|
|
gdisplays_flush ();
|
|
|
|
/* connect to the removed signal, so the buttons get updated */
|
|
gtk_signal_connect (GTK_OBJECT (gmask), "removed",
|
|
GTK_SIGNAL_FUNC (qmask_removed_callback), gdisp);
|
|
}
|
|
}
|
|
|
|
static void
|
|
edit_qmask_channel_query (GDisplay * gdisp)
|
|
{
|
|
EditQmaskOptions *options;
|
|
GtkWidget *hbox;
|
|
GtkWidget *vbox;
|
|
GtkWidget *table;
|
|
GtkWidget *label;
|
|
GtkWidget *opacity_scale;
|
|
GtkObject *opacity_scale_data;
|
|
guchar r, g, b, a;
|
|
|
|
/* channel = gimp_image_get_channel_by_name (gdisp->gimage, "Qmask"); */
|
|
/* the new options structure */
|
|
options = g_new (EditQmaskOptions, 1);
|
|
options->gimage = gdisp->gimage;
|
|
options->opacity = (gdouble) options->gimage->qmask_opacity;
|
|
|
|
r = options->gimage->qmask_color[0];
|
|
g = options->gimage->qmask_color[1];
|
|
b = options->gimage->qmask_color[2];
|
|
a = 255;
|
|
|
|
options->color_panel = color_panel_new (r, g, b, a, FALSE, 48, 64);
|
|
|
|
/* The dialog */
|
|
options->query_box =
|
|
gimp_dialog_new (_("Edit Qmask Attributes"), "edit_qmask_attributes",
|
|
gimp_standard_help_func,
|
|
"dialogs/edit_qmask_attributes.html",
|
|
GTK_WIN_POS_MOUSE,
|
|
FALSE, TRUE, FALSE,
|
|
|
|
_("OK"), edit_qmask_query_ok_callback,
|
|
options, NULL, NULL, TRUE, FALSE,
|
|
_("Cancel"), edit_qmask_query_cancel_callback,
|
|
options, NULL, NULL, FALSE, TRUE,
|
|
|
|
NULL);
|
|
|
|
/* The main hbox */
|
|
hbox = gtk_hbox_new (FALSE, 2);
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
|
|
hbox);
|
|
/* The vbox */
|
|
vbox = gtk_vbox_new (FALSE, 2);
|
|
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
|
|
|
/* The table */
|
|
table = gtk_table_new (2, 3, FALSE);
|
|
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
|
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
|
|
|
/* The opacity scale */
|
|
label = gtk_label_new (_("Mask Opacity:"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
|
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
|
|
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
|
|
gtk_widget_show (label);
|
|
|
|
opacity_scale_data =
|
|
gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
|
|
opacity_scale = gtk_hscale_new (GTK_ADJUSTMENT (opacity_scale_data));
|
|
gtk_table_attach_defaults (GTK_TABLE (table), opacity_scale, 1, 2, 1, 2);
|
|
gtk_scale_set_value_pos (GTK_SCALE (opacity_scale), GTK_POS_TOP);
|
|
gtk_signal_connect (GTK_OBJECT (opacity_scale_data), "value_changed",
|
|
(GtkSignalFunc) qmask_query_scale_update,
|
|
&options->opacity);
|
|
gtk_widget_show (opacity_scale);
|
|
|
|
/* The color panel */
|
|
gtk_box_pack_start (GTK_BOX (hbox), options->color_panel->color_panel_widget,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_show (options->color_panel->color_panel_widget);
|
|
|
|
gtk_widget_show (table);
|
|
gtk_widget_show (vbox);
|
|
gtk_widget_show (hbox);
|
|
gtk_widget_show (options->query_box);
|
|
}
|
|
|
|
static void
|
|
edit_qmask_query_ok_callback (GtkWidget *widget,
|
|
gpointer client_data)
|
|
{
|
|
EditQmaskOptions *options;
|
|
Channel *channel;
|
|
const guchar *tmpcolp;
|
|
guchar tmpcol[3];
|
|
gboolean update = FALSE;
|
|
gint opacity;
|
|
gint i;
|
|
|
|
options = (EditQmaskOptions *) client_data;
|
|
channel = gimp_image_get_channel_by_name (options->gimage, "Qmask");
|
|
opacity = (gint) (255 * options->opacity/100);
|
|
|
|
if (options->gimage && channel)
|
|
{ /* don't update if opacity hasn't changed */
|
|
if (channel_get_opacity(channel) != opacity)
|
|
{
|
|
update = TRUE;
|
|
}
|
|
tmpcolp = channel_get_color (channel);
|
|
for (i = 0; i < 3; i++)
|
|
{ /* don't update if color hasn't changed */
|
|
tmpcol[i] = tmpcolp[i]; /* initialize to same values */
|
|
if (options->color_panel->color[i] != tmpcolp[i])
|
|
{
|
|
tmpcol[i] = options->color_panel->color[i];
|
|
update = TRUE;
|
|
}
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
channel_set_opacity(channel, 100*opacity/255);
|
|
channel_set_color(channel,tmpcol);
|
|
channel_update (channel);
|
|
}
|
|
}
|
|
/* update the qmask color no matter what */
|
|
for (i = 0; i < 3; i++)
|
|
{ /* TODO: should really have accessor functions for gimage private stuff */
|
|
options->gimage->qmask_color[i] = options->color_panel->color[i];
|
|
options->gimage->qmask_opacity = (gint) 100*opacity/255;
|
|
}
|
|
|
|
gtk_widget_destroy (options->query_box);
|
|
g_free (options);
|
|
}
|
|
|
|
static void
|
|
edit_qmask_query_cancel_callback (GtkWidget *widget,
|
|
gpointer client_data)
|
|
{
|
|
EditQmaskOptions *options;
|
|
|
|
options = (EditQmaskOptions *) client_data;
|
|
|
|
gtk_widget_destroy (options->query_box);
|
|
g_free (options);
|
|
}
|
|
|
|
|
|
|
|
|
|
|