[gnome-taquin] Prepare for libgames-support.



commit 2a7e48b797e3e7ece0b299ba9ad46b3463e15bf3
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Sun Mar 1 05:40:32 2015 +0100

    Prepare for libgames-support.

 data/Makefile.am                 |    1 +
 data/org.gnome.taquin.desktop.in |    1 -
 data/taquin-menus.ui             |    2 +
 data/taquin-screens.ui           |  123 ++++++++++++++
 data/taquin.css                  |    2 +-
 data/taquin.ui                   |  159 ++----------------
 gnome-taquin.doap                |    2 +
 help/C/shortcuts.page            |   13 ++
 po/POTFILES.in                   |    2 +
 src/Makefile.am                  |    2 +
 src/game-window.vala             |  338 ++++++++++++++++++++++++++++++++++++++
 src/taquin-game.vala             |   13 ++
 src/taquin-main.vala             |  225 ++++++++------------------
 src/taquin.gresource.xml         |    3 +-
 14 files changed, 580 insertions(+), 306 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 39152f7..8137df1 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -4,6 +4,7 @@ SUBDIRS = \
 
 dist_noinst_DATA = \
        taquin-menus.ui \
+       taquin-screens.ui \
        taquin.ui \
        taquin.css \
        schema-15.png \
diff --git a/data/org.gnome.taquin.desktop.in b/data/org.gnome.taquin.desktop.in
index 1b9db74..19cafa7 100644
--- a/data/org.gnome.taquin.desktop.in
+++ b/data/org.gnome.taquin.desktop.in
@@ -8,7 +8,6 @@ Terminal=false
 Type=Application
 Categories=GNOME;GTK;Game;LogicGame;
 StartupNotify=true
-DBusActivatable=true
 Actions=Fifteen;Sixteen;
 
 [Desktop Action Fifteen]
diff --git a/data/taquin-menus.ui b/data/taquin-menus.ui
index 2bba404..68f3bbe 100644
--- a/data/taquin-menus.ui
+++ b/data/taquin-menus.ui
@@ -12,6 +12,7 @@
       <item>
         <attribute name="label" translatable="yes">_Help</attribute>
         <attribute name="action">app.help</attribute>
+        <attribute name="accel">F1</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">_About</attribute>
@@ -20,6 +21,7 @@
       <item>
         <attribute name="label" translatable="yes">_Quit</attribute>
         <attribute name="action">app.quit</attribute>
+        <attribute name="accel">&lt;Primary&gt;q</attribute>
       </item>
     </section>
   </menu>
