home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / move.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  12.8 KB  |  540 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.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26. #include "appenv.h"
  27. #include "cursorutil.h"
  28. #include "draw_core.h"
  29. #include "edit_selection.h"
  30. #include "floating_sel.h"
  31. #include "gimage_mask.h"
  32. #include "gdisplay.h"
  33. #include "gdisplay_ops.h"
  34. #include "move.h"
  35. #include "undo.h"
  36.  
  37. #include "config.h"
  38. #include "libgimp/gimpintl.h"
  39.  
  40. /*  the move structures  */
  41.  
  42. typedef struct _MoveTool MoveTool;
  43. struct _MoveTool
  44. {
  45.   Layer    *layer;
  46.   Guide    *guide;
  47.   GDisplay *disp;
  48. };
  49.  
  50.  
  51. /*  the move tool options  */
  52. static ToolOptions *move_options = NULL;
  53.  
  54. /*  local variables  */
  55. static GdkGC *move_gc = NULL;
  56.  
  57.  
  58. /*  move tool action functions  */
  59. static void   move_tool_button_press   (Tool *, GdkEventButton *, gpointer);
  60. static void   move_tool_button_release (Tool *, GdkEventButton *, gpointer);
  61. static void   move_tool_motion         (Tool *, GdkEventMotion *, gpointer);
  62. static void   move_tool_cursor_update  (Tool *, GdkEventMotion *, gpointer);
  63. static void   move_tool_control           (Tool *, ToolAction,       gpointer);
  64.  
  65. static void   move_create_gc           (GDisplay *gdisp);
  66.  
  67.  
  68. /*  move action functions  */
  69.  
  70. static void
  71. move_tool_button_press (Tool           *tool,
  72.             GdkEventButton *bevent,
  73.             gpointer        gdisp_ptr)
  74. {
  75.   GDisplay *gdisp;
  76.   MoveTool *move;
  77.   Layer    *layer;
  78.   Guide    *guide;
  79.   gint      x, y;
  80.  
  81.   gdisp = (GDisplay *) gdisp_ptr;
  82.   move = (MoveTool *) tool->private;
  83.  
  84.   tool->gdisp_ptr = gdisp_ptr;
  85.   move->layer = NULL;
  86.   move->guide = NULL;
  87.   move->disp  = NULL;
  88.  
  89.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, FALSE, FALSE);
  90.  
  91.   if (bevent->state & GDK_MOD1_MASK &&
  92.       !gimage_mask_is_empty (gdisp->gimage))
  93.     {
  94.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE);
  95.       tool->state = ACTIVE;
  96.     }
  97.   else if (bevent->state & GDK_SHIFT_MASK)
  98.     {
  99.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_LAYER_TRANSLATE);
  100.       tool->state = ACTIVE;
  101.     }
  102.   else
  103.     {
  104.       if (gdisp->draw_guides &&
  105.       (guide = gdisplay_find_guide (gdisp, bevent->x, bevent->y)))
  106.     {
  107.       undo_push_guide (gdisp->gimage, guide);
  108.  
  109.       gdisplays_expose_guide (gdisp->gimage, guide);
  110.       gimage_remove_guide (gdisp->gimage, guide);
  111.       gdisplay_flush (gdisp);
  112.       gimage_add_guide (gdisp->gimage, guide);
  113.  
  114.       move->guide = guide;
  115.       move->disp  = gdisp;
  116.  
  117.       tool->scroll_lock = TRUE;
  118.       tool->state       = ACTIVE;
  119.  
  120.       move_tool_motion (tool, NULL, gdisp);
  121.     }
  122.       else if ((layer = gimage_pick_correlate_layer (gdisp->gimage, x, y)))
  123.     {
  124.       /*  If there is a floating selection, and this aint it,
  125.        *  use the move tool
  126.        */
  127.       if (gimage_floating_sel (gdisp->gimage) &&
  128.           !layer_is_floating_sel (layer))
  129.         {
  130.           move->layer = gimage_floating_sel (gdisp->gimage);
  131.         }
  132.       /*  Otherwise, init the edit selection  */
  133.       else
  134.         {
  135.           gimage_set_active_layer (gdisp->gimage, layer);
  136.           init_edit_selection (tool, gdisp_ptr, bevent, EDIT_LAYER_TRANSLATE);
  137.         }
  138.       tool->state = ACTIVE;
  139.     }
  140.     }
  141.  
  142.   /* if we've got an active tool grab the pointer */
  143.   if (tool->state == ACTIVE)      
  144.     {
  145.       gdk_pointer_grab (gdisp->canvas->window, FALSE,
  146.             GDK_POINTER_MOTION_HINT_MASK |
  147.             GDK_BUTTON1_MOTION_MASK |
  148.             GDK_BUTTON_RELEASE_MASK,
  149.             NULL, NULL, bevent->time);
  150.     }
  151. }
  152.  
  153. static void
  154. move_draw_guide (GDisplay *gdisp, 
  155.          Guide    *guide)
  156. {
  157.   gint x1, y1;
  158.   gint x2, y2;
  159.   gint w, h;
  160.   gint x, y;
  161.  
  162.   if (!move_gc)
  163.     move_create_gc (gdisp);
  164.  
  165.   if (guide->position == -1)
  166.     return;
  167.   
  168.   gdisplay_transform_coords (gdisp, gdisp->gimage->width, 
  169.                  gdisp->gimage->height, &x2, &y2, FALSE); 
  170.  
  171.   gdk_window_get_size (gdisp->canvas->window, &w, &h);
  172.  
  173.   switch (guide->orientation)
  174.     {
  175.     case ORIENTATION_HORIZONTAL:
  176.       gdisplay_transform_coords (gdisp, 0, guide->position, &x1, &y, FALSE);
  177.       if (x1 < 0) x1 = 0;
  178.       if (x2 > w) x2 = w;
  179.  
  180.       gdk_draw_line (gdisp->canvas->window, move_gc, x1, y, x2, y); 
  181.       break;
  182.  
  183.     case ORIENTATION_VERTICAL:
  184.       gdisplay_transform_coords (gdisp, guide->position, 0, &x, &y1, FALSE);
  185.       if (y1 < 0) y1 = 0;
  186.       if (y2 > h) y2 = h;
  187.  
  188.       gdk_draw_line (gdisp->canvas->window, move_gc, x, y1, x, y2);
  189.       break;
  190.  
  191.     default:
  192.       g_warning ("mdg / BAD FALLTHROUGH");
  193.     }
  194. }
  195.  
  196. static void
  197. move_tool_button_release (Tool           *tool,
  198.               GdkEventButton *bevent,
  199.               gpointer        gdisp_ptr)
  200. {
  201.   MoveTool *move;
  202.   GDisplay *gdisp;
  203.   gboolean  delete_guide;
  204.   gint      x1, y1;
  205.   gint      x2, y2;
  206.  
  207.   gdisp = (GDisplay *) gdisp_ptr;
  208.   move = (MoveTool *) tool->private;
  209.  
  210.   gdk_flush ();
  211.  
  212.   tool->state = INACTIVE;
  213.   gdk_pointer_ungrab (bevent->time);
  214.  
  215.   if (move->guide)
  216.     {
  217.       tool->scroll_lock = FALSE;
  218.  
  219.       delete_guide = FALSE;
  220.       gdisplay_untransform_coords (gdisp, 0, 0, &x1, &y1, FALSE, FALSE);
  221.       gdisplay_untransform_coords (gdisp, gdisp->disp_width, gdisp->disp_height,
  222.                    &x2, &y2, FALSE, FALSE);
  223.  
  224.       if (x1 < 0) x1 = 0;
  225.       if (y1 < 0) y1 = 0;
  226.       if (x2 > gdisp->gimage->width)  x2 = gdisp->gimage->width;
  227.       if (y2 > gdisp->gimage->height) y2 = gdisp->gimage->height;
  228.  
  229.       switch (move->guide->orientation)
  230.     {
  231.     case ORIENTATION_HORIZONTAL:
  232.       if ((move->guide->position < y1) || (move->guide->position > y2))
  233.         delete_guide = TRUE;
  234.       break;
  235.     case ORIENTATION_VERTICAL:
  236.       if ((move->guide->position < x1) || (move->guide->position > x2))
  237.         delete_guide = TRUE;
  238.       break;
  239.     }
  240.  
  241.       gdisplays_expose_guide (gdisp->gimage, move->guide);
  242.  
  243.       if (delete_guide)
  244.     {
  245.       move_draw_guide (gdisp, move->guide);
  246.       gimp_image_delete_guide (gdisp->gimage, move->guide);
  247.       move->guide = NULL;
  248.       move->disp = NULL;
  249.     }
  250.       else
  251.     {
  252.       move_tool_motion (tool, NULL, gdisp_ptr);
  253.     }
  254.  
  255.       selection_resume (gdisp->select);
  256.       gdisplays_flush ();
  257.  
  258.       if (move->guide)
  259.     gdisplay_draw_guide (gdisp, move->guide, TRUE);
  260.     }
  261.   else
  262.     {
  263.       /*  Take care of the case where the user "cancels" the action  */
  264.       if (! (bevent->state & GDK_BUTTON3_MASK))
  265.     {
  266.       if (move->layer)
  267.         {
  268.           floating_sel_anchor (move->layer);
  269.           gdisplays_flush ();
  270.         }
  271.     }
  272.     }
  273. }
  274.  
  275. static void
  276. move_tool_motion (Tool           *tool,
  277.           GdkEventMotion *mevent,
  278.           gpointer        gdisp_ptr)
  279.  
  280. {
  281.   MoveTool *move;
  282.   GDisplay *gdisp;
  283.   gint      x, y;
  284.  
  285.   move = (MoveTool *) tool->private;
  286.   gdisp = (GDisplay *) gdisp_ptr;
  287.  
  288.   if (move->guide)
  289.     {
  290.       move_draw_guide (gdisp, move->guide);
  291.  
  292.       if (mevent && mevent->window != gdisp->canvas->window)
  293.     {
  294.       move->guide->position = -1;
  295.       return;
  296.     }
  297.       
  298.       if (mevent)
  299.     {
  300.       gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, 
  301.                        &x, &y, TRUE, FALSE);
  302.  
  303.       if (move->guide->orientation == ORIENTATION_HORIZONTAL)
  304.         move->guide->position = y;
  305.       else
  306.         move->guide->position = x;
  307.       
  308.       move_draw_guide (gdisp, move->guide);
  309.     }
  310.     }
  311. }
  312.  
  313. static void
  314. move_tool_cursor_update (Tool           *tool,
  315.              GdkEventMotion *mevent,
  316.              gpointer        gdisp_ptr)
  317. {
  318.   MoveTool *move;
  319.   GDisplay *gdisp;
  320.   Guide    *guide;
  321.   Layer    *layer;
  322.   gint      x, y;
  323.  
  324.   move = (MoveTool *) tool->private;
  325.   gdisp = (GDisplay *) gdisp_ptr;
  326.  
  327.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
  328.                    FALSE, FALSE);
  329.  
  330.   if (mevent->state & GDK_MOD1_MASK &&
  331.       !gimage_mask_is_empty (gdisp->gimage))
  332.     {
  333.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  334.                     RECT_SELECT,
  335.                     CURSOR_MODIFIER_MOVE,
  336.                     FALSE);
  337.     }
  338.   else if (mevent->state & GDK_SHIFT_MASK)
  339.     {
  340.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  341.                     MOVE,
  342.                     CURSOR_MODIFIER_NONE,
  343.                     FALSE);
  344.     }
  345.   else
  346.     {
  347.       if (gdisp->draw_guides &&
  348.       (guide = gdisplay_find_guide (gdisp, mevent->x, mevent->y)))
  349.     {
  350.       tool->gdisp_ptr = gdisp_ptr;
  351.       gdisplay_install_tool_cursor (gdisp, GDK_HAND2,
  352.                     TOOL_TYPE_NONE,
  353.                     CURSOR_MODIFIER_HAND,
  354.                     FALSE);
  355.  
  356.       if (tool->state != ACTIVE)
  357.         {
  358.           if (move->guide)
  359.         {
  360.           gdisp = gdisplays_check_valid (move->disp, move->disp->gimage);
  361.           if (gdisp)
  362.             gdisplay_draw_guide (gdisp, move->guide, FALSE);
  363.         }
  364.  
  365.           gdisp = gdisp_ptr;
  366.           gdisplay_draw_guide (gdisp, guide, TRUE);
  367.           move->guide = guide;
  368.           move->disp = gdisp;
  369.         }
  370.     }
  371.       else if ((layer = gimage_pick_correlate_layer (gdisp->gimage, x, y)))
  372.     {
  373.       /*  if there is a floating selection, and this aint it...  */
  374.       if (gimage_floating_sel (gdisp->gimage) &&
  375.           !layer_is_floating_sel (layer))
  376.         gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  377.                       RECT_SELECT,
  378.                       CURSOR_MODIFIER_ANCHOR,
  379.                       FALSE);
  380.       else if (layer == gdisp->gimage->active_layer)
  381.         gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  382.                       MOVE,
  383.                       CURSOR_MODIFIER_NONE,
  384.                       FALSE);
  385.       else
  386.         gdisplay_install_tool_cursor (gdisp, GDK_HAND2,
  387.                       TOOL_TYPE_NONE,
  388.                       CURSOR_MODIFIER_HAND,
  389.                       FALSE);
  390.     }
  391.       else
  392.     {
  393.       gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
  394.                     MOVE,
  395.                     CURSOR_MODIFIER_NONE,
  396.                     FALSE);
  397.     }
  398.     }
  399. }
  400.  
  401.  
  402. static void
  403. move_tool_control (Tool       *tool,
  404.            ToolAction  action,
  405.            gpointer    gdisp_ptr)
  406. {
  407.   MoveTool *move;
  408.  
  409.   move = tool->private;
  410.  
  411.   switch (action)
  412.     {
  413.     case PAUSE:
  414.       break;
  415.  
  416.     case RESUME:
  417.       if (move->guide)
  418.     gdisplay_draw_guide (gdisp_ptr, move->guide, TRUE);
  419.       break;
  420.  
  421.     case HALT:
  422.       break;
  423.  
  424.     default:
  425.       break;
  426.     }
  427. }
  428.  
  429. static void
  430. move_create_gc (GDisplay *gdisp)
  431. {
  432.   if (!move_gc)
  433.     {
  434.       GdkGCValues values;
  435.  
  436.       values.foreground.pixel = gdisplay_white_pixel (gdisp);
  437.       values.function = GDK_INVERT;
  438.       move_gc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  439.                     GDK_GC_FUNCTION);
  440.     }
  441. }
  442.  
  443. void
  444. move_tool_start_hguide (Tool     *tool,
  445.             GDisplay *gdisp)
  446. {
  447.   MoveTool *private;
  448.  
  449.   selection_pause (gdisp->select);
  450.  
  451.   tool->gdisp_ptr = gdisp;
  452.   tool->scroll_lock = TRUE;
  453.  
  454.   private = tool->private;
  455.  
  456.   if (private->guide && private->disp && private->disp->gimage)
  457.     gdisplay_draw_guide (private->disp, private->guide, FALSE);
  458.  
  459.   private->guide = gimage_add_hguide (gdisp->gimage);
  460.   private->disp  = gdisp;
  461.  
  462.   tool->state = ACTIVE;
  463.  
  464.   undo_push_guide (gdisp->gimage, private->guide);
  465. }
  466.  
  467. void
  468. move_tool_start_vguide (Tool     *tool,
  469.             GDisplay *gdisp)
  470. {
  471.   MoveTool *private;
  472.  
  473.   selection_pause (gdisp->select);
  474.  
  475.   tool->gdisp_ptr = gdisp;
  476.   tool->scroll_lock = TRUE;
  477.  
  478.   private = tool->private;
  479.  
  480.   if (private->guide && private->disp && private->disp->gimage)
  481.     gdisplay_draw_guide (private->disp, private->guide, FALSE);
  482.  
  483.   private->guide = gimage_add_vguide (gdisp->gimage);
  484.   private->disp  = gdisp;
  485.  
  486.   tool->state = ACTIVE;
  487.  
  488.   undo_push_guide (gdisp->gimage, private->guide);
  489. }
  490.  
  491. Tool *
  492. tools_new_move_tool (void)
  493. {
  494.   Tool     *tool;
  495.   MoveTool *private;
  496.  
  497.   /*  The tool options  */
  498.   if (! move_options)
  499.     {
  500.       move_options = tool_options_new (_("Move Tool"));
  501.       tools_register (MOVE, (ToolOptions *) move_options);
  502.     }
  503.  
  504.   tool = tools_new_tool (MOVE);
  505.   private = g_new0 (MoveTool, 1);
  506.  
  507.   private->layer = NULL;
  508.   private->guide = NULL;
  509.   private->disp  = NULL;
  510.  
  511.   tool->auto_snap_to = FALSE;  /*  Don't snap to guides  */
  512.  
  513.   tool->private = (void *) private;
  514.  
  515.   tool->button_press_func   = move_tool_button_press;
  516.   tool->button_release_func = move_tool_button_release;
  517.   tool->motion_func         = move_tool_motion;
  518.   tool->arrow_keys_func     = edit_sel_arrow_keys_func;
  519.   tool->cursor_update_func  = move_tool_cursor_update;
  520.   tool->control_func        = move_tool_control;
  521.  
  522.   return tool;
  523. }
  524.  
  525. void
  526. tools_free_move_tool (Tool *tool)
  527. {
  528.   MoveTool *move;
  529.  
  530.   move = (MoveTool *) tool->private;
  531.  
  532.   if (tool->gdisp_ptr)
  533.     {
  534.       if (move->guide)
  535.     gdisplay_draw_guide (tool->gdisp_ptr, move->guide, FALSE);
  536.     }
  537.  
  538.   g_free (move);
  539. }
  540.