diff --git a/data/rugby.css b/data/rugby.css index 1652a3fdf5bc41a862e838459ed2ac61434b6fe3..daaa65170ecb95d737b2b06f0971d444c463ccb7 100644 --- a/data/rugby.css +++ b/data/rugby.css @@ -1,9 +1,9 @@ -.cell.level-cell.fill-block +.level-cell.fill-block { border-radius: 10px; } -.cell.level-cell.fill-block.score-try +.level-cell.fill-block.score-try { /* Scarlet red */ background-image: linear-gradient(to top, @@ -11,7 +11,7 @@ #cc0000); } -.cell.level-cell.fill-block.score-utry +.level-cell.fill-block.score-utry { /* Chameleon */ background-image: linear-gradient(to top, @@ -19,7 +19,7 @@ #73d216); } -.cell.level-cell.fill-block.score-kick +.level-cell.fill-block.score-kick { /* Butter */ background-image: linear-gradient(to top, diff --git a/src/meson.build b/src/meson.build index 27c4017bb277b14aa47a023f318cb04218724398..595a328cac70e97edd6ae5adb76e2ce61e26a357 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,6 +5,7 @@ sources = files( 'rugby-application.c', 'rugby-app-window.c', 'rugby-possibility.c', + 'rugby-possibility-widget.c', 'rugby-scoring.c' ) diff --git a/src/rugby-app-window.c b/src/rugby-app-window.c index e8fdcffdce9131f0cad8b09d0e2bc5e4ad3d5533..a56c1971445d736f4dcde9131aa17248ce1b6c43 100644 --- a/src/rugby-app-window.c +++ b/src/rugby-app-window.c @@ -21,6 +21,7 @@ #include "rugby-application.h" #include "rugby-app-window.h" #include "rugby-possibility.h" +#include "rugby-possibility-widget.h" #include "rugby-scoring.h" struct _RugbyAppWindow @@ -36,7 +37,7 @@ struct _RugbyAppWindow GtkWidget *listbox; }; -G_DEFINE_TYPE(RugbyAppWindow, rugby_app_window, GTK_TYPE_APPLICATION_WINDOW); +G_DEFINE_TYPE (RugbyAppWindow, rugby_app_window, GTK_TYPE_APPLICATION_WINDOW); static void scorespin_value_changed_cb (GtkSpinButton *spin, @@ -65,19 +66,8 @@ listbox_widget_func (gpointer item, gpointer user_data) { RugbyPossibility *possibility = RUGBY_POSSIBILITY (item); - RugbyAppWindow *self = RUGBY_APP_WINDOW (user_data); - gint tries, utries, kicks; - g_object_get (possibility, - "tries", &tries, - "utries", &utries, - "kicks", &kicks, - NULL); - - g_autofree gchar *text = - g_strdup_printf ("%d tries, %d unconverted tries, %d kicks", tries, utries, kicks); - - return gtk_label_new (text); + return rugby_possibility_widget_new (possibility); } static void diff --git a/src/rugby-possibility-widget.c b/src/rugby-possibility-widget.c new file mode 100644 index 0000000000000000000000000000000000000000..d1195b0a2aeb50f7497da7dfdcee687b12f15677 --- /dev/null +++ b/src/rugby-possibility-widget.c @@ -0,0 +1,219 @@ +#include "rugby-possibility-widget.h" + +struct _RugbyPossibilityWidget +{ + GtkDrawingArea parent_instance; + + RugbyPossibility *possibility; +}; + +G_DEFINE_TYPE (RugbyPossibilityWidget, rugby_possibility_widget, GTK_TYPE_DRAWING_AREA) + +enum +{ + PROP_0, + PROP_POSSIBILITY, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +#define FIXED_HEIGHT 20 + +static void +rugby_possibility_widget_dispose (GObject *object) +{ + RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (object); + + g_clear_object (&self->possibility); + + G_OBJECT_CLASS (rugby_possibility_widget_parent_class)->dispose (object); +} + +static void +rugby_possibility_widget_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (object); + + switch (prop_id) + { + case PROP_POSSIBILITY: + g_value_set_object (value, self->possibility); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +rugby_possibility_widget_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (object); + + switch (prop_id) + { + case PROP_POSSIBILITY: + self->possibility = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +rugby_possibility_widget_get_preferred_height (GtkWidget *widget, + gint *minimum_height, + gint *natural_height) +{ + if (minimum_height) + *minimum_height = FIXED_HEIGHT; + if (natural_height) + *natural_height = FIXED_HEIGHT; +} + +static void +render_bar (cairo_t *cr, + GtkStyleContext *context, + gint x, + gint y, + gint w, + gint h, + const gchar *style) +{ + gtk_style_context_save (context); + gtk_style_context_add_class (context, style); + gtk_render_background (context, cr, x, y, w, h); + gtk_style_context_restore (context); +} + +static gboolean +rugby_possibility_widget_draw (GtkWidget *widget, + cairo_t *cr) +{ + RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (widget); + + gint width = gtk_widget_get_allocated_width (widget); + gint height = gtk_widget_get_allocated_height (widget); + gint x = 0, y = 0; + + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_style_context_save (context); + gtk_style_context_add_class (context, "level-cell"); + + gtk_render_background (context, cr, x, y, width, height); + gtk_render_frame (context, cr, x, y, width, height); + + gint tries, utries, kicks; + + g_object_get (self->possibility, + "tries", &tries, + "utries", &utries, + "kicks", &kicks, + NULL); + gint score = tries * 7 + utries * 5 + kicks * 3; + + gtk_style_context_add_class (context, "fill-block"); + + // Tries + gint w = width / (score / 7.0); + for (int i = 0; i < tries; i++) + { + render_bar (cr, context, x, y, w, height, "score-try"); + x += w; + } + + // Unconverted tries + w = width / (score / 5.0); + for (int i = 0; i < utries; i++) + { + render_bar (cr, context, x, y, w, height, "score-utry"); + x += w; + } + + // Unconverted kicks + w = width / (score / 3.0); + for (int i = 0; i < kicks; i++) + { + render_bar (cr, context, x, y, w, height, "score-kick"); + x += w; + } + + gtk_style_context_restore (context); + + return TRUE; +} + +static void +rugby_possibility_widget_constructed (GObject *obj) +{ + RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (obj); + gint tries, utries, kicks; + g_autoptr (GString) tooltip = g_string_new (NULL); + + g_object_get (self->possibility, + "tries", &tries, + "utries", &utries, + "kicks", &kicks, + NULL); + + if (tries > 0 || utries > 0) + g_string_append_printf (tooltip, "%d tries, %d converted", + tries + utries, tries); + + if (kicks > 0) + { + if (tooltip->len == 0) + g_string_append_printf (tooltip, "%d kicks", kicks); + else + g_string_append_printf (tooltip, ", %d kicks", kicks); + } + + gtk_widget_set_tooltip_text (GTK_WIDGET (self), tooltip->str); + + G_OBJECT_CLASS (rugby_possibility_widget_parent_class)->constructed (obj); +} + +static void +rugby_possibility_widget_class_init (RugbyPossibilityWidgetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->constructed = rugby_possibility_widget_constructed; + object_class->dispose = rugby_possibility_widget_dispose; + object_class->get_property = rugby_possibility_widget_get_property; + object_class->set_property = rugby_possibility_widget_set_property; + + widget_class->draw = rugby_possibility_widget_draw; + widget_class->get_preferred_height = rugby_possibility_widget_get_preferred_height; + + + properties[PROP_POSSIBILITY] = g_param_spec_object ("possibility", + "Possibility", + "Possibility to be represented", + RUGBY_TYPE_POSSIBILITY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, + N_PROPS, + properties); +} + +static void +rugby_possibility_widget_init (RugbyPossibilityWidget *self) +{ +} + +GtkWidget * +rugby_possibility_widget_new (RugbyPossibility *possibility) +{ + return g_object_new (RUGBY_TYPE_POSSIBILITY_WIDGET, + "possibility", possibility, + NULL); +} diff --git a/src/rugby-possibility-widget.h b/src/rugby-possibility-widget.h new file mode 100644 index 0000000000000000000000000000000000000000..44943e2fa3f0745e2bd6adb0908719dcdb97ada9 --- /dev/null +++ b/src/rugby-possibility-widget.h @@ -0,0 +1,33 @@ +/* rugby-possibility-widget.h + * + * Copyright © 2018 Bruce Cowan <bruce@bcowan.eu> + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This file 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <gtk/gtk.h> + +#include "rugby-possibility.h" + +G_BEGIN_DECLS + +#define RUGBY_TYPE_POSSIBILITY_WIDGET (rugby_possibility_widget_get_type()) + +G_DECLARE_FINAL_TYPE (RugbyPossibilityWidget, rugby_possibility_widget, RUGBY, POSSIBILITY_WIDGET, GtkDrawingArea) + +GtkWidget * rugby_possibility_widget_new (RugbyPossibility *possibility); + +G_END_DECLS