diff --git a/data/taquin-screens.ui b/data/taquin-screens.ui
new file mode 100644
index 0000000..b194c29
--- /dev/null
+++ b/data/taquin-screens.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <menu id="size-menu"><!-- TODO 3/4/5 accels? -->
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">3 × 3</attribute>
+        <attribute name="action">app.change-size</attribute>
+        <attribute name="target">3</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">4 × 4</attribute>
+        <attribute name="action">app.change-size</attribute>
+        <attribute name="target">4</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">5 × 5</attribute>
+        <attribute name="action">app.change-size</attribute>
+        <attribute name="target">5</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="theme-menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Cats</attribute>
+        <attribute name="action">app.change-theme</attribute>
+        <attribute name="target">cats</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Numbers</attribute>
+        <attribute name="action">app.change-theme</attribute>
+        <attribute name="target">numbers</attribute>
+      </item>
+    </section>
+  </menu>
+  <object class="GtkBox" id="new-game-screen">
+    <property name="orientation">vertical</property>
+    <property name="visible">True</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">horizontal</property>
+        <property name="visible">True</property>
+        <property name="homogeneous">True</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkRadioButton" id="radio-fifteen">
+            <property name="visible">True</property>
+            <property name="name">radio-fifteen</property>
+            <style><class name="radio-like-toggle"/></style>
+            <property name="focus-on-click">False</property>
+            <property name="relief">none</property> <!-- could probably be replaced by a use of the "flat" 
style-class -->
+            <property name="action-name">app.change-type</property>
+            <property name="action-target">'fifteen'</property>
+            <property name="draw-indicator">False</property>
+            <property name="label" translatable="yes">15-Puzzle</property>
+            <property name="width-request">197</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkRadioButton" id="radio-sixteen">
+            <property name="visible">True</property>
+            <property name="name">radio-sixteen</property>
+            <style><class name="radio-like-toggle"/></style>
+            <property name="focus-on-click">False</property>
+            <property name="relief">none</property>
+            <property name="action-name">app.change-type</property>
+            <property name="action-target">'sixteen'</property>
+            <property name="group">radio-fifteen</property>
+            <property name="draw-indicator">False</property>
+            <property name="label" translatable="yes">16-Puzzle</property>
+            <property name="width-request">197</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">horizontal</property>
+        <property name="visible">True</property>
+        <property name="homogeneous">True</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkMenuButton" id="size-button">
+            <property name="visible">True</property>
+            <property name="use-underline">True</property>
+            <property name="menu-model">size-menu</property>
+            <property name="height-request">60</property>
+            <style><class name="menubutton-like-combo"/></style>
+            <property name="relief">none</property> <!-- could probably be replaced by a use of the "flat" 
style-class -->
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkMenuButton" id="theme-button">
+            <property name="visible">True</property>
+            <property name="use-underline">True</property>
+            <property name="menu-model">theme-menu</property>
+            <property name="height-request">60</property>
+            <style><class name="menubutton-like-combo"/></style>
+            <property name="relief">none</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/data/taquin.css b/data/taquin.css
index 714e053..d3f5232 100644
--- a/data/taquin.css
+++ b/data/taquin.css
@@ -7,7 +7,7 @@ GtkRadioButton.radio-like-toggle#radio-sixteen {
 
 GtkRadioButton.radio-like-toggle {
     background-repeat: no-repeat;
-    /* width is requested by the widget: 200 */
+    /* width is requested by the widget: 197 */
     padding-top: 15px;
     padding-bottom: 185px;
     background-position: center 25px;
diff --git a/data/taquin.ui b/data/taquin.ui
index 77dcff7..3e5d383 100644
--- a/data/taquin.ui
+++ b/data/taquin.ui
@@ -1,68 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="3.12"/>
-  <menu id="size-menu">
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">3 × 3</attribute>
-        <attribute name="action">win.change-size</attribute>
-        <attribute name="target">3</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">4 × 4</attribute>
-        <attribute name="action">win.change-size</attribute>
-        <attribute name="target">4</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">5 × 5</attribute>
-        <attribute name="action">win.change-size</attribute>
-        <attribute name="target">5</attribute>
-      </item>
-    </section>
-  </menu>
-  <menu id="theme-menu">
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">Cats</attribute>
-        <attribute name="action">win.change-theme</attribute>
-        <attribute name="target">cats</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Numbers</attribute>
-        <attribute name="action">win.change-theme</attribute>
-        <attribute name="target">numbers</attribute>
-      </item>
-    </section>
-  </menu>
-  <object class="GtkApplicationWindow" id="taquin-window">
+  <template class="GameWindow" parent="GtkApplicationWindow">
     <!-- <initial-focus name="view"/> -->
-    <property name="title" translatable="yes">Taquin</property>
     <child type="titlebar">
       <object class="GtkHeaderBar" id="headerbar">
         <property name="visible">True</property>
         <property name="show-close-button">True</property>
-        <property name="title" translatable="yes">Taquin</property>
         <child>
-          <object class="GtkButton" id="undo-button">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="valign">center</property>
-            <property name="tooltip-text" translatable="yes">Undo your most recent move</property>
-            <property name="can-focus">True</property>
-            <property name="focus-on-click">False</property>
-            <property name="action-name">win.undo</property>
-            <style><class name="image-button"/></style>
-            <child>
-              <object class="GtkImage">
-                <property name="icon-name">edit-undo-symbolic</property>
-                <property name="visible">True</property>
-                <property name="icon-size">1</property>
-              </object>
-            </child>
+          <object class="GtkBox" id="controls_box">
+            <property name="visible">False</property>
+            <property name="orientation">horizontal</property>
           </object>
         </child>
         <child>
-          <object class="GtkButton" id="back-button">
+          <object class="GtkButton" id="back_button">
             <property name="visible">False</property>
             <property name="halign">center</property>
             <property name="valign">center</property>
@@ -82,11 +34,11 @@
       </object>
     </child>
     <child>
-      <object class="GtkStack" id="main-stack">
+      <object class="GtkStack" id="stack">
         <property name="visible">True</property>
         <property name="homogeneous">True</property>
         <child>
-          <object class="GtkBox">
+          <object class="GtkBox" id="new_game_box">
             <property name="orientation">vertical</property>
             <property name="visible">True</property>
             <property name="halign">center</property>
@@ -96,91 +48,11 @@
             <property name="height-request">350</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkBox">
-                <property name="orientation">horizontal</property>
-                <property name="visible">True</property>
-                <property name="homogeneous">True</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkRadioButton" id="radio-fifteen">
-                    <property name="visible">True</property>
-                    <property name="name">radio-fifteen</property>
-                    <style><class name="radio-like-toggle"/></style>
-                    <property name="focus-on-click">False</property>
-                    <property name="relief">none</property> <!-- could probably be replaced by a use of the 
"flat" style-class -->
-                    <property name="action-name">win.change-type</property>
-                    <property name="action-target">'fifteen'</property>
-                    <property name="draw-indicator">False</property>
-                    <property name="label" translatable="yes">15-Puzzle</property>
-                    <property name="width-request">200</property>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkRadioButton" id="radio-sixteen">
-                    <property name="visible">True</property>
-                    <property name="name">radio-sixteen</property>
-                    <style><class name="radio-like-toggle"/></style>
-                    <property name="focus-on-click">False</property>
-                    <property name="relief">none</property>
-                    <property name="action-name">win.change-type</property>
-                    <property name="action-target">'sixteen'</property>
-                    <property name="group">radio-fifteen</property>
-                    <property name="draw-indicator">False</property>
-                    <property name="label" translatable="yes">16-Puzzle</property>
-                    <property name="width-request">200</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox">
-                <property name="orientation">horizontal</property>
-                <property name="visible">True</property>
-                <property name="homogeneous">True</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkMenuButton" id="size-button">
-                    <property name="visible">True</property>
-                    <property name="use-underline">True</property>
-                    <property name="menu-model">size-menu</property>
-                    <property name="height-request">60</property>
-                    <style><class name="menubutton-like-combo"/></style>
-                    <property name="relief">none</property> <!-- could probably be replaced by a use of the 
"flat" style-class -->
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkMenuButton" id="theme-button">
-                    <property name="visible">True</property>
-                    <property name="use-underline">True</property>
-                    <property name="menu-model">theme-menu</property>
-                    <property name="height-request">60</property>
-                    <style><class name="menubutton-like-combo"/></style>
-                    <property name="relief">none</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="start-game-button">
+              <object class="GtkButton" id="start_game_button">
                 <property name="visible">True</property>
                 <property name="use-underline">True</property>
                 <property name="label" translatable="yes">_Start Game</property>
+                <property name="tooltip-text" translatable="yes">Start a new game as configured</property>
                 <property name="action-name">win.start-game</property>
                 <property name="width-request">222</property>
                 <property name="height-request">60</property>
@@ -188,6 +60,7 @@
                 <style><class name="suggested-action"/></style>
               </object>
               <packing>
+                <property name="pack-type">end</property>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
               </packing>
@@ -205,23 +78,21 @@
             <property name="ratio">1.4</property>
             <property name="margin">25</property>
             <child>
-              <object class="GtkBox" id="game-box">
+              <object class="GtkBox" id="game_box">
                 <property name="visible">True</property>
                 <property name="orientation">horizontal</property>
                 <property name="spacing">25</property>
                 <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <object class="GtkBox">
+                  <object class="GtkBox" id="side_box">
                     <property name="visible">True</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
-                      <object class="GtkButton" id="start-over-button">
+                      <object class="GtkButton" id="new_game_button">
                         <property name="visible">True</property>
                         <property name="use-underline">True</property>
                         <property name="label" translatable="yes">_Start Over</property>
+                        <property name="tooltip-text" translatable="yes">Configure a new game</property>
                         <property name="halign">center</property>
                         <property name="valign">center</property>
                         <property name="action-name">win.new-game</property>
@@ -254,5 +125,5 @@
         </child>
       </object>
     </child>
-  </object>
+  </template>
 </interface>
diff --git a/gnome-taquin.doap b/gnome-taquin.doap
index c1c1ff0..397f184 100644
--- a/gnome-taquin.doap
+++ b/gnome-taquin.doap
@@ -1,3 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+
 <Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
          xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#";
          xmlns:foaf="http://xmlns.com/foaf/0.1/";
diff --git a/help/C/shortcuts.page b/help/C/shortcuts.page
index 3f88539..19d825d 100644
--- a/help/C/shortcuts.page
+++ b/help/C/shortcuts.page
@@ -62,6 +62,19 @@
       </tr>
     </table>
   </section>
+  <section id="start-screen">
+    <title>Start Screen shortcuts</title>
+    <table frame="all" rules="cols" shade="rows">
+      <tr>
+        <td><p>New Game</p></td>
+        <td><p><keyseq><key>Ctrl</key><key>Shift</key><key>N</key></keyseq></p></td>
+      </tr>
+      <tr>
+        <td><p>Back to previous game (if any)</p></td>
+        <td><p><key>Escape</key></p></td>
+      </tr>
+    </table>
+  </section>
   <section id="general">
     <title>General shortcuts</title>
     <table frame="all" rules="cols" shade="rows">
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 80dd365..1f2a24b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,10 +2,12 @@
 # Please keep this file in alphabetical order.
 [encoding: UTF-8]
 [type: gettext/glade]data/taquin-menus.ui
+[type: gettext/glade]data/taquin-screens.ui
 [type: gettext/glade]data/taquin.ui
 data/org.gnome.taquin.appdata.xml.in
 data/org.gnome.taquin.desktop.in
 data/org.gnome.taquin.gschema.xml
+src/game-window.vala
 src/taquin-main.vala
 src/taquin-game.vala
 src/taquin-view.vala
diff --git a/src/Makefile.am b/src/Makefile.am
index 7aa35a5..e6192d3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,7 @@ bin_PROGRAMS = gnome-taquin
 BUILT_SOURCES = taquin-resources.c
 
 gnome_taquin_SOURCES = \
+       game-window.vala \
        taquin-main.vala \
        taquin-view.vala \
        taquin-game.vala \
@@ -24,6 +25,7 @@ gnome_taquin_VALAFLAGS = \
        --pkg librsvg-2.0 \
        --pkg libcanberra \
        --pkg libcanberra-gtk \
+       --gresources taquin.gresource.xml \
        --target-glib $(GLIB_REQUIRED)
 
 gnome_taquin_LDADD = $(GNOME_TAQUIN_LIBS)
diff --git a/src/game-window.vala b/src/game-window.vala
new file mode 100644
index 0000000..c75ffce
--- /dev/null
+++ b/src/game-window.vala
@@ -0,0 +1,338 @@
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * Copyright (C) 2015 Arnaud Bonatti <arnaud bonatti gmail com>
+ *
+ * This file is part of a GNOME game.
+ *
+ * This application 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this application. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gtk;
+
+[Flags]
+public enum GameWindowFlags {
+    SHOW_UNDO,
+    SHOW_REDO,
+    SHOW_HINT;
+}
+
+[GtkTemplate (ui = "/org/gnome/taquin/ui/game-window.ui")]
+public class GameWindow : ApplicationWindow
+{
+    /* settings */
+    private bool tiled_state;
+    private bool maximized_state;
+    private int window_width;
+    private int window_height;
+
+    private bool game_finished = false;
+
+    /* private widgets */
+    [GtkChild]
+    private HeaderBar headerbar;
+    [GtkChild]
+    private Stack stack;
+
+    [GtkChild]
+    private Button new_game_button;
+    [GtkChild]
+    private Button start_game_button;
+    [GtkChild]
+    private Button back_button;
+
+    [GtkChild]
+    private Box controls_box;
+    [GtkChild]
+    private Box game_box;
+    [GtkChild]
+    private Box new_game_box;
+    [GtkChild]
+    private Box side_box;
+
+    private Widget view;
+
+    /* signals */
+    public signal void play ();
+    public signal void wait ();
+    public signal void back ();
+
+    public signal void undo ();
+    public signal void redo ();
+    public signal void hint ();
+
+    /* actions */
+    private const GLib.ActionEntry win_actions[] =
+    {
+        { "new-game", new_game_cb },
+        { "start-game", start_game_cb },
+        { "back", back_cb },
+
+        { "undo", undo_cb },
+        { "redo", redo_cb },
+        { "hint", hint_cb }
+    };
+
+    private SimpleAction back_action;
+
+    public SimpleAction undo_action;
+    public SimpleAction redo_action;
+
+    public GameWindow (string name, int width, int height, bool maximized, bool start_now, GameWindowFlags 
flags, Box new_game_screen, Widget _view)
+    {
+        view = _view;
+
+        /* window actions */
+        add_action_entries (win_actions, this);
+
+        back_action = (SimpleAction) lookup_action ("back");
+        undo_action = (SimpleAction) lookup_action ("undo");
+        redo_action = (SimpleAction) lookup_action ("redo");
+
+        back_action.set_enabled (false);
+        undo_action.set_enabled (false);
+        redo_action.set_enabled (false);
+
+        /* window config */
+        set_title (name);
+        headerbar.set_title (name);
+
+        set_default_size (width, height);
+        if (maximized)
+            maximize ();
+
+        size_allocate.connect (size_allocate_cb);
+        window_state_event.connect (window_state_event_cb);
+
+        /* add widgets */
+        new_game_box.pack_start (new_game_screen, true, true, 0);
+
+        game_box.pack_start (view, true, true, 0);
+        game_box.set_focus_child (view);            // TODO test if necessary; note: view could grab focus 
from application
+        view.halign = Align.FILL;
+        view.can_focus = true;
+        view.show ();
+
+        /* add controls */
+        if (GameWindowFlags.SHOW_UNDO in flags)
+        {
+            Box history_box = new Box (Orientation.HORIZONTAL, 0);
+            history_box.get_style_context ().add_class ("linked");
+
+            Button undo_button = new Button.from_icon_name ("edit-undo-symbolic", Gtk.IconSize.BUTTON);
+            undo_button.action_name = "win.undo";
+            undo_button.set_tooltip_text (_("Undo your most recent move"));
+            undo_button.show ();
+            history_box.pack_start (undo_button, true, true, 0);
+
+            /* if (GameWindowFlags.SHOW_REDO in flags)
+            {
+                Button redo_button = new Button.from_icon_name ("edit-redo-symbolic", Gtk.IconSize.BUTTON);
+                redo_button.action_name = "app.redo";
+                redo_button.set_tooltip_text (_("Redo your most recent undone move"));
+                redo_button.show ();
+                history_box.pack_start (redo_button, true, true, 0);
+            } */
+
+            history_box.show ();
+            controls_box.pack_start (history_box, true, true, 0);
+        }
+        /* if (GameWindowFlags.SHOW_HINT in flags)
+        {
+            Button hint_button = new Button.from_icon_name ("dialog-question-symbolic", Gtk.IconSize.BUTTON);
+            hint_button.action_name = "app.hint";
+            hint_button.set_tooltip_text (_("Receive a hint for your next move"));
+            hint_button.show ();
+            controls_box.pack_start (hint_button, true, true, 0);
+        } */
+
+        /* start or not */
+        if (start_now)
+            show_view ();
+        else
+            show_new_game_screen ();
+    }
+
+    /*\
+    * * Window events
+    \*/
+
+    private void size_allocate_cb (Allocation allocation)
+    {
+        if (maximized_state || tiled_state)
+            return;
+        window_width = allocation.width;
+        window_height = allocation.height;
+    }
+
+    private bool window_state_event_cb (Gdk.EventWindowState event)
+    {
+        if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0)
+            maximized_state = (event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0;
+        /* We don’t save this state, but track it for saving size allocation */
+        if ((event.changed_mask & Gdk.WindowState.TILED) != 0)
+            tiled_state = (event.new_window_state & Gdk.WindowState.TILED) != 0;
+        return false;
+    }
+
+    public void save_state (GLib.Settings settings)
+    {
+        settings.set_int ("window-width", window_width);
+        settings.set_int ("window-height", window_height);
+        settings.set_boolean ("window-is-maximized", maximized_state);
+    }
+
+    /*\
+    * * Some public calls
+    \*/
+
+    public void add_to_sidebox (Widget widget)
+    {
+        side_box.pack_start (widget, false, false, 0);
+    }
+
+    public void cannot_undo_more ()
+    {
+        undo_action.set_enabled (false);
+        view.grab_focus ();
+    }
+
+    public void set_subtitle (string? subtitle)
+    {
+        headerbar.set_subtitle (subtitle);
+    }
+
+    public void finish_game ()
+    {
+        game_finished = true;
+        new_game_button.grab_focus ();
+    }
+
+    /* public void about ()
+    {
+        TODO
+    } */
+
+    /*\
+    * * Showing the Stack
+    \*/
+
+    private void show_new_game_screen ()
+    {
+        headerbar.set_subtitle (null);      // TODO save / restore?
+
+        stack.set_visible_child_name ("start-box");
+        controls_box.hide ();
+
+        if (!game_finished && back_button.visible)
+            back_button.grab_focus ();
+        else
+            start_game_button.grab_focus ();
+    }
+
+    private void show_view ()
+    {
+        stack.set_visible_child_name ("frame");
+        back_button.hide ();        // TODO transition?
+        controls_box.show ();
+
+        if (game_finished)
+            new_game_button.grab_focus ();
+        else
+            view.grab_focus ();
+    }
+
+    /*\
+    * * Switching the Stack
+    \*/
+
+    private void new_game_cb ()
+    {
+        if (stack.get_visible_child_name () != "frame")
+            return;
+
+        wait ();
+
+        stack.set_transition_type (StackTransitionType.SLIDE_LEFT);
+        stack.set_transition_duration (800);
+
+        back_button.show ();
+        back_action.set_enabled (true);
+
+        show_new_game_screen ();
+    }
+
+    private void start_game_cb ()
+    {
+        if (stack.get_visible_child_name () != "start-box")
+            return;
+
+        game_finished = false;
+
+        undo_action.set_enabled (false);
+        redo_action.set_enabled (false);
+
+        play ();        // FIXME lag (see in Taquin…)
+
+        stack.set_transition_type (StackTransitionType.SLIDE_DOWN);
+        stack.set_transition_duration (1000);
+        show_view ();
+    }
+
+    private void back_cb ()
+    {
+        if (stack.get_visible_child_name () != "start-box")
+            return;
+        // TODO change back headerbar subtitle?
+        stack.set_transition_type (StackTransitionType.SLIDE_RIGHT);
+        stack.set_transition_duration (800);
+        show_view ();
+
+        back ();
+    }
+
+    /*\
+    * * Controls_box actions
+    \*/
+
+    private void undo_cb ()
+    {
+        if (stack.get_visible_child_name () != "frame")
+            return;
+
+        game_finished = false;
+
+        if (new_game_button.is_focus)
+            view.grab_focus();
+        redo_action.set_enabled (true);
+        undo ();
+    }
+
+    private void redo_cb ()
+    {
+        if (stack.get_visible_child_name () != "frame")
+            return;
+
+        if (new_game_button.is_focus)
+            view.grab_focus();
+        undo_action.set_enabled (true);
+        redo ();
+    }
+
+    private void hint_cb ()
+    {
+        if (stack.get_visible_child_name () != "frame")
+            return;
+        hint ();
+    }
+}
diff --git a/src/taquin-game.vala b/src/taquin-game.vala
index 5d93867..1e33a59 100644
--- a/src/taquin-game.vala
+++ b/src/taquin-game.vala
@@ -22,6 +22,19 @@ public enum GameType
 {
     FIFTEEN,
     SIXTEEN;
+
+    public string to_string ()
+    {
+        switch (this)
+        {
+            case FIFTEEN:
+                return "fifteen";
+            case SIXTEEN:
+                return "sixteen";
+            default:
+                assert_not_reached ();
+        }
+    }
 }
 
 public class Game : Object
diff --git a/src/taquin-main.vala b/src/taquin-main.vala
index 21f441e..3de8b00 100644
--- a/src/taquin-main.vala
+++ b/src/taquin-main.vala
@@ -1,6 +1,6 @@
 /* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
- * Copyright (C) 2014 Arnaud Bonatti <arnaud bonatti gmail com>
+ * Copyright (C) 2014-2015 Arnaud Bonatti <arnaud bonatti gmail com>
  *
  * This file is part of Taquin.
  *
@@ -24,34 +24,22 @@ public class Taquin : Gtk.Application
 {
     /* Settings */
     private GLib.Settings settings;
-    private bool is_tiled;
-    private bool is_maximized;
-    private int window_width;
-    private int window_height;
     private static int tmp_size = 0;
-    private string tmp_type;
+    private GameType? tmp_type = null;
     private bool type_changed = false;
     private bool size_changed = false;
     private bool theme_changed = false;
     private static bool? sound = null;
 
     /* Widgets */
-    private ApplicationWindow window;
-    private HeaderBar headerbar;
-    private Button back_button;
-    private Button undo_button;
-    private Button start_game_button;
-    private Button start_over_button;
-    private Stack stack;
+    private GameWindow window;
     private MenuButton size_button;
     private MenuButton theme_button;
     private TaquinView view;
 
     /* The game being played */
     private Game? game = null;
-    private SimpleAction undo_action;
     List<string> theme_dirlist;
-    private bool game_finished = false;
 
     private static const OptionEntry[] option_entries =
     {
@@ -67,16 +55,6 @@ public class Taquin : Gtk.Application
 
     private const GLib.ActionEntry app_actions[] =
     {
-        {"help", help_cb},
-        {"about", about_cb},
-        {"quit", quit}
-    };
-    private const GLib.ActionEntry win_actions[] =
-    {
-        {"new-game", new_game_cb},
-        {"start-game", start_game_cb},
-        {"back", back_cb},
-
         /* {"change-type", null, "s", null, null, change_type_cb},  TODO SimpleActionChangeStateCallback is 
deprecated...
         {"change-size", null, "s", null, null, change_size_cb},     
http://valadoc.org/#!api=gio-2.0/GLib.SimpleActionChangeStateCallback
         {"change-theme", null, "s", null, null, change_theme_cb},   see comments about window.add_action 
(settings.create_action (…)) */
@@ -85,7 +63,9 @@ public class Taquin : Gtk.Application
         {"change-size", change_size_cb, "s"},
         {"change-theme", change_theme_cb, "s"},
 
-        {"undo", undo_cb}
+        {"help", help_cb},
+        {"about", about_cb},
+        {"quit", quit}
     };
 
     public static int main (string[] args)
@@ -96,7 +76,6 @@ public class Taquin : Gtk.Application
         Intl.textdomain (GETTEXT_PACKAGE);
 
         Environment.set_application_name (_("Taquin"));
-
         Window.set_default_icon_name ("gnome-taquin");
 
         return new Taquin ().run (args);
@@ -121,15 +100,15 @@ public class Taquin : Gtk.Application
         if (tmp_size != 0 && tmp_size < 2)
             tmp_size = 2;
 
-        if (options.contains ("unmute"))
-            sound = true;
         if (options.contains ("mute"))
             sound = false;
+        else if (options.contains ("unmute"))
+            sound = true;
 
         if (options.contains ("fifteen"))
-            tmp_type = "fifteen";
+            tmp_type = GameType.FIFTEEN;
         else if (options.contains ("sixteen"))
-            tmp_type = "sixteen";
+            tmp_type = GameType.SIXTEEN;
 
         return -1;
     }
@@ -138,7 +117,7 @@ public class Taquin : Gtk.Application
     {
         base.startup ();
 
-        var css_provider = new CssProvider ();
+        CssProvider css_provider = new CssProvider ();
         css_provider.load_from_resource ("/org/gnome/taquin/ui/taquin.css");
         StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), css_provider, 
STYLE_PROVIDER_PRIORITY_APPLICATION);
 
