[gnome-nibbles/arnaudb/kill-preferences-dialog: 7/17] Do not start game with uncontrollable worm.



commit 76295c026edcf84d7dbe01e6947103292429a683
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Thu Jun 11 18:05:00 2020 +0200

    Do not start game with uncontrollable worm.

 data/controls.ui        |  2 +-
 src/controls.vala       | 48 +++++++++++++++++++++++++++++++++++++++++++++---
 src/nibbles-game.vala   | 48 ++++++++++++++++++++++++++++++++++++++++--------
 src/nibbles-window.vala | 36 ++++++++++++++++++++++++++++++------
 src/worm.vala           | 14 +++++++-------
 5 files changed, 123 insertions(+), 25 deletions(-)
---
diff --git a/data/controls.ui b/data/controls.ui
index a1247f7..f80a87a 100644
--- a/data/controls.ui
+++ b/data/controls.ui
@@ -53,7 +53,7 @@
         <property name="use-underline">True</property>
         <!-- Translators: label of a button in the last panel displayed during game configuration (the 
"Controls" one); starts the game -->
         <property name="label" translatable="yes">_Start</property>
-        <property name="action-name">win.next-screen</property>
+        <property name="action-name">win.start-game</property>
         <property name="halign">center</property>
         <property name="width-request">116</property>
         <property name="height-request">34</property>
diff --git a/src/controls.vala b/src/controls.vala
index 773c179..7762245 100644
--- a/src/controls.vala
+++ b/src/controls.vala
@@ -23,6 +23,7 @@ using Gtk;
 private class Controls : Box
 {
     [GtkChild] private Box grids_box;
+    private Gee.LinkedList<ControlsGrid> grids = new Gee.LinkedList<ControlsGrid> ();
 
     private Gdk.Pixbuf arrow_pixbuf;
     private Gdk.Pixbuf arrow_key_pixbuf;
@@ -33,7 +34,7 @@ private class Controls : Box
         arrow_key_pixbuf = NibblesView.load_pixmap_file ("arrow-key.svg", 5 * tile_size, 5 * tile_size);
     }
 
-    internal void prepare (Gee.LinkedList<Worm> worms, Gee.HashMap<Worm, WormProperties?> worm_props)
+    internal void prepare (Gee.LinkedList<Worm> worms, Gee.HashMap<Worm, WormProperties> worm_props)
     {
         foreach (var grid in grids_box.get_children ())
             grid.destroy ();
@@ -44,9 +45,17 @@ private class Controls : Box
             {
                 var grid = new ControlsGrid (worm.id, worm_props.@get (worm), arrow_pixbuf, 
arrow_key_pixbuf);
                 grids_box.add (grid);
+                grids.add (grid);
             }
         }
     }
+
+    internal void clean ()
+    {
+        foreach (ControlsGrid grid in grids)
+            grid.disconnect_stuff ();
+        grids.clear ();
+    }
 }
 
 [GtkTemplate (ui = "/org/gnome/nibbles/ui/controls-grid.ui")]
@@ -62,13 +71,26 @@ private class ControlsGrid : Grid
     [GtkChild] private Label move_left_label;
     [GtkChild] private Label move_right_label;
 
+    private WormProperties worm_props;
+    private ulong    up_handler;
+    private ulong  down_handler;
+    private ulong  left_handler;
+    private ulong right_handler;
+    private ulong color_handler;
+
     internal ControlsGrid (int worm_id, WormProperties worm_props, Gdk.Pixbuf arrow, Gdk.Pixbuf arrow_key)
     {
-        var color = Pango.Color ();
-        color.parse (NibblesView.colorval_name_untranslated (worm_props.color));
+        this.worm_props = worm_props;
 
         /* Translators: text displayed in a screen showing the keys used by the players; the %d is replaced 
by the number that identifies the player */
         var player_id = _("Player %d").printf (worm_id + 1);
+        color_handler = worm_props.notify ["color"].connect (() => {
+                var color = Pango.Color ();
+                color.parse (NibblesView.colorval_name_untranslated (worm_props.color));
+                name_label.set_markup (@"<b><span font-family=\"Sans\" color=\"$(color.to_string 
())\">$(player_id)</span></b>");
+            });
+        var color = Pango.Color ();
+        color.parse (NibblesView.colorval_name_untranslated (worm_props.color));
         name_label.set_markup (@"<b><span font-family=\"Sans\" color=\"$(color.to_string 
())\">$(player_id)</span></b>");
 
         arrow_up.set_from_pixbuf    (arrow.rotate_simple (Gdk.PixbufRotation.NONE));
