[gnome-chess/chess-telepathy-networking-support-664946-rebase: 23/64] Abstract out chess-launcher as a separate window



commit abbe7d821f590923fd2763c037c4ad54e4d83595
Author: Chandni Verma <chandniverma2112 gmail com>
Date:   Mon Sep 3 11:16:55 2012 +0530

    Abstract out chess-launcher as a separate window

 src/Makefile.am         |    1 +
 src/chess-launcher.vala |  663 ++++++++++++++++++++++++++++++++++++++
 src/gnome-chess.vala    |  813 +++++++++--------------------------------------
 3 files changed, 816 insertions(+), 661 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index bc5f8fd..02ede67 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ gnome_chess_SOURCES = \
 	glx.vapi \
 	3ds.vala \
 	gnome-chess.vala \
+	chess-launcher.vala \
 	ai-profile.vala \
 	chess-bitboard.vala \
 	chess-clock.vala \
diff --git a/src/chess-launcher.vala b/src/chess-launcher.vala
new file mode 100644
index 0000000..75eb099
--- /dev/null
+++ b/src/chess-launcher.vala
@@ -0,0 +1,663 @@
+/* chess-launcher.vala: This is a GtkWindow that helps you
+ * launch a new game chess and remembers your last launch settings.
+ *
+ * Copyright  2012 Chandni Verma
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * Author: Chandni Verma <chandniverma2112 gmail com>
+ */
+
+public class ChessLauncher : Gtk.Window
+{
+    private Gtk.Builder builder;
+    private Settings settings;
+    public signal void start_game ();
+    public signal void load_game (File file, bool from_history);
+
+    /* Chess welcome screen widgets */
+    private Gtk.Widget grid_welcome;
+    private Gtk.Widget grid_select_game;
+    private Gtk.Widget grid_select_opponent;
+    private Gtk.Widget grid_select_remote_player;
+    private Gtk.Widget grid_game_options;
+    private Gtk.Widget grid_preferences;
+
+    private Gtk.Action radioaction_previous_game;
+    private Gtk.Action radioaction_new_game;
+
+    private Gtk.Widget togglebutton_robot;
+    private Gtk.Widget togglebutton_remote_player;
+    private Gtk.Action radioaction_opponent_robot;
+    private Gtk.Action radioaction_opponent_local_player;
+    private Gtk.Action radioaction_opponent_remote_player;
+
+    private Gtk.Widget togglebutton_easy;
+    private Gtk.Widget togglebutton_normal;
+    private Gtk.Widget togglebutton_difficult;
+    private Gtk.Action radioaction_easy;
+    private Gtk.Action radioaction_normal;
+    private Gtk.Action radioaction_difficult;
+    private Gtk.Action radioaction_white;
+    private Gtk.Action radioaction_black;
+    private Gtk.ComboBox duration_combo;
+    private Gtk.Adjustment duration_adjustment;
+    private Gtk.Container custom_duration_box;
+    private Gtk.ComboBox custom_duration_units_combo;
+
+    private Gtk.TreeView treeview_robots;
+    private Gtk.ListStore robot_list_model;
+    private Gtk.Button done_button;
+    private Gtk.Widget grid_installable_robots;
+    private Gtk.Label label_install_robots;
+
+    private uint save_duration_timeout = 0;
+    private History history;
+
+    public ChessLauncher (string engines_file,
+        List<AIProfile>? ai_profiles,
+        History history)
+    {
+        this.history = history;
+
+        settings = new Settings ("org.gnome.gnome-chess.Settings");
+        builder = new Gtk.Builder ();
+        try
+        {
+          builder.add_from_file (Path.build_filename (Config.PKGDATADIR,
+              "new-game-launcher.ui", null));
+        }
+        catch (Error e)
+        {
+          warning ("Could not load UI: %s", e.message);
+        }
+
+        Gtk.Window ui_window = (Gtk.Window) builder.get_object ("gnome_chess_app");
+
+        grid_welcome = (Gtk.Widget) builder.get_object ("grid_welcome");
+
+        /* Make this window hold all widgets of UI description's window
+           container */
+        grid_welcome.reparent (this);
+        ui_window.destroy ();
+
+        grid_select_game = (Gtk.Widget) builder.get_object ("grid_select_game");
+        grid_select_opponent = (Gtk.Widget) builder.get_object ("grid_select_opponent");
+        grid_select_remote_player = (Gtk.Widget) builder.get_object ("grid_select_remote_player");
+        grid_game_options = (Gtk.Widget) builder.get_object ("grid_game_options");
+        grid_preferences = (Gtk.Widget) builder.get_object ("grid_preferences");
+
+        radioaction_previous_game = (Gtk.Action) builder.get_object ("radioaction_previous_game");
+        radioaction_new_game = (Gtk.Action) builder.get_object ("radioaction_new_game");
+
+        togglebutton_robot = (Gtk.Widget) builder.get_object ("togglebutton_robot");
+        togglebutton_remote_player = (Gtk.Widget) builder.get_object
+        ("togglebutton_remote_player");
+
+        radioaction_opponent_robot = (Gtk.Action) builder.get_object ("radioaction_opponent_robot");
+        radioaction_opponent_local_player = (Gtk.Action) builder.get_object ("radioaction_opponent_local_player");
+        radioaction_opponent_remote_player = (Gtk.Action) builder.get_object ("radioaction_opponent_remote_player");
+
+        togglebutton_easy = (Gtk.Widget) builder.get_object ("togglebutton_easy");
+        togglebutton_normal = (Gtk.Widget) builder.get_object ("togglebutton_normal");
+        togglebutton_difficult = (Gtk.Widget) builder.get_object ("togglebutton_difficult");
+        radioaction_easy = (Gtk.Action) builder.get_object ("radioaction_easy");
+        radioaction_normal = (Gtk.Action) builder.get_object ("radioaction_normal");
+        radioaction_difficult = (Gtk.Action) builder.get_object ("radioaction_difficult");
+        radioaction_white = (Gtk.Action) builder.get_object ("radioaction_white");
+        radioaction_black = (Gtk.Action) builder.get_object ("radioaction_black");
+        duration_combo = (Gtk.ComboBox) builder.get_object ("duration_combo");
+        duration_adjustment = (Gtk.Adjustment) builder.get_object ("duration_adjustment");
+        custom_duration_box = (Gtk.Container) builder.get_object ("custom_duration_box");
+        custom_duration_units_combo = (Gtk.ComboBox) builder.get_object ("custom_duration_units_combo");
+
+
+        treeview_robots = (Gtk.TreeView) builder.get_object ("treeview_robots");
+        robot_list_model = (Gtk.ListStore) treeview_robots.model;
+        done_button = (Gtk.Button) builder.get_object ("button_preferences_done");
+        grid_installable_robots = (Gtk.Widget) builder.get_object ("grid_installable_robots");
+        label_install_robots = (Gtk.Label) builder.get_object ("label_install_robots");
+
+        /* Connect signals of all objects to their respective handlers */
+        builder.connect_signals (this);
+
+        this.title = _("Chess");
+
+        grid_welcome.show ();
+
+        (this as Gtk.Widget).configure_event.connect
+            (launcher_configure_event_cb);
+
+        /* Populate robots/ prepare installation message */
+
+        if (ai_profiles == null)
+        {
+            togglebutton_robot.hide ();
+            show_robot_opponent_widgets (false);
+
+            StringBuilder engine_names = get_supported_engines (engines_file);
+            engine_names.prepend ("No robot is currently installed.\n" +
+                "Here is a list of suported robots. Install atleast one for " +
+                "advanced options.\n\n");
+
+            label_install_robots.set_label (engine_names.str);
+        }
+        else
+        {
+            /* Populate list of robots */
+
+            Gtk.TreeIter iter;
+            robot_list_model.clear ();
+
+            foreach (var profile in ai_profiles)
+            {
+                robot_list_model.append (out iter);
+                robot_list_model.set (iter, 0, profile.name, -1);
+            }
+
+            message ("No. of robots: %d", robot_list_model.iter_n_children (null));
+            treeview_robots.insert_column_with_attributes (-1, "Robot Name", new
+                Gtk.CellRendererText (), "text", 0);
+            treeview_robots.set_headers_visible (false);
+
+            var robot_selection = treeview_robots.get_selection ();
+            if (robot_list_model.get_iter_first (out iter))
+                robot_selection.select_iter (iter);
+        }
+
+        /* Check if networking is enabled */
+        if (!Config.ENABLE_NETWORKING)
+          togglebutton_remote_player.hide ();
+
+    }
+
+    ~ChessLauncher ()
+    {
+        if (save_duration_timeout != 0)
+            save_duration_cb ();
+
+        settings.sync ();
+    }
+
+    private bool launcher_configure_event_cb (Gtk.Widget widget,
+        Gdk.EventConfigure event)
+    {
+        if (grid_preferences.visible)
+        {
+            settings.set_int ("preferences-screen-width", event.width);
+            settings.set_int ("preferences-screen-height",
+            event.height);
+        }
+        else
+        {
+            if (grid_select_remote_player.visible)
+            {
+                settings.set_int ("remote-player-selector-width",
+                event.width);
+                settings.set_int ("remote-player-selector-height",
+                event.height);
+            }
+            else
+            {
+                settings.set_int ("welcome-screen-width", event.width);
+                settings.set_int ("welcome-screen-height", event.height);
+            }
+        }
+
+        return false;
+    }
+
+    private StringBuilder get_supported_engines (string filename)
+    {
+       var file = new KeyFile ();
+       StringBuilder names = new StringBuilder ();
+
+       debug ("Loading AI names");
+       try
+       {
+           file.load_from_file (filename, KeyFileFlags.NONE);
+       }
+       catch (KeyFileError e)
+       {
+           warning ("Failed to load AI names: %s", e.message);
+           return names;
+       }
+       catch (FileError e)
+       {
+           warning ("Failed to load AI names: %s", e.message);
+           return names;
+       }
+
+       foreach (string name in file.get_groups ())
+       {
+           if (name != null)
+           {
+               names.append (name);
+               names.append_c ('\n');
+           }
+       }
+
+       return names;
+    }
+
+    public void show_game_selector ()
+    {
+        this.resize (settings.get_int ("welcome-screen-width"),
+            settings.get_int ("welcome-screen-height"));
+
+        grid_select_game.show ();
+        grid_select_opponent.hide ();
+        grid_select_remote_player.hide ();
+        grid_game_options.hide ();
+        grid_preferences.hide ();
+    }
+
+    public void show_opponent_selector ()
+    {
+        this.resize (settings.get_int ("welcome-screen-width"),
+            settings.get_int ("welcome-screen-height"));
+
+        grid_select_game.hide ();
+        grid_select_opponent.show ();
+        grid_select_remote_player.hide ();
+        grid_game_options.hide ();
+        grid_preferences.hide ();
+    }
+
+    private void show_remote_player_selector ()
+    {
+        this.resize (settings.get_int ("remote-player-selector-width"),
+            settings.get_int ("remote-player-selector-height"));
+
+        grid_select_game.hide ();
+        grid_select_opponent.hide ();
+        grid_select_remote_player.show ();
+        grid_game_options.hide ();
+        grid_preferences.hide ();
+    }
+
+    public void show_game_options ()
+    {
+        this.resize (settings.get_int ("welcome-screen-width"),
+            settings.get_int ("welcome-screen-height"));
+
+        grid_select_game.hide ();
+        grid_select_opponent.hide ();
+        grid_select_remote_player.hide ();
+        grid_game_options.show ();
+        grid_preferences.hide ();
+
+        /* Present settings */
+        string difficulty = settings.get_string ("difficulty");
+        if (difficulty == "easy")
+            radioaction_easy.activate ();
+        else
+            if (difficulty == "normal")
+                radioaction_normal.activate ();
+            else
+                radioaction_difficult.activate ();
+
+        bool play_as_white = settings.get_boolean ("play-as-white");
+        if (play_as_white)
+            radioaction_white.activate ();
+        else
+            radioaction_black.activate ();
+
+        set_duration (settings.get_int ("duration"));
+    }
+
+    private void show_robot_installation_choice (bool install)
+    {
+        if (install)
+        {
+            treeview_robots.hide ();
+            done_button.hide ();
+            grid_installable_robots.show ();
+        }
+        else
+        {
+            treeview_robots.show ();
+            done_button.show ();
+            grid_installable_robots.hide ();
+        }
+    }
+
+    private void show_preferences ()
+    {
+        this.resize (settings.get_int ("preferences-screen-width"),
+            settings.get_int ("preferences-screen-height"));
+
+        grid_select_game.hide ();
+        grid_select_opponent.hide ();
+        grid_select_remote_player.hide ();
+        grid_game_options.hide ();
+        grid_preferences.show ();
+
+        if (((Gtk.TreeModel)robot_list_model).iter_n_children (null) != 0)
+        {
+            Gtk.TreeIter iter;
+
+            show_robot_installation_choice (false);
+
+            for (bool valid_iter = robot_list_model.get_iter_first (out iter);
+                 valid_iter;
+                 valid_iter = robot_list_model.iter_next (ref iter))
+            {
+                string robot = null;
+                robot_list_model.get (iter, 0, &robot, -1);
+
+                if (settings.get_string ("opponent") == robot)
+                {
+                    var robot_selection = treeview_robots.get_selection ();
+                    robot_selection.select_iter (iter);
+                }
+                break;
+            }
+
+            if (settings.get_string ("opponent-type") == "robot")
+            {
+                treeview_robots.sensitive = true;
+                done_button.label = _("_Done");
+            }
+            else
+            {
+                treeview_robots.sensitive = false;
+                done_button.label = _("_Back");
+            }
+        }
+        else
+        {
+            /* Present an option to install chess engines */
+            show_robot_installation_choice (true);
+        }
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT game_selected_cb", instance_pos = 1.1)]
+    public void game_selected_cb (Gtk.Action action) throws Error
+    {
+        if (action == radioaction_previous_game)
+        {
+            var unfinished = history.get_unfinished ();
+            var file = unfinished.data;
+
+            /* Signal load_game */
+            load_game (file, true);
+        }
+        else
+        {
+            show_opponent_selector ();
+        }
+    }
+
+    private void show_robot_opponent_widgets (bool robot_selected)
+    {
+        if (robot_selected)
+        {
+            togglebutton_easy.show ();
+            togglebutton_normal.show ();
+            togglebutton_difficult.show ();
+        }
+        else
+        {
+            togglebutton_easy.hide ();
+            togglebutton_normal.hide ();
+            togglebutton_difficult.hide ();
+        }
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT opponent_changed_cb", instance_pos = -1)]
+    public void opponent_changed_cb (Gtk.Action action)
+    {
+        if (action == radioaction_opponent_robot)
+        {
+            settings.set_string ("opponent-type", "robot");
+
+            show_robot_opponent_widgets (true);
+            show_game_options ();
+        }
+        else
+        {
+            show_robot_opponent_widgets (false);
+            if (action == radioaction_opponent_local_player)
+            {
+                settings.set_string ("opponent-type", "local-player");
+                show_game_options ();
+            }
+            else
+            {
+                settings.set_string ("opponent-type", "remote-player");
+                show_remote_player_selector ();
+            }
+        }
+    }
+
+//    [CCode (cname = "G_MODULE_EXPORT chat_clicked_cb", instance_pos = -1)]
+    [CCode (cname = "G_MODULE_EXPORT remote_player_selected_cb", instance_pos = -1)]
+    public void remote_player_selected_cb (Gtk.Button button)
+    {
+        /* TODO: Cache player details */
+        show_game_options ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT remote_player_selection_cancelled_cb", instance_pos = -1)]
+    public void remote_player_selection_cancelled_cb (Gtk.Button button)
+    {
+        show_opponent_selector ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT color_selection_changed_cb", instance_pos = -1)]
+    public void color_selection_changed_cb (Gtk.Action action)
+    {
+        bool play_as_white = (action == radioaction_white) ? true : false;
+
+        settings.set_boolean ("play-as-white", play_as_white);
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT difficulty_changed_cb", instance_pos = -1)]
+    public void difficulty_changed_cb (Gtk.Action action)
+    {
+        if (action == radioaction_easy)
+            settings.set_string ("difficulty", "easy");
+        else
+            if (action == radioaction_normal)
+                settings.set_string ("difficulty", "normal");
+            else
+                settings.set_string ("difficulty", "hard");
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT start_game_clicked_cb", instance_pos = -1)]
+    public void start_game_clicked_cb (Gtk.Button button)
+    {
+        /* signal start_game which eventually destroys this launcher */
+        start_game ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT game_options_preferences_clicked_cb", instance_pos = -1)]
+    public void game_options_preferences_clicked_cb (Gtk.Button button)
+    {
+        show_preferences ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT preferences_back_clicked_cb", instance_pos = -1)]
+    public void preferences_back_clicked_cb (Gtk.Button button)
+    {
+        show_game_options ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT game_options_go_back_clicked_cb", instance_pos = -1)]
+    public void game_options_go_back_clicked_cb (Gtk.Button button)
+    {
+        show_opponent_selector ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT preferences_done_cb", instance_pos = -1)]
+    public void preferences_done_cb (Gtk.Button button)
+    {
+        var robot_selection = treeview_robots.get_selection ();
+        Gtk.TreeIter iter;
+        robot_selection.get_selected (null, out iter);
+
+        string selected_robot_opponent = null;
+        treeview_robots.model.get (iter, 0, &selected_robot_opponent);
+        settings.set_string ("opponent", selected_robot_opponent);
+
+        show_game_options ();
+    }
+
+    private void set_duration (int duration, bool simplify = true)
+    {
+        var model = custom_duration_units_combo.model;
+        Gtk.TreeIter iter, max_iter = {};
+
+        /* Find the largest units that can be used for this value */
+        int max_multiplier = 0;
+        if (model.get_iter_first (out iter))
+        {
+            do
+            {
+                int multiplier;
+                model.get (iter, 1, out multiplier, -1);
+                if (multiplier > max_multiplier && duration % multiplier == 0)
+                {
+                    max_multiplier = multiplier;
+                    max_iter = iter;
+                }
+            } while (model.iter_next (ref iter));
+        }
+
+        /* Set the spin button to the value with the chosen units */
+        var value = 0;
+        if (max_multiplier > 0)
+        {
+            value = duration / max_multiplier;
+            duration_adjustment.value = value;
+            custom_duration_units_combo.set_active_iter (max_iter);
+        }
+
+        if (!simplify)
+            return;
+
+        model = duration_combo.model;
+        if (!model.get_iter_first (out iter))
+            return;
+        do
+        {
+            int v;
+            model.get (iter, 1, out v, -1);
+            if (v == duration || v == -1)
+            {
+                duration_combo.set_active_iter (iter);
+                custom_duration_box.visible = v == -1;
+                return;
+            }
+        } while (model.iter_next (ref iter));
+    }
+
+    private int get_duration ()
+    {
+        Gtk.TreeIter iter;
+        if (duration_combo.get_active_iter (out iter))
+        {
+            int duration;
+            duration_combo.model.get (iter, 1, out duration, -1);
+            if (duration >= 0)
+                return duration;
+        }
+    
+        var magnitude = (int) duration_adjustment.value;
+        int multiplier = 1;
+        if (custom_duration_units_combo.get_active_iter (out iter))
+            custom_duration_units_combo.model.get (iter, 1, out multiplier, -1);
+        return magnitude * multiplier;
+    }
+
+    private bool save_duration_cb ()
+    {
+        settings.set_int ("duration", get_duration ());
+        Source.remove (save_duration_timeout);
+        save_duration_timeout = 0;
+        return false;
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT duration_changed_cb", instance_pos = -1)]
+    public void duration_changed_cb (Gtk.Adjustment adjustment)
+    {
+        var model = (Gtk.ListStore) custom_duration_units_combo.model;
+        Gtk.TreeIter iter;
+        /* Set the unit labels to the correct plural form */
+        if (model.get_iter_first (out iter))
+        {
+            do
+            {
+                int multiplier;
+                model.get (iter, 1, out multiplier, -1);
+                switch (multiplier)
+                {
+                case 1:
+                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in seconds */
+                                                  "second", "seconds", (ulong) adjustment.value), -1);
+                    break;
+                case 60:
+                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in minutes */
+                                                  "minute", "minutes", (ulong) adjustment.value), -1);
+                    break;
+                case 3600:
+                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in hours */
+                                                  "hour", "hours", (ulong) adjustment.value), -1);
+                    break;
+                }
+            } while (model.iter_next (ref iter));
+        }
+
+        save_duration ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT duration_units_changed_cb", instance_pos = -1)]
+    public void duration_units_changed_cb (Gtk.Widget widget)
+    {
+        save_duration ();
+    }
+
+    private void save_duration ()
+    {
+        /* Delay writing the value as it this event will be generated a lot spinning through the value */
+        if (save_duration_timeout != 0)
+            Source.remove (save_duration_timeout);
+        save_duration_timeout = Timeout.add (100, save_duration_cb);
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT duration_combo_changed_cb", instance_pos = -1)]
+    public void duration_combo_changed_cb (Gtk.ComboBox combo)
+    {
+        Gtk.TreeIter iter;
+        if (!combo.get_active_iter (out iter))
+            return;
+        int duration;
+        combo.model.get (iter, 1, out duration, -1);
+        custom_duration_box.visible = duration < 0;
+
+        if (duration >= 0)
+            set_duration (duration, false);
+        /* Default to 5 minutes when setting custom duration */
+        else if (get_duration () <= 0)
+            set_duration (5 * 60, false);
+
+        save_duration ();
+    }
+
+
+
+}
diff --git a/src/gnome-chess.vala b/src/gnome-chess.vala
index 5d0b26f..88e2bc2 100644
--- a/src/gnome-chess.vala
+++ b/src/gnome-chess.vala
@@ -7,44 +7,8 @@ public class Application : Gtk.Application
     private History history;
     private Gtk.Builder builder;
     private Gtk.Builder preferences_builder;
-    private Gtk.Window window;
-
-    /* Chess welcome screen widgets */
-    private Gtk.Widget grid_welcome;
-    private Gtk.Widget grid_select_game;
-    private Gtk.Widget grid_select_opponent;
-    private Gtk.Widget grid_select_remote_player;
-    private Gtk.Widget grid_game_options;
-    private Gtk.Widget grid_preferences;
-
-    private Gtk.Action radioaction_previous_game;
-    private Gtk.Action radioaction_new_game;
-
-    private Gtk.Widget togglebutton_robot;
-    private Gtk.Widget togglebutton_remote_player;
-    private Gtk.Action radioaction_opponent_robot;
-    private Gtk.Action radioaction_opponent_local_player;
-    private Gtk.Action radioaction_opponent_remote_player;
-
-    private Gtk.Widget togglebutton_easy;
-    private Gtk.Widget togglebutton_normal;
-    private Gtk.Widget togglebutton_difficult;
-    private Gtk.Action radioaction_easy;
-    private Gtk.Action radioaction_normal;
-    private Gtk.Action radioaction_difficult;
-    private Gtk.Action radioaction_white;
-    private Gtk.Action radioaction_black;
-    private Gtk.ComboBox duration_combo;
-    private Gtk.Adjustment duration_adjustment;
-    private Gtk.Container custom_duration_box;
-    private Gtk.ComboBox custom_duration_units_combo;
-
-
-    private Gtk.TreeView treeview_robots;
-    private Gtk.ListStore robot_list_model;
-    private Gtk.Button done_button;
-    private Gtk.Widget grid_installable_robots;
-    private Gtk.Label label_install_robots;
+    private ChessLauncher? launcher = null;
+    private Gtk.Window? window = null;
 
     /* Chess game screen widgets */
     private Gtk.Widget game_vbox;
@@ -70,7 +34,6 @@ public class Application : Gtk.Application
     private Gtk.Widget black_time_label;
 
     private Gtk.Dialog? preferences_dialog = null;
-    private uint save_duration_timeout = 0;
     private Gtk.FileChooserDialog? open_dialog = null;
     private Gtk.InfoBar? open_dialog_info_bar = null;
     private Gtk.Label? open_dialog_error_label = null;
@@ -84,6 +47,7 @@ public class Application : Gtk.Application
     private bool in_history;
     private File game_file;
     private bool game_needs_saving;
+    private string engines_file;
     private List<AIProfile> ai_profiles;
     private ChessPlayer? opponent = null;
     private ChessPlayer? human_player = null;
@@ -95,39 +59,6 @@ public class Application : Gtk.Application
         this.game_file = game_file;
     }
 
-    private StringBuilder get_supported_engines (string filename)
-    {
-       var file = new KeyFile ();
-       StringBuilder names = new StringBuilder ();
-
-       debug ("Loading AI names");
-       try
-       {
-           file.load_from_file (filename, KeyFileFlags.NONE);
-       }
-       catch (KeyFileError e)
-       {
-           warning ("Failed to load AI names: %s", e.message);
-           return names;
-       }
-       catch (FileError e)
-       {
-           warning ("Failed to load AI names: %s", e.message);
-           return names;
-       }
-
-       foreach (string name in file.get_groups ())
-       {
-           if (name != null)
-           {
-               names.append (name);
-               names.append_c ('\n');
-           }
-       }
-
-       return names;
-    }
-
     public override void startup ()
     {
         base.startup ();
@@ -142,50 +73,66 @@ public class Application : Gtk.Application
         builder = new Gtk.Builder ();
         try
         {
-            builder.add_from_file (Path.build_filename (Config.PKGDATADIR, "gnome-chess.ui", null));
+            builder.add_from_file (Path.build_filename (Config.PKGDATADIR, "gnome-chess-game-window.ui", null));
         }
         catch (Error e)
         {
             warning ("Could not load UI: %s", e.message);
         }
-        window = (Gtk.Window) builder.get_object ("gnome_chess_app");
-
-        grid_welcome = (Gtk.Widget) builder.get_object ("grid_welcome");
-        grid_select_game = (Gtk.Widget) builder.get_object ("grid_select_game");
-        grid_select_opponent = (Gtk.Widget) builder.get_object ("grid_select_opponent");
-        grid_select_remote_player = (Gtk.Widget) builder.get_object ("grid_select_remote_player");
-        grid_game_options = (Gtk.Widget) builder.get_object ("grid_game_options");
-        grid_preferences = (Gtk.Widget) builder.get_object ("grid_preferences");
-
-        radioaction_previous_game = (Gtk.Action) builder.get_object ("radioaction_previous_game");
-        radioaction_new_game = (Gtk.Action) builder.get_object ("radioaction_new_game");
-
-        togglebutton_robot = (Gtk.Widget) builder.get_object ("togglebutton_robot");
-        togglebutton_remote_player = (Gtk.Widget) builder.get_object ("togglebutton_remote_player");
-
-        radioaction_opponent_robot = (Gtk.Action) builder.get_object ("radioaction_opponent_robot");
-        radioaction_opponent_local_player = (Gtk.Action) builder.get_object ("radioaction_opponent_local_player");
-        radioaction_opponent_remote_player = (Gtk.Action) builder.get_object ("radioaction_opponent_remote_player");
-
-        togglebutton_easy = (Gtk.Widget) builder.get_object ("togglebutton_easy");
-        togglebutton_normal = (Gtk.Widget) builder.get_object ("togglebutton_normal");
-        togglebutton_difficult = (Gtk.Widget) builder.get_object ("togglebutton_difficult");
-        radioaction_easy = (Gtk.Action) builder.get_object ("radioaction_easy");
-        radioaction_normal = (Gtk.Action) builder.get_object ("radioaction_normal");
-        radioaction_difficult = (Gtk.Action) builder.get_object ("radioaction_difficult");
-        radioaction_white = (Gtk.Action) builder.get_object ("radioaction_white");
-        radioaction_black = (Gtk.Action) builder.get_object ("radioaction_black");
-        duration_combo = (Gtk.ComboBox) builder.get_object ("duration_combo");
-        duration_adjustment = (Gtk.Adjustment) builder.get_object ("duration_adjustment");
-        custom_duration_box = (Gtk.Container) builder.get_object ("custom_duration_box");
-        custom_duration_units_combo = (Gtk.ComboBox) builder.get_object ("custom_duration_units_combo");
-
-
-        treeview_robots = (Gtk.TreeView) builder.get_object ("treeview_robots");
-        robot_list_model = (Gtk.ListStore) treeview_robots.model;
-        done_button = (Gtk.Button) builder.get_object ("button_preferences_done");
-        grid_installable_robots = (Gtk.Widget) builder.get_object ("grid_installable_robots");
-        label_install_robots = (Gtk.Label) builder.get_object ("label_install_robots");
+
+        settings.changed.connect (settings_changed_cb);
+
+        string engines_file = Path.build_filename (Config.PKGDATADIR, "engines.conf", null);
+        ai_profiles = load_ai_profiles (engines_file);
+
+        foreach (var profile in ai_profiles)
+            message ("Detected AI profile %s in %s", profile.name, profile.path);
+
+        if (game_file == null)
+        {
+            launcher = create_launcher (engines_file, ai_profiles, history);
+
+            var unfinished = history.get_unfinished ();
+            if (unfinished != null)
+                launcher.show_game_selector ();
+            else
+                launcher.show_opponent_selector ();
+
+            /* Show top-level */
+            launcher.show ();
+        }
+        else
+        {
+            try
+            {
+                load_game (game_file, false);
+            }
+            catch (Error e)
+            {
+                stderr.printf ("Failed to load %s: %s\n", game_file.get_path (), e.message);
+                quit ();
+            }
+        }
+
+    }
+
+    private ChessLauncher create_launcher (string engines_file,
+        List<AIProfile>? ai_profiles,
+        History history)
+    {
+        var launcher = new ChessLauncher (engines_file, ai_profiles, history);
+        launcher.application = this;
+
+        launcher.start_game.connect (start_new_game);
+        launcher.load_game.connect (this.load_game_handler);
+        launcher.destroy.connect (launcher_destroy_cb);
+
+        return launcher;
+    }
+
+    private void create_game_window ()
+    {
+        window = (Gtk.Window) builder.get_object ("window_game_screen");
 
         game_vbox = (Gtk.Widget) builder.get_object ("game_vbox");
         save_menu = (Gtk.Widget) builder.get_object ("menu_save_item");
@@ -209,8 +156,6 @@ public class Application : Gtk.Application
 
         builder.connect_signals (this);
 
-        add_window (window);
-
         info_bar = new Gtk.InfoBar ();
         var content_area = (Gtk.Container) info_bar.get_content_area ();
         view_box.pack_start (info_bar, false, true, 0);
@@ -237,82 +182,7 @@ public class Application : Gtk.Application
         settings.bind ("move-format", scene, "move-format", SettingsBindFlags.GET);
         settings.bind ("board-side", scene, "board-side", SettingsBindFlags.GET);
 
-        settings.changed.connect (settings_changed_cb);
         settings_changed_cb (settings, "show-3d");
-
-        string engines_file = Path.build_filename (Config.PKGDATADIR, "engines.conf", null);
-        ai_profiles = load_ai_profiles (engines_file);
-
-        foreach (var profile in ai_profiles)
-            message ("Detected AI profile %s in %s", profile.name, profile.path);
-
-        if (ai_profiles == null)
-        {
-            togglebutton_robot.hide ();
-            show_robot_opponent_widgets (false);
-
-            StringBuilder engine_names = get_supported_engines (engines_file);
-            engine_names.prepend ("No robot is currently installed.\n" +
-                "Here is a list of suported robots. Install atleast one for " +
-                "advanced options.\n\n");
-
-            label_install_robots.set_label (engine_names.str);
-        }
-        else
-        {
-            /* Populate list of robots */
-
-            Gtk.TreeIter iter;
-            robot_list_model.clear ();
-
-            foreach (var profile in ai_profiles)
-            {
-                robot_list_model.append (out iter);
-                robot_list_model.set (iter, 0, profile.name, -1);
-            }
-
-            message ("No. of robots: %d", robot_list_model.iter_n_children (null));
-            treeview_robots.insert_column_with_attributes (-1, "Robot Name", new
-                Gtk.CellRendererText (), "text", 0);
-            treeview_robots.set_headers_visible (false);
-
-            var robot_selection = treeview_robots.get_selection ();
-            if (robot_list_model.get_iter_first (out iter))
-                robot_selection.select_iter (iter);
-
-        }
-
-        if (!Config.ENABLE_NETWORKING)
-          togglebutton_remote_player.hide ();
-
-        if (game_file == null)
-        {
-            var unfinished = history.get_unfinished ();
-            if (unfinished != null)
-                show_game_selector ();
-            else
-                show_opponent_selector ();
-        }
-        else
-        {
-            show_game_vbox ();
-
-            try
-            {
-                load_game (game_file, false);
-            }
-            catch (Error e)
-            {
-                stderr.printf ("Failed to load %s: %s\n", game_file.get_path (), e.message);
-                quit ();
-            }
-        }
-
-        if (settings.get_boolean ("fullscreen"))
-            window.fullscreen ();
-        else if (settings.get_boolean ("maximized"))
-            window.maximize ();
-        show ();
     }
 
     protected override void shutdown ()
@@ -410,13 +280,21 @@ public class Application : Gtk.Application
         BISHOP
     }
 
+    /* Quits the application */
     public void quit_game ()
     {
-        if (save_duration_timeout != 0)
-            save_duration_cb ();
-
         autosave ();
-        window.destroy ();
+        settings.sync ();
+        if (launcher != null)
+        {
+          launcher.destroy ();
+          launcher = null;
+        }
+        if (window != null)
+        {
+          window.destroy ();
+          window = null;
+        }
     }
 
     private void autosave ()
@@ -508,7 +386,7 @@ public class Application : Gtk.Application
     {
         if (in_history)
         {
-            window.title = /* Title of the main window */
+            window.title = /* Title of the game window */
                            _("Chess");
         }
         else
@@ -684,7 +562,20 @@ public class Application : Gtk.Application
 
     public override void activate ()
     {
-        window.show ();
+      /* Launcher or game-window would have been created by startup () already. Show it. */
+      if (launcher != null)
+          launcher.show ();
+      if (window != null)
+          window.show ();
+    }
+
+    [CCode (cname = "launcher_destroy_cb", instance_pos = -1)]
+    public void launcher_destroy_cb (Gtk.Widget widget)
+    {
+        launcher = null;
+
+        if (window == null)
+          quit_game ();
     }
 
     private void engine_ready_cb (ChessEngine engine)
@@ -695,7 +586,7 @@ public class Application : Gtk.Application
             view.queue_draw ();
         }
     }
-    
+
     private void engine_move_cb (ChessEngine engine, string move)
     {
         opponent.move (move);
@@ -969,7 +860,7 @@ public class Application : Gtk.Application
         update_history_panel ();
         update_control_buttons ();
     }
-    
+
     private void update_control_buttons ()
     {
         var can_resign = game.n_moves > 0;
@@ -1066,59 +957,27 @@ public class Application : Gtk.Application
         black_time_label.queue_draw ();
     }
 
-    public void show ()
-    {
-        window.show ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT gnome_chess_app_delete_event_cb", instance_pos = -1)]
-    public bool gnome_chess_app_delete_event_cb (Gtk.Widget widget, Gdk.Event event)
+    [CCode (cname = "G_MODULE_EXPORT game_window_delete_event_cb", instance_pos = -1)]
+    public bool game_window_delete_event_cb (Gtk.Widget widget, Gdk.Event event)
     {
         quit_game ();
         return false;
     }
 
-    [CCode (cname = "G_MODULE_EXPORT gnome_chess_app_configure_event_cb", instance_pos = -1)]
-    public bool gnome_chess_app_configure_event_cb (Gtk.Widget widget, Gdk.EventConfigure event)
+    [CCode (cname = "G_MODULE_EXPORT game_window_configure_event_cb", instance_pos = -1)]
+    public bool game_window_configure_event_cb (Gtk.Widget widget, Gdk.EventConfigure event)
     {
         if (!settings.get_boolean ("maximized") && !settings.get_boolean ("fullscreen"))
         {
-            if (grid_welcome.visible)
-            {
-                if (grid_preferences.visible)
-                {
-                    settings.set_int ("preferences-screen-width", event.width);
-                    settings.set_int ("preferences-screen-height",
-                    event.height);
-                }
-                else
-                {
-                    if (grid_select_remote_player.visible)
-                    {
-                        settings.set_int ("remote-player-selector-width",
-                        event.width);
-                        settings.set_int ("remote-player-selector-height",
-                        event.height);
-                    }
-                    else
-                    {
-                        settings.set_int ("welcome-screen-width", event.width);
-                        settings.set_int ("welcome-screen-height", event.height);
-                    }
-                }
-            }
-            else
-            {
-                settings.set_int ("game-screen-width", event.width);
-                settings.set_int ("game-screen-height", event.height);
-            }
+            settings.set_int ("game-screen-width", event.width);
+            settings.set_int ("game-screen-height", event.height);
         }
 
         return false;
     }
 
-    [CCode (cname = "G_MODULE_EXPORT gnome_chess_app_window_state_event_cb", instance_pos = -1)]
-    public bool gnome_chess_app_window_state_event_cb (Gtk.Widget widget, Gdk.EventWindowState event)
+    [CCode (cname = "G_MODULE_EXPORT game_window_window_state_event_cb", instance_pos = -1)]
+    public bool game_window_window_state_event_cb (Gtk.Widget widget, Gdk.EventWindowState event)
     {
         if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0)
         {
@@ -1135,287 +994,6 @@ public class Application : Gtk.Application
         return false;
     }
 
-    private void show_game_selector ()
-    {
-        game_vbox.hide ();
-        grid_welcome.show ();
-        window.resize (settings.get_int ("welcome-screen-width"),
-            settings.get_int ("welcome-screen-height"));
-
-        grid_select_game.show ();
-        grid_select_opponent.hide ();
-        grid_select_remote_player.hide ();
-        grid_game_options.hide ();
-        grid_preferences.hide ();
-    }
-
-    private void show_opponent_selector ()
-    {
-        game_vbox.hide ();
-        grid_welcome.show ();
-        window.resize (settings.get_int ("welcome-screen-width"),
-            settings.get_int ("welcome-screen-height"));
-
-        grid_select_game.hide ();
-        grid_select_opponent.show ();
-        grid_select_remote_player.hide ();
-        grid_game_options.hide ();
-        grid_preferences.hide ();
-    }
-
-    private void show_remote_player_selector ()
-    {
-        game_vbox.hide ();
-        grid_welcome.show ();
-        window.resize (settings.get_int ("remote-player-selector-width"),
-            settings.get_int ("remote-player-selector-height"));
-
-        grid_select_game.hide ();
-        grid_select_opponent.hide ();
-        grid_select_remote_player.show ();
-        grid_game_options.hide ();
-        grid_preferences.hide ();
-    }
-
-    private void show_game_options ()
-    {
-        game_vbox.hide ();
-        grid_welcome.show ();
-        window.resize (settings.get_int ("welcome-screen-width"),
-            settings.get_int ("welcome-screen-height"));
-
-        grid_select_game.hide ();
-        grid_select_opponent.hide ();
-        grid_select_remote_player.hide ();
-        grid_game_options.show ();
-        grid_preferences.hide ();
-
-        /* Present settings */
-        string difficulty = settings.get_string ("difficulty");
-        if (difficulty == "easy")
-            radioaction_easy.activate ();
-        else
-            if (difficulty == "normal")
-                radioaction_normal.activate ();
-            else
-                radioaction_difficult.activate ();
-
-        bool play_as_white = settings.get_boolean ("play-as-white");
-        if (play_as_white)
-            radioaction_white.activate ();
-        else
-            radioaction_black.activate ();
-
-        set_duration (settings.get_int ("duration"));
-    }
-
-    private void show_robot_installation_choice (bool install)
-    {
-        if (install)
-        {
-            treeview_robots.hide ();
-            done_button.hide ();
-            grid_installable_robots.show ();
-        }
-        else
-        {
-            treeview_robots.show ();
-            done_button.show ();
-            grid_installable_robots.hide ();
-        }
-    }
-
-    private void show_preferences ()
-    {
-        game_vbox.hide ();
-        grid_welcome.show ();
-        window.resize (settings.get_int ("preferences-screen-width"),
-            settings.get_int ("preferences-screen-height"));
-
-        grid_select_game.hide ();
-        grid_select_opponent.hide ();
-        grid_select_remote_player.hide ();
-        grid_game_options.hide ();
-        grid_preferences.show ();
-
-        if (((Gtk.TreeModel)robot_list_model).iter_n_children (null) != 0)
-        {
-            Gtk.TreeIter iter;
-
-            show_robot_installation_choice (false);
-
-            for (bool valid_iter = robot_list_model.get_iter_first (out iter);
-                 valid_iter;
-                 valid_iter = robot_list_model.iter_next (ref iter))
-            {
-                string robot = null;
-                robot_list_model.get (iter, 0, &robot, -1);
-
-                if (settings.get_string ("opponent") == robot)
-                {
-                    var robot_selection = treeview_robots.get_selection ();
-                    robot_selection.select_iter (iter);
-                }
-                break;
-            }
-
-            if (settings.get_string ("opponent-type") == "robot")
-            {
-                treeview_robots.sensitive = true;
-                done_button.label = _("_Done");
-            }
-            else
-            {
-                treeview_robots.sensitive = false;
-                done_button.label = _("_Back");
-            }
-        }
-        else
-        {
-            /* Present an option to install chess engines */
-            show_robot_installation_choice (true);
-        }
-    }
-
-    private void show_game_vbox ()
-    {
-        game_vbox.show ();
-        grid_welcome.hide ();
-        window.resize (settings.get_int ("game-screen-width"),
-            settings.get_int ("game-screen-height"));
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT game_selected_cb", instance_pos = 1.1)]
-    public void game_selected_cb (Gtk.Action action) throws Error
-    {
-        if (action == radioaction_previous_game)
-        {
-            var unfinished = history.get_unfinished ();
-            var file = unfinished.data;
-            show_game_vbox ();
-            load_game (file, true);
-        }
-        else
-        {
-            show_opponent_selector ();
-        }
-    }
-
-    private void show_robot_opponent_widgets (bool robot_selected)
-    {
-        if (robot_selected)
-        {
-            togglebutton_easy.show ();
-            togglebutton_normal.show ();
-            togglebutton_difficult.show ();
-        }
-        else
-        {
-            togglebutton_easy.hide ();
-            togglebutton_normal.hide ();
-            togglebutton_difficult.hide ();
-        }
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT opponent_changed_cb", instance_pos = -1)]
-    public void opponent_changed_cb (Gtk.Action action)
-    {
-        if (action == radioaction_opponent_robot)
-        {
-            settings.set_string ("opponent-type", "robot");
-
-            show_robot_opponent_widgets (true);
-            show_game_options ();
-        }
-        else
-        {
-            show_robot_opponent_widgets (false);
-            if (action == radioaction_opponent_local_player)
-            {
-                settings.set_string ("opponent-type", "local-player");
-                show_game_options ();
-            }
-            else
-            {
-                settings.set_string ("opponent-type", "remote-player");
-                show_remote_player_selector ();
-            }
-        }
-    }
-
-//    [CCode (cname = "G_MODULE_EXPORT chat_clicked_cb", instance_pos = -1)]
-    [CCode (cname = "G_MODULE_EXPORT remote_player_selected_cb", instance_pos = -1)]
-    public void remote_player_selected_cb (Gtk.Button button)
-    {
-        /* TODO: Cache player details */
-        show_game_options ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT remote_player_selection_cancelled_cb", instance_pos = -1)]
-    public void remote_player_selection_cancelled_cb (Gtk.Button button)
-    {
-        show_opponent_selector ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT color_selection_changed_cb", instance_pos = -1)]
-    public void color_selection_changed_cb (Gtk.Action action)
-    {
-        bool play_as_white = (action == radioaction_white) ? true : false;
-
-        settings.set_boolean ("play-as-white", play_as_white);
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT difficulty_changed_cb", instance_pos = -1)]
-    public void difficulty_changed_cb (Gtk.Action action)
-    {
-        if (action == radioaction_easy)
-            settings.set_string ("difficulty", "easy");
-        else
-            if (action == radioaction_normal)
-                settings.set_string ("difficulty", "normal");
-            else
-                settings.set_string ("difficulty", "hard");
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT start_game_clicked_cb", instance_pos = -1)]
-    public void start_game_clicked_cb (Gtk.Button button)
-    {
-        show_game_vbox ();
-        start_new_game ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT game_options_preferences_clicked_cb", instance_pos = -1)]
-    public void game_options_preferences_clicked_cb (Gtk.Button button)
-    {
-        show_preferences ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT preferences_back_clicked_cb", instance_pos = -1)]
-    public void preferences_back_clicked_cb (Gtk.Button button)
-    {
-        show_game_options ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT game_options_go_back_clicked_cb", instance_pos = -1)]
-    public void game_options_go_back_clicked_cb (Gtk.Button button)
-    {
-        show_opponent_selector ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT preferences_done_cb", instance_pos = -1)]
-    public void preferences_done_cb (Gtk.Button button)
-    {
-        var robot_selection = treeview_robots.get_selection ();
-        Gtk.TreeIter iter;
-        robot_selection.get_selected (null, out iter);
-
-        string selected_robot_opponent = null;
-        treeview_robots.model.get (iter, 0, &selected_robot_opponent);
-        settings.set_string ("opponent", selected_robot_opponent);
-
-        show_game_options ();
-    }
-
     [CCode (cname = "G_MODULE_EXPORT new_game_cb", instance_pos = -1)]
     public void new_game_cb (Gtk.Widget widget)
     {
@@ -1444,7 +1022,12 @@ public class Application : Gtk.Application
 
         autosave ();
 
-        show_opponent_selector ();
+        /* Hide game-window and show launcher */
+        window.hide ();
+        if (launcher == null)
+          launcher = create_launcher (engines_file, ai_profiles, history);
+        launcher.present ();
+        launcher.show_opponent_selector ();
     }
 
     [CCode (cname = "G_MODULE_EXPORT resign_cb", instance_pos = -1)]
@@ -1610,7 +1193,7 @@ public class Application : Gtk.Application
             warning ("Could not load preferences UI: %s", e.message);
         }
         preferences_dialog = (Gtk.Dialog) preferences_builder.get_object ("preferences");
-        
+
         settings.bind ("show-numbering", preferences_builder.get_object ("show_numbering_check"),
                        "active", SettingsBindFlags.DEFAULT);
         settings.bind ("show-move-hints", preferences_builder.get_object ("show_move_hints_check"),
@@ -1666,147 +1249,6 @@ public class Application : Gtk.Application
         return value;
     }
 
-    private void set_duration (int duration, bool simplify = true)
-    {
-        var model = custom_duration_units_combo.model;
-        Gtk.TreeIter iter, max_iter = {};
-
-        /* Find the largest units that can be used for this value */
-        int max_multiplier = 0;
-        if (model.get_iter_first (out iter))
-        {
-            do
-            {
-                int multiplier;
-                model.get (iter, 1, out multiplier, -1);
-                if (multiplier > max_multiplier && duration % multiplier == 0)
-                {
-                    max_multiplier = multiplier;
-                    max_iter = iter;
-                }
-            } while (model.iter_next (ref iter));
-        }
-
-        /* Set the spin button to the value with the chosen units */
-        var value = 0;
-        if (max_multiplier > 0)
-        {
-            value = duration / max_multiplier;
-            duration_adjustment.value = value;
-            custom_duration_units_combo.set_active_iter (max_iter);
-        }
-
-        if (!simplify)
-            return;
-
-        model = duration_combo.model;
-        if (!model.get_iter_first (out iter))
-            return;
-        do
-        {
-            int v;
-            model.get (iter, 1, out v, -1);
-            if (v == duration || v == -1)
-            {
-                duration_combo.set_active_iter (iter);
-                custom_duration_box.visible = v == -1;
-                return;
-            }
-        } while (model.iter_next (ref iter));
-    }
-
-    private int get_duration ()
-    {
-        Gtk.TreeIter iter;
-        if (duration_combo.get_active_iter (out iter))
-        {
-            int duration;
-            duration_combo.model.get (iter, 1, out duration, -1);
-            if (duration >= 0)
-                return duration;
-        }
-    
-        var magnitude = (int) duration_adjustment.value;
-        int multiplier = 1;
-        if (custom_duration_units_combo.get_active_iter (out iter))
-            custom_duration_units_combo.model.get (iter, 1, out multiplier, -1);
-        return magnitude * multiplier;
-    }
-
-    private bool save_duration_cb ()
-    {
-        settings.set_int ("duration", get_duration ());
-        Source.remove (save_duration_timeout);
-        save_duration_timeout = 0;
-        return false;
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT duration_changed_cb", instance_pos = -1)]
-    public void duration_changed_cb (Gtk.Adjustment adjustment)
-    {
-        var model = (Gtk.ListStore) custom_duration_units_combo.model;
-        Gtk.TreeIter iter;
-        /* Set the unit labels to the correct plural form */
-        if (model.get_iter_first (out iter))
-        {
-            do
-            {
-                int multiplier;
-                model.get (iter, 1, out multiplier, -1);
-                switch (multiplier)
-                {
-                case 1:
-                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in seconds */
-                                                  "second", "seconds", (ulong) adjustment.value), -1);
-                    break;
-                case 60:
-                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in minutes */
-                                                  "minute", "minutes", (ulong) adjustment.value), -1);
-                    break;
-                case 3600:
-                    model.set (iter, 0, ngettext (/* Preferences Dialog: Combo box entry for a custom game timer set in hours */
-                                                  "hour", "hours", (ulong) adjustment.value), -1);
-                    break;
-                }
-            } while (model.iter_next (ref iter));
-        }
-
-        save_duration ();
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT duration_units_changed_cb", instance_pos = -1)]
-    public void duration_units_changed_cb (Gtk.Widget widget)
-    {
-        save_duration ();
-    }
-
-    private void save_duration ()
-    {
-        /* Delay writing the value as it this event will be generated a lot spinning through the value */
-        if (save_duration_timeout != 0)
-            Source.remove (save_duration_timeout);
-        save_duration_timeout = Timeout.add (100, save_duration_cb);
-    }
-
-    [CCode (cname = "G_MODULE_EXPORT duration_combo_changed_cb", instance_pos = -1)]
-    public void duration_combo_changed_cb (Gtk.ComboBox combo)
-    {
-        Gtk.TreeIter iter;
-        if (!combo.get_active_iter (out iter))
-            return;
-        int duration;
-        combo.model.get (iter, 1, out duration, -1);
-        custom_duration_box.visible = duration < 0;
-
-        if (duration >= 0)
-            set_duration (duration, false);
-        /* Default to 5 minutes when setting custom duration */
-        else if (get_duration () <= 0)
-            set_duration (5 * 60, false);
-
-        save_duration ();
-    }
-
     [CCode (cname = "G_MODULE_EXPORT preferences_response_cb", instance_pos = -1)]
     public void preferences_response_cb (Gtk.Widget widget, int response_id)
     {
@@ -1928,7 +1370,7 @@ public class Application : Gtk.Application
         dialog.border_width = 0;
         dialog.add (vbox);
     }
-    
+
     private void save_game ()
     {
         /* Show active dialog */
@@ -2062,8 +1504,28 @@ public class Application : Gtk.Application
         open_dialog_error_label = null;
     }
 
+    private void display_window ()
+    {
+        if (settings.get_boolean ("fullscreen"))
+            window.fullscreen ();
+        else if (settings.get_boolean ("maximized"))
+            window.maximize ();
+
+        game_vbox.show ();
+        window.resize (settings.get_int ("game-screen-width"),
+            settings.get_int ("game-screen-height"));
+
+        window.show ();
+    }
+
     private void start_new_game ()
     {
+        if (window == null)
+        {
+          create_game_window ();
+          add_window (window);
+        }
+
         in_history = true;
         game_file = null;
 
@@ -2094,16 +1556,45 @@ public class Application : Gtk.Application
             }
         }
         start_game ();
+
+        display_window ();
+        if (launcher != null)
+          launcher.destroy ();
+    }
+
+    [CCode (cname = "load_game_handler", instance_pos = -1)]
+    private void load_game_handler (ChessLauncher launcher,
+        File file,
+        bool from_history)
+    {
+        try
+        {
+            load_game (file, from_history);
+        }
+        catch (Error e)
+        {
+           stderr.printf ("Error loading pgn from file: %s", e.message);
+        }
     }
 
     private void load_game (File file, bool from_history) throws Error
     {
+        if (window == null)
+        {
+          create_game_window ();
+          add_window (window);
+        }
+
         var pgn = new PGN.from_file (file);
         pgn_game = pgn.games.nth_data (0);
 
         game_file = file;
         in_history = from_history;
         start_game ();
+
+        display_window ();
+        if (launcher != null)
+          launcher.destroy ();
     }
 }
 



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