@@ -148,36 +127,34 @@ public class Taquin : Gtk.Application
         if (tmp_size > 1)
             settings.set_int ("size", tmp_size);
         if (tmp_type != null)
-            settings.set_string ("type", tmp_type);
+            settings.set_string ("type", tmp_type.to_string());     // TODO better?
 
-        var builder = new Builder.from_resource ("/org/gnome/taquin/ui/taquin.ui");
-        window = builder.get_object ("taquin-window") as ApplicationWindow;
-        window.size_allocate.connect (size_allocate_cb);
-        window.window_state_event.connect (window_state_event_cb);
-        window.set_default_size (settings.get_int ("window-width"), settings.get_int ("window-height"));
-        if (settings.get_boolean ("window-is-maximized"))
-            window.maximize ();
+        /* UI parts */
+        view = new TaquinView ();
 
-        add_action_entries (app_actions, this);
-        window.add_action_entries (win_actions, this);
-        undo_action = (SimpleAction) window.lookup_action ("undo");
-        // TODO window.add_action (settings.create_action ("type"));        // Problem: same bug as in 
Iagno, the settings are resetted to the first radiobutton found
-        // TODO window.add_action (settings.create_action ("size"));        // Problem: cannot use this way 
for an integer from a menu; works for radiobuttons in Iagno
-        // TODO window.add_action (settings.create_action ("theme"));       // Problem: a bug that exists in 
the three tries, and in Iagno: you cannot manually change the gsetting or it bugs completely (gsetting 
between two states)
-        set_accels_for_action ("app.help", {"F1"});
-        set_accels_for_action ("app.quit", {"<Primary>q"});
+        Builder builder = new Builder.from_resource ("/org/gnome/taquin/ui/taquin-screens.ui");
+
+        /* Window */
+        window = new GameWindow (_("Taquin"),
+                                 settings.get_int ("window-width"),
+                                 settings.get_int ("window-height"),
+                                 settings.get_boolean ("window-is-maximized"),
+                                 true,     // TODO add an option to go to new-game screen?
+                                 GameWindowFlags.SHOW_UNDO,
+                                 (Box) builder.get_object ("new-game-screen"),
+                                 view);
+        window.play.connect (start_game);
+        window.undo.connect (undo_cb);
+
+        // TODO use UI file?
         set_accels_for_action ("win.new-game", {"<Primary>n"});
