[gnome-tetravex] Allow Undo.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-tetravex] Allow Undo.
- Date: Sat, 21 Sep 2019 00:45:54 +0000 (UTC)
commit 309516d526169587b546dbd6cb139abb3e545a41
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Fri Sep 20 23:30:20 2019 +0200
Allow Undo.
Progress on #2.
src/gnome-tetravex.vala | 32 +++++++++++++++++++++++++----
src/puzzle-view.vala | 16 +++++++++++++++
src/puzzle.vala | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 4 deletions(-)
---
diff --git a/src/gnome-tetravex.vala b/src/gnome-tetravex.vala
index b35368d..ab01b89 100644
--- a/src/gnome-tetravex.vala
+++ b/src/gnome-tetravex.vala
@@ -39,6 +39,7 @@ private class Tetravex : Gtk.Application
private Stack new_game_solve_stack;
private Stack play_pause_stack;
+ private SimpleAction undo_action;
private SimpleAction pause_action;
private SimpleAction solve_action;
private SimpleAction finish_action;
@@ -68,6 +69,7 @@ private class Tetravex : Gtk.Application
{ "move-down", move_down },
{ "move-left", move_left },
{ "move-right", move_right },
+ { "undo", undo_cb },
{ "size", radio_cb, "s", "'2'", size_changed },
{ "help", help_cb },
{ "about", about_cb }
@@ -109,6 +111,7 @@ private class Tetravex : Gtk.Application
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" });
// F1 and friends are managed manually
Builder builder = new Builder.from_resource ("/org/gnome/Tetravex/gnome-tetravex.ui");
@@ -145,6 +148,11 @@ private class Tetravex : Gtk.Application
menu_button.set_menu_model (appmenu);
headerbar.pack_end (menu_button);
+ 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);
+
Grid grid = (Grid) builder.get_object ("grid");
view = new PuzzleView ();
@@ -212,10 +220,14 @@ private class Tetravex : Gtk.Application
box.set_margin_bottom (20);
grid.attach (box, 1, 1, 1, 1);
+ undo_action = (SimpleAction) lookup_action ("undo");
pause_action = (SimpleAction) lookup_action ("pause");
solve_action = (SimpleAction) lookup_action ("solve");
finish_action = (SimpleAction) lookup_action ("finish");
+
+ undo_action.set_enabled (false);
finish_action.set_enabled (false);
+
view.notify ["tile-selected"].connect (() => {
if (!puzzle_init_done)
return;
@@ -332,6 +344,8 @@ private class Tetravex : Gtk.Application
puzzle.tick.connect (tick_cb);
puzzle.solved.connect (solved_cb);
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.show_end_game.connect (show_end_game_cb);
view.puzzle = puzzle;
tick_cb ();
@@ -341,7 +355,7 @@ private class Tetravex : Gtk.Application
puzzle.paused = true;
start_paused = false;
}
- update_button_states ();
+ update_bottom_button_states ();
}
private void tick_cb ()
@@ -360,6 +374,7 @@ private class Tetravex : Gtk.Application
private void solved_cb (Puzzle puzzle)
{
+ undo_action.set_enabled (false);
pause_action.set_enabled (false);
solve_action.set_enabled (false);
finish_action.set_enabled (false);
@@ -455,7 +470,7 @@ private class Tetravex : Gtk.Application
if (puzzle.paused)
{
puzzle.paused = false;
- update_button_states ();
+ update_bottom_button_states ();
return true;
}
@@ -543,13 +558,22 @@ private class Tetravex : Gtk.Application
}
private void move_right () { puzzle.move_right (); }
+ private void undo_cb ()
+ {
+ if (view.tile_selected)
+ view.release_selected_tile ();
+ else
+ view.undo ();
+ }
+
private void pause_cb (SimpleAction action, Variant? parameter)
{
puzzle.paused = !puzzle.paused;
- update_button_states ();
+ undo_action.set_enabled (puzzle.can_undo && !puzzle.is_solved && !puzzle.paused);
+ update_bottom_button_states ();
}
- private void update_button_states ()
+ private void update_bottom_button_states ()
{
if (puzzle.is_solved_right)
{
diff --git a/src/puzzle-view.vala b/src/puzzle-view.vala
index 76bf21e..bca0d66 100644
--- a/src/puzzle-view.vala
+++ b/src/puzzle-view.vala
@@ -611,4 +611,20 @@ private class PuzzleView : Gtk.DrawingArea
for (uint8 y = 0; y < puzzle.size; y++)
puzzle.switch_tiles (x + puzzle.size, y, x, y, final_animation_duration);
}
+
+ internal void release_selected_tile ()
+ {
+ uint8 selected_x, selected_y;
+ puzzle.get_tile_location (((!) selected_tile).tile, out selected_x, out selected_y);
+ move_tile_to_location ((!) selected_tile, selected_x, selected_y, animation_duration);
+ ((!) selected_tile).snap_to_cursor = true;
+ selected_tile = null;
+ tile_selected = false;
+ }
+
+ internal void undo ()
+ {
+ last_selected_tile = null;
+ puzzle.undo ();
+ }
}
diff --git a/src/puzzle.vala b/src/puzzle.vala
index 102ef6a..39bf6c5 100644
--- a/src/puzzle.vala
+++ b/src/puzzle.vala
@@ -237,6 +237,10 @@ private class Puzzle : Object
[CCode (notify = false)] internal bool game_in_progress { internal get; private set; default = false; }
[CCode (notify = true)] 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)
+ {
+ _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)
{
if (x0 == x1 && y0 == y1)
return;
@@ -269,6 +273,9 @@ private class Puzzle : Object
is_solved_right = true;
else if (is_solved_right)
is_solved_right = false;
+
+ if (!undoing)
+ add_to_history (x0, y0, x1, y1);
}
/*\
@@ -416,4 +423,51 @@ private class Puzzle : Object
return false;
}
+
+ /*\
+ * * history
+ \*/
+
+ [CCode (notify = true)] internal bool can_undo { internal get; private set; default = false; }
+ private uint history_length = 0;
+
+ private List<Inversion> reversed_history = new List<Inversion> ();
+ private const uint animation_duration = 250; // FIXME might better be in view
+
+ private class Inversion : Object
+ {
+ public uint8 x0 { internal get; protected construct; }
+ public uint8 y0 { internal get; protected construct; }
+ public uint8 x1 { internal get; protected construct; }
+ public uint8 y1 { internal get; protected construct; }
+
+ internal Inversion (uint8 x0, uint8 y0, uint8 x1, uint8 y1)
+ {
+ Object (x0: x0, y0: y0, x1: x1, y1: y1);
+ }
+ }
+
+ private void add_to_history (uint8 x0, uint8 y0, uint8 x1, uint8 y1)
+ {
+ Inversion history_entry = new Inversion (x0, y0, x1, y1);
+ reversed_history.prepend (history_entry);
+
+ history_length++;
+ can_undo = true;
+ }
+
+ internal void undo ()
+ {
+ unowned List<Inversion>? history_entry = reversed_history.first ();
+ if (history_entry == null)
+ 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);
+
+ history_length--;
+ if (history_length == 0)
+ can_undo = false;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]