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

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  * Copyright (C) 1998 Andy Thomas.
  4.  *
  5.  * Gradient editor module copyight (C) 1996-1997 Federico Mena Quintero
  6.  * federico@nuclecu.unam.mx
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURIGHTE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. /* This is the popup for the gradient selection stuff..
  24.  * idea is a cut down version of the gradient selection widget 
  25.  * just a clist on which each gradient can be selected. 
  26.  * Of course all the support functions for getting the slected gradient and
  27.  * setting the slection all need to be done as well.
  28.  */
  29.  
  30. /* Main structure for the dialog. There can be multiple of these 
  31.  * so every thing has to go into the strcuture and we have to have a list 
  32.  * the structures so we can find which one we are taking about.
  33.  */
  34.  
  35. #include "config.h"
  36.  
  37. #include <string.h>
  38.  
  39. #include <gtk/gtk.h>
  40.  
  41. #include "apptypes.h"
  42.  
  43. #include "appenv.h"
  44. #include "dialog_handler.h"
  45. #include "gimpcontext.h"
  46. #include "gimpdnd.h"
  47. #include "gimpui.h"
  48. #include "gradient_header.h"
  49. #include "gradientP.h"
  50. #include "gradient_select.h"
  51. #include "session.h"
  52.  
  53. #include "config.h"
  54. #include "libgimp/gimpintl.h"
  55.  
  56. static void gradient_change_callbacks            (GradientSelect *gsp,
  57.                           gboolean        closing);
  58. static gradient_t* gradient_select_drag_gradient (GtkWidget      *widget,
  59.                               gpointer        data);
  60. static void gradient_select_drop_gradient        (GtkWidget      *widget,
  61.                           gradient_t     *gradient,
  62.                           gpointer        data);
  63. static void gradient_select_gradient_changed     (GimpContext    *context,
  64.                           gradient_t     *gradient,
  65.                           GradientSelect *gsp);
  66. static void gradient_select_select               (GradientSelect *gsp,
  67.                           gradient_t     *gradient);
  68.  
  69. static gint gradient_select_button_press         (GtkWidget      *widget,
  70.                           GdkEventButton *bevent,
  71.                           gpointer        data);
  72. static void gradient_select_list_item_update     (GtkWidget      *widget, 
  73.                           gint            row,
  74.                           gint            column,
  75.                           GdkEventButton *event,
  76.                           gpointer        data);
  77.  
  78. static void gradient_select_close_callback       (GtkWidget      *widget,
  79.                           gpointer        data);
  80. static void gradient_select_edit_callback        (GtkWidget      *widget,
  81.                           gpointer        data);
  82.  
  83. /*  dnd stuff  */
  84. static GtkTargetEntry clist_target_table[] =
  85. {
  86.   GIMP_TARGET_GRADIENT
  87. };
  88. static guint clist_n_targets = (sizeof (clist_target_table) /
  89.                 sizeof (clist_target_table[0]));
  90.  
  91. /*  list of active dialogs   */
  92. GSList         *gradient_active_dialogs = NULL;
  93.  
  94. /*  the main gradient selection dialog  */
  95. GradientSelect *gradient_select_dialog  = NULL;
  96.  
  97.  
  98. void
  99. gradient_dialog_create (void)
  100. {
  101.   if (! gradient_select_dialog)
  102.     {
  103.       gradient_select_dialog = gradient_select_new (NULL, NULL);
  104.     }
  105.   else
  106.     {
  107.       if (!GTK_WIDGET_VISIBLE (gradient_select_dialog->shell))
  108.     gtk_widget_show (gradient_select_dialog->shell);
  109.       else
  110.     gdk_window_raise (gradient_select_dialog->shell->window);
  111.     }
  112. }
  113.  
  114. void
  115. gradient_dialog_free (void)
  116. {
  117.   if (gradient_select_dialog)
  118.     {
  119.       session_get_window_info (gradient_select_dialog->shell,
  120.                    &gradient_select_session_info);
  121.  
  122.       gradient_select_free (gradient_select_dialog);
  123.       gradient_select_dialog = NULL;
  124.  
  125.     }
  126.  
  127.   gradient_editor_free ();
  128. }
  129.  
  130. /*  If title == NULL then it is the main gradient select dialog  */
  131. GradientSelect *
  132. gradient_select_new (gchar *title,
  133.              gchar *initial_gradient)
  134. {
  135.   GradientSelect  *gsp;
  136.   GtkWidget       *vbox;
  137.   GtkWidget       *scrolled_win;
  138.   GdkColormap     *colormap;
  139.   gchar           *titles[2];
  140.   gint             column_width;
  141.   gint             select_pos;
  142.  
  143.   gradient_t      *active = NULL;
  144.  
  145.   static gboolean  first_call = TRUE;
  146.  
  147.   gsp = g_new (GradientSelect, 1);
  148.   gsp->callback_name = NULL;
  149.   gsp->dnd_gradient = NULL;
  150.   
  151.   /*  The shell  */
  152.   gsp->shell = gimp_dialog_new (title ? title : _("Gradient Selection"),
  153.                 "gradient_selection",
  154.                 gimp_standard_help_func,
  155.                 "dialogs/gradient_selection.html",
  156.                 title ? GTK_WIN_POS_MOUSE : GTK_WIN_POS_NONE,
  157.                 FALSE, TRUE, FALSE,
  158.  
  159.                 _("Edit"), gradient_select_edit_callback,
  160.                 gsp, NULL, NULL, FALSE, FALSE,
  161.                 _("Close"), gradient_select_close_callback,
  162.                 gsp, NULL, NULL, TRUE, TRUE,
  163.  
  164.                 NULL);
  165.  
  166.   if (title)
  167.     {
  168.       gsp->context = gimp_context_new (title, NULL);
  169.     }
  170.   else
  171.     {
  172.       gsp->context = gimp_context_get_user ();
  173.  
  174.       session_set_window_geometry (gsp->shell, &gradient_select_session_info,
  175.                    TRUE);
  176.       dialog_register (gsp->shell);
  177.     }
  178.  
  179.   if (no_data && first_call)
  180.     gradients_init (FALSE);
  181.  
  182.   first_call = FALSE;
  183.  
  184.   if (title && initial_gradient && strlen (initial_gradient))
  185.     {
  186.       active = gradient_list_get_gradient (gradients_list, initial_gradient);
  187.     }
  188.   else
  189.     {
  190.       active = gimp_context_get_gradient (gimp_context_get_user ());
  191.     }
  192.  
  193.   if (!active)
  194.     {
  195.       active = gimp_context_get_gradient (gimp_context_get_standard ());
  196.     }
  197.  
  198.   if (title)
  199.     {
  200.       gimp_context_set_gradient (gsp->context, active);
  201.     }
  202.  
  203.   vbox = gtk_vbox_new (FALSE, 0);
  204.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  205.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (gsp->shell)->vbox), vbox);
  206.  
  207.   /*  clist preview of gradients  */
  208.   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  209.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
  210.                   GTK_POLICY_AUTOMATIC,
  211.                   GTK_POLICY_ALWAYS);
  212.   gtk_container_add (GTK_CONTAINER (vbox), scrolled_win);
  213.   gtk_widget_show (scrolled_win);
  214.  
  215.   titles[0] = _("Gradient");
  216.   titles[1] = _("Name");
  217.   gsp->clist = gtk_clist_new_with_titles (2, titles);
  218.   gtk_clist_set_shadow_type (GTK_CLIST (gsp->clist), GTK_SHADOW_IN);
  219.   gtk_clist_set_selection_mode (GTK_CLIST (gsp->clist), GTK_SELECTION_BROWSE);
  220.   gtk_clist_set_row_height (GTK_CLIST (gsp->clist), 18);
  221.   gtk_clist_set_use_drag_icons (GTK_CLIST (gsp->clist), FALSE);
  222.   gtk_clist_column_titles_passive (GTK_CLIST (gsp->clist));
  223.   gtk_widget_set_usize (gsp->clist, 200, 250);
  224.   gtk_container_add (GTK_CONTAINER (scrolled_win), gsp->clist);
  225.  
  226.   column_width =
  227.     MAX (50, gtk_clist_optimal_column_width (GTK_CLIST (gsp->clist), 0));
  228.   gtk_clist_set_column_min_width (GTK_CLIST (gsp->clist), 0, 50);
  229.   gtk_clist_set_column_width (GTK_CLIST (gsp->clist), 0, column_width);
  230.  
  231.   gtk_widget_show (gsp->clist);
  232.  
  233.   colormap = gtk_widget_get_colormap (gsp->clist);
  234.   gdk_color_parse ("black", &gsp->black);
  235.   gdk_color_alloc (colormap, &gsp->black);
  236.  
  237.   gtk_widget_realize (gsp->shell);
  238.   gsp->gc = gdk_gc_new (gsp->shell->window);
  239.  
  240.   select_pos = gradient_clist_init (gsp->shell, gsp->gc, gsp->clist, active);
  241.  
  242.   /* Now show the dialog */
  243.   gtk_widget_show (vbox);
  244.   gtk_widget_show (gsp->shell);
  245.  
  246.   gtk_signal_connect (GTK_OBJECT (gsp->clist), "button_press_event",
  247.               GTK_SIGNAL_FUNC (gradient_select_button_press),
  248.               (gpointer) gsp);
  249.  
  250.   gtk_signal_connect (GTK_OBJECT (gsp->clist), "select_row",
  251.               GTK_SIGNAL_FUNC (gradient_select_list_item_update),
  252.               (gpointer) gsp);
  253.  
  254.   gtk_signal_connect (GTK_OBJECT (gsp->context), "gradient_changed",
  255.                       GTK_SIGNAL_FUNC (gradient_select_gradient_changed),
  256.                       (gpointer) gsp);
  257.  
  258.   /*  dnd stuff  */
  259.   gtk_drag_source_set (gsp->clist,
  260.                GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  261.                clist_target_table, clist_n_targets,
  262.                GDK_ACTION_COPY);
  263.   gimp_dnd_gradient_source_set (gsp->clist, gradient_select_drag_gradient, gsp);
  264.  
  265.   gtk_drag_dest_set (gsp->clist,
  266.                      GTK_DEST_DEFAULT_ALL,
  267.                      clist_target_table, clist_n_targets,
  268.                      GDK_ACTION_COPY);
  269.   gimp_dnd_gradient_dest_set (gsp->clist, gradient_select_drop_gradient, gsp);
  270.  
  271.   if (active)
  272.     gradient_select_select (gsp, active);
  273.  
  274.   /*  Add to active gradient dialogs list  */
  275.   gradient_active_dialogs = g_slist_append (gradient_active_dialogs, gsp);
  276.  
  277.   return gsp;
  278. }
  279.  
  280. void
  281. gradient_select_free (GradientSelect *gsp)
  282. {
  283.   if (!gsp)
  284.     return;
  285.  
  286.   /* remove from active list */
  287.   gradient_active_dialogs = g_slist_remove (gradient_active_dialogs, gsp);
  288.  
  289.   gtk_signal_disconnect_by_data (GTK_OBJECT (gsp->context), gsp);
  290.  
  291.   if (gsp->callback_name)
  292.     { 
  293.       g_free (gsp->callback_name);
  294.       gtk_object_unref (GTK_OBJECT (gsp->context));
  295.     }
  296.  
  297.    g_free (gsp);
  298. }
  299.  
  300. /*  Call this dialog's PDB callback  */
  301.  
  302. static void
  303. gradient_change_callbacks (GradientSelect *gsp,
  304.                gboolean        closing)
  305. {
  306.   gchar           *name;
  307.   ProcRecord      *prec = NULL;
  308.   gradient_t      *gradient;
  309.   gint             nreturn_vals;
  310.   static gboolean  busy = FALSE;
  311.  
  312.   /* Any procs registered to callback? */
  313.   Argument *return_vals; 
  314.  
  315.   if (!gsp || !gsp->callback_name || busy != 0)
  316.     return;
  317.  
  318.   busy = TRUE;
  319.   name = gsp->callback_name;
  320.   gradient = gimp_context_get_gradient (gsp->context);
  321.  
  322.   /*  If its still registered run it  */
  323.   prec = procedural_db_lookup (name);
  324.  
  325.   if (prec && gradient)
  326.     {
  327.       gdouble  *values, *pv;
  328.       double    pos, delta;
  329.       double    r, g, b, a;
  330.       gint i = gsp->sample_size;
  331.       pos    = 0.0;
  332.       delta  = 1.0 / (i - 1);
  333.       
  334.       values = g_new (gdouble, 4 * i);
  335.       pv     = values;
  336.  
  337.       while (i--)
  338.     {
  339.       gradient_get_color_at (gradient, pos, &r, &g, &b, &a);
  340.  
  341.       *pv++ = r;
  342.       *pv++ = g;
  343.       *pv++ = b;
  344.       *pv++ = a;
  345.  
  346.       pos += delta;
  347.     }
  348.  
  349.       return_vals = procedural_db_run_proc (name,
  350.                         &nreturn_vals,
  351.                         PDB_STRING,     gradient->name,
  352.                         PDB_INT32,      gsp->sample_size * 4,
  353.                         PDB_FLOATARRAY, values,
  354.                         PDB_INT32,      (gint) closing,
  355.                         PDB_END);
  356.  
  357.       if (!return_vals || return_vals[0].value.pdb_int != PDB_SUCCESS)
  358.     g_message ("failed to run gradient callback function");
  359.       else
  360.     procedural_db_destroy_args (return_vals, nreturn_vals);
  361.     }
  362.   busy = FALSE;
  363. }
  364.  
  365. /*  Close active dialogs that no longer have PDB registered for them  */
  366.  
  367. void
  368. gradients_check_dialogs (void)
  369. {
  370.   GradientSelect *gsp;
  371.   GSList         *list;
  372.   gchar          *name;
  373.   ProcRecord     *prec = NULL;
  374.  
  375.   list = gradient_active_dialogs;
  376.  
  377.   while (list)
  378.     {
  379.       gsp = (GradientSelect *) list->data;
  380.       list = g_slist_next (list);
  381.  
  382.       name = gsp->callback_name;
  383.  
  384.       if (name)
  385.     {
  386.       prec = procedural_db_lookup (name);
  387.  
  388.       if (!prec)
  389.         {
  390.           /*  Can alter gradient_active_dialogs list  */
  391.           gradient_select_close_callback (NULL, gsp); 
  392.         }
  393.     }
  394.     }
  395. }
  396.  
  397. void
  398. gradient_select_rename_all (gradient_t *gradient)
  399. {
  400.   GradientSelect *gsp; 
  401.   GSList         *list;
  402.   gint            row;
  403.  
  404.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  405.     {
  406.       gsp = (GradientSelect *) list->data;
  407.  
  408.       row = gtk_clist_find_row_from_data (GTK_CLIST (gsp->clist), gradient);
  409.       if (row > -1)
  410.     gtk_clist_set_text (GTK_CLIST (gsp->clist), row, 1, gradient->name);  
  411.     }
  412. }
  413.  
  414. void
  415. gradient_select_insert_all (gint        pos,
  416.                 gradient_t *gradient)
  417. {
  418.   GradientSelect *gsp; 
  419.   GSList         *list;
  420.  
  421.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  422.     {
  423.       gsp = (GradientSelect *) list->data;
  424.  
  425.       gtk_clist_freeze (GTK_CLIST (gsp->clist));
  426.       gradient_clist_insert (gsp->shell, gsp->gc, gsp->clist,
  427.                  gradient, pos, FALSE);
  428.       gtk_clist_thaw (GTK_CLIST (gsp->clist));
  429.     }
  430. }
  431.  
  432. void
  433. gradient_select_delete_all (gradient_t *gradient)
  434. {
  435.   GradientSelect *gsp; 
  436.   GSList         *list;
  437.   gint            row;
  438.  
  439.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  440.     {
  441.       gsp = (GradientSelect *) list->data;
  442.       
  443.       row = gtk_clist_find_row_from_data (GTK_CLIST (gsp->clist), gradient);
  444.       if (row > -1)
  445.     gtk_clist_remove (GTK_CLIST (gsp->clist), row);
  446.     }
  447. }
  448.  
  449. void
  450. gradient_select_free_all (void)
  451. {
  452.   GradientSelect *gsp; 
  453.   GSList *list;
  454.  
  455.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  456.     {
  457.       gsp = (GradientSelect *) list->data;
  458.  
  459.       gtk_clist_clear (GTK_CLIST (gsp->clist));
  460.     }
  461. }
  462.  
  463. void
  464. gradient_select_refill_all (void)
  465. {
  466.   GradientSelect *gsp;
  467.   GSList         *list;
  468.   gint            index = -1;
  469.  
  470.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  471.     {
  472.       gsp = (GradientSelect *) list->data;
  473.  
  474.       index = gradient_clist_init (gsp->shell, gsp->gc, gsp->clist, 
  475.                    gimp_context_get_gradient (gsp->context));
  476.  
  477.       if (index != -1)
  478.     gradient_select_select (gsp, gimp_context_get_gradient (gsp->context));
  479.     }
  480. }
  481.  
  482. void
  483. gradient_select_update_all (gradient_t *gradient)
  484. {
  485.   GSList         *list;
  486.   GradientSelect *gsp; 
  487.   gint            row;
  488.   
  489.   for (list = gradient_active_dialogs; list; list = g_slist_next (list))
  490.     {
  491.       gsp = (GradientSelect *) list->data;
  492.  
  493.       row = gtk_clist_find_row_from_data (GTK_CLIST (gsp->clist), gradient);
  494.       if (row > -1)
  495.     gtk_clist_set_text (GTK_CLIST (gsp->clist), row, 1, gradient->name);  
  496.     }
  497. }
  498.  
  499. /*
  500.  *  Local functions
  501.  */
  502.  
  503. static gradient_t *
  504. gradient_select_drag_gradient (GtkWidget  *widget,
  505.                    gpointer    data)
  506. {
  507.   GradientSelect *gsp;
  508.  
  509.   gsp = (GradientSelect *) data;
  510.  
  511.   return gsp->dnd_gradient;
  512. }
  513.  
  514. static void
  515. gradient_select_drop_gradient (GtkWidget  *widget,
  516.                    gradient_t *gradient,
  517.                    gpointer    data)
  518. {
  519.   GradientSelect *gsp;
  520.  
  521.   gsp = (GradientSelect *) data;
  522.  
  523.   gimp_context_set_gradient (gsp->context, gradient);
  524. }
  525.  
  526. static void
  527. gradient_select_gradient_changed (GimpContext    *context,
  528.                   gradient_t     *gradient,
  529.                   GradientSelect *gsp)
  530. {
  531.   if (gradient)
  532.     {
  533.       gradient_select_select (gsp, gradient);
  534.  
  535.       if (gsp->callback_name)
  536.     gradient_change_callbacks (gsp, FALSE);
  537.  
  538.       gsp->dnd_gradient = gradient;
  539.     }
  540. }
  541.  
  542. static void
  543. gradient_select_select (GradientSelect *gsp,
  544.             gradient_t     *gradient)
  545. {
  546.   gint index;
  547.  
  548.   index = gradient_list_get_gradient_index (gradients_list, gradient);
  549.  
  550.   if (index != -1)
  551.     {
  552.       gtk_signal_handler_block_by_data (GTK_OBJECT (gsp->clist), gsp);
  553.  
  554.       gtk_clist_select_row (GTK_CLIST (gsp->clist), index, -1);
  555.       gtk_clist_moveto (GTK_CLIST (gsp->clist), index, 0, 0.5, 0.0);
  556.  
  557.       gtk_signal_handler_unblock_by_data (GTK_OBJECT (gsp->clist), gsp);
  558.     }
  559. }
  560.  
  561. static gint
  562. gradient_select_button_press (GtkWidget      *widget,
  563.                   GdkEventButton *bevent,
  564.                   gpointer        data)
  565. {
  566.   GradientSelect *gsp;
  567.  
  568.   gsp = (GradientSelect *) data;
  569.  
  570.   if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS)
  571.     {
  572.       gradient_select_edit_callback (widget, data);
  573.  
  574.       return TRUE;
  575.     }
  576.  
  577.   if (bevent->button == 2)
  578.     {
  579.       GSList *list = NULL;
  580.       gint row;
  581.       gint column;
  582.  
  583.       gtk_clist_get_selection_info (GTK_CLIST (gsp->clist),
  584.                     bevent->x, bevent->y,
  585.                     &row, &column);
  586.  
  587.       if (gradients_list)
  588.     list = g_slist_nth (gradients_list, row);
  589.  
  590.       if (list)
  591.     gsp->dnd_gradient = (gradient_t *) list->data;
  592.       else
  593.     gsp->dnd_gradient = NULL;
  594.  
  595.       return TRUE;
  596.     }
  597.  
  598.   return FALSE;
  599. }
  600.  
  601. static void
  602. gradient_select_list_item_update (GtkWidget      *widget, 
  603.                   gint            row,
  604.                   gint            column,
  605.                   GdkEventButton *event,
  606.                   gpointer        data)
  607. {
  608.   GradientSelect *gsp;
  609.   GSList *list;
  610.  
  611.   gsp  = (GradientSelect *) data;
  612.   list = g_slist_nth (gradients_list, row);
  613.  
  614.   gtk_signal_handler_block_by_data (GTK_OBJECT (gsp->context), gsp);
  615.  
  616.   gimp_context_set_gradient (gsp->context, (gradient_t *) list->data);
  617.  
  618.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (gsp->context), gsp);
  619.  
  620.   gsp->dnd_gradient = (gradient_t *) list->data;
  621.  
  622.   if (gsp->callback_name)
  623.     gradient_change_callbacks (gsp, FALSE);
  624. }
  625.  
  626. static void
  627. gradient_select_edit_callback (GtkWidget *widget,
  628.                    gpointer   data)
  629. {
  630.   GradientSelect *gsp;
  631.  
  632.   gsp = (GradientSelect *) data;
  633.  
  634.   gradient_editor_create ();
  635.  
  636.   if (gsp)
  637.     gradient_editor_set_gradient (gimp_context_get_gradient (gsp->context));
  638. }
  639.  
  640. static void
  641. gradient_select_close_callback (GtkWidget *widget,
  642.                 gpointer   data)
  643. {
  644.   GradientSelect *gsp;
  645.  
  646.   gsp = (GradientSelect *) data;
  647.  
  648.   if (GTK_WIDGET_VISIBLE (gsp->shell))
  649.     gtk_widget_hide (gsp->shell);
  650.  
  651.   /* Free memory if poping down dialog which is not the main one */
  652.   if (gsp != gradient_select_dialog)
  653.     {
  654.       gradient_change_callbacks (gsp, TRUE);
  655.       gtk_widget_destroy (gsp->shell);
  656.       gradient_select_free (gsp);
  657.     }
  658. }
  659.