#include "rugby-application.h" #include "rugby-cell-renderer-score.h" #include "rugby-score-store.h" #include "rugby-scoring.h" struct _RugbyApplicationPrivate { GtkWidget *tryfilter; GtkWidget *tryscale; GtkWidget *kickfilter; GtkWidget *kickscale; RugbyScoreStore *store; GtkTreeModel *fmodel; }; 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->priv->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->priv->tryscale), 0.0, max_tries); max_kicks = MAX (rugby_scoring_get_max_kicks (score), 1.0); gtk_range_set_range (GTK_RANGE (app->priv->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->priv->tryscale, TRUE); else gtk_widget_set_sensitive (app->priv->tryscale, FALSE); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->priv->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->priv->kickscale, TRUE); else gtk_widget_set_sensitive (app->priv->kickscale, FALSE); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->priv->fmodel)); } static void scale_changed_cb (GtkRange *range, RugbyApplication *app) { gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (app->priv->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) { RugbyApplicationPrivate *priv = app->priv; gint ctries, ckicks; /* TODO fix these crap names */ gint tries, utries, kicks; gboolean try, kick; ctries = (gint) gtk_range_get_value (GTK_RANGE (app->priv->tryscale)); ckicks = (gint) gtk_range_get_value (GTK_RANGE (app->priv->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 (priv->tryfilter)); kick = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->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 } }; static void rugby_application_startup (GApplication *application) { 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 *app) { RugbyApplicationPrivate *priv = RUGBY_APPLICATION (app)->priv; 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); priv->tryfilter = GTK_WIDGET (gtk_builder_get_object (builder, "tryfilter")); g_signal_connect (priv->tryfilter, "toggled", G_CALLBACK (tryfilter_toggled_cb), app); priv->tryscale = GTK_WIDGET (gtk_builder_get_object (builder, "tryscale")); g_signal_connect (priv->tryscale, "value-changed", G_CALLBACK (scale_changed_cb), app); priv->kickfilter = GTK_WIDGET (gtk_builder_get_object (builder, "kickfilter")); g_signal_connect (priv->kickfilter, "toggled", G_CALLBACK (kickfilter_toggled_cb), app); priv->kickscale = GTK_WIDGET (gtk_builder_get_object (builder, "kickscale")); g_signal_connect (priv->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 */ priv->store = rugby_score_store_new (); priv->fmodel = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->store), NULL); gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->fmodel), (GtkTreeModelFilterVisibleFunc) filter_func, app, NULL); gtk_tree_view_set_model (GTK_TREE_VIEW (tree), priv->fmodel); statusbar = GTK_WIDGET (gtk_builder_get_object (builder, "status")); g_signal_connect (priv->store, "finished", G_CALLBACK (store_finished_cb), statusbar); /* init CSS */ provider = gtk_css_provider_new (); /* TODO load this from resource */ gtk_css_provider_load_from_path (provider, "rugby.css", NULL); 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); } 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; g_type_class_add_private (klass, sizeof (RugbyApplicationPrivate)); } static void rugby_application_init (RugbyApplication *app) { app->priv = G_TYPE_INSTANCE_GET_PRIVATE (app, RUGBY_TYPE_APPLICATION, RugbyApplicationPrivate); } /** * rugby_application_new: * * Creates a #RugbyApplication. This is the main UI of the program * * Returns: a new #RugbyApplication */ RugbyApplication * rugby_application_new (void) { g_type_init (); g_set_application_name ("Rugby"); return g_object_new (RUGBY_TYPE_APPLICATION, "application-id", "uk.me.bcowan.Rugby", NULL); }