home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / channels_dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  79.6 KB  |  2,770 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <gtk/gtk.h>
  22. #include <gdk/gdkkeysyms.h>
  23.  
  24. #include "apptypes.h"
  25.  
  26. #include "appenv.h"
  27. #include "channels_dialog.h"
  28. #include "color_panel.h"
  29. #include "drawable.h"
  30. #include "gdisplay.h"
  31. #include "gimage.h"
  32. #include "gimage_mask.h"
  33. #include "gimpdnd.h"
  34. #include "gimppreviewcache.h"
  35. #include "gimprc.h"
  36. #include "gimpui.h"
  37. #include "layers_dialogP.h"
  38. #include "lc_dialogP.h"
  39. #include "menus.h"
  40. #include "ops_buttons.h"
  41. #include "paint_funcs.h"
  42. #include "undo.h"
  43.  
  44. #include "channel_pvt.h"
  45.  
  46. #include "libgimp/gimpintl.h"
  47. #include "libgimp/gimpmath.h"
  48.  
  49. #include "pixmaps/eye.xbm"
  50. #include "pixmaps/channel.xbm"
  51. #include "pixmaps/new.xpm"
  52. #include "pixmaps/raise.xpm"
  53. #include "pixmaps/lower.xpm"
  54. #include "pixmaps/duplicate.xpm"
  55. #include "pixmaps/delete.xpm"
  56. #include "pixmaps/toselection.xpm"
  57.  
  58. #define COMPONENT_BASE_ID 0x10000000
  59.  
  60. typedef struct _ChannelsDialog ChannelsDialog;
  61.  
  62. struct _ChannelsDialog
  63. {
  64.   GtkWidget     *vbox;
  65.   GtkWidget     *channel_list;
  66.   GtkWidget     *scrolled_win;
  67.   GtkWidget     *preview;
  68.   GtkWidget     *ops_menu;
  69.   GtkAccelGroup *accel_group;
  70.  
  71.   /*  state information  */
  72.   GimpImage   *gimage;
  73.   gint         image_width, image_height;
  74.   gint         gimage_width, gimage_height;
  75.   gdouble      ratio;
  76.  
  77.   gint         num_components;
  78.   gint         base_type;
  79.   ChannelType  components[3];
  80.  
  81.   Channel     *active_channel;
  82.   Layer       *floating_sel;
  83.   GSList      *channel_widgets;
  84. };
  85.  
  86. typedef struct _ChannelWidget ChannelWidget;
  87.  
  88. struct _ChannelWidget
  89. {
  90.   GtkWidget *eye_widget;
  91.   GtkWidget *clip_widget;
  92.   GtkWidget *channel_preview;
  93.   GtkWidget *list_item;
  94.   GtkWidget *label;
  95.  
  96.   GdkPixmap *channel_pixmap;
  97.  
  98.   /*  state information  */
  99.   GimpImage   *gimage;
  100.   Channel     *channel;
  101.   gint         width, height;
  102.  
  103.   ChannelType  type;
  104.   gint         ID;
  105.   gboolean     visited;
  106.  
  107.   GimpDropType drop_type;
  108. };
  109.  
  110. /*  channels dialog widget routines  */
  111. static void channels_dialog_preview_extents      (void);
  112. static void channels_dialog_set_menu_sensitivity (void);
  113. static void channels_dialog_set_channel          (ChannelWidget  *cw);
  114. static void channels_dialog_unset_channel        (ChannelWidget  *cw);
  115. static void channels_dialog_position_channel     (Channel        *channel,
  116.                           gint            position);
  117. static void channels_dialog_add_channel          (Channel        *channel);
  118. static void channels_dialog_remove_channel       (ChannelWidget  *cw);
  119.  
  120. static gint channel_list_events                  (GtkWidget      *widget,
  121.                           GdkEvent       *event);
  122.  
  123. /*  for (un)installing the menu accelarators  */
  124. static void channels_dialog_map_callback         (GtkWidget      *widget,
  125.                           gpointer        data);
  126. static void channels_dialog_unmap_callback       (GtkWidget      *widget,
  127.                           gpointer        data);
  128.  
  129. /*  ops buttons dnd callbacks  */
  130. static gboolean channels_dialog_drag_new_channel_callback
  131.                                                  (GtkWidget      *widget,
  132.                           GdkDragContext *context,
  133.                           gint            x,
  134.                           gint            y,
  135.                           guint           time);
  136. static gboolean channels_dialog_drag_duplicate_channel_callback
  137.                                                  (GtkWidget      *widget,
  138.                           GdkDragContext *context,
  139.                           gint            x,
  140.                           gint            y,
  141.                           guint           time);
  142. static gboolean channels_dialog_drag_channel_to_sel_callback
  143.                                                  (GtkWidget      *widget,
  144.                           GdkDragContext *context,
  145.                           gint            x,
  146.                           gint            y,
  147.                           guint           time);
  148. static gboolean channels_dialog_drag_delete_channel_callback
  149.                                                  (GtkWidget      *widget,
  150.                           GdkDragContext *context,
  151.                           gint            x,
  152.                           gint            y,
  153.                           guint           time);
  154.  
  155. /*  channel widget function prototypes  */
  156. static ChannelWidget * channel_widget_get_ID     (Channel        *channel);
  157. static ChannelWidget * channel_widget_create     (GimpImage      *gimage,
  158.                           Channel        *channel,
  159.                           ChannelType     channel_type);
  160.  
  161. static gboolean channel_widget_drag_motion_callback
  162.                                                  (GtkWidget      *widget,
  163.                           GdkDragContext *context,
  164.                           gint            x,
  165.                           gint            y,
  166.                           guint           time);
  167. static gboolean channel_widget_drag_drop_callback(GtkWidget      *widget,
  168.                           GdkDragContext *context,
  169.                           gint            x,
  170.                           gint            y,
  171.                           guint           time);
  172. static void channel_widget_drag_begin_callback   (GtkWidget      *widget,
  173.                           GdkDragContext *context);
  174. static void channel_widget_drag_leave_callback   (GtkWidget      *widget,
  175.                           GdkDragContext *context,
  176.                           guint           time);
  177. static void channel_widget_drag_indicator_callback
  178.                                                  (GtkWidget      *widget,
  179.                           gpointer        data);
  180.  
  181. static void channel_widget_drop_color            (GtkWidget      *widget,
  182.                           guchar          r,
  183.                           guchar          g,
  184.                           guchar          b,
  185.                           gpointer        data);
  186. static void channel_widget_draw_drop_indicator   (ChannelWidget  *cw,
  187.                           GimpDropType    drop_type);
  188. static void channel_widget_delete                (ChannelWidget  *cw);
  189. static void channel_widget_select_update         (GtkWidget      *widget,
  190.                           gpointer        data);
  191. static gint channel_widget_button_events         (GtkWidget      *widget,
  192.                           GdkEvent       *event,
  193.                           gpointer        data);
  194. static gint channel_widget_preview_events        (GtkWidget      *widget,
  195.                           GdkEvent       *event,
  196.                           gpointer        data);
  197. static void channel_widget_preview_redraw        (ChannelWidget  *cw);
  198. static void channel_widget_no_preview_redraw     (ChannelWidget  *cw);
  199. static void channel_widget_eye_redraw            (ChannelWidget  *cw);
  200. static void channel_widget_exclusive_visible     (ChannelWidget  *cw);
  201. static void channel_widget_channel_flush         (GtkWidget      *widget,
  202.                           gpointer        data);
  203.  
  204. /*  assorted query dialogs  */
  205. static void channels_dialog_new_channel_query    (GimpImage      *gimage);
  206. static void channels_dialog_edit_channel_query   (ChannelWidget  *cw);
  207.  
  208. /****************/
  209. /*  Local data  */
  210. /****************/
  211.  
  212. static ChannelsDialog *channelsD = NULL;
  213.  
  214. static GdkPixmap *eye_pixmap[]     = { NULL, NULL, NULL };
  215. static GdkPixmap *channel_pixmap[] = { NULL, NULL, NULL };
  216.  
  217. static gint suspend_gimage_notify = 0;
  218.  
  219. /*  the ops buttons  */
  220. static GtkSignalFunc to_selection_ext_callbacks[] = 
  221.   channels_dialog_add_channel_to_sel_callback,          /* SHIFT */
  222.   channels_dialog_sub_channel_from_sel_callback,        /* CTRL  */
  223.   channels_dialog_intersect_channel_with_sel_callback,  /* MOD1  */
  224.   channels_dialog_intersect_channel_with_sel_callback,  /* SHIFT + CTRL */
  225. };
  226.  
  227. static OpsButton channels_ops_buttons[] =
  228. {
  229.   { new_xpm, channels_dialog_new_channel_callback, NULL,
  230.     N_("New Channel"),
  231.     "channels/dialogs/new_channel.html",
  232.     NULL, 0 },
  233.   { raise_xpm, channels_dialog_raise_channel_callback, NULL,
  234.     N_("Raise Channel"),
  235.     "channels/raise_channel.html",
  236.     NULL, 0 },
  237.   { lower_xpm, channels_dialog_lower_channel_callback, NULL,
  238.     N_("Lower Channel"),
  239.     "channels/lower_channel.html",
  240.     NULL, 0 },
  241.   { duplicate_xpm, channels_dialog_duplicate_channel_callback, NULL,
  242.     N_("Duplicate Channel"),
  243.     "channels/duplicate_channel.html",
  244.     NULL, 0 },
  245.   { toselection_xpm, channels_dialog_channel_to_sel_callback,
  246.     to_selection_ext_callbacks,
  247.     N_("Channel to Selection \n"
  248.        "<Shift> Add          "
  249.        "<Ctrl> Subtract      "
  250.        "<Shift><Ctrl> Intersect"),
  251.     "channels/channel_to_selection.html",
  252.     NULL, 0 },
  253.   { delete_xpm, channels_dialog_delete_channel_callback, NULL,
  254.     N_("Delete Channel"),
  255.     "channels/delete_channel.html",
  256.     NULL, 0 },
  257.   { NULL, NULL, NULL, NULL, NULL, NULL, 0 }
  258. };
  259.  
  260. /*  dnd structures  */
  261. static GtkTargetEntry channel_color_target_table[] =
  262. {
  263.   GIMP_TARGET_CHANNEL,
  264.   GIMP_TARGET_COLOR
  265. };
  266. static guint n_channel_color_targets = (sizeof (channel_color_target_table) /
  267.                     sizeof (channel_color_target_table[0]));
  268.  
  269. static GtkTargetEntry channel_target_table[] =
  270. {
  271.   GIMP_TARGET_CHANNEL
  272. };
  273. static guint n_channel_targets = (sizeof (channel_target_table) /
  274.                   sizeof (channel_target_table[0]));
  275.  
  276. static GtkTargetEntry component_target_table[] =
  277. {
  278.   GIMP_TARGET_COMPONENT
  279. };
  280. static guint n_component_targets = (sizeof (component_target_table) /
  281.                     sizeof (component_target_table[0]));
  282.  
  283.  
  284. /**************************************/
  285. /*  Public channels dialog functions  */
  286. /**************************************/
  287.  
  288. GtkWidget *
  289. channels_dialog_create (void)
  290. {
  291.   GtkWidget *vbox;
  292.   GtkWidget *button_box;
  293.  
  294.   if (channelsD)
  295.     return channelsD->vbox;
  296.  
  297.   channelsD = g_new (ChannelsDialog, 1);
  298.   channelsD->preview         = NULL;
  299.   channelsD->gimage          = NULL;
  300.   channelsD->active_channel  = NULL;
  301.   channelsD->floating_sel    = NULL;
  302.   channelsD->channel_widgets = NULL;
  303.  
  304.   if (preview_size)
  305.     {
  306.       channelsD->preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
  307.       gtk_preview_size (GTK_PREVIEW (channelsD->preview),
  308.             preview_size, preview_size);
  309.     }
  310.  
  311.   /*  The main vbox  */
  312.   channelsD->vbox = gtk_event_box_new ();
  313.  
  314.   gimp_help_set_help_data (channelsD->vbox, NULL,
  315.                "dialogs/channels/channels.html");
  316.  
  317.   vbox = gtk_vbox_new (FALSE, 1);
  318.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  319.   gtk_container_add (GTK_CONTAINER (channelsD->vbox), vbox);
  320.  
  321.   /*  The channels commands pulldown menu  */
  322.   menus_get_channels_menu (&channelsD->ops_menu, &channelsD->accel_group);
  323.  
  324.   /*  The channels listbox  */
  325.   channelsD->scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  326.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (channelsD->scrolled_win), 
  327.                   GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  328.   gtk_widget_set_usize (channelsD->scrolled_win, LIST_WIDTH, LIST_HEIGHT);
  329.   gtk_box_pack_start (GTK_BOX (vbox), channelsD->scrolled_win, TRUE, TRUE, 2);
  330.  
  331.   channelsD->channel_list = gtk_list_new ();
  332.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (channelsD->scrolled_win),
  333.                      channelsD->channel_list);
  334.   gtk_list_set_selection_mode (GTK_LIST (channelsD->channel_list),
  335.                    GTK_SELECTION_MULTIPLE);
  336.   gtk_signal_connect (GTK_OBJECT (channelsD->channel_list), "event",
  337.               (GtkSignalFunc) channel_list_events,
  338.               channelsD);
  339.   gtk_container_set_focus_vadjustment (GTK_CONTAINER (channelsD->channel_list),
  340.                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (channelsD->scrolled_win)));
  341.   GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (channelsD->scrolled_win)->vscrollbar,
  342.               GTK_CAN_FOCUS);
  343.  
  344.   gtk_widget_show (channelsD->channel_list);
  345.   gtk_widget_show (channelsD->scrolled_win);
  346.  
  347.   /*  The ops buttons  */
  348.   button_box = ops_button_box_new (channels_ops_buttons, OPS_BUTTON_NORMAL);
  349.   gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
  350.   gtk_widget_show (button_box);
  351.  
  352.   /*  Drop to new  */
  353.   gtk_drag_dest_set (channels_ops_buttons[0].widget,
  354.                      GTK_DEST_DEFAULT_ALL,
  355.                      channel_target_table, n_channel_targets,
  356.                      GDK_ACTION_COPY);
  357.   gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[0].widget), "drag_drop",
  358.                       GTK_SIGNAL_FUNC (channels_dialog_drag_new_channel_callback),
  359.                       NULL);
  360.  
  361.   /*  Drop to duplicate  */
  362.   gtk_drag_dest_set (channels_ops_buttons[3].widget,
  363.                      GTK_DEST_DEFAULT_ALL,
  364.                      channel_target_table, n_channel_targets,
  365.                      GDK_ACTION_COPY);
  366.   gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[3].widget), "drag_drop",
  367.                       GTK_SIGNAL_FUNC (channels_dialog_drag_duplicate_channel_callback),
  368.               NULL);
  369.  
  370.   /*  Drop to channel to selection  */
  371.   gtk_drag_dest_set (channels_ops_buttons[4].widget,
  372.                      GTK_DEST_DEFAULT_ALL,
  373.                      channel_target_table, n_channel_targets,
  374.                      GDK_ACTION_COPY);
  375.   gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[4].widget), "drag_drop",
  376.                       GTK_SIGNAL_FUNC (channels_dialog_drag_channel_to_sel_callback),
  377.               NULL);
  378.  
  379.   /*  Drop to trahcan  */
  380.   gtk_drag_dest_set (channels_ops_buttons[5].widget,
  381.                      GTK_DEST_DEFAULT_ALL,
  382.                      channel_target_table, n_channel_targets,
  383.                      GDK_ACTION_COPY);
  384.   gtk_signal_connect (GTK_OBJECT (channels_ops_buttons[5].widget), "drag_drop",
  385.                       GTK_SIGNAL_FUNC (channels_dialog_drag_delete_channel_callback),
  386.                       NULL);
  387.  
  388.   /*  Set up signals for map/unmap for the accelerators  */
  389.   gtk_signal_connect (GTK_OBJECT (channelsD->vbox), "map",
  390.               (GtkSignalFunc) channels_dialog_map_callback,
  391.               NULL);
  392.   gtk_signal_connect (GTK_OBJECT (channelsD->vbox), "unmap",
  393.               (GtkSignalFunc) channels_dialog_unmap_callback,
  394.               NULL);
  395.  
  396.   gtk_widget_show (vbox);
  397.   gtk_widget_show (channelsD->vbox);
  398.  
  399.   return channelsD->vbox;
  400. }
  401.  
  402. void
  403. channels_dialog_free (void)
  404. {
  405.   ChannelWidget *cw;
  406.   GSList *list;
  407.  
  408.   if (!channelsD)
  409.     return;
  410.  
  411.   suspend_gimage_notify++;
  412.   /*  Free all elements in the channels listbox  */
  413.   gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
  414.   suspend_gimage_notify--;
  415.  
  416.   list = channelsD->channel_widgets;
  417.   while (list)
  418.     {
  419.       cw = (ChannelWidget *) list->data;
  420.       list = g_slist_next (list);
  421.       channel_widget_delete (cw);
  422.     }
  423.   channelsD->channel_widgets = NULL;
  424.   channelsD->active_channel  = NULL;
  425.   channelsD->floating_sel    = NULL;
  426.  
  427.   if (channelsD->preview)
  428.     gtk_object_sink (GTK_OBJECT (channelsD->preview));
  429.  
  430.   g_free (channelsD);
  431.   channelsD = NULL;
  432. }
  433.  
  434. void
  435. channels_dialog_update (GimpImage* gimage)
  436. {
  437.   Channel       *channel;
  438.   ChannelWidget *cw;
  439.   GSList        *list;
  440.   GList         *item_list;
  441.  
  442.   if (!channelsD || channelsD->gimage == gimage)
  443.     return;
  444.  
  445.   channelsD->gimage = gimage;
  446.  
  447.   suspend_gimage_notify++;
  448.   /*  Free all elements in the channels listbox  */
  449.   gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
  450.   suspend_gimage_notify--;
  451.  
  452.   list = channelsD->channel_widgets;
  453.   while (list)
  454.     {
  455.       cw = (ChannelWidget *) list->data;
  456.       list = g_slist_next (list);
  457.       channel_widget_delete (cw);
  458.     }
  459.   channelsD->channel_widgets = NULL;
  460.  
  461.   /*  Find the preview extents  */
  462.   channels_dialog_preview_extents ();
  463.  
  464.   channelsD->active_channel = NULL;
  465.   channelsD->floating_sel = NULL;
  466.  
  467.   /*  The image components  */
  468.   item_list = NULL;
  469.   switch ((channelsD->base_type = gimp_image_base_type (gimage)))
  470.     {
  471.     case RGB:
  472.       cw = channel_widget_create (gimage, NULL, RED_CHANNEL);
  473.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  474.       item_list = g_list_append (item_list, cw->list_item);
  475.       channelsD->components[0] = RED_CHANNEL;
  476.  
  477.       cw = channel_widget_create (gimage, NULL, GREEN_CHANNEL);
  478.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  479.       item_list = g_list_append (item_list, cw->list_item);
  480.       channelsD->components[1] = GREEN_CHANNEL;
  481.  
  482.       cw = channel_widget_create (gimage, NULL, BLUE_CHANNEL);
  483.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  484.       item_list = g_list_append (item_list, cw->list_item);
  485.       channelsD->components[2] = BLUE_CHANNEL;
  486.  
  487.       channelsD->num_components = 3;
  488.       break;
  489.  
  490.     case GRAY:
  491.       cw = channel_widget_create (gimage, NULL, GRAY_CHANNEL);
  492.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  493.       item_list = g_list_append (item_list, cw->list_item);
  494.       channelsD->components[0] = GRAY_CHANNEL;
  495.  
  496.       channelsD->num_components = 1;
  497.       break;
  498.  
  499.     case INDEXED:
  500.       cw = channel_widget_create (gimage, NULL, INDEXED_CHANNEL);
  501.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  502.       item_list = g_list_append (item_list, cw->list_item);
  503.       channelsD->components[0] = INDEXED_CHANNEL;
  504.  
  505.       channelsD->num_components = 1;
  506.       break;
  507.     }
  508.  
  509.   /*  The auxillary image channels  */
  510.   for (list = gimage->channels; list; list = g_slist_next (list))
  511.     {
  512.       /*  create a channel list item  */
  513.       channel = (Channel *) list->data;
  514.       cw = channel_widget_create (gimage, channel, AUXILLARY_CHANNEL);
  515.       channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
  516.       item_list = g_list_append (item_list, cw->list_item);
  517.     }
  518.  
  519.   /*  get the index of the active channel  */
  520.   if (item_list)
  521.     gtk_list_insert_items (GTK_LIST (channelsD->channel_list), item_list, 0);
  522. }
  523.  
  524. void
  525. channels_dialog_flush (void)
  526. {
  527.   GimpImage     *gimage;
  528.   Channel       *channel;
  529.   ChannelWidget *cw;
  530.   GSList        *list;
  531.   gint           pos;
  532.  
  533.   if (!channelsD || !(gimage = channelsD->gimage))
  534.     return;
  535.  
  536.   /*  Check if the gimage extents have changed  */
  537.   if ((gimage->width != channelsD->gimage_width) ||
  538.       (gimage->height != channelsD->gimage_height) ||
  539.       (gimp_image_base_type (gimage) != channelsD->base_type))
  540.     {
  541.       channelsD->gimage = NULL;
  542.       channels_dialog_update (gimage);
  543.     }
  544.   else
  545.     {
  546.       /*  Set all current channel widgets to visited = FALSE  */
  547.       for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
  548.     {
  549.       cw = (ChannelWidget *) list->data;
  550.       cw->visited = FALSE;
  551.     }
  552.  
  553.       /*  Add any missing channels  */
  554.       for (list = gimage->channels; list; list = g_slist_next (list))
  555.     {
  556.       channel = (Channel *) list->data;
  557.       cw = channel_widget_get_ID (channel);
  558.  
  559.       /*  If the channel isn't in the channel widget list, add it  */
  560.       if (cw == NULL)
  561.         {
  562.           /*  sets visited = TRUE  */
  563.           channels_dialog_add_channel (channel);
  564.         }
  565.       else
  566.         cw->visited = TRUE;
  567.     }
  568.  
  569.       /*  Remove any extraneous auxillary channels  */
  570.       list = channelsD->channel_widgets;
  571.       while (list)
  572.     {
  573.       cw = (ChannelWidget *) list->data;
  574.       list = g_slist_next (list);
  575.       if (cw->visited == FALSE && cw->type == AUXILLARY_CHANNEL)
  576.         {
  577.           /*  will only be true for auxillary channels  */
  578.           channels_dialog_remove_channel (cw);
  579.         }
  580.     }
  581.  
  582.       /*  Switch positions of items if necessary  */
  583.       pos = 0;
  584.       for (list = gimage->channels; list; list = g_slist_next (list))
  585.     {
  586.       channel = (Channel *) list->data;
  587.       channels_dialog_position_channel (channel, pos++);
  588.     }
  589.  
  590.       /*  Set the active channel  */
  591.       if (channelsD->active_channel != gimage->active_channel)
  592.     channelsD->active_channel = gimage->active_channel;
  593.  
  594.       /*  set the menus if floating sel status has changed  */
  595.       if (channelsD->floating_sel != gimage->floating_sel)
  596.     channelsD->floating_sel = gimage->floating_sel;
  597.  
  598.       channels_dialog_set_menu_sensitivity ();
  599.  
  600.       gtk_container_foreach (GTK_CONTAINER (channelsD->channel_list),
  601.                  channel_widget_channel_flush, NULL);
  602.     }
  603. }
  604.  
  605. void
  606. channels_dialog_clear (void)
  607. {
  608.   if (!channelsD)
  609.     return;
  610.  
  611.   suspend_gimage_notify++;
  612.   gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
  613.   suspend_gimage_notify--;
  614.  
  615.   channelsD->gimage = NULL;
  616. }
  617.  
  618. static void
  619. channels_dialog_preview_extents (void)
  620. {
  621.   GimpImage *gimage;
  622.  
  623.   g_return_if_fail (channelsD);
  624.   if (! (gimage = channelsD->gimage))
  625.     return;
  626.  
  627.   channelsD->gimage_width  = gimage->width;
  628.   channelsD->gimage_height = gimage->height;
  629.  
  630.   /*  Get the image width and height variables, based on the gimage  */
  631.   if (gimage->width > gimage->height)
  632.     channelsD->ratio = (gdouble) preview_size / (gdouble) gimage->width;
  633.   else  
  634.     channelsD->ratio = (gdouble) preview_size / (gdouble) gimage->height;
  635.  
  636.   if (preview_size)
  637.     {
  638.       channelsD->image_width  = RINT (channelsD->ratio * gimage->width);
  639.       channelsD->image_height = RINT (channelsD->ratio * gimage->height);
  640.  
  641.       if (channelsD->image_width < 1)  channelsD->image_width  = 1;
  642.       if (channelsD->image_height < 1) channelsD->image_height = 1;
  643.     }
  644.   else
  645.     {
  646.       channelsD->image_width  = channel_width;
  647.       channelsD->image_height = channel_height;
  648.     }
  649. }
  650.  
  651. static void
  652. channels_dialog_set_menu_sensitivity (void)
  653. {
  654.   ChannelWidget *cw;
  655.   gint fs_sens;
  656.   gint aux_sens;
  657.  
  658.   cw = channel_widget_get_ID (channelsD->active_channel);
  659.   fs_sens = (channelsD->floating_sel != NULL);
  660.  
  661.   if (cw)
  662.     aux_sens = (cw->type == AUXILLARY_CHANNEL);
  663.   else
  664.     aux_sens = FALSE;
  665.  
  666. #define SET_SENSITIVE(menu,condition) \
  667.         menus_set_sensitive ("<Channels>/" menu, (condition) != 0)
  668. #define SET_OPS_SENSITIVE(button,condition) \
  669.         gtk_widget_set_sensitive (channels_ops_buttons[(button)].widget, \
  670.                                  (condition) != 0)
  671.  
  672.   SET_SENSITIVE ("New Channel...", !fs_sens);
  673.   SET_OPS_SENSITIVE (0, !fs_sens);
  674.  
  675.   SET_SENSITIVE ("Raise Channel", !fs_sens && aux_sens);
  676.   SET_OPS_SENSITIVE (1, !fs_sens && aux_sens);
  677.  
  678.   SET_SENSITIVE ("Lower Channel", !fs_sens && aux_sens);
  679.   SET_OPS_SENSITIVE (2, !fs_sens && aux_sens);
  680.  
  681.   SET_SENSITIVE ("Duplicate Channel", !fs_sens && aux_sens);
  682.   SET_OPS_SENSITIVE (3, !fs_sens && aux_sens);
  683.  
  684.   SET_SENSITIVE ("Channel to Selection", aux_sens);
  685.   SET_OPS_SENSITIVE (4, aux_sens);
  686.  
  687.   SET_SENSITIVE ("Add to Selection", aux_sens);
  688.   SET_SENSITIVE ("Subtract from Selection", aux_sens);
  689.   SET_SENSITIVE ("Intersect with Selection", aux_sens);
  690.  
  691.   SET_SENSITIVE ("Delete Channel", !fs_sens && aux_sens);
  692.   SET_OPS_SENSITIVE (5, !fs_sens && aux_sens);
  693.  
  694.   SET_SENSITIVE ("Edit Channel Attributes...", !fs_sens && aux_sens);
  695.  
  696. #undef SET_OPS_SENSITIVE
  697. #undef SET_SENSITIVE
  698. }
  699.  
  700. static gint
  701. channels_dialog_idle_set_channel_focus (gpointer data)
  702. {
  703.   gtk_widget_grab_focus (GTK_WIDGET (data));
  704.  
  705.   return FALSE;
  706. }
  707.  
  708. static void
  709. channels_dialog_set_channel (ChannelWidget *channel_widget)
  710. {
  711.   GtkStateType state;
  712.   gint index;
  713.  
  714.   if (!channelsD || !channel_widget)
  715.     return;
  716.  
  717.   /*  Make sure the gimage is not notified of this change  */
  718.   suspend_gimage_notify++;
  719.  
  720.   /*  get the list item data  */
  721.   state = channel_widget->list_item->state;
  722.  
  723.   if (channel_widget->type == AUXILLARY_CHANNEL)
  724.     {
  725.       /*  turn on the specified auxillary channel  */
  726.       index = gimp_image_get_channel_index (channel_widget->gimage,
  727.                         channel_widget->channel);
  728.       if ((index >= 0) && (state != GTK_STATE_SELECTED))
  729.     {
  730.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  731.                     NULL);
  732.       gtk_list_select_item (GTK_LIST (channelsD->channel_list),
  733.                 index + channelsD->num_components);
  734.       /*  let dnd finish it's work before setting the focus  */
  735.       gtk_idle_add ((GtkFunction) channels_dialog_idle_set_channel_focus,
  736.             channel_widget->list_item);
  737.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  738.                     channel_widget);
  739.       /* channels_dialog_scroll_index (index + channelsD->num_components); */
  740.     }
  741.     }
  742.   else
  743.     {
  744.       if (state != GTK_STATE_SELECTED)
  745.     {
  746.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  747.                     NULL);
  748.       switch (channel_widget->type)
  749.         {
  750.         case RED_CHANNEL:
  751.         case GRAY_CHANNEL:
  752.         case INDEXED_CHANNEL:
  753.           gtk_list_select_item (GTK_LIST (channelsD->channel_list), 0);
  754.           break;
  755.         case GREEN_CHANNEL:
  756.           gtk_list_select_item (GTK_LIST (channelsD->channel_list), 1);
  757.           break;
  758.         case BLUE_CHANNEL:
  759.           gtk_list_select_item (GTK_LIST (channelsD->channel_list), 2);
  760.           break;
  761.         case AUXILLARY_CHANNEL:
  762.           g_error ("error in %s at %d: this shouldn't happen.",
  763.                __FILE__, __LINE__);
  764.           break;
  765.         }
  766.  
  767.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  768.                     channel_widget);
  769.       /* channels_dialog_scroll_index (0); */
  770.     }
  771.     }
  772.   suspend_gimage_notify--;
  773. }
  774.  
  775. static void
  776. channels_dialog_unset_channel (ChannelWidget *channel_widget)
  777. {
  778.   GtkStateType state;
  779.   gint index;
  780.  
  781.   if (!channelsD || !channel_widget)
  782.     return;
  783.  
  784.   /*  Make sure the gimage is not notified of this change  */
  785.   suspend_gimage_notify++;
  786.  
  787.   /*  get the list item data  */
  788.   state = channel_widget->list_item->state;
  789.  
  790.   if (channel_widget->type == AUXILLARY_CHANNEL)
  791.     {
  792.       /*  turn off the specified auxillary channel  */
  793.       index = gimp_image_get_channel_index (channel_widget->gimage,
  794.                         channel_widget->channel);
  795.       if ((index >= 0) && (state == GTK_STATE_SELECTED))
  796.     {
  797.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  798.                     NULL);
  799.       gtk_list_unselect_item (GTK_LIST (channelsD->channel_list),
  800.                   index + channelsD->num_components);
  801.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  802.                     channel_widget);
  803.     }
  804.     }
  805.   else
  806.     {
  807.       if (state == GTK_STATE_SELECTED)
  808.     {
  809.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  810.                     NULL);
  811.       switch (channel_widget->type)
  812.         {
  813.         case RED_CHANNEL:
  814.         case GRAY_CHANNEL:
  815.         case INDEXED_CHANNEL:
  816.           gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 0);
  817.           break;
  818.         case GREEN_CHANNEL:
  819.           gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 1);
  820.           break;
  821.         case BLUE_CHANNEL:
  822.           gtk_list_unselect_item (GTK_LIST (channelsD->channel_list), 2);
  823.           break;
  824.         case AUXILLARY_CHANNEL:
  825.           g_error ("error in %s at %d: this shouldn't happen.",
  826.                __FILE__, __LINE__);
  827.           break;
  828.         }
  829.  
  830.       gtk_object_set_user_data (GTK_OBJECT (channel_widget->list_item),
  831.                     channel_widget);
  832.     }
  833.     }
  834.  
  835.   suspend_gimage_notify--;
  836. }
  837.  
  838. static void
  839. channels_dialog_position_channel (Channel *channel,
  840.                   gint     new_index)
  841. {
  842.   ChannelWidget *channel_widget;
  843.   GList *list = NULL;
  844.  
  845.   channel_widget = channel_widget_get_ID (channel);
  846.   if (!channelsD || !channel_widget)
  847.     return;
  848.  
  849.   if ((new_index + channelsD->num_components) ==
  850.       g_slist_index (channelsD->channel_widgets, channel_widget))
  851.     return;
  852.  
  853.   /*  Make sure the gimage is not notified of this change  */
  854.   suspend_gimage_notify++;
  855.  
  856.   /*  Remove the channel from the dialog  */
  857.   list = g_list_append (list, channel_widget->list_item);
  858.   gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
  859.   channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets,
  860.                            channel_widget);
  861.  
  862.   /*  Add it back at the proper index  */
  863.   gtk_list_insert_items (GTK_LIST (channelsD->channel_list), list,
  864.              new_index + channelsD->num_components);
  865.   channelsD->channel_widgets =
  866.     g_slist_insert (channelsD->channel_widgets, channel_widget,
  867.             new_index + channelsD->num_components);
  868.  
  869.   /*   channels_dialog_scroll_index (new_index > 0 ?  */
  870.   /*                 new_index + channelsD->num_components + 1 : */
  871.   /*                 channelsD->num_components); */
  872.   
  873.   suspend_gimage_notify--;
  874. }
  875.  
  876. static void
  877. channels_dialog_add_channel (Channel *channel)
  878. {
  879.   ChannelWidget *channel_widget;
  880.   GimpImage *gimage;
  881.   GList *item_list;
  882.   gint   position;
  883.  
  884.   if (!channelsD || !channel || !(gimage = channelsD->gimage))
  885.     return;
  886.  
  887.   item_list = NULL;
  888.  
  889.   channel_widget = channel_widget_create (gimage, channel, AUXILLARY_CHANNEL);
  890.   item_list = g_list_append (item_list, channel_widget->list_item);
  891.  
  892.   position = gimp_image_get_channel_index (gimage, channel);
  893.   channelsD->channel_widgets =
  894.     g_slist_insert (channelsD->channel_widgets, channel_widget,
  895.             position + channelsD->num_components);
  896.   gtk_list_insert_items (GTK_LIST (channelsD->channel_list), item_list,
  897.              position + channelsD->num_components);
  898. }
  899.  
  900. static void
  901. channels_dialog_remove_channel (ChannelWidget *channel_widget)
  902. {
  903.   GList *list = NULL;
  904.  
  905.   if (!channelsD || !channel_widget)
  906.     return;
  907.  
  908.   /*  Make sure the gimage is not notified of this change  */
  909.   suspend_gimage_notify++;
  910.  
  911.   /*  Remove the requested channel from the dialog  */
  912.   list = g_list_append (list, channel_widget->list_item);
  913.   gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
  914.  
  915.   /*  Delete the channel_widget  */
  916.   channel_widget_delete (channel_widget);
  917.  
  918.   suspend_gimage_notify--;
  919. }
  920.  
  921. static gint
  922. channel_list_events (GtkWidget *widget,
  923.              GdkEvent  *event)
  924. {
  925.   ChannelWidget  *channel_widget;
  926.   GdkEventButton *bevent;
  927.   GtkWidget      *event_widget;
  928.  
  929.   event_widget = gtk_get_event_widget (event);
  930.  
  931.   if (GTK_IS_LIST_ITEM (event_widget))
  932.     {
  933.       channel_widget =
  934.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (event_widget));
  935.  
  936.       switch (event->type)
  937.     {
  938.     case GDK_BUTTON_PRESS:
  939.       bevent = (GdkEventButton *) event;
  940.       if (bevent->button == 3)
  941.         {
  942.           gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
  943.                   NULL, NULL, NULL, NULL,
  944.                   bevent->button, bevent->time);
  945.           return TRUE;
  946.         }
  947.       break;
  948.  
  949.     case GDK_2BUTTON_PRESS:
  950.       if (channel_widget->type == AUXILLARY_CHANNEL)
  951.         channels_dialog_edit_channel_query (channel_widget);
  952.       return TRUE;
  953.  
  954.     default:
  955.       break;
  956.     }
  957.     }
  958.  
  959.   return FALSE;
  960. }
  961.  
  962. /*******************************/
  963. /*  channels dialog callbacks  */
  964. /*******************************/
  965.  
  966. static void
  967. channels_dialog_map_callback (GtkWidget *widget,
  968.                   gpointer   data)
  969. {
  970.   if (! channelsD)
  971.     return;
  972.  
  973.   gtk_window_add_accel_group (GTK_WINDOW (lc_dialog->shell),
  974.                   channelsD->accel_group);
  975. }
  976.  
  977. static void
  978. channels_dialog_unmap_callback (GtkWidget *widget,
  979.                 gpointer   data)
  980. {
  981.   if (! channelsD)
  982.     return;
  983.  
  984.   gtk_window_remove_accel_group (GTK_WINDOW (lc_dialog->shell),
  985.                  channelsD->accel_group);
  986. }
  987.  
  988. /***********************************/
  989. /*  callbacks exported to menus.c  */
  990. /***********************************/
  991.  
  992. void
  993. channels_dialog_new_channel_callback (GtkWidget *widget,
  994.                       gpointer   data)
  995. {
  996.   if (!channelsD || channelsD->gimage == NULL)
  997.     return;
  998.  
  999.   channels_dialog_new_channel_query (channelsD->gimage);
  1000. }
  1001.  
  1002. void
  1003. channels_dialog_raise_channel_callback (GtkWidget *widget,
  1004.                     gpointer   data)
  1005. {
  1006.   GimpImage *gimage;
  1007.  
  1008.   if (!channelsD || !(gimage = channelsD->gimage))
  1009.     return;
  1010.  
  1011.   if (gimage->active_channel != NULL)
  1012.     {
  1013.       gimp_image_raise_channel (gimage, gimage->active_channel);
  1014.       gdisplays_flush ();
  1015.     }
  1016. }
  1017.  
  1018. void
  1019. channels_dialog_lower_channel_callback (GtkWidget *widget,
  1020.                     gpointer   data)
  1021. {
  1022.   GimpImage *gimage;
  1023.  
  1024.   if (!channelsD || !(gimage = channelsD->gimage))
  1025.     return;
  1026.  
  1027.   if (gimage->active_channel != NULL)
  1028.     {
  1029.       gimp_image_lower_channel (gimage, gimage->active_channel);
  1030.       gdisplays_flush ();
  1031.     }
  1032. }
  1033.  
  1034. void
  1035. channels_dialog_duplicate_channel_callback (GtkWidget *widget,
  1036.                         gpointer   data)
  1037. {
  1038.   GimpImage *gimage;
  1039.   Channel *active_channel;
  1040.   Channel *new_channel;
  1041.  
  1042.   if (!channelsD || !(gimage = channelsD->gimage))
  1043.     return;
  1044.  
  1045.   if ((active_channel = gimp_image_get_active_channel (gimage)))
  1046.     {
  1047.       new_channel = channel_copy (active_channel);
  1048.       gimp_image_add_channel (gimage, new_channel, -1);
  1049.       gdisplays_flush ();
  1050.     }
  1051. }
  1052.  
  1053. void
  1054. channels_dialog_delete_channel_callback (GtkWidget *widget,
  1055.                      gpointer   data)
  1056. {
  1057.   GimpImage *gimage;
  1058.  
  1059.   if (!channelsD || !(gimage = channelsD->gimage))
  1060.     return;
  1061.  
  1062.   if (gimage->active_channel != NULL)
  1063.     {
  1064.       gimp_image_remove_channel (gimage, gimage->active_channel);
  1065.       gdisplays_flush ();
  1066.     }
  1067. }
  1068.  
  1069. void
  1070. channels_dialog_channel_to_sel_callback (GtkWidget *widget,
  1071.                      gpointer   data)
  1072. {
  1073.   GimpImage *gimage;
  1074.  
  1075.   if (!channelsD || !(gimage = channelsD->gimage))
  1076.     return;
  1077.  
  1078.   if (gimage->active_channel != NULL)
  1079.     {
  1080.       gimage_mask_load (gimage, gimage->active_channel);
  1081.       gdisplays_flush ();
  1082.     }
  1083. }
  1084.  
  1085. void
  1086. channels_dialog_add_channel_to_sel_callback (GtkWidget *widget,
  1087.                          gpointer   data)
  1088. {
  1089.   GimpImage *gimage;
  1090.   Channel *active_channel;
  1091.   Channel *new_channel;
  1092.  
  1093.   if (!channelsD || !(gimage = channelsD->gimage))
  1094.     return;
  1095.  
  1096.   if ((active_channel = gimp_image_get_active_channel (gimage)))
  1097.     {
  1098.       new_channel = channel_copy (gimp_image_get_mask (gimage));
  1099.       channel_combine_mask (new_channel,
  1100.                 active_channel,
  1101.                 ADD, 
  1102.                 0, 0);  /* off x/y */
  1103.       gimage_mask_load (gimage, new_channel);
  1104.       channel_delete (new_channel);
  1105.       gdisplays_flush ();
  1106.     }
  1107. }
  1108.  
  1109. void
  1110. channels_dialog_sub_channel_from_sel_callback (GtkWidget *widget,
  1111.                            gpointer   data)
  1112. {
  1113.   GimpImage *gimage;
  1114.   Channel *active_channel;
  1115.   Channel *new_channel;
  1116.  
  1117.   if (!channelsD || !(gimage = channelsD->gimage))
  1118.     return;
  1119.  
  1120.   if ((active_channel = gimp_image_get_active_channel (gimage)))
  1121.     {
  1122.        new_channel = channel_copy (gimp_image_get_mask (gimage));
  1123.        channel_combine_mask (new_channel,
  1124.                              active_channel,
  1125.                  SUB, 
  1126.                  0, 0);  /* off x/y */
  1127.       gimage_mask_load (gimage, new_channel);
  1128.       channel_delete (new_channel);
  1129.       gdisplays_flush ();
  1130.     }
  1131. }
  1132.  
  1133. void
  1134. channels_dialog_intersect_channel_with_sel_callback (GtkWidget *widget,
  1135.                              gpointer   data)
  1136. {
  1137.   GimpImage *gimage;
  1138.   Channel *active_channel;
  1139.   Channel *new_channel;
  1140.  
  1141.   if (!channelsD || !(gimage = channelsD->gimage))
  1142.     return;
  1143.  
  1144.   if ((active_channel = gimp_image_get_active_channel (gimage)))
  1145.     {
  1146.       new_channel = channel_copy (gimp_image_get_mask (gimage));
  1147.       channel_combine_mask (new_channel,
  1148.                 active_channel,
  1149.                 INTERSECT, 
  1150.                 0, 0);  /* off x/y */
  1151.       gimage_mask_load (gimage, new_channel);
  1152.       channel_delete (new_channel);
  1153.       gdisplays_flush ();
  1154.     }
  1155. }
  1156.  
  1157. void
  1158. channels_dialog_edit_channel_attributes_callback (GtkWidget *widget,
  1159.                           gpointer   data)
  1160. {
  1161.   if (channelsD && channelsD->active_channel)
  1162.     {
  1163.       ChannelWidget *channel_widget;
  1164.  
  1165.       channel_widget = channel_widget_get_ID (channelsD->active_channel);
  1166.  
  1167.       channels_dialog_edit_channel_query (channel_widget);
  1168.     }
  1169. }
  1170.  
  1171. /*******************************/
  1172. /*  ops buttons dnd callbacks  */
  1173. /*******************************/
  1174.  
  1175. static gboolean
  1176. channels_dialog_drag_new_channel_callback (GtkWidget      *widget,
  1177.                        GdkDragContext *context,
  1178.                        gint            x,
  1179.                        gint            y,
  1180.                        guint           time)
  1181. {
  1182.   GtkWidget *src_widget;
  1183.   gboolean return_val = FALSE;
  1184.  
  1185.   if ((src_widget = gtk_drag_get_source_widget (context)))
  1186.     {
  1187.       ChannelWidget *src;
  1188.  
  1189.       src
  1190.         = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1191.  
  1192.       if (src &&
  1193.           src->channel == channelsD->active_channel)
  1194.         {
  1195.           Channel   *channel;
  1196.           GimpImage *gimage;
  1197.           gint  width, height;
  1198.           gint  off_x, off_y;
  1199.  
  1200.           gimage = channelsD->gimage;
  1201.  
  1202.           width  = gimp_drawable_width  (GIMP_DRAWABLE (src->channel));
  1203.           height = gimp_drawable_height (GIMP_DRAWABLE (src->channel));
  1204.           gimp_drawable_offsets (GIMP_DRAWABLE (src->channel), &off_x, &off_y);
  1205.  
  1206.           /*  Start a group undo  */
  1207.           undo_push_group_start (gimage, EDIT_PASTE_UNDO);
  1208.  
  1209.           channel = channel_new (gimage, width, height,
  1210.                  _("Empty Channel Copy"),
  1211.                  src->channel->opacity,
  1212.                  src->channel->col);
  1213.           if (channel)
  1214.             {
  1215.               drawable_fill (GIMP_DRAWABLE (channel), TRANSPARENT_FILL);
  1216.               channel_translate (channel, off_x, off_y);
  1217.               gimp_image_add_channel (gimage, channel, -1);
  1218.  
  1219.               /*  End the group undo  */
  1220.               undo_push_group_end (gimage);
  1221.  
  1222.               gdisplays_flush ();
  1223.             } 
  1224.           else
  1225.             {
  1226.               g_message ("channels_dialog_drop_new_channel_callback():\n"
  1227.              "could not allocate new channel");
  1228.             }
  1229.  
  1230.           return_val = TRUE;
  1231.         }
  1232.     }
  1233.  
  1234.   gtk_drag_finish (context, return_val, FALSE, time);
  1235.  
  1236.   return return_val;
  1237. }
  1238.  
  1239. static gboolean
  1240. channels_dialog_drag_duplicate_channel_callback (GtkWidget      *widget,
  1241.                          GdkDragContext *context,
  1242.                          gint            x,
  1243.                          gint            y,
  1244.                          guint           time)
  1245. {
  1246.   GtkWidget *src_widget;
  1247.   gboolean return_val = FALSE;
  1248.  
  1249.   if ((src_widget = gtk_drag_get_source_widget (context)))
  1250.     {
  1251.       ChannelWidget *src;
  1252.  
  1253.       src
  1254.         = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1255.  
  1256.       if (src &&
  1257.           src->channel == channelsD->active_channel)
  1258.         {
  1259.           channels_dialog_duplicate_channel_callback (widget, NULL);
  1260.  
  1261.           return_val = TRUE;
  1262.         }
  1263.     }
  1264.  
  1265.   gtk_drag_finish (context, return_val, FALSE, time);
  1266.  
  1267.   return return_val;
  1268. }
  1269.  
  1270. static gboolean
  1271. channels_dialog_drag_channel_to_sel_callback (GtkWidget      *widget,
  1272.                           GdkDragContext *context,
  1273.                           gint            x,
  1274.                           gint            y,
  1275.                           guint           time)
  1276. {
  1277.   GtkWidget *src_widget;
  1278.   gboolean return_val = FALSE;
  1279.  
  1280.   if ((src_widget = gtk_drag_get_source_widget (context)))
  1281.     {
  1282.       ChannelWidget *src;
  1283.  
  1284.       src
  1285.         = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1286.  
  1287.       if (src &&
  1288.           src->channel == channelsD->active_channel)
  1289.         {
  1290.           channels_dialog_channel_to_sel_callback (widget, NULL);
  1291.  
  1292.           return_val = TRUE;
  1293.         }
  1294.     }
  1295.  
  1296.   gtk_drag_finish (context, return_val, FALSE, time);
  1297.  
  1298.   return return_val;
  1299. }
  1300.  
  1301. static gboolean
  1302. channels_dialog_drag_delete_channel_callback (GtkWidget      *widget,
  1303.                           GdkDragContext *context,
  1304.                           gint            x,
  1305.                           gint            y,
  1306.                           guint           time)
  1307. {
  1308.   GtkWidget *src_widget;
  1309.   gboolean return_val = FALSE;
  1310.  
  1311.   if ((src_widget = gtk_drag_get_source_widget (context)))
  1312.     {
  1313.       ChannelWidget *src;
  1314.  
  1315.       src
  1316.         = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1317.  
  1318.       if (src &&
  1319.           src->channel == channelsD->active_channel)
  1320.         {
  1321.           channels_dialog_delete_channel_callback (widget, NULL);
  1322.  
  1323.           return_val = TRUE;
  1324.         }
  1325.     }
  1326.  
  1327.   gtk_drag_finish (context, return_val, FALSE, time);
  1328.  
  1329.   return return_val;
  1330. }
  1331.  
  1332. /******************************/
  1333. /*  channel widget functions  */
  1334. /******************************/
  1335.  
  1336. static ChannelWidget *
  1337. channel_widget_get_ID (Channel *channel)
  1338. {
  1339.   ChannelWidget *lw;
  1340.   GSList *list;
  1341.  
  1342.   if (!channelsD)
  1343.     return NULL;
  1344.  
  1345.   for (list = channelsD->channel_widgets; list; list = g_slist_next (list))
  1346.     {
  1347.       lw = (ChannelWidget *) list->data;
  1348.  
  1349.       if (lw->channel == channel)
  1350.     return lw;
  1351.     }
  1352.  
  1353.   return NULL;
  1354. }
  1355.  
  1356. static ChannelWidget *
  1357. channel_widget_create (GimpImage   *gimage,
  1358.                Channel     *channel,
  1359.                ChannelType  type)
  1360. {
  1361.   ChannelWidget *channel_widget;
  1362.   GtkWidget *list_item;
  1363.   GtkWidget *hbox;
  1364.   GtkWidget *vbox;
  1365.   GtkWidget *alignment;
  1366.  
  1367.   list_item = gtk_list_item_new ();
  1368.  
  1369.   /*  Create the channel widget and add it to the list  */
  1370.   channel_widget = g_new (ChannelWidget, 1);
  1371.   channel_widget->gimage          = gimage;
  1372.   channel_widget->channel         = channel;
  1373.   channel_widget->channel_preview = NULL;
  1374.   channel_widget->channel_pixmap  = NULL;
  1375.   channel_widget->type            = type;
  1376.   channel_widget->ID              = ((type == AUXILLARY_CHANNEL) ?
  1377.                      GIMP_DRAWABLE (channel)->ID :
  1378.                      (COMPONENT_BASE_ID + type));
  1379.   channel_widget->list_item       = list_item;
  1380.   channel_widget->width           = -1;
  1381.   channel_widget->height          = -1;
  1382.   channel_widget->visited         = TRUE;
  1383.   channel_widget->drop_type       = GIMP_DROP_NONE;
  1384.  
  1385.   /*  Need to let the list item know about the channel_widget  */
  1386.   gtk_object_set_user_data (GTK_OBJECT (list_item), channel_widget);
  1387.  
  1388.   /*  Set up the list item observer  */
  1389.   gtk_signal_connect (GTK_OBJECT (list_item), "select",
  1390.               GTK_SIGNAL_FUNC (channel_widget_select_update),
  1391.               channel_widget);
  1392.   gtk_signal_connect (GTK_OBJECT (list_item), "deselect",
  1393.               GTK_SIGNAL_FUNC (channel_widget_select_update),
  1394.               channel_widget);
  1395.  
  1396.   vbox = gtk_vbox_new (FALSE, 1);
  1397.   gtk_container_add (GTK_CONTAINER (list_item), vbox);
  1398.  
  1399.   hbox = gtk_hbox_new (FALSE, 1);
  1400.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1);
  1401.  
  1402.   /*  Create the visibility toggle button  */
  1403.   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  1404.   gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, TRUE, 2);
  1405.   channel_widget->eye_widget = gtk_drawing_area_new ();
  1406.   gtk_drawing_area_size (GTK_DRAWING_AREA (channel_widget->eye_widget),
  1407.              eye_width, eye_height);
  1408.   gtk_widget_set_events (channel_widget->eye_widget, BUTTON_EVENT_MASK);
  1409.   gtk_signal_connect (GTK_OBJECT (channel_widget->eye_widget), "event",
  1410.               GTK_SIGNAL_FUNC (channel_widget_button_events),
  1411.               channel_widget);
  1412.   gtk_object_set_user_data (GTK_OBJECT (channel_widget->eye_widget),
  1413.                 channel_widget);
  1414.   gtk_container_add (GTK_CONTAINER (alignment), channel_widget->eye_widget);
  1415.   gtk_widget_show (channel_widget->eye_widget);
  1416.   gtk_widget_show (alignment);
  1417.  
  1418.   /*  The channel preview  */
  1419.   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  1420.   gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, FALSE, 2);
  1421.   gtk_widget_show (alignment);
  1422.  
  1423.   channel_widget->channel_preview = gtk_drawing_area_new ();
  1424.   gtk_drawing_area_size (GTK_DRAWING_AREA (channel_widget->channel_preview),
  1425.              channelsD->image_width, channelsD->image_height);
  1426.   gtk_widget_set_events (channel_widget->channel_preview, PREVIEW_EVENT_MASK);
  1427.   gtk_signal_connect (GTK_OBJECT (channel_widget->channel_preview), "event",
  1428.               GTK_SIGNAL_FUNC (channel_widget_preview_events),
  1429.               channel_widget);
  1430.   gtk_object_set_user_data (GTK_OBJECT (channel_widget->channel_preview),
  1431.                 channel_widget);
  1432.   gtk_container_add (GTK_CONTAINER (alignment), channel_widget->channel_preview);
  1433.   gtk_widget_show (channel_widget->channel_preview);
  1434.  
  1435.   /*  The channel name label */
  1436.   switch (channel_widget->type)
  1437.     {
  1438.     case RED_CHANNEL:
  1439.       channel_widget->label = gtk_label_new (_("Red"));
  1440.       break;
  1441.  
  1442.     case GREEN_CHANNEL:
  1443.       channel_widget->label = gtk_label_new (_("Green"));
  1444.       break;
  1445.  
  1446.     case BLUE_CHANNEL:
  1447.       channel_widget->label = gtk_label_new (_("Blue"));
  1448.       break;
  1449.  
  1450.     case GRAY_CHANNEL:
  1451.       channel_widget->label = gtk_label_new (_("Gray"));
  1452.       break;
  1453.  
  1454.     case INDEXED_CHANNEL:
  1455.       channel_widget->label = gtk_label_new (_("Indexed"));
  1456.       break;
  1457.  
  1458.     case AUXILLARY_CHANNEL:
  1459.       channel_widget->label = gtk_label_new (channel_get_name (channel));
  1460.       break;
  1461.     }
  1462.  
  1463.   gtk_box_pack_start (GTK_BOX (hbox), channel_widget->label, FALSE, FALSE, 2);
  1464.   gtk_widget_show (channel_widget->label);
  1465.  
  1466.   if (channel_widget->type == AUXILLARY_CHANNEL)
  1467.     {
  1468.       /*  dnd destination  */
  1469.       gtk_drag_dest_set (list_item,
  1470.              GTK_DEST_DEFAULT_ALL,
  1471.              channel_color_target_table, n_channel_color_targets,
  1472.              GDK_ACTION_MOVE | GDK_ACTION_COPY);
  1473.       gimp_dnd_color_dest_set (list_item,
  1474.                    channel_widget_drop_color,
  1475.                    (gpointer) channel_widget);
  1476.  
  1477.       gtk_signal_connect (GTK_OBJECT (list_item), "drag_leave",
  1478.               GTK_SIGNAL_FUNC (channel_widget_drag_leave_callback),
  1479.               NULL);
  1480.       gtk_signal_connect (GTK_OBJECT (list_item), "drag_motion",
  1481.               GTK_SIGNAL_FUNC (channel_widget_drag_motion_callback),
  1482.               NULL);
  1483.       gtk_signal_connect (GTK_OBJECT (list_item), "drag_drop",
  1484.               GTK_SIGNAL_FUNC (channel_widget_drag_drop_callback),
  1485.               NULL);
  1486.  
  1487.       /*  re-paint the drop indicator after drawing the widget  */
  1488.       gtk_signal_connect_after (GTK_OBJECT (list_item), "draw",
  1489.                 GTK_SIGNAL_FUNC (channel_widget_drag_indicator_callback),
  1490.                 channel_widget);
  1491.  
  1492.       /*  dnd source  */
  1493.       gtk_drag_source_set (list_item,
  1494.                GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  1495.                channel_target_table, n_channel_targets, 
  1496.                GDK_ACTION_MOVE | GDK_ACTION_COPY);
  1497.  
  1498.       gtk_signal_connect (GTK_OBJECT (list_item), "drag_begin",
  1499.               GTK_SIGNAL_FUNC (channel_widget_drag_begin_callback),
  1500.               NULL);
  1501.  
  1502.       gtk_object_set_data (GTK_OBJECT (list_item), "gimp_channel",
  1503.                (gpointer) channel);
  1504.     }
  1505.   else
  1506.     {
  1507.       /*  dnd source  */
  1508.       gtk_drag_source_set (list_item,
  1509.                GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  1510.                component_target_table, n_component_targets, 
  1511.                GDK_ACTION_MOVE | GDK_ACTION_COPY);
  1512.  
  1513.       gtk_object_set_data (GTK_OBJECT (list_item), "gimp_component",
  1514.                (gpointer) gimage);
  1515.       gtk_object_set_data (GTK_OBJECT (list_item), "gimp_component_type",
  1516.                (gpointer) channel_widget->type);
  1517.     }
  1518.  
  1519.   gtk_widget_show (hbox);
  1520.   gtk_widget_show (vbox);
  1521.   gtk_widget_show (list_item);
  1522.  
  1523.   gtk_widget_ref (channel_widget->list_item);
  1524.  
  1525.   return channel_widget;
  1526. }
  1527.  
  1528. static gboolean
  1529. channel_widget_drag_motion_callback (GtkWidget      *widget,
  1530.                      GdkDragContext *context,
  1531.                      gint            x,
  1532.                      gint            y,
  1533.                      guint           time)
  1534. {
  1535.   ChannelWidget *dest;
  1536.   gint           dest_index;
  1537.   GtkWidget     *src_widget;
  1538.   ChannelWidget *src = NULL;
  1539.   gint           src_index;
  1540.   gint           difference;
  1541.  
  1542.   GimpDropType  drop_type   = GIMP_DROP_NONE;
  1543.   GdkDragAction drag_action = GDK_ACTION_DEFAULT;
  1544.   gboolean      return_val  = FALSE;
  1545.  
  1546.   dest = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1547.  
  1548.   if (dest)
  1549.     {
  1550.       src_widget = gtk_drag_get_source_widget (context);
  1551.  
  1552.       if (src_widget)
  1553.     {
  1554.       src = (ChannelWidget *)
  1555.         gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1556.  
  1557.       if (src &&
  1558.           src->channel == channelsD->active_channel)
  1559.         {
  1560.           src_index  = gimp_image_get_channel_index (channelsD->gimage,
  1561.                              src->channel);
  1562.           dest_index = gimp_image_get_channel_index (channelsD->gimage,
  1563.                              dest->channel);
  1564.  
  1565.           difference = dest_index - src_index;
  1566.  
  1567.           drop_type = ((y < widget->allocation.height / 2) ?
  1568.                GIMP_DROP_ABOVE : GIMP_DROP_BELOW);
  1569.  
  1570.           if (difference < 0 &&
  1571.           drop_type == GIMP_DROP_BELOW)
  1572.         {
  1573.           dest_index++;
  1574.         }
  1575.           else if (difference > 0 &&
  1576.                drop_type == GIMP_DROP_ABOVE)
  1577.         {
  1578.           dest_index--;
  1579.         }
  1580.  
  1581.           if (src_index != dest_index)
  1582.         {
  1583.           drag_action = GDK_ACTION_MOVE;
  1584.           return_val = TRUE;
  1585.         }
  1586.           else
  1587.         {
  1588.           drop_type = GIMP_DROP_NONE;
  1589.         }
  1590.         }
  1591.     }
  1592.  
  1593.       if (!src)
  1594.     {
  1595.       drag_action = GDK_ACTION_COPY;
  1596.       return_val = TRUE;
  1597.       drop_type = GIMP_DROP_NONE;
  1598.     }
  1599.     }
  1600.  
  1601.   gdk_drag_status (context, drag_action, time);
  1602.  
  1603.   if (dest && drop_type != dest->drop_type)
  1604.     {
  1605.       channel_widget_draw_drop_indicator (dest, dest->drop_type);
  1606.       channel_widget_draw_drop_indicator (dest, drop_type);
  1607.       dest->drop_type = drop_type;
  1608.     }
  1609.  
  1610.   return return_val;
  1611. }
  1612.  
  1613. static void
  1614. channel_widget_drag_begin_callback (GtkWidget      *widget,
  1615.                     GdkDragContext *context)
  1616. {
  1617.   ChannelWidget *channel_widget;
  1618.  
  1619.   channel_widget =
  1620.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1621.  
  1622.   gimp_dnd_set_drawable_preview_icon (widget, context,
  1623.                       GIMP_DRAWABLE (channel_widget->channel));
  1624. }
  1625.  
  1626. typedef struct
  1627. {
  1628.   GimpImage *gimage;
  1629.   Channel   *channel;
  1630.   gint       dest_index;
  1631. } ChannelDrop;
  1632.  
  1633. static gint
  1634. channel_widget_idle_drop_channel (gpointer data)
  1635. {
  1636.   ChannelDrop *cd;
  1637.  
  1638.   cd = (ChannelDrop *) data;
  1639.  
  1640.   gimp_image_position_channel (cd->gimage, cd->channel, cd->dest_index);
  1641.   gdisplays_flush ();
  1642.  
  1643.   g_free (cd);
  1644.  
  1645.   return FALSE;
  1646. }
  1647.  
  1648. static gboolean
  1649. channel_widget_drag_drop_callback (GtkWidget      *widget,
  1650.                    GdkDragContext *context,
  1651.                    gint            x,
  1652.                    gint            y,
  1653.                    guint           time)
  1654. {
  1655.   ChannelWidget *dest;
  1656.   gint           dest_index;
  1657.   GtkWidget     *src_widget;
  1658.   ChannelWidget *src;
  1659.   gint           src_index;
  1660.   gint           difference;
  1661.  
  1662.   GimpDropType   drop_type  = GIMP_DROP_NONE;
  1663.   gboolean       return_val = FALSE;
  1664.  
  1665.   dest = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1666.  
  1667.   if (dest &&
  1668.       (src_widget = gtk_drag_get_source_widget (context)))
  1669.     {
  1670.       src = (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (src_widget));
  1671.  
  1672.       if (src &&
  1673.           src->channel == channelsD->active_channel)
  1674.         {
  1675.           src_index  = gimp_image_get_channel_index (channelsD->gimage,
  1676.                              src->channel);
  1677.           dest_index = gimp_image_get_channel_index (channelsD->gimage,
  1678.                              dest->channel);
  1679.  
  1680.           difference = dest_index - src_index;
  1681.  
  1682.           drop_type = ((y < widget->allocation.height / 2) ?
  1683.                        GIMP_DROP_ABOVE : GIMP_DROP_BELOW);
  1684.  
  1685.           if (difference < 0 &&
  1686.               drop_type == GIMP_DROP_BELOW)
  1687.             {
  1688.               dest_index++;
  1689.             }
  1690.           else if (difference > 0 &&
  1691.                    drop_type == GIMP_DROP_ABOVE)
  1692.             {
  1693.               dest_index--;
  1694.             }
  1695.  
  1696.           if (src_index != dest_index)
  1697.             {
  1698.               ChannelDrop *cd;
  1699.  
  1700.               cd = g_new (ChannelDrop, 1);
  1701.               cd->gimage     = channelsD->gimage;
  1702.               cd->channel    = src->channel;
  1703.               cd->dest_index = dest_index;
  1704.  
  1705.               /*  let dnd finish it's work before changing the widget tree  */
  1706.               gtk_idle_add ((GtkFunction) channel_widget_idle_drop_channel, cd);
  1707.               return_val = TRUE;
  1708.             }
  1709.         }
  1710.     }
  1711.  
  1712.   if (dest)
  1713.     {
  1714.       if (!return_val)
  1715.     channel_widget_draw_drop_indicator (dest, dest->drop_type);
  1716.  
  1717.       dest->drop_type = GIMP_DROP_NONE;
  1718.     }
  1719.  
  1720.   gtk_drag_finish (context, return_val, FALSE, time);
  1721.  
  1722.   return return_val;
  1723. }
  1724.  
  1725. static void
  1726. channel_widget_drag_leave_callback (GtkWidget      *widget,
  1727.                     GdkDragContext *context,
  1728.                     guint           time)
  1729. {
  1730.   ChannelWidget *channel_widget;
  1731.  
  1732.   channel_widget =
  1733.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1734.  
  1735.   channel_widget->drop_type = GIMP_DROP_NONE;
  1736. }
  1737.  
  1738. static void
  1739. channel_widget_drag_indicator_callback (GtkWidget *widget,
  1740.                     gpointer   data)
  1741. {
  1742.   ChannelWidget *channel_widget;
  1743.  
  1744.   channel_widget =
  1745.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1746.  
  1747.   channel_widget_draw_drop_indicator (channel_widget, channel_widget->drop_type);
  1748. }
  1749.  
  1750. static void
  1751. channel_widget_drop_color (GtkWidget *widget,
  1752.                guchar     r,
  1753.                guchar     g,
  1754.                guchar     b,
  1755.                gpointer   data)
  1756. {
  1757.   ChannelWidget *channel_widget = (ChannelWidget *) data;
  1758.   Channel *channel = channel_widget->channel;
  1759.  
  1760.   if (r != channel->col[0] ||
  1761.       g != channel->col[1] ||
  1762.       b != channel->col[2])
  1763.     {
  1764.       channel->col[0] = r;
  1765.       channel->col[1] = g;
  1766.       channel->col[2] = b;
  1767.  
  1768.       drawable_update (GIMP_DRAWABLE (channel), 0, 0,
  1769.                GIMP_DRAWABLE (channel)->width,
  1770.                GIMP_DRAWABLE (channel)->height);
  1771.       gdisplays_flush ();
  1772.     }
  1773. }
  1774.  
  1775. static void
  1776. channel_widget_draw_drop_indicator (ChannelWidget *channel_widget,
  1777.                     GimpDropType   drop_type)
  1778. {
  1779.   static GdkGC *gc = NULL;
  1780.   gint y = 0;
  1781.  
  1782.   if (!gc)
  1783.     {
  1784.       GdkColor fg, bg;
  1785.  
  1786.       gc = gdk_gc_new (channel_widget->list_item->window);
  1787.  
  1788.       fg.pixel = 0xFFFFFFFF;
  1789.       bg.pixel = 0x00000000;
  1790.  
  1791.       gdk_gc_set_function (gc, GDK_INVERT);
  1792.       gdk_gc_set_foreground (gc, &fg);
  1793.       gdk_gc_set_background (gc, &bg);
  1794.       gdk_gc_set_line_attributes (gc, 5, GDK_LINE_SOLID,
  1795.                                   GDK_CAP_BUTT, GDK_JOIN_MITER);
  1796.     }
  1797.  
  1798.   if (drop_type != GIMP_DROP_NONE)
  1799.     {
  1800.       y = ((drop_type == GIMP_DROP_ABOVE) ?
  1801.            3 : channel_widget->list_item->allocation.height - 4);
  1802.  
  1803.       gdk_draw_line (channel_widget->list_item->window, gc,
  1804.                      2, y, channel_widget->list_item->allocation.width - 3, y);
  1805.     }
  1806. }
  1807.  
  1808. static void
  1809. channel_widget_delete (ChannelWidget *channel_widget)
  1810. {
  1811.   if (channel_widget->channel_pixmap)
  1812.     gdk_pixmap_unref (channel_widget->channel_pixmap);
  1813.  
  1814.   /*  Remove the channel widget from the list  */
  1815.   channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets,
  1816.                            channel_widget);
  1817.  
  1818.   /*  Release the widget  */
  1819.   gtk_widget_unref (channel_widget->list_item);
  1820.   g_free (channel_widget);
  1821. }
  1822.  
  1823. static void
  1824. channel_widget_select_update (GtkWidget *widget,
  1825.                   gpointer   data)
  1826. {
  1827.   ChannelWidget *channel_widget;
  1828.  
  1829.   if ((channel_widget = (ChannelWidget *) data) == NULL)
  1830.     return;
  1831.  
  1832.   if (suspend_gimage_notify == 0)
  1833.     {
  1834.       if (channel_widget->type == AUXILLARY_CHANNEL)
  1835.     {
  1836.       if (widget->state == GTK_STATE_SELECTED)
  1837.         /*  set the gimage's active channel to be this channel  */
  1838.         gimp_image_set_active_channel (channel_widget->gimage,
  1839.                        channel_widget->channel);
  1840.       else
  1841.         /*  unset the gimage's active channel  */
  1842.         gimp_image_unset_active_channel (channel_widget->gimage);
  1843.  
  1844.       gdisplays_flush ();
  1845.     }
  1846.       else if (channel_widget->type != AUXILLARY_CHANNEL)
  1847.     {
  1848.       if (widget->state == GTK_STATE_SELECTED)
  1849.         gimp_image_set_component_active (channel_widget->gimage,
  1850.                          channel_widget->type, TRUE);
  1851.       else
  1852.         gimp_image_set_component_active (channel_widget->gimage,
  1853.                          channel_widget->type, FALSE);
  1854.     }
  1855.     }
  1856. }
  1857.  
  1858. static gint
  1859. channel_widget_button_events (GtkWidget *widget,
  1860.                   GdkEvent  *event,
  1861.                   gpointer   data)
  1862. {
  1863.   ChannelWidget  *channel_widget;
  1864.   GtkWidget      *event_widget;
  1865.   GdkEventButton *bevent;
  1866.   gint return_val;
  1867.   gint visible;
  1868.   gint width, height;
  1869.  
  1870.   static gboolean button_down = FALSE;
  1871.   static GtkWidget *click_widget = NULL;
  1872.   static gint old_state;
  1873.   static gint exclusive;
  1874.  
  1875.   channel_widget =
  1876.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  1877.   return_val = FALSE;
  1878.  
  1879.   switch (channel_widget->type)
  1880.     {
  1881.     case AUXILLARY_CHANNEL:
  1882.       visible = GIMP_DRAWABLE (channel_widget->channel)->visible;
  1883.       width   = GIMP_DRAWABLE (channel_widget->channel)->width;
  1884.       height  = GIMP_DRAWABLE (channel_widget->channel)->height;
  1885.       break;
  1886.     default:
  1887.       visible = gimp_image_get_component_visible (channel_widget->gimage,
  1888.                           channel_widget->type);
  1889.       width   = channel_widget->gimage->width;
  1890.       height  = channel_widget->gimage->height;
  1891.       break;
  1892.     }
  1893.  
  1894.  
  1895.   switch (event->type)
  1896.     {
  1897.     case GDK_EXPOSE:
  1898.       if (widget == channel_widget->eye_widget)
  1899.     channel_widget_eye_redraw (channel_widget);
  1900.       break;
  1901.  
  1902.     case GDK_BUTTON_PRESS:
  1903.       return_val = TRUE;
  1904.       bevent = (GdkEventButton *) event;
  1905.  
  1906.       if (bevent->button == 3)
  1907.     {
  1908.       gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
  1909.               NULL, NULL, NULL, NULL,
  1910.               3, bevent->time);
  1911.       return TRUE;
  1912.     }
  1913.  
  1914.       button_down = TRUE;
  1915.       click_widget = widget;
  1916.       gtk_grab_add (click_widget);
  1917.  
  1918.       if (widget == channel_widget->eye_widget)
  1919.     {
  1920.       old_state = visible;
  1921.  
  1922.       /*  If this was a shift-click, make all/none visible  */
  1923.       if (event->button.state & GDK_SHIFT_MASK)
  1924.         {
  1925.           exclusive = TRUE;
  1926.           channel_widget_exclusive_visible (channel_widget);
  1927.         }
  1928.       else
  1929.         {
  1930.           exclusive = FALSE;
  1931.           if (channel_widget->type == AUXILLARY_CHANNEL)
  1932.         GIMP_DRAWABLE (channel_widget->channel)->visible = !visible;
  1933.           else
  1934.         gimp_image_set_component_visible (channel_widget->gimage,
  1935.                           channel_widget->type,
  1936.                           !visible);
  1937.           channel_widget_eye_redraw (channel_widget);
  1938.         }
  1939.     }
  1940.       break;
  1941.  
  1942.     case GDK_BUTTON_RELEASE:
  1943.       return_val = TRUE;
  1944.  
  1945.       button_down = FALSE;
  1946.       gtk_grab_remove (click_widget);
  1947.  
  1948.       if (widget == channel_widget->eye_widget)
  1949.     {
  1950.       if (exclusive)
  1951.         {
  1952.           gdisplays_update_area (channel_widget->gimage, 0, 0, width, height);
  1953.           gdisplays_flush ();
  1954.         }
  1955.       else if (old_state != visible)
  1956.         {
  1957.           gdisplays_update_area (channel_widget->gimage, 0, 0, width, height);
  1958.           gdisplays_flush ();
  1959.         }
  1960.     }
  1961.       break;
  1962.  
  1963.     case GDK_LEAVE_NOTIFY:
  1964.       event_widget = gtk_get_event_widget (event);
  1965.  
  1966.       if (button_down && (event_widget == click_widget))
  1967.     {
  1968.       /* the user moved the cursor out of the widget before
  1969.              releasing the button -> cancel the button_press */ 
  1970.       button_down = FALSE;
  1971.       
  1972.       if (widget == channel_widget->eye_widget)
  1973.         {
  1974.           if (exclusive)
  1975.         {
  1976.           channel_widget_exclusive_visible (channel_widget);
  1977.         }
  1978.           else
  1979.         {
  1980.           if (channel_widget->type == AUXILLARY_CHANNEL)
  1981.             GIMP_DRAWABLE (channel_widget->channel)->visible = !visible;
  1982.           else
  1983.             gimp_image_set_component_visible (channel_widget->gimage,
  1984.                               channel_widget->type,
  1985.                               !visible);
  1986.           channel_widget_eye_redraw (channel_widget);
  1987.         }
  1988.         }
  1989.     }
  1990.       break;
  1991.  
  1992.     default:
  1993.       break;
  1994.     }
  1995.  
  1996.   return return_val;
  1997. }
  1998.  
  1999. static gint
  2000. channel_widget_preview_events (GtkWidget *widget,
  2001.                    GdkEvent  *event,
  2002.                    gpointer   data)
  2003. {
  2004.   ChannelWidget  *channel_widget;
  2005.   GdkEventExpose *eevent;
  2006.   GdkEventButton *bevent;
  2007.   gboolean valid;
  2008.  
  2009.   valid = FALSE;
  2010.  
  2011.   channel_widget =
  2012.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  2013.  
  2014.   switch (event->type)
  2015.     {
  2016.     case GDK_BUTTON_PRESS:
  2017.       bevent = (GdkEventButton *) event;
  2018.  
  2019.       if (bevent->button == 3)
  2020.     {
  2021.       gtk_menu_popup (GTK_MENU (channelsD->ops_menu),
  2022.               NULL, NULL, NULL, NULL,
  2023.               3, bevent->time);
  2024.       return TRUE;
  2025.     }
  2026.       break;
  2027.  
  2028.     case GDK_EXPOSE:
  2029.       if (!preview_size)
  2030.     channel_widget_no_preview_redraw (channel_widget);
  2031.       else
  2032.     {
  2033.       switch (channel_widget->type)
  2034.         {
  2035.         case AUXILLARY_CHANNEL:
  2036.           valid = GIMP_DRAWABLE (channel_widget->channel)->preview_valid;
  2037.           break;
  2038.         default:
  2039.           valid = gimp_image_preview_valid (channel_widget->gimage,
  2040.                         channel_widget->type);
  2041.           break;
  2042.         }
  2043.  
  2044.       if (!valid || !channel_widget->channel_pixmap)
  2045.         {
  2046.           channel_widget_preview_redraw (channel_widget);
  2047.  
  2048.           gdk_draw_pixmap (widget->window,
  2049.                    widget->style->black_gc,
  2050.                    channel_widget->channel_pixmap,
  2051.                    0, 0, 0, 0,
  2052.                    channelsD->image_width,
  2053.                    channelsD->image_height);
  2054.         }
  2055.       else
  2056.         {
  2057.           eevent = (GdkEventExpose *) event;
  2058.  
  2059.           gdk_draw_pixmap (widget->window,
  2060.                    widget->style->black_gc,
  2061.                    channel_widget->channel_pixmap,
  2062.                    eevent->area.x, eevent->area.y,
  2063.                    eevent->area.x, eevent->area.y,
  2064.                    eevent->area.width, eevent->area.height);
  2065.         }
  2066.     }
  2067.       break;
  2068.  
  2069.     default:
  2070.       break;
  2071.     }
  2072.  
  2073.   return FALSE;
  2074. }
  2075.  
  2076. static void
  2077. channel_widget_preview_redraw (ChannelWidget *channel_widget)
  2078. {
  2079.   TempBuf *preview_buf;
  2080.   gint width, height;
  2081.   gint channel;
  2082.  
  2083.   /*  allocate the channel widget pixmap  */
  2084.   if (! channel_widget->channel_pixmap)
  2085.     channel_widget->channel_pixmap =
  2086.       gdk_pixmap_new (channel_widget->channel_preview->window,
  2087.               channelsD->image_width,
  2088.               channelsD->image_height,
  2089.               -1);
  2090.  
  2091.   /*  determine width and height  */
  2092.   switch (channel_widget->type)
  2093.     {
  2094.     case AUXILLARY_CHANNEL:
  2095.       width  = GIMP_DRAWABLE (channel_widget->channel)->width;
  2096.       height = GIMP_DRAWABLE (channel_widget->channel)->height;
  2097.       channel_widget->width  = RINT (channelsD->ratio * width);
  2098.       channel_widget->height = RINT (channelsD->ratio * height);
  2099.  
  2100.       if (channelsD->ratio > 1.0) /*  Preview is scaling up!  */
  2101.     {
  2102.       preview_buf = channel_preview (channel_widget->channel,
  2103.                      channelsD->gimage_width,
  2104.                      channelsD->gimage_height);
  2105.       preview_buf = gimp_preview_scale (preview_buf,
  2106.                         channel_widget->width,
  2107.                         channel_widget->height);
  2108.     }
  2109.       else
  2110.     {
  2111.       preview_buf = channel_preview (channel_widget->channel,
  2112.                      channel_widget->width,
  2113.                      channel_widget->height);
  2114.     }
  2115.       break;
  2116.  
  2117.     default:
  2118.       width  = channel_widget->gimage->width;
  2119.       height = channel_widget->gimage->height;
  2120.       channel_widget->width  = RINT (channelsD->ratio * width);
  2121.       channel_widget->height = RINT (channelsD->ratio * height);
  2122.  
  2123.       if (channelsD->ratio > 1.0) /*  Preview is scaling up!  */
  2124.     {
  2125.       preview_buf = gimp_image_composite_preview (channel_widget->gimage,
  2126.                               channel_widget->type,
  2127.                               width,
  2128.                               height);
  2129.       preview_buf = gimp_preview_scale (preview_buf,
  2130.                         channel_widget->width,
  2131.                         channel_widget->height);
  2132.     }
  2133.       else
  2134.     {
  2135.       preview_buf = gimp_image_composite_preview (channel_widget->gimage,
  2136.                               channel_widget->type,
  2137.                               channel_widget->width,
  2138.                               channel_widget->height);
  2139.     }
  2140.       break;
  2141.     }
  2142.  
  2143.   switch (channel_widget->type)
  2144.     {
  2145.     case RED_CHANNEL:       channel = RED_PIX; break;
  2146.     case GREEN_CHANNEL:     channel = GREEN_PIX; break;
  2147.     case BLUE_CHANNEL:      channel = BLUE_PIX; break;
  2148.     case GRAY_CHANNEL:      channel = GRAY_PIX; break;
  2149.     case INDEXED_CHANNEL:   channel = INDEXED_PIX; break;
  2150.     case AUXILLARY_CHANNEL: channel = -1; break;
  2151.     default:                channel = -1; break;
  2152.     }
  2153.  
  2154.   render_preview (preview_buf,
  2155.           channelsD->preview,
  2156.           channelsD->image_width,
  2157.           channelsD->image_height,
  2158.           channel);
  2159.  
  2160.   gtk_preview_put (GTK_PREVIEW (channelsD->preview),
  2161.            channel_widget->channel_pixmap,
  2162.            channel_widget->channel_preview->style->black_gc,
  2163.            0, 0, 0, 0, 
  2164.            channelsD->image_width, channelsD->image_height);
  2165.  
  2166.   /*  make sure the image has been transfered completely to the pixmap before
  2167.    *  we use it again...
  2168.    */
  2169.   gdk_flush ();
  2170.  
  2171.   if (channelsD->ratio > 1.0)
  2172.     temp_buf_free (preview_buf);
  2173. }
  2174.  
  2175. static void
  2176. channel_widget_no_preview_redraw (ChannelWidget *channel_widget)
  2177. {
  2178.   GdkPixmap  *pixmap;
  2179.   GdkPixmap **pixmap_normal;
  2180.   GdkPixmap **pixmap_selected;
  2181.   GdkPixmap **pixmap_insensitive;
  2182.   GdkColor   *color;
  2183.   GtkWidget  *widget;
  2184.   GtkStateType state;
  2185.   gchar *bits;
  2186.   gint   width, height;
  2187.  
  2188.   state = channel_widget->list_item->state;
  2189.  
  2190.   pixmap_normal      = &channel_pixmap[NORMAL];
  2191.   pixmap_selected    = &channel_pixmap[SELECTED];
  2192.   pixmap_insensitive = &channel_pixmap[INSENSITIVE];
  2193.   widget             = channel_widget->channel_preview;
  2194.   bits               = (gchar *) channel_bits;
  2195.   width              = channel_width;
  2196.   height             = channel_height;
  2197.  
  2198.   if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2199.     {
  2200.       if (state == GTK_STATE_SELECTED)
  2201.     color = &widget->style->bg[GTK_STATE_SELECTED];
  2202.       else
  2203.     color = &widget->style->white;
  2204.     }
  2205.   else
  2206.     color = &widget->style->bg[GTK_STATE_INSENSITIVE];
  2207.  
  2208.   gdk_window_set_background (widget->window, color);
  2209.  
  2210.   if (!*pixmap_normal)
  2211.     {
  2212.       *pixmap_normal =
  2213.     gdk_pixmap_create_from_data (widget->window,
  2214.                      bits, width, height, -1,
  2215.                      &widget->style->fg[GTK_STATE_SELECTED],
  2216.                      &widget->style->bg[GTK_STATE_SELECTED]);
  2217.       *pixmap_selected =
  2218.     gdk_pixmap_create_from_data (widget->window,
  2219.                      bits, width, height, -1,
  2220.                      &widget->style->fg[GTK_STATE_NORMAL],
  2221.                      &widget->style->white);
  2222.       *pixmap_insensitive =
  2223.     gdk_pixmap_create_from_data (widget->window,
  2224.                      bits, width, height, -1,
  2225.                      &widget->style->fg[GTK_STATE_INSENSITIVE],
  2226.                      &widget->style->bg[GTK_STATE_INSENSITIVE]);
  2227.     }
  2228.  
  2229.   if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2230.     {
  2231.       if (state == GTK_STATE_SELECTED)
  2232.     pixmap = *pixmap_selected;
  2233.       else
  2234.     pixmap = *pixmap_normal;
  2235.     }
  2236.   else
  2237.     pixmap = *pixmap_insensitive;
  2238.  
  2239.   gdk_draw_pixmap (widget->window,
  2240.            widget->style->black_gc,
  2241.            pixmap, 0, 0, 0, 0, width, height);
  2242. }
  2243.  
  2244. static void
  2245. channel_widget_eye_redraw (ChannelWidget *channel_widget)
  2246. {
  2247.   GdkPixmap *pixmap;
  2248.   GdkColor  *color;
  2249.   GtkStateType state;
  2250.   gboolean visible;
  2251.  
  2252.   state = channel_widget->list_item->state;
  2253.  
  2254.   if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2255.     {
  2256.       if (state == GTK_STATE_SELECTED)
  2257.     color = &channel_widget->eye_widget->style->bg[GTK_STATE_SELECTED];
  2258.       else
  2259.     color = &channel_widget->eye_widget->style->white;
  2260.     }
  2261.   else
  2262.     color = &channel_widget->eye_widget->style->bg[GTK_STATE_INSENSITIVE];
  2263.  
  2264.   gdk_window_set_background (channel_widget->eye_widget->window, color);
  2265.  
  2266.   switch (channel_widget->type)
  2267.     {
  2268.     case AUXILLARY_CHANNEL:
  2269.       visible = GIMP_DRAWABLE (channel_widget->channel)->visible;
  2270.       break;
  2271.     default:
  2272.       visible = gimp_image_get_component_visible (channel_widget->gimage,
  2273.                           channel_widget->type);
  2274.       break;
  2275.     }
  2276.  
  2277.   if (visible)
  2278.     {
  2279.       if (!eye_pixmap[NORMAL])
  2280.     {
  2281.       eye_pixmap[NORMAL] =
  2282.         gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
  2283.                      (gchar*) eye_bits, eye_width, eye_height, -1,
  2284.                      &channel_widget->eye_widget->style->fg[GTK_STATE_NORMAL],
  2285.                      &channel_widget->eye_widget->style->white);
  2286.       eye_pixmap[SELECTED] =
  2287.         gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
  2288.                      (gchar*) eye_bits, eye_width, eye_height, -1,
  2289.                      &channel_widget->eye_widget->style->fg[GTK_STATE_SELECTED],
  2290.                      &channel_widget->eye_widget->style->bg[GTK_STATE_SELECTED]);
  2291.       eye_pixmap[INSENSITIVE] =
  2292.         gdk_pixmap_create_from_data (channel_widget->eye_widget->window,
  2293.                      (gchar*) eye_bits, eye_width, eye_height, -1,
  2294.                      &channel_widget->eye_widget->style->fg[GTK_STATE_INSENSITIVE],
  2295.                      &channel_widget->eye_widget->style->bg[GTK_STATE_INSENSITIVE]);
  2296.     }
  2297.  
  2298.       if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2299.     {
  2300.       if (state == GTK_STATE_SELECTED)
  2301.         pixmap = eye_pixmap[SELECTED];
  2302.       else
  2303.         pixmap = eye_pixmap[NORMAL];
  2304.     }
  2305.       else
  2306.     pixmap = eye_pixmap[INSENSITIVE];
  2307.  
  2308.       gdk_draw_pixmap (channel_widget->eye_widget->window,
  2309.                channel_widget->eye_widget->style->black_gc,
  2310.                pixmap, 0, 0, 0, 0, eye_width, eye_height);
  2311.     }
  2312.   else
  2313.     {
  2314.       gdk_window_clear (channel_widget->eye_widget->window);
  2315.     }
  2316. }
  2317.  
  2318. static void
  2319. channel_widget_exclusive_visible (ChannelWidget *channel_widget)
  2320. {
  2321.   GSList        *list;
  2322.   ChannelWidget *cw;
  2323.   gboolean       visible = FALSE;
  2324.  
  2325.   if (!channelsD)
  2326.     return;
  2327.  
  2328.   /*  First determine if _any_ other channel widgets are set to visible  */
  2329.   for (list = channelsD->channel_widgets; list;  list = g_slist_next (list))
  2330.     {
  2331.       cw = (ChannelWidget *) list->data;
  2332.  
  2333.       if (cw != channel_widget)
  2334.     {
  2335.       switch (cw->type)
  2336.         {
  2337.         case AUXILLARY_CHANNEL:
  2338.           visible |= GIMP_DRAWABLE (cw->channel)->visible;
  2339.           break;
  2340.         default:
  2341.           visible |= gimp_image_get_component_visible (cw->gimage, cw->type);
  2342.           break;
  2343.         }
  2344.     }
  2345.     }
  2346.  
  2347.   /*  Now, toggle the visibility for all channels except the specified one  */
  2348.   for (list = channelsD->channel_widgets; list;  list = g_slist_next (list))
  2349.     {
  2350.       cw = (ChannelWidget *) list->data;
  2351.  
  2352.       if (cw != channel_widget)
  2353.     switch (cw->type)
  2354.       {
  2355.       case AUXILLARY_CHANNEL:
  2356.         GIMP_DRAWABLE (cw->channel)->visible = !visible;
  2357.         break;
  2358.       default:
  2359.         gimp_image_set_component_visible (cw->gimage, cw->type, !visible);
  2360.         break;
  2361.       }
  2362.       else
  2363.     switch (cw->type)
  2364.       {
  2365.       case AUXILLARY_CHANNEL:
  2366.         GIMP_DRAWABLE (cw->channel)->visible = TRUE;
  2367.         break;
  2368.       default:
  2369.         gimp_image_set_component_visible (cw->gimage, cw->type, TRUE);
  2370.         break;
  2371.       }
  2372.  
  2373.       channel_widget_eye_redraw (cw);
  2374.     }
  2375. }
  2376.  
  2377. static void
  2378. channel_widget_channel_flush (GtkWidget *widget,
  2379.                   gpointer   data)
  2380. {
  2381.   ChannelWidget *channel_widget;
  2382.   gboolean update_preview = FALSE;
  2383.  
  2384.   channel_widget =
  2385.     (ChannelWidget *) gtk_object_get_user_data (GTK_OBJECT (widget));
  2386.  
  2387.   /*  Set sensitivity  */
  2388.  
  2389.   /*  If there is a floating selection...  */
  2390.   if (channelsD->floating_sel != NULL)
  2391.     {
  2392.       /*  to insensitive if this is an auxillary channel  */
  2393.       if (channel_widget->type == AUXILLARY_CHANNEL)
  2394.     {
  2395.       if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2396.         gtk_widget_set_sensitive (channel_widget->list_item, FALSE);
  2397.     }
  2398.       /*  to sensitive otherwise  */
  2399.       else
  2400.     {
  2401.       if (! GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2402.         gtk_widget_set_sensitive (channel_widget->list_item, TRUE);
  2403.     }
  2404.     }
  2405.   else
  2406.     {
  2407.       /*  to insensitive if there is an active channel,
  2408.        *  and this is a component channel
  2409.        */
  2410.       if (channel_widget->type != AUXILLARY_CHANNEL &&
  2411.       channelsD->active_channel != NULL)
  2412.     {
  2413.       if (GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2414.         gtk_widget_set_sensitive (channel_widget->list_item, FALSE);
  2415.     }
  2416.       /*  to sensitive otherwise  */
  2417.       else
  2418.     {
  2419.       if (! GTK_WIDGET_IS_SENSITIVE (channel_widget->list_item))
  2420.         gtk_widget_set_sensitive (channel_widget->list_item, TRUE);
  2421.     }
  2422.     }
  2423.  
  2424.   /*  Set selection  */
  2425.  
  2426.   /*  If this is an auxillary channel  */
  2427.   if (channel_widget->type == AUXILLARY_CHANNEL)
  2428.     {
  2429.       /*  select if this is the active channel  */
  2430.       if (channelsD->active_channel == (channel_widget->channel))
  2431.     channels_dialog_set_channel (channel_widget);
  2432.       /*  unselect if this is not the active channel  */
  2433.       else
  2434.     channels_dialog_unset_channel (channel_widget);
  2435.     }
  2436.   else
  2437.     {
  2438.       /*  If the component is active, select. otherwise, deselect  */
  2439.       if (gimp_image_get_component_active (channel_widget->gimage,
  2440.                        channel_widget->type))
  2441.     channels_dialog_set_channel (channel_widget);
  2442.       else
  2443.     channels_dialog_unset_channel (channel_widget);
  2444.     }
  2445.  
  2446.   switch (channel_widget->type)
  2447.     {
  2448.     case AUXILLARY_CHANNEL:
  2449.       update_preview = !GIMP_DRAWABLE (channel_widget->channel)->preview_valid;
  2450.       break;
  2451.     default:
  2452.       update_preview = !gimp_image_preview_valid (channel_widget->gimage,
  2453.                           channel_widget->type);
  2454.       break;
  2455.     }
  2456.  
  2457.   if (update_preview)
  2458.     gtk_widget_queue_draw (channel_widget->channel_preview);
  2459. }
  2460.  
  2461. /**********************************/
  2462. /*  The new channel query dialog  */
  2463. /**********************************/
  2464.  
  2465. typedef struct _NewChannelOptions NewChannelOptions;
  2466.  
  2467. struct _NewChannelOptions
  2468. {
  2469.   GtkWidget  *query_box;
  2470.   GtkWidget  *name_entry;
  2471.   ColorPanel *color_panel;
  2472.  
  2473.   GimpImage *gimage;
  2474.   gdouble    opacity;
  2475. };
  2476.  
  2477. static gchar  *channel_name     = NULL;
  2478. static guchar  channel_color[3] = { 0, 0, 0 };
  2479.  
  2480. static void
  2481. new_channel_query_ok_callback (GtkWidget *widget,
  2482.                    gpointer   data)
  2483. {
  2484.   NewChannelOptions *options;
  2485.   Channel   *new_channel;
  2486.   GimpImage *gimage;
  2487.   gint i;
  2488.  
  2489.   options = (NewChannelOptions *) data;
  2490.  
  2491.   if (channel_name)
  2492.     g_free (channel_name);
  2493.   channel_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
  2494.  
  2495.   if ((gimage = options->gimage))
  2496.     {
  2497.       new_channel = channel_new (gimage, gimage->width, gimage->height,
  2498.                  channel_name,
  2499.                  (gint) (255 * options->opacity) / 100,
  2500.                  options->color_panel->color);
  2501.       drawable_fill (GIMP_DRAWABLE (new_channel), TRANSPARENT_FILL);
  2502.  
  2503.       for (i = 0; i < 3; i++)
  2504.     channel_color[i] = options->color_panel->color[i];
  2505.  
  2506.       gimp_image_add_channel (gimage, new_channel, -1);
  2507.       gdisplays_flush ();
  2508.     }
  2509.  
  2510.   gtk_widget_destroy (options->query_box);
  2511. }
  2512.  
  2513. static void
  2514. channels_dialog_new_channel_query (GimpImage* gimage)
  2515. {
  2516.   NewChannelOptions *options;
  2517.   GtkWidget *hbox;
  2518.   GtkWidget *vbox;
  2519.   GtkWidget *table;
  2520.   GtkWidget *label;
  2521.   GtkWidget *opacity_scale;
  2522.   GtkObject *opacity_scale_data;
  2523.  
  2524.   /*  the new options structure  */
  2525.   options = g_new (NewChannelOptions, 1);
  2526.   options->gimage      = gimage;
  2527.   options->opacity     = 50.0;
  2528.   options->color_panel = color_panel_new (channel_color, 48, 64);
  2529.  
  2530.   /*  The dialog  */
  2531.   options->query_box =
  2532.     gimp_dialog_new (_("New Channel Options"), "new_channel_options",
  2533.              gimp_standard_help_func,
  2534.              "dialogs/channels/new_channel.html",
  2535.              GTK_WIN_POS_MOUSE,
  2536.              FALSE, TRUE, FALSE,
  2537.  
  2538.              _("OK"), new_channel_query_ok_callback,
  2539.              options, NULL, NULL, TRUE, FALSE,
  2540.              _("Cancel"), gtk_widget_destroy,
  2541.              NULL, 1, NULL, FALSE, TRUE,
  2542.  
  2543.              NULL);
  2544.  
  2545.   gtk_signal_connect_object (GTK_OBJECT (options->query_box), "destroy",
  2546.                  GTK_SIGNAL_FUNC (g_free),
  2547.                  (GtkObject *) options);
  2548.  
  2549.   /*  The main hbox  */
  2550.   hbox = gtk_hbox_new (FALSE, 2);
  2551.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  2552.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
  2553.              hbox);
  2554.  
  2555.   /*  The vbox  */
  2556.   vbox = gtk_vbox_new (FALSE, 2);
  2557.   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  2558.  
  2559.   /*  The table  */
  2560.   table = gtk_table_new (2, 3, FALSE);
  2561.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  2562.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  2563.  
  2564.   /*  The name entry hbox, label and entry  */
  2565.   label = gtk_label_new (_("Channel name:"));
  2566.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  2567.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
  2568.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  2569.   gtk_widget_show (label);
  2570.  
  2571.   options->name_entry = gtk_entry_new ();
  2572.   gtk_widget_set_usize (options->name_entry, 150, 0);
  2573.   gtk_table_attach_defaults (GTK_TABLE (table), options->name_entry,
  2574.                  1, 2, 0, 1);
  2575.   gtk_entry_set_text (GTK_ENTRY (options->name_entry),
  2576.               (channel_name ? channel_name : _("New Channel")));
  2577.   gtk_widget_show (options->name_entry);
  2578.  
  2579.   /*  The opacity scale  */
  2580.   label = gtk_label_new (_("Fill Opacity:"));
  2581.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  2582.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  2583.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  2584.   gtk_widget_show (label);
  2585.  
  2586.   opacity_scale_data =
  2587.     gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
  2588.   opacity_scale = gtk_hscale_new (GTK_ADJUSTMENT (opacity_scale_data));
  2589.   gtk_table_attach_defaults (GTK_TABLE (table), opacity_scale, 1, 2, 1, 2);
  2590.   gtk_scale_set_value_pos (GTK_SCALE (opacity_scale), GTK_POS_TOP);
  2591.   gtk_range_set_update_policy (GTK_RANGE (opacity_scale), GTK_UPDATE_DELAYED);
  2592.   gtk_signal_connect (GTK_OBJECT (opacity_scale_data), "value_changed",
  2593.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  2594.               &options->opacity);
  2595.   gtk_widget_show (opacity_scale);
  2596.  
  2597.   /*  The color panel  */
  2598.   gtk_box_pack_start (GTK_BOX (hbox), options->color_panel->color_panel_widget,
  2599.               TRUE, TRUE, 0);
  2600.   gtk_widget_show (options->color_panel->color_panel_widget);
  2601.  
  2602.   gtk_widget_show (table);
  2603.   gtk_widget_show (vbox);
  2604.   gtk_widget_show (hbox);
  2605.   gtk_widget_show (options->query_box);
  2606. }
  2607.  
  2608. /****************************************/
  2609. /*  The edit channel attributes dialog  */
  2610. /****************************************/
  2611.  
  2612. typedef struct _EditChannelOptions EditChannelOptions;
  2613.  
  2614. struct _EditChannelOptions
  2615. {
  2616.   GtkWidget *query_box;
  2617.   GtkWidget *name_entry;
  2618.  
  2619.   ChannelWidget *channel_widget;
  2620.   GimpImage     *gimage;
  2621.   ColorPanel    *color_panel;
  2622.   gdouble        opacity;
  2623. };
  2624.  
  2625. static void
  2626. edit_channel_query_ok_callback (GtkWidget *widget,
  2627.                 gpointer   data)
  2628. {
  2629.   EditChannelOptions *options;
  2630.   Channel *channel;
  2631.   gint opacity;
  2632.   gint update = FALSE;
  2633.   gint i;
  2634.  
  2635.   options = (EditChannelOptions *) data;
  2636.   channel = options->channel_widget->channel;
  2637.   opacity = (gint) (255 * options->opacity) / 100;
  2638.  
  2639.   if (options->gimage)
  2640.     {
  2641.       /*  Set the new channel name  */
  2642.       channel_set_name (channel,
  2643.             gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
  2644.       gtk_label_set_text (GTK_LABEL (options->channel_widget->label),
  2645.               channel_get_name (channel));
  2646.  
  2647.       if (channel->opacity != opacity)
  2648.     {
  2649.       channel->opacity = opacity;
  2650.       update = TRUE;
  2651.     }
  2652.       for (i = 0; i < 3; i++)
  2653.     if (options->color_panel->color[i] != channel->col[i])
  2654.       {
  2655.         channel->col[i] = options->color_panel->color[i];
  2656.         update = TRUE;
  2657.       }
  2658.  
  2659.       if (update)
  2660.     {
  2661.       drawable_update (GIMP_DRAWABLE (channel), 0, 0,
  2662.                GIMP_DRAWABLE (channel)->width,
  2663.                GIMP_DRAWABLE (channel)->height);
  2664.       gdisplays_flush ();
  2665.     }
  2666.     }
  2667.  
  2668.   gtk_widget_destroy (options->query_box);
  2669. }
  2670.  
  2671. static void
  2672. channels_dialog_edit_channel_query (ChannelWidget *channel_widget)
  2673. {
  2674.   EditChannelOptions *options;
  2675.   GtkWidget *hbox;
  2676.   GtkWidget *vbox;
  2677.   GtkWidget *table;
  2678.   GtkWidget *label;
  2679.   GtkWidget *opacity_scale;
  2680.   GtkObject *opacity_scale_data;
  2681.   gint i;
  2682.  
  2683.   /*  the new options structure  */
  2684.   options = g_new (EditChannelOptions, 1);
  2685.   options->channel_widget = channel_widget;
  2686.   options->gimage         = channel_widget->gimage;
  2687.   options->opacity        = (gdouble) channel_widget->channel->opacity / 2.55;
  2688.   for (i = 0; i < 3; i++)
  2689.     channel_color[i] = channel_widget->channel->col[i];
  2690.  
  2691.   options->color_panel = color_panel_new (channel_color, 48, 64);
  2692.  
  2693.   /*  The dialog  */
  2694.   options->query_box =
  2695.     gimp_dialog_new (_("Edit Channel Attributes"), "edit_channel_attributes",
  2696.              gimp_standard_help_func,
  2697.              "dialogs/channels/edit_channel_attributes.html",
  2698.              GTK_WIN_POS_MOUSE,
  2699.              FALSE, TRUE, FALSE,
  2700.  
  2701.              _("OK"), edit_channel_query_ok_callback,
  2702.              options, NULL, NULL, TRUE, FALSE,
  2703.              _("Cancel"), gtk_widget_destroy,
  2704.              NULL, 1, NULL, FALSE, TRUE,
  2705.  
  2706.              NULL);
  2707.  
  2708.   gtk_signal_connect_object (GTK_OBJECT (options->query_box), "destroy",
  2709.                  GTK_SIGNAL_FUNC (g_free),
  2710.                  (GtkObject *) options);
  2711.  
  2712.   /*  The main hbox  */
  2713.   hbox = gtk_hbox_new (FALSE, 2);
  2714.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  2715.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
  2716.              hbox);
  2717.  
  2718.   /*  The vbox  */
  2719.   vbox = gtk_vbox_new (FALSE, 2);
  2720.   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  2721.  
  2722.   /*  The table  */
  2723.   table = gtk_table_new (2, 3, FALSE);
  2724.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  2725.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  2726.  
  2727.   /*  The name entry  */
  2728.   label = gtk_label_new (_("Channel name:"));
  2729.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  2730.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
  2731.             GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2732.   gtk_widget_show (label);
  2733.  
  2734.   options->name_entry = gtk_entry_new ();
  2735.   gtk_widget_set_usize (options->name_entry, 150, 0);
  2736.   gtk_table_attach_defaults (GTK_TABLE (table), options->name_entry,
  2737.                  1, 2, 0, 1);
  2738.   gtk_entry_set_text (GTK_ENTRY (options->name_entry),
  2739.               channel_get_name (channel_widget->channel));
  2740.   gtk_widget_show (options->name_entry);
  2741.  
  2742.   /*  The opacity scale  */
  2743.   label = gtk_label_new (_("Fill Opacity:"));
  2744.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  2745.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  2746.             GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2747.   gtk_widget_show (label);
  2748.  
  2749.   opacity_scale_data =
  2750.     gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
  2751.   opacity_scale = gtk_hscale_new (GTK_ADJUSTMENT (opacity_scale_data));
  2752.   gtk_table_attach_defaults (GTK_TABLE (table), opacity_scale, 1, 2, 1, 2);
  2753.   gtk_scale_set_value_pos (GTK_SCALE (opacity_scale), GTK_POS_TOP);
  2754.   gtk_signal_connect (GTK_OBJECT (opacity_scale_data), "value_changed",
  2755.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  2756.               &options->opacity);
  2757.   gtk_widget_show (opacity_scale);
  2758.  
  2759.   /*  The color panel  */
  2760.   gtk_box_pack_start (GTK_BOX (hbox), options->color_panel->color_panel_widget,
  2761.               TRUE, TRUE, 0);
  2762.   gtk_widget_show (options->color_panel->color_panel_widget);
  2763.  
  2764.   gtk_widget_show (table);
  2765.   gtk_widget_show (vbox);
  2766.   gtk_widget_show (hbox);
  2767.   gtk_widget_show (options->query_box);
  2768. }
  2769.