[gnome-tetravex] Allow Redo.



commit 8f2eb9482bd729ac0c64eaf08465eff23e80633e
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Sat Sep 21 01:38:52 2019 +0200

    Allow Redo.
    
    Fixes #2.

 src/gnome-tetravex.vala | 53 ++++++++++++++++++++++++++++++++++------------
 src/puzzle-view.vala    |  6 ++++++
 src/puzzle.vala         | 56 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 93 insertions(+), 22 deletions(-)
---
diff --git a/src/gnome-tetravex.vala b/src/gnome-tetravex.vala
index ab01b89..aba6253 100644
--- a/src/gnome-tetravex.vala
+++ b/src/gnome-tetravex.vala
@@ -40,6 +40,7 @@ private class Tetravex : Gtk.Application
     private Stack play_pause_stack;
 
     private SimpleAction undo_action;
+    private SimpleAction redo_action;
     private SimpleAction pause_action;
     private SimpleAction solve_action;
     private SimpleAction finish_action;
@@ -70,6 +71,7 @@ private class Tetravex : Gtk.Application
         { "move-left",      move_left                                       },
         { "move-right",     move_right                                      },
         { "undo",           undo_cb                                         },
+        { "redo",           redo_cb                                         },
         { "size",           radio_cb,       "s",    "'2'",  size_changed    },
         { "help",           help_cb                                         },
         { "about",          about_cb                                        }
@@ -101,17 +103,18 @@ private class Tetravex : Gtk.Application
         Window.set_default_icon_name ("org.gnome.Tetravex");
 
         add_action_entries (action_entries, this);
-        set_accels_for_action ("app.solve",         {"<Primary>h"       });
-        set_accels_for_action ("app.scores",        {"<Primary>i"       });
-        set_accels_for_action ("app.new-game",      {"<Primary>n"       });
-        set_accels_for_action ("app.pause",         {"<Primary>p",
-                                                              "Pause"   });
-        set_accels_for_action ("app.quit",          {"<Primary>q"       });
-        set_accels_for_action ("app.move-up",       {"<Primary>Up"      });
-        set_accels_for_action ("app.move-down",     {"<Primary>Down"    });
-        set_accels_for_action ("app.move-left",     {"<Primary>Left"    });
-        set_accels_for_action ("app.move-right",    {"<Primary>Right"   });
-        set_accels_for_action ("app.undo",          {"<Primary>z"       });
+        set_accels_for_action ("app.solve",         {        "<Primary>h"       });
+        set_accels_for_action ("app.scores",        {        "<Primary>i"       });
+        set_accels_for_action ("app.new-game",      {        "<Primary>n"       });
+        set_accels_for_action ("app.pause",         {        "<Primary>p",
+                                                                      "Pause"   });
+        set_accels_for_action ("app.quit",          {        "<Primary>q"       });
+        set_accels_for_action ("app.move-up",       {        "<Primary>Up"      });
+        set_accels_for_action ("app.move-down",     {        "<Primary>Down"    });
+        set_accels_for_action ("app.move-left",     {        "<Primary>Left"    });
+        set_accels_for_action ("app.move-right",    {        "<Primary>Right"   });
+        set_accels_for_action ("app.undo",          {        "<Primary>z"       });
+        set_accels_for_action ("app.redo",          { "<Shift><Primary>z"       });
         // F1 and friends are managed manually
 
         Builder builder = new Builder.from_resource ("/org/gnome/Tetravex/gnome-tetravex.ui");
@@ -151,7 +154,17 @@ private class Tetravex : Gtk.Application
         Button undo_button = new Button.from_icon_name ("edit-undo-symbolic");
         undo_button.set_action_name ("app.undo");
         undo_button.show ();
-        headerbar.pack_start (undo_button);
+
+        Button redo_button = new Button.from_icon_name ("edit-redo-symbolic");
+        redo_button.set_action_name ("app.redo");
+        redo_button.show ();
+
+        Box undo_redo_box = new Box (Orientation.HORIZONTAL, /* spacing */ 0);
+        undo_redo_box.get_style_context ().add_class ("linked");
+        undo_redo_box.pack_start (undo_button);
+        undo_redo_box.pack_start (redo_button);
+        undo_redo_box.show ();
+        headerbar.pack_start (undo_redo_box);
 
         Grid grid = (Grid) builder.get_object ("grid");
 
@@ -209,7 +222,7 @@ private class Tetravex : Gtk.Application
         new_game_solve_stack.add_named (finish_button, "finish");
         grid.attach (new_game_solve_stack, 2, 1, 1, 1);
 
-        Box box = new Box (Orientation.HORIZONTAL, 8);
+        Box box = new Box (Orientation.HORIZONTAL, /* spacing */ 8);
         Image image = new Image.from_icon_name ("preferences-system-time-symbolic", IconSize.MENU);
         box.add (image);
         clock_label = new Label ("");
@@ -221,11 +234,13 @@ private class Tetravex : Gtk.Application
         grid.attach (box, 1, 1, 1, 1);
 
         undo_action   = (SimpleAction) lookup_action ("undo");
+        redo_action   = (SimpleAction) lookup_action ("redo");
         pause_action  = (SimpleAction) lookup_action ("pause");
         solve_action  = (SimpleAction) lookup_action ("solve");
         finish_action = (SimpleAction) lookup_action ("finish");
 
         undo_action.set_enabled (false);
