[gimp] app: add tool-internal undo to the blend tool



commit 95b27a1ac869282ba029b30fbbe31ba5d3665993
Author: Michael Natterer <mitch gimp org>
Date:   Fri Apr 28 00:27:34 2017 +0200

    app: add tool-internal undo to the blend tool
    
    also add button-3 cancel of a blend shape modification.

 app/tools/gimpblendtool.c |  191 ++++++++++++++++++++++++++++++++++++++++++++-
 app/tools/gimpblendtool.h |    3 +
 2 files changed, 193 insertions(+), 1 deletions(-)
---
diff --git a/app/tools/gimpblendtool.c b/app/tools/gimpblendtool.c
index 62e8980..67c5939 100644
--- a/app/tools/gimpblendtool.c
+++ b/app/tools/gimpblendtool.c
@@ -66,6 +66,17 @@
 #define PARTIAL_HANDLE_THRESHOLD_SQ (FULL_HANDLE_THRESHOLD_SQ * 5)
 
 
+typedef struct _BlendInfo BlendInfo;
+
+struct _BlendInfo
+{
+  gdouble start_x;
+  gdouble start_y;
+  gdouble end_x;
+  gdouble end_y;
+};
+
+
 /*  local function prototypes  */
 
 static void   gimp_blend_tool_dispose             (GObject               *object);
@@ -112,6 +123,14 @@ static void   gimp_blend_tool_cursor_update       (GimpTool              *tool,
                                                    const GimpCoords      *coords,
                                                    GdkModifierType        state,
                                                    GimpDisplay           *display);
+static const gchar * gimp_blend_tool_get_undo_desc(GimpTool              *tool,
+                                                   GimpDisplay           *display);
+static const gchar * gimp_blend_tool_get_redo_desc(GimpTool              *tool,
+                                                   GimpDisplay           *display);
+static gboolean  gimp_blend_tool_undo             (GimpTool              *tool,
+                                                   GimpDisplay           *display);
+static gboolean  gimp_blend_tool_redo             (GimpTool              *tool,
+                                                   GimpDisplay           *display);
 static void   gimp_blend_tool_options_notify      (GimpTool              *tool,
                                                    GimpToolOptions       *options,
                                                    const GParamSpec      *pspec);