+        set_accels_for_action ("win.start-game", {"<Primary><Shift>n"});
         set_accels_for_action ("win.undo", {"<Primary>z"});
-        add_action (settings.create_action ("sound"));
+        set_accels_for_action ("win.redo", {"<Primary><Shift>z"});
+        set_accels_for_action ("win.back", {"Escape"});
 
-        headerbar = builder.get_object ("headerbar") as HeaderBar;
-        back_button = builder.get_object ("back-button") as Button;
-        undo_button = builder.get_object ("undo-button") as Button;
-        start_game_button = builder.get_object ("start-game-button") as Button;
-        start_over_button = builder.get_object ("start-over-button") as Button;
-        stack = builder.get_object ("main-stack") as Stack;
-
-        size_button = builder.get_object ("size-button") as MenuButton;
+        /* New-game screen signals */
+        size_button = (MenuButton) builder.get_object ("size-button");
         settings.changed["size"].connect (() => {
             if (!size_changed)
                 update_size_button_label (settings.get_int ("size"));
@@ -185,7 +162,7 @@ public class Taquin : Gtk.Application
         });
         update_size_button_label (settings.get_int ("size"));
 
-        theme_button = builder.get_object ("theme-button") as MenuButton;
+        theme_button = (MenuButton) builder.get_object ("theme-button");
         settings.changed["theme"].connect (() => {
             if (!theme_changed)
                 update_theme (settings.get_string ("theme"));
@@ -204,14 +181,15 @@ public class Taquin : Gtk.Application
         var button_name = "radio-" + settings.get_string ("type");
         ((RadioButton) builder.get_object (button_name)).set_active (true);
 
-        var game_box = builder.get_object ("game-box") as Box;
-        view = new TaquinView ();
-        view.halign = Align.FILL;
-        view.show ();
-        game_box.pack_start (view, true, true, 0);
+        add_action_entries (app_actions, this);
+        add_action (settings.create_action ("sound"));
+        // TODO window.add_action (settings.create_action ("type"));        // Problem: same bug as in 
Iagno, the settings are resetted to the first radiobutton found
+        // TODO window.add_action (settings.create_action ("size"));        // Problem: cannot use this way 
for an integer from a menu; works for radiobuttons in Iagno
+        // TODO window.add_action (settings.create_action ("theme"));       // Problem: a bug that exists in 
the three tries, and in Iagno: you cannot manually change the gsetting or it bugs completely (gsetting 
between two states)
 
-        add_window (window);
         start_game ();
+
+        add_window (window);
     }
 
     protected override void activate ()
@@ -222,73 +200,7 @@ public class Taquin : Gtk.Application
     protected override void shutdown ()
     {
         base.shutdown ();
-
-        /* Save window state; don’t try to query it here */
-        settings.set_int ("window-width", window_width);
-        settings.set_int ("window-height", window_height);
-        settings.set_boolean ("window-is-maximized", is_maximized);
-    }
-
-    /*\
-    * * Window events
-    \*/
-
-    private void size_allocate_cb (Allocation allocation)
-    {
-        if (is_maximized || is_tiled)
-            return;
-        window_width = allocation.width;
-        window_height = allocation.height;
-    }
-
-    private bool window_state_event_cb (Gdk.EventWindowState event)
-    {
-        if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0)
-            is_maximized = (event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0;
-        /* We don’t save this state, but track it for saving size allocation */
-        if ((event.changed_mask & Gdk.WindowState.TILED) != 0)
-            is_tiled = (event.new_window_state & Gdk.WindowState.TILED) != 0;
-        return false;
-    }
-
-    /*\
-    * * Switching the Stack
-    \*/
-
-    private void new_game_cb ()
-    {
-        headerbar.set_subtitle (null);
-        stack.set_transition_type (StackTransitionType.SLIDE_LEFT);
-        stack.set_transition_duration (800);
-        undo_button.hide ();
-        stack.set_visible_child_name ("start-box");
-        back_button.show ();
-        if (undo_action.enabled)
-            back_button.grab_focus ();
-        else
-            start_game_button.grab_focus ();
-    }
-
-    private void back_cb ()
-    {
-        stack.set_transition_type (StackTransitionType.SLIDE_RIGHT);
-        stack.set_transition_duration (800);
-        back_button.hide ();
-        stack.set_visible_child_name ("frame");
-        undo_button.show ();
-        if (game_finished)
-            start_over_button.grab_focus ();    // TODO change headerbar subtitle?
-        else
-            view.grab_focus ();
-    }
-
-    private void start_game_cb ()
-    {
-        stack.set_transition_type (StackTransitionType.SLIDE_DOWN);
-        stack.set_transition_duration (1500);
-        back_button.hide ();
-        start_game ();
-        undo_button.show ();
+        window.save_state (settings);
     }
 
     /*\
@@ -300,32 +212,27 @@ public class Taquin : Gtk.Application
         if (game != null)
             SignalHandler.disconnect_by_func (game, null, this);
 
-        undo_action.set_enabled (false);
-        game_finished = false;
-
-        var type = (GameType) settings.get_enum ("type");
-        var size = settings.get_int ("size");
+        GameType type = (GameType) settings.get_enum ("type");
+        int size = settings.get_int ("size");
         game = new Game (type, size);
         view.game = game;
-        view.grab_focus ();
 
-        var filename = "";
+        string filename = "";
         var dirlist = theme_dirlist.copy ();
         do
         {
-            var random = Random.int_range (0, (int) dirlist.length());
+            int random = Random.int_range (0, (int) dirlist.length());
             filename = dirlist.nth_data(random);
             unowned List<string> entry = dirlist.find_custom (filename, strcmp);
             dirlist.remove_link (entry);
         } while (filename[0] == '0' || (filename[0] != '1' && filename[0] != size.to_string ()[0] && 
dirlist.length () != 0));
         view.theme = Path.build_filename (DATA_DIRECTORY, "themes", settings.get_string ("theme"), filename);
+        view.realize ();        // TODO does that help?
 
         game.complete.connect (game_complete_cb);
         game.cannot_move.connect (cannot_move_cb);
-        game.cannot_undo_more.connect (cannot_undo_more_cb);
+        game.cannot_undo_more.connect (window.cannot_undo_more);
         game.move.connect (move_cb);
-
-        stack.set_visible_child_name ("frame"); // FIXME lag…
     }
 
     /*\
@@ -346,7 +253,7 @@ public class Taquin : Gtk.Application
         show_about_dialog (window,
                            "name", _("Taquin"),
                            "version", VERSION,
-                           "copyright", "Copyright © 2014 Arnaud Bonatti",
+                           "copyright", "Copyright © 2014-2015 Arnaud Bonatti",
                            "license-type", License.GPL_3_0,
                            "comments", _("A classic 15-puzzle game"),
                            "authors", authors,
@@ -371,7 +278,7 @@ public class Taquin : Gtk.Application
     }
 
     /*\
-    * * Undoing and signals from game
+    * * Signals from window
     \*/
 
     private void undo_cb ()
@@ -380,27 +287,27 @@ public class Taquin : Gtk.Application
         play_sound ("sliding-1");
     }
 
