[gtk/wip/otte/undo: 11/17] undocommand: Add gtk_undo_command_should_merge() function



commit 729e90fbf505e72d1c1f14525c2bb88db47f2e6b
Author: Benjamin Otte <otte redhat com>
Date:   Mon Aug 17 02:17:13 2015 +0200

    undocommand: Add gtk_undo_command_should_merge() function
    
    This splits merging into 2 steps:
    
    1. The actual merging
    
    2. Determining if merging should happen for the UI.
    
    Sometimes commands should be compressed unconditionally and in that case
    the 2nd step can be omitted.

 gtk/gtkentryundocommand.c   | 27 ++++++++++++++++++++++-----
 gtk/gtkundocommand.c        | 30 ++++++++++++++++++++++++++++++
 gtk/gtkundocommandprivate.h |  5 +++++
 gtk/gtkundostack.c          | 15 ++++++++++-----
 4 files changed, 67 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkentryundocommand.c b/gtk/gtkentryundocommand.c
index b8d2f18071..0709a86764 100644
--- a/gtk/gtkentryundocommand.c
+++ b/gtk/gtkentryundocommand.c
@@ -134,15 +134,31 @@ gtk_entry_undo_command_merge (GtkUndoCommand *command,
   if (command_priv->entry != followup_priv->entry)
     return NULL;
 
+  return gtk_entry_undo_command_new_from_snapshots (command_priv->entry, &command_priv->before, 
&followup_priv->after);
+}
+
+gboolean
+gtk_entry_undo_command_should_merge (GtkUndoCommand *command,
+                                     GtkUndoCommand *followup)
+{
+  GtkEntryUndoCommandPrivate *command_priv = gtk_entry_undo_command_get_instance_private 
(GTK_ENTRY_UNDO_COMMAND (command));
+  GtkEntryUndoCommandPrivate *followup_priv = gtk_entry_undo_command_get_instance_private 
(GTK_ENTRY_UNDO_COMMAND (followup));
+
+  if (!GTK_UNDO_COMMAND_CLASS (gtk_entry_undo_command_parent_class)->should_merge (command, followup))
+    return FALSE;
+
+  if (!GTK_IS_ENTRY_UNDO_COMMAND (followup))
+    return FALSE;
+
+  if (command_priv->entry != followup_priv->entry)
+    return FALSE;
+
   if (!g_str_equal (command_priv->after.text, followup_priv->before.text) ||
       command_priv->after.cursor != followup_priv->before.cursor ||
       command_priv->after.selection_start != followup_priv->before.selection_start)
-    return NULL;
+    return FALSE;
 
-  /* We don't insist on cursor positions being equal here, someone
-   * might ie. move the cursor to correct a typo
-   */
-  return gtk_entry_undo_command_new_from_snapshots (command_priv->entry, &command_priv->before, 
&followup_priv->after);
+  return TRUE;
 }
 
 static guint
@@ -225,6 +241,7 @@ gtk_entry_undo_command_class_init (GtkEntryUndoCommandClass *klass)
   undo_class->undo = gtk_entry_undo_command_undo;
   undo_class->redo = gtk_entry_undo_command_redo;
   undo_class->merge = gtk_entry_undo_command_merge;
+  undo_class->should_merge = gtk_entry_undo_command_should_merge;
   undo_class->describe = gtk_entry_undo_command_describe;
 }
 
diff --git a/gtk/gtkundocommand.c b/gtk/gtkundocommand.c
index 8fbe0e6798..08da66f3d0 100644
--- a/gtk/gtkundocommand.c
+++ b/gtk/gtkundocommand.c
@@ -54,6 +54,13 @@ gtk_undo_command_real_merge (GtkUndoCommand *command,
   return NULL;
 }
 
+gboolean
+gtk_undo_command_real_should_merge (GtkUndoCommand *command,
+                                    GtkUndoCommand *followup)
+{
+  return TRUE;
+}
+
 char *
 gtk_undo_command_real_describe (GtkUndoCommand *command)
 {
@@ -71,6 +78,7 @@ gtk_undo_command_class_init (GtkUndoCommandClass *klass)
   klass->undo = gtk_undo_command_real_undo;
   klass->redo = gtk_undo_command_real_redo;
   klass->merge = gtk_undo_command_real_merge;
+  klass->should_merge = gtk_undo_command_real_should_merge;
   klass->describe = gtk_undo_command_real_describe;
 }
 
