[lightsoff/wip/gtkview] Moved board logic to gtk board view



commit a601e1f41d9d1266c5855c071bac66dec5ebce83
Author: Robert Roth <robert roth off gmail com>
Date:   Sun Jul 15 00:37:03 2018 +0300

    Moved board logic to gtk board view

 src/board-view-gtk.vala | 162 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/game-view-gtk.vala  | 142 +++++++++++-------------------------------
 src/meson.build         |   1 +
 3 files changed, 199 insertions(+), 106 deletions(-)
---
diff --git a/src/board-view-gtk.vala b/src/board-view-gtk.vala
new file mode 100644
index 0000000..8fa1989
--- /dev/null
+++ b/src/board-view-gtk.vala
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 Robert Roth
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public class BoardViewGtk : Gtk.Grid
+{
+    private new const int size = 5;
+    private PuzzleGenerator puzzle_generator;
+    private Gtk.ToggleButton[,] lights;
+
+    public bool playable = true;
+
+    private int _moves = 0;
+    public int moves
+    {
+        get { return _moves;}
+    }
+
+    public signal void game_won ();
+    public signal void light_toggled ();
+
+    public BoardViewGtk ()
+    {
+        get_style_context ().add_class ("grid");
+        row_homogeneous = true;
+        column_homogeneous = true;
+        border_width = 4;
+        row_spacing = 2;
+        column_spacing = 2;
+
+        set_size_request (size * 72, size * 72);
+
+        puzzle_generator = new PuzzleGenerator (size);
+        lights = new Gtk.ToggleButton [size, size];
+        for (var x = 0; x < size; x++)
+            for (var y = 0; y < size; y++)
+            {
+                lights[x, y] = new Gtk.ToggleButton ();
+                lights[x, y].show ();
+                lights[x, y].toggled.connect (light_toggled_cb);
+                attach (lights[x, y], x, y, 1, 1);
+            }
+
+        _moves = 0;
+    }
+
+    public void slide_in (int direction, int sign, Clutter.Timeline timeline)
+    {
+    }
+
+    public void slide_out (int direction, int sign, Clutter.Timeline timeline)
+    {
+    }
+
+    public void swap_in (float direction, Clutter.Timeline timeline)
+    {
+    }
+
+    public void swap_out (float direction, Clutter.Timeline timeline)
+    {
+    }
+
+    private void find_light (Gtk.ToggleButton light, out int x, out int y)
+    {
+        x = y = 0;
+        for (x = 0; x < size; x++)
+            for (y = 0; y < size; y++)
+                if (lights[x, y] == light)
+                    return;
+    }
+
+    private bool is_completed ()
+    {
+        var cleared = true;
+        for (var x = 0; x < size; x++)
+            for (var y = 0; y < size; y++)
+                if (lights[x, y].active)
+                    cleared = false;
+
+        return cleared;
+    }
+
+    public void light_toggled_cb (Gtk.ToggleButton source)
+    {
+        int xl, yl;
+        find_light (source, out xl, out yl);
+
+        toggle_light (xl, yl, true);
+        _moves += 1;
+        light_toggled ();
+        if (is_completed ()) {
+            game_won ();
+        }
+    }
+    // Pseudorandomly generates and sets the state of each light based on
+    // a level number; hopefully this is stable between machines, but that
+    // depends on GLib's PRNG stability. Also, provides some semblance of
+    // symmetry for some levels.
+
+     // Toggle a light and those in each cardinal direction around it.
+    private void toggle_light (int x, int y, bool clicked = false)
+    {
+        for (var xi = 0; xi < size; xi++)
+            for (var yi = 0; yi < size; yi++)
+                lights[xi, yi].toggled.disconnect (light_toggled_cb);
+
+        if (x>= size || y >= size || x < 0 || y < 0 )
+            return;
+        if ((int) x + 1 < size)
+            lights[(int) x + 1, (int) y].set_active (!lights[(int) x + 1, (int) y].get_active ());
+        if ((int) x - 1 >= 0)
+            lights[(int) x - 1, (int) y].set_active (!lights[(int) x - 1, (int) y].get_active ());
+        if ((int) y + 1 < size)
+            lights[(int) x, (int) y + 1].set_active (!lights[(int) x, (int) y + 1].get_active ());
+        if ((int) y - 1 >= 0)
+            lights[(int) x, (int) y - 1].set_active (!lights[(int) x, (int) y - 1].get_active ());
+
+        if (!clicked)
+            lights[(int) x, (int) y].set_active (!lights[(int) x, (int) y ].get_active ());
+
+        for (var xi = 0; xi < size; xi++)
+            for (var yi = 0; yi < size; yi++)
+                lights[xi, yi].toggled.connect (light_toggled_cb);
+    }
+
+    public void load_level (int level)
+    {
+        _moves = 0;
+        light_toggled ();
+        /* We *must* not have level < 1, as the following assumes a nonzero, nonnegative number */
+        if (level < 1)
+            level = 1;
+
+        for (var xi = 0; xi < size; xi++)
+            for (var yi = 0; yi < size; yi++)
+                lights[xi, yi].toggled.disconnect (light_toggled_cb);
+
+        /* Clear level */
+        for (var x = 0; x < size; x++)
+            for (var y = 0; y < size; y++)
+                lights[x, y].active = false;
+
+        /* Use the same pseudo-random levels */
+        Random.set_seed (level);
+
+        /* Levels require more and more clicks to make */
+        var solution_length = (int) Math.floor (2 * Math.log (level) + 1);
+
+        /* Do the moves the player needs to */
+        var sol = puzzle_generator.minimal_solution (solution_length);
+        for (var x = 0; x < size; x++)
+            for (var y = 0; y < size; y++)
+                if (sol[x, y])
+                    toggle_light (x, y);
+    }
+}
diff --git a/src/game-view-gtk.vala b/src/game-view-gtk.vala
index 5e83597..b6bce8e 100644
--- a/src/game-view-gtk.vala
+++ b/src/game-view-gtk.vala
@@ -1,15 +1,17 @@
-public class GtkGameView : Gtk.Grid, GameView {
+public class GtkGameView : Gtk.Frame, GameView {
 
-    private Gtk.ToggleButton[,] lights;
-    private new const int SIZE = 5;
-    private PuzzleGenerator puzzle_generator;
+    private BoardViewGtk board_view;
+    private BoardViewGtk? new_board_view = null;
     private int current_level;
-    private int moves;
 
     public void swap_board (int direction)
     {
         current_level += direction;
-        load_level (current_level);
+        new_board_view = create_board_view (current_level);
+        remove (board_view);
+        add (new_board_view);
+        board_view = new_board_view;
+        level_changed (current_level);
     }
     public void hide_cursor ()
     {
@@ -23,125 +25,53 @@ public class GtkGameView : Gtk.Grid, GameView {
     public void reset_game ()
     {
         current_level = 1;
-        load_level (current_level);
+        new_board_view = create_board_view (current_level);
+        remove (board_view);
+        add (new_board_view);
+        board_view = new_board_view;
+
+        level_changed (current_level);
     }
 
     public GtkGameView (int level)
     {
-        get_style_context ().add_class ("grid");
-        puzzle_generator = new PuzzleGenerator (SIZE);
                 /* Clear level */
         current_level = level;
-        lights = new Gtk.ToggleButton [SIZE, SIZE];
-        for (var x = 0; x < SIZE; x++)
-            for (var y = 0; y < SIZE; y++)
-            {
-                lights[x, y] = new Gtk.ToggleButton ();
-                lights[x, y].show ();
-                lights[x, y].toggled.connect (light_toggled_cb);
-                attach (lights[x, y], x, y, 1, 1);
-            }
 
-        set_size_request (SIZE * 72, SIZE * 72);
-        row_homogeneous = true;
-        column_homogeneous = true;
-        load_level (current_level);
-        border_width = 4;
-        row_spacing = 2;
-        column_spacing = 2;
-    }
+        board_view = create_board_view (current_level);
+        board_view.playable = true;
+        add (board_view);
 
-    private void find_light (Gtk.ToggleButton light, out int x, out int y)
-    {
-        x = y = 0;
-        for (x = 0; x < SIZE; x++)
-            for (y = 0; y < SIZE; y++)
-                if (lights[x, y] == light)
-                    return;
     }
 
-    private bool is_completed ()
+    private BoardViewGtk create_board_view (int level)
     {
-        var cleared = true;
-        for (var x = 0; x < SIZE; x++)
-            for (var y = 0; y < SIZE; y++)
-                if (lights[x, y].active)
-                    cleared = false;
-
-        return cleared;
+        var view = new BoardViewGtk ();
+        view.load_level (level);
+        view.game_won.connect (game_won_cb);
+        view.light_toggled.connect (light_toggled_cb);
+        view.playable = false;
+        view.show_all ();
+        return view;
     }
 
-    public void light_toggled_cb (Gtk.ToggleButton source)
+    private void light_toggled_cb ()
     {
-        int xl, yl;
-        find_light (source, out xl, out yl);
-
-        toggle_light (xl, yl, true);
-        moves_changed (++moves);
-        if (is_completed ()) {
-            load_level (++current_level);
-        }
+        moves_changed (board_view.moves);
     }
-    // Pseudorandomly generates and sets the state of each light based on
-    // a level number; hopefully this is stable between machines, but that
-    // depends on GLib's PRNG stability. Also, provides some semblance of
-    // symmetry for some levels.
 
-     // Toggle a light and those in each cardinal direction around it.
-    private void toggle_light (int x, int y, bool clicked = false)
+// The player won the game; create a new board, update the level count,
+    // and transition between the two boards in a random direction.
+    private void game_won_cb ()
     {
-        for (var xi = 0; xi < SIZE; xi++)
-            for (var yi = 0; yi < SIZE; yi++)
-                lights[xi, yi].toggled.disconnect (light_toggled_cb);
-
-        if (x>= SIZE || y >= SIZE || x < 0 || y < 0 )
-            return;
-        if ((int) x + 1 < SIZE)
-            lights[(int) x + 1, (int) y].set_active (!lights[(int) x + 1, (int) y].get_active ());
-        if ((int) x - 1 >= 0)
-            lights[(int) x - 1, (int) y].set_active (!lights[(int) x - 1, (int) y].get_active ());
-        if ((int) y + 1 < SIZE)
-            lights[(int) x, (int) y + 1].set_active (!lights[(int) x, (int) y + 1].get_active ());
-        if ((int) y - 1 >= 0)
-            lights[(int) x, (int) y - 1].set_active (!lights[(int) x, (int) y - 1].get_active ());
+        current_level++;
 
-        if (!clicked)
-            lights[(int) x, (int) y].set_active (!lights[(int) x, (int) y ].get_active ());
+        new_board_view = create_board_view (current_level);
+        remove (board_view);
+        add (new_board_view);
+        board_view = new_board_view;
 
-        for (var xi = 0; xi < SIZE; xi++)
-            for (var yi = 0; yi < SIZE; yi++)
-                lights[xi, yi].toggled.connect (light_toggled_cb);
+        level_changed (current_level);
     }
 
-    public void load_level (int level)
-    {
-        moves = 0;
-        moves_changed (moves);
-        level_changed (level);
-        /* We *must* not have level < 1, as the following assumes a nonzero, nonnegative number */
-        if (level < 1)
-            level = 1;
-
-        for (var xi = 0; xi < SIZE; xi++)
-            for (var yi = 0; yi < SIZE; yi++)
-                lights[xi, yi].toggled.disconnect (light_toggled_cb);
-
-        /* Clear level */
-        for (var x = 0; x < SIZE; x++)
-            for (var y = 0; y < SIZE; y++)
-                lights[x, y].active = false;
-
-        /* Use the same pseudo-random levels */
-        Random.set_seed (level);
-
-        /* Levels require more and more clicks to make */
-        var solution_length = (int) Math.floor (2 * Math.log (level) + 1);
-
-        /* Do the moves the player needs to */
-        var sol = puzzle_generator.minimal_solution (solution_length);
-        for (var x = 0; x < SIZE; x++)
-            for (var y = 0; y < SIZE; y++)
-                if (sol[x, y])
-                    toggle_light (x, y);
-    }
 }
diff --git a/src/meson.build b/src/meson.build
index 1fb5533..6e69dd8 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,5 +1,6 @@
 lightsoff_vala_sources = [
   'board-view-clutter.vala',
+  'board-view-gtk.vala',
   'lightsoff.vala',
   'lightsoff-window.vala',
   'puzzle-generator.vala',


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