예제 #1
0
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);
    }
}
예제 #2
0
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;
}
예제 #3
0
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);
}
예제 #4
0
파일: gimpcagetool.c 프로젝트: STRNG/gimp
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));
}
예제 #5
0
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));
    }
}
예제 #6
0
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));
    }
}
예제 #7
0
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));
    }
}
예제 #8
0
파일: gimpcagetool.c 프로젝트: STRNG/gimp
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;
    }
}
예제 #10
0
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);
    }
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
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;
}
예제 #16
0
/*
 * 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;
}
예제 #17
0
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;
}
예제 #18
0
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;
}
예제 #19
0
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);
    }
}