[gnome-tetravex] Allow finishing puzzle on right.



commit 096865c44e70a24f0b4caa1a7032c136aa9ffe29
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Fri Sep 20 19:09:07 2019 +0200

    Allow finishing puzzle on right.
    
    Or to be exact, allow to work
    a puzzle on the right side of
    the board, then move it left.
    
    Fixes #15.

 src/gnome-tetravex.vala | 65 +++++++++++++++++++++++++++++++++++++++++++++----
 src/puzzle-view.vala    | 20 ++++++++++-----
 src/puzzle.vala         | 14 ++++++++++-
 3 files changed, 87 insertions(+), 12 deletions(-)
---
diff --git a/src/gnome-tetravex.vala b/src/gnome-tetravex.vala
index f004122..06ffa40 100644
--- a/src/gnome-tetravex.vala
+++ b/src/gnome-tetravex.vala
@@ -41,6 +41,7 @@ private class Tetravex : Gtk.Application
 
     private SimpleAction pause_action;
     private SimpleAction solve_action;
+    private SimpleAction finish_action;
 
     private const OptionEntry [] option_entries =
     {
@@ -60,6 +61,7 @@ private class Tetravex : Gtk.Application
         { "new-game",       new_game_cb                                     },
         { "pause",          pause_cb                                        },
         { "solve",          solve_cb                                        },
+        { "finish",         finish_cb                                       },
         { "scores",         scores_cb                                       },
         { "quit",           quit                                            },
         { "move-up",        move_up                                         },
@@ -186,9 +188,17 @@ private class Tetravex : Gtk.Application
                                                     /* align end */ true,
                                                     sizegroup);
 
+        Button finish_button    = new BottomButton ("go-previous-symbolic",
+                                                    "app.finish",
+        /* Translators: tooltip text of bottom bar button that appears is the puzzle is solved on the right 
part of the board */
+                                                    _("Move all tiles left"),
+                                                    /* align end */ true,
+                                                    sizegroup);
+
         new_game_solve_stack = new Stack ();
         new_game_solve_stack.add_named (solve_button, "solve");
         new_game_solve_stack.add_named (new_game_button, "new-game");
+        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);
@@ -202,14 +212,20 @@ private class Tetravex : Gtk.Application
         box.set_margin_bottom (20);
         grid.attach (box, 1, 1, 1, 1);
 
