[iagno] Highlight on hover.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [iagno] Highlight on hover.
- Date: Mon, 15 Jul 2019 21:43:21 +0000 (UTC)
commit cf7a250e9e58a32d98cfe95abedfd40e6dfb4b3d
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Sat Feb 23 18:43:24 2019 +0100
Highlight on hover.
Inspired by a patch by
Iulian Radu, issue #5.
src/game-view.vala | 207 ++++++++++++++++++++++++++++++++++++++++++++++-------
src/game.vala | 13 ++++
src/iagno.vala | 6 +-
3 files changed, 197 insertions(+), 29 deletions(-)
---
diff --git a/src/game-view.vala b/src/game-view.vala
index b3a16f3..3c4be11 100644
--- a/src/game-view.vala
+++ b/src/game-view.vala
@@ -76,9 +76,19 @@ private class GameView : Gtk.DrawingArea
private bool highlight_set = false;
private uint8 highlight_x = uint8.MAX;
private uint8 highlight_y = uint8.MAX;
+ private uint8 old_highlight_x = uint8.MAX;
+ private uint8 old_highlight_y = uint8.MAX;
private uint8 highlight_state = 0;
private const uint8 HIGHLIGHT_MAX = 5;
+ /* Mouse */
+ private bool show_mouse_highlight = false;
+ private bool mouse_position_set = false;
+ private uint8 mouse_highlight_x = uint8.MAX;
+ private uint8 mouse_highlight_y = uint8.MAX;
+ private uint8 mouse_position_x = uint8.MAX;
+ private uint8 mouse_position_y = uint8.MAX;
+
/* Delay in milliseconds between tile flip frames */
private const int PIXMAP_FLIP_DELAY = 20;
@@ -146,10 +156,17 @@ private class GameView : Gtk.DrawingArea
{
set_events (Gdk.EventMask.EXPOSURE_MASK
| Gdk.EventMask.BUTTON_PRESS_MASK
- | Gdk.EventMask.BUTTON_RELEASE_MASK);
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
set_size_request (350, 350);
}
+ private Iagno iagno_instance;
+ internal GameView (Iagno iagno_instance)
+ {
+ this.iagno_instance = iagno_instance;
+ }
+
/*\
* * theme
\*/
@@ -379,19 +396,48 @@ private class GameView : Gtk.DrawingArea
{
if (game.is_complete) // TODO highlight last played tile on game.is_complete, even if it's the
opponent one...
return;
- if (highlight_x != x || highlight_y != y)
- return;
- if (!show_highlight && highlight_state == 0)
+
+ bool display_mouse_highlight = !show_highlight // no mouse highlight if keyboard one
+ && (show_mouse_highlight || highlight_state != 0)
+ && (mouse_highlight_x == x)
+ && (mouse_highlight_y == y)
+ // disable the hover if the computer is thinking; that should not happen
with current AI
+ && (iagno_instance.player_one == game.current_color ||
iagno_instance.computer == null);
+
+ bool display_keybd_highlight = show_highlight
+ && !show_mouse_highlight
+ && (highlight_x == x)
+ && (highlight_y == y);
+
+ // disappearing keyboard highlight after Escape pressed, if mouse hovered tile is not playable (else
it is selected)
+ bool display_ghost_highlight = !show_highlight
+ && !show_mouse_highlight
+ && highlight_state != 0
+ && (old_highlight_x == x)
+ && (old_highlight_y == y);
+
+ if (!display_mouse_highlight && !display_keybd_highlight && !display_ghost_highlight)
return;
+ bool highlight_on = show_highlight || (show_mouse_highlight && (game.get_owner (x, y) ==
Player.NONE));
+
/* manage animated highlight */
- if (show_highlight && highlight_state != HIGHLIGHT_MAX)
+ if (highlight_on && highlight_state != HIGHLIGHT_MAX)
{
- highlight_state ++;
+ highlight_state++;
queue_draw_area (board_x + tile_x, board_y + tile_y, tile_size, tile_size);
}
- else if (!show_highlight && highlight_state != 0)
- highlight_state = 0; // TODO highlight_state--; on mouse click, conflict updating coords &
showing the anim on previous place
+ else if (!highlight_on && highlight_state != 0)
+ {
+ // either we hit Escape with a keyboard highlight and the mouse does not hover a playable tile,
+ // or we moved mouse from a playable tile to a non playable one; in both cases, we decrease the
+ // highlight state and redraw for the mouse highlight to re-animate when re-entering a playable
+ // tile, or for the keyboard highlight to animate when disappearing; the first displays nothing
+ highlight_state--;
+ queue_draw_area (board_x + tile_x, board_y + tile_y, tile_size, tile_size);
+ if (old_highlight_x != x || old_highlight_y != y) // is not a keyboard highlight disappearing
+ return;
+ }
/* draw animated highlight */
cr.set_source_rgba (highlight_red, highlight_green, highlight_blue, highlight_alpha);
@@ -476,23 +522,45 @@ private class GameView : Gtk.DrawingArea
get_missing_tile (out x, out y);
// clear the previous highlight (if any)
- if (show_highlight)
+ if (show_highlight || show_mouse_highlight || (highlight_state != 0))
{
highlight_state = 0;
- set_square (highlight_x,
- highlight_y,
- get_pixmap (game.get_owner (x, y)),
- /* is final animation */ false,
- /* force redraw */ true);
- // no highlight animation after undo
+ if (show_highlight)
+ set_square (highlight_x,
+ highlight_y,
+ get_pixmap (game.get_owner (highlight_x, highlight_y)),
+ /* is final animation */ false,
+ /* force redraw */ true);
+ if (show_mouse_highlight)
+ set_square (mouse_highlight_x,
+ mouse_highlight_y,
+ get_pixmap (game.get_owner (mouse_highlight_x, mouse_highlight_y)),
+ /* is final animation */ false,
+ /* force redraw */ true);
+
if (!game.is_complete)
- highlight_state = HIGHLIGHT_MAX;
+ {
+ if (show_highlight
+ && x == highlight_x
+ && y == highlight_y)
+ highlight_state = HIGHLIGHT_MAX;
+ else if (show_mouse_highlight
+ && x == mouse_highlight_x
+ && y == mouse_highlight_y)
+ highlight_state = HIGHLIGHT_MAX;
+ else
+ highlight_state = 1;
+ }
}
// set highlight on undone play position
highlight_set = true;
highlight_x = x;
highlight_y = y;
+ mouse_highlight_x = x;
+ mouse_highlight_y = y;
+ if (!show_highlight)
+ show_mouse_highlight = true;
}
private void get_missing_tile (out uint8 x, out uint8 y)
{
@@ -577,6 +645,8 @@ private class GameView : Gtk.DrawingArea
else
{
animate_timeout = 0;
+ if (!show_highlight)
+ _motion_notify_event (mouse_position_x, mouse_position_y, /* force redraw */
true);
return Source.REMOVE;
}
});
@@ -701,12 +771,70 @@ private class GameView : Gtk.DrawingArea
highlight_x = (uint8) x;
highlight_y = (uint8) y;
move (highlight_x, highlight_y);
+ if (game.test_placing_tile (highlight_x, highlight_y))
+ queue_draw_tile (highlight_x, highlight_y);
}
}
return true;
}
+ internal override bool motion_notify_event (Gdk.EventMotion event)
+ {
+ uint8 x = (uint8) ((event.x - board_x) / paving_size);
+ uint8 y = (uint8) ((event.y - board_y) / paving_size);
+ if ((x >= 0 && x < game_size)
+ && (y >= 0 && y < game_size)
+ && ((x != mouse_position_x)
+ || (y != mouse_position_y)))
+ {
+ mouse_position_x = x;
+ mouse_position_y = y;
+ mouse_position_set = true;
+ if (show_highlight
+ || (x != mouse_highlight_x)
+ || (y != mouse_highlight_y))
+ Timeout.add (200, () => { _motion_notify_event (x, y); return Source.REMOVE; });
+ }
+
+ return base.motion_notify_event (event);
+ }
+ private void _motion_notify_event (uint8 x, uint8 y, bool force_redraw = false)
+ {
+ if (!force_redraw
+ && ((x != mouse_position_x)
+ || (y != mouse_position_y)))
+ return;
+
+ bool old_show_mouse_highlight = show_mouse_highlight;
+ show_mouse_highlight = game.test_placing_tile (x, y);
+
+ if (old_show_mouse_highlight && !show_mouse_highlight)
+ {
+ old_highlight_x = uint8.MAX;
+ old_highlight_y = uint8.MAX;
+ }
+
+ uint8 old_mouse_highlight_x = mouse_highlight_x;
+ uint8 old_mouse_highlight_y = mouse_highlight_y;
+
+ mouse_highlight_x = x;
+ mouse_highlight_y = y;
+
+ if (old_mouse_highlight_x != uint8.MAX && old_mouse_highlight_y != uint8.MAX)
+ queue_draw_tile (old_mouse_highlight_x, old_mouse_highlight_y);
+ if (show_mouse_highlight && show_highlight)
+ {
+ show_highlight = false;
+ if (highlight_x != x || highlight_y != y)
+ queue_draw_tile (highlight_x, highlight_y);
+ }
+ if (show_mouse_highlight || force_redraw)
+ {
+ queue_draw_tile (mouse_highlight_x, mouse_highlight_y);
+ }
+ }
+
internal override bool key_press_event (Gdk.EventKey event)
{
if (!game_is_set)
@@ -728,42 +856,57 @@ private class GameView : Gtk.DrawingArea
(game_size <= 9 && (key == "j" || key == "J" || key == "0" || key == "KP_0")))
return false;
- uint8 old_highlight_x = highlight_x;
- uint8 old_highlight_y = highlight_y;
+ old_highlight_x = highlight_x;
+ old_highlight_y = highlight_y;
switch (key)
{
case "Left":
case "KP_Left":
- if (!highlight_set && game.current_color == Player.LIGHT) highlight_y = game_size / 2;
- if (highlight_x > 0) highlight_x --;
+ if (mouse_position_set && show_mouse_highlight) { highlight_x = mouse_highlight_x;
highlight_y = mouse_highlight_y; }
+ else if (!highlight_set && game.current_color == Player.LIGHT) highlight_y = game_size / 2;
+ if (highlight_x > 0) highlight_x--;
break;
case "Right":
case "KP_Right":
- if (!highlight_set)
+ if (mouse_position_set && show_mouse_highlight) { highlight_x = mouse_highlight_x;
highlight_y = mouse_highlight_y; }
+ else if (!highlight_set)
{
highlight_x = game_size / 2;
if (game.current_color == Player.DARK) highlight_y = highlight_x;
}
- if (highlight_x < game_size - 1) highlight_x ++;
+ if (highlight_x < game_size - 1) highlight_x++;
break;
case "Up":
case "KP_Up":
- if (!highlight_set && game.current_color == Player.LIGHT) highlight_x = game_size / 2;
- if (highlight_y > 0) highlight_y --;
+ if (mouse_position_set && show_mouse_highlight) { highlight_x = mouse_highlight_x;
highlight_y = mouse_highlight_y; }
+ else if (!highlight_set && game.current_color == Player.LIGHT) highlight_x = game_size / 2;
+ if (highlight_y > 0) highlight_y--;
break;
case "Down":
case "KP_Down":
- if (!highlight_set)
+ if (mouse_position_set && show_mouse_highlight) { highlight_x = mouse_highlight_x;
highlight_y = mouse_highlight_y; }
+ else if (!highlight_set)
{
highlight_y = game_size / 2;
if (game.current_color == Player.DARK) highlight_x = highlight_y;
}
- if (highlight_y < game_size - 1) highlight_y ++;
+ if (highlight_y < game_size - 1) highlight_y++;
break;
case "space":
case "Return":
case "KP_Enter":
+ if (show_mouse_highlight)
+ {
+ move (mouse_highlight_x, mouse_highlight_y);
+ return true;
+ }
+ else if (mouse_position_set)
+ {
+ highlight_x = mouse_position_x;
+ highlight_y = mouse_position_y;
+ }
+ break;
case "Escape": break;
@@ -824,6 +967,18 @@ private class GameView : Gtk.DrawingArea
if ((old_highlight_x != highlight_x)
|| (old_highlight_y != highlight_y))
queue_draw_tile (highlight_x, highlight_y);
+ if (key != "Escape")
+ {
+ show_mouse_highlight = false;
+ if (mouse_position_set)
+ queue_draw_tile (mouse_highlight_x, mouse_highlight_y);
+ }
+ else if (mouse_position_set)
+ {
+ highlight_x = mouse_position_x;
+ highlight_y = mouse_position_y;
+ _motion_notify_event (highlight_x, highlight_y, /* force redraw */ true);
+ }
return true;
}
diff --git a/src/game.vala b/src/game.vala
index 7eb2f86..a89f57e 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -742,6 +742,19 @@ private class Game : Object
private SList<PossibleMove?> possible_moves;
+ internal bool test_placing_tile (uint8 x, uint8 y)
+ {
+ unowned SList<PossibleMove?>? test_move = possible_moves.nth (0);
+ while (test_move != null)
+ {
+ PossibleMove move = (!) ((!) test_move).data;
+ if (move.x == x && move.y == y)
+ return true;
+ test_move = ((!) test_move).next;
+ }
+ return false;
+ }
+
internal void get_possible_moves (out SList<PossibleMove?> moves)
{
moves = possible_moves.copy_deep ((a) => {
diff --git a/src/iagno.vala b/src/iagno.vala
index 06e1de4..cefc83b 100644
--- a/src/iagno.vala
+++ b/src/iagno.vala
@@ -52,10 +52,10 @@ private class Iagno : Gtk.Application
private ThemesDialog themes_dialog;
/* Computer player (if there is one) */
- private ComputerPlayer? computer = null;
+ internal ComputerPlayer? computer { internal get; private set; default = null; }
/* Human player */
- private Player player_one;
+ internal Player player_one { internal get; private set; }
/* The game being played */
private Game game;
@@ -212,7 +212,7 @@ private class Iagno : Gtk.Application
/* UI parts */
Builder builder = new Builder.from_resource ("/org/gnome/Reversi/ui/iagno-screens.ui");
- view = new GameView ();
+ view = new GameView (this);
view.move.connect (player_move_cb);
DrawingArea scoredrawing = (DrawingArea) builder.get_object ("scoredrawing");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]