+        redo_action.set_enabled (false);
         finish_action.set_enabled (false);
 
         view.notify ["tile-selected"].connect (() => {
@@ -346,6 +361,8 @@ private class Tetravex : Gtk.Application
         puzzle.notify ["is-solved-right"].connect (solved_right_cb);
         puzzle.notify ["can-undo"].connect (() =>
             undo_action.set_enabled (puzzle.can_undo && !puzzle.is_solved && !puzzle.paused));
+        puzzle.notify ["can-redo"].connect (() =>
+            redo_action.set_enabled (puzzle.can_redo && !puzzle.is_solved && !puzzle.paused));
         puzzle.show_end_game.connect (show_end_game_cb);
         view.puzzle = puzzle;
         tick_cb ();
@@ -375,6 +392,7 @@ private class Tetravex : Gtk.Application
     private void solved_cb (Puzzle puzzle)
     {
         undo_action.set_enabled (false);
+        redo_action.set_enabled (false);
         pause_action.set_enabled (false);
         solve_action.set_enabled (false);
         finish_action.set_enabled (false);
@@ -566,10 +584,19 @@ private class Tetravex : Gtk.Application
             view.undo ();
     }
 
+    private void redo_cb ()
+    {
+        if (view.tile_selected)
+            view.release_selected_tile ();
+        else
+            view.redo ();
+    }
+
     private void pause_cb (SimpleAction action, Variant? parameter)
     {
         puzzle.paused = !puzzle.paused;
         undo_action.set_enabled (puzzle.can_undo && !puzzle.is_solved && !puzzle.paused);
+        redo_action.set_enabled (puzzle.can_redo && !puzzle.is_solved && !puzzle.paused);
         update_bottom_button_states ();
     }
 
diff --git a/src/puzzle-view.vala b/src/puzzle-view.vala
index bca0d66..17f1474 100644
--- a/src/puzzle-view.vala
+++ b/src/puzzle-view.vala
@@ -627,4 +627,10 @@ private class PuzzleView : Gtk.DrawingArea
         last_selected_tile = null;
         puzzle.undo ();
     }
+
+    internal void redo ()
+    {
+        last_selected_tile = null;
+        puzzle.redo ();
+    }
 }
diff --git a/src/puzzle.vala b/src/puzzle.vala
index 39bf6c5..07122f2 100644
--- a/src/puzzle.vala
+++ b/src/puzzle.vala
@@ -240,7 +240,7 @@ private class Puzzle : Object
     {
         _switch_tiles (x0, y0, x1, y1, delay_if_finished, /* undoing */ false);
     }
-    private void _switch_tiles (uint8 x0, uint8 y0, uint8 x1, uint8 y1, uint delay_if_finished, bool undoing)
+    private void _switch_tiles (uint8 x0, uint8 y0, uint8 x1, uint8 y1, uint delay_if_finished, bool 
undoing_or_redoing)
     {
         if (x0 == x1 && y0 == y1)
             return;
@@ -274,7 +274,7 @@ private class Puzzle : Object
         else if (is_solved_right)
             is_solved_right = false;
 
-        if (!undoing)
+        if (!undoing_or_redoing)
             add_to_history (x0, y0, x1, y1);
     }
 
@@ -429,7 +429,9 @@ private class Puzzle : Object
     \*/
 
     [CCode (notify = true)] internal bool can_undo { internal get; private set; default = false; }
+    [CCode (notify = true)] internal bool can_redo { internal get; private set; default = false; }
     private uint history_length = 0;
+    private uint last_move_index = 0;
 
     private List<Inversion> reversed_history = new List<Inversion> ();
     private const uint animation_duration = 250; // FIXME might better be in view
@@ -449,6 +451,17 @@ private class Puzzle : Object
 
     private void add_to_history (uint8 x0, uint8 y0, uint8 x1, uint8 y1)
     {
+        while (last_move_index != 0)
+        {
+            unowned Inversion? inversion = reversed_history.nth_data (0);
+            if (inversion == null)
+                assert_not_reached ();
+            reversed_history.remove ((!) inversion);
+
+            last_move_index--;
+            history_length--;
+        }
+
         Inversion history_entry = new Inversion (x0, y0, x1, y1);
         reversed_history.prepend (history_entry);
 
@@ -458,16 +471,41 @@ private class Puzzle : Object
 
     internal void undo ()
     {
-        unowned List<Inversion>? history_entry = reversed_history.first ();
-        if (history_entry == null)
+        if (!can_undo)
             return;
 
-        unowned Inversion inversion = ((!) history_entry).data;
-        _switch_tiles (inversion.x0, inversion.y0, inversion.x1, inversion.y1, animation_duration, /* 
undoing */ true);
-        reversed_history.remove (inversion);
+        unowned Inversion? inversion = reversed_history.nth_data (last_move_index);
+        if (inversion == null)
+            assert_not_reached ();
 
-        history_length--;
-        if (history_length == 0)
+        _switch_tiles (((!) inversion).x0, ((!) inversion).y0,
+                       ((!) inversion).x1, ((!) inversion).y1,
+                       animation_duration, /* no log */ true);
+
+        last_move_index++;
+
+        if (last_move_index == history_length)
             can_undo = false;
+        can_redo = true;
+    }
+
+    internal void redo ()
+    {
+        if (!can_redo)
+            return;
+
+        last_move_index--;
+
+        unowned Inversion? inversion = reversed_history.nth_data (last_move_index);
+        if (inversion == null)
+            assert_not_reached ();
+
+        _switch_tiles (((!) inversion).x0, ((!) inversion).y0,
+                       ((!) inversion).x1, ((!) inversion).y1,
+                       animation_duration, /* no log */ true);
+
+        if (last_move_index == 0)
+            can_redo = false;
+        can_undo = true;
     }
 }


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