/* Mouse cursor policy: * - Always use the move cursor * - While dragging the paste, use a move modified * - Else, While hovering above it, display no modifier * - Else, display a "bad" modifier */ static void gimp_seamless_clone_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_BAD; /* Only update if the tool is actually active on some display */ if (tool->display) { if (sc->tool_state == SC_STATE_RENDER_MOTION) { modifier = GIMP_CURSOR_MODIFIER_MOVE; } else if (sc->tool_state == SC_STATE_RENDER_WAIT && gimp_seamless_clone_tool_is_in_paste_c (sc, coords)) { modifier = GIMP_CURSOR_MODIFIER_NONE; } gimp_tool_control_set_cursor_modifier (tool->control, modifier); } GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_seamless_clone_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); switch (action) { case GIMP_TOOL_ACTION_PAUSE: case GIMP_TOOL_ACTION_RESUME: break; case GIMP_TOOL_ACTION_HALT: if (tool->display) gimp_seamless_clone_tool_stop (sc, FALSE); /* TODO: If we have any tool options that should be reset, here is * a good place to do so. */ break; case GIMP_TOOL_ACTION_COMMIT: gimp_seamless_clone_tool_commit (sc); break; } GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); }
static void gimp_seamless_clone_tool_draw (GimpDrawTool *draw_tool) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (draw_tool); if (sc->tool_state == SC_STATE_RENDER_WAIT || sc->tool_state == SC_STATE_RENDER_MOTION) { gimp_draw_tool_add_rectangle (draw_tool, FALSE, sc->xoff, sc->yoff, sc->width, sc->height); } }
static void gimp_seamless_clone_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); if (display != tool->display) { gimp_seamless_clone_tool_start (sc, display); /* Center the paste on the mouse */ sc->xoff = (gint) coords->x - sc->width / 2; sc->yoff = (gint) coords->y - sc->height / 2; } if (sc->tool_state == SC_STATE_RENDER_WAIT && gimp_seamless_clone_tool_is_in_paste_c (sc, coords)) { gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc)); /* Record previous location, in case the user cancels the * movement */ sc->xoff_p = sc->xoff; sc->yoff_p = sc->yoff; /* Record the mouse location, so that the dragging offset can be * calculated */ sc->xclick = coords->x; sc->yclick = coords->y; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); if (gimp_seamless_clone_tool_render_node_update (sc)) { gimp_seamless_clone_tool_filter_update (sc); } sc->tool_state = SC_STATE_RENDER_MOTION; /* In order to receive motion events from the current click, we must * activate the tool control */ gimp_tool_control_activate (tool->control); } }
static gboolean gimp_seamless_clone_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpSeamlessCloneTool *sct = GIMP_SEAMLESS_CLONE_TOOL (tool); if (sct->tool_state == SC_STATE_RENDER_MOTION || sct->tool_state == SC_STATE_RENDER_WAIT) { switch (kevent->keyval) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: gimp_tool_control_set_preserve (tool->control, TRUE); /* TODO: there may be issues with committing the image map * result after some changes were made and the preview * was scrolled. We can fix these by either invalidating * the area which is a union of the previous paste * rectangle each time (in the update function) or by * invalidating and re-rendering all now (expensive and * perhaps useless */ gimp_image_map_commit (sct->image_map, GIMP_PROGRESS (tool)); g_object_unref (sct->image_map); sct->image_map = NULL; gimp_tool_control_set_preserve (tool->control, FALSE); gimp_image_flush (gimp_display_get_image (display)); gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; case GDK_KEY_Escape: gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; default: break; } } return FALSE; }
void gimp_seamless_clone_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); gimp_tool_control_halt (tool->control); /* There is nothing to do, unless we were actually moving a paste */ if (sc->tool_state == SC_STATE_RENDER_MOTION) { gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc)); if (release_type == GIMP_BUTTON_RELEASE_CANCEL) { sc->xoff = sc->xoff_p; sc->yoff = sc->yoff_p; } else { sc->xoff = sc->xoff_p + (gint) (coords->x - sc->xclick); sc->yoff = sc->yoff_p + (gint) (coords->y - sc->yclick); } gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); if (gimp_seamless_clone_tool_render_node_update (sc)) { gimp_seamless_clone_tool_filter_update (sc); } sc->tool_state = SC_STATE_RENDER_WAIT; } }
static void gimp_seamless_clone_tool_options_notify (GimpTool *tool, GimpToolOptions *options, const GParamSpec *pspec) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); GIMP_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec); if (! tool->display) return; gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); if (! strcmp (pspec->name, "max-refine-scale")) { if (gimp_seamless_clone_tool_render_node_update (sc)) { gimp_seamless_clone_tool_filter_update (sc); } } gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); }
static void gimp_seamless_clone_tool_motion (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpDisplay *display) { GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool); if (sc->tool_state == SC_STATE_RENDER_MOTION) { gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc)); sc->xoff = sc->xoff_p + (gint) (coords->x - sc->xclick); sc->yoff = sc->yoff_p + (gint) (coords->y - sc->yclick); gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); if (gimp_seamless_clone_tool_render_node_update (sc)) { gimp_seamless_clone_tool_filter_update (sc); } } }