home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / lc_dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  20.2 KB  |  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.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "dialog_handler.h"
  27. #include "gimage.h"
  28. #include "gimpcontext.h"
  29. #include "gimppreviewcache.h"
  30. #include "gimprc.h"
  31. #include "gimpset.h"
  32. #include "gimpui.h"
  33. #include "image_render.h"
  34. #include "lc_dialog.h"
  35. #include "lc_dialogP.h"
  36. #include "layers_dialogP.h"
  37. #include "session.h"
  38.  
  39. #include "libgimp/gimpintl.h"
  40. #include "libgimp/gimplimits.h"
  41. #include "libgimp/gimpmath.h"
  42.  
  43.  
  44. #define MENU_THUMBNAIL_SIZE  24
  45.  
  46.  
  47. /*  local function prototypes  */
  48. static void  lc_dialog_update              (GimpImage   *gimage);
  49. static void  lc_dialog_image_menu_callback (GtkWidget   *widget,
  50.                         gpointer     data);
  51. static void  lc_dialog_auto_callback       (GtkWidget   *widget,
  52.                         gpointer     data);
  53. static gint  lc_dialog_close_callback      (GtkWidget   *widget,
  54.                         gpointer     data);
  55. static void  lc_dialog_add_callback        (GimpSet     *set,
  56.                         GimpImage   *gimage,
  57.                         gpointer     data);
  58. static void  lc_dialog_remove_callback     (GimpSet     *set,
  59.                         GimpImage   *gimage,
  60.                         gpointer     data);
  61. static void  lc_dialog_change_image        (GimpContext *context,
  62.                         GimpImage   *gimage,
  63.                         gpointer     data);
  64. static void  lc_dialog_help_func           (const gchar *help_data);
  65.  
  66. static void  lc_dialog_image_menu_preview_update_callback (GtkWidget *widget,
  67.                                gpointer   data);
  68. static void  lc_dialog_fill_preview_with_thumb            (GtkWidget *widget,
  69.                                GimpImage *gimage,
  70.                                gint       width,
  71.                                gint       height);
  72.  
  73.  
  74. /*  FIXME: move these to a better place  */
  75. static GtkWidget * lc_dialog_create_image_menu    (GimpImage     **def,
  76.                            gint           *default_index,
  77.                            GtkSignalFunc   callback);
  78. static void        lc_dialog_create_image_menu_callback (gpointer  image,
  79.                              gpointer  data);
  80.  
  81.  
  82. /*  the main dialog structure  */
  83. LCDialog * lc_dialog = NULL;
  84.  
  85.  
  86. /*********************************/
  87. /*  Public L&C dialog functions  */
  88. /*********************************/
  89.  
  90. void
  91. lc_dialog_create (GimpImage *gimage)
  92. {
  93.   GtkWidget *util_box;
  94.   GtkWidget *auto_button;
  95.   GtkWidget *button;
  96.   GtkWidget *label;
  97.   GtkWidget *separator;
  98.   gint       default_index;
  99.  
  100.   if (lc_dialog)
  101.     {
  102.       if (! GTK_WIDGET_VISIBLE (lc_dialog->shell))
  103.     {
  104.       gtk_widget_show (lc_dialog->shell);
  105.     }
  106.       else 
  107.     {
  108.       gdk_window_raise (lc_dialog->shell->window);
  109.     }
  110.  
  111.       if (gimage)
  112.     lc_dialog_update (gimage);
  113.  
  114.       lc_dialog_update_image_list ();
  115.  
  116.       return;
  117.     }
  118.  
  119.   lc_dialog = g_new (LCDialog, 1);
  120.   lc_dialog->shell =
  121.     gimp_dialog_new (_("Layers, Channels & Paths"), "layers_channels_paths",
  122.              lc_dialog_help_func,
  123.              "dialogs/layers_and_channels.html",
  124.              GTK_WIN_POS_NONE,
  125.              FALSE, TRUE, FALSE,
  126.              NULL);
  127.   lc_dialog->gimage = NULL;
  128.   lc_dialog->auto_follow_active = TRUE;
  129.  
  130.   /*  Register the dialog  */
  131.   dialog_register (lc_dialog->shell);
  132.   session_set_window_geometry (lc_dialog->shell, &lc_dialog_session_info, TRUE);
  133.  
  134.   /*  Handle the WM delete event  */
  135.   gtk_signal_connect (GTK_OBJECT (lc_dialog->shell), "delete_event", 
  136.               GTK_SIGNAL_FUNC (lc_dialog_close_callback), NULL);
  137.  
  138.   /*  The toplevel vbox  */
  139.   lc_dialog->subshell = gtk_vbox_new (FALSE, 1);
  140.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (lc_dialog->shell)->vbox),
  141.              lc_dialog->subshell);
  142.  
  143.   /*  The hbox to hold the image option menu box  */
  144.   util_box = gtk_hbox_new (FALSE, 2);
  145.   gtk_container_set_border_width (GTK_CONTAINER (util_box), 2);
  146.   gtk_box_pack_start (GTK_BOX (lc_dialog->subshell), util_box, FALSE, FALSE, 0);
  147.  
  148.   /*  The GIMP image option menu  */
  149.   label = gtk_label_new (_("Image:"));
  150.   gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
  151.   gtk_widget_show (label);
  152.  
  153.   lc_dialog->image_option_menu = gtk_option_menu_new ();
  154.   lc_dialog->image_menu = 
  155.     lc_dialog_create_image_menu (&gimage, &default_index,
  156.                  lc_dialog_image_menu_callback);
  157.   gtk_box_pack_start (GTK_BOX (util_box), lc_dialog->image_option_menu,
  158.               TRUE, TRUE, 0);
  159.   gimp_help_set_help_data (lc_dialog->image_option_menu, NULL, "#image_menu");
  160.   gtk_widget_show (lc_dialog->image_option_menu);
  161.  
  162.   gtk_option_menu_set_menu (GTK_OPTION_MENU (lc_dialog->image_option_menu),
  163.                 lc_dialog->image_menu);
  164.   if (default_index != -1)
  165.     gtk_option_menu_set_history
  166.       (GTK_OPTION_MENU (lc_dialog->image_option_menu), default_index);
  167.  
  168.   /*  The Auto-button  */
  169.   auto_button = gtk_toggle_button_new_with_label (_("Auto"));
  170.   gtk_box_pack_start (GTK_BOX (util_box), auto_button, FALSE, FALSE, 0);
  171.   gtk_signal_connect (GTK_OBJECT (auto_button), "clicked",
  172.               (GtkSignalFunc) lc_dialog_auto_callback,
  173.               auto_button);
  174.   gimp_help_set_help_data (auto_button, NULL, "#auto_button");
  175.   gtk_widget_show (auto_button);
  176.   /*  State will be set when the sub-dialogs exists (see below)  */
  177.  
  178.   gtk_widget_show (util_box);
  179.  
  180.   separator = gtk_hseparator_new ();
  181.   gtk_box_pack_start (GTK_BOX (lc_dialog->subshell), separator,
  182.               FALSE, FALSE, 0);
  183.   gtk_widget_show (separator);
  184.  
  185.   /*  The notebook widget  */
  186.   lc_dialog->notebook = gtk_notebook_new ();
  187.   gtk_container_set_border_width (GTK_CONTAINER (lc_dialog->notebook), 2);
  188.   gtk_box_pack_start (GTK_BOX (lc_dialog->subshell), lc_dialog->notebook,
  189.               TRUE, TRUE, 0);
  190.  
  191.   label = gtk_label_new (_("Layers"));
  192.   gtk_notebook_append_page (GTK_NOTEBOOK (lc_dialog->notebook),
  193.                 layers_dialog_create (), label);
  194.   gtk_widget_show (label);
  195.  
  196.   label = gtk_label_new (_("Channels"));
  197.   gtk_notebook_append_page (GTK_NOTEBOOK (lc_dialog->notebook),
  198.                 channels_dialog_create (), label);
  199.   gtk_widget_show (label);
  200.  
  201.   label = gtk_label_new (_("Paths"));
  202.   gtk_notebook_append_page (GTK_NOTEBOOK (lc_dialog->notebook),
  203.                 paths_dialog_create (), label);
  204.   gtk_widget_show (label);
  205.  
  206.   /*  Now all notebook pages exist, we can set the Auto-togglebutton  */
  207.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_button),
  208.                 lc_dialog->auto_follow_active);
  209.  
  210.   gtk_widget_show (lc_dialog->notebook);
  211.  
  212.   /*  The action area  */
  213.   gtk_container_set_border_width
  214.     (GTK_CONTAINER (GTK_DIALOG (lc_dialog->shell)->action_area), 1);
  215.  
  216.   /*  The close button  */
  217.   button = gtk_button_new_with_label (_("Close"));
  218.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (lc_dialog->shell)->action_area),
  219.               button, TRUE, TRUE, 0);
  220.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  221.               (GtkSignalFunc) lc_dialog_close_callback,
  222.               lc_dialog->shell);
  223.   gtk_widget_show (button);
  224.  
  225.   /*  Make sure the channels page is realized  */
  226.   gtk_notebook_set_page (GTK_NOTEBOOK (lc_dialog->notebook), 1);
  227.   gtk_notebook_set_page (GTK_NOTEBOOK (lc_dialog->notebook), 0);
  228.  
  229.   gtk_signal_connect (GTK_OBJECT (image_context), "add",
  230.               GTK_SIGNAL_FUNC (lc_dialog_add_callback), NULL);
  231.   gtk_signal_connect (GTK_OBJECT (image_context), "remove",
  232.               GTK_SIGNAL_FUNC (lc_dialog_remove_callback), NULL);
  233.   gtk_signal_connect (GTK_OBJECT (gimp_context_get_user ()), "image_changed",
  234.               GTK_SIGNAL_FUNC (lc_dialog_change_image), NULL);
  235.  
  236.   lc_dialog_update (gimage);
  237.   lc_dialog_update_image_list ();
  238.  
  239.   gtk_widget_show (lc_dialog->subshell);
  240.   gtk_widget_show (lc_dialog->shell);
  241.  
  242.   gdisplays_flush ();
  243. }
  244.  
  245. void
  246. lc_dialog_free (void)
  247. {
  248.   if (lc_dialog == NULL)
  249.     return;
  250.  
  251.   session_get_window_info (lc_dialog->shell, &lc_dialog_session_info);
  252.  
  253.   layers_dialog_free ();
  254.   channels_dialog_free ();
  255.  
  256.   gtk_widget_destroy (lc_dialog->shell);
  257.  
  258.   g_free (lc_dialog);
  259.   lc_dialog = NULL;
  260. }
  261.  
  262. void
  263. lc_dialog_rebuild (gint new_preview_size)
  264. {
  265.   GimpImage *gimage;
  266.   gboolean   flag;
  267.  
  268.   gimage = NULL;
  269.   flag   = FALSE;
  270.  
  271.   if (lc_dialog)
  272.     {
  273.       flag = TRUE;
  274.       gimage = lc_dialog->gimage;
  275.       /*  Unregister the dialog  */
  276.       dialog_unregister (lc_dialog->shell);
  277.       lc_dialog_free ();
  278.     }
  279.  
  280.   preview_size = new_preview_size;
  281.   render_setup (transparency_type, transparency_size);
  282.  
  283.   if (flag)
  284.     lc_dialog_create (gimage);
  285. }
  286.  
  287. void
  288. lc_dialog_flush (void)
  289. {
  290.   if (! lc_dialog || lc_dialog->gimage == NULL)
  291.     return;
  292.  
  293.   layers_dialog_flush ();
  294.   channels_dialog_flush ();
  295.   paths_dialog_flush ();
  296. }
  297.  
  298. static gint 
  299. image_menu_preview_update_do (GimpImage *gimage)
  300. {
  301.   if (lc_dialog)
  302.     {
  303.       gtk_container_foreach (GTK_CONTAINER (lc_dialog->image_menu),
  304.                  lc_dialog_image_menu_preview_update_callback,
  305.                  (gpointer) gimage);
  306.     }
  307.   return FALSE;
  308. }
  309.  
  310. void
  311. lc_dialog_menu_preview_dirty (GtkObject *obj,
  312.                   gpointer   data)
  313. {
  314.   if (!preview_size)
  315.     return;
  316.  
  317.   /* Update preview at a less busy time */
  318.   gtk_idle_add ((GtkFunction) image_menu_preview_update_do, obj); 
  319. }
  320.  
  321. void 
  322. lc_dialog_preview_update (GimpImage *gimage)
  323. {
  324.   if (!preview_size)
  325.     return;
  326.  
  327.   layers_dialog_invalidate_previews (gimage);
  328.   gtk_idle_add ((GtkFunction) image_menu_preview_update_do, gimage);
  329. }
  330.  
  331. static void
  332. lc_dialog_image_menu_preview_update_callback (GtkWidget *widget,
  333.                           gpointer   data)
  334. {
  335.   GtkWidget *menu_preview;
  336.   GimpImage *gimage;
  337.   GimpImage *gimage_to_update;
  338.  
  339.   gimage_to_update = (GimpImage *) data; 
  340.  
  341.   /* This is called via an idle  function, so it is possible
  342.    * that the client_data no longer points to a GimpImage.. So don't
  343.    * pass it to the GIMP_IMAGE() cast function. We never deference
  344.    * it here anyways.
  345.    */
  346.  
  347.   menu_preview = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (widget),
  348.                             "menu_preview");
  349.   gimage = (GimpImage *) gtk_object_get_data (GTK_OBJECT (widget),
  350.                           "menu_preview_gimage");
  351.  
  352.   if (menu_preview && gimage && gimage_to_update == gimage)
  353.     {
  354.       /* Must update the preview? */
  355.       lc_dialog_fill_preview_with_thumb (menu_preview,
  356.                      gimage,
  357.                      MENU_THUMBNAIL_SIZE,
  358.                      MENU_THUMBNAIL_SIZE);
  359.       gtk_widget_queue_draw (GTK_WIDGET (menu_preview));
  360.     }
  361. }
  362.  
  363. void
  364. lc_dialog_update_image_list (void)
  365. {
  366.   GimpImage *default_gimage;
  367.   gint       default_index;
  368.  
  369.   if (lc_dialog == NULL)
  370.     return;
  371.  
  372.   default_gimage = lc_dialog->gimage;
  373.   lc_dialog->image_menu =
  374.     lc_dialog_create_image_menu (&default_gimage, &default_index,
  375.                  lc_dialog_image_menu_callback);
  376.   gtk_option_menu_set_menu (GTK_OPTION_MENU (lc_dialog->image_option_menu),
  377.                 lc_dialog->image_menu);
  378.  
  379.   if (default_index != -1)
  380.     {
  381.       gtk_option_menu_set_history
  382.     (GTK_OPTION_MENU (lc_dialog->image_option_menu), default_index);
  383.  
  384.       lc_dialog_update (default_gimage);
  385.       gdisplays_flush ();
  386.  
  387.       if (! GTK_WIDGET_IS_SENSITIVE (lc_dialog->subshell))
  388.     gtk_widget_set_sensitive (lc_dialog->subshell, TRUE);
  389.     }
  390.   else
  391.     {
  392.       layers_dialog_clear ();
  393.       channels_dialog_clear ();
  394.  
  395.       lc_dialog->gimage = NULL;
  396.  
  397.       if (GTK_WIDGET_IS_SENSITIVE (lc_dialog->subshell))
  398.     gtk_widget_set_sensitive (lc_dialog->subshell, FALSE);
  399.     }
  400. }
  401.  
  402. /**********************************/
  403. /*  Private L&C dialog functions  */
  404. /**********************************/
  405.  
  406. static void
  407. lc_dialog_update (GimpImage *gimage)
  408. {
  409.   if (! lc_dialog || lc_dialog->gimage == gimage)
  410.     return;
  411.  
  412.   lc_dialog->gimage = gimage;
  413.  
  414.   layers_dialog_update (gimage);
  415.   channels_dialog_update (gimage);
  416.   paths_dialog_update (gimage);
  417. }
  418.  
  419. typedef struct
  420. {
  421.   GImage        **def;
  422.   gint           *default_index;
  423.   GtkSignalFunc   callback;
  424.   GtkWidget      *menu;
  425.   gint            num_items;
  426.   GImage         *id;
  427. } IMCBData;
  428.  
  429. static void
  430. lc_dialog_fill_preview_with_thumb (GtkWidget *widget,
  431.                    GimpImage *gimage,
  432.                    gint       width,
  433.                    gint       height)
  434. {
  435.   guchar    *drawable_data;
  436.   TempBuf   *buf;
  437.   gint       bpp;
  438.   gint       x, y;
  439.   guchar    *src;
  440.   gdouble    r, g, b, a;
  441.   gdouble    c0, c1;
  442.   guchar    *p0, *p1, *even, *odd;
  443.   gdouble    ratio;
  444.   
  445.   bpp = 0; /* Only returned */
  446.  
  447.   /* Get right aspect ratio */  
  448.   if (gimage->width > gimage->height)
  449.     {
  450.       ratio = (gdouble) width / (gdouble) gimage->width;
  451.     }
  452.   else
  453.     {
  454.       ratio = (gdouble) height / (gdouble) gimage->height;
  455.     }
  456.  
  457.   width  = RINT (ratio * (gdouble) gimage->width);
  458.   height = RINT (ratio * (gdouble) gimage->height);
  459.  
  460.   if (width  < 1) width  = 1;
  461.   if (height < 1) height = 1;
  462.  
  463.   if (ratio > 1.0)   /*  Preview is scaling up!  */
  464.     {
  465.       TempBuf *tmp;
  466.  
  467.       tmp = gimp_image_construct_composite_preview (gimage, 
  468.                             gimage->width, 
  469.                             gimage->height);
  470.       buf = gimp_preview_scale (tmp, width, height);
  471.       temp_buf_free (tmp);
  472.     }
  473.   else
  474.     {
  475.       buf = gimp_image_construct_composite_preview (gimage, 
  476.                             width, 
  477.                             height);
  478.     }
  479.  
  480.   gtk_preview_size (GTK_PREVIEW (widget), width, height);
  481.   drawable_data = temp_buf_data (buf);
  482.   bpp = buf->bytes;
  483.  
  484.   /*  Draw the thumbnail with checks  */
  485.   src = drawable_data;
  486.  
  487.   even = g_malloc (width * 3);
  488.   odd  = g_malloc (width * 3);
  489.  
  490.   for (y = 0; y < height; y++)
  491.     {
  492.       p0 = even;
  493.       p1 = odd;
  494.       
  495.       for (x = 0; x < width; x++)
  496.     {
  497.       if (bpp == 4)
  498.         {
  499.           r = ((gdouble) src[x * 4 + 0]) / 255.0;
  500.           g = ((gdouble) src[x * 4 + 1]) / 255.0;
  501.           b = ((gdouble) src[x * 4 + 2]) / 255.0;
  502.           a = ((gdouble) src[x * 4 + 3]) / 255.0;
  503.         }
  504.       else
  505.         {
  506.           r = ((gdouble) src[x * bpp + 0]) / 255.0;
  507.           g = b = r;
  508.           a = ((gdouble) src[x * bpp + 1]) / 255.0;
  509.         }
  510.  
  511.       if ((x / GIMP_CHECK_SIZE_SM) & 1)
  512.         {
  513.           c0 = GIMP_CHECK_LIGHT;
  514.           c1 = GIMP_CHECK_DARK;
  515.         }
  516.       else
  517.         {
  518.           c0 = GIMP_CHECK_DARK;
  519.           c1 = GIMP_CHECK_LIGHT;
  520.         }
  521.  
  522.       *p0++ = (c0 + (r - c0) * a) * 255.0;
  523.       *p0++ = (c0 + (g - c0) * a) * 255.0;
  524.       *p0++ = (c0 + (b - c0) * a) * 255.0;
  525.       
  526.       *p1++ = (c1 + (r - c1) * a) * 255.0;
  527.       *p1++ = (c1 + (g - c1) * a) * 255.0;
  528.       *p1++ = (c1 + (b - c1) * a) * 255.0;
  529.     }
  530.       
  531.       if ((y / GIMP_CHECK_SIZE_SM) & 1)
  532.     {
  533.       gtk_preview_draw_row (GTK_PREVIEW (widget),
  534.                 (guchar *) odd, 0, y, width);
  535.     }
  536.       else
  537.     {
  538.       gtk_preview_draw_row (GTK_PREVIEW (widget),
  539.                 (guchar *) even, 0, y, width);
  540.     }
  541.  
  542.       src += width * bpp;
  543.     }
  544.  
  545.   g_free (even);
  546.   g_free (odd);
  547.   temp_buf_free (buf);
  548. }
  549.  
  550. static void
  551. lc_dialog_create_image_menu_callback (gpointer im,
  552.                       gpointer d)
  553. {
  554.   GimpImage *gimage = GIMP_IMAGE (im);
  555.   IMCBData  *data   = (IMCBData *) d;
  556.   gchar     *image_name;
  557.   gchar     *menu_item_label;
  558.   GtkWidget *menu_item;
  559.   GtkWidget *hbox;
  560.   GtkWidget *vbox;
  561.   GtkWidget *wcolor_box;
  562.   GtkWidget *wlabel;
  563.  
  564.   /*  make sure the default index gets set to _something_, if possible  */
  565.   if (*data->default_index == -1)
  566.     {
  567.       data->id = gimage;
  568.       *data->default_index = data->num_items;
  569.     }
  570.  
  571.   if (gimage == *data->def)
  572.     {
  573.       data->id = *data->def;
  574.       *data->default_index = data->num_items;
  575.     }
  576.  
  577.   image_name = g_basename (gimage_filename (gimage));
  578.   menu_item_label =
  579.     g_strdup_printf ("%s-%d", image_name, pdb_image_to_id (gimage));
  580.   menu_item = gtk_menu_item_new();
  581.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  582.               data->callback,
  583.               gimage);
  584.   hbox = gtk_hbox_new (FALSE, 0);
  585.   gtk_container_add  (GTK_CONTAINER (menu_item), hbox);
  586.   gtk_widget_show (hbox);
  587.  
  588.   if (preview_size)
  589.     {
  590.       vbox = gtk_vbox_new (FALSE, 0);
  591.       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  592.       gtk_widget_show (vbox);
  593.  
  594.       wcolor_box = gtk_preview_new (GTK_PREVIEW_COLOR);
  595.       gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
  596.       gtk_widget_set_usize (GTK_WIDGET (wcolor_box), 
  597.                 MENU_THUMBNAIL_SIZE, MENU_THUMBNAIL_SIZE);
  598.  
  599.       lc_dialog_fill_preview_with_thumb (wcolor_box,
  600.                      gimage,
  601.                      MENU_THUMBNAIL_SIZE,
  602.                      MENU_THUMBNAIL_SIZE);
  603.  
  604.       gtk_container_add (GTK_CONTAINER (vbox), wcolor_box);
  605.       gtk_widget_show (wcolor_box);
  606.  
  607.       if (gtk_object_get_data (GTK_OBJECT (gimage),
  608.                    "menu_preview_dirty") == NULL)
  609.     {
  610.       /* Only add this signal once */
  611.       gtk_object_set_data (GTK_OBJECT (gimage), "menu_preview_dirty",
  612.                    (gpointer) 1);
  613.       gtk_signal_connect_after (GTK_OBJECT (gimage), "dirty",
  614.                     GTK_SIGNAL_FUNC (lc_dialog_menu_preview_dirty),
  615.                     NULL);
  616.     }
  617.       gtk_object_set_data (GTK_OBJECT (menu_item), "menu_preview",
  618.                wcolor_box);
  619.       gtk_object_set_data (GTK_OBJECT (menu_item), "menu_preview_gimage",
  620.                gimage);
  621.     }
  622.  
  623.   gtk_container_add (GTK_CONTAINER (data->menu), menu_item);
  624.  
  625.   wlabel = gtk_label_new (menu_item_label);
  626.   gtk_misc_set_alignment (GTK_MISC (wlabel), 0.0, 0.5);
  627.   gtk_box_pack_start (GTK_BOX (hbox), wlabel, TRUE, TRUE, 4);
  628.   gtk_widget_show (wlabel);
  629.  
  630.   gtk_widget_show (menu_item);
  631.  
  632.   g_free (menu_item_label);
  633.   data->num_items++;  
  634. }
  635.  
  636. static GtkWidget *
  637. lc_dialog_create_image_menu (GimpImage     **def,
  638.                  gint           *default_index,
  639.                  GtkSignalFunc   callback)
  640. {
  641.   IMCBData data;
  642.  
  643.   data.def           = def;
  644.   data.default_index = default_index;
  645.   data.callback      = callback;
  646.   data.menu          = gtk_menu_new ();
  647.   data.num_items     = 0;
  648.   data.id            = NULL;
  649.  
  650.   *default_index = -1;
  651.  
  652.   gimage_foreach (lc_dialog_create_image_menu_callback, &data);
  653.  
  654.   if (! data.num_items)
  655.     {
  656.       GtkWidget *menu_item;
  657.  
  658.       menu_item = gtk_menu_item_new_with_label (_("none"));
  659.       gtk_container_add (GTK_CONTAINER (data.menu), menu_item);
  660.       gtk_widget_show (menu_item);
  661.     }
  662.  
  663.   *def = data.id;
  664.  
  665.   return data.menu;
  666. }
  667.  
  668. static void
  669. lc_dialog_image_menu_callback (GtkWidget *widget,
  670.                    gpointer   data)
  671. {
  672.   if (! lc_dialog)
  673.     return;
  674.  
  675.   lc_dialog_update (GIMP_IMAGE (data));
  676.   gdisplays_flush ();
  677. }
  678.  
  679. static void
  680. lc_dialog_auto_callback (GtkWidget *widget,
  681.              gpointer   data)
  682. {
  683.   GimpContext *context;
  684.  
  685.   if (! lc_dialog)
  686.     return;
  687.  
  688.   lc_dialog->auto_follow_active =
  689.     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
  690.  
  691.   context = gimp_context_get_user ();
  692.  
  693.   if (lc_dialog->auto_follow_active)
  694.     lc_dialog_change_image (context,
  695.                 gimp_context_get_image (context),
  696.                 NULL);
  697. }
  698.  
  699. static gint
  700. lc_dialog_close_callback (GtkWidget *widget,
  701.               gpointer   data)
  702. {
  703.   if (! lc_dialog)
  704.     return TRUE;
  705.  
  706.   lc_dialog->gimage = NULL;
  707.   gtk_widget_hide (lc_dialog->shell);
  708.  
  709.   return TRUE;
  710. }
  711.  
  712. static void
  713. lc_dialog_add_callback (GimpSet   *set,
  714.             GimpImage *gimage,
  715.             gpointer   data)
  716. {
  717.   if (! lc_dialog)
  718.     return;
  719.  
  720.   lc_dialog_update_image_list ();
  721. }
  722.  
  723. static void
  724. lc_dialog_remove_callback (GimpSet   *set,
  725.                GimpImage *gimage,
  726.                gpointer   data)
  727. {
  728.   if (! lc_dialog)
  729.     return;
  730.  
  731.   lc_dialog_update_image_list ();
  732. }
  733.  
  734. static void
  735. lc_dialog_change_image (GimpContext *context,
  736.             GimpImage   *gimage,
  737.                 gpointer     data)
  738. {
  739.   if (! lc_dialog || ! lc_dialog->auto_follow_active)
  740.     return;
  741.  
  742.   if (gimage && gimp_set_have (image_context, gimage))
  743.     {
  744.       lc_dialog_update (gimage);
  745.       lc_dialog_update_image_list ();
  746.     }
  747. }
  748.  
  749. static void
  750. lc_dialog_help_func (const gchar *help_data)
  751. {
  752.   gchar *help_page;
  753.   gint page_num;
  754.  
  755.   static gchar* dialog_names[] = { "layers", "channels", "paths" };
  756.  
  757.   page_num =
  758.     gtk_notebook_get_current_page (GTK_NOTEBOOK (lc_dialog->notebook));
  759.  
  760.   if (page_num > 2)
  761.     return;
  762.  
  763.   help_page = g_strconcat (dialog_names[page_num], "/",
  764.                "dialogs/",
  765.                dialog_names[page_num], ".html",
  766.                NULL);
  767.   gimp_standard_help_func (help_page);
  768.   g_free (help_page);
  769. }
  770.