@@ -76,12 +98,26 @@ private class ControlsGrid : Grid
         arrow_left.set_from_pixbuf  (arrow.rotate_simple (Gdk.PixbufRotation.COUNTERCLOCKWISE));
         arrow_right.set_from_pixbuf (arrow.rotate_simple (Gdk.PixbufRotation.CLOCKWISE));
 
+           up_handler = worm_props.notify ["up"].connect    (() => configure_label (Gdk.keyval_name 
(worm_props.up),    ref move_up_label));
+         down_handler = worm_props.notify ["down"].connect  (() => configure_label (Gdk.keyval_name 
(worm_props.down),  ref move_down_label));
+         left_handler = worm_props.notify ["left"].connect  (() => configure_label (Gdk.keyval_name 
(worm_props.left),  ref move_left_label));
+        right_handler = worm_props.notify ["right"].connect (() => configure_label (Gdk.keyval_name 
(worm_props.right), ref move_right_label));
+
         configure_label (Gdk.keyval_name (worm_props.up),    ref move_up_label);
         configure_label (Gdk.keyval_name (worm_props.down),  ref move_down_label);
         configure_label (Gdk.keyval_name (worm_props.left),  ref move_left_label);
         configure_label (Gdk.keyval_name (worm_props.right), ref move_right_label);
     }
 
+    internal void disconnect_stuff ()
+    {
+        worm_props.disconnect (   up_handler);
+        worm_props.disconnect ( down_handler);
+        worm_props.disconnect ( left_handler);
+        worm_props.disconnect (right_handler);
+        worm_props.disconnect (color_handler);
+    }
+
     private static void configure_label (string? key_name, ref Label label)
     {
         if (key_name == "Up")
@@ -105,8 +141,14 @@ private class ControlsGrid : Grid
             label.set_text ("→");
         }
         else if (key_name == null || key_name == "")
+        {
+            label.get_style_context ().remove_class ("arrow");
             label.set_text ("");
+        }
         else
+        {
+            label.get_style_context ().remove_class ("arrow");
             label.set_text (@"$(key_name.up ())");
+        }
     }
 }
diff --git a/src/nibbles-game.vala b/src/nibbles-game.vala
index bd941a1..d83c949 100644
--- a/src/nibbles-game.vala
+++ b/src/nibbles-game.vala
@@ -59,8 +59,8 @@ private class NibblesGame : Object
     internal int numworms       { internal get; private set; }
 
     /* Game models */
-    public Gee.LinkedList<Worm> worms                       { internal get; default = new 
Gee.LinkedList<Worm> (); }
-    public Gee.HashMap<Worm, WormProperties?> worm_props    { internal get; default = new Gee.HashMap<Worm, 
WormProperties?> (); }
+    public Gee.LinkedList<Worm> worms                   { internal get; default = new Gee.LinkedList<Worm> 
(); }
+    public Gee.HashMap<Worm, WormProperties> worm_props { internal get; default = new Gee.HashMap<Worm, 
WormProperties> (); }
 
     private Boni boni = new Boni ();
     private WarpManager warp_manager = new WarpManager ();
@@ -601,16 +601,48 @@ private class NibblesGame : Object
         worm_props.clear ();
         foreach (var worm in worms)
         {
-            var properties = WormProperties ();
-            properties.color = worm_settings[worm.id].get_enum ("color");
-            properties.up = worm_settings[worm.id].get_int ("key-up");
-            properties.down = worm_settings[worm.id].get_int ("key-down");
-            properties.left = worm_settings[worm.id].get_int ("key-left");
-            properties.right = worm_settings[worm.id].get_int ("key-right");
+            var properties = new WormProperties ();
+
+            worm_settings[worm.id].bind_with_mapping ("color", properties, "color", 
SettingsBindFlags.DEFAULT,
+                                                      (prop_value, variant) => { prop_value.set_int 
(get_color_num (variant.get_string ()));
+                                                                                 return /* success */ true; 
},
+                                                      (prop_value, variant_type) => { return new 
Variant.@string (get_color_string (prop_value.get_int ())); },
+                                                      null, null);
+
+            worm_settings[worm.id].bind ("key-up",      properties, "up",       SettingsBindFlags.DEFAULT);
+            worm_settings[worm.id].bind ("key-down",    properties, "down",     SettingsBindFlags.DEFAULT);
+            worm_settings[worm.id].bind ("key-left",    properties, "left",     SettingsBindFlags.DEFAULT);
+            worm_settings[worm.id].bind ("key-right",   properties, "right",    SettingsBindFlags.DEFAULT);
 
             worm_props.@set (worm, properties);
         }
     }
