From 58e00431b758dcda8389987baf55ca1c386a10ba Mon Sep 17 00:00:00 2001
From: Bruce Cowan <bruce@bcowan.eu>
Date: Sun, 31 Dec 2017 12:17:42 +0000
Subject: [PATCH] Change to using templates

Rather than GtkBuilder directly
---
 .gitignore              |   2 +-
 data/interface.ui       | 324 ++++++++++++++++++++--------------------
 src/meson.build         |   1 +
 src/rugby-app-window.c  | 161 ++++++++++++++++++++
 src/rugby-app-window.h  |  17 +++
 src/rugby-application.c | 271 ++-------------------------------
 src/rugby-score-store.c |   4 +-
 7 files changed, 355 insertions(+), 425 deletions(-)
 create mode 100644 src/rugby-app-window.c
 create mode 100644 src/rugby-app-window.h

diff --git a/.gitignore b/.gitignore
index 378eac2..dfc1a4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-build
+.flatpak*
diff --git a/data/interface.ui b/data/interface.ui
index cbe4810..1198f84 100644
--- a/data/interface.ui
+++ b/data/interface.ui
@@ -1,30 +1,33 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.2 -->
 <interface>
-  <!-- interface-requires gtk+ 3.4 -->
+  <requires lib="gtk+" version="3.10"/>
   <object class="GtkAboutDialog" id="about">
     <property name="can_focus">False</property>
-    <property name="border_width">5</property>
     <property name="type_hint">dialog</property>
     <property name="program_name">Rugby</property>
-    <property name="copyright" translatable="yes">Copyright © 2012 Bruce Cowan</property>
-    <property name="comments" translatable="yes">A rugby scores possibilities program.</property>
-    <property name="website">http://www.bcowan.me.uk</property>
-    <property name="authors">Bruce Cowan</property>
-    <property name="license_type">mit-x11</property>
+    <property name="copyright" translatable="yes">Copyright © 2012-2017 Bruce Cowan</property>
+    <property name="logo_icon_name">image-missing</property>
+    <property name="license_type">lgpl-3-0</property>
     <child internal-child="vbox">
-      <object class="GtkBox" id="aboutdialog-vbox1">
+      <object class="GtkBox">
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
-          <object class="GtkButtonBox" id="aboutdialog-action_area1">
+          <object class="GtkButtonBox">
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
+            <property name="fill">False</property>
             <property name="position">0</property>
           </packing>
         </child>
@@ -33,183 +36,174 @@
         </child>
       </object>
     </child>
+    <child>
+      <placeholder/>
+    </child>
   </object>
-  <object class="GtkAdjustment" id="filteradj">
-    <property name="upper">1</property>
+  <object class="GtkAdjustment" id="adjustment1">
+    <property name="upper">200</property>
     <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
   </object>
-  <object class="GtkAdjustment" id="kickadj">
-    <property name="upper">1</property>
+  <object class="GtkAdjustment" id="adjustment2">
+    <property name="upper">20</property>
     <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
   </object>
-  <object class="GtkAdjustment" id="scoreadj">
-    <property name="upper">150</property>
+  <object class="GtkAdjustment" id="adjustment3">
+    <property name="upper">20</property>
     <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
   </object>
-  <object class="GtkApplicationWindow" id="window">
+  <template class="RugbyAppWindow" parent="GtkApplicationWindow">
     <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Rugby scores</property>
     <child>
-      <object class="GtkGrid" id="grid">
+      <object class="GtkScrolledWindow">
+        <property name="height_request">300</property>
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <child>
-          <object class="GtkLabel" id="label1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="label" translatable="yes">_Score:</property>
-            <property name="use_underline">True</property>
-            <property name="mnemonic_widget">scorespin</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkSpinButton" id="scorespin">
-            <property name="can_focus">True</property>
-            <property name="invisible_char">•</property>
-            <property name="invisible_char_set">True</property>
-            <property name="adjustment">scoreadj</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkCheckButton" id="tryfilter">
-            <property name="label" translatable="yes">_Try filter:</property>
-            <property name="use_action_appearance">False</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">False</property>
-            <property name="use_action_appearance">False</property>
-            <property name="use_underline">True</property>
-            <property name="xalign">0</property>
-            <property name="draw_indicator">True</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
+        <property name="can_focus">True</property>
+        <property name="shadow_type">in</property>
         <child>
-          <object class="GtkScale" id="tryscale">
+          <object class="GtkTreeView" id="treeview">
             <property name="visible">True</property>
