[five-or-more/gsoc-vala-port: 26/29] Add keyboard controls



commit b17cac83a71e8b536c0fd30aa0f195005460421e
Author: Ruxandra Simion <ruxandra simion93 gmail com>
Date:   Mon Aug 6 20:03:31 2018 +0300

    Add keyboard controls

 data/five-or-more-vala.ui |  21 ++++---
 src-vala/main.vala        |   1 +
 src-vala/view.vala        | 154 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 158 insertions(+), 18 deletions(-)
---
diff --git a/data/five-or-more-vala.ui b/data/five-or-more-vala.ui
index 2eac945..57e5db0 100644
--- a/data/five-or-more-vala.ui
+++ b/data/five-or-more-vala.ui
@@ -76,16 +76,17 @@
             <property name="visible">True</property>
           </object>
           <object class="GtkButton" id="new_game_button">
-                <property name="visible">True</property>
-                <property name="use_underline">True</property>
-                <property name="label" translatable="yes">_New Game</property>
-                <property name="halign">center</property>
-                <property name="valign">end</property>
-                <property name="action-name">app.new-game</property>
-                <property name="tooltip-text" translatable="yes">Start a new puzzle</property>
-                <property name="width-request">120</property>
-                <property name="height-request">60</property>
-            </object>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="use_underline">True</property>
+            <property name="label" translatable="yes">_New Game</property>
+            <property name="halign">center</property>
+            <property name="valign">end</property>
+            <property name="action-name">app.new-game</property>
+            <property name="tooltip-text" translatable="yes">Start a new puzzle</property>
+            <property name="width-request">120</property>
+            <property name="height-request">60</property>
+          </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
diff --git a/src-vala/main.vala b/src-vala/main.vala
index 83a3618..0c92c1e 100644
--- a/src-vala/main.vala
+++ b/src-vala/main.vala
@@ -37,6 +37,7 @@ public class FiveOrMoreApp: Gtk.Application
         window = new GameWindow (this, settings);
 
         add_action_entries (action_entries, this);
+        set_accels_for_action ("app.new-game", {"<Primary>n"});
     }
 
     public static int main (string[] args)
diff --git a/src-vala/view.vala b/src-vala/view.vala
index 098d8bd..b39a270 100644
--- a/src-vala/view.vala
+++ b/src-vala/view.vala
@@ -19,6 +19,10 @@ public class View : Gtk.DrawingArea
     private int end_x;
     private int end_y;
 
+    private bool show_cursor;
+    private int keyboard_cursor_x;
+    private int keyboard_cursor_y;
+
     private int animation_state;
     private uint animation_id;
 
@@ -58,6 +62,10 @@ public class View : Gtk.DrawingArea
 
         game.board.grid_changed.connect (board_changed_cb);
         add_events (Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK);
+        add_events (Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK);
+
+        set_can_focus (true);
+        grab_focus ();
 
         game.current_path_cell_pos_changed.connect (current_path_cell_pos_changed_cb);
 
@@ -66,6 +74,10 @@ public class View : Gtk.DrawingArea
         end_x = -1;
         end_y = -1;
 
+        show_cursor = false;
+        keyboard_cursor_x = -1;
+        keyboard_cursor_y = -1;
+
         animation_state = 0;
         animation_id = -1;
     }
@@ -101,18 +113,104 @@ public class View : Gtk.DrawingArea
         cs.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
     }
 
-    public override bool button_press_event (Gdk.EventButton event)
+    private void draw_box (int x, int y, int width, int height)
     {
-        if (game == null || game.animating)
-            return false;
+        queue_draw_area (x, y, width, height);
+    }
 
