[iagno] Improve HistoryButton.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [iagno] Improve HistoryButton.
- Date: Sun, 26 Jan 2020 01:31:34 +0000 (UTC)
commit 771db5e3a21d62cf894ebda810b69ce370139928
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Sun Jan 26 02:18:47 2020 +0100
Improve HistoryButton.
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1772813
and partially syncs code with the one from Four-in-a-row.
data/ui/history-button.ui | 28 ++++++--
src/history-button.vala | 171 +++++++++++++++++++++++++++++++++-------------
src/iagno.vala | 41 ++++++++---
3 files changed, 176 insertions(+), 64 deletions(-)
---
diff --git a/data/ui/history-button.ui b/data/ui/history-button.ui
index a6c56c4..28ff6a7 100644
--- a/data/ui/history-button.ui
+++ b/data/ui/history-button.ui
@@ -4,7 +4,7 @@
Copyright 2012 Tiffany Antopolski and Robert Ancell
Copyright 2013, 2014, 2015 Michael Catanzaro
- Copyright 2014, 2015, 2019 Arnaud Bonatti
+ Copyright 2014, 2015, 2019, 2020 Arnaud Bonatti
GNOME Reversi is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,8 +25,28 @@
<property name="valign">center</property>
<property name="can-focus">True</property>
<property name="focus-on-click">False</property>
- <style>
- <class name="history-button"/>
- </style>
+ <property name="width-request">56</property>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="visible-child">drawing</property>
+ <child>
+ <object class="GtkDrawingArea" id="drawing">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="ellipsize">end</property>
+ <!-- Translators: label of the game status button (in the headerbar, next to the hamburger
button), when the game is finished; please keep the string as small as possible (3~5 characters) -->
+ <property name="label" translatable="yes">End!</property>
+ </object>
+ <packing>
+ <property name="name">label</property>
+ </packing>
+ </child>
+ </object>
+ </child>
</template>
</interface>
diff --git a/src/history-button.vala b/src/history-button.vala
index b79c192..4cd3673 100644
--- a/src/history-button.vala
+++ b/src/history-button.vala
@@ -23,79 +23,152 @@ using Gtk;
[GtkTemplate (ui = "/org/gnome/Reversi/ui/history-button.ui")]
private class HistoryButton : MenuButton, AdaptativeWidget
{
- private GLib.Menu history_menu;
- private GLib.Menu finish_menu;
+ [CCode (notify = false)] public ThemeManager theme_manager { private get; protected construct; }
- private string history_button_light_label;
- private string history_button_dark_label;
+ [GtkChild] private Stack stack;
+ [GtkChild] private DrawingArea drawing;
- construct
+ internal HistoryButton (GLib.Menu menu, ThemeManager theme_manager)
{
- history_menu = new GLib.Menu ();
- /* Translators: history menu entry (with a mnemonic that appears pressing Alt) */
- history_menu.append (_("_Undo last move"), "ui.undo");
- history_menu.freeze ();
+ Object (menu_model: menu, theme_manager: theme_manager);
+ }
- finish_menu = new GLib.Menu ();
- /* Translators: history menu entry, when game is finished, after final animation; undoes the
animation (with a mnemonic that appears pressing Alt) */
- finish_menu.append (_("_Show final board"), "ui.undo");
- finish_menu.freeze ();
+ construct
+ {
+ drawing.configure_event.connect (configure_drawing);
+ drawing.draw.connect (update_drawing);
+ theme_manager.theme_changed.connect (() => {
+ if (!drawing_configured)
+ return;
+ tiles_pattern = null;
+ if (current_player != Player.NONE)
+ drawing.queue_draw ();
+ });
+ }
- bool dir_is_ltr = get_locale_direction () == TextDirection.LTR;
- history_button_light_label = dir_is_ltr ? "⮚ ⚪" : /* yes */ "⮘ ⚪"; /* both have an LTR/RTL mark
*/
- history_button_dark_label = dir_is_ltr ? "⮚ ⚫" : /* yes */ "⮘ ⚫"; /* both have an LTR/RTL mark
*/
+ protected override void set_window_size (AdaptativeWidget.WindowSize new_size)
+ {
+ }
- new_game ();
+ internal void set_player (Player player)
+ {
+ current_player = player;
+ if (player == Player.NONE)
+ stack.set_visible_child_name ("label");
+ else
+ {
+ stack.set_visible_child (drawing);
+ drawing.queue_draw ();
+ }
}
- private bool is_extra_thin = true;
- protected override void set_window_size (AdaptativeWidget.WindowSize new_size)
+ internal inline void update_menu (GLib.Menu menu)
{
- bool _is_extra_thin = AdaptativeWidget.WindowSize.is_extra_thin (new_size);
- if (_is_extra_thin == is_extra_thin)
- return;
- is_extra_thin = _is_extra_thin;
- update_label (last_player);
+ set_menu_model (menu);
}
/*\
- * * internal calls
+ * * drawing
\*/
- internal inline void update_menu (bool finish_animation)
+ private bool drawing_configured = false;
+ private int drawing_height = int.MIN;
+ private int drawing_width = int.MIN;
+ private double arrow_half_width = - double.MAX;
+ private int board_x = int.MIN;
+ private int board_y = int.MIN;
+ private const int pixbuf_margin = 1;
+
+ private Gdk.Pixbuf tileset_pixbuf;
+
+ private bool configure_drawing ()
{
- set_menu_model (finish_animation ? finish_menu : history_menu);
+ int height = drawing.get_allocated_height ();
+ int width = drawing.get_allocated_width ();
+ int new_height = (int) double.min (height, width / 2.0);
+
+ drawing_height = new_height;
+ arrow_half_width = ((double) drawing_height - 2.0 * pixbuf_margin) / 4.0;
+ tiles_pattern = null;
+
+ bool vertical_fill = height == new_height;
+ drawing_width = vertical_fill ? (int) (new_height * 2.0) : width;
+ board_x = vertical_fill ? (int) ((width - drawing_width) / 2.0) : 0;
+ board_y = !vertical_fill ? (int) ((height - drawing_height) / 2.0) : 0;
+
+ drawing_configured = true;
+ return true;
+ }
+
+ private Cairo.Pattern? tiles_pattern = null;
+ private void init_pattern (Cairo.Context cr) // TODO unduplicate with ReversiView
+ {
+ Cairo.Surface surface = new Cairo.Surface.similar (cr.get_target (), Cairo.Content.COLOR_ALPHA,
drawing_height * 8,
+
drawing_height * 4);
+ Cairo.Context context = new Cairo.Context (surface);
+ Rsvg.DimensionData size = theme_manager.tileset_handle.get_dimensions ();
+ context.scale ((double) drawing_height * 8.0 / (double) size.width,
+ (double) drawing_height * 4.0 / (double) size.height);
+ theme_manager.tileset_handle.render_cairo (context);
+ tiles_pattern = new Cairo.Pattern.for_surface (surface);
+ }
+
+ private bool update_drawing (Cairo.Context cr)
+ {
+ if (!drawing_configured)
+ return false;
+
+ if (tiles_pattern == null)
+ init_pattern (cr);
+
+ draw_arrow (cr);
+ draw_piece (cr);
+ return true;
}
- internal inline void new_game ()
+ private const double arrow_margin_top = 3.0;
+ private void draw_arrow (Cairo.Context cr)
{
- update_label (Player.DARK);
- update_menu (/* final animation */ false);
+ cr.save ();
+
+ cr.set_line_cap (Cairo.LineCap.ROUND);
+ cr.set_line_join (Cairo.LineJoin.ROUND);
+
+ cr.set_source_rgba (/* red */ 0.5, /* green */ 0.5, /* blue */ 0.5, 1.0);
+ cr.set_line_width (/* looks good */ 2.0);
+
+ cr.translate (board_x, board_y);
+ cr.move_to ( arrow_half_width, arrow_margin_top);
+ cr.line_to (3.0 * arrow_half_width, drawing_height / 2.0);
+ cr.line_to ( arrow_half_width, drawing_height - arrow_margin_top);
+ cr.stroke ();
+
+ cr.restore ();
}
- private Player last_player = Player.NONE;
- internal void update_label (Player player)
+ private Player current_player = Player.NONE;
+ private void draw_piece (Cairo.Context cr)
{
- last_player = player;
- switch (player)
+ int pixmap;
+ switch (current_player)
{
- case Player.LIGHT:
- set_label (history_button_light_label); break;
- case Player.DARK:
- set_label (history_button_dark_label); break;
- case Player.NONE:
- if (is_extra_thin)
- /* Translators: label of the game status button (in the headerbar, next to the hamburger
button), at the end of the game; this string is for when the window is really small, so keep the string as
small as possible (3~5 characters) */
- set_label (_("End!"));
-
- else
- /* Translators: label of the game status button (in the headerbar, next to the hamburger
button), at the end of the game, if the window is not too thin */
- set_label (_("Finished!")); break;
+ case Player.NONE : return;
+ case Player.DARK : pixmap = 1; break;
+ case Player.LIGHT : pixmap = 31; break;
default: assert_not_reached ();
}
- Widget? history_label = get_child ();
- if (history_label != null && (!) history_label is Label)
- ((Label) (!) history_label).set_ellipsize (Pango.EllipsizeMode.END);
+ cr.save ();
+ Cairo.Matrix matrix = Cairo.Matrix.identity ();
+ int x = board_x + drawing_width - drawing_height;
+ matrix.translate (/* texture x */ (pixmap % 8) * drawing_height - /* x position */ x,
+ /* texture y */ (pixmap / 8) * drawing_height - /* y position */ board_y);
+ ((!) tiles_pattern).set_matrix (matrix);
+ cr.set_source ((!) tiles_pattern);
+ cr.rectangle (x, board_y, drawing_height, drawing_height);
+
+ cr.clip ();
+ cr.paint ();
+ cr.restore ();
}
}
diff --git a/src/iagno.vala b/src/iagno.vala
index d1fa006..5145ee5 100644
--- a/src/iagno.vala
+++ b/src/iagno.vala
@@ -54,6 +54,9 @@ private class Iagno : Gtk.Application, BaseApplication
private HistoryButton history_button_1;
private HistoryButton history_button_2;
+ private GLib.Menu history_menu;
+ private GLib.Menu finish_menu;
+
private ThemeManager theme_manager = new ThemeManager ();
/* Computer player (if there is one) */
@@ -397,14 +400,28 @@ private class Iagno : Gtk.Application, BaseApplication
appearance_menu.append_section (_("Highlights"), section);
appearance_menu.freeze ();
- history_button_1 = new HistoryButton ();
- history_button_2 = new HistoryButton ();
- view.notify_final_animation.connect ((undoing) => { history_button_1.update_menu (!undoing);
- history_button_2.update_menu (!undoing); });
+ /* history buttons */
+
+ history_menu = new GLib.Menu ();
+ /* Translators: history menu entry (with a mnemonic that appears pressing Alt) */
+ history_menu.append (_("_Undo last move"), "ui.undo");
+ history_menu.freeze ();
+
+ finish_menu = new GLib.Menu ();
+ /* Translators: history menu entry, when game is finished, after final animation; undoes the
animation (with a mnemonic that appears pressing Alt) */
+ finish_menu.append (_("_Show final board"), "ui.undo");
+ finish_menu.freeze ();
+
+ history_button_1 = new HistoryButton (history_menu, theme_manager);
+ history_button_2 = new HistoryButton (history_menu, theme_manager);
+ view.notify_final_animation.connect ((undoing) => {
+ history_button_1.update_menu (undoing ? history_menu : finish_menu);
+ history_button_2.update_menu (undoing ? history_menu : finish_menu);
+ });
history_button_1.show ();
history_button_2.show ();
- /* Window */
+ /* window */
init_night_mode ();
window = new GameWindow ("/org/gnome/Reversi/ui/iagno.css",
PROGRAM_NAME,
@@ -697,8 +714,10 @@ private class Iagno : Gtk.Application, BaseApplication
game.turn_ended.connect (turn_ended_cb);
view.game = game;
- history_button_1.new_game ();
- history_button_2.new_game ();
+ history_button_1.set_player (Player.DARK);
+ history_button_2.set_player (Player.DARK);
+ history_button_1.update_menu (history_menu);
+ history_button_2.update_menu (history_menu);
if (two_players)
computer = null;
@@ -842,8 +861,8 @@ private class Iagno : Gtk.Application, BaseApplication
requires (game_is_set)
{
window.finish_game ();
- history_button_1.update_label (Player.NONE);
- history_button_2.update_label (Player.NONE);
+ history_button_1.set_player (Player.NONE);
+ history_button_2.set_player (Player.NONE);
if ((!game.reverse && game.n_light_tiles > game.n_dark_tiles)
|| ( game.reverse && game.n_light_tiles < game.n_dark_tiles))
@@ -900,8 +919,8 @@ private class Iagno : Gtk.Application, BaseApplication
{
/* for the move that just ended */
play_sound (Sound.FLIP);
- history_button_1.update_label (game.current_color);
- history_button_2.update_label (game.current_color);
+ history_button_1.set_player (game.current_color);
+ history_button_2.set_player (game.current_color);
}
private void set_window_title ()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]