[gimp/soc-2013-combined-selection-tool] app: selectbyshapetool added base functions
- From: Ajay Ramanathan <ajayr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2013-combined-selection-tool] app: selectbyshapetool added base functions
- Date: Fri, 26 Jul 2013 13:11:06 +0000 (UTC)
commit 016669bfa69398b48be677b60c2c8bb4d06da7da
Author: Ajay Ramanathan <ajay 010293 gmail com>
Date: Fri Jul 26 18:37:59 2013 +0530
app: selectbyshapetool added base functions
app/tools/gimpselectbyshapetool.c | 957 ++++++++++++++++++++++++++++++++++---
app/tools/gimpselectbyshapetool.h | 17 +-
2 files changed, 896 insertions(+), 78 deletions(-)
---
diff --git a/app/tools/gimpselectbyshapetool.c b/app/tools/gimpselectbyshapetool.c
index 8c6ad5a..582d724 100644
--- a/app/tools/gimpselectbyshapetool.c
+++ b/app/tools/gimpselectbyshapetool.c
@@ -20,39 +20,135 @@
#include <gegl.h>
#include <gtk/gtk.h>
+#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
+#include "core/gimpchannel.h"
#include "core/gimpchannel-select.h"
+#include "core/gimplayer-floating-sel.h"
#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimppickable.h"
+#include "core/gimp-utils.h"
+#include "core/gimpundostack.h"
+#include "widgets/gimpdialogfactory.h"
#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpviewabledialog.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "display/gimpcanvasgroup.h"
#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-transform.h"
+#include "display/gimpdisplayshell-appearance.h"
+#include "gimpeditselectiontool.h"
+#include "gimpselectiontool.h"
+#include "gimpselectionoptions.h"
+#include "gimprectangletool.h"
+#include "gimprectangleoptions.h"
#include "gimpselectbyshapetool.h"
#include "gimprectangleselectoptions.h"
#include "gimptoolcontrol.h"
#include "gimp-intl.h"
+typedef struct GimpSelectByShapeToolPrivate
+{
+ GimpChannelOps operation; /* remember for use when modifying */
+ gboolean use_saved_op; /* use operation or get from options */
+ gboolean saved_show_selection; /* used to remember existing value */
+ GimpUndo *undo;
+ GimpUndo *redo;
-static void gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool);
+ gboolean round_corners;
+ gdouble corner_radius;
-static void gimp_select_by_shape_tool_select (GimpRectangleSelectTool *rect_tool,
- GimpChannelOps operation,
- gint x,
- gint y,
- gint w,
- gint h);
+ gdouble press_x;
+ gdouble press_y;
+} GimpSelectByShapeToolPrivate;
+#define GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE(obj) \
+ ((GimpSelectByShapeToolPrivate *) ((GimpSelectByShapeTool *) (obj))->priv)
-G_DEFINE_TYPE (GimpSelectByShapeTool, gimp_select_by_shape_tool,
- GIMP_TYPE_RECTANGLE_SELECT_TOOL)
-#define parent_class gimp_select_by_shape_tool_parent_class
+static void gimp_select_by_shape_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface);
+
+static void gimp_select_by_shape_tool_constructed (GObject *object);
+
+static void gimp_select_by_shape_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_button_press (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_button_release (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_active_modifier_key
+ (GimpTool *tool,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state,
+ GimpDisplay *display);
+static gboolean gimp_select_by_shape_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_oper_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_cursor_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ GimpDisplay *display);
+static void gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool);
+static gboolean gimp_select_by_shape_tool_select (GimpRectangleTool *rect_tool,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
+static gboolean gimp_select_by_shape_tool_execute (GimpRectangleTool *rect_tool,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
+static void gimp_select_by_shape_tool_cancel (GimpRectangleTool *rect_tool);
+static gboolean gimp_select_by_shape_tool_rectangle_change_complete
+ (GimpRectangleTool *rect_tool);
+static void gimp_select_by_shape_tool_real_select (GimpSelectByShapeTool *rect_sel_tool,
+ GimpChannelOps operation,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
+static GimpChannelOps
+ gimp_select_by_shape_tool_get_operation (GimpSelectByShapeTool *rect_sel_tool);
+static void gimp_select_by_shape_tool_update_option_defaults
+ (GimpSelectByShapeTool *rect_sel_tool,
+ gboolean ignore_pending);
+
+static void gimp_select_by_shape_tool_round_corners_notify
+ (GimpRectangleSelectOptions *options,
+ GParamSpec *pspec,
+ GimpSelectByShapeTool *rect_sel_tool);
+
+G_DEFINE_TYPE_WITH_CODE (GimpSelectByShapeTool, gimp_select_by_shape_tool,
+ GIMP_TYPE_SELECTION_TOOL,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_TOOL,
+ gimp_select_by_shape_tool_rectangle_tool_iface_init))
+#define parent_class gimp_select_by_shape_tool_parent_class
void
gimp_select_by_shape_tool_register (GimpToolRegisterCallback callback,
@@ -69,67 +165,125 @@ gimp_select_by_shape_tool_register (GimpToolRegisterCallback callback,
NULL, GIMP_HELP_TOOL_SELECT_BY_SHAPE,
GIMP_STOCK_TOOL_SELECT_BY_SHAPE,
data);
-}
+}
static void
gimp_select_by_shape_tool_class_init (GimpSelectByShapeToolClass *klass)
{
- GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
- GimpRectangleSelectToolClass *rect_tool_class = GIMP_RECTANGLE_SELECT_TOOL_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+ GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GimpSelectByShapeToolPrivate));
+
+ object_class->constructed = gimp_select_by_shape_tool_constructed;
+ object_class->set_property = gimp_rectangle_tool_set_property;
+ object_class->get_property = gimp_rectangle_tool_get_property;
+
+ tool_class->control = gimp_select_by_shape_tool_control;
+ tool_class->button_press = gimp_select_by_shape_tool_button_press;
+ tool_class->button_release = gimp_select_by_shape_tool_button_release;
+ tool_class->motion = gimp_rectangle_tool_motion;
+ tool_class->key_press = gimp_select_by_shape_tool_key_press;
+ tool_class->active_modifier_key = gimp_select_by_shape_tool_active_modifier_key;
+ tool_class->oper_update = gimp_select_by_shape_tool_oper_update;
+ tool_class->cursor_update = gimp_select_by_shape_tool_cursor_update;
+
+ draw_tool_class->draw = gimp_select_by_shape_tool_draw;
- draw_tool_class->draw = gimp_select_by_shape_tool_draw;
+ klass->select = gimp_select_by_shape_tool_real_select;
- rect_tool_class->select = gimp_select_by_shape_tool_select;
+ gimp_rectangle_tool_install_properties (object_class);
}
static void
-gimp_select_by_shape_tool_init (GimpSelectByShapeTool *select_by_shape)
+gimp_select_by_shape_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface)
{
- GimpTool *tool = GIMP_TOOL (select_by_shape);
+ iface->execute = gimp_select_by_shape_tool_execute;
+ iface->cancel = gimp_select_by_shape_tool_cancel;
+ iface->rectangle_change_complete = gimp_select_by_shape_tool_rectangle_change_complete;
+}
+
+static void
+gimp_select_by_shape_tool_init (GimpSelectByShapeTool *rect_sel_tool)
+{
+ GimpTool *tool = GIMP_TOOL (rect_sel_tool);
+ GimpSelectByShapeToolPrivate *priv;
+
+ gimp_rectangle_tool_init (GIMP_RECTANGLE_TOOL (rect_sel_tool));
+
+ rect_sel_tool->priv = G_TYPE_INSTANCE_GET_PRIVATE (rect_sel_tool,
+ GIMP_TYPE_SELECT_BY_SHAPE_TOOL,
+ GimpSelectByShapeToolPrivate);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ gimp_tool_control_set_wants_click (tool->control, TRUE);
+ gimp_tool_control_set_precision (tool->control,
+ GIMP_CURSOR_PRECISION_PIXEL_BORDER);
gimp_tool_control_set_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_ELLIPSE_SELECT);
- //Need to add new Cursors :'(
+ GIMP_TOOL_CURSOR_RECT_SELECT);
+ gimp_tool_control_set_preserve (tool->control, FALSE);
+ gimp_tool_control_set_dirty_mask (tool->control,
+ GIMP_DIRTY_IMAGE_SIZE |
+ GIMP_DIRTY_SELECTION);
+
+ priv->undo = NULL;
+ priv->redo = NULL;
+
+ priv->press_x = 0.0;
+ priv->press_y = 0.0;
}
static void
-gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool)
+gimp_select_by_shape_tool_constructed (GObject *object)
{
- GimpCanvasGroup *stroke_group = NULL;
- /*GimpSelectByShapeTool *shp_sel_tool;
- GimpSelectByShapeTool *priv;
-
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpRectangleSelectOptions *options;
+ GimpSelectByShapeToolPrivate *priv;
- gint x1, y1, x2, y2;
+ G_OBJECT_CLASS (parent_class)->constructed (object);
- GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
- shp_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (draw_tool);
- priv = GIMP_SELECT_BY_SHAPE_TOOL_GET (shp_sel_tool);
-
- switch(priv->shape_type)
- {
- case GIMP_SHAPE_RECTANGLE :
- gimp_rectangle_tool_draw (draw_tool, stroke_group);
- break;
+ gimp_rectangle_tool_constructor (object);
- case GIMP_SHAPE_ELLIPSE :
- {
- g_object_get (draw_tool,
- "x1", &x1,
- "y1", &y1,
- "x2", &x2,
- "y2", &y2,
- NULL);
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (object);
+ options = GIMP_SELECT_BY_SHAPE_TOOL_GET_OPTIONS (rect_sel_tool);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
- gimp_draw_tool_add_arc (draw_tool,
- FALSE,
- x1, y1,
- x2 - x1, y2 - y1,
- 0.0, 2 * G_PI);
- break;
- }
+ priv->round_corners = options->round_corners;
+ priv->corner_radius = options->corner_radius;
- case GIMP_SHAPE_ROUNDED_RECT :
+ g_signal_connect_object (options, "notify::round-corners",
+ G_CALLBACK (gimp_select_by_shape_tool_round_corners_notify),
+ object, 0);
+ g_signal_connect_object (options, "notify::corner-radius",
+ G_CALLBACK (gimp_select_by_shape_tool_round_corners_notify),
+ object, 0);
+
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool, FALSE);
+}
+
+static void
+gimp_select_by_shape_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display)
+{
+ gimp_rectangle_tool_control (tool, action, display);
+
+ GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
+}
+
+static void
+gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool)
+{
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpSelectByShapeToolPrivate *priv;
+ GimpCanvasGroup *stroke_group = NULL;
+
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (draw_tool);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ if (priv->round_corners)
{
GimpCanvasItem *item;
gint x1, y1, x2, y2;
@@ -178,36 +332,284 @@ gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool)
G_PI, G_PI / 2.0);
gimp_canvas_group_add_item (stroke_group, item);
gimp_draw_tool_remove_item (draw_tool, item);
- break;
}
- default
- {
- gimp_rectangle_tool_draw (draw_tool, stroke_group);
- break;
- }
- }*/
+
gimp_rectangle_tool_draw (draw_tool, stroke_group);
+} //Need to edit this.
+
+static void
+gimp_select_by_shape_tool_button_press (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type,
+ GimpDisplay *display)
+{
+ GimpRectangleTool *rectangle;
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpDisplayShell *shell;
+ GimpSelectByShapeToolPrivate *priv;
+ GimpRectangleFunction function;
+
+ rectangle = GIMP_RECTANGLE_TOOL (tool);
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (tool);
+ shell = gimp_display_get_shell (display);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ if (tool->display && display != tool->display)
+ {
+ gimp_rectangle_tool_cancel (GIMP_RECTANGLE_TOOL (tool));
+ }
+
+ if (gimp_selection_tool_start_edit (GIMP_SELECTION_TOOL (tool),
+ display, coords))
+ {
+ gimp_rectangle_tool_execute (rectangle);
+ gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool,
+ TRUE);
+ return;
+ }
+
+ gimp_tool_control_activate (tool->control);
+
+ priv->saved_show_selection = gimp_display_shell_get_show_selection (shell);
+
+ /* if the shift or ctrl keys are down, we don't want to adjust, we
+ * want to create a new rectangle, regardless of pointer loc */
+ if (state & (gimp_get_extend_selection_mask () |
+ gimp_get_modify_selection_mask ()))
+ {
+ gimp_rectangle_tool_set_function (rectangle,
+ GIMP_RECTANGLE_TOOL_CREATING);
+ }
+
+ gimp_rectangle_tool_button_press (tool, coords, time, state, display);
+
+ priv->press_x = coords->x;
+ priv->press_y = coords->y;
+
+ /* if we have an existing rectangle in the current display, then
+ * we have already "executed", and need to undo at this point,
+ * unless the user has done something in the meantime
+ */
+ function = gimp_rectangle_tool_get_function (rectangle);
+
+ if (function == GIMP_RECTANGLE_TOOL_CREATING)
+ {
+ priv->use_saved_op = FALSE;
+ }
+ else
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+ GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
+ GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image);
+ GimpUndo *undo;
+ GimpChannelOps operation;
+
+ undo = gimp_undo_stack_peek (undo_stack);
+
+ if (undo && priv->undo == undo)
+ {
+ /* prevent this change from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ gimp_image_undo (image);
+
+ gimp_tool_control_pop_preserve (tool->control);
+
+ /* we will need to redo if the user cancels or executes */
+ priv->redo = gimp_undo_stack_peek (redo_stack);
+ }
+
+ /* if the operation is "Replace", turn off the marching ants,
+ because they are confusing */
+ operation = gimp_select_by_shape_tool_get_operation (rect_sel_tool);
+
+ if (operation == GIMP_CHANNEL_OP_REPLACE)
+ gimp_display_shell_set_show_selection (shell, FALSE);
+ }
+
+ priv->undo = NULL;
}
+static void
+gimp_select_by_shape_tool_button_release (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type,
+ GimpDisplay *display)
+{
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpSelectByShapeToolPrivate *priv;
+ GimpImage *image;
+
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (tool);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ image = gimp_display_get_image (tool->display);
+
+ gimp_tool_control_halt (tool->control);
+
+ gimp_tool_pop_status (tool, display);
+ gimp_display_shell_set_show_selection (gimp_display_get_shell (display),
+ priv->saved_show_selection);
+
+ /*
+ * if the user has not moved the mouse, we need to redo the operation
+ * that was undone on button press.
+ */
+ if (release_type == GIMP_BUTTON_RELEASE_CLICK)
+ {
+ GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image);
+ GimpUndo *redo = gimp_undo_stack_peek (redo_stack);
+
+ if (redo && priv->redo == redo)
+ {
+ /* prevent this from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ gimp_image_redo (image);
+ priv->redo = NULL;
+
+ gimp_tool_control_pop_preserve (tool->control);
+ }
+ }
+
+ gimp_rectangle_tool_button_release (tool, coords, time, state, release_type,
+ display);
+
+ if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
+ {
+ if (priv->redo)
+ {
+ /* prevent this from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ gimp_image_redo (image);
+
+ gimp_tool_control_pop_preserve (tool->control);
+ }
+
+ priv->use_saved_op = TRUE; /* is this correct? */
+ }
+
+ priv->redo = NULL;
+}
static void
-gimp_select_by_shape_tool_select (GimpRectangleSelectTool *rect_tool,
- GimpChannelOps operation,
- gint x,
- gint y,
- gint w,
- gint h)
+gimp_select_by_shape_tool_active_modifier_key (GimpTool *tool,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state,
+ GimpDisplay *display)
{
- GimpTool *tool = GIMP_TOOL (rect_tool);
- GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (rect_tool);
- GimpRectangleSelectOptions *sel_options = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (tool);
+ GIMP_TOOL_CLASS (parent_class)->active_modifier_key (tool, key, press, state,
+ display);
+
+ gimp_rectangle_tool_active_modifier_key (tool, key, press, state, display);
+}
+
+static gboolean
+gimp_select_by_shape_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display)
+{
+ return (gimp_rectangle_tool_key_press (tool, kevent, display) ||
+ gimp_edit_selection_tool_key_press (tool, kevent, display));
+}
+
+static void
+gimp_select_by_shape_tool_oper_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity,
+ GimpDisplay *display)
+{
+ gimp_rectangle_tool_oper_update (tool, coords, state, proximity, display);
+
+ GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
+ display);
+}
+
+static void
+gimp_select_by_shape_tool_cursor_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ GimpDisplay *display)
+{
+ gimp_rectangle_tool_cursor_update (tool, coords, state, display);
+
+ /* override the previous if shift or ctrl are down */
+ if (state & (gimp_get_extend_selection_mask () |
+ gimp_get_modify_selection_mask ()))
+ {
+ gimp_tool_control_set_cursor (tool->control,
+ GIMP_CURSOR_CROSSHAIR_SMALL);
+ }
+
+ GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
+}
+
+
+static gboolean
+gimp_select_by_shape_tool_select (GimpRectangleTool *rectangle,
+ gint x,
+ gint y,
+ gint w,
+ gint h)
+{
+ GimpTool *tool;
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpImage *image;
+ gboolean rectangle_exists;
+ GimpChannelOps operation;
+
+ tool = GIMP_TOOL (rectangle);
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (rectangle);
+
+ image = gimp_display_get_image (tool->display);
+
+ gimp_tool_pop_status (tool, tool->display);
+
+ rectangle_exists = (x <= gimp_image_get_width (image) &&
+ y <= gimp_image_get_height (image) &&
+ x + w >= 0 &&
+ y + h >= 0 &&
+ w > 0 &&
+ h > 0);
+
+ operation = gimp_select_by_shape_tool_get_operation (rect_sel_tool);
+
+ /* if rectangle exists, turn it into a selection */
+ if (rectangle_exists)
+ GIMP_SELECT_BY_SHAPE_TOOL_GET_CLASS (rect_sel_tool)->select (rect_sel_tool,
+ operation,
+ x, y, w, h);
+
+ return rectangle_exists;
+}
+
+static void
+gimp_select_by_shape_tool_real_select (GimpSelectByShapeTool *rect_sel_tool,
+ GimpChannelOps operation,
+ gint x,
+ gint y,
+ gint w,
+ gint h)
+{
+ GimpTool *tool = GIMP_TOOL (rect_sel_tool);
+ GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
+ GimpRectangleOptions *shape_select_options;
GimpChannel *channel;
- GimpImage *image;
-
- channel = gimp_image_get_mask (gimp_display_get_image (tool->display));
- image = gimp_display_get_image (tool->display);
+ GimpImage *image;
+
+ shape_select_options = GIMP_SELECT_BY_SHAPE_TOOL_GET_OPTIONS (tool);
- switch(sel_options->shape_type)
+ channel = gimp_image_get_mask (gimp_display_get_image (tool->display));
+
+ switch(shape_select_options->shape_type)
{
case GIMP_SHAPE_RECTANGLE :
gimp_channel_select_rectangle (channel,
@@ -233,8 +635,7 @@ gimp_select_by_shape_tool_select (GimpRectangleSelectTool *rect_tool,
case GIMP_SHAPE_ROUNDED_RECT :
{
gdouble max = MIN (w / 2.0, h / 2.0);
- //gdouble radius = MIN (sel_options->corner_radius, max);
- gdouble radius = sel_options->corner_radius*max/100;
+ gdouble radius = shape_select_options->corner_radius*max/100;
gimp_channel_select_round_rect (channel,
x, y, w, h,
@@ -254,7 +655,7 @@ gimp_select_by_shape_tool_select (GimpRectangleSelectTool *rect_tool,
gdouble w1 = gimp_image_get_width (image);
gdouble h1 = gimp_image_get_height (image);
- switch(sel_options->line_orientation)
+ switch(shape_select_options->line_orientation)
{
case GIMP_ORIENTATION_HORIZONTAL :
gimp_channel_select_rectangle (channel,
@@ -303,5 +704,411 @@ gimp_select_by_shape_tool_select (GimpRectangleSelectTool *rect_tool,
break;
}
- }
+ }
+}
+
+static GimpChannelOps
+gimp_select_by_shape_tool_get_operation (GimpSelectByShapeTool *rect_sel_tool)
+{
+ GimpSelectByShapeToolPrivate *priv;
+ GimpSelectionOptions *options;
+
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+ options = GIMP_SELECTION_TOOL_GET_OPTIONS (rect_sel_tool);
+
+ if (priv->use_saved_op)
+ return priv->operation;
+ else
+ return options->operation;
+}
+
+/**
+ * gimp_select_by_shape_tool_update_option_defaults:
+ * @crop_tool:
+ * @ignore_pending: %TRUE to ignore any pending crop rectangle.
+ *
+ * Sets the default Fixed: Aspect ratio and Fixed: Size option
+ * properties.
+ */
+static void
+gimp_select_by_shape_tool_update_option_defaults (GimpSelectByShapeTool *rect_sel_tool,
+ gboolean ignore_pending)
+{
+ GimpTool *tool;
+ GimpRectangleTool *rectangle_tool;
+ GimpRectangleOptions *rectangle_options;
+
+ tool = GIMP_TOOL (rect_sel_tool);
+ rectangle_tool = GIMP_RECTANGLE_TOOL (tool);
+ rectangle_options = GIMP_RECTANGLE_TOOL_GET_OPTIONS (rectangle_tool);
+
+ if (tool->display != NULL && !ignore_pending)
+ {
+ /* There is a pending rectangle and we should not ignore it, so
+ * set default Fixed: Size to the same as the current pending
+ * rectangle width/height.
+ */
+
+ gimp_rectangle_tool_pending_size_set (rectangle_tool,
+ G_OBJECT (rectangle_options),
+ "default-aspect-numerator",
+ "default-aspect-denominator");
+
+ g_object_set (G_OBJECT (rectangle_options),
+ "use-string-current", TRUE,
+ NULL);
+ }
+ else
+ {
+ g_object_set (G_OBJECT (rectangle_options),
+ "default-aspect-numerator", 1.0,
+ "default-aspect-denominator", 1.0,
+ NULL);
+
+ g_object_set (G_OBJECT (rectangle_options),
+ "use-string-current", FALSE,
+ NULL);
+ }
+}
+
+/*
+ * This function is called if the user clicks and releases the left
+ * button without moving it. There are the things we might want
+ * to do here:
+ * 1) If there is an existing rectangle and we are inside it, we
+ * convert it into a selection.
+ * 2) If there is an existing rectangle and we are outside it, we
+ * clear it.
+ * 3) If there is no rectangle and there is a floating selection,
+ * we anchor it.
+ * 4) If there is no rectangle and we are inside the selection, we
+ * create a rectangle from the selection bounds.
+ * 5) If there is no rectangle and we are outside the selection,
+ * we clear the selection.
+ */
+static gboolean
+gimp_select_by_shape_tool_execute (GimpRectangleTool *rectangle,
+ gint x,
+ gint y,
+ gint w,
+ gint h)
+{
+ GimpTool *tool = GIMP_TOOL (rectangle);
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpSelectByShapeToolPrivate *priv;
+
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (rectangle);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ if (w == 0 && h == 0 && tool->display != NULL)
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+ GimpChannel *selection = gimp_image_get_mask (image);
+ gint pressx;
+ gint pressy;
+
+ if (gimp_image_get_floating_selection (image))
+ {
+ floating_sel_anchor (gimp_image_get_floating_selection (image));
+ gimp_image_flush (image);
+ return TRUE;
+ }
+
+ pressx = ROUND (priv->press_x);
+ pressy = ROUND (priv->press_y);
+
+ /* if the click was inside the marching ants */
+ if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (selection),
+ pressx, pressy) > 0.5)
+ {
+ gint x1, y1, x2, y2;
+
+ if (gimp_channel_bounds (selection, &x1, &y1, &x2, &y2))
+ {
+ g_object_set (rectangle,
+ "x1", x1,
+ "y1", y1,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+ }
+
+ gimp_rectangle_tool_set_function (rectangle,
+ GIMP_RECTANGLE_TOOL_MOVING);
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool,
+ FALSE);
+
+ return FALSE;
+ }
+ else
+ {
+ GimpTool *tool = GIMP_TOOL (rectangle);
+ GimpChannelOps operation;
+
+ /* prevent this change from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ /* We can conceptually think of a click outside of the
+ * selection as adding a 0px selection. Behave intuitivly
+ * for the current selection mode
+ */
+ operation = gimp_select_by_shape_tool_get_operation (rect_sel_tool);
+ switch (operation)
+ {
+ case GIMP_CHANNEL_OP_REPLACE:
+ case GIMP_CHANNEL_OP_INTERSECT:
+ gimp_channel_clear (selection, NULL, TRUE);
+ gimp_image_flush (image);
+ break;
+
+ case GIMP_CHANNEL_OP_ADD:
+ case GIMP_CHANNEL_OP_SUBTRACT:
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ gimp_tool_control_pop_preserve (tool->control);
+ }
+ }
+
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool, FALSE);
+
+ /* Reset the automatic undo/redo mechanism */
+ priv->undo = NULL;
+ priv->redo = NULL;
+
+ return TRUE;
+}
+
+static void
+gimp_select_by_shape_tool_cancel (GimpRectangleTool *rectangle)
+{
+ GimpTool *tool;
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpSelectByShapeToolPrivate *priv;
+
+ tool = GIMP_TOOL (rectangle);
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (rectangle);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ if (tool->display)
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+ GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
+ GimpUndo *undo = gimp_undo_stack_peek (undo_stack);
+
+ /* if we have an existing rectangle in the current display, then
+ * we have already "executed", and need to undo at this point,
+ * unless the user has done something in the meantime
+ */
+ if (undo && priv->undo == undo)
+ {
+ /* prevent this change from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ gimp_image_undo (image);
+ gimp_image_flush (image);
+
+ gimp_tool_control_pop_preserve (tool->control);
+ }
+ }
+
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool, TRUE);
+
+ priv->undo = NULL;
+ priv->redo = NULL;
}
+
+static gboolean
+gimp_select_by_shape_tool_rectangle_change_complete (GimpRectangleTool *rectangle)
+{
+ GimpTool *tool;
+ GimpSelectByShapeTool *rect_sel_tool;
+ GimpSelectByShapeToolPrivate *priv;
+
+ tool = GIMP_TOOL (rectangle);
+ rect_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (tool);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ /* prevent change in selection from halting the tool */
+ gimp_tool_control_push_preserve (tool->control, TRUE);
+
+ if (tool->display && ! gimp_tool_control_is_active (tool->control))
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+ GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
+ GimpUndo *undo = gimp_undo_stack_peek (undo_stack);
+ gint x1, y1, x2, y2;
+
+ /* if we got here via button release, we have already undone the
+ * previous operation. But if we got here by some other means,
+ * we need to undo it now.
+ */
+ if (undo && priv->undo == undo)
+ {
+ gimp_image_undo (image);
+ priv->undo = NULL;
+ }
+
+ g_object_get (rectangle,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ if (gimp_select_by_shape_tool_select (rectangle, x1, y1, x2 - x1, y2 - y1))
+ {
+ /* save the undo that we got when executing, but only if
+ * we actually selected something
+ */
+ priv->undo = gimp_undo_stack_peek (undo_stack);
+ priv->redo = NULL;
+ }
+
+ if (! priv->use_saved_op)
+ {
+ GimpSelectionOptions *options;
+
+ options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
+
+ /* remember the operation now in case we modify the rectangle */
+ priv->operation = options->operation;
+ priv->use_saved_op = TRUE;
+ }
+
+ gimp_image_flush (image);
+ }
+
+ gimp_tool_control_pop_preserve (tool->control);
+
+ gimp_select_by_shape_tool_update_option_defaults (rect_sel_tool, FALSE);
+
+ return TRUE;
+}
+
+static void
+gimp_select_by_shape_tool_round_corners_notify (GimpRectangleOptions *options,
+ GParamSpec *pspec,
+ GimpSelectByShapeTool *rect_sel_tool)
+{
+ GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (rect_sel_tool);
+ GimpRectangleTool *rect_tool = GIMP_RECTANGLE_TOOL (rect_sel_tool);
+ GimpSelectByShapeToolPrivate *priv;
+
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET_PRIVATE (rect_sel_tool);
+
+ gimp_draw_tool_pause (draw_tool);
+
+ priv->round_corners = options->round_corners;
+ priv->corner_radius = options->corner_radius;
+
+ gimp_select__by_shape_tool_rectangle_change_complete (rect_tool);
+
+ gimp_draw_tool_resume (draw_tool);
+}
+
+
+
+
+
+/*
+static void
+gimp_select_by_shape_tool_draw (GimpDrawTool *draw_tool)
+{
+ GimpCanvasGroup *stroke_group = NULL;
+ GimpSelectByShapeTool *shp_sel_tool;
+ GimpSelectByShapeTool *priv;
+
+
+ gint x1, y1, x2, y2;
+
+ GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
+ shp_sel_tool = GIMP_SELECT_BY_SHAPE_TOOL (draw_tool);
+ priv = GIMP_SELECT_BY_SHAPE_TOOL_GET (shp_sel_tool);
+
+ switch(priv->shape_type)
+ {
+ case GIMP_SHAPE_RECTANGLE :
+ gimp_rectangle_tool_draw (draw_tool, stroke_group);
+ break;
+
+ case GIMP_SHAPE_ELLIPSE :
+ {
+ g_object_get (draw_tool,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ gimp_draw_tool_add_arc (draw_tool,
+ FALSE,
+ x1, y1,
+ x2 - x1, y2 - y1,
+ 0.0, 2 * G_PI);
+ break;
+ }
+
+ case GIMP_SHAPE_ROUNDED_RECT :
+ {
+ GimpCanvasItem *item;
+ gint x1, y1, x2, y2;
+ gdouble radius;
+ gint square_size;
+
+ g_object_get (rect_sel_tool,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ radius = MIN (priv->corner_radius,
+ MIN ((x2 - x1) / 2.0, (y2 - y1) / 2.0));
+
+ square_size = (int) (radius * 2);
+
+ stroke_group =
+ GIMP_CANVAS_GROUP (gimp_draw_tool_add_stroke_group (draw_tool));
+
+ item = gimp_draw_tool_add_arc (draw_tool, FALSE,
+ x1, y1,
+ square_size, square_size,
+ G_PI / 2.0, G_PI / 2.0);
+ gimp_canvas_group_add_item (stroke_group, item);
+ gimp_draw_tool_remove_item (draw_tool, item);
+
+ item = gimp_draw_tool_add_arc (draw_tool, FALSE,
+ x2 - square_size, y1,
+ square_size, square_size,
+ 0.0, G_PI / 2.0);
+ gimp_canvas_group_add_item (stroke_group, item);
+ gimp_draw_tool_remove_item (draw_tool, item);
+
+ item = gimp_draw_tool_add_arc (draw_tool, FALSE,
+ x2 - square_size, y2 - square_size,
+ square_size, square_size,
+ G_PI * 1.5, G_PI / 2.0);
+ gimp_canvas_group_add_item (stroke_group, item);
+ gimp_draw_tool_remove_item (draw_tool, item);
+
+ item = gimp_draw_tool_add_arc (draw_tool, FALSE,
+ x1, y2 - square_size,
+ square_size, square_size,
+ G_PI, G_PI / 2.0);
+ gimp_canvas_group_add_item (stroke_group, item);
+ gimp_draw_tool_remove_item (draw_tool, item);
+ break;
+ }
+ default
+ {
+ gimp_rectangle_tool_draw (draw_tool, stroke_group);
+ break;
+ }
+ }*/ /*
+ gimp_rectangle_tool_draw (draw_tool, stroke_group);
+}
+*/
+
diff --git a/app/tools/gimpselectbyshapetool.h b/app/tools/gimpselectbyshapetool.h
index cf18501..cdcc4ca 100644
--- a/app/tools/gimpselectbyshapetool.h
+++ b/app/tools/gimpselectbyshapetool.h
@@ -19,7 +19,7 @@
#define __GIMP_SELECT_BY_SHAPE_TOOL_H__
-#include "gimprectangleselecttool.h"
+#include "gimpselectiontool.h"
#define GIMP_TYPE_SELECT_BY_SHAPE_TOOL (gimp_select_by_shape_tool_get_type ())
@@ -29,18 +29,29 @@
#define GIMP_IS_SELECT_BY_SHAPE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GIMP_TYPE_SELECT_BY_SHAPE_TOOL))
#define GIMP_SELECT_BY_SHAPE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GIMP_TYPE_SELECT_BY_SHAPE_TOOL, GimpSelectByShapeToolClass))
+#define GIMP_SELECT_BY_SHAPE_TOOL_GET_OPTIONS(t) (GIMP_RECTANGLE_SELECT_OPTIONS (gimp_tool_get_options
(GIMP_TOOL (t)))) //Not sure whether GIMP_RECTANGLE_SELECT_OPTIONS or anything else.
+
typedef struct _GimpSelectByShapeTool GimpSelectByShapeTool;
typedef struct _GimpSelectByShapeToolClass GimpSelectByShapeToolClass;
struct _GimpSelectByShapeTool
{
- GimpRectangleSelectTool parent_instance;
+ GimpSelectionTool parent_instance;
+
+ gpointer priv;
};
struct _GimpSelectByShapeToolClass
{
- GimpRectangleSelectToolClass parent_class;
+ GimpSelectionToolClass parent_class;
+
+ void (* select) (GimpSelectByShapeTool *rect_select,
+ GimpChannelOps operation,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]