Skip to content
Snippets Groups Projects
rugby-possibility-widget.c 6.3 KiB
Newer Older
Bruce Cowan's avatar
Bruce Cowan committed
/*
Bruce Cowan's avatar
Bruce Cowan committed
 * SPDX-FileCopyrightText: 2018-2021 Bruce Cowan <bruce@bcowan.me.uk>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
Bruce Cowan's avatar
Bruce Cowan committed
#include "config.h"
#include "rugby-possibility-widget.h"

struct _RugbyPossibilityWidget
{
    GtkDrawingArea parent_instance;

Bruce Cowan's avatar
Bruce Cowan committed
    GSettings *settings;
    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];

static void
rugby_possibility_widget_dispose (GObject *object)
{
    RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (object);

Bruce Cowan's avatar
Bruce Cowan committed
    g_clear_object (&self->settings);
    g_clear_object (&self->possibility);

    G_OBJECT_CLASS (rugby_possibility_widget_parent_class)->dispose (object);
}

static void
rugby_possibility_widget_get_property (GObject    *object,
Bruce Cowan's avatar
Bruce Cowan committed
                                       unsigned    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,
Bruce Cowan's avatar
Bruce Cowan committed
                                       unsigned      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
render_bar (cairo_t         *cr,
            GtkStyleContext *context,
Bruce Cowan's avatar
Bruce Cowan committed
            double           x,
            double           y,
            double           w,
            double           h,
            const char      *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);
}

Bruce Cowan's avatar
Bruce Cowan committed
static void
draw_func (GtkDrawingArea        *drawing_area,
           cairo_t               *cr,
           int                    width,
           int                    height,
           G_GNUC_UNUSED gpointer user_data)
Bruce Cowan's avatar
Bruce Cowan committed
    RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (drawing_area);
Bruce Cowan's avatar
Bruce Cowan committed
    GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (drawing_area));
    gtk_widget_add_css_class (GTK_WIDGET (drawing_area), "possibility");
Bruce Cowan's avatar
Bruce Cowan committed
    double x = 0.0;
    gtk_render_background (context, cr, x, 0.0, width, height);
    int try_points = g_settings_get_int (self->settings, "try-points");
    int utry_points = g_settings_get_int (self->settings, "utry-points");
    int kick_points = g_settings_get_int (self->settings, "kick-points");
Bruce Cowan's avatar
Bruce Cowan committed
    int tries, utries, kicks;

    g_object_get (self->possibility,
                  "tries", &tries,
                  "utries", &utries,
                  "kicks", &kicks,
                  NULL);
Bruce Cowan's avatar
Bruce Cowan committed
    int score = tries * try_points + utries * utry_points + kicks * kick_points;
Bruce Cowan's avatar
Bruce Cowan committed
    gtk_widget_add_css_class (GTK_WIDGET (drawing_area), "score-block");
Bruce Cowan's avatar
Bruce Cowan committed
    double w = width / (score / (double) try_points);
    for (int i = 0; i < tries; i++)
    {
Bruce Cowan's avatar
Bruce Cowan committed
        render_bar (cr, context, x, 0.0, w, height, "try");
Bruce Cowan's avatar
Bruce Cowan committed
    w = width / (score / (double) utry_points);
    for (int i = 0; i < utries; i++)
    {
Bruce Cowan's avatar
Bruce Cowan committed
        render_bar (cr, context, x, 0.0, w, height, "utry");
Bruce Cowan's avatar
Bruce Cowan committed
    w = width / (score / (double) kick_points);
    for (int i = 0; i < kicks; i++)
    {
Bruce Cowan's avatar
Bruce Cowan committed
        render_bar (cr, context, x, 0.0, w, height, "kick");
        x += w;
    }
}

static void
rugby_possibility_widget_constructed (GObject *obj)
{
    RugbyPossibilityWidget *self = RUGBY_POSSIBILITY_WIDGET (obj);
Bruce Cowan's avatar
Bruce Cowan committed
    int 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);

    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;

    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
Bruce Cowan's avatar
Bruce Cowan committed
rugby_possibility_widget_init (RugbyPossibilityWidget *self)
Bruce Cowan's avatar
Bruce Cowan committed
    gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self),
                                    draw_func, NULL, NULL);

    self->settings = g_settings_new ("uk.me.bcowan.Rugby");
}

GtkWidget *
rugby_possibility_widget_new (RugbyPossibility *possibility)
{
    return g_object_new (RUGBY_TYPE_POSSIBILITY_WIDGET,
                         "possibility", possibility,
                         NULL);
}