-            <property name="sensitive">False</property>
             <property name="can_focus">True</property>
-            <property name="hexpand">True</property>
-            <property name="adjustment">filteradj</property>
-            <property name="round_digits">0</property>
-            <property name="digits">0</property>
+            <child internal-child="selection">
+              <object class="GtkTreeSelection"/>
+            </child>
           </object>
-          <packing>
-            <property name="left_attach">3</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
         </child>
-        <child>
-          <object class="GtkScrolledWindow" id="scrolledwindow">
-            <property name="height_request">300</property>
+      </object>
+    </child>
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="show_close_button">True</property>
+        <child type="title">
+          <object class="GtkBox">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="vexpand">True</property>
-            <property name="hscrollbar_policy">never</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">6</property>
             <child>
-              <object class="GtkTreeView" id="treeview">
-                <property name="width_request">400</property>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Score:</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton">
+                <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="has_tooltip">True</property>
-                <property name="headers_visible">False</property>
-                <property name="enable_search">False</property>
-                <property name="tooltip_column">3</property>
-                <child internal-child="selection">
-                  <object class="GtkTreeSelection" id="treeview-selection1"/>
+                <property name="text" translatable="yes">0</property>
+                <property name="adjustment">adjustment1</property>
+                <signal name="value-changed" handler="scorespin_value_changed_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">Kick filter:</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">Try filter:</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="tryfilter">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <signal name="notify::active" handler="tryfilter_active_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="kickfilter">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <signal name="notify::active" handler="kickfilter_active_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScale" id="tryscale">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="adjustment">adjustment2</property>
+                    <property name="round_digits">1</property>
+                    <property name="digits">0</property>
+                    <signal name="value-changed" handler="scale_value_changed_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScale" id="kickscale">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="adjustment">adjustment3</property>
+                    <property name="round_digits">1</property>
+                    <property name="digits">0</property>
+                    <signal name="value-changed" handler="scale_value_changed_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="top_attach">1</property>
+                  </packing>
                 </child>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
             </child>
           </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">2</property>
-            <property name="width">4</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkStatusbar" id="status">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="spacing">2</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">3</property>
-            <property name="width">4</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkCheckButton" id="kickfilter">
-            <property name="label" translatable="yes">Kick filter:</property>
-            <property name="use_action_appearance">False</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">False</property>
-            <property name="use_action_appearance">False</property>
-            <property name="xalign">0</property>
-            <property name="draw_indicator">True</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">1</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkScale" id="kickscale">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="adjustment">kickadj</property>
-            <property name="round_digits">1</property>
-            <property name="digits">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">3</property>
-            <property name="top_attach">1</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
         </child>
       </object>
     </child>
-  </object>
-  <menu id="app-menu">
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">_About</attribute>
-        <attribute name="action">app.about</attribute>
-        <attribute name="accel">&lt;Primary&gt;a</attribute>
-      </item>
-    </section>
-    <section>
-      <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>
+  </template>
 </interface>
