home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / brush_select.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  53.7 KB  |  1,891 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 <string.h>
  22.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "brush_scale.h"
  29. #include "brush_edit.h"
  30. #include "brush_select.h"
  31. #include "dialog_handler.h"
  32. #include "gimpbrushgenerated.h"
  33. #include "gimpbrushlist.h"
  34. #include "gimpbrushpipe.h"
  35. #include "gimpcontext.h"
  36. #include "gimpdnd.h"
  37. #include "gimplist.h"
  38. #include "gimprc.h"
  39. #include "gimpui.h"
  40. #include "paint_options.h"
  41. #include "session.h"
  42.  
  43. #include "config.h"
  44. #include "libgimp/gimpintl.h"
  45.  
  46. #define MIN_CELL_SIZE     25
  47. #define MAX_CELL_SIZE     25  /*  disable variable brush preview size  */ 
  48.  
  49. #define STD_BRUSH_COLUMNS 5
  50. #define STD_BRUSH_ROWS    5
  51.  
  52. /* how long to wait after mouse-down before showing brush popup */
  53. #define POPUP_DELAY_MS      150
  54.  
  55. #define MAX_WIN_WIDTH(bsp)     (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_COLUMNS))
  56. #define MAX_WIN_HEIGHT(bsp)    (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_ROWS))
  57. #define MARGIN_WIDTH      1
  58. #define MARGIN_HEIGHT     1
  59.  
  60. #define BRUSH_EVENT_MASK  GDK_EXPOSURE_MASK | \
  61.                           GDK_BUTTON_PRESS_MASK | \
  62.               GDK_BUTTON_RELEASE_MASK | \
  63.                           GDK_BUTTON1_MOTION_MASK | \
  64.               GDK_ENTER_NOTIFY_MASK
  65.  
  66. /*  the pixmaps for the [scale|pipe]_indicators  */
  67. #define indicator_width  7
  68. #define indicator_height 7
  69.  
  70. #define WHT {255, 255, 255}
  71. #define BLK {  0,   0,   0}
  72. #define RED {255, 127, 127}
  73.  
  74. /*  local function prototypes  */
  75. static void     brush_change_callbacks             (BrushSelect      *bsp,
  76.                             gboolean          closing);
  77.  
  78. static GimpBrush * brush_select_drag_brush         (GtkWidget        *widget,
  79.                             gpointer          data);
  80. static void     brush_select_drop_brush            (GtkWidget        *widget,
  81.                             GimpBrush        *brush,
  82.                             gpointer          data);
  83. static void     brush_select_brush_changed         (GimpContext      *context,
  84.                             GimpBrush        *brush,
  85.                             BrushSelect      *bsp);
  86. static void     brush_select_opacity_changed       (GimpContext      *context,
  87.                             gdouble           opacity,
  88.                             BrushSelect      *bsp);
  89. static void     brush_select_paint_mode_changed    (GimpContext      *context,
  90.                             LayerModeEffects  paint_mode,
  91.                             BrushSelect      *bsp);
  92. static void     brush_select_select                (BrushSelect      *bsp,
  93.                             GimpBrush        *brush);
  94.  
  95. static void     brush_select_brush_dirty_callback  (GimpBrush        *brush,
  96.                             BrushSelect      *bsp);
  97. static void     connect_signals_to_brush           (GimpBrush        *brush, 
  98.                             BrushSelect      *bsp);
  99. static void     disconnect_signals_from_brush      (GimpBrush        *brush,
  100.                             BrushSelect      *bsp);
  101. static void     brush_added_callback               (GimpBrushList    *list,
  102.                             GimpBrush        *brush,
  103.                             BrushSelect      *bsp);
  104. static void     brush_removed_callback             (GimpBrushList    *list,
  105.                             GimpBrush        *brush,
  106.                             BrushSelect      *bsp);
  107.  
  108. static void     draw_brush_popup                   (GtkPreview       *preview,
  109.                             GimpBrush        *brush,
  110.                             gint              width,
  111.                             gint              height);
  112. static gint     brush_popup_anim_timeout           (gpointer          data);
  113. static gboolean brush_popup_timeout                (gpointer          data);
  114. static void     brush_popup_open                   (BrushSelect *,
  115.                             gint, gint, GimpBrush *);
  116. static void     brush_popup_close                  (BrushSelect *);
  117.  
  118. static void     display_setup                      (BrushSelect *);
  119. static void     clear_brush                        (BrushSelect *,
  120.                             GimpBrush *, gint, gint);
  121. static void     display_brush                      (BrushSelect *,
  122.                             GimpBrush *, gint, gint,
  123.                             gboolean);
  124. static void     do_display_brush                   (GimpBrush   *brush,
  125.                             BrushSelect *bsp);
  126. static void     display_brushes                    (BrushSelect *);
  127.  
  128. static void     brush_select_show_selected         (BrushSelect *, gint, gint);
  129. static void     update_active_brush_field          (BrushSelect *);
  130. static void     preview_calc_scrollbar             (BrushSelect *);
  131.  
  132. static gint     brush_select_resize           (GtkWidget *, GdkEvent *,
  133.                             BrushSelect *);
  134. static gint     brush_select_events                (GtkWidget *, GdkEvent *,
  135.                             BrushSelect *);
  136.  
  137. /* static void  brush_select_map_callback          (GtkWidget *,
  138.                                                     BrushSelect *); */
  139. static void     brush_select_scroll_update         (GtkAdjustment *, gpointer);
  140. static void     opacity_scale_update               (GtkAdjustment *, gpointer);
  141. static void     paint_mode_menu_callback           (GtkWidget *, gpointer);
  142. static void     spacing_scale_update               (GtkAdjustment *, gpointer);
  143.  
  144. static void     brush_select_close_callback        (GtkWidget *, gpointer);
  145. static void     brush_select_refresh_callback      (GtkWidget *, gpointer);
  146. static void     brush_select_new_brush_callback    (GtkWidget *, gpointer);
  147. static void     brush_select_edit_brush_callback   (GtkWidget *, gpointer);
  148. static void     brush_select_delete_brush_callback (GtkWidget *, gpointer);
  149.  
  150. static unsigned char scale_indicator_bits[7][7][3] = 
  151. {
  152.   { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
  153.   { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
  154.   { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
  155.   { WHT, BLK, BLK, BLK, BLK, BLK, WHT },
  156.   { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
  157.   { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
  158.   { WHT, WHT, WHT, WHT, WHT, WHT, WHT }
  159. };
  160.  
  161. static unsigned char pipe_indicator_bits[7][7][3] = 
  162. {
  163.   { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
  164.   { WHT, WHT, WHT, WHT, WHT, WHT, RED },
  165.   { WHT, WHT, WHT, WHT, WHT, RED, RED },
  166.   { WHT, WHT, WHT, WHT, RED, RED, RED },
  167.   { WHT, WHT, WHT, RED, RED, RED, RED },
  168.   { WHT, WHT, RED, RED, RED, RED, RED },
  169.   { WHT, RED, RED, RED, RED, RED, RED }
  170. };
  171.  
  172. static unsigned char scale_pipe_indicator_bits[7][7][3] = 
  173. {
  174.   { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
  175.   { WHT, WHT, WHT, BLK, WHT, WHT, RED },
  176.   { WHT, WHT, WHT, BLK, WHT, RED, RED },
  177.   { WHT, BLK, BLK, BLK, BLK, BLK, RED },
  178.   { WHT, WHT, WHT, BLK, RED, RED, RED },
  179.   { WHT, WHT, RED, BLK, RED, RED, RED },
  180.   { WHT, RED, RED, RED, RED, RED, RED }
  181. };
  182.  
  183. /*  dnd stuff  */
  184. static GtkTargetEntry preview_target_table[] =
  185. {
  186.   GIMP_TARGET_BRUSH
  187. };
  188. static guint preview_n_targets = (sizeof (preview_target_table) /
  189.                                   sizeof (preview_target_table[0]));
  190.  
  191. /*  The main brush selection dialog  */
  192. BrushSelect *brush_select_dialog = NULL;
  193.  
  194. /*  local variables  */
  195.  
  196. /*  List of active dialogs  */
  197. GSList *brush_active_dialogs = NULL;
  198.  
  199. /*  Brush editor dialog  */
  200. static BrushEditGeneratedWindow *brush_edit_generated_dialog;
  201.  
  202. void
  203. brush_dialog_create (void)
  204. {
  205.   if (! brush_select_dialog)
  206.     {
  207.       brush_select_dialog = brush_select_new (NULL, NULL, 0.0, 0, 0);
  208.     }
  209.   else
  210.     {
  211.       if (!GTK_WIDGET_VISIBLE (brush_select_dialog->shell))
  212.     gtk_widget_show (brush_select_dialog->shell);
  213.       else
  214.     gdk_window_raise (brush_select_dialog->shell->window);
  215.     }
  216. }
  217.  
  218. void
  219. brush_dialog_free (void)
  220. {
  221.   if (brush_select_dialog)
  222.     {
  223.       session_get_window_info (brush_select_dialog->shell,
  224.                    &brush_select_session_info);
  225.  
  226.       /*  save the size of the preview  */
  227.       brush_select_session_info.width =
  228.     brush_select_dialog->preview->allocation.width;
  229.       brush_select_session_info.height =
  230.     brush_select_dialog->preview->allocation.height;
  231.  
  232.       brush_select_free (brush_select_dialog);
  233.       brush_select_dialog = NULL;
  234.     }
  235. }
  236.  
  237. /*  If title == NULL then it is the main brush dialog  */
  238. BrushSelect *
  239. brush_select_new (gchar   *title,
  240.           /*  These are the required initial vals
  241.            *  If init_name == NULL then use current brush
  242.            */
  243.           gchar   *init_name,
  244.           gdouble  init_opacity,
  245.           gint     init_spacing,
  246.           gint     init_mode)
  247. {
  248.   BrushSelect *bsp;
  249.   GtkWidget *vbox;
  250.   GtkWidget *hbox;
  251.   GtkWidget *frame;
  252.   GtkWidget *sbar;
  253.   GtkWidget *sep;
  254.   GtkWidget *table;
  255.   GtkWidget *util_box;
  256.   GtkWidget *slider;
  257.   GtkWidget *button;
  258.  
  259.   GimpBrush *active = NULL;
  260.  
  261.   static gboolean first_call = TRUE;
  262.  
  263.   bsp = g_new (BrushSelect, 1);
  264.   bsp->callback_name          = NULL;
  265.   bsp->dnd_brush              = NULL;
  266.   bsp->brush_popup            = NULL;
  267.   bsp->popup_timeout_tag      = 0;
  268.   bsp->popup_anim_timeout_tag = 0;
  269.   bsp->scroll_offset          = 0;
  270.   bsp->old_row                = 0;
  271.   bsp->old_col                = 0;
  272.   bsp->NUM_BRUSH_COLUMNS      = STD_BRUSH_COLUMNS;
  273.   bsp->NUM_BRUSH_ROWS         = STD_BRUSH_ROWS;
  274.   bsp->redraw                 = TRUE;
  275.   bsp->freeze                 = FALSE;
  276.  
  277.   /*  The shell  */
  278.   bsp->shell = gimp_dialog_new (title ? title : _("Brush Selection"),
  279.                 "brush_selection",
  280.                 gimp_standard_help_func,
  281.                 "dialogs/brush_selection.html",
  282.                 title ? GTK_WIN_POS_MOUSE : GTK_WIN_POS_NONE,
  283.                 FALSE, TRUE, FALSE,
  284.  
  285.                 _("Refresh"), brush_select_refresh_callback,
  286.                 bsp, NULL, NULL, FALSE, FALSE,
  287.                 _("Close"), brush_select_close_callback,
  288.                 bsp, NULL, NULL, TRUE, TRUE,
  289.  
  290.                 NULL);
  291.  
  292.   if (title)
  293.     {
  294.       bsp->context = gimp_context_new (title, NULL);
  295.     }
  296.   else
  297.     {
  298.       bsp->context = gimp_context_get_user ();
  299.  
  300.       session_set_window_geometry (bsp->shell, &brush_select_session_info,
  301.                    FALSE);
  302.       dialog_register (bsp->shell);
  303.     }
  304.  
  305.   if (no_data && first_call)
  306.     brushes_init (FALSE);
  307.  
  308.   first_call = FALSE;
  309.  
  310.   if (title && init_name && strlen (init_name))
  311.     {
  312.       active = gimp_brush_list_get_brush (brush_list, init_name);
  313.     }
  314.   else
  315.     {
  316.       active = gimp_context_get_brush (gimp_context_get_user ());
  317.     }
  318.  
  319.   if (!active)
  320.     {
  321.       active = gimp_context_get_brush (gimp_context_get_standard ());
  322.     }
  323.  
  324.   if (title)
  325.     {
  326.       gimp_context_set_brush (bsp->context, active);
  327.       gimp_context_set_paint_mode (bsp->context, init_mode);
  328.       gimp_context_set_opacity (bsp->context, init_opacity);
  329.       bsp->spacing_value = init_spacing;
  330.     }
  331.  
  332.   /*  The main vbox  */
  333.   vbox = gtk_vbox_new (FALSE, 0);
  334.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  335.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (bsp->shell)->vbox), vbox);
  336.  
  337.   /*  The horizontal box containing the brush list & options box */
  338.   hbox = gtk_hbox_new (FALSE, 2);
  339.   gtk_container_add (GTK_CONTAINER (vbox), hbox);
  340.  
  341.   /*  A place holder for paint mode switching  */
  342.   bsp->left_box = gtk_hbox_new (FALSE, 0);
  343.   gtk_box_pack_start (GTK_BOX (hbox), bsp->left_box, TRUE, TRUE, 0);
  344.  
  345.   /*  The horizontal box containing preview & scrollbar  */
  346.   bsp->brush_selection_box = gtk_hbox_new (FALSE, 2);
  347.   gtk_container_add (GTK_CONTAINER (bsp->left_box), bsp->brush_selection_box);
  348.  
  349.   frame = gtk_frame_new (NULL);
  350.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  351.   gtk_box_pack_start (GTK_BOX (bsp->brush_selection_box), frame,
  352.               TRUE, TRUE, 0);
  353.  
  354.   bsp->sbar_data =
  355.     GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, MAX_WIN_HEIGHT (bsp),
  356.                     1, 1, MAX_WIN_HEIGHT (bsp)));
  357.   sbar = gtk_vscrollbar_new (bsp->sbar_data);
  358.   gtk_signal_connect (GTK_OBJECT (bsp->sbar_data), "value_changed",
  359.               GTK_SIGNAL_FUNC (brush_select_scroll_update),
  360.               bsp);
  361.   gtk_box_pack_start (GTK_BOX (bsp->brush_selection_box), sbar, FALSE, FALSE, 0);
  362.  
  363.   /*  Create the brush preview window and the underlying image  */
  364.  
  365.   /*  Get the maximum brush extents  */
  366.   bsp->cell_width  = MIN_CELL_SIZE;
  367.   bsp->cell_height = MIN_CELL_SIZE;
  368.  
  369.   bsp->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  370.   gtk_preview_size (GTK_PREVIEW (bsp->preview),
  371.             MAX_WIN_WIDTH (bsp), MAX_WIN_HEIGHT (bsp));
  372.   gtk_widget_set_usize (bsp->preview,
  373.             MAX_WIN_WIDTH (bsp), MAX_WIN_HEIGHT (bsp));
  374.   gtk_preview_set_expand (GTK_PREVIEW (bsp->preview), TRUE);
  375.   gtk_widget_set_events (bsp->preview, BRUSH_EVENT_MASK);
  376.  
  377.   gtk_signal_connect (GTK_OBJECT (bsp->preview), "event",
  378.               GTK_SIGNAL_FUNC (brush_select_events),
  379.               bsp);
  380.   gtk_signal_connect (GTK_OBJECT(bsp->preview), "size_allocate",
  381.               GTK_SIGNAL_FUNC (brush_select_resize),
  382.               bsp);
  383.  
  384.   /*  dnd stuff  */
  385.   gtk_drag_source_set (bsp->preview,
  386.                GDK_BUTTON2_MASK,
  387.                preview_target_table, preview_n_targets,
  388.                GDK_ACTION_COPY);
  389.   gimp_dnd_brush_source_set (bsp->preview, brush_select_drag_brush, bsp);
  390.  
  391.   gtk_drag_dest_set (bsp->preview,
  392.                      GTK_DEST_DEFAULT_ALL,
  393.                      preview_target_table, preview_n_targets,
  394.                      GDK_ACTION_COPY);
  395.   gimp_dnd_brush_dest_set (bsp->preview, brush_select_drop_brush, bsp);
  396.  
  397.   gtk_container_add (GTK_CONTAINER (frame), bsp->preview);
  398.   gtk_widget_show (bsp->preview);
  399.  
  400.   gtk_widget_show (sbar);
  401.   gtk_widget_show (frame);
  402.   gtk_widget_show (bsp->brush_selection_box);
  403.   gtk_widget_show (bsp->left_box);
  404.  
  405.   /*  Options box  */
  406.   bsp->options_box = gtk_vbox_new (FALSE, 0);
  407.   gtk_box_pack_start (GTK_BOX (hbox), bsp->options_box, FALSE, FALSE, 0);
  408.  
  409.   /*  Create the active brush label  */
  410.   util_box = gtk_hbox_new (FALSE, 0);
  411.   gtk_box_pack_start (GTK_BOX (bsp->options_box), util_box, FALSE, FALSE, 2);
  412.  
  413.   bsp->brush_name = gtk_label_new (_("No Brushes available"));
  414.   gtk_box_pack_start (GTK_BOX (util_box), bsp->brush_name, FALSE, FALSE, 4);
  415.   bsp->brush_size = gtk_label_new ("(0 x 0)");
  416.   gtk_box_pack_start (GTK_BOX (util_box), bsp->brush_size, FALSE, FALSE, 2);
  417.  
  418.   gtk_widget_show (bsp->brush_name);
  419.   gtk_widget_show (bsp->brush_size);
  420.   gtk_widget_show (util_box);
  421.  
  422.   /*  A place holder for paint mode switching  */
  423.   bsp->right_box = gtk_vbox_new (FALSE, 0);
  424.   gtk_box_pack_start (GTK_BOX (bsp->options_box), bsp->right_box, TRUE, TRUE, 0);
  425.  
  426.   /*  The vbox for the paint options  */
  427.   bsp->paint_options_box = gtk_vbox_new (FALSE, 0);
  428.   gtk_box_pack_start (GTK_BOX (bsp->right_box), bsp->paint_options_box,
  429.               FALSE, FALSE, 0);
  430.  
  431.   /*  A separator before the paint options  */
  432.   sep = gtk_hseparator_new ();
  433.   gtk_box_pack_start (GTK_BOX (bsp->paint_options_box), sep, FALSE, FALSE, 0);
  434.   gtk_widget_show (sep);
  435.  
  436.   /*  Create the frame and the table for the options  */
  437.   table = gtk_table_new (2, 2, FALSE);
  438.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  439.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  440.   gtk_box_pack_start (GTK_BOX (bsp->paint_options_box), table, FALSE, FALSE, 2);
  441.  
  442.   /*  Create the opacity scale widget  */
  443.   bsp->opacity_data = 
  444.     GTK_ADJUSTMENT (gtk_adjustment_new
  445.             (gimp_context_get_opacity (bsp->context) * 100.0,
  446.              0.0, 100.0, 1.0, 1.0, 0.0));
  447.   slider = gtk_hscale_new (bsp->opacity_data);
  448.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  449.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  450.   gtk_signal_connect (GTK_OBJECT (bsp->opacity_data), "value_changed",
  451.               GTK_SIGNAL_FUNC (opacity_scale_update),
  452.               bsp);
  453.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  454.                  _("Opacity:"), 1.0, 1.0,
  455.                  slider, 1, FALSE);
  456.  
  457.   /*  Create the paint mode option menu  */
  458.   bsp->option_menu =
  459.     paint_mode_menu_new (paint_mode_menu_callback, (gpointer) bsp,
  460.              gimp_context_get_paint_mode (bsp->context));
  461.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  462.                  _("Mode:"), 1.0, 0.5,
  463.                  bsp->option_menu, 1, TRUE);
  464.  
  465.   gtk_widget_show (table);
  466.   gtk_widget_show (bsp->paint_options_box);
  467.   gtk_widget_show (bsp->right_box);
  468.  
  469.   /*  Create the edit/new buttons  */
  470.   util_box = gtk_hbox_new (FALSE, 0);
  471.   gtk_box_pack_end (GTK_BOX (bsp->options_box), util_box, FALSE, FALSE, 4);
  472.  
  473.   button =  gtk_button_new_with_label (_("New"));
  474.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  475.               GTK_SIGNAL_FUNC (brush_select_new_brush_callback),
  476.               bsp);
  477.   gtk_box_pack_start (GTK_BOX (util_box), button, TRUE, TRUE, 6);
  478.  
  479.   bsp->edit_button =  gtk_button_new_with_label (_("Edit"));
  480.   gtk_signal_connect (GTK_OBJECT (bsp->edit_button), "clicked",
  481.               GTK_SIGNAL_FUNC (brush_select_edit_brush_callback),
  482.               bsp);
  483.   gtk_box_pack_start (GTK_BOX (util_box), bsp->edit_button, TRUE, TRUE, 5);
  484.  
  485.   bsp->delete_button =  gtk_button_new_with_label (_("Delete"));
  486.   gtk_signal_connect (GTK_OBJECT (bsp->delete_button), "clicked",
  487.               GTK_SIGNAL_FUNC (brush_select_delete_brush_callback),
  488.               bsp);
  489.   gtk_box_pack_start (GTK_BOX (util_box), bsp->delete_button, TRUE, TRUE, 5);
  490.  
  491.   gtk_widget_show (bsp->edit_button);    
  492.   gtk_widget_show (button);
  493.   gtk_widget_show (bsp->delete_button);    
  494.   gtk_widget_show (util_box);
  495.  
  496.   /*  Create the spacing scale widget  */
  497.   table = gtk_table_new (1, 2, FALSE);
  498.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  499.   gtk_box_pack_end (GTK_BOX (bsp->options_box), table, FALSE, FALSE, 2);
  500.  
  501.   bsp->spacing_data =
  502.     GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 1000.0, 1.0, 1.0, 0.0));
  503.   slider = gtk_hscale_new (bsp->spacing_data);
  504.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  505.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  506.   if (title && init_spacing >= 0)
  507.     {
  508.       /*  Use passed spacing instead of brushes default  */
  509.       gtk_adjustment_set_value (GTK_ADJUSTMENT (bsp->spacing_data),
  510.                 init_spacing);
  511.     }
  512.   gtk_signal_connect (GTK_OBJECT (bsp->spacing_data), "value_changed",
  513.               GTK_SIGNAL_FUNC (spacing_scale_update),
  514.               bsp);
  515.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  516.                  _("Spacing:"), 1.0, 1.0,
  517.                  slider, 1, FALSE);
  518.  
  519.   gtk_widget_show (table);
  520.  
  521.   gtk_widget_show (bsp->options_box);
  522.   gtk_widget_show (hbox);
  523.   gtk_widget_show (vbox);
  524.  
  525.   /*  add callbacks to keep the display area current  */
  526.   gimp_list_foreach (GIMP_LIST (brush_list),
  527.              (GFunc) connect_signals_to_brush,
  528.              bsp);
  529.   gtk_signal_connect (GTK_OBJECT (brush_list), "add",
  530.               GTK_SIGNAL_FUNC (brush_added_callback),
  531.               bsp);
  532.   gtk_signal_connect (GTK_OBJECT (brush_list), "remove",
  533.               GTK_SIGNAL_FUNC (brush_removed_callback),
  534.               bsp);
  535.  
  536.   /*  Only for main dialog  */
  537.   if (!title)
  538.     {
  539.       /*  set the preview's size in the callback
  540.       gtk_signal_connect (GTK_OBJECT (bsp->shell), "map",
  541.               GTK_SIGNAL_FUNC (brush_select_map_callback),
  542.               bsp);
  543.       */
  544.  
  545.       /*  if we are in per-tool paint options mode, hide the paint options  */
  546.       brush_select_show_paint_options (bsp, global_paint_options);
  547.     }
  548.  
  549.   gtk_widget_show (bsp->shell);
  550.  
  551.   preview_calc_scrollbar (bsp);
  552.  
  553.   gtk_signal_connect (GTK_OBJECT (bsp->context), "brush_changed",
  554.               GTK_SIGNAL_FUNC (brush_select_brush_changed),
  555.               bsp);
  556.   gtk_signal_connect (GTK_OBJECT (bsp->context), "opacity_changed",
  557.               GTK_SIGNAL_FUNC (brush_select_opacity_changed),
  558.               bsp);
  559.   gtk_signal_connect (GTK_OBJECT (bsp->context), "paint_mode_changed",
  560.               GTK_SIGNAL_FUNC (brush_select_paint_mode_changed),
  561.               bsp);
  562.  
  563.   if (active)
  564.     brush_select_select (bsp, active);
  565.  
  566.   /*  Add to active brush dialogs list  */
  567.   brush_active_dialogs = g_slist_append (brush_active_dialogs, bsp);
  568.  
  569.   return bsp;
  570. }
  571.  
  572. void
  573. brush_select_free (BrushSelect *bsp)
  574. {
  575.   if (!bsp)
  576.     return;
  577.  
  578.   /* remove from active list */
  579.   brush_active_dialogs = g_slist_remove (brush_active_dialogs, bsp);
  580.  
  581.   gtk_signal_disconnect_by_data (GTK_OBJECT (bsp->context), bsp);
  582.  
  583.   if (bsp->brush_popup != NULL)
  584.     gtk_widget_destroy (bsp->brush_popup);
  585.  
  586.   if (bsp->callback_name)
  587.     {
  588.       g_free (bsp->callback_name);
  589.       gtk_object_unref (GTK_OBJECT (bsp->context));
  590.     }
  591.  
  592.   gimp_list_foreach (GIMP_LIST (brush_list),
  593.              (GFunc) disconnect_signals_from_brush,
  594.              bsp);
  595.   gtk_signal_disconnect_by_data (GTK_OBJECT (brush_list), bsp);
  596.  
  597.   g_free (bsp);
  598. }
  599.  
  600. void
  601. brush_select_freeze_all (void)
  602. {
  603.   BrushSelect *bsp;
  604.   GSList *list;
  605.  
  606.   for (list = brush_active_dialogs; list; list = g_slist_next (list))
  607.     {
  608.       bsp = (BrushSelect *) list->data;
  609.  
  610.       bsp->freeze = TRUE;
  611.     }
  612. }
  613.  
  614. void
  615. brush_select_thaw_all (void)
  616. {
  617.   BrushSelect *bsp;
  618.   GSList *list;
  619.  
  620.   for (list = brush_active_dialogs; list; list = g_slist_next (list))
  621.     {
  622.       bsp = (BrushSelect *) list->data;
  623.  
  624.       bsp->freeze = FALSE;
  625.  
  626.       preview_calc_scrollbar (bsp);
  627.     }
  628. }
  629.  
  630. void
  631. brush_select_show_paint_options (BrushSelect *bsp,
  632.                  gboolean     show)
  633. {
  634.   if ((bsp == NULL) && ((bsp = brush_select_dialog) == NULL))
  635.     return;
  636.  
  637.   if (show)
  638.     {
  639.       if (! GTK_WIDGET_VISIBLE (bsp->paint_options_box))
  640.     gtk_widget_show (bsp->paint_options_box);
  641.  
  642.       if (bsp->brush_selection_box->parent != bsp->left_box)
  643.     gtk_widget_reparent (bsp->brush_selection_box, bsp->left_box);
  644.       gtk_box_set_child_packing (GTK_BOX (bsp->options_box->parent),
  645.                  bsp->options_box,
  646.                  FALSE, FALSE, 0, GTK_PACK_START);
  647.       gtk_box_set_child_packing (GTK_BOX (bsp->left_box->parent),
  648.                  bsp->left_box,
  649.                  TRUE, TRUE, 0, GTK_PACK_START);
  650.       gtk_box_set_spacing (GTK_BOX (bsp->left_box->parent), 2);
  651.     }
  652.   else
  653.     {
  654.       if (GTK_WIDGET_VISIBLE (bsp->paint_options_box))
  655.     gtk_widget_hide (bsp->paint_options_box);
  656.  
  657.       if (bsp->brush_selection_box->parent != bsp->right_box)
  658.     gtk_widget_reparent (bsp->brush_selection_box, bsp->right_box);
  659.       gtk_box_set_child_packing (GTK_BOX (bsp->left_box->parent),
  660.                  bsp->left_box,
  661.                  FALSE, FALSE, 0, GTK_PACK_START);
  662.       gtk_box_set_child_packing (GTK_BOX (bsp->options_box->parent),
  663.                  bsp->options_box,
  664.                  TRUE, TRUE, 0, GTK_PACK_START);
  665.       gtk_box_set_spacing (GTK_BOX (bsp->left_box->parent), 0);
  666.     }
  667. }
  668.  
  669. /*  call this dialog's PDB callback  */
  670.  
  671. static void
  672. brush_change_callbacks (BrushSelect *bsp,
  673.             gboolean     closing)
  674. {
  675.   gchar *name;
  676.   ProcRecord *prec = NULL;
  677.   GimpBrush *brush;
  678.   gint nreturn_vals;
  679.   static gboolean busy = FALSE;
  680.  
  681.   /* Any procs registered to callback? */
  682.   Argument *return_vals; 
  683.  
  684.   if (!bsp || !bsp->callback_name || busy)
  685.     return;
  686.  
  687.   busy = TRUE;
  688.   name = bsp->callback_name;
  689.   brush = gimp_context_get_brush (bsp->context);
  690.  
  691.   /* If its still registered run it */
  692.   prec = procedural_db_lookup (name);
  693.  
  694.   if (prec && brush)
  695.     {
  696.       return_vals =
  697.     procedural_db_run_proc (name,
  698.                 &nreturn_vals,
  699.                 PDB_STRING,    brush->name,
  700.                 PDB_FLOAT,     gimp_context_get_opacity (bsp->context),
  701.                 PDB_INT32,     bsp->spacing_value,
  702.                 PDB_INT32,     (gint) gimp_context_get_paint_mode (bsp->context),
  703.                 PDB_INT32,     brush->mask->width,
  704.                 PDB_INT32,     brush->mask->height,
  705.                 PDB_INT32,     brush->mask->width * brush->mask->height,
  706.                 PDB_INT8ARRAY, temp_buf_data (brush->mask),
  707.                 PDB_INT32,     (gint) closing,
  708.                 PDB_END);
  709.  
  710.       if (!return_vals || return_vals[0].value.pdb_int != PDB_SUCCESS)
  711.     g_message ("failed to run brush callback function");
  712.       
  713.       procedural_db_destroy_args (return_vals, nreturn_vals);
  714.     }
  715.   busy = FALSE;
  716. }
  717.  
  718. /* Close active dialogs that no longer have PDB registered for them */
  719.  
  720. void
  721. brushes_check_dialogs (void)
  722. {
  723.   BrushSelect *bsp;
  724.   GSList *list;
  725.   gchar *name;
  726.   ProcRecord *prec = NULL;
  727.  
  728.   list = brush_active_dialogs;
  729.  
  730.   while (list)
  731.     {
  732.       bsp = (BrushSelect *) list->data;
  733.       list = g_slist_next (list);
  734.  
  735.       name = bsp->callback_name;
  736.  
  737.       if (name)
  738.     {
  739.       prec = procedural_db_lookup (name);
  740.  
  741.       if (!prec)
  742.         {
  743.           /*  Can alter brush_active_dialogs list  */
  744.           brush_select_close_callback (NULL, bsp);
  745.         }
  746.     }
  747.     }
  748. }
  749.  
  750. /*
  751.  *  Local functions
  752.  */
  753.  
  754. static GimpBrush *
  755. brush_select_drag_brush (GtkWidget *widget,
  756.              gpointer   data)
  757. {
  758.   BrushSelect *bsp;
  759.  
  760.   bsp = (BrushSelect *) data;
  761.  
  762.   return bsp->dnd_brush;
  763. }
  764.  
  765. static void
  766. brush_select_drop_brush (GtkWidget *widget,
  767.              GimpBrush *brush,
  768.              gpointer   data)
  769. {
  770.   BrushSelect *bsp;
  771.  
  772.   bsp = (BrushSelect *) data;
  773.  
  774.   gimp_context_set_brush (bsp->context, brush);
  775. }
  776.  
  777. static void
  778. brush_select_brush_changed (GimpContext *context,
  779.                 GimpBrush   *brush,
  780.                 BrushSelect *bsp)
  781. {
  782.   if (brush)
  783.     {
  784.       brush_select_select (bsp, brush);
  785.  
  786.       if (bsp->callback_name)
  787.     brush_change_callbacks (bsp, FALSE);
  788.     }
  789. }
  790.  
  791. static void
  792. brush_select_opacity_changed (GimpContext *context,
  793.                   gdouble      opacity,
  794.                   BrushSelect *bsp)
  795. {
  796.   gtk_signal_handler_block_by_data (GTK_OBJECT (bsp->opacity_data), bsp);
  797.   gtk_adjustment_set_value (GTK_ADJUSTMENT (bsp->opacity_data),
  798.                 opacity * 100.0);
  799.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (bsp->opacity_data), bsp);
  800.  
  801.   if (bsp->callback_name)
  802.     brush_change_callbacks (bsp, FALSE);
  803. }
  804.  
  805. static void
  806. brush_select_paint_mode_changed (GimpContext      *context,
  807.                  LayerModeEffects  paint_mode,
  808.                  BrushSelect      *bsp)
  809. {
  810.   gimp_option_menu_set_history (GTK_OPTION_MENU (bsp->option_menu),
  811.                 (gpointer) paint_mode);
  812.  
  813.   if (bsp->callback_name)
  814.     brush_change_callbacks (bsp, FALSE);
  815. }
  816.  
  817. static void
  818. brush_select_select (BrushSelect *bsp,
  819.              GimpBrush   *brush)
  820. {
  821.   gint index;
  822.   gint row, col;
  823.   gint scroll_offset = 0;
  824.  
  825.   index = gimp_brush_list_get_brush_index (brush_list, brush); 
  826.  
  827.   if (index < 0)
  828.     return;
  829.  
  830.   if (GIMP_IS_BRUSH_GENERATED (brush))
  831.     {
  832.       gtk_widget_set_sensitive (bsp->edit_button, TRUE);
  833.       gtk_widget_set_sensitive (bsp->delete_button, TRUE);
  834.     }
  835.   else
  836.     {
  837.       gtk_widget_set_sensitive (bsp->edit_button, FALSE);
  838.       gtk_widget_set_sensitive (bsp->delete_button, FALSE);
  839.     }
  840.  
  841.   update_active_brush_field (bsp);
  842.  
  843.   row = index / bsp->NUM_BRUSH_COLUMNS;
  844.   col = index - row * (bsp->NUM_BRUSH_COLUMNS);
  845.  
  846.   /*  check if the new active brush is already in the preview  */
  847.   if (((row + 1) * bsp->cell_height) >
  848.       (bsp->preview->allocation.height + bsp->scroll_offset))
  849.     {
  850.       scroll_offset = (((row + 1) * bsp->cell_height) -
  851.                (bsp->scroll_offset + bsp->preview->allocation.height));
  852.     }
  853.   else if ((row * bsp->cell_height) < bsp->scroll_offset)
  854.     {
  855.       scroll_offset = (row * bsp->cell_height) - bsp->scroll_offset;
  856.     }
  857.   else
  858.     {
  859.       brush_select_show_selected (bsp, row, col);
  860.     }
  861.  
  862.   gtk_adjustment_set_value (bsp->sbar_data, bsp->scroll_offset + scroll_offset);
  863. }
  864.  
  865. static void
  866. brush_select_brush_dirty_callback (GimpBrush   *brush,
  867.                    BrushSelect *bsp)
  868. {
  869.   gint     index;
  870.   gboolean redraw;
  871.  
  872.   if (!bsp || bsp->freeze)
  873.     return;
  874.  
  875.   index  = gimp_brush_list_get_brush_index (brush_list, brush);
  876.   redraw = (brush != gimp_context_get_brush (bsp->context));
  877.  
  878.   clear_brush (bsp, brush,
  879.            index % (bsp->NUM_BRUSH_COLUMNS),
  880.            index / (bsp->NUM_BRUSH_COLUMNS));
  881.  
  882.   display_brush (bsp, brush,
  883.          index % (bsp->NUM_BRUSH_COLUMNS),
  884.          index / (bsp->NUM_BRUSH_COLUMNS),
  885.          redraw);
  886. }
  887.  
  888. static void
  889. connect_signals_to_brush (GimpBrush   *brush,
  890.               BrushSelect *bsp)
  891. {
  892.   gtk_signal_connect (GTK_OBJECT (brush), "dirty",
  893.               GTK_SIGNAL_FUNC (brush_select_brush_dirty_callback),
  894.               bsp);
  895.   gtk_signal_connect (GTK_OBJECT (brush), "rename",
  896.               GTK_SIGNAL_FUNC (brush_select_brush_dirty_callback),
  897.               bsp);
  898. }
  899.  
  900. static void
  901. disconnect_signals_from_brush (GimpBrush   *brush,
  902.                    BrushSelect *bsp)
  903. {
  904.   if (!GTK_OBJECT_DESTROYED (brush))
  905.     gtk_signal_disconnect_by_data (GTK_OBJECT (brush), bsp);
  906. }
  907.  
  908. static void
  909. brush_added_callback (GimpBrushList *list,
  910.               GimpBrush     *brush, 
  911.               BrushSelect   *bsp)
  912. {
  913.   connect_signals_to_brush (brush, bsp);
  914.  
  915.   if (bsp->freeze)
  916.     return;
  917.  
  918.   preview_calc_scrollbar (bsp);
  919. }
  920.  
  921. static void
  922. brush_removed_callback (GimpBrushList *list,
  923.             GimpBrush     *brush,
  924.             BrushSelect   *bsp)
  925. {
  926.   disconnect_signals_from_brush (brush, bsp);
  927.  
  928.   if (bsp->freeze)
  929.     return;
  930.  
  931.   preview_calc_scrollbar (bsp);
  932. }
  933.  
  934. static void
  935. draw_brush_popup (GtkPreview *preview,
  936.           GimpBrush  *brush,
  937.           gint        width,
  938.           gint        height)
  939. {
  940.   gint x, y;
  941.   gint brush_width, brush_height;
  942.   gint offset_x, offset_y;
  943.   guchar *mask, *buf, *b;
  944.   guchar bg;
  945.   
  946.   brush_width = brush->mask->width;
  947.   brush_height = brush->mask->height;
  948.   offset_x = (width - brush_width) / 2;
  949.   offset_y = (height - brush_height) / 2;
  950.  
  951.   mask = temp_buf_data (brush->mask);
  952.   buf = g_new (guchar, 3 * width);
  953.   memset (buf, 255, 3 * width);
  954.  
  955.   if (gimp_brush_get_pixmap (brush)) 
  956.     {
  957.       guchar *pixmap = temp_buf_data (gimp_brush_get_pixmap (brush));
  958.  
  959.       for (y = 0; y < offset_y; y++)
  960.     gtk_preview_draw_row (preview, buf, 0, y, width); 
  961.       for (y = offset_y; y < brush_height + offset_y; y++)
  962.     {
  963.       b = buf + 3 * offset_x;
  964.       for (x = 0; x < brush_width ; x++)
  965.         {
  966.           bg = (255 - *mask);
  967.           *b++ = bg + (*mask * *pixmap++) / 255;
  968.           *b++ = bg + (*mask * *pixmap++) / 255; 
  969.           *b++ = bg + (*mask * *pixmap++) / 255;
  970.           mask++;
  971.         }
  972.       gtk_preview_draw_row (preview, buf, 0, y, width); 
  973.     }
  974.       memset (buf, 255, 3 * width);
  975.       for (y = brush_height + offset_y; y < height; y++)
  976.     gtk_preview_draw_row (preview, buf, 0, y, width); 
  977.     }
  978.   else
  979.     {
  980.       for (y = 0; y < offset_y; y++)
  981.     gtk_preview_draw_row (preview, buf, 0, y, width); 
  982.       for (y = offset_y; y < brush_height + offset_y; y++)
  983.     {
  984.       b = buf + 3 * offset_x;
  985.       for (x = 0; x < brush_width ; x++)
  986.         {
  987.           bg = 255 - *mask++;
  988.           memset (b, bg, 3);
  989.           b += 3;
  990.         }   
  991.       gtk_preview_draw_row (preview, buf, 0, y, width); 
  992.     }
  993.       memset (buf, 255, 3 * width);
  994.       for (y = brush_height + offset_y; y < height; y++)
  995.     gtk_preview_draw_row (preview, buf, 0, y, width);    
  996.     }
  997.  
  998.   g_free (buf);
  999. }
  1000.  
  1001. typedef struct
  1002. {
  1003.   BrushSelect *bsp;
  1004.   gint         x;
  1005.   gint         y;
  1006.   GimpBrush   *brush;
  1007. } popup_timeout_args_t;
  1008.  
  1009. static gint
  1010. brush_popup_anim_timeout (gpointer data)
  1011. {
  1012.   popup_timeout_args_t *args = data;
  1013.   BrushSelect *bsp = args->bsp;
  1014.   GimpBrushPipe *pipe;
  1015.   GimpBrush *brush;
  1016.  
  1017.   if (bsp->brush_popup != NULL && !GTK_WIDGET_VISIBLE (bsp->brush_popup))
  1018.     {
  1019.       bsp->popup_anim_timeout_tag = 0;
  1020.       return (FALSE);
  1021.     }
  1022.  
  1023.   pipe = GIMP_BRUSH_PIPE (args->brush);
  1024.   if (++bsp->popup_pipe_index >= pipe->nbrushes)
  1025.     bsp->popup_pipe_index = 0;
  1026.   brush = GIMP_BRUSH (pipe->brushes[bsp->popup_pipe_index]);
  1027.  
  1028.   draw_brush_popup (GTK_PREVIEW (bsp->brush_preview), brush, args->x, args->y);
  1029.   gtk_widget_queue_draw (bsp->brush_preview);
  1030.  
  1031.   return (TRUE);
  1032. }
  1033.  
  1034. static gboolean
  1035. brush_popup_timeout (gpointer data)
  1036. {
  1037.   popup_timeout_args_t *args = data;
  1038.   BrushSelect *bsp = args->bsp;
  1039.   GimpBrush *brush = args->brush;
  1040.   gint x, y;
  1041.   gint x_org, y_org;
  1042.   gint scr_w, scr_h;
  1043.   gint width, height;
  1044.  
  1045.   /* timeout has gone off so our tag is now invalid  */
  1046.   bsp->popup_timeout_tag = 0;
  1047.  
  1048.   /* make sure the popup exists and is not visible */
  1049.   if (bsp->brush_popup == NULL)
  1050.     {
  1051.       GtkWidget *frame;
  1052.  
  1053.       bsp->brush_popup = gtk_window_new (GTK_WINDOW_POPUP);
  1054.       gtk_window_set_policy (GTK_WINDOW (bsp->brush_popup),
  1055.                  FALSE, FALSE, TRUE);
  1056.       frame = gtk_frame_new (NULL);
  1057.       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
  1058.       gtk_container_add (GTK_CONTAINER (bsp->brush_popup), frame);
  1059.       gtk_widget_show (frame);
  1060.       bsp->brush_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1061.       gtk_container_add (GTK_CONTAINER (frame), bsp->brush_preview);
  1062.       gtk_widget_show (bsp->brush_preview);
  1063.     }
  1064.   else
  1065.     {
  1066.       gtk_widget_hide (bsp->brush_popup);
  1067.     }
  1068.  
  1069.   /* decide where to put the popup */
  1070.   width = brush->mask->width;
  1071.   height = brush->mask->height;
  1072.   if (GIMP_IS_BRUSH_PIPE (brush))
  1073.     {      
  1074.       GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (brush);
  1075.       GimpBrush     *tmp_brush;
  1076.       gint i;
  1077.       
  1078.       for (i = 1; i < pipe->nbrushes; i++)
  1079.     {
  1080.       tmp_brush = GIMP_BRUSH (pipe->brushes[i]);
  1081.       width = MAX (width, tmp_brush->mask->width);
  1082.       height = MAX (height, tmp_brush->mask->height);
  1083.     }
  1084.     }
  1085.   gdk_window_get_origin (bsp->preview->window, &x_org, &y_org);
  1086.   scr_w = gdk_screen_width ();
  1087.   scr_h = gdk_screen_height ();
  1088.   x = x_org + args->x - width * 0.5;
  1089.   y = y_org + args->y - height * 0.5;
  1090.   x = (x < 0) ? 0 : x;
  1091.   y = (y < 0) ? 0 : y;
  1092.   x = (x + width > scr_w) ? scr_w - width : x;
  1093.   y = (y + height > scr_h) ? scr_h - height : y;
  1094.   gtk_preview_size (GTK_PREVIEW (bsp->brush_preview), width, height);
  1095.  
  1096.   gtk_widget_popup (bsp->brush_popup, x, y);
  1097.  
  1098.   /*  Draw the brush preview  */
  1099.   draw_brush_popup (GTK_PREVIEW (bsp->brush_preview), brush, width, height);
  1100.   gtk_widget_queue_draw (bsp->brush_preview);
  1101.  
  1102.   if (GIMP_IS_BRUSH_PIPE (brush) && bsp->popup_anim_timeout_tag == 0)
  1103.     {
  1104.       static popup_timeout_args_t timeout_args;
  1105.       
  1106.       timeout_args.bsp = bsp;
  1107.       timeout_args.x = width;
  1108.       timeout_args.y = height;
  1109.       timeout_args.brush = brush;
  1110.  
  1111.       bsp->popup_pipe_index = 0;
  1112.       bsp->popup_anim_timeout_tag =
  1113.     gtk_timeout_add (300, brush_popup_anim_timeout, &timeout_args);
  1114.     }
  1115.  
  1116.   return FALSE;  /* don't repeat */
  1117. }
  1118.  
  1119. static void
  1120. brush_popup_open (BrushSelect *bsp,
  1121.           gint         x,
  1122.           gint         y,
  1123.           GimpBrush   *brush)
  1124. {
  1125.   static popup_timeout_args_t popup_timeout_args;
  1126.  
  1127.   /* if we've already got a timeout scheduled, then we complain */
  1128.   g_return_if_fail (bsp->popup_timeout_tag == 0);
  1129.  
  1130.   popup_timeout_args.bsp = bsp;
  1131.   popup_timeout_args.x = x;
  1132.   popup_timeout_args.y = y;
  1133.   popup_timeout_args.brush = brush;
  1134.   bsp->popup_timeout_tag = gtk_timeout_add (POPUP_DELAY_MS,
  1135.                         brush_popup_timeout,
  1136.                         &popup_timeout_args);
  1137. }
  1138.  
  1139. static void
  1140. brush_popup_close (BrushSelect *bsp)
  1141. {
  1142.   if (bsp->popup_timeout_tag != 0)
  1143.     gtk_timeout_remove (bsp->popup_timeout_tag);
  1144.   bsp->popup_timeout_tag = 0;
  1145.  
  1146.   if (bsp->popup_anim_timeout_tag != 0)
  1147.     gtk_timeout_remove (bsp->popup_anim_timeout_tag);
  1148.   bsp->popup_anim_timeout_tag = 0;
  1149.  
  1150.   if (bsp->brush_popup != NULL)
  1151.     gtk_widget_hide (bsp->brush_popup);
  1152. }
  1153.  
  1154. static void
  1155. display_setup (BrushSelect *bsp)
  1156. {
  1157.   guchar * buf;
  1158.   gint i;
  1159.  
  1160.   buf = g_new (guchar, 3 * bsp->preview->allocation.width);
  1161.  
  1162.   /*  Set the buffer to white  */
  1163.   memset (buf, 255, bsp->preview->allocation.width * 3);
  1164.  
  1165.   /*  Set the image buffer to white  */
  1166.   for (i = 0; i < bsp->preview->allocation.height; i++)
  1167.     gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf, 0, i,
  1168.               bsp->preview->allocation.width);
  1169.  
  1170.   g_free (buf);
  1171. }
  1172.  
  1173. static void
  1174. clear_brush (BrushSelect *bsp,
  1175.          GimpBrush   *brush,
  1176.          gint         col,
  1177.          gint         row)
  1178. {
  1179.   guchar *buf;
  1180.   gint width, height;
  1181.   gint offset_x, offset_y;
  1182.   gint ystart, yend;
  1183.   gint i;
  1184.  
  1185.   width  = bsp->cell_width  - 2 * MARGIN_WIDTH;
  1186.   height = bsp->cell_height - 2 * MARGIN_HEIGHT;
  1187.  
  1188.   offset_x = col * bsp->cell_width  + MARGIN_WIDTH;
  1189.   offset_y = row * bsp->cell_height - bsp->scroll_offset + MARGIN_HEIGHT;
  1190.  
  1191.   ystart = CLAMP (offset_y, 0, bsp->preview->allocation.height);
  1192.   yend   = CLAMP (offset_y + height, 0, bsp->preview->allocation.height);
  1193.  
  1194.   buf = g_new (guchar, 3 * width);
  1195.  
  1196.   memset (buf, 255, 3 * width * sizeof (guchar));
  1197.  
  1198.   for (i = ystart; i < yend; i++)
  1199.     gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1200.               offset_x, i, width);
  1201. }
  1202.  
  1203. static void
  1204. display_brush (BrushSelect *bsp,
  1205.            GimpBrush   *brush,
  1206.            gint         col,
  1207.            gint         row,
  1208.            gboolean     redraw)
  1209. {
  1210.   TempBuf *mask_buf, *pixmap_buf = NULL;
  1211.   guchar *mask, *buf, *b;
  1212.   guchar bg;
  1213.   gboolean scale = FALSE;
  1214.   gint cell_width, cell_height;
  1215.   gint width, height;
  1216.   gint offset_x, offset_y;
  1217.   gint yend;
  1218.   gint ystart;
  1219.   gint i, j;
  1220.  
  1221.   cell_width  = bsp->cell_width  - 2 * MARGIN_WIDTH;
  1222.   cell_height = bsp->cell_height - 2 * MARGIN_HEIGHT;
  1223.  
  1224.   mask_buf = gimp_brush_get_mask (brush);
  1225.   pixmap_buf = gimp_brush_get_pixmap (brush);
  1226.  
  1227.   if (mask_buf->width > cell_width || mask_buf->height > cell_height)
  1228.     {
  1229.       gdouble ratio_x = (gdouble)mask_buf->width / cell_width;
  1230.       gdouble ratio_y = (gdouble)mask_buf->height / cell_height;
  1231.    
  1232.       mask_buf = brush_scale_mask (mask_buf, 
  1233.                    (gdouble)(mask_buf->width) / MAX (ratio_x, ratio_y) + 0.5, 
  1234.                    (gdouble)(mask_buf->height) / MAX (ratio_x, ratio_y) + 0.5);
  1235.       if (pixmap_buf)
  1236.     {
  1237.       /*  TODO: the scale function should scale the pixmap 
  1238.                 and the mask in one run                     */
  1239.        pixmap_buf = brush_scale_pixmap (pixmap_buf,
  1240.                        mask_buf->width, mask_buf->height);
  1241.     }
  1242.       scale = TRUE;
  1243.     }
  1244.  
  1245.   /*  calculate the offset into the image  */
  1246.   width = (mask_buf->width > cell_width) ? cell_width : mask_buf->width;
  1247.   height = (mask_buf->height > cell_height) ? cell_height : mask_buf->height;
  1248.  
  1249.   offset_x = col * bsp->cell_width + ((cell_width - width) >> 1) + MARGIN_WIDTH;
  1250.   offset_y = row * bsp->cell_height + ((cell_height - height) >> 1) - bsp->scroll_offset + MARGIN_HEIGHT;
  1251.  
  1252.   ystart = CLAMP (offset_y, 0, bsp->preview->allocation.height);
  1253.   yend   = CLAMP (offset_y + height, 0, bsp->preview->allocation.height);
  1254.  
  1255.   mask = temp_buf_data (mask_buf) + (ystart - offset_y) * mask_buf->width;
  1256.   buf = g_new (guchar, 3 * cell_width);
  1257.  
  1258.   if (pixmap_buf) 
  1259.     { 
  1260.       guchar *pixmap = 
  1261.     temp_buf_data (pixmap_buf) + (ystart - offset_y) * mask_buf->width * 3;
  1262.  
  1263.       for (i = ystart; i < yend; i++)
  1264.     {
  1265.       b = buf;
  1266.       for (j = 0; j < width ; j++)
  1267.         {
  1268.           bg = (255 - *mask);
  1269.           *b++ = bg + (*mask * *pixmap++) / 255;
  1270.           *b++ = bg + (*mask * *pixmap++) / 255; 
  1271.           *b++ = bg + (*mask * *pixmap++) / 255;
  1272.           mask++;
  1273.         }
  1274.       gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1275.                 offset_x, i, width);
  1276.     }
  1277.     }
  1278.   else 
  1279.     {
  1280.       for (i = ystart; i < yend; i++)
  1281.     {
  1282.       /*  Invert the mask for display.  We're doing this because
  1283.        *  a value of 255 in the  mask means it is full intensity.
  1284.        *  However, it makes more sense for full intensity to show
  1285.        *  up as black in this brush preview window...
  1286.        */
  1287.       b = buf;
  1288.       for (j = 0; j < width; j++) 
  1289.         {
  1290.           bg = 255 - *mask++;
  1291.           memset (b, bg, 3);
  1292.           b += 3;
  1293.         }
  1294.       gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1295.                 offset_x, i, width);
  1296.     }
  1297.     }
  1298.   g_free (buf);
  1299.  
  1300.   offset_x = (col + 1) * bsp->cell_width  - indicator_width - MARGIN_WIDTH;
  1301.   offset_y = (row + 1) * bsp->cell_height - indicator_height - bsp->scroll_offset - MARGIN_HEIGHT;
  1302.  
  1303.   if (scale)
  1304.     {
  1305.       temp_buf_free (mask_buf);
  1306.       if (pixmap_buf)
  1307.     temp_buf_free (pixmap_buf);
  1308.  
  1309.       for (i = 0; i < indicator_height; i++, offset_y++)
  1310.     { 
  1311.       if (offset_y > 0 && offset_y < bsp->preview->allocation.height)
  1312.         (GIMP_IS_BRUSH_PIPE (brush)) ?
  1313.           gtk_preview_draw_row (GTK_PREVIEW (bsp->preview),
  1314.                     scale_pipe_indicator_bits[i][0],
  1315.                     offset_x, offset_y, indicator_width) :
  1316.           gtk_preview_draw_row (GTK_PREVIEW (bsp->preview),
  1317.                     scale_indicator_bits[i][0],
  1318.                     offset_x, offset_y, indicator_width);
  1319.     }
  1320.     }
  1321.   else if (GIMP_IS_BRUSH_PIPE (brush))
  1322.     {
  1323.       for (i = 0; i < indicator_height; i++, offset_y++)
  1324.     {
  1325.       if (offset_y > 0 && offset_y < bsp->preview->allocation.height)
  1326.         gtk_preview_draw_row (GTK_PREVIEW (bsp->preview),
  1327.                   pipe_indicator_bits[i][0],
  1328.                   offset_x, offset_y, indicator_width);
  1329.     }
  1330.     }
  1331.  
  1332.   if (redraw && bsp->redraw)
  1333.     {
  1334.       GdkRectangle area;
  1335.  
  1336.       area.x = col * bsp->cell_width + MARGIN_WIDTH;
  1337.       area.y = CLAMP (row * bsp->cell_height - bsp->scroll_offset +
  1338.               MARGIN_HEIGHT,
  1339.               0, bsp->preview->allocation.height);
  1340.       area.width  = cell_width;
  1341.       area.height = CLAMP (row * bsp->cell_height - bsp->scroll_offset +
  1342.                MARGIN_HEIGHT + cell_height,
  1343.                0, bsp->preview->allocation.height);
  1344.  
  1345.       gtk_widget_draw (bsp->preview, &area);
  1346.     }
  1347. }
  1348.  
  1349. static gint brush_counter = 0;
  1350.  
  1351. static void
  1352. do_display_brush (GimpBrush   *brush,
  1353.           BrushSelect *bsp)
  1354. {
  1355.   display_brush (bsp, brush,
  1356.          brush_counter % (bsp->NUM_BRUSH_COLUMNS),
  1357.          brush_counter / (bsp->NUM_BRUSH_COLUMNS),
  1358.          FALSE);
  1359.   brush_counter++;
  1360. }
  1361.  
  1362. static void
  1363. display_brushes (BrushSelect *bsp)
  1364. {
  1365.   if (brush_list == NULL || gimp_brush_list_length (brush_list) == 0)
  1366.     {
  1367.       gtk_widget_set_sensitive (bsp->options_box, FALSE);
  1368.       return;
  1369.     }
  1370.   else
  1371.     {
  1372.       gtk_widget_set_sensitive (bsp->options_box, TRUE);
  1373.     }
  1374.  
  1375.   /*  setup the display area  */
  1376.   display_setup (bsp);
  1377.  
  1378.   brush_counter = 0;
  1379.   gimp_list_foreach (GIMP_LIST (brush_list), (GFunc) do_display_brush, bsp);
  1380. }
  1381.  
  1382. static void
  1383. brush_select_show_selected (BrushSelect *bsp,
  1384.                 gint         row,
  1385.                 gint         col)
  1386. {
  1387.   GdkRectangle area;
  1388.   guchar *buf;
  1389.   gint yend;
  1390.   gint ystart;
  1391.   gint offset_x, offset_y;
  1392.   gint i;
  1393.  
  1394.   buf = g_new (guchar, 3 * bsp->cell_width);
  1395.  
  1396.   if (bsp->old_col != col || bsp->old_row != row)
  1397.     {
  1398.       /*  remove the old selection  */
  1399.       offset_x = bsp->old_col * bsp->cell_width;
  1400.       offset_y = bsp->old_row * bsp->cell_height - bsp->scroll_offset;
  1401.  
  1402.       ystart = CLAMP (offset_y , 0, bsp->preview->allocation.height);
  1403.       yend = CLAMP (offset_y + bsp->cell_height, 0, bsp->preview->allocation.height);
  1404.  
  1405.       /*  set the buf to white  */
  1406.       memset (buf, 255, 3 * bsp->cell_width);
  1407.  
  1408.       for (i = ystart; i < yend; i++)
  1409.     {
  1410.       if (i == offset_y || i == (offset_y + bsp->cell_height - 1))
  1411.         gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1412.                   offset_x, i, bsp->cell_width);
  1413.       else
  1414.         {
  1415.           gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1416.                     offset_x, i, 1);
  1417.           gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1418.                     offset_x + bsp->cell_width - 1, i, 1);
  1419.         }
  1420.     }
  1421.  
  1422.       if (bsp->redraw)
  1423.     {
  1424.       area.x = offset_x;
  1425.       area.y = ystart;
  1426.       area.width = bsp->cell_width;
  1427.       area.height = (yend - ystart);
  1428.       gtk_widget_draw (bsp->preview, &area);
  1429.     }
  1430.     }
  1431.  
  1432.   /*  make the new selection  */
  1433.   offset_x = col * bsp->cell_width;
  1434.   offset_y = row * bsp->cell_height - bsp->scroll_offset;
  1435.  
  1436.   ystart = CLAMP (offset_y , 0, bsp->preview->allocation.height);
  1437.   yend = CLAMP (offset_y + bsp->cell_height, 0, bsp->preview->allocation.height);
  1438.  
  1439.   /*  set the buf to black  */
  1440.   memset (buf, 0, bsp->cell_width * 3);
  1441.  
  1442.   for (i = ystart; i < yend; i++)
  1443.     {
  1444.       if (i == offset_y || i == (offset_y + bsp->cell_height - 1))
  1445.     gtk_preview_draw_row (GTK_PREVIEW (bsp->preview),
  1446.                   buf, offset_x, i, bsp->cell_width);
  1447.       else
  1448.     {
  1449.       gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1450.                 offset_x, i, 1);
  1451.       gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf,
  1452.                 offset_x + bsp->cell_width - 1, i, 1);
  1453.     }
  1454.     }
  1455.  
  1456.   if (bsp->redraw)
  1457.     {
  1458.       area.x = offset_x;
  1459.       area.y = ystart;
  1460.       area.width = bsp->cell_width;
  1461.       area.height = (yend - ystart);
  1462.       gtk_widget_draw (bsp->preview, &area);
  1463.     }
  1464.  
  1465.   bsp->old_row = row;
  1466.   bsp->old_col = col;
  1467.  
  1468.   g_free (buf);
  1469. }
  1470.  
  1471. static void
  1472. update_active_brush_field (BrushSelect *bsp)
  1473. {
  1474.   GimpBrush *brush;
  1475.   gchar buf[32];
  1476.  
  1477.   brush = gimp_context_get_brush (bsp->context);
  1478.  
  1479.   if (!brush)
  1480.     return;
  1481.  
  1482.   /*  Set brush name  */
  1483.   gtk_label_set_text (GTK_LABEL (bsp->brush_name), brush->name);
  1484.  
  1485.   /*  Set brush size  */
  1486.   g_snprintf (buf, sizeof (buf), "(%d x %d)",
  1487.           brush->mask->width, brush->mask->height);
  1488.   gtk_label_set_text (GTK_LABEL (bsp->brush_size), buf);
  1489.  
  1490.   /*  Set brush spacing  */
  1491.   gtk_adjustment_set_value (GTK_ADJUSTMENT (bsp->spacing_data),
  1492.                 gimp_brush_get_spacing (brush));
  1493. }
  1494.  
  1495. static void
  1496. preview_calc_scrollbar (BrushSelect *bsp)
  1497. {
  1498.   gint num_rows;
  1499.   gint page_size;
  1500.   gint max;
  1501.  
  1502.   bsp->scroll_offset = 0;
  1503.   num_rows = ((gimp_brush_list_length (brush_list) +
  1504.            (bsp->NUM_BRUSH_COLUMNS) - 1)
  1505.           / (bsp->NUM_BRUSH_COLUMNS));
  1506.   max = num_rows * bsp->cell_width;
  1507.   if (!num_rows)
  1508.     num_rows = 1;
  1509.   page_size = bsp->preview->allocation.height;
  1510.  
  1511.   bsp->sbar_data->value          = bsp->scroll_offset;
  1512.   bsp->sbar_data->upper          = max;
  1513.   bsp->sbar_data->page_size      = ((page_size < max) ? page_size : max);
  1514.   bsp->sbar_data->page_increment = (page_size >> 1);
  1515.   bsp->sbar_data->step_increment = bsp->cell_width;
  1516.  
  1517.   gtk_signal_emit_by_name (GTK_OBJECT (bsp->sbar_data), "changed");
  1518.   gtk_signal_emit_by_name (GTK_OBJECT (bsp->sbar_data), "value_changed");
  1519. }
  1520.  
  1521. static gint 
  1522. brush_select_resize (GtkWidget   *widget, 
  1523.              GdkEvent    *event, 
  1524.              BrushSelect *bsp)
  1525. {
  1526.   /*  calculate the best-fit approximation...  */  
  1527.   gint wid;
  1528.   gint now;
  1529.   gint cell_size;
  1530.  
  1531.   wid = widget->allocation.width;
  1532.  
  1533.   for (now = cell_size = MIN_CELL_SIZE;
  1534.        now < MAX_CELL_SIZE; ++now)
  1535.     {
  1536.       if ((wid % now) < (wid % cell_size)) cell_size = now;
  1537.       if ((wid % cell_size) == 0)
  1538.         break;
  1539.     }
  1540.  
  1541.    bsp->NUM_BRUSH_COLUMNS =
  1542.      (gint) (wid / cell_size);
  1543.    bsp->NUM_BRUSH_ROWS =
  1544.      (gint) ((gimp_brush_list_length (brush_list) + bsp->NUM_BRUSH_COLUMNS - 1) /
  1545.          bsp->NUM_BRUSH_COLUMNS);
  1546.  
  1547.    bsp->cell_width  = cell_size;
  1548.    bsp->cell_height = cell_size;
  1549.  
  1550.    /*  recalculate scrollbar extents  */
  1551.    preview_calc_scrollbar (bsp);
  1552.  
  1553.    return FALSE;
  1554. }
  1555.  
  1556. static gint
  1557. brush_select_events (GtkWidget   *widget,
  1558.              GdkEvent    *event,
  1559.              BrushSelect *bsp)
  1560. {
  1561.   GdkEventButton *bevent;
  1562.   GimpBrush *brush;
  1563.   gint row, col, index;
  1564.  
  1565.   switch (event->type)
  1566.     {
  1567.     case GDK_EXPOSE:
  1568.       break;
  1569.  
  1570.     case GDK_2BUTTON_PRESS:
  1571.       bevent = (GdkEventButton *) event;
  1572.       col = bevent->x / bsp->cell_width;
  1573.       row = (bevent->y + bsp->scroll_offset) / bsp->cell_height;
  1574.       index = row * bsp->NUM_BRUSH_COLUMNS + col;
  1575.       
  1576.       /*  Get the brush and check if it is editable  */
  1577.       brush = gimp_brush_list_get_brush_by_index (brush_list, index);
  1578.       if (GIMP_IS_BRUSH_GENERATED (brush))
  1579.     brush_select_edit_brush_callback (NULL, bsp);
  1580.       break;
  1581.  
  1582.     case GDK_BUTTON_PRESS:
  1583.       bevent = (GdkEventButton *) event;
  1584.  
  1585.       col = bevent->x / bsp->cell_width;
  1586.       row = (bevent->y + bsp->scroll_offset) / bsp->cell_height;
  1587.       index = row * bsp->NUM_BRUSH_COLUMNS + col;
  1588.  
  1589.       brush = gimp_brush_list_get_brush_by_index (brush_list, index);
  1590.  
  1591.       if (brush)
  1592.     bsp->dnd_brush = brush;
  1593.       else
  1594.     bsp->dnd_brush = gimp_context_get_brush (bsp->context);
  1595.  
  1596.       if (bevent->button == 1)
  1597.     {
  1598.       /*  Get the brush and display the popup brush preview  */
  1599.       if (brush)
  1600.         {
  1601.           gdk_pointer_grab (bsp->preview->window, FALSE,
  1602.                 (GDK_POINTER_MOTION_HINT_MASK |
  1603.                  GDK_BUTTON1_MOTION_MASK |
  1604.                  GDK_BUTTON_RELEASE_MASK),
  1605.                 NULL, NULL, bevent->time);
  1606.  
  1607.           /*  Make this brush the active brush  */
  1608.           gimp_context_set_brush (bsp->context, brush);
  1609.  
  1610.           /*  only if dialog is main one        */
  1611.           if (bsp == brush_select_dialog &&
  1612.           brush_edit_generated_dialog)
  1613.         {
  1614.           brush_edit_generated_set_brush (brush_edit_generated_dialog,
  1615.                           brush);
  1616.         }
  1617.           
  1618.           /*  Show the brush popup window if the brush is too large  */
  1619.           if (brush->mask->width  > bsp->cell_width - 2 * MARGIN_WIDTH ||
  1620.           brush->mask->height > bsp->cell_height - 2 * MARGIN_HEIGHT ||
  1621.           GIMP_IS_BRUSH_PIPE (brush))
  1622.         {
  1623.           brush_popup_open (bsp, bevent->x, bevent->y, brush);
  1624.         }
  1625.         }
  1626.     }
  1627.  
  1628.       /*  wheelmouse support  */
  1629.       else if (bevent->button == 4)
  1630.     {
  1631.       GtkAdjustment *adj = bsp->sbar_data;
  1632.       gfloat new_value = adj->value - adj->page_increment / 2;
  1633.       new_value =
  1634.         CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
  1635.       gtk_adjustment_set_value (adj, new_value);
  1636.     }
  1637.       else if (bevent->button == 5)
  1638.     {
  1639.       GtkAdjustment *adj = bsp->sbar_data;
  1640.       gfloat new_value = adj->value + adj->page_increment / 2;
  1641.       new_value =
  1642.         CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
  1643.       gtk_adjustment_set_value (adj, new_value);
  1644.     }
  1645.  
  1646.       break;
  1647.  
  1648.     case GDK_BUTTON_RELEASE:
  1649.       bevent = (GdkEventButton *) event;
  1650.  
  1651.       if (bevent->button == 1)
  1652.     {
  1653.       /*  Ungrab the pointer  */
  1654.       gdk_pointer_ungrab (bevent->time);
  1655.  
  1656.       /*  Close the brush popup window  */
  1657.       brush_popup_close (bsp);
  1658.     }
  1659.       break;
  1660.  
  1661.     case GDK_DELETE:
  1662.       /* g_warning ("test"); */
  1663.       break;
  1664.  
  1665.     default:
  1666.       break;
  1667.     }
  1668.  
  1669.   return FALSE;
  1670. }
  1671.  
  1672. /*  Disabled until I've figured out how gtk window resizing *really* works.
  1673.  *  I don't think that the function below is the correct way to do it
  1674.  *    --  Michael
  1675.  *
  1676. static void
  1677. brush_select_map_callback (GtkWidget   *widget,
  1678.                BrushSelect *bsp)
  1679. {
  1680.   GtkAllocation allocation;
  1681.   gint xdiff, ydiff;
  1682.  
  1683.   xdiff =
  1684.     bsp->shell->allocation.width - bsp->preview->allocation.width;
  1685.   ydiff =
  1686.     bsp->shell->allocation.height - bsp->preview->allocation.height;
  1687.  
  1688.   allocation = bsp->shell->allocation;
  1689.   allocation.width = brush_select_session_info.width + xdiff;
  1690.   allocation.height = brush_select_session_info.height + ydiff;
  1691.  
  1692.   gtk_widget_size_allocate (bsp->shell, &allocation);
  1693. }
  1694. */
  1695.  
  1696. static void
  1697. brush_select_scroll_update (GtkAdjustment *adjustment,
  1698.                 gpointer       data)
  1699. {
  1700.   BrushSelect *bsp;
  1701.   GimpBrush *active;
  1702.   gint row, col, index;
  1703.  
  1704.   bsp = (BrushSelect *) data;
  1705.  
  1706.   if (bsp)
  1707.     {
  1708.       bsp->scroll_offset = adjustment->value;
  1709.  
  1710.       display_brushes (bsp);
  1711.  
  1712.       active = gimp_context_get_brush (bsp->context);
  1713.  
  1714.       if (active)
  1715.     {
  1716.       index = gimp_brush_list_get_brush_index (brush_list, active);
  1717.       if (index < 0)
  1718.         return;
  1719.       row = index / bsp->NUM_BRUSH_COLUMNS;
  1720.       col = index - row * bsp->NUM_BRUSH_COLUMNS;
  1721.  
  1722.       brush_select_show_selected (bsp, row, col);
  1723.     }
  1724.  
  1725.       if (bsp->redraw)
  1726.     gtk_widget_draw (bsp->preview, NULL);
  1727.     }
  1728. }
  1729.  
  1730. static void
  1731. opacity_scale_update (GtkAdjustment *adjustment,
  1732.               gpointer       data)
  1733. {
  1734.   BrushSelect *bsp;
  1735.  
  1736.   bsp = (BrushSelect *) data;
  1737.  
  1738.   gtk_signal_handler_block_by_data (GTK_OBJECT (bsp->context), data);
  1739.   gimp_context_set_opacity (bsp->context, adjustment->value / 100.0);
  1740.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (bsp->context), data);
  1741. }
  1742.  
  1743. static void
  1744. paint_mode_menu_callback (GtkWidget *widget,
  1745.               gpointer   data)
  1746. {
  1747.   LayerModeEffects  paint_mode;
  1748.   BrushSelect      *bsp;
  1749.  
  1750.   paint_mode = (LayerModeEffects) gtk_object_get_user_data (GTK_OBJECT (widget));
  1751.   bsp = (BrushSelect *) data;
  1752.  
  1753.   gimp_context_set_paint_mode (((BrushSelect *) data)->context, paint_mode);
  1754. }
  1755.  
  1756. static void
  1757. spacing_scale_update (GtkAdjustment *adjustment,
  1758.               gpointer       data)
  1759. {
  1760.   BrushSelect *bsp;
  1761.  
  1762.   bsp = (BrushSelect *) data;
  1763.  
  1764.   if (bsp == brush_select_dialog)
  1765.     {
  1766.       gimp_brush_set_spacing (gimp_context_get_brush (bsp->context),
  1767.                   (gint) adjustment->value);
  1768.     }
  1769.   else
  1770.     {
  1771.       if (bsp->spacing_value != adjustment->value)
  1772.     {
  1773.       bsp->spacing_value = adjustment->value;
  1774.       brush_change_callbacks (bsp, FALSE);
  1775.     }
  1776.     }
  1777. }
  1778.  
  1779. static void
  1780. brush_select_close_callback (GtkWidget *widget,
  1781.                  gpointer   data)
  1782. {
  1783.   BrushSelect *bsp;
  1784.  
  1785.   bsp = (BrushSelect *) data;
  1786.  
  1787.   if (GTK_WIDGET_VISIBLE (bsp->shell))
  1788.     gtk_widget_hide (bsp->shell);
  1789.  
  1790.   /* Free memory if poping down dialog which is not the main one */
  1791.   if (bsp != brush_select_dialog)
  1792.     {
  1793.       /* Send data back */
  1794.       brush_change_callbacks (bsp, TRUE);
  1795.       gtk_widget_destroy (bsp->shell); 
  1796.       brush_select_free (bsp); 
  1797.     }
  1798. }
  1799.  
  1800. static void
  1801. brush_select_refresh_callback (GtkWidget *widget,
  1802.                    gpointer   data)
  1803. {
  1804.   /*  re-init the brush list  */
  1805.   brushes_init (FALSE);
  1806. }
  1807.  
  1808. static void
  1809. brush_select_new_brush_callback (GtkWidget *widget,
  1810.                  gpointer   data)
  1811. {
  1812.   GimpBrush *brush;
  1813.   BrushSelect *bsp;
  1814.  
  1815.   bsp = (BrushSelect *) data;
  1816.  
  1817.   brush = gimp_brush_generated_new (10, .5, 0.0, 1.0);
  1818.   if (brush)
  1819.     {
  1820.       gimp_brush_list_add (brush_list, brush);
  1821.  
  1822.       gimp_context_set_brush (bsp->context, brush);
  1823.  
  1824.       if (brush_edit_generated_dialog)
  1825.     brush_edit_generated_set_brush (brush_edit_generated_dialog, brush);
  1826.     }
  1827.  
  1828.   brush_select_edit_brush_callback (widget, data);
  1829. }
  1830.  
  1831. static void
  1832. brush_select_edit_brush_callback (GtkWidget *widget,
  1833.                   gpointer   data)
  1834. {
  1835.   BrushSelect *bsp;
  1836.   GimpBrush *brush;
  1837.  
  1838.   bsp = (BrushSelect *) data;
  1839.   brush = gimp_context_get_brush (bsp->context);
  1840.  
  1841.   if (GIMP_IS_BRUSH_GENERATED (brush))
  1842.     {
  1843.       if (!brush_edit_generated_dialog)
  1844.     {
  1845.       /*  Create the dialog...  */
  1846.       brush_edit_generated_dialog = brush_edit_generated_new ();
  1847.       brush_edit_generated_set_brush (brush_edit_generated_dialog, brush);
  1848.     }
  1849.       else
  1850.     {
  1851.       /*  Popup the dialog  */
  1852.       if (!GTK_WIDGET_VISIBLE (brush_edit_generated_dialog->shell))
  1853.         gtk_widget_show (brush_edit_generated_dialog->shell);
  1854.       else
  1855.         gdk_window_raise (brush_edit_generated_dialog->shell->window);
  1856.     }
  1857.     }
  1858.   else
  1859.     /* this should never happen */
  1860.     g_message (_("Sorry, this brush can't be edited."));
  1861. }
  1862.  
  1863. static void
  1864. brush_select_delete_brush_callback (GtkWidget *widget,
  1865.                     gpointer   data)
  1866. {
  1867.   BrushSelect *bsp;
  1868.   GimpBrush *brush;
  1869.  
  1870.   bsp = (BrushSelect *) data;
  1871.   brush = gimp_context_get_brush (bsp->context);
  1872.  
  1873.   if (GIMP_IS_BRUSH_GENERATED (brush))
  1874.     {
  1875.       gint index;
  1876.  
  1877.       gimp_brush_generated_delete (GIMP_BRUSH_GENERATED (brush));
  1878.  
  1879.       brush_select_freeze_all ();
  1880.  
  1881.       index = gimp_brush_list_get_brush_index (brush_list, brush);
  1882.       gimp_brush_list_remove (brush_list, GIMP_BRUSH (brush));
  1883.       gimp_context_refresh_brushes ();
  1884.  
  1885.       brush_select_thaw_all ();
  1886.     }
  1887.   else
  1888.     /* this should never happen */
  1889.     g_message (_("Sorry, this brush can't be deleted."));
  1890. }
  1891.