-        pause_action = (SimpleAction) lookup_action ("pause");
-        solve_action = (SimpleAction) lookup_action ("solve");
-        view.tile_selected.connect ((/* bool */ selected) => {
+        pause_action  = (SimpleAction) lookup_action ("pause");
+        solve_action  = (SimpleAction) lookup_action ("solve");
+        finish_action = (SimpleAction) lookup_action ("finish");
+        finish_action.set_enabled (false);
+        view.notify ["tile-selected"].connect (() => {
                 if (!puzzle_init_done)
                     return;
                 if (puzzle.is_solved)
                     return;
-                solve_action.set_enabled (!selected);
+                if (puzzle.is_solved_right)
+                    solve_action.set_enabled (false);
+                else
+                    solve_action.set_enabled (!view.tile_selected && /* should never happen */ 
!puzzle.paused);
+                finish_action.set_enabled (!view.tile_selected);
             });
 
         window.show_all ();
@@ -301,8 +317,10 @@ private class Tetravex : Gtk.Application
 
     private void new_game ()
     {
+        has_been_finished = false;
         pause_action.set_enabled (true);
         solve_action.set_enabled (true);
+        finish_action.set_enabled (false);
         new_game_solve_stack.set_visible_child_name ("solve");
 
         if (puzzle_init_done)
@@ -313,6 +331,7 @@ private class Tetravex : Gtk.Application
         puzzle_init_done = true;
         puzzle.tick.connect (tick_cb);
         puzzle.solved.connect (solved_cb);
+        puzzle.solved_right.connect (solved_right_cb);
         puzzle.show_end_game.connect (show_end_game_cb);
         view.puzzle = puzzle;
         tick_cb ();
@@ -343,6 +362,24 @@ private class Tetravex : Gtk.Application
     {
         pause_action.set_enabled (false);
         solve_action.set_enabled (false);
+        finish_action.set_enabled (false);
+    }
+
+    private void solved_right_cb (Puzzle puzzle, bool is_solved)
+    {
+        if (is_solved)
+        {
+            solve_action.set_enabled (false);
+            finish_action.set_enabled (/* should never happen */ !puzzle.paused);
+            new_game_solve_stack.set_visible_child_name ("finish");
+        }
+        else
+        {
+            solve_action.set_enabled (/* should never happen */ !puzzle.paused);
+            finish_action.set_enabled (false);
+            if (!has_been_finished) // keep the "finish" button if it has been clicked
+                new_game_solve_stack.set_visible_child_name ("solve");
+        }
     }
 
     private void show_end_game_cb (Puzzle puzzle)
@@ -429,9 +466,18 @@ private class Tetravex : Gtk.Application
             new_game_solve_stack.set_visible_child_name ("new-game");
             pause_action.set_enabled (false);
             solve_action.set_enabled (false);
+            finish_action.set_enabled (false);
         }
     }
 
+    private bool has_been_finished = false;
+    private void finish_cb ()
+    {
+        finish_action.set_enabled (false);
+        has_been_finished = true;
+        view.finish ();
+    }
+
     private void size_changed (SimpleAction action, Variant variant)
     {
         int size = ((string) variant)[0] - '0'; // FIXME that... is... horrible
@@ -479,7 +525,16 @@ private class Tetravex : Gtk.Application
 
     private void update_button_states ()
     {
-        solve_action.set_enabled (!puzzle.paused);
+        if (puzzle.is_solved_right)
+        {
+            solve_action.set_enabled (false);
+            finish_action.set_enabled (!puzzle.paused && !view.tile_selected);
+        }
+        else
+        {
+            solve_action.set_enabled (!puzzle.paused && !view.tile_selected);
+            finish_action.set_enabled (false);
+        }
         play_pause_stack.set_visible_child_name (puzzle.paused ? "play" : "pause");
     }
 
diff --git a/src/puzzle-view.vala b/src/puzzle-view.vala
index 6838b6b..dc01d2d 100644
--- a/src/puzzle-view.vala
+++ b/src/puzzle-view.vala
@@ -48,6 +48,7 @@ private class PuzzleView : Gtk.DrawingArea
 
     /* Animations duration */
     private const double animation_duration = 0.25;
+    private const uint final_animation_duration = 250;
     private const double half_animation_duration = 0.15;
 
     /* Puzzle being rendered */
@@ -92,7 +93,7 @@ private class PuzzleView : Gtk.DrawingArea
     /* Tile being controlled by the mouse */
     private TileImage? selected_tile = null;
     private TileImage? last_selected_tile = null;
-    internal signal void tile_selected (bool selected);
+    [CCode (notify = true)] internal bool tile_selected { internal get; private set; default = false; }
 
     /* Timeout to detect if a click is a selection or a drag */
     private uint selection_timeout = 0;
@@ -321,7 +322,7 @@ private class PuzzleView : Gtk.DrawingArea
         if (selected_tile != null)
             ((!) selected_tile).snap_to_cursor = true;
         selected_tile = null;
-        tile_selected (false);
+        tile_selected = false;
 
         return false;
     }
@@ -429,7 +430,7 @@ private class PuzzleView : Gtk.DrawingArea
             {
                 selected_tile = image;
                 last_selected_tile = image;
-                tile_selected (true);
+                tile_selected = true;
                 selected_x_offset = x - image.x;
                 selected_y_offset = y - image.y;
 
@@ -485,7 +486,7 @@ private class PuzzleView : Gtk.DrawingArea
             move_tile_to_location ((!) selected_tile, selected_x, selected_y, animation_duration);
         ((!) selected_tile).snap_to_cursor = true;
         selected_tile = null;
-        tile_selected (false);
+        tile_selected = false;
     }
 
     private void move_tile_to_right_half (Tile tile)
@@ -536,14 +537,14 @@ private class PuzzleView : Gtk.DrawingArea
                         uint8 selected_x, selected_y;
                         puzzle.get_tile_location (((!) selected_tile).tile, out selected_x, out selected_y);
                         if (puzzle.can_switch (selected_x, selected_y, x, y))
-                            puzzle.switch_tiles (selected_x, selected_y, x, y, (uint) (animation_duration * 
1000.0));
+                            puzzle.switch_tiles (selected_x, selected_y, x, y, final_animation_duration);
                     }
                 }
                 else
                     move_tile_to_right_half (((!) selected_tile).tile);
                 ((!) selected_tile).snap_to_cursor = true;
                 selected_tile = null;
-                tile_selected (false);
+                tile_selected = false;
             }
         }
 
@@ -622,4 +623,11 @@ private class PuzzleView : Gtk.DrawingArea
 
         return false;
     }
+
+    internal void finish ()
+    {
+        for (uint8 x = 0; x < puzzle.size; x++)
+            for (uint8 y = 0; y < puzzle.size; y++)
+                puzzle.switch_tiles (x + puzzle.size, y, x, y, final_animation_duration);
+    }
 }
diff --git a/src/puzzle.vala b/src/puzzle.vala
index e3cc2c5..b0feb0f 100644
--- a/src/puzzle.vala
+++ b/src/puzzle.vala
@@ -66,6 +66,7 @@ private class Puzzle : Object
 
     internal signal void tile_moved (Tile tile, uint8 x, uint8 y);
     internal signal void solved ();
+    internal signal void solved_right (bool is_solved);
     internal signal void show_end_game ();
     internal signal void tick ();
 
@@ -157,7 +158,7 @@ private class Puzzle : Object
             }
         }
     }
-    private inline bool solved_on_right ()
+    private bool solved_on_right ()
     {
         for (uint8 x = size; x < 2 * size; x++)
         {
@@ -234,6 +235,7 @@ private class Puzzle : Object
     }
 
     private uint timeout_id = 0;
+    internal bool is_solved_right { internal get; private set; default = false; }
     internal void switch_tiles (uint8 x0, uint8 y0, uint8 x1, uint8 y1, uint delay_if_finished = 0)
     {
         if (x0 == x1 && y0 == y1)
@@ -262,6 +264,16 @@ private class Puzzle : Object
                         return Source.REMOVE;
                     });
         }
+        else if (solved_on_right ())
+        {
+            is_solved_right = true;
+            solved_right (true);
+        }
+        else if (is_solved_right)
+        {
+            is_solved_right = false;
+            solved_right (false);
+        }
     }
 
     /*\


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