home *** CD-ROM | disk | FTP | other *** search
- /* 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 <gtk/gtk.h>
- #include <gdk/gdkkeysyms.h>
-
- #include "apptypes.h"
-
- #include "appenv.h"
- #include "channels_dialog.h"
- #include "color_panel.h"
- #include "drawable.h"
- #include "gdisplay.h"
- #include "gimage.h"
- #include "gimage_mask.h"
- #include "gimpdnd.h"
- #include "gimppreviewcache.h"
- #include "gimprc.h"
- #include "gimpui.h"
- #include "layers_dialogP.h"
- #include "lc_dialogP.h"
- #include "menus.h"
- #include "ops_buttons.h"
- #include "paint_funcs.h"
- #include "undo.h"
-
- #include "channel_pvt.h"
-
- #include "libgimp/gimpintl.h"
- #include "libgimp/gimpmath.h"
-
- #include "pixmaps/eye.xbm"
- #include "pixmaps/channel.xbm"
- #include "pixmaps/new.xpm"
- #include "pixmaps/raise.xpm"
- #include "pixmaps/lower.xpm"
- #include "pixmaps/duplicate.xpm"
- #include "pixmaps/delete.xpm"
- #include "pixmaps/toselection.xpm"
-
- #define COMPONENT_BASE_ID 0x10000000
-
- typedef struct _ChannelsDialog ChannelsDialog;
-
- struct _ChannelsDialog
- {
- GtkWidget *vbox;
- GtkWidget *channel_list;
- GtkWidget *scrolled_win;
- GtkWidget *preview;
- GtkWidget *ops_menu;
- GtkAccelGroup *accel_group;
-
- /* state information */
- GimpImage *gimage;
- gint image_width, image_height;
- gint gimage_width, gimage_height;
- gdouble ratio;
-
- gint num_components;
- gint base_type;
- ChannelType components[3];
-
- Channel *active_channel;
- Layer *floating_sel;
- GSList *channel_widgets;
- };
-
- typedef struct _ChannelWidget ChannelWidget;
-
- struct _ChannelWidget
- {
- GtkWidget *eye_widget;
- GtkWidget *clip_widget;
- GtkWidget *channel_preview;
- GtkWidget *list_item;
- GtkWidget *label;
-
- GdkPixmap *channel_pixmap;
-
- /* state information */
- GimpImage *gimage;
- Channel *channel;
- gint width, height;
-
- ChannelType type;
- gint ID;
- gboolean visited;
-
- GimpDropType drop_type;
- };
-
- /* channels dialog widget routines */
- static void channels_dialog_preview_extents (void);
- static void channels_dialog_set_menu_sensitivity (void);
- static void channels_dialog_set_channel (ChannelWidget *cw);
- static void channels_dialog_unset_channel (ChannelWidget *cw);
- static void channels_dialog_position_channel (Channel *channel,
- gint position);
- static void channels_dialog_add_channel (Channel *channel);
- static void channels_dialog_remove_channel (ChannelWidget *cw);
-
- static gint channel_list_events (GtkWidget *widget,
- GdkEvent *event);
-
- /* for (un)installing the menu accelarators */
- static void channels_dialog_map_callback (GtkWidget *widget,
- gpointer data);
- static void channels_dialog_unmap_callback (GtkWidget *widget,
- gpointer data);
-
- /* ops buttons dnd callbacks */
- static gboolean channels_dialog_drag_new_channel_callback
- (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
- static gboolean channels_dialog_drag_duplicate_channel_callback
- (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
- static gboolean channels_dialog_drag_channel_to_sel_callback
- (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
- static gboolean channels_dialog_drag_delete_channel_callback
- (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
-
- /* channel widget function prototypes */
- static ChannelWidget * channel_widget_get_ID (Channel *channel);
- static ChannelWidget * channel_widget_create (GimpImage *gimage,
- Channel *channel,
- ChannelType channel_type);
-
- static gboolean channel_widget_drag_motion_callback
- (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
- static gboolean channel_widget_drag_drop_callback(GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time);
- static void channel_widget_drag_begin_callback (GtkWidget *widget,
- GdkDragContext *context);
- static void channel_widget_drag_leave_callback (GtkWidget *widget,
- GdkDragContext *context,
- guint time);
- static void channel_widget_drag_indicator_callback
- (GtkWidget *widget,
- gpointer data);
-
- static void channel_widget_drop_color (GtkWidget *widget,
- guchar r,
- guchar g,
- guchar b,
- gpointer data);
- static void channel_widget_draw_drop_indicator (ChannelWidget *cw,
- GimpDropType drop_type);
- static void channel_widget_delete (ChannelWidget *cw);
- static void channel_widget_select_update (GtkWidget *widget,
- gpointer data);
- static gint channel_widget_button_events (GtkWidget *widget,
- GdkEvent *event,
- gpointer data);
- static gint channel_widget_preview_events (GtkWidget *widget,
- GdkEvent *event,
- gpointer data);
- static void channel_widget_preview_redraw (ChannelWidget *cw);
- static void channel_widget_no_preview_redraw (ChannelWidget *cw);
- static void channel_widget_eye_redraw (ChannelWidget *cw);
- static void channel_widget_exclusive_visible (ChannelWidget *cw);
- static void channel_widget_channel_flush (GtkWidget *widget,
- gpointer data);
-
- /* assorted query dialogs */
- static void channels_dialog_new_channel_query (GimpImage *gimage);
- static void channels_dialog_edit_channel_query (ChannelWidget *cw);
-
- /****************/
- /* Local data */
- /****************/
-
- static ChannelsDialog *channelsD = NULL;
-
- static GdkPixmap *eye_pixmap[] = { NULL, NULL, NULL };
- static GdkPixmap *channel_pixmap[] = { NULL, NULL, NULL };
-
- static gint suspend_gimage_notify = 0;
-
- /* the ops buttons */
- static GtkSignalFunc to_selection_ext_callbacks[] =
- {
- channels_dialog_add_channel_to_sel_callback, /* SHIFT */
- channels_dialog_sub_channel_from_sel_callback, /* CTRL */
- channels_dialog_intersect_channel_with_sel_callback, /* MOD1 */
- channels_dialog_intersect_channel_with_sel_callback, /* SHIFT + CTRL */
- };
-
- static OpsButton channels_ops_buttons[] =
- {
- { new_xpm, channels_dialog_new_channel_callback, NULL,
- N_("New Channel"),
- "channels/dialogs/new_channel.html",
- NULL, 0 },
- { raise_xpm, channels_dialog_raise_channel_callback, NULL,
- N_("Raise Channel"),
- "channels/raise_channel.html",
- NULL, 0 },
- { lower_xpm, channels_dialog_lower_channel_callback, NULL,
- N_("Lower Channel"),
- "channels/lower_channel.html",
- NULL, 0 },
- { duplicate_xpm, channels_dialog_duplicate_channel_callback, NULL,
- N_("Duplicate Channel"),
- "channels/duplicate_channel.html",
- NULL, 0 },
- { toselection_xpm, channels_dialog_channel_to_sel_callback,
- to_selection_ext_callbacks,
- N_("Channel to Selection \n"
- "<Shift> Add "
- "<Ctrl> Subtract "
- "<Shift><Ctrl> Intersect"),
- "channels/channel_to_selection.html",
- NULL, 0 },
- { delete_xpm, channels_dialog_delete_channel_callback, NULL,
- N_("Delete Channel"),
- "channels/delete_channel.html",
- NULL, 0 },
- { NULL, NULL, NULL, NULL, NULL, NULL, 0 }
- };
-
- /* dnd structures */
- static GtkTargetEntry channel_color_target_table[] =
- {
- GIMP_TARGET_CHANNEL,
- GIMP_TARGET_COLOR
- };
- static guint n_channel_color_targets = (sizeof (channel_color_target_table) /
- sizeof (channel_color_target_table[0]));
-
- static GtkTargetEntry channel_target_table[] =
- {
- GIMP_TARGET_CHANNEL
- };
- static guint n_channel_targets = (sizeof (channel_target_table) /
- sizeof (channel_target_table[0]));
-
- static GtkTargetEntry component_target_table[] =
- {
- GIMP_TARGET_COMPONENT
- };
- static guint n_component_targets = (sizeof (component_target_table) /
- sizeof (component_target_table[0]));
-
-
- /**************************************/
- /* Public channels dialog functions */
- /**************************************/
-
- GtkWidget *
- channels_dialog_create (void)
- {
- GtkWidget *vbox;
- GtkWidget *button_box;
-
- if (channelsD)
- return channelsD->vbox;
-
- channelsD = g_new (ChannelsDialog, 1);
- channelsD->preview = NULL;
- channelsD->gimage = NULL;
- channelsD->active_channel = NULL;
- channelsD->floating_sel = NULL;
- channelsD->channel_widgets = NULL;
-
- if (preview_size)
- {
- channelsD->preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
- gtk_preview_size (GTK_PREVIEW (channelsD->preview),
- preview_size, preview_size);
- }
-
- /* The main vbox */
- channelsD->vbox = gtk_event_box_new ();
-
- gimp_help_set_help_data (channelsD->vbox, NULL,
- "dialogs/channels/channels.html");
-
- vbox = gtk_vbox_new (FALSE, 1);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
- gtk_container_add (GTK_CONTAINER (channelsD->vbox), vbox);
-
- /* The channels commands pulldown menu */
- menus_get_channels_menu (&channelsD->ops_menu, &channelsD->accel_group);
-
- /* The channels listbox */
- channelsD->scrolled_win = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (channelsD->scrolled_win),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_widget_set_usize (channelsD->scrolled_win, LIST_WIDTH, LIST_HEIGHT);
- gtk_box_pack_start (GTK_BOX (vbox), channelsD->scrolled_win, TRUE, TRUE, 2);
-
- channelsD->channel_list = gtk_list_new ();
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (channelsD->scrolled_win),
- channelsD->channel_list);
- gtk_list_set_selection_mode (GTK_LIST (channelsD->channel_list),
- GTK_SELECTION_MULTIPLE);
- gtk_signal_connect (GTK_OBJECT (channelsD->channel_list), "event",
- (GtkSignalFunc) channel_list_events,
- channelsD);
- gtk_container_set_focus_vadjustment (GTK_CONTAINER (channelsD->channel_list),
- gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (channelsD->scrolled_win)));
- GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (channelsD->scrolled_win)->vscrollbar,
- GTK_CAN_FOCUS);
-
- gtk_widget_show (channelsD->channel_list);
- gtk_widget_show (channelsD->scrolled_win);
-
- /* The ops buttons */
- button_box = ops_button_box_new (channels_ops_buttons, OPS_BUTTON_NORMAL);
- gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
- gtk_widget_show (button_box);
-
- /* Drop to new */
- gtk_drag_dest_set (channels_ops_buttons[0].widget,
- GTK_DEST_DEFAULT_ALL,
- channel_target_table, n_channel_targets,
- GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[0].widget), "drag_drop",
- GTK_SIGNAL_FUNC (channels_dialog_drag_new_channel_callback),
- NULL);
-
- /* Drop to duplicate */
- gtk_drag_dest_set (channels_ops_buttons[3].widget,
- GTK_DEST_DEFAULT_ALL,
- channel_target_table, n_channel_targets,
- GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[3].widget), "drag_drop",
- GTK_SIGNAL_FUNC (channels_dialog_drag_duplicate_channel_callback),
- NULL);
-
- /* Drop to channel to selection */
- gtk_drag_dest_set (channels_ops_buttons[4].widget,
- GTK_DEST_DEFAULT_ALL,
- channel_target_table, n_channel_targets,
- GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[4].widget), "drag_drop",
- GTK_SIGNAL_FUNC (channels_dialog_drag_channel_to_sel_callback),
- NULL);
-
- /* Drop to trahcan */
- gtk_drag_dest_set (channels_ops_buttons[5].widget,
- GTK_DEST_DEFAULT_ALL,
- channel_target_table, n_channel_targets,
- GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[5].widget), "drag_drop",
- GTK_SIGNAL_FUNC (channels_dialog_drag_delete_channel_callback),
- NULL);
-
- /* Set up signals for map/unmap for the accelerators */
- gtk_signal_connect (GTK_OBJECT (channelsD->vbox), "map",
- (GtkSignalFunc) channels_dialog_map_callback,
- NULL);
- gtk_signal_connect (GTK_OBJECT (channelsD->vbox), "unmap",
- (GtkSignalFunc) channels_dialog_unmap_callback,
- NULL);
-
- gtk_widget_show (vbox);
- gtk_widget_show (channelsD->vbox);
-
- return channelsD->vbox;
- }
-
- void
- channels_dialog_free (void)
- {
- ChannelWidget *cw;
- GSList *list;
-
- if (!channelsD)
- return;
-
- suspend_gimage_notify++;
- /* Free all elements in the channels listbox */
- gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
- suspend_gimage_notify--;
-
- list = channelsD->channel_widgets;
- while (list)
- {
- cw = (ChannelWidget *) list->data;
- list = g_slist_next (list);
- channel_widget_delete (cw);
- }
- channelsD->channel_widgets = NULL;
- channelsD->active_channel = NULL;
- channelsD->floating_sel = NULL;
-
- if (channelsD->preview)
- gtk_object_sink (GTK_OBJECT (channelsD->preview));
-
- g_free (channelsD);
- channelsD = NULL;
- }
-
- void
- channels_dialog_update (GimpImage* gimage)
- {
- Channel *channel;
- ChannelWidget *cw;
- GSList *list;
- GList *item_list;
-
- if (!channelsD || channelsD->gimage == gimage)
- return;
-
- channelsD->gimage = gimage;
-
- suspend_gimage_notify++;
- /* Free all elements in the channels listbox */
- gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
- suspend_gimage_notify--;
-
- list = channelsD->channel_widgets;
- while (list)
- {
- cw = (ChannelWidget *) list->data;
- list = g_slist_next (list);
- channel_widget_delete (cw);
- }
- channelsD->channel_widgets = NULL;
-
- /* Find the preview extents */
- channels_dialog_preview_extents ();
-
- channelsD->active_channel = NULL;
- channelsD->floating_sel = NULL;
-
- /* The image components */
- item_list = NULL;
- switch ((channelsD->base_type = gimp_image_base_type (gimage)))
- {
- case RGB:
- cw = channel_widget_create (gimage, NULL, RED_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- channelsD->components[0] = RED_CHANNEL;
-
- cw = channel_widget_create (gimage, NULL, GREEN_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- channelsD->components[1] = GREEN_CHANNEL;
-
- cw = channel_widget_create (gimage, NULL, BLUE_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- channelsD->components[2] = BLUE_CHANNEL;
-
- channelsD->num_components = 3;
- break;
-
- case GRAY:
- cw = channel_widget_create (gimage, NULL, GRAY_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- channelsD->components[0] = GRAY_CHANNEL;
-
- channelsD->num_components = 1;
- break;
-
- case INDEXED:
- cw = channel_widget_create (gimage, NULL, INDEXED_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- channelsD->components[0] = INDEXED_CHANNEL;
-
- channelsD->num_components = 1;
- break;
- }
-
- /* The auxillary image channels */
- for (list = gimage->channels; list; list = g_slist_next (list))
- {
- /* create a channel list item */
- channel = (Channel *) list->data;
- cw = channel_widget_create (gimage, channel, AUXILLARY_CHANNEL);
- channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
- item_list = g_list_append (item_list, cw->list_item);
- }
-
- /* get the index of the active channel */
- if (item_list)
- gtk_list_insert_items (GTK_LIST (channelsD->channel_list), item_list, 0);
- }
-
- void
- channels_dialog_flush (void)
- {
- GimpImage *gimage;
- Channel *channel;
- ChannelWidget *cw;
- GSList *list;
- gint pos;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- /* Check if the gimage extents have changed */
- if ((gimage->width != channelsD->gimage_width) ||
- (gimage->height != channelsD->gimage_height) ||
- (gimp_image_base_type (gimage) != channelsD->base_type))
- {
- channelsD->gimage = NULL;
- channels_dialog_update (gimage);
- }
- else
- {
- /* Set all current channel widgets to visited = FALSE */
- for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
- {
- cw = (ChannelWidget *) list->data;
- cw->visited = FALSE;
- }
-
- /* Add any missing channels */
- for (list = gimage->channels; list; list = g_slist_next (list))
- {
- channel = (Channel *) list->data;
- cw = channel_widget_get_ID (channel);
-
- /* If the channel isn't in the channel widget list, add it */
- if (cw == NULL)
- {
- /* sets visited = TRUE */
- channels_dialog_add_channel (channel);
- }
- else
- cw->visited = TRUE;
- }
-
- /* Remove any extraneous auxillary channels */
- list = channelsD->channel_widgets;
- while (list)
- {
- cw = (ChannelWidget *) list->data;
- list = g_slist_next (list);
- if (cw->visited == FALSE && cw->type == AUXILLARY_CHANNEL)
- {
- /* will only be true for auxillary channels */
- channels_dialog_remove_channel (cw);
- }
- }
-
- /* Switch positions of items if necessary */
- pos = 0;
- for (list = gimage->channels; list; list = g_slist_next (list))
- {
- channel = (Channel *) list->data;
- channels_dialog_position_channel (channel, pos++);
- }
-
- /* Set the active channel */
- if (channelsD->active_channel != gimage->active_channel)
- channelsD->active_channel = gimage->active_channel;
-
- /* set the menus if floating sel status has changed */
- if (channelsD->floating_sel != gimage->floating_sel)
- channelsD->floating_sel = gimage->floating_sel;
-
- channels_dialog_set_menu_sensitivity ();
-
- gtk_container_foreach (GTK_CONTAINER (channelsD->channel_list),
- channel_widget_channel_flush, NULL);
- }
- }
-
- void
- channels_dialog_clear (void)
- {
- if (!channelsD)
- return;
-
- suspend_gimage_notify++;
- gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
- suspend_gimage_notify--;
-
- channelsD->gimage = NULL;
- }
-
- static void
- channels_dialog_preview_extents (void)
- {
- GimpImage *gimage;
-
- g_return_if_fail (channelsD);
- if (! (gimage = channelsD->gimage))
- return;
-
- channelsD->gimage_width = gimage->width;
- channelsD->gimage_height = gimage->height;
-
- /* Get the image width and height variables, based on the gimage */
- if (gimage->width > gimage->height)
- channelsD->ratio = (gdouble) preview_size / (gdouble) gimage->width;
- else
- channelsD->ratio = (gdouble) preview_size / (gdouble) gimage->height;
-
- if (preview_size)
- {
- channelsD->image_width = RINT (channelsD->ratio * gimage->width);
- channelsD->image_height = RINT (channelsD->ratio * gimage->height);
-
- if (channelsD->image_width < 1) channelsD->image_width = 1;
- if (channelsD->image_height < 1) channelsD->image_height = 1;
- }
- else
- {
- channelsD->image_width = channel_width;
- channelsD->image_height = channel_height;
- }
- }
-
- static void
- channels_dialog_set_menu_sensitivity (void)
- {
- ChannelWidget *cw;
- gint fs_sens;
- gint aux_sens;
-
- cw = channel_widget_get_ID (channelsD->active_channel);
- fs_sens = (channelsD->floating_sel != NULL);
-
- if (cw)
- aux_sens = (cw->type == AUXILLARY_CHANNEL);
- else
- aux_sens = FALSE;
-
- #define SET_SENSITIVE(menu,condition) \
- menus_set_sensitive ("<Channels>/" menu, (condition) != 0)
- #define SET_OPS_SENSITIVE(button,condition) \
- gtk_widget_set_sensitive (channels_ops_buttons[(button)].widget, \
- (condition) != 0)
-
- SET_SENSITIVE ("New Channel...", !fs_sens);
- SET_OPS_SENSITIVE (0, !fs_sens);
-
- SET_SENSITIVE ("Raise Channel", !fs_sens && aux_sens);
- SET_OPS_SENSITIVE (1, !fs_sens && aux_sens);
-
- SET_SENSITIVE ("Lower Channel", !fs_sens && aux_sens);
- SET_OPS_SENSITIVE (2, !fs_sens && aux_sens);
-
- SET_SENSITIVE ("Duplicate Channel", !fs_sens && aux_sens);
- SET_OPS_SENSITIVE (3, !fs_sens && aux_sens);
-
- SET_SENSITIVE ("Channel to Selection", aux_sens);
- SET_OPS_SENSITIVE (4, aux_sens);
-
- SET_SENSITIVE ("Add to Selection", aux_sens);
- SET_SENSITIVE ("Subtract from Selection", aux_sens);
- SET_SENSITIVE ("Intersect with Selection", aux_sens);
-
- SET_SENSITIVE ("Delete Channel", !fs_sens && aux_sens);
- SET_OPS_SENSITIVE (5, !fs_sens && aux_sens);
-
- SET_SENSITIVE ("Edit Channel Attributes...", !fs_sens && aux_sens);
-
- #undef SET_OPS_SENSITIVE
- #undef SET_SENSITIVE
- }
-
- static gint
- channels_dialog_idle_set_channel_focus (gpointer data)
- {
- gtk_widget_grab_focus (GTK_WIDGET (data));
-
- return FALSE;
- }
-
- static void
- channels_dialog_set_channel (ChannelWidget *channel_widget)
- {
- GtkStateType state;
- gint index;
-
- if (!channelsD || !channel_widget)
- return;
-
- /* Make sure the gimage is not notified of this change */
- suspend_gimage_notify++;
-
- /* get the list item data */
- state = channel_widget->list_item->state;
-
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- /* turn on the specified auxillary channel */
- index = gimp_image_get_channel_index (channel_widget->gimage,
- channel_widget->channel);
- if ((index >= 0) && (state != GTK_STATE_SELECTED))
- {
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- NULL);
- gtk_list_select_item (GTK_LIST (channelsD->channel_list),
- index + channelsD->num_components);
- /* let dnd finish it's work before setting the focus */
- gtk_idle_add ((GtkFunction) channels_dialog_idle_set_channel_focus,
- channel_widget->list_item);
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- channel_widget);
- /* channels_dialog_scroll_index (index + channelsD->num_components); */
- }
- }
- else
- {
- if (state != GTK_STATE_SELECTED)
- {
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- NULL);
- switch (channel_widget->type)
- {
- case RED_CHANNEL:
- case GRAY_CHANNEL:
- case INDEXED_CHANNEL:
- gtk_list_select_item (GTK_LIST (channelsD->channel_list), 0);
- break;
- case GREEN_CHANNEL:
- gtk_list_select_item (GTK_LIST (channelsD->channel_list), 1);
- break;
- case BLUE_CHANNEL:
- gtk_list_select_item (GTK_LIST (channelsD->channel_list), 2);
- break;
- case AUXILLARY_CHANNEL:
- g_error ("error in %s at %d: this shouldn't happen.",
- __FILE__, __LINE__);
- break;
- }
-
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- channel_widget);
- /* channels_dialog_scroll_index (0); */
- }
- }
- suspend_gimage_notify--;
- }
-
- static void
- channels_dialog_unset_channel (ChannelWidget *channel_widget)
- {
- GtkStateType state;
- gint index;
-
- if (!channelsD || !channel_widget)
- return;
-
- /* Make sure the gimage is not notified of this change */
- suspend_gimage_notify++;
-
- /* get the list item data */
- state = channel_widget->list_item->state;
-
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- /* turn off the specified auxillary channel */
- index = gimp_image_get_channel_index (channel_widget->gimage,
- channel_widget->channel);
- if ((index >= 0) && (state == GTK_STATE_SELECTED))
- {
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- NULL);
- gtk_list_unselect_item (GTK_LIST (channelsD->channel_list),
- index + channelsD->num_components);
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- channel_widget);
- }
- }
- else
- {
- if (state == GTK_STATE_SELECTED)
- {
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- NULL);
- switch (channel_widget->type)
- {
- case RED_CHANNEL:
- case GRAY_CHANNEL:
- case INDEXED_CHANNEL:
- gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 0);
- break;
- case GREEN_CHANNEL:
- gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 1);
- break;
- case BLUE_CHANNEL:
- gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 2);
- break;
- case AUXILLARY_CHANNEL:
- g_error ("error in %s at %d: this shouldn't happen.",
- __FILE__, __LINE__);
- break;
- }
-
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
- channel_widget);
- }
- }
-
- suspend_gimage_notify--;
- }
-
- static void
- channels_dialog_position_channel (Channel *channel,
- gint new_index)
- {
- ChannelWidget *channel_widget;
- GList *list = NULL;
-
- channel_widget = channel_widget_get_ID (channel);
- if (!channelsD || !channel_widget)
- return;
-
- if ((new_index + channelsD->num_components) ==
- g_slist_index (channelsD->channel_widgets, channel_widget))
- return;
-
- /* Make sure the gimage is not notified of this change */
- suspend_gimage_notify++;
-
- /* Remove the channel from the dialog */
- list = g_list_append (list, channel_widget->list_item);
- gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
- channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets,
- channel_widget);
-
- /* Add it back at the proper index */
- gtk_list_insert_items (GTK_LIST (channelsD->channel_list), list,
- new_index + channelsD->num_components);
- channelsD->channel_widgets =
- g_slist_insert (channelsD->channel_widgets, channel_widget,
- new_index + channelsD->num_components);
-
- /* channels_dialog_scroll_index (new_index > 0 ? */
- /* new_index + channelsD->num_components + 1 : */
- /* channelsD->num_components); */
-
- suspend_gimage_notify--;
- }
-
- static void
- channels_dialog_add_channel (Channel *channel)
- {
- ChannelWidget *channel_widget;
- GimpImage *gimage;
- GList *item_list;
- gint position;
-
- if (!channelsD || !channel || !(gimage = channelsD->gimage))
- return;
-
- item_list = NULL;
-
- channel_widget = channel_widget_create (gimage, channel, AUXILLARY_CHANNEL);
- item_list = g_list_append (item_list, channel_widget->list_item);
-
- position = gimp_image_get_channel_index (gimage, channel);
- channelsD->channel_widgets =
- g_slist_insert (channelsD->channel_widgets, channel_widget,
- position + channelsD->num_components);
- gtk_list_insert_items (GTK_LIST (channelsD->channel_list), item_list,
- position + channelsD->num_components);
- }
-
- static void
- channels_dialog_remove_channel (ChannelWidget *channel_widget)
- {
- GList *list = NULL;
-
- if (!channelsD || !channel_widget)
- return;
-
- /* Make sure the gimage is not notified of this change */
- suspend_gimage_notify++;
-
- /* Remove the requested channel from the dialog */
- list = g_list_append (list, channel_widget->list_item);
- gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
-
- /* Delete the channel_widget */
- channel_widget_delete (channel_widget);
-
- suspend_gimage_notify--;
- }
-
- static gint
- channel_list_events (GtkWidget *widget,
- GdkEvent *event)
- {
- ChannelWidget *channel_widget;
- GdkEventButton *bevent;
- GtkWidget *event_widget;
-
- event_widget = gtk_get_event_widget (event);
-
- if (GTK_IS_LIST_ITEM (event_widget))
- {
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (event_widget));
-
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
- if (bevent->button == 3)
- {
- gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
- NULL, NULL, NULL, NULL,
- bevent->button, bevent->time);
- return TRUE;
- }
- break;
-
- case GDK_2BUTTON_PRESS:
- if (channel_widget->type == AUXILLARY_CHANNEL)
- channels_dialog_edit_channel_query (channel_widget);
- return TRUE;
-
- default:
- break;
- }
- }
-
- return FALSE;
- }
-
- /*******************************/
- /* channels dialog callbacks */
- /*******************************/
-
- static void
- channels_dialog_map_callback (GtkWidget *widget,
- gpointer data)
- {
- if (! channelsD)
- return;
-
- gtk_window_add_accel_group (GTK_WINDOW (lc_dialog->shell),
- channelsD->accel_group);
- }
-
- static void
- channels_dialog_unmap_callback (GtkWidget *widget,
- gpointer data)
- {
- if (! channelsD)
- return;
-
- gtk_window_remove_accel_group (GTK_WINDOW (lc_dialog->shell),
- channelsD->accel_group);
- }
-
- /***********************************/
- /* callbacks exported to menus.c */
- /***********************************/
-
- void
- channels_dialog_new_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- if (!channelsD || channelsD->gimage == NULL)
- return;
-
- channels_dialog_new_channel_query (channelsD->gimage);
- }
-
- void
- channels_dialog_raise_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if (gimage->active_channel != NULL)
- {
- gimp_image_raise_channel (gimage, gimage->active_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_lower_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if (gimage->active_channel != NULL)
- {
- gimp_image_lower_channel (gimage, gimage->active_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_duplicate_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
- Channel *active_channel;
- Channel *new_channel;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if ((active_channel = gimp_image_get_active_channel (gimage)))
- {
- new_channel = channel_copy (active_channel);
- gimp_image_add_channel (gimage, new_channel, -1);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_delete_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if (gimage->active_channel != NULL)
- {
- gimp_image_remove_channel (gimage, gimage->active_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_channel_to_sel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if (gimage->active_channel != NULL)
- {
- gimage_mask_load (gimage, gimage->active_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_add_channel_to_sel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
- Channel *active_channel;
- Channel *new_channel;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if ((active_channel = gimp_image_get_active_channel (gimage)))
- {
- new_channel = channel_copy (gimp_image_get_mask (gimage));
- channel_combine_mask (new_channel,
- active_channel,
- ADD,
- 0, 0); /* off x/y */
- gimage_mask_load (gimage, new_channel);
- channel_delete (new_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_sub_channel_from_sel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
- Channel *active_channel;
- Channel *new_channel;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if ((active_channel = gimp_image_get_active_channel (gimage)))
- {
- new_channel = channel_copy (gimp_image_get_mask (gimage));
- channel_combine_mask (new_channel,
- active_channel,
- SUB,
- 0, 0); /* off x/y */
- gimage_mask_load (gimage, new_channel);
- channel_delete (new_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_intersect_channel_with_sel_callback (GtkWidget *widget,
- gpointer data)
- {
- GimpImage *gimage;
- Channel *active_channel;
- Channel *new_channel;
-
- if (!channelsD || !(gimage = channelsD->gimage))
- return;
-
- if ((active_channel = gimp_image_get_active_channel (gimage)))
- {
- new_channel = channel_copy (gimp_image_get_mask (gimage));
- channel_combine_mask (new_channel,
- active_channel,
- INTERSECT,
- 0, 0); /* off x/y */
- gimage_mask_load (gimage, new_channel);
- channel_delete (new_channel);
- gdisplays_flush ();
- }
- }
-
- void
- channels_dialog_edit_channel_attributes_callback (GtkWidget *widget,
- gpointer data)
- {
- if (channelsD && channelsD->active_channel)
- {
- ChannelWidget *channel_widget;
-
- channel_widget = channel_widget_get_ID (channelsD->active_channel);
-
- channels_dialog_edit_channel_query (channel_widget);
- }
- }
-
- /*******************************/
- /* ops buttons dnd callbacks */
- /*******************************/
-
- static gboolean
- channels_dialog_drag_new_channel_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- GtkWidget *src_widget;
- gboolean return_val = FALSE;
-
- if ((src_widget = gtk_drag_get_source_widget (context)))
- {
- ChannelWidget *src;
-
- src
- = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- Channel *channel;
- GimpImage *gimage;
- gint width, height;
- gint off_x, off_y;
-
- gimage = channelsD->gimage;
-
- width = gimp_drawable_width (GIMP_DRAWABLE (src->channel));
- height = gimp_drawable_height (GIMP_DRAWABLE (src->channel));
- gimp_drawable_offsets (GIMP_DRAWABLE (src->channel), &off_x, &off_y);
-
- /* Start a group undo */
- undo_push_group_start (gimage, EDIT_PASTE_UNDO);
-
- channel = channel_new (gimage, width, height,
- _("Empty Channel Copy"),
- src->channel->opacity,
- src->channel->col);
- if (channel)
- {
- drawable_fill (GIMP_DRAWABLE (channel), TRANSPARENT_FILL);
- channel_translate (channel, off_x, off_y);
- gimp_image_add_channel (gimage, channel, -1);
-
- /* End the group undo */
- undo_push_group_end (gimage);
-
- gdisplays_flush ();
- }
- else
- {
- g_message ("channels_dialog_drop_new_channel_callback():\n"
- "could not allocate new channel");
- }
-
- return_val = TRUE;
- }
- }
-
- gtk_drag_finish (context, return_val, FALSE, time);
-
- return return_val;
- }
-
- static gboolean
- channels_dialog_drag_duplicate_channel_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- GtkWidget *src_widget;
- gboolean return_val = FALSE;
-
- if ((src_widget = gtk_drag_get_source_widget (context)))
- {
- ChannelWidget *src;
-
- src
- = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- channels_dialog_duplicate_channel_callback (widget, NULL);
-
- return_val = TRUE;
- }
- }
-
- gtk_drag_finish (context, return_val, FALSE, time);
-
- return return_val;
- }
-
- static gboolean
- channels_dialog_drag_channel_to_sel_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- GtkWidget *src_widget;
- gboolean return_val = FALSE;
-
- if ((src_widget = gtk_drag_get_source_widget (context)))
- {
- ChannelWidget *src;
-
- src
- = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- channels_dialog_channel_to_sel_callback (widget, NULL);
-
- return_val = TRUE;
- }
- }
-
- gtk_drag_finish (context, return_val, FALSE, time);
-
- return return_val;
- }
-
- static gboolean
- channels_dialog_drag_delete_channel_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- GtkWidget *src_widget;
- gboolean return_val = FALSE;
-
- if ((src_widget = gtk_drag_get_source_widget (context)))
- {
- ChannelWidget *src;
-
- src
- = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- channels_dialog_delete_channel_callback (widget, NULL);
-
- return_val = TRUE;
- }
- }
-
- gtk_drag_finish (context, return_val, FALSE, time);
-
- return return_val;
- }
-
- /******************************/
- /* channel widget functions */
- /******************************/
-
- static ChannelWidget *
- channel_widget_get_ID (Channel *channel)
- {
- ChannelWidget *lw;
- GSList *list;
-
- if (!channelsD)
- return NULL;
-
- for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
- {
- lw = (ChannelWidget *) list->data;
-
- if (lw->channel == channel)
- return lw;
- }
-
- return NULL;
- }
-
- static ChannelWidget *
- channel_widget_create (GimpImage *gimage,
- Channel *channel,
- ChannelType type)
- {
- ChannelWidget *channel_widget;
- GtkWidget *list_item;
- GtkWidget *hbox;
- GtkWidget *vbox;
- GtkWidget *alignment;
-
- list_item = gtk_list_item_new ();
-
- /* Create the channel widget and add it to the list */
- channel_widget = g_new (ChannelWidget, 1);
- channel_widget->gimage = gimage;
- channel_widget->channel = channel;
- channel_widget->channel_preview = NULL;
- channel_widget->channel_pixmap = NULL;
- channel_widget->type = type;
- channel_widget->ID = ((type == AUXILLARY_CHANNEL) ?
- GIMP_DRAWABLE (channel)->ID :
- (COMPONENT_BASE_ID + type));
- channel_widget->list_item = list_item;
- channel_widget->width = -1;
- channel_widget->height = -1;
- channel_widget->visited = TRUE;
- channel_widget->drop_type = GIMP_DROP_NONE;
-
- /* Need to let the list item know about the channel_widget */
- gtk_object_set_user_data (GTK_OBJECT (list_item), channel_widget);
-
- /* Set up the list item observer */
- gtk_signal_connect (GTK_OBJECT (list_item), "select",
- GTK_SIGNAL_FUNC (channel_widget_select_update),
- channel_widget);
- gtk_signal_connect (GTK_OBJECT (list_item), "deselect",
- GTK_SIGNAL_FUNC (channel_widget_select_update),
- channel_widget);
-
- vbox = gtk_vbox_new (FALSE, 1);
- gtk_container_add (GTK_CONTAINER (list_item), vbox);
-
- hbox = gtk_hbox_new (FALSE, 1);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1);
-
- /* Create the visibility toggle button */
- alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
- gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, TRUE, 2);
- channel_widget->eye_widget = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (channel_widget->eye_widget),
- eye_width, eye_height);
- gtk_widget_set_events (channel_widget->eye_widget, BUTTON_EVENT_MASK);
- gtk_signal_connect (GTK_OBJECT (channel_widget->eye_widget), "event",
- GTK_SIGNAL_FUNC (channel_widget_button_events),
- channel_widget);
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->eye_widget),
- channel_widget);
- gtk_container_add (GTK_CONTAINER (alignment), channel_widget->eye_widget);
- gtk_widget_show (channel_widget->eye_widget);
- gtk_widget_show (alignment);
-
- /* The channel preview */
- alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
- gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, FALSE, 2);
- gtk_widget_show (alignment);
-
- channel_widget->channel_preview = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (channel_widget->channel_preview),
- channelsD->image_width, channelsD->image_height);
- gtk_widget_set_events (channel_widget->channel_preview, PREVIEW_EVENT_MASK);
- gtk_signal_connect (GTK_OBJECT (channel_widget->channel_preview), "event",
- GTK_SIGNAL_FUNC (channel_widget_preview_events),
- channel_widget);
- gtk_object_set_user_data (GTK_OBJECT (channel_widget->channel_preview),
- channel_widget);
- gtk_container_add (GTK_CONTAINER (alignment), channel_widget->channel_preview);
- gtk_widget_show (channel_widget->channel_preview);
-
- /* The channel name label */
- switch (channel_widget->type)
- {
- case RED_CHANNEL:
- channel_widget->label = gtk_label_new (_("Red"));
- break;
-
- case GREEN_CHANNEL:
- channel_widget->label = gtk_label_new (_("Green"));
- break;
-
- case BLUE_CHANNEL:
- channel_widget->label = gtk_label_new (_("Blue"));
- break;
-
- case GRAY_CHANNEL:
- channel_widget->label = gtk_label_new (_("Gray"));
- break;
-
- case INDEXED_CHANNEL:
- channel_widget->label = gtk_label_new (_("Indexed"));
- break;
-
- case AUXILLARY_CHANNEL:
- channel_widget->label = gtk_label_new (channel_get_name (channel));
- break;
- }
-
- gtk_box_pack_start (GTK_BOX (hbox), channel_widget->label, FALSE, FALSE, 2);
- gtk_widget_show (channel_widget->label);
-
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- /* dnd destination */
- gtk_drag_dest_set (list_item,
- GTK_DEST_DEFAULT_ALL,
- channel_color_target_table, n_channel_color_targets,
- GDK_ACTION_MOVE | GDK_ACTION_COPY);
- gimp_dnd_color_dest_set (list_item,
- channel_widget_drop_color,
- (gpointer) channel_widget);
-
- gtk_signal_connect (GTK_OBJECT (list_item), "drag_leave",
- GTK_SIGNAL_FUNC (channel_widget_drag_leave_callback),
- NULL);
- gtk_signal_connect (GTK_OBJECT (list_item), "drag_motion",
- GTK_SIGNAL_FUNC (channel_widget_drag_motion_callback),
- NULL);
- gtk_signal_connect (GTK_OBJECT (list_item), "drag_drop",
- GTK_SIGNAL_FUNC (channel_widget_drag_drop_callback),
- NULL);
-
- /* re-paint the drop indicator after drawing the widget */
- gtk_signal_connect_after (GTK_OBJECT (list_item), "draw",
- GTK_SIGNAL_FUNC (channel_widget_drag_indicator_callback),
- channel_widget);
-
- /* dnd source */
- gtk_drag_source_set (list_item,
- GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
- channel_target_table, n_channel_targets,
- GDK_ACTION_MOVE | GDK_ACTION_COPY);
-
- gtk_signal_connect (GTK_OBJECT (list_item), "drag_begin",
- GTK_SIGNAL_FUNC (channel_widget_drag_begin_callback),
- NULL);
-
- gtk_object_set_data (GTK_OBJECT (list_item), "gimp_channel",
- (gpointer) channel);
- }
- else
- {
- /* dnd source */
- gtk_drag_source_set (list_item,
- GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
- component_target_table, n_component_targets,
- GDK_ACTION_MOVE | GDK_ACTION_COPY);
-
- gtk_object_set_data (GTK_OBJECT (list_item), "gimp_component",
- (gpointer) gimage);
- gtk_object_set_data (GTK_OBJECT (list_item), "gimp_component_type",
- (gpointer) channel_widget->type);
- }
-
- gtk_widget_show (hbox);
- gtk_widget_show (vbox);
- gtk_widget_show (list_item);
-
- gtk_widget_ref (channel_widget->list_item);
-
- return channel_widget;
- }
-
- static gboolean
- channel_widget_drag_motion_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- ChannelWidget *dest;
- gint dest_index;
- GtkWidget *src_widget;
- ChannelWidget *src = NULL;
- gint src_index;
- gint difference;
-
- GimpDropType drop_type = GIMP_DROP_NONE;
- GdkDragAction drag_action = GDK_ACTION_DEFAULT;
- gboolean return_val = FALSE;
-
- dest = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- if (dest)
- {
- src_widget = gtk_drag_get_source_widget (context);
-
- if (src_widget)
- {
- src = (ChannelWidget *)
- gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- src_index = gimp_image_get_channel_index (channelsD->gimage,
- src->channel);
- dest_index = gimp_image_get_channel_index (channelsD->gimage,
- dest->channel);
-
- difference = dest_index - src_index;
-
- drop_type = ((y < widget->allocation.height / 2) ?
- GIMP_DROP_ABOVE : GIMP_DROP_BELOW);
-
- if (difference < 0 &&
- drop_type == GIMP_DROP_BELOW)
- {
- dest_index++;
- }
- else if (difference > 0 &&
- drop_type == GIMP_DROP_ABOVE)
- {
- dest_index--;
- }
-
- if (src_index != dest_index)
- {
- drag_action = GDK_ACTION_MOVE;
- return_val = TRUE;
- }
- else
- {
- drop_type = GIMP_DROP_NONE;
- }
- }
- }
-
- if (!src)
- {
- drag_action = GDK_ACTION_COPY;
- return_val = TRUE;
- drop_type = GIMP_DROP_NONE;
- }
- }
-
- gdk_drag_status (context, drag_action, time);
-
- if (dest && drop_type != dest->drop_type)
- {
- channel_widget_draw_drop_indicator (dest, dest->drop_type);
- channel_widget_draw_drop_indicator (dest, drop_type);
- dest->drop_type = drop_type;
- }
-
- return return_val;
- }
-
- static void
- channel_widget_drag_begin_callback (GtkWidget *widget,
- GdkDragContext *context)
- {
- ChannelWidget *channel_widget;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- gimp_dnd_set_drawable_preview_icon (widget, context,
- GIMP_DRAWABLE (channel_widget->channel));
- }
-
- typedef struct
- {
- GimpImage *gimage;
- Channel *channel;
- gint dest_index;
- } ChannelDrop;
-
- static gint
- channel_widget_idle_drop_channel (gpointer data)
- {
- ChannelDrop *cd;
-
- cd = (ChannelDrop *) data;
-
- gimp_image_position_channel (cd->gimage, cd->channel, cd->dest_index);
- gdisplays_flush ();
-
- g_free (cd);
-
- return FALSE;
- }
-
- static gboolean
- channel_widget_drag_drop_callback (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
- {
- ChannelWidget *dest;
- gint dest_index;
- GtkWidget *src_widget;
- ChannelWidget *src;
- gint src_index;
- gint difference;
-
- GimpDropType drop_type = GIMP_DROP_NONE;
- gboolean return_val = FALSE;
-
- dest = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- if (dest &&
- (src_widget = gtk_drag_get_source_widget (context)))
- {
- src = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
-
- if (src &&
- src->channel == channelsD->active_channel)
- {
- src_index = gimp_image_get_channel_index (channelsD->gimage,
- src->channel);
- dest_index = gimp_image_get_channel_index (channelsD->gimage,
- dest->channel);
-
- difference = dest_index - src_index;
-
- drop_type = ((y < widget->allocation.height / 2) ?
- GIMP_DROP_ABOVE : GIMP_DROP_BELOW);
-
- if (difference < 0 &&
- drop_type == GIMP_DROP_BELOW)
- {
- dest_index++;
- }
- else if (difference > 0 &&
- drop_type == GIMP_DROP_ABOVE)
- {
- dest_index--;
- }
-
- if (src_index != dest_index)
- {
- ChannelDrop *cd;
-
- cd = g_new (ChannelDrop, 1);
- cd->gimage = channelsD->gimage;
- cd->channel = src->channel;
- cd->dest_index = dest_index;
-
- /* let dnd finish it's work before changing the widget tree */
- gtk_idle_add ((GtkFunction) channel_widget_idle_drop_channel, cd);
- return_val = TRUE;
- }
- }
- }
-
- if (dest)
- {
- if (!return_val)
- channel_widget_draw_drop_indicator (dest, dest->drop_type);
-
- dest->drop_type = GIMP_DROP_NONE;
- }
-
- gtk_drag_finish (context, return_val, FALSE, time);
-
- return return_val;
- }
-
- static void
- channel_widget_drag_leave_callback (GtkWidget *widget,
- GdkDragContext *context,
- guint time)
- {
- ChannelWidget *channel_widget;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- channel_widget->drop_type = GIMP_DROP_NONE;
- }
-
- static void
- channel_widget_drag_indicator_callback (GtkWidget *widget,
- gpointer data)
- {
- ChannelWidget *channel_widget;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- channel_widget_draw_drop_indicator (channel_widget, channel_widget->drop_type);
- }
-
- static void
- channel_widget_drop_color (GtkWidget *widget,
- guchar r,
- guchar g,
- guchar b,
- gpointer data)
- {
- ChannelWidget *channel_widget = (ChannelWidget *) data;
- Channel *channel = channel_widget->channel;
-
- if (r != channel->col[0] ||
- g != channel->col[1] ||
- b != channel->col[2])
- {
- channel->col[0] = r;
- channel->col[1] = g;
- channel->col[2] = b;
-
- drawable_update (GIMP_DRAWABLE (channel), 0, 0,
- GIMP_DRAWABLE (channel)->width,
- GIMP_DRAWABLE (channel)->height);
- gdisplays_flush ();
- }
- }
-
- static void
- channel_widget_draw_drop_indicator (ChannelWidget *channel_widget,
- GimpDropType drop_type)
- {
- static GdkGC *gc = NULL;
- gint y = 0;
-
- if (!gc)
- {
- GdkColor fg, bg;
-
- gc = gdk_gc_new (channel_widget->list_item->window);
-
- fg.pixel = 0xFFFFFFFF;
- bg.pixel = 0x00000000;
-
- gdk_gc_set_function (gc, GDK_INVERT);
- gdk_gc_set_foreground (gc, &fg);
- gdk_gc_set_background (gc, &bg);
- gdk_gc_set_line_attributes (gc, 5, GDK_LINE_SOLID,
- GDK_CAP_BUTT, GDK_JOIN_MITER);
- }
-
- if (drop_type != GIMP_DROP_NONE)
- {
- y = ((drop_type == GIMP_DROP_ABOVE) ?
- 3 : channel_widget->list_item->allocation.height - 4);
-
- gdk_draw_line (channel_widget->list_item->window, gc,
- 2, y, channel_widget->list_item->allocation.width - 3, y);
- }
- }
-
- static void
- channel_widget_delete (ChannelWidget *channel_widget)
- {
- if (channel_widget->channel_pixmap)
- gdk_pixmap_unref (channel_widget->channel_pixmap);
-
- /* Remove the channel widget from the list */
- channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets,
- channel_widget);
-
- /* Release the widget */
- gtk_widget_unref (channel_widget->list_item);
- g_free (channel_widget);
- }
-
- static void
- channel_widget_select_update (GtkWidget *widget,
- gpointer data)
- {
- ChannelWidget *channel_widget;
-
- if ((channel_widget = (ChannelWidget *) data) == NULL)
- return;
-
- if (suspend_gimage_notify == 0)
- {
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- if (widget->state == GTK_STATE_SELECTED)
- /* set the gimage's active channel to be this channel */
- gimp_image_set_active_channel (channel_widget->gimage,
- channel_widget->channel);
- else
- /* unset the gimage's active channel */
- gimp_image_unset_active_channel (channel_widget->gimage);
-
- gdisplays_flush ();
- }
- else if (channel_widget->type != AUXILLARY_CHANNEL)
- {
- if (widget->state == GTK_STATE_SELECTED)
- gimp_image_set_component_active (channel_widget->gimage,
- channel_widget->type, TRUE);
- else
- gimp_image_set_component_active (channel_widget->gimage,
- channel_widget->type, FALSE);
- }
- }
- }
-
- static gint
- channel_widget_button_events (GtkWidget *widget,
- GdkEvent *event,
- gpointer data)
- {
- ChannelWidget *channel_widget;
- GtkWidget *event_widget;
- GdkEventButton *bevent;
- gint return_val;
- gint visible;
- gint width, height;
-
- static gboolean button_down = FALSE;
- static GtkWidget *click_widget = NULL;
- static gint old_state;
- static gint exclusive;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
- return_val = FALSE;
-
- switch (channel_widget->type)
- {
- case AUXILLARY_CHANNEL:
- visible = GIMP_DRAWABLE (channel_widget->channel)->visible;
- width = GIMP_DRAWABLE (channel_widget->channel)->width;
- height = GIMP_DRAWABLE (channel_widget->channel)->height;
- break;
- default:
- visible = gimp_image_get_component_visible (channel_widget->gimage,
- channel_widget->type);
- width = channel_widget->gimage->width;
- height = channel_widget->gimage->height;
- break;
- }
-
-
- switch (event->type)
- {
- case GDK_EXPOSE:
- if (widget == channel_widget->eye_widget)
- channel_widget_eye_redraw (channel_widget);
- break;
-
- case GDK_BUTTON_PRESS:
- return_val = TRUE;
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 3)
- {
- gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
- NULL, NULL, NULL, NULL,
- 3, bevent->time);
- return TRUE;
- }
-
- button_down = TRUE;
- click_widget = widget;
- gtk_grab_add (click_widget);
-
- if (widget == channel_widget->eye_widget)
- {
- old_state = visible;
-
- /* If this was a shift-click, make all/none visible */
- if (event->button.state & GDK_SHIFT_MASK)
- {
- exclusive = TRUE;
- channel_widget_exclusive_visible (channel_widget);
- }
- else
- {
- exclusive = FALSE;
- if (channel_widget->type == AUXILLARY_CHANNEL)
- GIMP_DRAWABLE (channel_widget->channel)->visible = !visible;
- else
- gimp_image_set_component_visible (channel_widget->gimage,
- channel_widget->type,
- !visible);
- channel_widget_eye_redraw (channel_widget);
- }
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- return_val = TRUE;
-
- button_down = FALSE;
- gtk_grab_remove (click_widget);
-
- if (widget == channel_widget->eye_widget)
- {
- if (exclusive)
- {
- gdisplays_update_area (channel_widget->gimage, 0, 0, width, height);
- gdisplays_flush ();
- }
- else if (old_state != visible)
- {
- gdisplays_update_area (channel_widget->gimage, 0, 0, width, height);
- gdisplays_flush ();
- }
- }
- break;
-
- case GDK_LEAVE_NOTIFY:
- event_widget = gtk_get_event_widget (event);
-
- if (button_down && (event_widget == click_widget))
- {
- /* the user moved the cursor out of the widget before
- releasing the button -> cancel the button_press */
- button_down = FALSE;
-
- if (widget == channel_widget->eye_widget)
- {
- if (exclusive)
- {
- channel_widget_exclusive_visible (channel_widget);
- }
- else
- {
- if (channel_widget->type == AUXILLARY_CHANNEL)
- GIMP_DRAWABLE (channel_widget->channel)->visible = !visible;
- else
- gimp_image_set_component_visible (channel_widget->gimage,
- channel_widget->type,
- !visible);
- channel_widget_eye_redraw (channel_widget);
- }
- }
- }
- break;
-
- default:
- break;
- }
-
- return return_val;
- }
-
- static gint
- channel_widget_preview_events (GtkWidget *widget,
- GdkEvent *event,
- gpointer data)
- {
- ChannelWidget *channel_widget;
- GdkEventExpose *eevent;
- GdkEventButton *bevent;
- gboolean valid;
-
- valid = FALSE;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 3)
- {
- gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
- NULL, NULL, NULL, NULL,
- 3, bevent->time);
- return TRUE;
- }
- break;
-
- case GDK_EXPOSE:
- if (!preview_size)
- channel_widget_no_preview_redraw (channel_widget);
- else
- {
- switch (channel_widget->type)
- {
- case AUXILLARY_CHANNEL:
- valid = GIMP_DRAWABLE (channel_widget->channel)->preview_valid;
- break;
- default:
- valid = gimp_image_preview_valid (channel_widget->gimage,
- channel_widget->type);
- break;
- }
-
- if (!valid || !channel_widget->channel_pixmap)
- {
- channel_widget_preview_redraw (channel_widget);
-
- gdk_draw_pixmap (widget->window,
- widget->style->black_gc,
- channel_widget->channel_pixmap,
- 0, 0, 0, 0,
- channelsD->image_width,
- channelsD->image_height);
- }
- else
- {
- eevent = (GdkEventExpose *) event;
-
- gdk_draw_pixmap (widget->window,
- widget->style->black_gc,
- channel_widget->channel_pixmap,
- eevent->area.x, eevent->area.y,
- eevent->area.x, eevent->area.y,
- eevent->area.width, eevent->area.height);
- }
- }
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
- static void
- channel_widget_preview_redraw (ChannelWidget *channel_widget)
- {
- TempBuf *preview_buf;
- gint width, height;
- gint channel;
-
- /* allocate the channel widget pixmap */
- if (! channel_widget->channel_pixmap)
- channel_widget->channel_pixmap =
- gdk_pixmap_new (channel_widget->channel_preview->window,
- channelsD->image_width,
- channelsD->image_height,
- -1);
-
- /* determine width and height */
- switch (channel_widget->type)
- {
- case AUXILLARY_CHANNEL:
- width = GIMP_DRAWABLE (channel_widget->channel)->width;
- height = GIMP_DRAWABLE (channel_widget->channel)->height;
- channel_widget->width = RINT (channelsD->ratio * width);
- channel_widget->height = RINT (channelsD->ratio * height);
-
- if (channelsD->ratio > 1.0) /* Preview is scaling up! */
- {
- preview_buf = channel_preview (channel_widget->channel,
- channelsD->gimage_width,
- channelsD->gimage_height);
- preview_buf = gimp_preview_scale (preview_buf,
- channel_widget->width,
- channel_widget->height);
- }
- else
- {
- preview_buf = channel_preview (channel_widget->channel,
- channel_widget->width,
- channel_widget->height);
- }
- break;
-
- default:
- width = channel_widget->gimage->width;
- height = channel_widget->gimage->height;
- channel_widget->width = RINT (channelsD->ratio * width);
- channel_widget->height = RINT (channelsD->ratio * height);
-
- if (channelsD->ratio > 1.0) /* Preview is scaling up! */
- {
- preview_buf = gimp_image_composite_preview (channel_widget->gimage,
- channel_widget->type,
- width,
- height);
- preview_buf = gimp_preview_scale (preview_buf,
- channel_widget->width,
- channel_widget->height);
- }
- else
- {
- preview_buf = gimp_image_composite_preview (channel_widget->gimage,
- channel_widget->type,
- channel_widget->width,
- channel_widget->height);
- }
- break;
- }
-
- switch (channel_widget->type)
- {
- case RED_CHANNEL: channel = RED_PIX; break;
- case GREEN_CHANNEL: channel = GREEN_PIX; break;
- case BLUE_CHANNEL: channel = BLUE_PIX; break;
- case GRAY_CHANNEL: channel = GRAY_PIX; break;
- case INDEXED_CHANNEL: channel = INDEXED_PIX; break;
- case AUXILLARY_CHANNEL: channel = -1; break;
- default: channel = -1; break;
- }
-
- render_preview (preview_buf,
- channelsD->preview,
- channelsD->image_width,
- channelsD->image_height,
- channel);
-
- gtk_preview_put (GTK_PREVIEW (channelsD->preview),
- channel_widget->channel_pixmap,
- channel_widget->channel_preview->style->black_gc,
- 0, 0, 0, 0,
- channelsD->image_width, channelsD->image_height);
-
- /* make sure the image has been transfered completely to the pixmap before
- * we use it again...
- */
- gdk_flush ();
-
- if (channelsD->ratio > 1.0)
- temp_buf_free (preview_buf);
- }
-
- static void
- channel_widget_no_preview_redraw (ChannelWidget *channel_widget)
- {
- GdkPixmap *pixmap;
- GdkPixmap **pixmap_normal;
- GdkPixmap **pixmap_selected;
- GdkPixmap **pixmap_insensitive;
- GdkColor *color;
- GtkWidget *widget;
- GtkStateType state;
- gchar *bits;
- gint width, height;
-
- state = channel_widget->list_item->state;
-
- pixmap_normal = &channel_pixmap[NORMAL];
- pixmap_selected = &channel_pixmap[SELECTED];
- pixmap_insensitive = &channel_pixmap[INSENSITIVE];
- widget = channel_widget->channel_preview;
- bits = (gchar *) channel_bits;
- width = channel_width;
- height = channel_height;
-
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- {
- if (state == GTK_STATE_SELECTED)
- color = &widget->style->bg[GTK_STATE_SELECTED];
- else
- color = &widget->style->white;
- }
- else
- color = &widget->style->bg[GTK_STATE_INSENSITIVE];
-
- gdk_window_set_background (widget->window, color);
-
- if (!*pixmap_normal)
- {
- *pixmap_normal =
- gdk_pixmap_create_from_data (widget->window,
- bits, width, height, -1,
- &widget->style->fg[GTK_STATE_SELECTED],
- &widget->style->bg[GTK_STATE_SELECTED]);
- *pixmap_selected =
- gdk_pixmap_create_from_data (widget->window,
- bits, width, height, -1,
- &widget->style->fg[GTK_STATE_NORMAL],
- &widget->style->white);
- *pixmap_insensitive =
- gdk_pixmap_create_from_data (widget->window,
- bits, width, height, -1,
- &widget->style->fg[GTK_STATE_INSENSITIVE],
- &widget->style->bg[GTK_STATE_INSENSITIVE]);
- }
-
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- {
- if (state == GTK_STATE_SELECTED)
- pixmap = *pixmap_selected;
- else
- pixmap = *pixmap_normal;
- }
- else
- pixmap = *pixmap_insensitive;
-
- gdk_draw_pixmap (widget->window,
- widget->style->black_gc,
- pixmap, 0, 0, 0, 0, width, height);
- }
-
- static void
- channel_widget_eye_redraw (ChannelWidget *channel_widget)
- {
- GdkPixmap *pixmap;
- GdkColor *color;
- GtkStateType state;
- gboolean visible;
-
- state = channel_widget->list_item->state;
-
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- {
- if (state == GTK_STATE_SELECTED)
- color = &channel_widget->eye_widget->style->bg[GTK_STATE_SELECTED];
- else
- color = &channel_widget->eye_widget->style->white;
- }
- else
- color = &channel_widget->eye_widget->style->bg[GTK_STATE_INSENSITIVE];
-
- gdk_window_set_background (channel_widget->eye_widget->window, color);
-
- switch (channel_widget->type)
- {
- case AUXILLARY_CHANNEL:
- visible = GIMP_DRAWABLE (channel_widget->channel)->visible;
- break;
- default:
- visible = gimp_image_get_component_visible (channel_widget->gimage,
- channel_widget->type);
- break;
- }
-
- if (visible)
- {
- if (!eye_pixmap[NORMAL])
- {
- eye_pixmap[NORMAL] =
- gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
- (gchar*) eye_bits, eye_width, eye_height, -1,
- &channel_widget->eye_widget->style->fg[GTK_STATE_NORMAL],
- &channel_widget->eye_widget->style->white);
- eye_pixmap[SELECTED] =
- gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
- (gchar*) eye_bits, eye_width, eye_height, -1,
- &channel_widget->eye_widget->style->fg[GTK_STATE_SELECTED],
- &channel_widget->eye_widget->style->bg[GTK_STATE_SELECTED]);
- eye_pixmap[INSENSITIVE] =
- gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
- (gchar*) eye_bits, eye_width, eye_height, -1,
- &channel_widget->eye_widget->style->fg[GTK_STATE_INSENSITIVE],
- &channel_widget->eye_widget->style->bg[GTK_STATE_INSENSITIVE]);
- }
-
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- {
- if (state == GTK_STATE_SELECTED)
- pixmap = eye_pixmap[SELECTED];
- else
- pixmap = eye_pixmap[NORMAL];
- }
- else
- pixmap = eye_pixmap[INSENSITIVE];
-
- gdk_draw_pixmap (channel_widget->eye_widget->window,
- channel_widget->eye_widget->style->black_gc,
- pixmap, 0, 0, 0, 0, eye_width, eye_height);
- }
- else
- {
- gdk_window_clear (channel_widget->eye_widget->window);
- }
- }
-
- static void
- channel_widget_exclusive_visible (ChannelWidget *channel_widget)
- {
- GSList *list;
- ChannelWidget *cw;
- gboolean visible = FALSE;
-
- if (!channelsD)
- return;
-
- /* First determine if _any_ other channel widgets are set to visible */
- for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
- {
- cw = (ChannelWidget *) list->data;
-
- if (cw != channel_widget)
- {
- switch (cw->type)
- {
- case AUXILLARY_CHANNEL:
- visible |= GIMP_DRAWABLE (cw->channel)->visible;
- break;
- default:
- visible |= gimp_image_get_component_visible (cw->gimage, cw->type);
- break;
- }
- }
- }
-
- /* Now, toggle the visibility for all channels except the specified one */
- for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
- {
- cw = (ChannelWidget *) list->data;
-
- if (cw != channel_widget)
- switch (cw->type)
- {
- case AUXILLARY_CHANNEL:
- GIMP_DRAWABLE (cw->channel)->visible = !visible;
- break;
- default:
- gimp_image_set_component_visible (cw->gimage, cw->type, !visible);
- break;
- }
- else
- switch (cw->type)
- {
- case AUXILLARY_CHANNEL:
- GIMP_DRAWABLE (cw->channel)->visible = TRUE;
- break;
- default:
- gimp_image_set_component_visible (cw->gimage, cw->type, TRUE);
- break;
- }
-
- channel_widget_eye_redraw (cw);
- }
- }
-
- static void
- channel_widget_channel_flush (GtkWidget *widget,
- gpointer data)
- {
- ChannelWidget *channel_widget;
- gboolean update_preview = FALSE;
-
- channel_widget =
- (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
-
- /* Set sensitivity */
-
- /* If there is a floating selection... */
- if (channelsD->floating_sel != NULL)
- {
- /* to insensitive if this is an auxillary channel */
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- gtk_widget_set_sensitive (channel_widget->list_item, FALSE);
- }
- /* to sensitive otherwise */
- else
- {
- if (! GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- gtk_widget_set_sensitive (channel_widget->list_item, TRUE);
- }
- }
- else
- {
- /* to insensitive if there is an active channel,
- * and this is a component channel
- */
- if (channel_widget->type != AUXILLARY_CHANNEL &&
- channelsD->active_channel != NULL)
- {
- if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- gtk_widget_set_sensitive (channel_widget->list_item, FALSE);
- }
- /* to sensitive otherwise */
- else
- {
- if (! GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
- gtk_widget_set_sensitive (channel_widget->list_item, TRUE);
- }
- }
-
- /* Set selection */
-
- /* If this is an auxillary channel */
- if (channel_widget->type == AUXILLARY_CHANNEL)
- {
- /* select if this is the active channel */
- if (channelsD->active_channel == (channel_widget->channel))
- channels_dialog_set_channel (channel_widget);
- /* unselect if this is not the active channel */
- else
- channels_dialog_unset_channel (channel_widget);
- }
- else
- {
- /* If the component is active, select. otherwise, deselect */
- if (gimp_image_get_component_active (channel_widget->gimage,
- channel_widget->type))
- channels_dialog_set_channel (channel_widget);
- else
- channels_dialog_unset_channel (channel_widget);
- }
-
- switch (channel_widget->type)
- {
- case AUXILLARY_CHANNEL:
- update_preview = !GIMP_DRAWABLE (channel_widget->channel)->preview_valid;
- break;
- default:
- update_preview = !gimp_image_preview_valid (channel_widget->gimage,
- channel_widget->type);
- break;
- }
-
- if (update_preview)
- gtk_widget_queue_draw (channel_widget->channel_preview);
- }
-
- /**********************************/
- /* The new channel query dialog */
- /**********************************/
-
- typedef struct _NewChannelOptions NewChannelOptions;
-
- struct _NewChannelOptions
- {
- GtkWidget *query_box;
- GtkWidget *name_entry;
- ColorPanel *color_panel;
-
- GimpImage *gimage;
- gdouble opacity;
- };
-
- static gchar *channel_name = NULL;
- static guchar channel_color[3] = { 0, 0, 0 };
-
- static void
- new_channel_query_ok_callback (GtkWidget *widget,
- gpointer data)
- {
- NewChannelOptions *options;
- Channel *new_channel;
- GimpImage *gimage;
- gint i;
-
- options = (NewChannelOptions *) data;
-
- if (channel_name)
- g_free (channel_name);
- channel_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
-
- if ((gimage = options->gimage))
- {
- new_channel = channel_new (gimage, gimage->width, gimage->height,
- channel_name,
- (gint) (255 * options->opacity) / 100,
- options->color_panel->color);
- drawable_fill (GIMP_DRAWABLE (new_channel), TRANSPARENT_FILL);
-
- for (i = 0; i < 3; i++)
- channel_color[i] = options->color_panel->color[i];
-
- gimp_image_add_channel (gimage, new_channel, -1);
- gdisplays_flush ();
- }
-
- gtk_widget_destroy (options->query_box);
- }
-
- static void
- channels_dialog_new_channel_query (GimpImage* gimage)
- {
- NewChannelOptions *options;
- GtkWidget *hbox;
- GtkWidget *vbox;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *opacity_scale;
- GtkObject *opacity_scale_data;
-
- /* the new options structure */
- options = g_new (NewChannelOptions, 1);
- options->gimage = gimage;
- options->opacity = 50.0;
- options->color_panel = color_panel_new (channel_color, 48, 64);
-
- /* The dialog */
- options->query_box =
- gimp_dialog_new (_("New Channel Options"), "new_channel_options",
- gimp_standard_help_func,
- "dialogs/channels/new_channel.html",
- GTK_WIN_POS_MOUSE,
- FALSE, TRUE, FALSE,
-
- _("OK"), new_channel_query_ok_callback,
- options, NULL, NULL, TRUE, FALSE,
- _("Cancel"), gtk_widget_destroy,
- NULL, 1, NULL, FALSE, TRUE,
-
- NULL);
-
- gtk_signal_connect_object (GTK_OBJECT (options->query_box), "destroy",
- GTK_SIGNAL_FUNC (g_free),
- (GtkObject *) options);
-
- /* 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 name entry hbox, label and entry */
- label = gtk_label_new (_("Channel name:"));
- gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
- GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
- gtk_widget_show (label);
-
- options->name_entry = gtk_entry_new ();
- gtk_widget_set_usize (options->name_entry, 150, 0);
- gtk_table_attach_defaults (GTK_TABLE (table), options->name_entry,
- 1, 2, 0, 1);
- gtk_entry_set_text (GTK_ENTRY (options->name_entry),
- (channel_name ? channel_name : _("New Channel")));
- gtk_widget_show (options->name_entry);
-
- /* The opacity scale */
- label = gtk_label_new (_("Fill Opacity:"));
- gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
- GTK_SHRINK | GTK_FILL, GTK_SHRINK | 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_range_set_update_policy (GTK_RANGE (opacity_scale), GTK_UPDATE_DELAYED);
- gtk_signal_connect (GTK_OBJECT (opacity_scale_data), "value_changed",
- GTK_SIGNAL_FUNC (gimp_double_adjustment_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);
- }
-
- /****************************************/
- /* The edit channel attributes dialog */
- /****************************************/
-
- typedef struct _EditChannelOptions EditChannelOptions;
-
- struct _EditChannelOptions
- {
- GtkWidget *query_box;
- GtkWidget *name_entry;
-
- ChannelWidget *channel_widget;
- GimpImage *gimage;
- ColorPanel *color_panel;
- gdouble opacity;
- };
-
- static void
- edit_channel_query_ok_callback (GtkWidget *widget,
- gpointer data)
- {
- EditChannelOptions *options;
- Channel *channel;
- gint opacity;
- gint update = FALSE;
- gint i;
-
- options = (EditChannelOptions *) data;
- channel = options->channel_widget->channel;
- opacity = (gint) (255 * options->opacity) / 100;
-
- if (options->gimage)
- {
- /* Set the new channel name */
- channel_set_name (channel,
- gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
- gtk_label_set_text (GTK_LABEL (options->channel_widget->label),
- channel_get_name (channel));
-
- if (channel->opacity != opacity)
- {
- channel->opacity = opacity;
- update = TRUE;
- }
- for (i = 0; i < 3; i++)
- if (options->color_panel->color[i] != channel->col[i])
- {
- channel->col[i] = options->color_panel->color[i];
- update = TRUE;
- }
-
- if (update)
- {
- drawable_update (GIMP_DRAWABLE (channel), 0, 0,
- GIMP_DRAWABLE (channel)->width,
- GIMP_DRAWABLE (channel)->height);
- gdisplays_flush ();
- }
- }
-
- gtk_widget_destroy (options->query_box);
- }
-
- static void
- channels_dialog_edit_channel_query (ChannelWidget *channel_widget)
- {
- EditChannelOptions *options;
- GtkWidget *hbox;
- GtkWidget *vbox;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *opacity_scale;
- GtkObject *opacity_scale_data;
- gint i;
-
- /* the new options structure */
- options = g_new (EditChannelOptions, 1);
- options->channel_widget = channel_widget;
- options->gimage = channel_widget->gimage;
- options->opacity = (gdouble) channel_widget->channel->opacity / 2.55;
- for (i = 0; i < 3; i++)
- channel_color[i] = channel_widget->channel->col[i];
-
- options->color_panel = color_panel_new (channel_color, 48, 64);
-
- /* The dialog */
- options->query_box =
- gimp_dialog_new (_("Edit Channel Attributes"), "edit_channel_attributes",
- gimp_standard_help_func,
- "dialogs/channels/edit_channel_attributes.html",
- GTK_WIN_POS_MOUSE,
- FALSE, TRUE, FALSE,
-
- _("OK"), edit_channel_query_ok_callback,
- options, NULL, NULL, TRUE, FALSE,
- _("Cancel"), gtk_widget_destroy,
- NULL, 1, NULL, FALSE, TRUE,
-
- NULL);
-
- gtk_signal_connect_object (GTK_OBJECT (options->query_box), "destroy",
- GTK_SIGNAL_FUNC (g_free),
- (GtkObject *) options);
-
- /* 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 name entry */
- label = gtk_label_new (_("Channel name:"));
- gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
- GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
- gtk_widget_show (label);
-
- options->name_entry = gtk_entry_new ();
- gtk_widget_set_usize (options->name_entry, 150, 0);
- gtk_table_attach_defaults (GTK_TABLE (table), options->name_entry,
- 1, 2, 0, 1);
- gtk_entry_set_text (GTK_ENTRY (options->name_entry),
- channel_get_name (channel_widget->channel));
- gtk_widget_show (options->name_entry);
-
- /* The opacity scale */
- label = gtk_label_new (_("Fill 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",
- GTK_SIGNAL_FUNC (gimp_double_adjustment_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);
- }
-