@@ -108,6 +116,28 @@ gtk_undo_command_merge (GtkUndoCommand *command,
   return GTK_UNDO_COMMAND_GET_CLASS (command)->merge (command, followup_command);
 }
 
+/*
+ * gtk_undo_command_should_merge:
+ * @command: The command that would be undone second
+ * @followup_command: The command that would be undone first
+ *
+ * Determines if @command and @followup_comand should be merged for
+ * undo. That is, it determines if when the user triggers an undo
+ * (for example by pressing Ctrl-z), if both commands should be
+ * undone at once or if they should require two seperate undos.
+ *
+ * Returns: %TRUE if the commands should be merged for UI purposes.
+ */
+gboolean
+gtk_undo_command_should_merge (GtkUndoCommand *command,
+                               GtkUndoCommand *followup_command)
+{
+  g_return_val_if_fail (GTK_IS_UNDO_COMMAND (command), FALSE);
+  g_return_val_if_fail (GTK_IS_UNDO_COMMAND (followup_command), FALSE);
+
+  return GTK_UNDO_COMMAND_GET_CLASS (command)->should_merge (command, followup_command);
+}
+
 char *
 gtk_undo_command_describe (GtkUndoCommand *command)
 {
diff --git a/gtk/gtkundocommandprivate.h b/gtk/gtkundocommandprivate.h
index aba26cc7ff..9968c6c074 100644
--- a/gtk/gtkundocommandprivate.h
+++ b/gtk/gtkundocommandprivate.h
@@ -50,6 +50,9 @@ struct _GtkUndoCommandClass
   /* merge this command with a followup command, return NULL if merge not possible */
   GtkUndoCommand *      (* merge)                       (GtkUndoCommand                *command,
                                                          GtkUndoCommand                *followup_command);
+  /* should the two commands be merged for user undo purposes? */
+  gboolean              (* should_merge)                (GtkUndoCommand                *command,
+                                                         GtkUndoCommand                *followup_command);
   /* get a translated string describing the command */
   char *                (* describe)                    (GtkUndoCommand                *command);
 };
@@ -60,6 +63,8 @@ gboolean                gtk_undo_command_undo           (GtkUndoCommand
 gboolean                gtk_undo_command_redo           (GtkUndoCommand                *command);
 GtkUndoCommand *        gtk_undo_command_merge          (GtkUndoCommand                *command,
                                                          GtkUndoCommand                *followup_command);
+gboolean                gtk_undo_command_should_merge   (GtkUndoCommand                *command,
+                                                         GtkUndoCommand                *followup_command);
 char *                  gtk_undo_command_describe       (GtkUndoCommand                *command);
 
 
diff --git a/gtk/gtkundostack.c b/gtk/gtkundostack.c
index b2b72debad..d977b1799d 100644
--- a/gtk/gtkundostack.c
+++ b/gtk/gtkundostack.c
@@ -168,6 +168,8 @@ gtk_undo_stack_push_internal (GtkUndoStack   *stack,
   g_sequence_prepend (priv->commands, command);
 
   g_list_model_items_changed (G_LIST_MODEL (stack), 0, replace ? 1 : 0, 1);
+
+  gtk_undo_stack_dump (stack);
 }
 
 void
@@ -185,12 +187,15 @@ gtk_undo_stack_push (GtkUndoStack   *stack,
   if (!g_sequence_iter_is_end (begin_iter))
     {
       previous = g_sequence_get (begin_iter);
-      merge = gtk_undo_command_merge (previous, command);
-      if (merge)
+      if (gtk_undo_command_should_merge (previous, command))
         {
-          gtk_undo_stack_push_internal (stack, merge, TRUE);
-          g_object_unref (merge);
-          return;
+          merge = gtk_undo_command_merge (previous, command);
+          if (merge)
+            {
+              gtk_undo_stack_push_internal (stack, merge, TRUE);
+              g_object_unref (merge);
+              return;
+            }
         }
     }
 


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