diff --git a/src/meson.build b/src/meson.build
index 123ef0e..f810291 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -3,6 +3,7 @@ gnome = import('gnome')
 sources = files(
     'rugby.c',
     'rugby-application.c',
+    'rugby-app-window.c',
     'rugby-cell-renderer-score.c',
     'rugby-score-store.c',
     'rugby-scoring.c'
diff --git a/src/rugby-app-window.c b/src/rugby-app-window.c
new file mode 100644
index 0000000..18f4e30
--- /dev/null
+++ b/src/rugby-app-window.c
@@ -0,0 +1,161 @@
+#include <gtk/gtk.h>
+
+#include "rugby-application.h"
+#include "rugby-app-window.h"
+#include "rugby-cell-renderer-score.h"
+#include "rugby-score-store.h"
+#include "rugby-scoring.h"
+
+struct _RugbyAppWindow
+{
+    GtkApplicationWindow parent;
+
+    RugbyScoreStore *store;
+    GtkTreeModel *filter;
+
+    GtkWidget *tryfilter;
+    GtkWidget *kickfilter;
+    GtkWidget *tryscale;
+    GtkWidget *kickscale;
+    GtkWidget *treeview;
+};
+
+G_DEFINE_TYPE(RugbyAppWindow, rugby_app_window, GTK_TYPE_APPLICATION_WINDOW);
+
+static void
+scorespin_value_changed_cb (GtkSpinButton  *spin,
+                            RugbyAppWindow *self)
+{
+    gint score = gtk_spin_button_get_value_as_int (spin);
+    rugby_score_store_set_score (self->store, score);
+
+    gint max_tries = MAX (rugby_scoring_get_max_tries (score), 1.0);
+    gtk_range_set_range (GTK_RANGE (self->tryscale), 0.0, max_tries);
+
+    gint max_kicks = MAX (rugby_scoring_get_max_kicks (score), 1.0);
+    gtk_range_set_range (GTK_RANGE (self->kickscale), 0.0, max_kicks);
+}
+
+static void
+tryfilter_active_cb (GObject        *gobject,
+                     GParamSpec     *pspec,
+                     RugbyAppWindow *self)
+{
+    gboolean active = gtk_switch_get_active (GTK_SWITCH (gobject));
+    gtk_widget_set_sensitive (self->tryscale, active);
+}
+
+static void
+kickfilter_active_cb (GObject        *gobject,
+                      GParamSpec     *pspec,
+                      RugbyAppWindow *self)
+{
+    gboolean active = gtk_switch_get_active (GTK_SWITCH (gobject));
+    gtk_widget_set_sensitive (self->kickscale, active);
+}
+
+static void
+scale_value_changed_cb (GtkRange       *range,
+                        RugbyAppWindow *self)
+{
+    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (self->filter));
+}
+
+static gboolean
+filter_visible_func (GtkTreeModel *model,
+                     GtkTreeIter  *iter,
+                     gpointer      data)
+{
+    RugbyAppWindow *self = RUGBY_APP_WINDOW (data);
+
+    gint tries, utries, kicks;
+
+    gint ftries = gtk_range_get_value (GTK_RANGE (self->tryscale));
+    gint fkicks = gtk_range_get_value (GTK_RANGE (self->kickscale));
+    gtk_tree_model_get (model, iter,
+                        RUGBY_SCORE_STORE_TRIES, &tries,
+                        RUGBY_SCORE_STORE_UTRIES, &utries,
+                        RUGBY_SCORE_STORE_KICKS, &kicks,
+                        -1);
+
+    gboolean try = gtk_switch_get_active (GTK_SWITCH (self->tryfilter));
+    gboolean kick = gtk_switch_get_active (GTK_SWITCH (self->kickfilter));
+
+    if (try && kick)
+        return ((tries + utries == ftries) && (kicks == fkicks)) ? TRUE : FALSE;
+    else if (try)
+        return (tries + utries) == ftries ? TRUE : FALSE;
+    else if (kick)
+        return (kicks == fkicks) ? TRUE : FALSE;
+    else
+        return TRUE;
+
+}
+
+static void
+rugby_app_window_init (RugbyAppWindow *self)
+{
+    gtk_widget_init_template (GTK_WIDGET (self));
+
+    GtkCellRenderer *renderer = rugby_cell_renderer_score_new ();
+    GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ("Score", renderer,
+                                                                          "tries", RUGBY_SCORE_STORE_TRIES,
+                                                                          "utries", RUGBY_SCORE_STORE_UTRIES,
+                                                                          "kicks", RUGBY_SCORE_STORE_KICKS,
+                                                                          NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (self->treeview), column);
+
+    // TODO: put this in the builder file instead
+    self->store = rugby_score_store_new ();
+    self->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (self->store), NULL);
+
+    gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (self->filter),
+                                            filter_visible_func, self, NULL);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (self->treeview), self->filter);
+
+    GtkCssProvider *provider = gtk_css_provider_new ();
+    gtk_css_provider_load_from_resource (provider, "/uk/me/bcowan/rugby/rugby.css");
+
+    gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                               GTK_STYLE_PROVIDER (provider),
+                                               GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+rugby_app_window_dispose (GObject *object)
+{
+    RugbyAppWindow *self = RUGBY_APP_WINDOW (object);
+
+    g_clear_object (&self->store);
+    g_clear_object (&self->filter);
+
+    G_OBJECT_CLASS (rugby_app_window_parent_class)->dispose (object);
+}
+
+static void
+rugby_app_window_class_init (RugbyAppWindowClass *klass)
+{
+    GObjectClass *obj_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    obj_class->dispose = rugby_app_window_dispose;
+
+    gtk_widget_class_set_template_from_resource (widget_class,
+                                                 "/uk/me/bcowan/rugby/interface.ui");
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, tryfilter);
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, kickfilter);
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, tryscale);
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, kickscale);
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, treeview);
+
+    gtk_widget_class_bind_template_callback (widget_class, scorespin_value_changed_cb);
+    gtk_widget_class_bind_template_callback (widget_class, tryfilter_active_cb);
+    gtk_widget_class_bind_template_callback (widget_class, kickfilter_active_cb);
+    gtk_widget_class_bind_template_callback (widget_class, scale_value_changed_cb);
+}
+
+RugbyAppWindow *
+rugby_app_window_new (RugbyApplication *app)
+{
+    return g_object_new (RUGBY_TYPE_APP_WINDOW, "application", app, NULL);
+}
diff --git a/src/rugby-app-window.h b/src/rugby-app-window.h
new file mode 100644
index 0000000..382d7b5
--- /dev/null
+++ b/src/rugby-app-window.h
@@ -0,0 +1,17 @@
+#ifndef RUGBY_APP_WINDOW_H
+#define RUGBY_APP_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define RUGBY_TYPE_APP_WINDOW (rugby_app_window_get_type())
+
+G_DECLARE_FINAL_TYPE (RugbyAppWindow, rugby_app_window, RUGBY, APP_WINDOW, GtkApplicationWindow);
+
+RugbyAppWindow *rugby_app_window_new (RugbyApplication *app);
+
+G_END_DECLS
+
+#endif /* RUGBY_APPLICATION_WINDOW_H */
+
diff --git a/src/rugby-application.c b/src/rugby-application.c
index faa6be7..58a7411 100644
--- a/src/rugby-application.c
+++ b/src/rugby-application.c
@@ -1,281 +1,38 @@
-#include "rugby-application.h"
+#include <gtk/gtk.h>
 
