Skip to content
Snippets Groups Projects
rugby-possibility-widget.c 6.33 KiB
Newer Older
#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,
Bruce Cowan's avatar
Bruce Cowan committed
            gdouble          x,
            gdouble          y,
            gdouble          w,
            gdouble          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);

Bruce Cowan's avatar
Bruce Cowan committed
    gdouble width = gtk_widget_get_allocated_width (widget);
    gdouble height = gtk_widget_get_allocated_height (widget);
    gdouble x = 0.0, y = 0.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
Bruce Cowan's avatar
Bruce Cowan committed
    gdouble 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);
}