mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-23 21:11:43 +00:00
27a4faa0b2
2000-10-22 Sven Neumann <sven@gimp.org> * app/edit_selection.[ch]: plugged memleak (similar to the one that was present in gtkutil_compress_motion()) in the key snooper. Round moves to nearest integer instead of truncating the value. This seems to fix the reported redraw problems when moving selections at low zoom levels. Cleaned up the code a little and converted enum values to uppercase. * app/bezier_select.c * app/free_select.c * app/fuzzy_select.c * app/move.c * app/rect_select.c * app/text_tool.c: updated to use the new EditType enum values. * app/gimprc.c: minor optimization in the GList handling. * app/layer.[ch]: removed unused functions. * app/menus.c: removed "Dump Items (Debug)" menu entry.
741 lines
18 KiB
C
741 lines
18 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "gdk/gdkkeysyms.h"
|
|
|
|
#include "appenv.h"
|
|
#include "gdisplay.h"
|
|
#include "gimage_mask.h"
|
|
#include "edit_selection.h"
|
|
#include "floating_sel.h"
|
|
#include "rect_select.h"
|
|
#include "rect_selectP.h"
|
|
#include "selection_options.h"
|
|
#include "cursorutil.h"
|
|
|
|
#include "libgimp/gimpunitmenu.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
#define STATUSBAR_SIZE 128
|
|
|
|
|
|
/* the rectangular selection tool options */
|
|
static SelectionOptions *rect_options = NULL;
|
|
|
|
/* in gimp, ellipses are rectangular, too ;) */
|
|
extern SelectionOptions *ellipse_options;
|
|
extern void ellipse_select (GimpImage *gimage,
|
|
gint x,
|
|
gint y,
|
|
gint w,
|
|
gint h,
|
|
SelectOps op,
|
|
gboolean antialias,
|
|
gboolean feather,
|
|
gdouble feather_radius);
|
|
|
|
static void selection_tool_update_op_state (RectSelect *rect_sel,
|
|
gint x,
|
|
gint y,
|
|
gint state,
|
|
GDisplay *gdisp);
|
|
|
|
/*************************************/
|
|
/* Rectangular selection apparatus */
|
|
|
|
void
|
|
rect_select (GimpImage *gimage,
|
|
gint x,
|
|
gint y,
|
|
gint w,
|
|
gint h,
|
|
SelectOps op,
|
|
gboolean feather,
|
|
gdouble feather_radius)
|
|
{
|
|
Channel *new_mask;
|
|
|
|
/* if applicable, replace the current selection */
|
|
if (op == SELECTION_REPLACE)
|
|
gimage_mask_clear (gimage);
|
|
else
|
|
gimage_mask_undo (gimage);
|
|
|
|
/* if feathering for rect, make a new mask with the
|
|
* rectangle and feather that with the old mask
|
|
*/
|
|
if (feather)
|
|
{
|
|
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
|
|
channel_combine_rect (new_mask, ADD, x, y, w, h);
|
|
channel_feather (new_mask, gimage_get_mask (gimage),
|
|
feather_radius,
|
|
feather_radius,
|
|
op, 0, 0);
|
|
channel_delete (new_mask);
|
|
}
|
|
else if (op == SELECTION_INTERSECT)
|
|
{
|
|
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
|
|
channel_combine_rect (new_mask, ADD, x, y, w, h);
|
|
channel_combine_mask (gimage_get_mask (gimage), new_mask, op, 0, 0);
|
|
channel_delete (new_mask);
|
|
}
|
|
else
|
|
channel_combine_rect (gimage_get_mask (gimage), op, x, y, w, h);
|
|
}
|
|
|
|
void
|
|
rect_select_button_press (Tool *tool,
|
|
GdkEventButton *bevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
GDisplay *gdisp;
|
|
RectSelect *rect_sel;
|
|
gchar select_mode[STATUSBAR_SIZE];
|
|
gint x, y;
|
|
GimpUnit unit = GIMP_UNIT_PIXEL;
|
|
gdouble unit_factor;
|
|
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0);
|
|
|
|
rect_sel->x = x;
|
|
rect_sel->y = y;
|
|
switch (tool->type)
|
|
{
|
|
case RECT_SELECT:
|
|
rect_sel->fixed_size = rect_options->fixed_size;
|
|
rect_sel->fixed_width = rect_options->fixed_width;
|
|
rect_sel->fixed_height = rect_options->fixed_height;
|
|
unit = rect_options->fixed_unit;
|
|
break;
|
|
case ELLIPSE_SELECT:
|
|
rect_sel->fixed_size = ellipse_options->fixed_size;
|
|
rect_sel->fixed_width = ellipse_options->fixed_width;
|
|
rect_sel->fixed_height = ellipse_options->fixed_height;
|
|
unit = ellipse_options->fixed_unit;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (unit)
|
|
{
|
|
case GIMP_UNIT_PIXEL:
|
|
break;
|
|
case GIMP_UNIT_PERCENT:
|
|
rect_sel->fixed_width =
|
|
gdisp->gimage->width * rect_sel->fixed_width / 100;
|
|
rect_sel->fixed_height =
|
|
gdisp->gimage->height * rect_sel->fixed_height / 100;
|
|
break;
|
|
default:
|
|
unit_factor = gimp_unit_get_factor (unit);
|
|
rect_sel->fixed_width =
|
|
rect_sel->fixed_width * gdisp->gimage->xresolution / unit_factor;
|
|
rect_sel->fixed_height =
|
|
rect_sel->fixed_height * gdisp->gimage->yresolution / unit_factor;
|
|
break;
|
|
}
|
|
|
|
rect_sel->fixed_width = MAX (1, rect_sel->fixed_width);
|
|
rect_sel->fixed_height = MAX (1, rect_sel->fixed_height);
|
|
|
|
rect_sel->w = 0;
|
|
rect_sel->h = 0;
|
|
|
|
rect_sel->center = FALSE;
|
|
|
|
gdk_pointer_grab (gdisp->canvas->window, FALSE,
|
|
GDK_POINTER_MOTION_HINT_MASK |
|
|
GDK_BUTTON1_MOTION_MASK |
|
|
GDK_BUTTON_RELEASE_MASK,
|
|
NULL, NULL, bevent->time);
|
|
|
|
tool->state = ACTIVE;
|
|
tool->gdisp_ptr = gdisp_ptr;
|
|
|
|
switch (rect_sel->op)
|
|
{
|
|
case SELECTION_MOVE_MASK:
|
|
init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE);
|
|
return;
|
|
case SELECTION_MOVE:
|
|
init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* initialize the statusbar display */
|
|
rect_sel->context_id =
|
|
gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "selection");
|
|
switch (rect_sel->op)
|
|
{
|
|
case SELECTION_ADD:
|
|
g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: ADD"));
|
|
break;
|
|
case SELECTION_SUB:
|
|
g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: SUBTRACT"));
|
|
break;
|
|
case SELECTION_INTERSECT:
|
|
g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: INTERSECT"));
|
|
break;
|
|
case SELECTION_REPLACE:
|
|
g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: REPLACE"));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar),
|
|
rect_sel->context_id, select_mode);
|
|
|
|
draw_core_start (rect_sel->core, gdisp->canvas->window, tool);
|
|
}
|
|
|
|
void
|
|
rect_select_button_release (Tool *tool,
|
|
GdkEventButton *bevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
GDisplay *gdisp;
|
|
gint x1, y1;
|
|
gint x2, y2;
|
|
gint w, h;
|
|
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
gdk_pointer_ungrab (bevent->time);
|
|
gdk_flush ();
|
|
|
|
gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id);
|
|
|
|
draw_core_stop (rect_sel->core, tool);
|
|
tool->state = INACTIVE;
|
|
|
|
/* First take care of the case where the user "cancels" the action */
|
|
if (! (bevent->state & GDK_BUTTON3_MASK))
|
|
{
|
|
x1 = (rect_sel->w < 0) ? rect_sel->x + rect_sel->w : rect_sel->x;
|
|
y1 = (rect_sel->h < 0) ? rect_sel->y + rect_sel->h : rect_sel->y;
|
|
w = (rect_sel->w < 0) ? -rect_sel->w : rect_sel->w;
|
|
h = (rect_sel->h < 0) ? -rect_sel->h : rect_sel->h;
|
|
|
|
if ((!w || !h) && !rect_sel->fixed_size)
|
|
{
|
|
/* If there is a floating selection, anchor it */
|
|
if (gimage_floating_sel (gdisp->gimage))
|
|
floating_sel_anchor (gimage_floating_sel (gdisp->gimage));
|
|
/* Otherwise, clear the selection mask */
|
|
else
|
|
gimage_mask_clear (gdisp->gimage);
|
|
|
|
gdisplays_flush ();
|
|
return;
|
|
}
|
|
|
|
x2 = x1 + w;
|
|
y2 = y1 + h;
|
|
|
|
switch (tool->type)
|
|
{
|
|
case RECT_SELECT:
|
|
rect_select (gdisp->gimage,
|
|
x1, y1, (x2 - x1), (y2 - y1),
|
|
rect_sel->op,
|
|
rect_options->feather,
|
|
rect_options->feather_radius);
|
|
break;
|
|
|
|
case ELLIPSE_SELECT:
|
|
ellipse_select (gdisp->gimage,
|
|
x1, y1, (x2 - x1), (y2 - y1),
|
|
rect_sel->op,
|
|
ellipse_options->antialias,
|
|
ellipse_options->feather,
|
|
ellipse_options->feather_radius);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* show selection on all views */
|
|
gdisplays_flush ();
|
|
}
|
|
}
|
|
|
|
void
|
|
rect_select_motion (Tool *tool,
|
|
GdkEventMotion *mevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
GDisplay *gdisp;
|
|
gchar size[STATUSBAR_SIZE];
|
|
gint ox, oy;
|
|
gint x, y;
|
|
gint w, h, s;
|
|
gint tw, th;
|
|
gdouble ratio;
|
|
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
/* needed for immediate cursor update on modifier event */
|
|
rect_sel->current_x = mevent->x;
|
|
rect_sel->current_y = mevent->y;
|
|
|
|
if (tool->state != ACTIVE)
|
|
return;
|
|
|
|
if (rect_sel->op == SELECTION_ANCHOR)
|
|
{
|
|
rect_sel->op = SELECTION_REPLACE;
|
|
|
|
rect_select_cursor_update (tool, mevent, gdisp_ptr);
|
|
}
|
|
|
|
draw_core_pause (rect_sel->core, tool);
|
|
|
|
/* Calculate starting point */
|
|
|
|
if (rect_sel->center)
|
|
{
|
|
ox = rect_sel->x + rect_sel->w / 2;
|
|
oy = rect_sel->y + rect_sel->h / 2;
|
|
}
|
|
else
|
|
{
|
|
ox = rect_sel->x;
|
|
oy = rect_sel->y;
|
|
}
|
|
|
|
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0);
|
|
if (rect_sel->fixed_size)
|
|
{
|
|
if (mevent->state & GDK_SHIFT_MASK)
|
|
{
|
|
ratio = (double)(rect_sel->fixed_height /
|
|
(double)rect_sel->fixed_width);
|
|
tw = x - ox;
|
|
th = y - oy;
|
|
/*
|
|
* This is probably an inefficient way to do it, but it gives
|
|
* nicer, more predictable results than the original agorithm
|
|
*/
|
|
|
|
if ((abs(th) < (ratio * abs(tw))) && (abs(tw) > (abs(th) / ratio)))
|
|
{
|
|
w = tw;
|
|
h = (int)(tw * ratio);
|
|
/* h should have the sign of th */
|
|
if ((th < 0 && h > 0) || (th > 0 && h < 0))
|
|
h = -h;
|
|
}
|
|
else
|
|
{
|
|
h = th;
|
|
w = (int)(th / ratio);
|
|
/* w should have the sign of tw */
|
|
if ((tw < 0 && w > 0) || (tw > 0 && w < 0))
|
|
w = -w;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
w = (x - ox > 0 ? rect_sel->fixed_width : -rect_sel->fixed_width);
|
|
h = (y - oy > 0 ? rect_sel->fixed_height : -rect_sel->fixed_height);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
w = (x - ox);
|
|
h = (y - oy);
|
|
}
|
|
|
|
/* If the shift key is down, then make the rectangle square (or ellipse circular) */
|
|
if ((mevent->state & GDK_SHIFT_MASK) && !rect_sel->fixed_size)
|
|
{
|
|
s = MAX (abs (w), abs (h));
|
|
|
|
if (w < 0)
|
|
w = -s;
|
|
else
|
|
w = s;
|
|
|
|
if (h < 0)
|
|
h = -s;
|
|
else
|
|
h = s;
|
|
}
|
|
|
|
/* If the control key is down, create the selection from the center out */
|
|
if (mevent->state & GDK_CONTROL_MASK)
|
|
{
|
|
if (rect_sel->fixed_size)
|
|
{
|
|
if (mevent->state & GDK_SHIFT_MASK)
|
|
{
|
|
rect_sel->x = ox - w;
|
|
rect_sel->y = oy - h;
|
|
rect_sel->w = w * 2;
|
|
rect_sel->h = h * 2;
|
|
}
|
|
else
|
|
{
|
|
rect_sel->x = ox - w / 2;
|
|
rect_sel->y = oy - h / 2;
|
|
rect_sel->w = w;
|
|
rect_sel->h = h;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
w = abs(w);
|
|
h = abs(h);
|
|
|
|
rect_sel->x = ox - w;
|
|
rect_sel->y = oy - h;
|
|
rect_sel->w = 2 * w + 1;
|
|
rect_sel->h = 2 * h + 1;
|
|
}
|
|
rect_sel->center = TRUE;
|
|
}
|
|
else
|
|
{
|
|
rect_sel->x = ox;
|
|
rect_sel->y = oy;
|
|
rect_sel->w = w;
|
|
rect_sel->h = h;
|
|
|
|
rect_sel->center = FALSE;
|
|
}
|
|
|
|
gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id);
|
|
if (gdisp->dot_for_dot)
|
|
{
|
|
g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str,
|
|
_("Selection: "), abs(rect_sel->w), " x ", abs(rect_sel->h));
|
|
}
|
|
else /* show real world units */
|
|
{
|
|
gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
|
|
|
|
g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str,
|
|
_("Selection: "),
|
|
(gdouble) abs(rect_sel->w) * unit_factor /
|
|
gdisp->gimage->xresolution,
|
|
" x ",
|
|
(gdouble) abs(rect_sel->h) * unit_factor /
|
|
gdisp->gimage->yresolution);
|
|
}
|
|
gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id,
|
|
size);
|
|
|
|
draw_core_resume (rect_sel->core, tool);
|
|
}
|
|
|
|
void
|
|
rect_select_draw (Tool *tool)
|
|
{
|
|
GDisplay *gdisp;
|
|
RectSelect *rect_sel;
|
|
gint x1, y1;
|
|
gint x2, y2;
|
|
|
|
gdisp = (GDisplay *) tool->gdisp_ptr;
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
x1 = MIN (rect_sel->x, rect_sel->x + rect_sel->w);
|
|
y1 = MIN (rect_sel->y, rect_sel->y + rect_sel->h);
|
|
x2 = MAX (rect_sel->x, rect_sel->x + rect_sel->w);
|
|
y2 = MAX (rect_sel->y, rect_sel->y + rect_sel->h);
|
|
|
|
gdisplay_transform_coords (gdisp, x1, y1, &x1, &y1, 0);
|
|
gdisplay_transform_coords (gdisp, x2, y2, &x2, &y2, 0);
|
|
|
|
gdk_draw_rectangle (rect_sel->core->win,
|
|
rect_sel->core->gc, 0,
|
|
x1, y1, (x2 - x1), (y2 - y1));
|
|
}
|
|
|
|
static void
|
|
selection_tool_update_op_state (RectSelect *rect_sel,
|
|
gint x,
|
|
gint y,
|
|
gint state,
|
|
GDisplay *gdisp)
|
|
{
|
|
Layer *layer;
|
|
Layer *floating_sel;
|
|
gint tx, ty;
|
|
|
|
if (active_tool->state == ACTIVE)
|
|
return;
|
|
|
|
gdisplay_untransform_coords (gdisp, x, y, &tx, &ty, FALSE, FALSE);
|
|
|
|
layer = gimage_pick_correlate_layer (gdisp->gimage, tx, ty);
|
|
floating_sel = gimage_floating_sel (gdisp->gimage);
|
|
|
|
if (state & GDK_MOD1_MASK &&
|
|
!gimage_mask_is_empty (gdisp->gimage))
|
|
{
|
|
rect_sel->op = SELECTION_MOVE_MASK; /* move just the selection mask */
|
|
}
|
|
else if (!(state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) &&
|
|
layer &&
|
|
(layer == floating_sel ||
|
|
(gdisplay_mask_value (gdisp, x, y) &&
|
|
floating_sel == NULL)))
|
|
{
|
|
rect_sel->op = SELECTION_MOVE; /* move the selection */
|
|
}
|
|
else if ((state & GDK_SHIFT_MASK) &&
|
|
!(state & GDK_CONTROL_MASK))
|
|
{
|
|
rect_sel->op = SELECTION_ADD; /* add to the selection */
|
|
}
|
|
else if ((state & GDK_CONTROL_MASK) &&
|
|
!(state & GDK_SHIFT_MASK))
|
|
{
|
|
rect_sel->op = SELECTION_SUB; /* subtract from the selection */
|
|
}
|
|
else if ((state & GDK_CONTROL_MASK) &&
|
|
(state & GDK_SHIFT_MASK))
|
|
{
|
|
rect_sel->op = SELECTION_INTERSECT; /* intersect with selection */
|
|
}
|
|
else if (floating_sel)
|
|
{
|
|
rect_sel->op = SELECTION_ANCHOR; /* anchor the selection */
|
|
}
|
|
else
|
|
{
|
|
rect_sel->op = SELECTION_REPLACE; /* replace the selection */
|
|
}
|
|
}
|
|
|
|
void
|
|
rect_select_oper_update (Tool *tool,
|
|
GdkEventMotion *mevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
rect_sel->current_x = mevent->x;
|
|
rect_sel->current_y = mevent->y;
|
|
|
|
selection_tool_update_op_state (rect_sel,
|
|
rect_sel->current_x,
|
|
rect_sel->current_y,
|
|
mevent->state, gdisp_ptr);
|
|
}
|
|
|
|
void
|
|
rect_select_modifier_update (Tool *tool,
|
|
GdkEventKey *kevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
gint state;
|
|
|
|
state = kevent->state;
|
|
|
|
switch (kevent->keyval)
|
|
{
|
|
case GDK_Alt_L: case GDK_Alt_R:
|
|
if (state & GDK_MOD1_MASK)
|
|
state &= ~GDK_MOD1_MASK;
|
|
else
|
|
state |= GDK_MOD1_MASK;
|
|
break;
|
|
|
|
case GDK_Shift_L: case GDK_Shift_R:
|
|
if (state & GDK_SHIFT_MASK)
|
|
state &= ~GDK_SHIFT_MASK;
|
|
else
|
|
state |= GDK_SHIFT_MASK;
|
|
break;
|
|
|
|
case GDK_Control_L: case GDK_Control_R:
|
|
if (state & GDK_CONTROL_MASK)
|
|
state &= ~GDK_CONTROL_MASK;
|
|
else
|
|
state |= GDK_CONTROL_MASK;
|
|
break;
|
|
}
|
|
|
|
rect_sel = (RectSelect *) tool->private;
|
|
selection_tool_update_op_state (rect_sel,
|
|
rect_sel->current_x,
|
|
rect_sel->current_y,
|
|
state, gdisp_ptr);
|
|
}
|
|
|
|
void
|
|
rect_select_cursor_update (Tool *tool,
|
|
GdkEventMotion *mevent,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
GDisplay *gdisp;
|
|
|
|
rect_sel = (RectSelect *) tool->private;
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
|
|
switch (rect_sel->op)
|
|
{
|
|
case SELECTION_ADD:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_PLUS,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_SUB:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_MINUS,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_INTERSECT:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_INTERSECT,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_REPLACE:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_NONE,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_MOVE_MASK:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_MOVE,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_MOVE:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
MOVE,
|
|
CURSOR_MODIFIER_NONE,
|
|
FALSE);
|
|
break;
|
|
case SELECTION_ANCHOR:
|
|
gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
|
|
tool->type,
|
|
CURSOR_MODIFIER_ANCHOR,
|
|
FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
rect_select_control (Tool *tool,
|
|
ToolAction action,
|
|
gpointer gdisp_ptr)
|
|
{
|
|
RectSelect *rect_sel;
|
|
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
switch (action)
|
|
{
|
|
case PAUSE:
|
|
draw_core_pause (rect_sel->core, tool);
|
|
break;
|
|
|
|
case RESUME:
|
|
draw_core_resume (rect_sel->core, tool);
|
|
break;
|
|
|
|
case HALT:
|
|
draw_core_stop (rect_sel->core, tool);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
rect_select_options_reset (void)
|
|
{
|
|
selection_options_reset (rect_options);
|
|
}
|
|
|
|
Tool *
|
|
tools_new_rect_select (void)
|
|
{
|
|
Tool * tool;
|
|
RectSelect * private;
|
|
|
|
/* The tool options */
|
|
if (! rect_options)
|
|
{
|
|
rect_options =
|
|
selection_options_new (RECT_SELECT, rect_select_options_reset);
|
|
tools_register (RECT_SELECT, (ToolOptions *) rect_options);
|
|
}
|
|
|
|
tool = tools_new_tool (RECT_SELECT);
|
|
private = g_new0 (RectSelect, 1);
|
|
|
|
private->core = draw_core_new (rect_select_draw);
|
|
private->x = private->y = 0;
|
|
private->w = private->h = 0;
|
|
private->op = SELECTION_REPLACE;
|
|
|
|
tool->private = (void *) private;
|
|
|
|
tool->button_press_func = rect_select_button_press;
|
|
tool->button_release_func = rect_select_button_release;
|
|
tool->motion_func = rect_select_motion;
|
|
tool->modifier_key_func = rect_select_modifier_update;
|
|
tool->cursor_update_func = rect_select_cursor_update;
|
|
tool->oper_update_func = rect_select_oper_update;
|
|
tool->control_func = rect_select_control;
|
|
|
|
return tool;
|
|
}
|
|
|
|
void
|
|
tools_free_rect_select (Tool *tool)
|
|
{
|
|
RectSelect * rect_sel;
|
|
|
|
rect_sel = (RectSelect *) tool->private;
|
|
|
|
draw_core_free (rect_sel->core);
|
|
g_free (rect_sel);
|
|
}
|