-#include "rugby-cell-renderer-score.h"
-#include "rugby-score-store.h"
-#include "rugby-scoring.h"
+#include "rugby-application.h"
+#include "rugby-app-window.h"
 
 struct _RugbyApplication
 {
-  	GtkApplication parent_instance;
-
-	GtkWidget *tryfilter;
-	GtkWidget *tryscale;
-	GtkWidget *kickfilter;
-	GtkWidget *kickscale;
-	RugbyScoreStore *store;
-	GtkTreeModel *fmodel;
+    GtkApplication parent;
 };
 
-G_DEFINE_TYPE (RugbyApplication, rugby_application, GTK_TYPE_APPLICATION)
-
-static void
-scorespin_changed_cb (GtkSpinButton    *spin,
-                      RugbyApplication *app)
-{
-	gint score;
-	gint max_tries;
-	gint max_kicks;
-
-	score = gtk_spin_button_get_value_as_int (spin);
-	rugby_score_store_set_score (app->store, score);
-
-	/* I'd rather not have to do this */
-	max_tries = MAX (rugby_scoring_get_max_tries (score), 1.0);
-	gtk_range_set_range (GTK_RANGE (app->tryscale), 0.0, max_tries);
-
-	max_kicks = MAX (rugby_scoring_get_max_kicks (score), 1.0);
-	gtk_range_set_range (GTK_RANGE (app->kickscale), 0.0, max_kicks);
-}
-
-static void
-tryfilter_toggled_cb (GtkToggleButton  *toggle,
-                      RugbyApplication *app)
-{
-	if (gtk_toggle_button_get_active (toggle))
-		gtk_widget_set_sensitive (app->tryscale, TRUE);
-	else
-		gtk_widget_set_sensitive (app->tryscale, FALSE);
-
-	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->fmodel));
-}
-
-/* TODO replace this with one function */
-static void
-kickfilter_toggled_cb (GtkToggleButton  *toggle,
-                       RugbyApplication *app)
-{
-	if (gtk_toggle_button_get_active (toggle))
-		gtk_widget_set_sensitive (app->kickscale, TRUE);
-	else
-		gtk_widget_set_sensitive (app->kickscale, FALSE);
-
-	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->fmodel));
-}
-
-static void
-scale_changed_cb (GtkRange         *range,
-                  RugbyApplication *app)
-{
-	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->fmodel));
-}
-
-static void
-store_finished_cb (RugbyScoreStore *store,
-                   gint             possibilities,
-                   GtkStatusbar    *bar)
-{
-	gchar *status;
-	guint context_id;
-
-	status = g_strdup_printf ("%d possibilities", possibilities);
-	context_id = gtk_statusbar_get_context_id (bar, "possibilities count");
-
-	gtk_statusbar_pop (bar, context_id);
-	gtk_statusbar_push (bar, context_id, status);
-
-	g_free (status);
-}
-
-static gboolean
-filter_func (GtkTreeModel     *model,
-             GtkTreeIter      *iter,
-             RugbyApplication *app)
-{
-	gint ctries, ckicks;                         /* TODO fix these crap names */
-	gint tries, utries, kicks;
-	gboolean try, kick;
-
-	ctries = (gint) gtk_range_get_value (GTK_RANGE (app->tryscale));
-	ckicks = (gint) gtk_range_get_value (GTK_RANGE (app->kickscale));
-	gtk_tree_model_get (model, iter,
-	                    RUGBY_SCORE_STORE_TRIES, &tries,
-	                    RUGBY_SCORE_STORE_UTRIES, &utries,
-	                    RUGBY_SCORE_STORE_KICKS, &kicks, -1);
-
-	try = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (app->tryfilter));
-	kick = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (app->kickfilter));
-
-	if (try && kick)
-		return ((tries + utries == ctries) && (kicks == ckicks)) ? TRUE : FALSE;
-	else if (try)
-		return (tries + utries == ctries) ? TRUE : FALSE;
-	else if (kick)
-		return (kicks == ckicks) ? TRUE : FALSE;
-
-	return TRUE;
-}
-
-static void
-app_about (GSimpleAction *action,
-           GVariant      *parameter,
-           gpointer       user_data)
-{
-	GtkApplication *application = GTK_APPLICATION (user_data);
-	GList *windows;
-	GtkWindow *window;
-
-	windows = gtk_application_get_windows (application);
-	window = windows->data;
-
-	/* TODO show proper about dialogue */
-	gtk_show_about_dialog (window,
-	                       "program-name", "Rugby",
-	                       "license-type", GTK_LICENSE_MIT_X11,
-	                       NULL);
-}
-
-
-static void
-app_quit (GSimpleAction *action,
-          GVariant      *parameter,
-          gpointer       user_data)
-{
-	GApplication *application = G_APPLICATION (user_data);
-
-	g_application_quit (application);
-}
-
-static GActionEntry app_entries[] =
-{
-	{ "about", app_about, NULL, NULL, NULL },
-	{ "quit", app_quit, NULL, NULL, NULL }
-};
+G_DEFINE_TYPE (RugbyApplication, rugby_application, GTK_TYPE_APPLICATION);
 
 static void
