static void gimp_image_map_tool_options_notify (GimpTool *tool, GimpToolOptions *options, const GParamSpec *pspec) { GimpImageMapTool *image_map_tool = GIMP_IMAGE_MAP_TOOL (tool); GimpImageMapOptions *im_options = GIMP_IMAGE_MAP_OPTIONS (options); if (! strcmp (pspec->name, "preview") && image_map_tool->image_map) { if (im_options->preview) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_tool_map (image_map_tool); gimp_tool_control_pop_preserve (tool->control); } else { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_abort (image_map_tool->image_map); gimp_tool_control_pop_preserve (tool->control); } } else if (! strcmp (pspec->name, "region") && image_map_tool->image_map) { gimp_image_map_set_region (image_map_tool->image_map, im_options->region); gimp_image_map_tool_preview (image_map_tool); } }
static gboolean gimp_cage_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpCageTool *ct = GIMP_CAGE_TOOL (tool); switch (kevent->keyval) { case GDK_KEY_BackSpace: if (! ct->cage_complete && ct->tool_state == CAGE_STATE_WAIT) { gimp_cage_tool_remove_last_handle (ct); } else if (ct->cage_complete && ct->tool_state == CAGE_STATE_WAIT) { gimp_cage_config_remove_selected_points(ct->config); /* if the cage have less than 3 handles, we reopen it */ if (gimp_cage_config_get_n_points(ct->config) <= 2) ct->cage_complete = FALSE; } return TRUE; case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: if (ct->cage_complete == FALSE && gimp_cage_config_get_n_points (ct->config) > 2) { g_object_set (gimp_tool_get_options (tool), "cage-mode", GIMP_CAGE_MODE_DEFORM, NULL); } else if (ct->tool_state == DEFORM_STATE_WAIT) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (ct->image_map); g_object_unref (ct->image_map); ct->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (display)); gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); } break; case GDK_KEY_Escape: gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; default: break; } return FALSE; }
static void gimp_cage_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { GimpCageTool *ct = GIMP_CAGE_TOOL (tool); switch (action) { case GIMP_TOOL_ACTION_PAUSE: case GIMP_TOOL_ACTION_RESUME: break; case GIMP_TOOL_ACTION_HALT: if (ct->config) { g_object_unref (ct->config); ct->config = NULL; } if (ct->coef) { g_object_unref (ct->coef); ct->coef = NULL; } if (ct->render_node) { g_object_unref (ct->render_node); ct->render_node = NULL; ct->coef_node = NULL; ct->cage_node = NULL; } if (ct->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_abort (ct->image_map); g_object_unref (ct->image_map); ct->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); } tool->display = NULL; g_object_set (gimp_tool_get_options (tool), "cage-mode", GIMP_CAGE_MODE_CAGE_CHANGE, NULL); break; } GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); }
static void gimp_cage_tool_commit (GimpCageTool *ct) { GimpTool *tool = GIMP_TOOL (ct); gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (ct->image_map, GIMP_PROGRESS (tool)); g_object_unref (ct->image_map); ct->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); }
static void gimp_seamless_clone_tool_commit (GimpSeamlessCloneTool *sc) { GimpTool *tool = GIMP_TOOL (sc); if (sc->filter) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_drawable_filter_commit (sc->filter, GIMP_PROGRESS (tool), FALSE); g_clear_object (&sc->filter); gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); } }
static void gimp_warp_tool_commit (GimpWarpTool *wt) { GimpTool *tool = GIMP_TOOL (wt); if (wt->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (wt->image_map, GIMP_PROGRESS (tool), FALSE); g_object_unref (wt->image_map); wt->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); } }
static void gimp_seamless_clone_tool_commit (GimpSeamlessCloneTool *sc) { GimpTool *tool = GIMP_TOOL (sc); if (sc->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (sc->image_map, GIMP_PROGRESS (tool)); g_object_unref (sc->image_map); sc->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); } }
static void gimp_cage_tool_halt (GimpCageTool *ct) { GimpTool *tool = GIMP_TOOL (ct); if (ct->config) { g_object_unref (ct->config); ct->config = NULL; } if (ct->coef) { g_object_unref (ct->coef); ct->coef = NULL; } if (ct->render_node) { g_object_unref (ct->render_node); ct->render_node = NULL; ct->coef_node = NULL; ct->cage_node = NULL; } if (ct->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_abort (ct->image_map); g_object_unref (ct->image_map); ct->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (tool->display)); } tool->display = NULL; g_object_set (gimp_tool_get_options (tool), "cage-mode", GIMP_CAGE_MODE_CAGE_CHANGE, NULL); }
static void gimp_n_point_deformation_tool_commit (GimpNPointDeformationTool *npd_tool) { GimpTool *tool = GIMP_TOOL (npd_tool); if (npd_tool->active) { gimp_n_point_deformation_tool_halt_threads (npd_tool); gimp_tool_control_push_preserve (tool->control, TRUE); gimp_n_point_deformation_tool_apply_deformation (npd_tool); gimp_tool_control_pop_preserve (tool->control); /* show original/deformed image */ gimp_item_set_visible (GIMP_ITEM (tool->drawable), TRUE, FALSE); gimp_image_flush (gimp_display_get_image (tool->display)); npd_tool->active = FALSE; } }
void gimp_image_map_tool_preview (GimpImageMapTool *im_tool) { GimpTool *tool; GimpImageMapOptions *options; g_return_if_fail (GIMP_IS_IMAGE_MAP_TOOL (im_tool)); tool = GIMP_TOOL (im_tool); options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool); if (im_tool->image_map && options->preview) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_apply (im_tool->image_map, NULL); gimp_tool_control_pop_preserve (tool->control); } }
static void gimp_image_map_tool_halt (GimpImageMapTool *im_tool) { GimpTool *tool = GIMP_TOOL (im_tool); if (im_tool->gui) gimp_tool_gui_hide (im_tool->gui); if (im_tool->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_abort (im_tool->image_map); g_object_unref (im_tool->image_map); im_tool->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); } tool->drawable = NULL; }
static gboolean gimp_warp_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); switch (kevent->keyval) { case GDK_KEY_BackSpace: return TRUE; case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: if (wt->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (wt->image_map, GIMP_PROGRESS (tool)); g_object_unref (wt->image_map); wt->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (display)); } /* fall thru */ case GDK_KEY_Escape: gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; default: break; } return FALSE; }
static void gimp_image_map_tool_commit (GimpImageMapTool *im_tool) { GimpTool *tool = GIMP_TOOL (im_tool); if (im_tool->gui) gimp_tool_gui_hide (im_tool->gui); if (im_tool->image_map) { GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool); gimp_tool_control_push_preserve (tool->control, TRUE); if (! options->preview) gimp_image_map_apply (im_tool->image_map, NULL); gimp_image_map_commit (im_tool->image_map, GIMP_PROGRESS (tool), TRUE); g_object_unref (im_tool->image_map); im_tool->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_map_tool_remove_guide (im_tool); gimp_image_flush (gimp_display_get_image (tool->display)); if (im_tool->config && im_tool->settings_box) { GimpGuiConfig *config = GIMP_GUI_CONFIG (tool->tool_info->gimp->config); gimp_settings_box_add_current (GIMP_SETTINGS_BOX (im_tool->settings_box), config->image_map_tool_max_recent); } } tool->display = NULL; tool->drawable = NULL; }
static void gimp_rectangle_select_tool_cancel (GimpRectangleTool *rectangle) { GimpTool *tool; GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; tool = GIMP_TOOL (rectangle); rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle); priv = GIMP_RECTANGLE_SELECT_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_rectangle_select_tool_update_option_defaults (rect_sel_tool, TRUE); priv->undo = NULL; priv->redo = NULL; }
static gboolean gimp_rectangle_select_tool_rectangle_change_complete (GimpRectangleTool *rectangle) { GimpTool *tool; GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; tool = GIMP_TOOL (rectangle); rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); priv = GIMP_RECTANGLE_SELECT_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_rectangle_select_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_rectangle_select_tool_update_option_defaults (rect_sel_tool, FALSE); return TRUE; }
/* * 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_rectangle_select_tool_execute (GimpRectangleTool *rectangle, gint x, gint y, gint w, gint h) { GimpTool *tool = GIMP_TOOL (rectangle); GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle); priv = GIMP_RECTANGLE_SELECT_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); 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_rectangle_select_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_rectangle_select_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_rectangle_select_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; GimpImage *image; rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); priv = GIMP_RECTANGLE_SELECT_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_rectangle_select_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpRectangleTool *rectangle; GimpRectangleSelectTool *rect_sel_tool; GimpDisplayShell *shell; GimpRectangleSelectToolPrivate *priv; GimpRectangleFunction function; rectangle = GIMP_RECTANGLE_TOOL (tool); rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); shell = gimp_display_get_shell (display); priv = GIMP_RECTANGLE_SELECT_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)) { /* In some cases we want to finish the rectangle select tool * and hand over responsability to the selection tool */ gimp_rectangle_tool_execute (rectangle); gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); gimp_rectangle_select_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_rectangle_select_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_image_map_tool_options_notify (GimpTool *tool, GimpToolOptions *options, const GParamSpec *pspec) { GimpImageMapTool *im_tool = GIMP_IMAGE_MAP_TOOL (tool); GimpImageMapOptions *im_options = GIMP_IMAGE_MAP_OPTIONS (options); if (! strcmp (pspec->name, "preview") && im_tool->image_map) { if (im_options->preview) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_apply (im_tool->image_map, NULL); gimp_tool_control_pop_preserve (tool->control); if (im_options->preview_split) gimp_image_map_tool_add_guide (im_tool); } else { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_abort (im_tool->image_map); gimp_tool_control_pop_preserve (tool->control); if (im_options->preview_split) gimp_image_map_tool_remove_guide (im_tool); } } else if (! strcmp (pspec->name, "preview-split") && im_tool->image_map) { if (im_options->preview_split) { GimpDisplayShell *shell = gimp_display_get_shell (tool->display); GimpItem *item = GIMP_ITEM (im_tool->drawable); gint x, y, width, height; gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); if (gimp_rectangle_intersect (gimp_item_get_offset_x (item), gimp_item_get_offset_y (item), gimp_item_get_width (item), gimp_item_get_height (item), x, y, width, height, &x, &y, &width, &height)) { gdouble position; if (im_options->preview_alignment == GIMP_ALIGN_LEFT || im_options->preview_alignment == GIMP_ALIGN_RIGHT) { position = ((gdouble) ((x + width / 2) - gimp_item_get_offset_x (item)) / (gdouble) gimp_item_get_width (item)); } else { position = ((gdouble) ((y + height / 2) - gimp_item_get_offset_y (item)) / (gdouble) gimp_item_get_height (item)); } g_object_set (options, "preview-position", CLAMP (position, 0.0, 1.0), NULL); } } gimp_image_map_set_preview (im_tool->image_map, im_options->preview_split, im_options->preview_alignment, im_options->preview_position); if (im_options->preview_split) gimp_image_map_tool_add_guide (im_tool); else gimp_image_map_tool_remove_guide (im_tool); } else if (! strcmp (pspec->name, "preview-alignment") && im_tool->image_map) { gimp_image_map_set_preview (im_tool->image_map, im_options->preview_split, im_options->preview_alignment, im_options->preview_position); if (im_options->preview_split) gimp_image_map_tool_move_guide (im_tool); } else if (! strcmp (pspec->name, "preview-position") && im_tool->image_map) { gimp_image_map_set_preview (im_tool->image_map, im_options->preview_split, im_options->preview_alignment, im_options->preview_position); if (im_options->preview_split) gimp_image_map_tool_move_guide (im_tool); } else if (! strcmp (pspec->name, "region") && im_tool->image_map) { gimp_image_map_set_region (im_tool->image_map, im_options->region); gimp_image_map_tool_preview (im_tool); } }