home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / qmask.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  11.0 KB  |  396 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 <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24.  
  25. #include <gtk/gtk.h>
  26.  
  27. #include "apptypes.h"
  28.  
  29. #include "appenv.h" 
  30. #include "channel.h"
  31. #include "color_panel.h"
  32. #include "floating_sel.h"
  33. #include "gdisplayF.h"
  34. #include "gimpcontext.h"
  35. #include "gimage_mask.h"
  36. #include "gimpimage.h"
  37. #include "gimpui.h"
  38. #include "global_edit.h"
  39. #include "qmask.h"
  40. #include "undo.h"
  41.  
  42. #include "libgimp/gimpintl.h"
  43.  
  44.  
  45. struct _EditQmaskOptions
  46. {
  47.   GtkWidget   *query_box;
  48.   GtkWidget   *name_entry;
  49.  
  50.   GimpImage   *gimage;
  51.   ColorPanel  *color_panel;
  52.   gdouble      opacity;
  53. };
  54.  
  55. typedef struct _EditQmaskOptions EditQmaskOptions;
  56.  
  57. /*  Global variables  */
  58. /*  Static variables  */
  59. /*  Prototypes */
  60. static void edit_qmask_channel_query         (GDisplay      *gdisp);
  61. static void edit_qmask_query_ok_callback     (GtkWidget     *widget, 
  62.                                               gpointer       client_data);
  63. static void edit_qmask_query_cancel_callback (GtkWidget     *widget, 
  64.                                               gpointer       client_data);
  65. static void qmask_query_scale_update         (GtkAdjustment *adjustment,
  66.                                               gdouble       *scale_val);
  67. static void qmask_removed_callback           (GtkObject     *qmask, 
  68.                           gpointer       data);
  69.  
  70. /* Actual code */
  71.  
  72. static void 
  73. qmask_query_scale_update (GtkAdjustment *adjustment, 
  74.               gdouble       *scale_val)
  75. {
  76.   *scale_val = adjustment->value;
  77. }
  78.  
  79. static void
  80. qmask_removed_callback (GtkObject *qmask,
  81.             gpointer   data)
  82. {
  83.   GDisplay *gdisp = (GDisplay*) data;
  84.   
  85.   if (!gdisp->gimage)
  86.     return;
  87.   
  88.   gdisp->gimage->qmask_state = FALSE;
  89.  
  90.   qmask_buttons_update (gdisp);
  91. }
  92.  
  93.  
  94. void
  95. qmask_buttons_update (GDisplay *gdisp)
  96. {
  97.   g_assert (gdisp);
  98.   g_assert (gdisp->gimage);
  99.  
  100.   if (gdisp->gimage->qmask_state != GTK_TOGGLE_BUTTON (gdisp->qmaskon)->active)
  101.     {
  102.       /* Disable toggle from doing anything */
  103.       gtk_signal_handler_block_by_func(GTK_OBJECT(gdisp->qmaskoff), 
  104.                        (GtkSignalFunc) qmask_deactivate,
  105.                        gdisp);
  106.       gtk_signal_handler_block_by_func(GTK_OBJECT(gdisp->qmaskon), 
  107.                        (GtkSignalFunc) qmask_activate,
  108.                        gdisp);
  109.    
  110.       /* Change the state of the buttons */
  111.       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdisp->qmaskon), 
  112.                    gdisp->gimage->qmask_state);
  113.  
  114.       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdisp->qmaskoff),
  115.                    !gdisp->gimage->qmask_state);
  116.    
  117.       /* Enable toggle again */
  118.       gtk_signal_handler_unblock_by_func(GTK_OBJECT(gdisp->qmaskoff), 
  119.                      (GtkSignalFunc) qmask_deactivate,
  120.                      gdisp);
  121.       gtk_signal_handler_unblock_by_func(GTK_OBJECT(gdisp->qmaskon), 
  122.                      (GtkSignalFunc) qmask_activate,
  123.                      gdisp);
  124.     }
  125. }
  126.  
  127. void 
  128. qmask_click_handler (GtkWidget       *widget,
  129.              GdkEventButton  *event,
  130.                      gpointer         data)
  131. {
  132.   GDisplay *gdisp;
  133.   gdisp = (GDisplay *)data;
  134.  
  135.   if ((event->type == GDK_2BUTTON_PRESS) &&
  136.       (event->button == 1))
  137.     {
  138.       edit_qmask_channel_query(gdisp); 
  139.     }
  140. }
  141.  
  142. void
  143. qmask_deactivate (GtkWidget *widget,
  144.           GDisplay  *gdisp)
  145. {
  146.   GimpImage   *gimg;
  147.   GimpChannel *gmask;
  148.  
  149.   if (gdisp)
  150.     {
  151.       gimg = gdisp->gimage;
  152.       if (!gimg) 
  153.     return;
  154.       
  155.       if (!gdisp->gimage->qmask_state)
  156.     return; /* if already set do nothing */
  157.  
  158.       if ( (gmask = gimp_image_get_channel_by_name (gimg, "Qmask")) )
  159.       { 
  160.       undo_push_group_start (gimg, QMASK_UNDO);
  161.       /*  push the undo here since removing the mask will
  162.           call the qmask_removed_callback() which will set
  163.           the qmask_state to FALSE  */
  164.       undo_push_qmask (gimg);
  165.       gimage_mask_load (gimg, gmask);
  166.       gimage_remove_channel (gimg, gmask);
  167.       undo_push_group_end (gimg);
  168.     }
  169.  
  170.       gdisp->gimage->qmask_state = FALSE;
  171.  
  172.       if (gmask)
  173.     gdisplays_flush ();
  174.     }
  175. }
  176.  
  177. void
  178. qmask_activate (GtkWidget *widget,
  179.         GDisplay  *gdisp)
  180. {
  181.   GimpImage   *gimg;
  182.   GimpChannel *gmask;
  183.   GimpLayer   *layer;
  184.  
  185.   gdouble  opacity;
  186.   guchar  *color;
  187.  
  188.   if (gdisp)
  189.     {
  190.       gimg = gdisp->gimage;
  191.       if (!gimg) 
  192.     return;
  193.  
  194.       if (gdisp->gimage->qmask_state)
  195.     return; /* If already set, do nothing */
  196.   
  197.       /* Set the defaults */
  198.       opacity = (gdouble) gimg->qmask_opacity;
  199.       color = gimg->qmask_color;
  200.  
  201.       if ( (gmask = gimp_image_get_channel_by_name (gimg, "Qmask")) ) 
  202.     {
  203.       gimg->qmask_state = TRUE; 
  204.       /* if the user was clever and created his own */
  205.       return; 
  206.     }
  207.  
  208.       undo_push_group_start (gimg, QMASK_UNDO);
  209.  
  210.       if (gimage_mask_is_empty(gimg))
  211.     { 
  212.       if ((layer = gimage_floating_sel (gimg)))
  213.         {
  214.           floating_sel_to_layer (layer);
  215.         }
  216.       /* if no selection */
  217.       gmask = channel_new (gimg, 
  218.                    gimg->width, 
  219.                    gimg->height,
  220.                    "Qmask", 
  221.                    (gint)(255*opacity)/100,
  222.                    color);
  223.       gimp_image_add_channel (gimg, gmask, 0);
  224.       gimp_drawable_fill (GIMP_DRAWABLE (gmask), 0, 0, 0, 0);
  225.     }
  226.       else 
  227.     { /* if selection */
  228.       gmask = channel_copy (gimage_get_mask (gimg));
  229.       gimp_image_add_channel (gimg, gmask, 0);
  230.       channel_set_color (gmask, color);
  231.       channel_set_name (gmask, "Qmask");
  232.       channel_set_opacity (gmask, opacity);
  233.       gimage_mask_none (gimg);           /* Clear the selection */
  234.     }
  235.  
  236.       undo_push_qmask (gimg);
  237.       undo_push_group_end (gimg);
  238.       gdisp->gimage->qmask_state = TRUE;
  239.       gdisplays_flush ();
  240.       
  241.       /* connect to the removed signal, so the buttons get updated */
  242.       gtk_signal_connect (GTK_OBJECT (gmask), "removed", 
  243.               GTK_SIGNAL_FUNC (qmask_removed_callback), gdisp);
  244.     }
  245. }
  246.  
  247. static void
  248. edit_qmask_channel_query (GDisplay * gdisp)
  249. {
  250.   EditQmaskOptions *options;
  251.   GtkWidget *hbox;
  252.   GtkWidget *vbox;
  253.   GtkWidget *table;
  254.   GtkWidget *label;
  255.   GtkWidget *opacity_scale;
  256.   GtkObject *opacity_scale_data;
  257.  
  258.   gint i;
  259.   guchar channel_color[3] = { 0, 0, 0 };
  260.  
  261.   /* channel = gimp_image_get_channel_by_name (gdisp->gimage, "Qmask"); */
  262.   /*  the new options structure  */
  263.   options = g_new (EditQmaskOptions, 1);
  264.   options->gimage  = gdisp->gimage;
  265.   options->opacity = (gdouble) options->gimage->qmask_opacity;
  266.  
  267.   for (i = 0; i < 3; i++)
  268.     channel_color[i] = options->gimage->qmask_color[i];
  269.  
  270.   options->color_panel = color_panel_new (channel_color, 48, 64);
  271.  
  272.   /*  The dialog  */
  273.   options->query_box =
  274.     gimp_dialog_new (_("Edit Qmask Attributes"), "edit_qmask_attributes",
  275.              gimp_standard_help_func,
  276.              "dialogs/edit_qmask_attributes.html",
  277.              GTK_WIN_POS_MOUSE,
  278.              FALSE, TRUE, FALSE,
  279.  
  280.              _("OK"), edit_qmask_query_ok_callback,
  281.              options, NULL, NULL, TRUE, FALSE,
  282.              _("Cancel"), edit_qmask_query_cancel_callback,
  283.              options, NULL, NULL, FALSE, TRUE,
  284.  
  285.              NULL);
  286.  
  287.   /*  The main hbox  */
  288.   hbox = gtk_hbox_new (FALSE, 2);
  289.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  290.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
  291.                      hbox);
  292.   /*  The vbox  */
  293.   vbox = gtk_vbox_new (FALSE, 2);
  294.   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  295.  
  296.   /*  The table  */
  297.   table = gtk_table_new (2, 3, FALSE);
  298.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  299.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  300.  
  301.   /*  The opacity scale  */
  302.   label = gtk_label_new (_("Mask Opacity:"));
  303.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  304.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  305.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  306.   gtk_widget_show (label);
  307.  
  308.   opacity_scale_data =
  309.     gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
  310.   opacity_scale = gtk_hscale_new (GTK_ADJUSTMENT (opacity_scale_data));
  311.   gtk_table_attach_defaults (GTK_TABLE (table), opacity_scale, 1, 2, 1, 2);
  312.   gtk_scale_set_value_pos (GTK_SCALE (opacity_scale), GTK_POS_TOP);
  313.   gtk_signal_connect (GTK_OBJECT (opacity_scale_data), "value_changed",
  314.                       (GtkSignalFunc) qmask_query_scale_update,
  315.                       &options->opacity);
  316.   gtk_widget_show (opacity_scale);
  317.  
  318.   /*  The color panel  */
  319.   gtk_box_pack_start (GTK_BOX (hbox), options->color_panel->color_panel_widget,
  320.                       TRUE, TRUE, 0);
  321.   gtk_widget_show (options->color_panel->color_panel_widget);
  322.  
  323.   gtk_widget_show (table);
  324.   gtk_widget_show (vbox);
  325.   gtk_widget_show (hbox);
  326.   gtk_widget_show (options->query_box);
  327. }
  328.  
  329. static void 
  330. edit_qmask_query_ok_callback (GtkWidget *widget, 
  331.                   gpointer   client_data) 
  332. {
  333.   EditQmaskOptions *options;
  334.   Channel  *channel;
  335.   guchar   *tmpcolp;
  336.   guchar    tmpcol[3];
  337.   gboolean  update = FALSE;
  338.   gint      opacity;
  339.   gint      i;
  340.   
  341.   options = (EditQmaskOptions *) client_data;
  342.   channel = gimp_image_get_channel_by_name (options->gimage, "Qmask");
  343.   opacity = (gint) (255 * options->opacity/100);
  344.  
  345.   if (options->gimage && channel)
  346.     {     /* don't update if opacity hasn't changed */
  347.       if (channel_get_opacity(channel) != opacity)
  348.         {
  349.           update = TRUE;
  350.         }
  351.       tmpcolp = channel_get_color(channel);
  352.       for (i = 0; i < 3; i++)
  353.     {  /* don't update if color hasn't changed */
  354.       tmpcol[i] = tmpcolp[i]; /* initialize to same values */
  355.       if (options->color_panel->color[i] != tmpcolp[i])
  356.         {
  357.           tmpcol[i] = options->color_panel->color[i];
  358.           update = TRUE;
  359.         }
  360.         }
  361.       
  362.       if (update)
  363.     { 
  364.       channel_set_opacity(channel, 100*opacity/255);
  365.       channel_set_color(channel,tmpcol);
  366.       channel_update (channel);
  367.     }
  368.     }
  369.   /* update the qmask color no matter what */
  370.   for (i = 0; i < 3; i++)
  371.     { /* TODO: should really have accessor functions for gimage private stuff */
  372.       options->gimage->qmask_color[i] = options->color_panel->color[i];
  373.       options->gimage->qmask_opacity = (gint) 100*opacity/255;
  374.     }
  375.  
  376.   gtk_widget_destroy (options->query_box);
  377.   g_free (options);
  378. }
  379.  
  380. static void
  381. edit_qmask_query_cancel_callback (GtkWidget *widget,
  382.                   gpointer   client_data)
  383. {
  384.   EditQmaskOptions *options;
  385.  
  386.   options = (EditQmaskOptions *) client_data;
  387.  
  388.   gtk_widget_destroy (options->query_box);
  389.   g_free (options);
  390. }
  391.  
  392.  
  393.  
  394.  
  395.  
  396.