home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / transform_tool.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  12.7 KB  |  457 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 <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "gdisplay.h"
  27. #include "gimpui.h"
  28. #include "tools.h"
  29. #include "perspective_tool.h"
  30. #include "rotate_tool.h"
  31. #include "scale_tool.h"
  32. #include "shear_tool.h"
  33. #include "transform_core.h"
  34. #include "transform_tool.h"
  35.  
  36. #include "libgimp/gimpmath.h"
  37. #include "libgimp/gimpintl.h"
  38.  
  39. /*  the transform structures  */
  40.  
  41. typedef struct _TransformOptions TransformOptions;
  42.  
  43. struct _TransformOptions
  44. {
  45.   ToolOptions  tool_options;
  46.  
  47.   ToolType     type;
  48.   ToolType     type_d;
  49.   GtkWidget   *type_w[4];  /* 4 radio buttons */
  50.  
  51.   gboolean     smoothing;
  52.   gboolean     smoothing_d;
  53.   GtkWidget   *smoothing_w;
  54.  
  55.   gint           direction;
  56.   gint         direction_d;
  57.   GtkWidget   *direction_w[2];  /* 2 radio buttons */
  58.  
  59.   gboolean     show_grid;
  60.   gboolean     show_grid_d;
  61.   GtkWidget   *show_grid_w;
  62.  
  63.   gint           grid_size;
  64.   gint         grid_size_d;
  65.   GtkObject   *grid_size_w;
  66.  
  67.   gboolean     clip;
  68.   gboolean     clip_d;
  69.   GtkWidget   *clip_w;
  70.  
  71.   gboolean     showpath;
  72.   gboolean     showpath_d;
  73.   GtkWidget   *showpath_w;
  74. };
  75.  
  76.  
  77. /*  the transform tool options  */
  78. static TransformOptions *transform_options = NULL;
  79.  
  80.  
  81. /*  local functions  */
  82. static void   transform_change_type (ToolType new_type);
  83.  
  84.  
  85. /*  functions  */
  86.  
  87. static void
  88. transform_show_grid_update (GtkWidget *widget,
  89.                 gpointer   data)
  90. {
  91.   static gboolean first_call = TRUE;  /* eek, this hack avoids a segfault */
  92.  
  93.   if (first_call)
  94.     {
  95.       first_call = FALSE;
  96.       return;
  97.     }
  98.  
  99.   gimp_toggle_button_update (widget, data);
  100.  
  101.   transform_core_grid_density_changed ();
  102. }
  103.  
  104. static void
  105. transform_show_path_update (GtkWidget *widget,
  106.                 gpointer   data)
  107. {
  108.   static gboolean first_call = TRUE;  /* eek, this hack avoids a segfault */
  109.  
  110.   if (first_call)
  111.     {
  112.       first_call = FALSE;
  113.       return;
  114.     }
  115.  
  116.   transform_core_showpath_changed (1); /* pause */
  117.   gimp_toggle_button_update (widget, data);
  118.   transform_core_showpath_changed (0); /* resume */
  119. }
  120.  
  121. static void
  122. transform_type_callback (GtkWidget *widget,
  123.              gpointer   data)
  124. {
  125.   transform_change_type ((long) data);
  126. }
  127.  
  128. static void
  129. transform_direction_callback (GtkWidget *widget,
  130.                   gpointer   data)
  131. {
  132.   long dir = (long) data;
  133.   
  134.   if (dir == TRANSFORM_TRADITIONAL)
  135.     transform_options->direction = TRANSFORM_TRADITIONAL;
  136.   else
  137.     transform_options->direction = TRANSFORM_CORRECTIVE;
  138. }
  139.  
  140. static void
  141. transform_grid_density_callback (GtkWidget *widget,
  142.                  gpointer   data)
  143. {
  144.   transform_options->grid_size =
  145.     (int) (pow (2.0, 7.0 - GTK_ADJUSTMENT (widget)->value) + 0.5);
  146.  
  147.   transform_core_grid_density_changed ();
  148. }
  149.  
  150. static void
  151. transform_options_reset (void)
  152. {
  153.   TransformOptions *options = transform_options;
  154.  
  155.   gtk_toggle_button_set_active (((options->type_d == ROTATE) ?
  156.                  GTK_TOGGLE_BUTTON (options->type_w[0]) :
  157.                  ((options->type_d == SCALE) ?
  158.                   GTK_TOGGLE_BUTTON (options->type_w[1]) :
  159.                   ((options->type_d == SHEAR) ?
  160.                    GTK_TOGGLE_BUTTON (options->type_w[2]) :
  161.                    GTK_TOGGLE_BUTTON (options->type_w[3])))),
  162.                 TRUE);
  163.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->smoothing_w),
  164.                 options->smoothing_d);
  165.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->showpath_w),
  166.                 options->showpath_d);
  167.   gtk_toggle_button_set_active (((options->direction_d == TRANSFORM_TRADITIONAL) ?
  168.                  GTK_TOGGLE_BUTTON (options->direction_w[0]) :
  169.                  GTK_TOGGLE_BUTTON (options->direction_w[1])),
  170.                 TRUE);
  171.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->show_grid_w),
  172.                 options->show_grid_d);
  173.   gtk_adjustment_set_value (GTK_ADJUSTMENT (options->grid_size_w),
  174.                 7.0 - log (options->grid_size_d) / log (2.0));
  175.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->clip_w),
  176.                 options->clip_d);
  177. }
  178.  
  179. static TransformOptions *
  180. transform_options_new (void)
  181. {
  182.   TransformOptions *options;
  183.  
  184.   GtkWidget *table;
  185.   GtkWidget *vbox;
  186.   GtkWidget *hbox;
  187.   GtkWidget *label;
  188.   GtkWidget *frame;
  189.   GtkWidget *fbox;
  190.   GtkWidget *grid_density;
  191.  
  192.   /*  the new transform tool options structure  */
  193.   options = g_new (TransformOptions, 1);
  194.   tool_options_init ((ToolOptions *) options,
  195.              _("Transform Tool"),
  196.              transform_options_reset);
  197.   options->type      = options->type_d      = ROTATE;
  198.   options->smoothing = options->smoothing_d = TRUE;
  199.   options->showpath  = options->showpath_d  = TRUE;
  200.   options->clip      = options->clip_d      = FALSE;
  201.   options->direction = options->direction_d = TRANSFORM_TRADITIONAL;
  202.   options->grid_size = options->grid_size_d = 32;
  203.   options->show_grid = options->show_grid_d = TRUE;
  204.  
  205.   /* the main table */
  206.   table = gtk_table_new (2, 2, FALSE);
  207.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
  208.   gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), table,
  209.               FALSE, FALSE, 0);
  210.  
  211.   /*  the left vbox  */
  212.   vbox = gtk_vbox_new (FALSE, 2);
  213.   gtk_table_attach_defaults (GTK_TABLE (table), vbox, 0, 1, 0, 1);
  214.  
  215.   /*  the transform type radio buttons  */
  216.   frame = gimp_radio_group_new (TRUE, _("Transform"),
  217.  
  218.                 _("Rotation"), transform_type_callback,
  219.                 ROTATE, NULL, &options->type_w[0], TRUE,
  220.                 _("Scaling"), transform_type_callback,
  221.                 SCALE, NULL, &options->type_w[1], FALSE,
  222.                 _("Shearing"), transform_type_callback,
  223.                 SHEAR, NULL, &options->type_w[2], FALSE,
  224.                 _("Perspective"), transform_type_callback,
  225.                 PERSPECTIVE, NULL, &options->type_w[3], FALSE,
  226.  
  227.                 NULL);
  228.  
  229.   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
  230.   gtk_widget_show (frame);
  231.  
  232.   gtk_widget_show (vbox);
  233.  
  234.   /*  the right vbox  */
  235.   vbox = gtk_vbox_new (FALSE, 2);
  236.   gtk_table_attach_defaults (GTK_TABLE (table), vbox, 1, 2, 0, 1);
  237.  
  238.   /*  the second radio frame and box, for transform direction  */
  239.   frame = gimp_radio_group_new (TRUE, _("Tool Paradigm"),
  240.  
  241.                 _("Traditional"), transform_direction_callback,
  242.                 TRANSFORM_TRADITIONAL, NULL,
  243.                 &options->direction_w[0], TRUE,
  244.                 _("Corrective"), transform_direction_callback,
  245.                 TRANSFORM_CORRECTIVE, NULL,
  246.                 &options->direction_w[1], FALSE,
  247.  
  248.                 NULL);
  249.  
  250.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  251.   gtk_widget_show (frame);
  252.  
  253.   /*  the grid frame  */
  254.   frame = gtk_frame_new (NULL);
  255.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  256.  
  257.   fbox = gtk_vbox_new (FALSE, 1);
  258.   gtk_container_set_border_width (GTK_CONTAINER (fbox), 2);
  259.   gtk_container_add (GTK_CONTAINER (frame), fbox);
  260.  
  261.   /*  the show grid toggle button  */
  262.   options->show_grid_w = gtk_check_button_new_with_label (_("Show Grid"));
  263.   gtk_signal_connect (GTK_OBJECT (options->show_grid_w), "toggled",
  264.               GTK_SIGNAL_FUNC (transform_show_grid_update),
  265.               &options->show_grid);
  266.   gtk_box_pack_start (GTK_BOX (fbox), options->show_grid_w, FALSE, FALSE, 0);
  267.   gtk_widget_show (options->show_grid_w);
  268.   
  269.   /*  the grid density entry  */
  270.   hbox = gtk_hbox_new (FALSE, 6);
  271.   gtk_widget_show (hbox);
  272.   gtk_box_pack_start (GTK_BOX (fbox), hbox, FALSE, FALSE, 0);
  273.   label = gtk_label_new (_("Density:"));
  274.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  275.   gtk_widget_show (label);
  276.  
  277.   options->grid_size_w =
  278.     gtk_adjustment_new (7.0 - log (options->grid_size_d) / log (2.0), 0.0, 5.0,
  279.             1.0, 1.0, 0.0);
  280.   grid_density =
  281.     gtk_spin_button_new (GTK_ADJUSTMENT (options->grid_size_w), 0, 0);
  282.   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (grid_density), TRUE);
  283.   gtk_signal_connect (GTK_OBJECT (options->grid_size_w), "value_changed",
  284.               GTK_SIGNAL_FUNC (transform_grid_density_callback),
  285.               &options->grid_size);
  286.   gtk_box_pack_start (GTK_BOX (hbox), grid_density, FALSE, FALSE, 0);
  287.   gtk_widget_show (grid_density);
  288.   gtk_widget_set_sensitive (label, options->show_grid_d);
  289.   gtk_widget_set_sensitive (grid_density, options->show_grid_d);
  290.   gtk_object_set_data (GTK_OBJECT (options->show_grid_w), "set_sensitive",
  291.                grid_density);
  292.   gtk_object_set_data (GTK_OBJECT (grid_density), "set_sensitive", label);  
  293.  
  294.   gtk_widget_show (fbox);
  295.   gtk_widget_show (frame);
  296.  
  297.   gtk_widget_show (vbox);
  298.  
  299.   /*  the smoothing toggle button  */
  300.   options->smoothing_w = gtk_check_button_new_with_label (_("Smoothing"));
  301.   gtk_signal_connect (GTK_OBJECT (options->smoothing_w), "toggled",
  302.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  303.               &options->smoothing);
  304.   gtk_table_attach_defaults (GTK_TABLE (table), 
  305.                  options->smoothing_w, 0, 1, 1, 2);
  306.   gtk_widget_show (options->smoothing_w);
  307.  
  308.   /*  the showpath toggle button  */
  309.   options->showpath_w = gtk_check_button_new_with_label (_("Show Path"));
  310.   gtk_signal_connect (GTK_OBJECT (options->showpath_w), "toggled",
  311.               GTK_SIGNAL_FUNC (transform_show_path_update),
  312.               &options->showpath);
  313.   gtk_table_attach_defaults (GTK_TABLE (table), 
  314.                  options->showpath_w, 1, 2, 1, 2);
  315.   gtk_widget_show (options->showpath_w);
  316.  
  317.   gtk_widget_show (table);
  318.  
  319.   /*  the clip resulting image toggle button  */
  320.   options->clip_w = gtk_check_button_new_with_label (_("Clip Result"));
  321.   gtk_signal_connect (GTK_OBJECT (options->clip_w), "toggled",
  322.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  323.               &options->clip);
  324.   gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), 
  325.               options->clip_w, FALSE, FALSE, 0);
  326.   gtk_widget_show (options->clip_w);
  327.   
  328.   return options;
  329. }
  330.  
  331. Tool *
  332. tools_new_transform_tool (void)
  333. {
  334.   /* The tool options */
  335.   if (! transform_options)
  336.     {
  337.       transform_options = transform_options_new ();
  338.       tools_register (ROTATE, (ToolOptions *) transform_options);
  339.       tools_register (SCALE, (ToolOptions *) transform_options);
  340.       tools_register (SHEAR, (ToolOptions *) transform_options);
  341.       tools_register (PERSPECTIVE, (ToolOptions *) transform_options);
  342.  
  343.       /*  press all default buttons  */
  344.       transform_options_reset ();
  345.     }
  346.  
  347.   switch (transform_options->type)
  348.     {
  349.     case ROTATE:
  350.       return tools_new_rotate_tool ();
  351.       break;
  352.     case SCALE:
  353.       return tools_new_scale_tool ();
  354.       break;
  355.     case SHEAR:
  356.       return tools_new_shear_tool ();
  357.       break;
  358.     case PERSPECTIVE:
  359.       return tools_new_perspective_tool ();
  360.       break;
  361.     default :
  362.       return NULL;
  363.       break;
  364.     }
  365. }
  366.  
  367. void
  368. tools_free_transform_tool (Tool *tool)
  369. {
  370.   switch (transform_options->type)
  371.     {
  372.     case ROTATE:
  373.       tools_free_rotate_tool (tool);
  374.       break;
  375.     case SCALE:
  376.       tools_free_scale_tool (tool);
  377.       break;
  378.     case SHEAR:
  379.       tools_free_shear_tool (tool);
  380.       break;
  381.     case PERSPECTIVE:
  382.       tools_free_perspective_tool (tool);
  383.       break;
  384.     default:
  385.       break;
  386.     }
  387. }
  388.  
  389. static void
  390. transform_change_type (ToolType new_type)
  391. {
  392.   if (transform_options->type != new_type)
  393.     {
  394.       /*  change the type, free the old tool, create the new tool  */
  395.       transform_options->type = new_type;
  396.  
  397.       if (gimp_context_get_tool (gimp_context_get_user ()) != new_type)
  398.     gimp_context_set_tool (gimp_context_get_user (), new_type);
  399.       else
  400.     gimp_context_tool_changed (gimp_context_get_user ());
  401.     }
  402. }
  403.  
  404. gboolean
  405. transform_tool_smoothing (void)
  406. {
  407.   if (!transform_options)
  408.     return TRUE;
  409.   else
  410.     return transform_options->smoothing;
  411. }
  412.  
  413. gboolean
  414. transform_tool_showpath (void)
  415. {
  416.   if (!transform_options)
  417.     return TRUE;
  418.   else
  419.     return transform_options->showpath;
  420. }
  421.  
  422. gboolean
  423. transform_tool_clip (void)
  424. {
  425.   if (!transform_options)
  426.     return FALSE;
  427.   else
  428.     return transform_options->clip;
  429. }
  430.  
  431. gint
  432. transform_tool_direction (void)
  433. {
  434.   if (!transform_options)
  435.     return TRANSFORM_TRADITIONAL;
  436.   else
  437.     return transform_options->direction;
  438. }
  439.  
  440. gint
  441. transform_tool_grid_size (void)
  442. {
  443.   if (!transform_options)
  444.     return 32;
  445.   else
  446.     return transform_options->grid_size;
  447. }
  448.  
  449. gboolean
  450. transform_tool_show_grid (void)
  451. {
  452.   if (!transform_options)
  453.     return TRUE;
  454.   else
  455.     return transform_options->show_grid;
  456. }
  457.