@@ -148,6 +167,12 @@ static void   gimp_blend_tool_create_filter       (GimpBlendTool         *blend_
 static void   gimp_blend_tool_filter_flush        (GimpDrawableFilter    *filter,
                                                    GimpTool              *tool);
 
+static BlendInfo * blend_info_new  (gdouble    start_x,
+                                    gdouble    start_y,
+                                    gdouble    end_x,
+                                    gdouble    end_y);
+static void        blend_info_free (BlendInfo *info);
+
 
 G_DEFINE_TYPE (GimpBlendTool, gimp_blend_tool, GIMP_TYPE_DRAW_TOOL)
 
@@ -193,6 +218,10 @@ gimp_blend_tool_class_init (GimpBlendToolClass *klass)
   tool_class->key_press           = gimp_blend_tool_key_press;
   tool_class->active_modifier_key = gimp_blend_tool_active_modifier_key;
   tool_class->cursor_update       = gimp_blend_tool_cursor_update;
+  tool_class->get_undo_desc       = gimp_blend_tool_get_undo_desc;
+  tool_class->get_redo_desc       = gimp_blend_tool_get_redo_desc;
+  tool_class->undo                = gimp_blend_tool_undo;
+  tool_class->redo                = gimp_blend_tool_redo;
   tool_class->options_notify      = gimp_blend_tool_options_notify;
 
   draw_tool_class->draw           = gimp_blend_tool_draw;
@@ -355,6 +384,29 @@ gimp_blend_tool_button_press (GimpTool            *tool,
       blend_tool->grabbed_point = POINT_BOTH;
     }
 
+  if ((blend_tool->grabbed_point == POINT_START ||
+       blend_tool->grabbed_point == POINT_END   ||
+       blend_tool->grabbed_point == POINT_BOTH) &&
+      gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
+    {
+      blend_tool->undo_stack =
+        g_list_prepend (blend_tool->undo_stack,
+                        blend_info_new (blend_tool->start_x,
+                                        blend_tool->start_y,
+                                        blend_tool->end_x,
+                                        blend_tool->end_y));
+
+      if (blend_tool->redo_stack)
+        {
+          g_list_free_full (blend_tool->redo_stack,
+                            (GDestroyNotify) blend_info_free);
+          blend_tool->redo_stack = NULL;
+        }
+
+      /*  update the undo actions / menu items  */
+      gimp_image_flush (gimp_display_get_image (display));
+    }
+
   gimp_blend_tool_point_motion (blend_tool,
                                 state & gimp_get_constrain_behavior_mask ());
 
@@ -395,7 +447,16 @@ gimp_blend_tool_button_release (GimpTool              *tool,
       break;
 
     case GIMP_BUTTON_RELEASE_CANCEL:
-      /* XXX: handle cancel properly */
+      if ((blend_tool->grabbed_point == POINT_START ||
+           blend_tool->grabbed_point == POINT_END   ||
+           blend_tool->grabbed_point == POINT_BOTH) &&
+          blend_tool->undo_stack)
+        {
+          gimp_blend_tool_undo (tool, display);
+          blend_info_free (blend_tool->redo_stack->data);
+          blend_tool->redo_stack = g_list_remove (blend_tool->redo_stack,
+                                                  blend_tool->redo_stack->data);
+        }
       break;
 
     case GIMP_BUTTON_RELEASE_CLICK:
@@ -602,6 +663,98 @@ gimp_blend_tool_cursor_update (GimpTool         *tool,
   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
 }
 
+static const gchar *
+gimp_blend_tool_get_undo_desc (GimpTool    *tool,
+                               GimpDisplay *display)
+{
+  GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+  GimpDrawTool  *draw_tool  = GIMP_DRAW_TOOL (tool);
+
+  if (display != draw_tool->display || ! blend_tool->undo_stack)
+    return NULL;
+
+  return _("Blend Step");
+}
+
+static const gchar *
+gimp_blend_tool_get_redo_desc (GimpTool    *tool,
+                               GimpDisplay *display)
+{
+  GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+  GimpDrawTool  *draw_tool  = GIMP_DRAW_TOOL (tool);
+
+  if (display != draw_tool->display || ! blend_tool->redo_stack)
+    return NULL;
+
+  return _("Blend Step");
+}
+
+static gboolean
+gimp_blend_tool_undo (GimpTool    *tool,
+                      GimpDisplay *display)
+{
+  GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+  BlendInfo     *info;
+
+  if (! gimp_blend_tool_get_undo_desc (tool, display))
+    return FALSE;
+
+  info = blend_info_new (blend_tool->start_x,
+                         blend_tool->start_y,
+                         blend_tool->end_x,
+                         blend_tool->end_y);
+  blend_tool->redo_stack = g_list_prepend (blend_tool->redo_stack, info);
+
+  info = blend_tool->undo_stack->data;
+
+  blend_tool->start_x = info->start_x;
+  blend_tool->start_y = info->start_y;
+  blend_tool->end_x   = info->end_x;
+  blend_tool->end_y   = info->end_y;
+
+  blend_tool->undo_stack = g_list_remove (blend_tool->undo_stack, info);
+  blend_info_free (info);
+
+  gimp_blend_tool_update_graph (blend_tool);
+  gimp_drawable_filter_apply (blend_tool->filter, NULL);
+  gimp_blend_tool_update_items (blend_tool);
+
+  return TRUE;
+}
+
+static gboolean
+gimp_blend_tool_redo (GimpTool    *tool,
+                      GimpDisplay *display)
+{
+  GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+  BlendInfo     *info;
+
+  if (! gimp_blend_tool_get_redo_desc (tool, display))
+    return FALSE;
+
+  info = blend_info_new (blend_tool->start_x,
+                         blend_tool->start_y,
+                         blend_tool->end_x,
+                         blend_tool->end_y);
+  blend_tool->undo_stack = g_list_prepend (blend_tool->undo_stack, info);
+
+  info = blend_tool->redo_stack->data;
+
+  blend_tool->start_x = info->start_x;
+  blend_tool->start_y = info->start_y;
+  blend_tool->end_x   = info->end_x;
+  blend_tool->end_y   = info->end_y;
+
+  blend_tool->redo_stack = g_list_remove (blend_tool->redo_stack, info);
+  blend_info_free (info);
+
+  gimp_blend_tool_update_graph (blend_tool);
+  gimp_drawable_filter_apply (blend_tool->filter, NULL);
+  gimp_blend_tool_update_items (blend_tool);
+
+  return TRUE;
+}
+
 static void
 gimp_blend_tool_options_notify (GimpTool         *tool,
                                 GimpToolOptions  *options,
@@ -940,6 +1093,20 @@ gimp_blend_tool_halt (GimpBlendTool *blend_tool)
       gimp_image_flush (gimp_display_get_image (tool->display));
     }
 
+  if (blend_tool->undo_stack)
+    {
+      g_list_free_full (blend_tool->undo_stack,
+                        (GDestroyNotify) blend_info_free);
+      blend_tool->undo_stack = NULL;
+    }
+
+  if (blend_tool->redo_stack)
+    {
+      g_list_free_full (blend_tool->redo_stack,
+                        (GDestroyNotify) blend_info_free);
+      blend_tool->redo_stack = NULL;
+    }
+
   tool->display  = NULL;
   tool->drawable = NULL;
 
@@ -1233,3 +1400,25 @@ gimp_blend_tool_filter_flush (GimpDrawableFilter *filter,
 
   gimp_projection_flush (gimp_image_get_projection (image));
 }
+
+static BlendInfo *
+blend_info_new (gdouble start_x,
+                gdouble start_y,
+                gdouble end_x,
+                gdouble end_y)
+{
+  BlendInfo *info = g_slice_new0 (BlendInfo);
+
+  info->start_x = start_x;
+  info->start_y = start_y;
+  info->end_x   = end_x;
+  info->end_y   = end_y;
+
+  return info;
+}
+
+static void
+blend_info_free (BlendInfo *info)
+{
+  g_slice_free (BlendInfo, info);
+}
diff --git a/app/tools/gimpblendtool.h b/app/tools/gimpblendtool.h
index be99e04..1c839a9 100644
--- a/app/tools/gimpblendtool.h
+++ b/app/tools/gimpblendtool.h
@@ -64,6 +64,9 @@ struct _GimpBlendTool
   gdouble             end_x;      /*  ending x coord    */
   gdouble             end_y;      /*  ending y coord    */
 
+  GList              *undo_stack;
+  GList              *redo_stack;
+
   GimpCanvasItem     *line;
   GimpCanvasItem     *start_handle_circle;
   GimpCanvasItem     *start_handle_cross;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]