/* Copyright (C) 2006 Paolo Borelli
* Copyright (C) 2012-2021 MATE Developers
*
* This file is part of MATE Utils.
*
* MATE Utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MATE Utils 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MATE Utils. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include "baobab-cell-renderer-progress.h"
enum
{
PROP_0,
PROP_PERC
};
struct _BaobabCellRendererProgressPrivate
{
double perc;
};
G_DEFINE_TYPE_WITH_PRIVATE (BaobabCellRendererProgress, baobab_cell_renderer_progress, GTK_TYPE_CELL_RENDERER)
static void
baobab_cell_renderer_progress_init (BaobabCellRendererProgress *cellprogress)
{
cellprogress->priv = baobab_cell_renderer_progress_get_instance_private (cellprogress);
cellprogress->priv->perc = 0;
gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (cellprogress), 4, 4);
}
GtkCellRenderer*
baobab_cell_renderer_progress_new (void)
{
return g_object_new (BAOBAB_TYPE_CELL_RENDERER_PROGRESS, NULL);
}
static void
baobab_cell_renderer_progress_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
switch (param_id)
{
case PROP_PERC:
g_value_set_double (value, cellprogress->priv->perc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
baobab_cell_renderer_progress_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
switch (param_id)
{
case PROP_PERC:
cellprogress->priv->perc = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
/* we simply have a fixed size */
#define FIXED_WIDTH 70
#define FIXED_HEIGHT 8
static void
baobab_cell_renderer_progress_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height)
{
gint calc_width;
gint calc_height;
gint xpad;
gint ypad;
gfloat xalign;
gfloat yalign;
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
calc_width = (gint) xpad * 2 + FIXED_WIDTH;
calc_height = (gint) ypad * 2 + FIXED_HEIGHT;
if (width)
*width = calc_width;
if (height)
*height = calc_height;
if (cell_area)
{
gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
if (x_offset)
{
*x_offset = (gint) (xalign * (gfloat) (cell_area->width - calc_width));
*x_offset = MAX (*x_offset, 0);
}
if (y_offset)
{
*y_offset = (gint) (yalign * (gfloat) (cell_area->height - calc_height));
*y_offset = MAX (*y_offset, 0);
}
}
}
static void
set_color_according_to_perc (cairo_t *cr, double value)
{
static GdkRGBA red;
static GdkRGBA yellow;
static GdkRGBA green;
static gboolean colors_initialized = FALSE;
if (!colors_initialized)
{
/* hardcoded tango colors */
gdk_rgba_parse (&red, "#cc0000");
gdk_rgba_parse (&yellow, "#edd400");
gdk_rgba_parse (&green, "#73d216");
colors_initialized = TRUE;
}
if (value <= 0)
{
cairo_set_source_rgb (cr, 1, 1, 1);
return;
}
else if (value <= 33.33)
{
gdk_cairo_set_source_rgba (cr, &green);
return;
}
else if (value <= 66.66)
{
gdk_cairo_set_source_rgba (cr, &yellow);
return;
}
else if (value <= 100.0)
{
gdk_cairo_set_source_rgba (cr, &red);
return;
}
else
g_assert_not_reached ();
}
static void
baobab_cell_renderer_progress_render (GtkCellRenderer *cell,
cairo_t *cr,
GtkWidget *widget,
const GdkRectangle *background_area,
const GdkRectangle *cell_area,
guint flags)
{
BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (cell);
gint x, y, w, h, perc_w;
gboolean is_rtl;
gint xpad;
gint ypad;
GtkStyle *style;
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
x = cell_area->x + xpad;
y = cell_area->y + ypad;
w = cell_area->width - xpad * 2;
h = cell_area->height - ypad * 2;
/*
* we always use a white bar with black
* border and green/yellow/red progress...
* I know it's not theme friendly, but we don't
* want a plain progress bar
*/
cairo_rectangle (cr, x, y, w, h);
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_fill (cr);
style = gtk_widget_get_style (widget);
x += style->xthickness;
y += style->ythickness;
w -= style->xthickness * 2;
h -= style->ythickness * 2;
cairo_rectangle (cr, x, y, w, h);
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_fill (cr);
perc_w = (gint) (w * MAX (0, cellprogress->priv->perc) / 100);
cairo_rectangle (cr, is_rtl ? (x + w - perc_w) : x, y, perc_w, h);
set_color_according_to_perc (cr, cellprogress->priv->perc);
cairo_fill (cr);
}
static void
baobab_cell_renderer_progress_class_init (BaobabCellRendererProgressClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
object_class->get_property = baobab_cell_renderer_progress_get_property;
object_class->set_property = baobab_cell_renderer_progress_set_property;
cell_class->get_size = baobab_cell_renderer_progress_get_size;
cell_class->render = baobab_cell_renderer_progress_render;
g_object_class_install_property (object_class,
PROP_PERC,
g_param_spec_double ("perc",
"percentage",
"precentage",
-1, 100, 0,
G_PARAM_READWRITE));
}