home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / libgimp / gimpgradientmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-06  |  7.6 KB  |  283 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * gimpgradientmenu.c
  5.  * Copyright (C) 1998 Andy Thomas                
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the
  19.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20.  * Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. #include <string.h>
  24.  
  25. #include "gimp.h"
  26. #include "gimpui.h"
  27.  
  28.  
  29. /* Idea is to have a function to call that returns a widget that 
  30.  * completely controls the selection of a gradient.
  31.  * you get a widget returned that you can use in a table say.
  32.  * In:- Initial gradient name. Null means use current selection.
  33.  *      pointer to func to call when gradient changes (GimpRunGradientCallback).
  34.  * Returned:- Pointer to a widget that you can use in UI.
  35.  * 
  36.  * Widget simply made up of a preview widget (20x40) containing the gradient
  37.  * which can be clicked on to changed the gradient selection.
  38.  */
  39.  
  40.  
  41. #define GSEL_DATA_KEY     "__gsel_data"
  42. #define CELL_SIZE_HEIGHT  18
  43. #define CELL_SIZE_WIDTH   84
  44.  
  45.  
  46. struct __gradients_sel 
  47. {
  48.   gchar                   *dname;
  49.   GimpRunGradientCallback  cback;
  50.   GtkWidget               *gradient_preview;
  51.   GtkWidget               *button;
  52.   gchar                   *gradient_popup_pnt;
  53.   gint                     width;
  54.   gchar                   *gradient_name;      /* Local copy */
  55.   gdouble                 *grad_data;          /* local copy */
  56.   gint                     sample_size;
  57.   gpointer                 data;
  58. }; 
  59.  
  60. typedef struct __gradients_sel GSelect;
  61.  
  62. static void
  63. gradient_pre_update (GtkWidget *gradient_preview,
  64.              gint       width_data,
  65.              gdouble   *grad_data)
  66. {
  67.   gint     x;
  68.   gint     y;
  69.   gdouble *src;
  70.   gdouble  r, g, b, a;
  71.   gdouble  c0, c1;
  72.   guchar  *p0;
  73.   guchar  *p1;
  74.   guchar  *even;
  75.   guchar  *odd;
  76.   gint     width;
  77.  
  78.   width = width_data / 4;
  79.  
  80.   /*  Draw the gradient  */
  81.   src = grad_data;
  82.   p0  = even = g_malloc (width * 3);
  83.   p1  = odd  = g_malloc (width * 3);
  84.  
  85.   for (x = 0; x < width; x++) 
  86.     {
  87.       r =  src[x*4+0];
  88.       g = src[x*4+1];
  89.       b = src[x*4+2];
  90.       a = src[x*4+3];
  91.       
  92.       if ((x / GIMP_CHECK_SIZE_SM) & 1) 
  93.     {
  94.       c0 = GIMP_CHECK_LIGHT;
  95.       c1 = GIMP_CHECK_DARK;
  96.     } 
  97.       else 
  98.     {
  99.       c0 = GIMP_CHECK_DARK;
  100.       c1 = GIMP_CHECK_LIGHT;
  101.     }
  102.     
  103.       *p0++ = (c0 + (r - c0) * a) * 255.0;
  104.       *p0++ = (c0 + (g - c0) * a) * 255.0;
  105.       *p0++ = (c0 + (b - c0) * a) * 255.0;
  106.       
  107.       *p1++ = (c1 + (r - c1) * a) * 255.0;
  108.       *p1++ = (c1 + (g - c1) * a) * 255.0;
  109.       *p1++ = (c1 + (b - c1) * a) * 255.0;
  110.     }
  111.   
  112.   for (y = 0; y < CELL_SIZE_HEIGHT; y++)
  113.     {
  114.       if ((y / GIMP_CHECK_SIZE_SM) & 1)
  115.     gtk_preview_draw_row (GTK_PREVIEW (gradient_preview), 
  116.                   (guchar *)odd, 0, y, 
  117.                   (width < CELL_SIZE_WIDTH) ? width : CELL_SIZE_WIDTH);
  118.       else
  119.       gtk_preview_draw_row (GTK_PREVIEW (gradient_preview), 
  120.                 (guchar *)even, 0, y, 
  121.                 (width < CELL_SIZE_WIDTH) ? width : CELL_SIZE_WIDTH);
  122.     }
  123.  
  124.   g_free (even);
  125.   g_free (odd);
  126.  
  127.   /*  Draw the brush preview  */
  128.   gtk_widget_draw (gradient_preview, NULL);
  129. }
  130.  
  131. static void
  132. gradient_select_invoker (gchar    *name,
  133.              gint      width,
  134.              gdouble  *grad_data,
  135.              gint      closing,
  136.              gpointer  data)
  137. {
  138.   GSelect *gsel = (GSelect*)data;
  139.  
  140.   if (gsel->grad_data != NULL)
  141.     g_free (gsel->grad_data);
  142.  
  143.   gsel->width = width;
  144.   if (gsel->gradient_name)
  145.     g_free (gsel->gradient_name);
  146.  
  147.   gsel->gradient_name = g_strdup (name);
  148.   /* one row only each row has four doubles r,g,b,a */
  149.   gsel->grad_data = g_new (gdouble, width);
  150.   /*  printf("name = %s width = %d\n",name,width);*/
  151.   g_memmove (gsel->grad_data, grad_data, width * sizeof (gdouble)); 
  152.   gradient_pre_update (gsel->gradient_preview, gsel->width, gsel->grad_data);
  153.  
  154.   if (gsel->cback != NULL)
  155.     (gsel->cback)(name, width, grad_data, closing, gsel->data);
  156.   
  157.   if (closing)
  158.     gtk_widget_set_sensitive (gsel->button, TRUE);
  159. }
  160.  
  161.  
  162. static void
  163. gradient_preview_callback (GtkWidget *widget,
  164.                gpointer   data)
  165. {
  166.   GSelect *gsel = (GSelect*)data;
  167.  
  168.   gtk_widget_set_sensitive (gsel->button, FALSE);
  169.  
  170.   gsel->gradient_popup_pnt = 
  171.     gimp_interactive_selection_gradient ((gsel->dname) ? gsel->dname 
  172.                                    : "Gradient Plugin Selection",
  173.                      gsel->gradient_name,
  174.                      gsel->sample_size,
  175.                      gradient_select_invoker,
  176.                      gsel);
  177. }
  178.  
  179. GtkWidget * 
  180. gimp_gradient_select_widget (gchar                   *dname,
  181.                  gchar                   *igradient, 
  182.                  GimpRunGradientCallback  cback,
  183.                  gpointer                 data)
  184. {
  185.   GtkWidget *button;
  186.   GtkWidget *hbox;
  187.   GtkWidget *gradient;
  188.   gint       width;
  189.   gdouble   *grad_data;
  190.   gchar     *gradient_name;
  191.   GSelect   *gsel;
  192.   
  193.   gsel = g_new (GSelect, 1);
  194.  
  195.   hbox = gtk_hbox_new (FALSE, 3);
  196.   gtk_widget_show(hbox);
  197.  
  198.   button = gtk_button_new ();
  199.  
  200.   gradient = gtk_preview_new (GTK_PREVIEW_COLOR);
  201.   gtk_preview_size (GTK_PREVIEW (gradient), CELL_SIZE_WIDTH, CELL_SIZE_HEIGHT); 
  202.   gtk_widget_show (gradient);
  203.   gtk_container_add (GTK_CONTAINER (button), gradient); 
  204.  
  205.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  206.               (GtkSignalFunc) gradient_preview_callback,
  207.               (gpointer)gsel);
  208.   
  209.   gtk_widget_show(button);
  210.  
  211.   gsel->button             = button;
  212.   gsel->cback              = cback;
  213.   gsel->data               = data;
  214.   gsel->grad_data          = NULL;
  215.   gsel->gradient_preview   = gradient;
  216.   gsel->dname              = dname;
  217.   gsel->gradient_popup_pnt = NULL;
  218.   gsel->sample_size        = CELL_SIZE_WIDTH;
  219.  
  220.   /* Do initial gradient setup */
  221.   gradient_name = 
  222.     gimp_gradients_get_gradient_data (igradient, &width, CELL_SIZE_WIDTH, &grad_data);
  223.  
  224.   if (gradient_name)
  225.     {
  226.       gradient_pre_update (gsel->gradient_preview, width, grad_data);
  227.       gsel->grad_data     = grad_data;
  228.       gsel->gradient_name = gradient_name;
  229.       gsel->width         = width;
  230.     }
  231.   else
  232.     {
  233.       gsel->gradient_name = g_strdup (igradient);
  234.     }
  235.  
  236.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  237.  
  238.   gtk_object_set_data (GTK_OBJECT (hbox), GSEL_DATA_KEY, (gpointer)gsel);
  239.  
  240.   return hbox;
  241. }
  242.  
  243.  
  244. void
  245. gimp_gradient_select_widget_close_popup (GtkWidget *widget)
  246. {
  247.   GSelect  *gsel;
  248.   
  249.   gsel = (GSelect*) gtk_object_get_data (GTK_OBJECT (widget), GSEL_DATA_KEY);
  250.  
  251.   if (gsel && gsel->gradient_popup_pnt)
  252.     {
  253.       gimp_gradients_close_popup (gsel->gradient_popup_pnt);
  254.       gsel->gradient_popup_pnt = NULL;
  255.     }
  256. }
  257.  
  258. void
  259. gimp_gradient_select_widget_set_popup (GtkWidget *widget,
  260.                        gchar     *gname)
  261. {
  262.   gint      width;
  263.   gdouble  *grad_data;
  264.   gchar    *gradient_name;
  265.   GSelect  *gsel;
  266.   
  267.   gsel = (GSelect*) gtk_object_get_data (GTK_OBJECT (widget), GSEL_DATA_KEY);
  268.  
  269.   if (gsel)
  270.     {
  271.       gradient_name = 
  272.     gimp_gradients_get_gradient_data (gname, &width, gsel->sample_size, &grad_data);
  273.   
  274.       if (gradient_name)
  275.     {
  276.       gradient_select_invoker (gname, width, grad_data, 0, gsel);
  277.  
  278.       if (gsel->gradient_popup_pnt)
  279.         gimp_gradients_set_popup (gsel->gradient_popup_pnt, gname);
  280.     }
  281.     }
  282. }
  283.