-rugby_application_startup (GApplication *application)
+rugby_application_init (RugbyApplication *app)
 {
-	GtkBuilder *builder;
-	GError *err = NULL;
-
-	G_APPLICATION_CLASS (rugby_application_parent_class)->startup (application);
-
-	g_action_map_add_action_entries (G_ACTION_MAP (application), app_entries, G_N_ELEMENTS (app_entries), application);
-
-	builder = gtk_builder_new ();
-	if (!gtk_builder_add_from_resource (builder, "/uk/me/bcowan/rugby/interface.ui", &err))
-	{
-		g_error ("Error: %s", err->message);
-	}
-
-	gtk_application_set_app_menu (GTK_APPLICATION (application), G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
-	g_object_unref (builder);
 }
 
 static void
-rugby_application_activate (GApplication *self)
+rugby_application_activate (GApplication *app)
 {
-  	RugbyApplication *app = RUGBY_APPLICATION (self);
-	GtkBuilder *builder;
-	GError *err = NULL;
-	GtkWidget *score;
-	GtkWidget *tree;
-	GtkCellRenderer *renderer;
-	GtkTreeViewColumn *column;
-	GtkWidget *statusbar;
-	GtkWidget *window;
-	GtkCssProvider *provider;
-
-	builder = gtk_builder_new ();
-	if (!gtk_builder_add_from_resource (builder, "/uk/me/bcowan/rugby/interface.ui", &err))
-	{
-		g_error ("Error: %s", err->message);
-	}
-
-	score = GTK_WIDGET (gtk_builder_get_object (builder, "scorespin"));
-	g_signal_connect (score, "value-changed",
-	                  G_CALLBACK (scorespin_changed_cb), app);
-
-	app->tryfilter = GTK_WIDGET (gtk_builder_get_object (builder, "tryfilter"));
-	g_signal_connect (app->tryfilter, "toggled",
-	                  G_CALLBACK (tryfilter_toggled_cb), app);
-
-	app->tryscale = GTK_WIDGET (gtk_builder_get_object (builder, "tryscale"));
-	g_signal_connect (app->tryscale, "value-changed",
-	                  G_CALLBACK (scale_changed_cb), app);
-
-	app->kickfilter = GTK_WIDGET (gtk_builder_get_object (builder, "kickfilter"));
-	g_signal_connect (app->kickfilter, "toggled",
-	                  G_CALLBACK (kickfilter_toggled_cb), app);
-
-	app->kickscale = GTK_WIDGET (gtk_builder_get_object (builder, "kickscale"));
-	g_signal_connect (app->kickscale, "value-changed",
-	                  G_CALLBACK (scale_changed_cb), app);
-
-	tree = GTK_WIDGET (gtk_builder_get_object (builder, "treeview"));
-
-	/* Would be nice to use GtkBuilder */
-	renderer = rugby_cell_renderer_score_new ();
-	column = gtk_tree_view_column_new_with_attributes ("Score", renderer,
-	                                                   "tries", RUGBY_SCORE_STORE_TRIES,
-	                                                   "utries", RUGBY_SCORE_STORE_UTRIES,
-	                                                   "kicks", RUGBY_SCORE_STORE_KICKS,
-	                                                   NULL);
-	gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
-
-	/* Create a TreeModelFilter */
-	app->store = rugby_score_store_new ();
-	app->fmodel = gtk_tree_model_filter_new (GTK_TREE_MODEL (app->store), NULL);
-	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (app->fmodel),
-	                                        (GtkTreeModelFilterVisibleFunc) filter_func, app, NULL);
-	gtk_tree_view_set_model (GTK_TREE_VIEW (tree), app->fmodel);
-
-	statusbar = GTK_WIDGET (gtk_builder_get_object (builder, "status"));
-	g_signal_connect (app->store, "finished",
-	                  G_CALLBACK (store_finished_cb), statusbar);
-
-	/* init CSS */
-	provider = gtk_css_provider_new ();
-	gtk_css_provider_load_from_resource (provider, "/uk/me/bcowan/rugby/rugby.css");
-
-	gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
-	                                           GTK_STYLE_PROVIDER (provider),
-	                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
-	window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
-	gtk_window_set_application (GTK_WINDOW (window), GTK_APPLICATION (app));
-	gtk_widget_show_all (window);
-
-	g_object_unref (builder);
+    RugbyAppWindow *win = rugby_app_window_new (RUGBY_APPLICATION (app));
+    gtk_window_present (GTK_WINDOW (win));
 }
 
 static void
 rugby_application_class_init (RugbyApplicationClass *klass)
 {
-	GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
-
-	app_class->startup = rugby_application_startup;
-	app_class->activate = rugby_application_activate;
-}
-
-static void
-rugby_application_init (RugbyApplication *app)
-{
-
+    GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
+    app_class->activate = rugby_application_activate;
 }
 