-    private void cannot_undo_more_cb ()
-    {
-        undo_action.set_enabled (false);
-        view.grab_focus ();
-    }
+    /*\
+    * * Signals from game
+    \*/
+
     private void move_cb ()
     {
-        headerbar.set_subtitle (null);
-        undo_action.set_enabled (true);
-        play_sound ("sliding-1");
+        window.set_subtitle (null);
+        window.undo_action.set_enabled (true);
+        play_sound ("sliding-1");       // TODO sliding-n??
     }
+
     private void cannot_move_cb ()
     {
-        headerbar.set_subtitle (_("You can’t move this tile!"));
+        window.set_subtitle (_("You can’t move this tile!"));
     }
+
     private void game_complete_cb ()
     {
-        game_finished = true;
-        start_over_button.grab_focus ();
-        headerbar.set_subtitle (_("Bravo! You finished the game!"));
-        undo_action.set_enabled (false);
+        window.finish_game ();
+        window.set_subtitle (_("Bravo! You finished the game!"));
+        window.undo_action.set_enabled (false);    // Taquin specific
         play_sound ("gameover");
     }
 
@@ -417,7 +324,7 @@ public class Taquin : Gtk.Application
     private void change_size_cb (SimpleAction action, Variant? variant)
     {
         size_changed = true;
-        var size = int.parse (variant.get_string ());
+        int size = int.parse (variant.get_string ());
         update_size_button_label (size);
         settings.set_int ("size", size);
     }
@@ -429,7 +336,7 @@ public class Taquin : Gtk.Application
     private void change_theme_cb (SimpleAction action, Variant? variant)
     {
         theme_changed = true;
-        var name = variant.get_string ();
+        string name = variant.get_string ();
         update_theme (name);
         settings.set_string ("theme", name);
     }
diff --git a/src/taquin.gresource.xml b/src/taquin.gresource.xml
index d1d1582..03f9198 100644
--- a/src/taquin.gresource.xml
+++ b/src/taquin.gresource.xml
@@ -5,7 +5,8 @@
     <file preprocess="to-pixdata" alias="16-Puzzle.png">../data/schema-16.png</file>
   </gresource>
   <gresource prefix="/org/gnome/taquin/ui">
-    <file preprocess="xml-stripblanks" alias="taquin.ui">../data/taquin.ui</file>
+    <file preprocess="xml-stripblanks" alias="game-window.ui">../data/taquin.ui</file>
+    <file preprocess="xml-stripblanks" alias="taquin-screens.ui">../data/taquin-screens.ui</file>
     <file alias="taquin.css">../data/taquin.css</file>
   </gresource>
   <gresource prefix="/org/gnome/taquin/gtk">



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