-        /* Ignore the 2BUTTON and 3BUTTON events. */
-        if (event.type != Gdk.EventType.BUTTON_PRESS)
-            return false;
+    private void move_keyboard_cursor (int x, int y)
+    {
+        int prev_x = keyboard_cursor_x;
+        int prev_y = keyboard_cursor_y;
 
-        cell_x = (int)event.x / piece_size;
-        cell_y = (int)event.y / piece_size;
+        if (!show_cursor)
+        {
+            show_cursor = true;
+            // queue_draw ();
+            draw_box (keyboard_cursor_x * piece_size, keyboard_cursor_y * piece_size, piece_size, 
piece_size);
+        }
+
+        keyboard_cursor_x += x;
+        if (keyboard_cursor_x < 0)
+            keyboard_cursor_x = 0;
+        if (keyboard_cursor_x >= game.n_cols)
+            keyboard_cursor_x = game.n_cols - 1;
+
+        keyboard_cursor_y += y;
+        if (keyboard_cursor_y < 0)
+            keyboard_cursor_y = 0;
+        if (keyboard_cursor_y >= game.n_rows)
+            keyboard_cursor_y = game.n_rows - 1;
+
+        if (keyboard_cursor_x == prev_x && keyboard_cursor_y == prev_y)
+            return;
+            // queue_draw ();
+        draw_box (prev_x * piece_size, prev_y * piece_size, piece_size, piece_size);
+        draw_box (keyboard_cursor_x * piece_size, keyboard_cursor_y * piece_size, piece_size, piece_size);
+    }
+
+    public override bool key_press_event (Gdk.EventKey event)
+    {
+        uint key = event.keyval;
+        switch (key)
+        {
+            case (Gdk.Key.Left):
+                /* fall-thru */
+            case (Gdk.Key.KP_Left):
+                move_keyboard_cursor (-1, 0);
+                break;
+            case (Gdk.Key.Right):
+                /* fall-thru */
+            case (Gdk.Key.KP_Right):
+                move_keyboard_cursor (1, 0);
+                break;
+            case (Gdk.Key.Up):
+                /* fall-thru */
+            case (Gdk.Key.KP_Up):
+                move_keyboard_cursor (0, -1);
+                break;
+            case (Gdk.Key.Down):
+                /* fall-thru */
+            case (Gdk.Key.KP_Down):
+                move_keyboard_cursor (0, 1);
+                break;
+            case (Gdk.Key.Home):
+                /* fall-thru */
+            case (Gdk.Key.KP_Home):
+                move_keyboard_cursor (-999, 0);
+                break;
+            case (Gdk.Key.End):
+                /* fall-thru */
+            case (Gdk.Key.KP_End):
+                move_keyboard_cursor (999, 0);
+                break;
+            case (Gdk.Key.Page_Up):
+                /* fall-thru */
+            case (Gdk.Key.KP_Page_Up):
+                move_keyboard_cursor (0, -999);
+                break;
+            case (Gdk.Key.Page_Down):
+                /* fall-thru */
+            case (Gdk.Key.KP_Page_Down):
+                move_keyboard_cursor (0, 999);
+                break;
+            case (Gdk.Key.space):
+                /* fall-thru */
+            case (Gdk.Key.KP_Space):
+                /* fall-thru */
+            case (Gdk.Key.Return):
+                /* fall-thru */
+            case (Gdk.Key.KP_Enter):
+                if (show_cursor)
+                    cell_clicked (keyboard_cursor_x, keyboard_cursor_y);
+                break;
+        }
+
+        return true;
+    }
 
+    private bool cell_clicked (int cell_x, int cell_y)
+    {
         if (cell_x >= game.n_cols || cell_y >= game.n_rows)
             return false;
 
@@ -168,6 +266,27 @@ public class View : Gtk.DrawingArea
         return true;
     }
 
+    public override bool button_press_event (Gdk.EventButton event)
+    {
+        if (game == null || game.animating)
+            return false;
+
+        /* Ignore the 2BUTTON and 3BUTTON events. */
+        if (event.type != Gdk.EventType.BUTTON_PRESS)
+            return false;
+
+        if (show_cursor)
+        {
+            show_cursor = false;
+            draw_box (keyboard_cursor_x * piece_size, keyboard_cursor_y * piece_size, piece_size, 
piece_size);
+        }
+
+        cell_x = (int)event.x / piece_size;
+        cell_y = (int)event.y / piece_size;
+
+        return cell_clicked (cell_x, cell_y);
+    }
+
     private bool animate_clicked ()
     {
         animation_state = (animation_state + 1) % Game.N_ANIMATIONS;
@@ -223,6 +342,24 @@ public class View : Gtk.DrawingArea
         cr.stroke ();
     }
 
+    private void draw_cursor_box (Cairo.Context cr)
+    {
+        if (show_cursor)
+        {
+            Gdk.RGBA grid_color = cs.get_color (Gtk.StateFlags.NORMAL);
+            Gdk.cairo_set_source_rgba (cr, grid_color);
+            cr.set_line_width (2.0);
+
+            var cursor_rectangle = Gdk.Rectangle ();
+            cursor_rectangle.x = keyboard_cursor_x * piece_size + 1;
+            cursor_rectangle.y = keyboard_cursor_y * piece_size + 1;
+            cursor_rectangle.width = piece_size - 1;
+            cursor_rectangle.height = piece_size - 1;
+            Gdk.cairo_rectangle (cr, cursor_rectangle);
+            cr.stroke ();
+        }
+    }
+
     private void draw_shapes (Cairo.Context cr)
     {
         for (int row = 0; row < game.n_rows; row++)
@@ -264,6 +401,7 @@ public class View : Gtk.DrawingArea
         fill_background (cr);
         draw_gridlines (cr);
         draw_shapes (cr);
+        draw_cursor_box (cr);
         draw_path (cr);
 
         return true;


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