-/**
- * rugby_application_new:
- *
- * Creates a #RugbyApplication. This is the main UI of the program
- *
- * Returns: a new #RugbyApplication
- */
 RugbyApplication *
 rugby_application_new (void)
 {
-	g_set_application_name ("Rugby");
-
-	return g_object_new (RUGBY_TYPE_APPLICATION,
-	                     "application-id", "uk.me.bcowan.Rugby",
-	                     NULL);
+    return g_object_new (RUGBY_TYPE_APPLICATION,
+                         "application-id", "uk.me.bcowan.rugby",
+                         NULL);
 }
diff --git a/src/rugby-score-store.c b/src/rugby-score-store.c
index a61882d..e297a83 100644
--- a/src/rugby-score-store.c
+++ b/src/rugby-score-store.c
@@ -74,7 +74,7 @@ rugby_score_store_class_init (RugbyScoreStoreClass *klass)
 	obj_class->set_property = rugby_score_store_set_property;
 
 	pspecs[PROP_SCORE] = g_param_spec_int ("score", "Score", "The score",
-	                                       0, 150, 0,
+	                                       0, 200, 0,
 	                                       G_PARAM_READWRITE);
 	g_object_class_install_property (obj_class, PROP_SCORE, pspecs[PROP_SCORE]);
 
@@ -188,7 +188,7 @@ rugby_score_store_set_score (RugbyScoreStore *store,
                              gint             score)
 {
 	g_return_if_fail (RUGBY_IS_SCORE_STORE (store));
-	g_return_if_fail (score >= 0 && score <= 150);
+	g_return_if_fail (score >= 0 && score <= 200);
 
 	store->score = score;
 	g_object_notify_by_pspec (G_OBJECT (store), pspecs[PROP_SCORE]);
-- 
GitLab