+    private static inline string get_color_string (int color)
+    {
+        switch (color)
+        {
+            case 0: return "red";
+            case 1: return "green";
+            case 2: return "blue";
+            case 3: return "yellow";
+            case 4: return "cyan";
+            case 5: return "purple";
+            default: assert_not_reached ();
+        }
+    }
+    private static inline int get_color_num (string color)
+    {
+        switch (color)
+        {
+            case "red":     return 0;
+            case "green":   return 1;
+            case "blue":    return 2;
+            case "yellow":  return 3;
+            case "cyan":    return 4;
+            case "purple":  return 5;
+            default: assert_not_reached ();
+        }
+    }
 
     internal bool handle_keypress (uint keyval)
     {
diff --git a/src/nibbles-window.vala b/src/nibbles-window.vala
index eaf22d1..7507da2 100644
--- a/src/nibbles-window.vala
+++ b/src/nibbles-window.vala
@@ -68,6 +68,7 @@ private class NibblesWindow : ApplicationWindow
     private SimpleAction new_game_action;
     private SimpleAction pause_action;
     private SimpleAction back_action;
+    private SimpleAction start_game_action;
 
     private uint countdown_id = 0;
     private const int COUNTDOWN_TIME = 3;
@@ -80,16 +81,18 @@ private class NibblesWindow : ApplicationWindow
         { "preferences",    preferences_cb  },
         { "scores",         scores_cb       },
 
-        { "next-screen",    next_screen_cb  },  // called from first-run, players, speed and controls
+        { "next-screen",    next_screen_cb  },  // called from first-run, players and speed
+        { "start-game",     start_game      },  // called from controls
         { "back",           back_cb         }   // called on Escape pressed; disabled only during countdown 
(TODO pause?)
     };
 
     construct
     {
         add_action_entries (menu_entries, this);
-        new_game_action = (SimpleAction) lookup_action ("new-game");
-        pause_action    = (SimpleAction) lookup_action ("pause");
-        back_action     = (SimpleAction) lookup_action ("back");
+        new_game_action     = (SimpleAction) lookup_action ("new-game");
+        pause_action        = (SimpleAction) lookup_action ("pause");
+        back_action         = (SimpleAction) lookup_action ("back");
+        start_game_action   = (SimpleAction) lookup_action ("start-game");
 
         settings = new GLib.Settings ("org.gnome.Nibbles");
         settings.changed.connect (settings_changed_cb);
@@ -430,6 +433,9 @@ private class NibblesWindow : ApplicationWindow
         }
 
         game.worm_props.@set (worm, properties);
+
+        if (id < game.numhumans)
+            update_start_game_action ();
     }
 
     /*\
@@ -451,8 +457,7 @@ private class NibblesWindow : ApplicationWindow
                 show_controls_screen ();
                 break;
             case "controls":
-                start_game ();
-                break;
+                assert_not_reached ();
             default:
                 return;
         }
@@ -509,14 +514,33 @@ private class NibblesWindow : ApplicationWindow
         settings.set_boolean ("fakes", fakes);
 
         /* Create worms and load properties */
+        controls.clean ();
         game.create_worms ();
         game.load_worm_properties (worm_settings);
+        update_start_game_action ();
 
         controls.prepare (game.worms, game.worm_props);
 
         main_stack.set_visible_child_name ("controls");
     }
 
+    private void update_start_game_action ()
+    {
+        for (int i = 0; i < game.numhumans; i++)
+        {
+            WormProperties worm_prop = game.worm_props.@get (game.worms.@get (i));
+            if (worm_prop.up    == 0
+             || worm_prop.down  == 0
+             || worm_prop.left  == 0
+             || worm_prop.right == 0)
+            {
+                start_game_action.set_enabled (false);
+                return;
+            }
+        }
+        start_game_action.set_enabled (true);
+    }
+
     private void show_game_view ()
     {
         /* FIXME: If there's a transition set, on Wayland, the ClutterEmbed
diff --git a/src/worm.vala b/src/worm.vala
index f96e6d8..4f2d258 100644
--- a/src/worm.vala
+++ b/src/worm.vala
@@ -34,13 +34,13 @@ private struct Position
     int y;
 }
 
-private struct WormProperties
+private class WormProperties : Object
 {
-    int color;
-    uint up;
-    uint down;
-    uint left;
-    uint right;
+    internal int color  { internal get; internal set; }
+    internal uint up    { internal get; internal set; }
+    internal uint down  { internal get; internal set; }
+    internal uint left  { internal get; internal set; }
+    internal uint right { internal get; internal set; }
 }
 
 private class Worm : Object
@@ -396,7 +396,7 @@ private class Worm : Object
         direction_set (dir);
     }
 
-    internal bool handle_keypress (uint keyval, Gee.HashMap<Worm, WormProperties?> worm_props)
+    internal bool handle_keypress (uint keyval, Gee.HashMap<Worm, WormProperties> worm_props)
     {
         if (lives <= 0 || is_stopped)
             return false;


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