Example #1
0
/* 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);
}
Example #2
0
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);
}
Example #3
0
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);
    }
}
Example #4
0
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);
    }
}
Example #5
0
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;
}
Example #6
0
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;
    }
}
Example #7
0
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));
}
Example #8
0
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);
        }
    }
}