[gnome-disk-utility/ata-smart-ui-rework] Iterate a bit more over the ATA SMART graphs
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-disk-utility/ata-smart-ui-rework] Iterate a bit more over the ATA SMART graphs
- Date: Wed, 24 Jun 2009 22:10:16 +0000 (UTC)
commit 5b128f0393941ff7ddd0220a4f4a5c808232f4b3
Author: David Zeuthen <davidz redhat com>
Date: Wed Jun 24 18:06:08 2009 -0400
Iterate a bit more over the ATA SMART graphs
ZOMG, we have legend text
http://people.freedesktop.org/~david/ata-smart-rework-wip3.png
src/gdu-gtk/Makefile.am | 28 ++-
src/gdu-gtk/gdu-ata-smart-attribute-dialog.c | 243 -----------
src/gdu-gtk/gdu-ata-smart-attribute-dialog.h | 63 ---
src/gdu-gtk/gdu-ata-smart-dialog.c | 143 +++++--
src/gdu-gtk/gdu-curve.c | 463 +++++++++++++++++++++
src/gdu-gtk/gdu-curve.h | 107 +++++
src/gdu-gtk/gdu-graph.c | 572 +++++++++++++++-----------
src/gdu-gtk/gdu-graph.h | 26 +-
src/gdu-gtk/gdu-gtk-enums.h | 38 ++
src/gdu-gtk/gdu-gtk-enumtypes.c.template | 39 ++
src/gdu-gtk/gdu-gtk-enumtypes.h.template | 24 ++
src/gdu-gtk/gdu-gtk-types.h | 5 +-
src/gdu-gtk/gdu-gtk.h | 3 +-
13 files changed, 1160 insertions(+), 594 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index b122ac5..d2a018c 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -1,26 +1,40 @@
NULL =
+gdu-gtk-enumtypes.h: gdu-gtk-enums.h gdu-gtk-enumtypes.h.template
+ ( top_builddir=`cd $(top_builddir) && pwd`; \
+ cd $(srcdir) && glib-mkenums --template gdu-gtk-enumtypes.h.template gdu-gtk-enums.h ) > \
+ gdu-gtk-enumtypes.h.tmp && mv gdu-gtk-enumtypes.h.tmp gdu-gtk-enumtypes.h
+
+gdu-gtk-enumtypes.c: gdu-gtk-enums.h gdu-gtk-enumtypes.c.template
+ ( top_builddir=`cd $(top_builddir) && pwd`; \
+ cd $(srcdir) && glib-mkenums --template gdu-gtk-enumtypes.c.template gdu-gtk-enums.h ) > \
+ gdu-gtk-enumtypes.c.tmp && mv gdu-gtk-enumtypes.c.tmp gdu-gtk-enumtypes.c
+
lib_LTLIBRARIES=libgdu-gtk.la
libgdu_gtkincludedir=$(includedir)/gnome-disk-utility/gdu-gtk
libgdu_gtkinclude_HEADERS = \
gdu-gtk.h \
+ gdu-gtk-enums.h \
+ gdu-gtk-enumtypes.h \
gdu-gtk-types.h \
gdu-time-label.h \
gdu-ata-smart-dialog.h \
+ gdu-curve.h \
gdu-graph.h \
- gdu-ata-smart-attribute-dialog.h \
$(NULL)
libgdu_gtk_la_SOURCES = \
gdu-gtk.h gdu-gtk.c \
gdu-gtk-types.h \
+ gdu-gtk-enums.h \
+ gdu-gtk-enumtypes.h gdu-gtk-enumtypes.c \
gdu-time-label.h gdu-time-label.c \
gdu-ata-smart-dialog.h gdu-ata-smart-dialog.c \
+ gdu-curve.h gdu-curve.c \
gdu-graph.h gdu-graph.c \
- gdu-ata-smart-attribute-dialog.h gdu-ata-smart-attribute-dialog.c \
$(NULL)
libgdu_gtk_la_CPPFLAGS = \
@@ -60,8 +74,18 @@ libgdu_gtk_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gdu-gtk.pc
+BUILT_SOURCES = \
+ gdu-gtk-enumtypes.c \
+ gdu-gtk-enumtypes.h \
+ $(NULL)
+
CLEANFILES = $(BUILT_SOURCES) $(pkgconfig_DATA)
+EXTRADIST = \
+ gdu-gtk-enumtypes.h.template \
+ gdu-gtk-enumtypes.c.template \
+ $(NULL)
+
clean-local :
rm -f *~ $(BUILT_SOURCES)
diff --git a/src/gdu-gtk/gdu-ata-smart-dialog.c b/src/gdu-gtk/gdu-ata-smart-dialog.c
index e091f79..50339cb 100644
--- a/src/gdu-gtk/gdu-ata-smart-dialog.c
+++ b/src/gdu-gtk/gdu-ata-smart-dialog.c
@@ -23,9 +23,9 @@
#include <glib/gi18n.h>
#include "gdu-time-label.h"
+#include "gdu-curve.h"
#include "gdu-graph.h"
#include "gdu-ata-smart-dialog.h"
-#include "gdu-ata-smart-attribute-dialog.h"
struct GduAtaSmartDialogPrivate
{
@@ -166,13 +166,17 @@ selection_changed (GtkTreeSelection *tree_selection,
g_debug ("selected %s", attr_name);
GArray *cur_points;
+ GArray *worst_points;
+ GArray *threshold_points;
GArray *raw_points;
GArray *band_points;
GList *l;
guint64 now;
- cur_points = g_array_new (FALSE, FALSE, sizeof (GduGraphPoint));
- raw_points = g_array_new (FALSE, FALSE, sizeof (GduGraphPoint));
- band_points = g_array_new (FALSE, FALSE, sizeof (GduGraphPoint));
+ cur_points = g_array_new (FALSE, FALSE, sizeof (GduPoint));
+ worst_points = g_array_new (FALSE, FALSE, sizeof (GduPoint));
+ threshold_points = g_array_new (FALSE, FALSE, sizeof (GduPoint));
+ raw_points = g_array_new (FALSE, FALSE, sizeof (GduPoint));
+ band_points = g_array_new (FALSE, FALSE, sizeof (GduPoint));
guint64 raw_min;
guint64 raw_max;
@@ -263,17 +267,15 @@ selection_changed (GtkTreeSelection *tree_selection,
GduAtaSmartHistoricalData *data = GDU_ATA_SMART_HISTORICAL_DATA (l->data);
GduAtaSmartAttribute *attr;
guint64 time_collected;
- GduGraphPoint point;
+ GduPoint point;
guint64 age;
gboolean use_point;
- memset (&point, '\0', sizeof (GduGraphPoint));
+ memset (&point, '\0', sizeof (GduPoint));
time_collected = gdu_ata_smart_historical_data_get_time_collected (data);
age = now - time_collected;
- g_debug ("age = %d", (gint) age);
-
/* skip old points, except if the following point is not too old */
use_point = FALSE;
if (age < timespan) {
@@ -291,20 +293,30 @@ selection_changed (GtkTreeSelection *tree_selection,
if (use_point) {
- point.x = 1.0f - ((gfloat) age) / ((gfloat) timespan);
+ point.x = 1.0 - ((gdouble) age) / ((gdouble) timespan);
attr = gdu_ata_smart_historical_data_get_attribute (data, attr_name);
if (attr != NULL) {
guint current;
+ guint worst;
+ guint threshold;
guint64 raw;
current = gdu_ata_smart_attribute_get_current (attr);
+ worst = gdu_ata_smart_attribute_get_worst (attr);
+ threshold = gdu_ata_smart_attribute_get_threshold (attr);
raw = gdu_ata_smart_attribute_get_pretty_value (attr);
point.y = current / 255.0f;
g_array_append_val (cur_points, point);
- point.y = ((gfloat) (raw - raw_min)) / ((gfloat) (raw_max - raw_min));
+ point.y = worst / 255.0f;
+ g_array_append_val (worst_points, point);
+
+ point.y = threshold / 255.0f;
+ g_array_append_val (threshold_points, point);
+
+ point.y = ((gdouble) (raw - raw_min)) / ((gdouble) (raw_max - raw_min));
g_array_append_val (raw_points, point);
g_object_unref (attr);
@@ -318,12 +330,17 @@ selection_changed (GtkTreeSelection *tree_selection,
band_start = last_age - tolerance;
band_end = age + tolerance;
- point.x = 1.0f - band_start / ((gfloat) timespan);
- point.y = 0;
+ point.x = 1.0 - band_start / ((gdouble) timespan);
+ point.y = 1.0;
+ g_array_append_val (band_points, point);
+
+ point.x = 1.0 - band_end / ((gdouble) timespan);
+ point.y = 1.0;
g_array_append_val (band_points, point);
- point.x = 1.0f - band_end / ((gfloat) timespan);
- point.y = 0;
+ /* close the segment */
+ point.x = G_MAXDOUBLE;
+ point.y = G_MAXDOUBLE;
g_array_append_val (band_points, point);
}
}
@@ -331,26 +348,92 @@ selection_changed (GtkTreeSelection *tree_selection,
last_age = age;
}
- GdkColor cur_color = { 0, 0x8c00, 0xb000, 0xd700};
- GdkColor raw_color = { 0, 0xfc00, 0xaf00, 0x3e00};
- GdkColor band_color = { 0, 0x4000, 0x4000, 0x4000};
+#define GDU_COLOR_FROM_HEX(argb_hex, alpha) \
+ { \
+ (((argb_hex) >> 16)&0xff) / 255.0, \
+ (((argb_hex) >> 8)&0xff) / 255.0, \
+ (((argb_hex) >> 0)&0xff) / 255.0, \
+ alpha \
+ }
- gdu_graph_set_curve (GDU_GRAPH (dialog->priv->graph),
+ /* see http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines for colors
+ */
+ GduColor raw_color = GDU_COLOR_FROM_HEX (0xfcaf3e, 255.0); /* orange */
+ GduColor cur_color = GDU_COLOR_FROM_HEX (0x729fcf, 255.0); /* sky blue */
+ GduColor worst_color = GDU_COLOR_FROM_HEX (0xad7fa8, 255.0); /* plum */
+ GduColor threshold_color = GDU_COLOR_FROM_HEX (0xef2929, 255.0); /* scarlet red */
+ GduColor band_color = { 0.00, 0.00, 0.00, 0.0 };
+ GduColor band_fill_color = { 0.85, 0.85, 0.85, 0.5 };
+ GduCurve *c;
+
+ /* add graphs in order */
+ gint z_order = 0;
+
+ /* first the bands representing no data */
+ c = gdu_curve_new ();
+ gdu_curve_set_legend (c, _("No data"));
+ gdu_curve_set_z_order (c, z_order++);
+ gdu_curve_set_points (c, band_points);
+ gdu_curve_set_color (c, &band_color);
+ gdu_curve_set_fill_color (c, &band_fill_color);
+ gdu_curve_set_flags (c, GDU_CURVE_FLAGS_FILLED | GDU_CURVE_FLAGS_FADE_EDGES);
+ gdu_graph_add_curve (GDU_GRAPH (dialog->priv->graph),
+ "band",
+ c);
+ g_object_unref (c);
+
+ /* then worst */
+ c = gdu_curve_new ();
+ gdu_curve_set_legend (c, _("Worst"));
+ gdu_curve_set_z_order (c, z_order++);
+ gdu_curve_set_points (c, worst_points);
+ gdu_curve_set_color (c, &worst_color);
+ gdu_curve_set_width (c, 1.0);
+ gdu_graph_add_curve (GDU_GRAPH (dialog->priv->graph),
+ "worst",
+ c);
+ g_object_unref (c);
+
+ /* then threshold */
+ c = gdu_curve_new ();
+ gdu_curve_set_legend (c, _("Treshold"));
+ gdu_curve_set_z_order (c, z_order++);
+ gdu_curve_set_points (c, threshold_points);
+ gdu_curve_set_color (c, &threshold_color);
+ gdu_curve_set_width (c, 1.0);
+ gdu_graph_add_curve (GDU_GRAPH (dialog->priv->graph),
+ "threshold",
+ c);
+ g_object_unref (c);
+
+ /* then current */
+ c = gdu_curve_new ();
+ gdu_curve_set_legend (c, _("Current"));
+ gdu_curve_set_z_order (c, z_order++);
+ gdu_curve_set_points (c, cur_points);
+ gdu_curve_set_color (c, &cur_color);
+ gdu_curve_set_width (c, 2.0);
+ gdu_graph_add_curve (GDU_GRAPH (dialog->priv->graph),
"current",
- &cur_color,
- cur_points);
-
- gdu_graph_set_curve (GDU_GRAPH (dialog->priv->graph),
+ c);
+ g_object_unref (c);
+
+
+ /* then raw */
+ c = gdu_curve_new ();
+ gdu_curve_set_legend (c, _("Raw")); /* TODO: units? */
+ gdu_curve_set_z_order (c, z_order++);
+ gdu_curve_set_points (c, raw_points);
+ gdu_curve_set_color (c, &raw_color);
+ gdu_curve_set_width (c, 2.0);
+ gdu_graph_add_curve (GDU_GRAPH (dialog->priv->graph),
"raw",
- &raw_color,
- raw_points);
-
- gdu_graph_set_band (GDU_GRAPH (dialog->priv->graph),
- "discontinuity",
- &band_color,
- band_points);
+ c);
+ g_object_unref (c);
g_array_unref (cur_points);
+ g_array_unref (worst_points);
+ g_array_unref (threshold_points);
g_array_unref (raw_points);
g_array_unref (band_points);
@@ -415,7 +498,7 @@ gdu_ata_smart_dialog_constructed (GObject *object)
graph = gdu_graph_new ();
dialog->priv->graph = graph;
- gtk_widget_set_size_request (graph, 480, 180);
+ gtk_widget_set_size_request (graph, 480, 250);
gtk_box_pack_start (GTK_BOX (hbox), graph, TRUE, TRUE, 0);
const gchar *time_axis[7];
diff --git a/src/gdu-gtk/gdu-curve.c b/src/gdu-gtk/gdu-curve.c
new file mode 100644
index 0000000..cc7a5a0
--- /dev/null
+++ b/src/gdu-gtk/gdu-curve.c
@@ -0,0 +1,463 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-curve.c
+ *
+ * Copyright (C) 2009 David Zeuthen
+ *
+ * This library 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <math.h>
+
+#include <gdu-gtk/gdu-gtk-enumtypes.h>
+
+#include "gdu-curve.h"
+
+struct GduCurvePrivate
+{
+ GduCurveFlags flags;
+ GArray *points;
+ gint z_order;
+ GduColor *color;
+ GduColor *fill_color;
+ gdouble width;
+ gchar *legend;
+};
+
+G_DEFINE_TYPE (GduCurve, gdu_curve, G_TYPE_OBJECT)
+
+enum
+{
+ PROP_0,
+ PROP_FLAGS,
+ PROP_POINTS,
+ PROP_Z_ORDER,
+ PROP_COLOR,
+ PROP_FILL_COLOR,
+ PROP_WIDTH,
+ PROP_LEGEND,
+};
+
+static void
+gdu_curve_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GduCurve *curve = GDU_CURVE (object);
+
+ switch (prop_id) {
+ case PROP_FLAGS:
+ gdu_curve_set_flags (curve, g_value_get_flags (value));
+ break;
+
+ case PROP_POINTS:
+ gdu_curve_set_points (curve, g_value_get_boxed (value));
+ break;
+
+ case PROP_Z_ORDER:
+ gdu_curve_set_z_order (curve, g_value_get_int (value));
+ break;
+
+ case PROP_COLOR:
+ gdu_curve_set_color (curve, g_value_get_boxed (value));
+ break;
+
+ case PROP_FILL_COLOR:
+ gdu_curve_set_fill_color (curve, g_value_get_boxed (value));
+ break;
+
+ case PROP_WIDTH:
+ gdu_curve_set_width (curve, g_value_get_double (value));
+ break;
+
+ case PROP_LEGEND:
+ gdu_curve_set_legend (curve, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_curve_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GduCurve *curve = GDU_CURVE (object);
+
+ switch (prop_id) {
+ case PROP_FLAGS:
+ g_value_set_flags (value, gdu_curve_get_flags (curve));
+ break;
+
+ case PROP_POINTS:
+ g_value_set_boxed (value, gdu_curve_get_points (curve));
+ break;
+
+ case PROP_Z_ORDER:
+ g_value_set_int (value, gdu_curve_get_z_order (curve));
+ break;
+
+ case PROP_COLOR:
+ g_value_set_boxed (value, gdu_curve_get_color (curve));
+ break;
+
+ case PROP_FILL_COLOR:
+ g_value_set_boxed (value, gdu_curve_get_fill_color (curve));
+ break;
+
+ case PROP_WIDTH:
+ g_value_set_double (value, gdu_curve_get_width (curve));
+ break;
+
+ case PROP_LEGEND:
+ g_value_set_string (value, gdu_curve_get_legend (curve));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_curve_finalize (GObject *object)
+{
+ GduCurve *curve = GDU_CURVE (object);
+
+ if (curve->priv->color != NULL)
+ gdu_color_free (curve->priv->color);
+ if (curve->priv->fill_color != NULL)
+ gdu_color_free (curve->priv->fill_color);
+ if (curve->priv->points != NULL)
+ g_array_unref (curve->priv->points);
+
+ g_free (curve->priv->legend);
+
+ if (G_OBJECT_CLASS (gdu_curve_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (gdu_curve_parent_class)->finalize (object);
+}
+
+static void
+gdu_curve_constructed (GObject *object)
+{
+ GduCurve *curve = GDU_CURVE (object);
+
+ /* default to an orange color if not set */
+ if (curve->priv->color == NULL) {
+ GduColor orange = { 0.5, 0.7, 0.85, 1.0 };
+ curve->priv->color = gdu_color_dup (&orange);
+ }
+
+ if (G_OBJECT_CLASS (gdu_curve_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_curve_parent_class)->constructed (object);
+}
+
+static void
+gdu_curve_class_init (GduCurveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gdu_curve_finalize;
+ gobject_class->constructed = gdu_curve_constructed;
+ gobject_class->set_property = gdu_curve_set_property;
+ gobject_class->get_property = gdu_curve_get_property;
+
+ g_type_class_add_private (klass, sizeof (GduCurvePrivate));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FLAGS,
+ g_param_spec_flags ("flags",
+ _("Flags"),
+ _("The flags for the curve"),
+ GDU_TYPE_CURVE_FLAGS,
+ GDU_CURVE_FLAGS_NONE,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class,
+ PROP_POINTS,
+ g_param_spec_boxed ("points",
+ _("Points"),
+ _("The points of the curve"),
+ G_TYPE_ARRAY,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_Z_ORDER,
+ g_param_spec_int ("z-order",
+ _("Z order"),
+ _("Z order of the curve"),
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class,
+ PROP_COLOR,
+ g_param_spec_boxed ("color",
+ _("Color"),
+ _("The color of the curve"),
+ GDU_TYPE_COLOR,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FILL_COLOR,
+ g_param_spec_boxed ("fill-color",
+ _("Fill Color"),
+ _("The color of the interior of the curve"),
+ GDU_TYPE_COLOR,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_WIDTH,
+ g_param_spec_double ("width",
+ _("Width"),
+ _("The width of the line for the curve"),
+ 0.0,
+ G_MAXDOUBLE,
+ 1.0,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LEGEND,
+ g_param_spec_string ("legend",
+ _("Legend"),
+ _("The text to show in the legend"),
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT));
+
+}
+
+static void
+gdu_curve_init (GduCurve *curve)
+{
+ curve->priv = G_TYPE_INSTANCE_GET_PRIVATE (curve, GDU_TYPE_CURVE, GduCurvePrivate);
+}
+
+GduCurve *
+gdu_curve_new (void)
+{
+ return GDU_CURVE (g_object_new (GDU_TYPE_CURVE, NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+GduCurveFlags
+gdu_curve_get_flags (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), G_MAXINT);
+ return curve->priv->flags;
+}
+
+GArray *
+gdu_curve_get_points (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), NULL);
+ return curve->priv->points;
+}
+
+gint
+gdu_curve_get_z_order (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), G_MAXINT);
+ return curve->priv->z_order;
+}
+
+GduColor *
+gdu_curve_get_color (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), NULL);
+ return curve->priv->color;
+}
+
+GduColor *
+gdu_curve_get_fill_color (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), NULL);
+ return curve->priv->fill_color;
+}
+
+gdouble
+gdu_curve_get_width (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), -G_MAXDOUBLE);
+ return curve->priv->width;
+}
+
+const gchar *
+gdu_curve_get_legend (GduCurve *curve)
+{
+ g_return_val_if_fail (GDU_IS_CURVE (curve), NULL);
+ return curve->priv->legend;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+gdu_curve_set_flags (GduCurve *curve,
+ GduCurveFlags flags)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+ curve->priv->flags = flags;
+}
+
+void
+gdu_curve_set_points (GduCurve *curve,
+ GArray *points)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+
+ if (curve->priv->points != NULL)
+ g_array_unref (curve->priv->points);
+ curve->priv->points = points != NULL ? g_array_ref (points) : NULL;
+}
+
+void
+gdu_curve_set_z_order (GduCurve *curve,
+ gint z_order)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+
+ curve->priv->z_order = z_order;
+}
+
+void
+gdu_curve_set_color (GduCurve *curve,
+ GduColor *color)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+ g_return_if_fail (color != NULL);
+
+ if (curve->priv->color != NULL)
+ gdu_color_free (curve->priv->color);
+ curve->priv->color = gdu_color_dup (color);
+}
+
+void
+gdu_curve_set_fill_color (GduCurve *curve,
+ GduColor *color)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+ g_return_if_fail (color != NULL);
+
+ if (curve->priv->fill_color != NULL)
+ gdu_color_free (curve->priv->fill_color);
+ curve->priv->fill_color = gdu_color_dup (color);
+}
+
+void
+gdu_curve_set_width (GduCurve *curve,
+ gdouble width)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+ g_return_if_fail (width >= 0);
+
+ curve->priv->width = width;
+}
+
+void
+gdu_curve_set_legend (GduCurve *curve,
+ const gchar *text)
+{
+ g_return_if_fail (GDU_IS_CURVE (curve));
+
+ g_free (curve->priv->legend);
+ curve->priv->legend = g_strdup (text);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+GduColor *
+gdu_color_dup (GduColor *color)
+{
+ GduColor *c;
+ c = g_memdup (color, sizeof (GduColor));
+ return c;
+}
+
+void
+gdu_color_free (GduColor *color)
+{
+ g_free (color);
+}
+
+GType
+gdu_color_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ GType g_define_type_id =
+ g_boxed_type_register_static ("GduColor",
+ (GBoxedCopyFunc) gdu_color_dup,
+ (GBoxedFreeFunc) gdu_color_free);
+
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+GduPoint *
+gdu_point_dup (GduPoint *point)
+{
+ GduPoint *p;
+ p = g_memdup (point, sizeof (GduPoint));
+ return p;
+}
+
+void
+gdu_point_free (GduPoint *point)
+{
+ g_free (point);
+}
+
+GType
+gdu_point_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ GType g_define_type_id =
+ g_boxed_type_register_static ("GduPoint",
+ (GBoxedCopyFunc) gdu_point_dup,
+ (GBoxedFreeFunc) gdu_point_free);
+
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
diff --git a/src/gdu-gtk/gdu-curve.h b/src/gdu-gtk/gdu-curve.h
new file mode 100644
index 0000000..294695d
--- /dev/null
+++ b/src/gdu-gtk/gdu-curve.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-curve.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_GTK_INSIDE_GDU_GTK_H) && !defined (GDU_GTK_COMPILATION)
+#error "Only <gdu-gtk/gdu-gtk.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef GDU_CURVE_H
+#define GDU_CURVE_H
+
+#include <gdu-gtk/gdu-gtk-types.h>
+
+#define GDU_TYPE_CURVE (gdu_curve_get_type ())
+#define GDU_CURVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_CURVE, GduCurve))
+#define GDU_CURVE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GDU_CURVE, GduCurveClass))
+#define GDU_IS_CURVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_CURVE))
+#define GDU_IS_CURVE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GDU_TYPE_CURVE))
+#define GDU_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_CURVE, GduCurveClass))
+
+typedef struct GduCurveClass GduCurveClass;
+typedef struct GduCurvePrivate GduCurvePrivate;
+
+struct GduCurve
+{
+ GObject parent;
+
+ /* private */
+ GduCurvePrivate *priv;
+};
+
+struct GduCurveClass
+{
+ GObjectClass parent_class;
+};
+
+GType gdu_curve_get_type (void) G_GNUC_CONST;
+GduCurve *gdu_curve_new (void);
+
+GduCurveFlags gdu_curve_get_flags (GduCurve *curve);
+GArray *gdu_curve_get_points (GduCurve *curve);
+gint gdu_curve_get_z_order (GduCurve *curve);
+GduColor *gdu_curve_get_color (GduCurve *curve);
+GduColor *gdu_curve_get_fill_color (GduCurve *curve);
+gdouble gdu_curve_get_width (GduCurve *curve);
+const gchar *gdu_curve_get_legend (GduCurve *curve);
+
+void gdu_curve_set_flags (GduCurve *curve,
+ GduCurveFlags flags);
+void gdu_curve_set_points (GduCurve *curve,
+ GArray *points);
+void gdu_curve_set_z_order (GduCurve *curve,
+ gint z_order);
+void gdu_curve_set_color (GduCurve *curve,
+ GduColor *color);
+void gdu_curve_set_fill_color (GduCurve *curve,
+ GduColor *color);
+void gdu_curve_set_width (GduCurve *curve,
+ gdouble line_width);
+void gdu_curve_set_legend (GduCurve *curve,
+ const gchar *text);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct GduPoint
+{
+ gdouble x;
+ gdouble y;
+};
+
+#define GDU_TYPE_POINT (gdu_point_get_type ())
+GType gdu_point_get_type (void) G_GNUC_CONST;
+GduPoint *gdu_point_dup (GduPoint *point);
+void gdu_point_free (GduPoint *point);
+
+struct GduColor
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble alpha;
+};
+
+#define GDU_TYPE_COLOR (gdu_color_get_type ())
+GType gdu_color_get_type (void) G_GNUC_CONST;
+GduColor *gdu_color_dup (GduColor *color);
+void gdu_color_free (GduColor *color);
+
+
+#endif /* GDU_CURVE_H */
diff --git a/src/gdu-gtk/gdu-graph.c b/src/gdu-gtk/gdu-graph.c
index f0b0cf9..d04f969 100644
--- a/src/gdu-gtk/gdu-graph.c
+++ b/src/gdu-gtk/gdu-graph.c
@@ -24,43 +24,11 @@
#include <string.h>
#include <math.h>
+#include "gdu-curve.h"
#include "gdu-graph.h"
/* ---------------------------------------------------------------------------------------------------- */
-typedef struct
-{
- gchar *id;
- GdkColor *color;
- GArray *points;
-} Curve;
-
-static Curve *
-curve_new (const gchar *curve_id,
- GdkColor *color,
- GArray *points)
-{
- Curve *c;
-
- c = g_new0 (Curve, 1);
- c->id = g_strdup (curve_id);
- c->color = gdk_color_copy (color);
- c->points = g_array_ref (points);
-
- return c;
-}
-
-static void
-curve_free (Curve *c)
-{
- g_free (c->id);
- gdk_color_free (c->color);
- g_array_unref (c->points);
- g_free (c);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
struct GduGraphPrivate
{
guint foo;
@@ -69,8 +37,7 @@ struct GduGraphPrivate
gchar **y_markers_left;
gchar **y_markers_right;
- GPtrArray *curves;
- GPtrArray *bands;
+ GHashTable *curves;
};
G_DEFINE_TYPE (GduGraph, gdu_graph, GTK_TYPE_DRAWING_AREA)
@@ -149,8 +116,7 @@ gdu_graph_finalize (GObject *object)
g_strfreev (graph->priv->y_markers_left);
g_strfreev (graph->priv->y_markers_right);
- g_ptr_array_unref (graph->priv->curves);
- g_ptr_array_unref (graph->priv->bands);
+ g_hash_table_unref (graph->priv->curves);
if (G_OBJECT_CLASS (gdu_graph_parent_class)->finalize != NULL)
G_OBJECT_CLASS (gdu_graph_parent_class)->finalize (object);
@@ -205,8 +171,7 @@ static void
gdu_graph_init (GduGraph *graph)
{
graph->priv = G_TYPE_INSTANCE_GET_PRIVATE (graph, GDU_TYPE_GRAPH, GduGraphPrivate);
- graph->priv->curves = g_ptr_array_new_with_free_func ((GDestroyNotify) curve_free);
- graph->priv->bands = g_ptr_array_new_with_free_func ((GDestroyNotify) curve_free);
+ graph->priv->curves = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}
GtkWidget *
@@ -283,6 +248,91 @@ measure_width (cairo_t *cr,
return te.width;
}
+static gdouble
+measure_height (cairo_t *cr,
+ const gchar *s)
+{
+ cairo_text_extents_t te;
+ cairo_select_font_face (cr,
+ "sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, 8.0);
+ cairo_text_extents (cr, s, &te);
+ return te.height;
+}
+
+static void
+set_fade_edges_pattern (cairo_t *cr,
+ gdouble x0,
+ gdouble x1,
+ GduColor *color)
+{
+ cairo_pattern_t *pattern;
+
+ pattern = cairo_pattern_create_linear (x0, 0,
+ x1, 0);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.00,
+ 1.00,
+ 1.00,
+ 1.00,
+ 0.00);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.35,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.65,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+ cairo_pattern_add_color_stop_rgba (pattern, 1.00,
+ 1.00,
+ 1.00,
+ 1.00,
+ 0.00);
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+}
+
+static gint
+compute_all_legends_width (cairo_t *cr,
+ gdouble lb_width,
+ GList *curve_list)
+{
+ GList *l;
+ gint width;
+
+ width = 0;
+ for (l = curve_list; l != NULL; l = l->next) {
+ GduCurve *c = GDU_CURVE (l->data);
+ cairo_text_extents_t te;
+ const gchar *text;
+
+ text = gdu_curve_get_legend (c);
+
+ if (text == NULL)
+ continue;
+
+ cairo_select_font_face (cr, "sans",
+ CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, 8.0);
+ cairo_text_extents (cr, text, &te);
+
+ width += lb_width + 3 + ceil (te.width) + 12;
+ }
+
+ return width;
+}
+
+static gint
+curve_z_order_sort (GduCurve *a,
+ GduCurve *b)
+{
+ return gdu_curve_get_z_order (a) - gdu_curve_get_z_order (b);
+}
+
static gboolean
gdu_graph_expose_event (GtkWidget *widget,
GdkEventExpose *event)
@@ -294,6 +344,29 @@ gdu_graph_expose_event (GtkWidget *widget,
cairo_t *cr;
gdouble width, height;
guint n;
+ gdouble x, y;
+ guint twidth;
+ guint theight;
+ guint left_margin;
+ guint right_margin;
+ guint top_margin;
+ guint bottom_margin;
+ guint x_markers_height;
+ double gx, gy, gw, gh;
+ guint64 t_left;
+ guint64 t_right;
+ GTimeVal now;
+ GList *curve_list;
+ GList *l;
+ gdouble lb_width;
+ gdouble lb_height;
+ gdouble lb_padding;
+ gdouble lb_xpos;
+ gdouble lb_ypos;
+
+ curve_list = g_hash_table_get_values (graph->priv->curves);
+ curve_list = g_list_sort (curve_list,
+ (GCompareFunc) curve_z_order_sort);
n_x_markers = graph->priv->x_markers != NULL ? g_strv_length (graph->priv->x_markers) : 0;
n_y_markers_left = graph->priv->y_markers_left != NULL ? g_strv_length (graph->priv->y_markers_left) : 0;
@@ -308,47 +381,152 @@ gdu_graph_expose_event (GtkWidget *widget,
event->area.width, event->area.height);
cairo_clip (cr);
- double gx, gy, gw, gh;
gx = 0;
- gy = 10;
- gw = width - 10;
- gh = height - gy - 30;
+ gy = 0;
+ gw = width;
+ gh = height;
- guint twidth;
+ top_margin = 10;
+
+ /* measure text of all x markers */
+ bottom_margin = 0;
+ for (n = 0; n < n_x_markers; n++) {
+ theight = ceil (measure_height (cr, graph->priv->x_markers[n]));
+ if (theight > bottom_margin)
+ bottom_margin = theight;
+ }
+ bottom_margin += 12; /* padding */
+ x_markers_height = bottom_margin;
+
+ /* compute how much size we need for legends */
+ bottom_margin += 6; /* padding */
+ lb_height = 14;
+ lb_width = 23; /* golden ratio */
+ lb_padding = 6;
+ bottom_margin += lb_height + lb_padding;
+
+ /* adjust drawing area */
+ gy += top_margin;
+ gh -= top_margin;
+ gh -= bottom_margin;
+
+ gint all_legends_width;
+ all_legends_width = compute_all_legends_width (cr,
+ lb_width,
+ curve_list);
+
+ /* draw legends */
+ lb_ypos = gy + gh + x_markers_height + 6; /* padding */
+ lb_xpos = 10 + ceil (((width - 20) - all_legends_width) / 2);
+ for (l = curve_list; l != NULL; l = l->next) {
+ GduCurve *c = GDU_CURVE (l->data);
+ GduColor *color;
+ GduColor *fill_color;
+ gdouble width;
+ GduCurveFlags flags;
+ const gchar *text;
+ gdouble x, y;
+ cairo_text_extents_t te;
+
+ color = gdu_curve_get_color (c);
+ fill_color = gdu_curve_get_fill_color (c);
+ if (fill_color == NULL)
+ fill_color = color;
+ width = gdu_curve_get_width (c);
+ flags = gdu_curve_get_flags (c);
+ text = gdu_curve_get_legend (c);
+
+ if (text == NULL)
+ continue;
+
+ x = lb_xpos + 0.5;
+ y = lb_ypos + 0.5;
+
+ cairo_new_path (cr);
+ cairo_set_dash (cr, NULL, 0, 0.0);
+ cairo_set_line_width (cr, 1.0);
+ cairo_rectangle (cr, x, y, lb_width, lb_height);
+ cairo_close_path (cr);
+ cairo_set_source_rgba (cr, 1, 1, 1, 1);
+ cairo_fill_preserve (cr);
+ cairo_set_source_rgba (cr, 0, 0, 0, 1);
+ cairo_stroke (cr);
+
+ cairo_new_path (cr);
+
+ if (flags * GDU_CURVE_FLAGS_FILLED) {
+ if (flags & GDU_CURVE_FLAGS_FADE_EDGES) {
+ set_fade_edges_pattern (cr, x, x + lb_width, fill_color);
+ } else {
+ cairo_set_source_rgba (cr,
+ fill_color->red,
+ fill_color->green,
+ fill_color->blue,
+ fill_color->alpha);
+ }
+ cairo_rectangle (cr, x + 1, y + 1, lb_width - 2, lb_height - 2);
+ cairo_fill (cr);
+ } else {
+ cairo_move_to (cr, x, y + lb_height/2.0);
+ cairo_line_to (cr, x + lb_width / 2.0, y + lb_height/3.0);
+ cairo_line_to (cr, x + lb_width, y + 2.0 * lb_height/3.0);
+
+ cairo_set_line_width (cr, width);
+ cairo_set_source_rgba (cr,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+ cairo_stroke (cr);
+ }
+
+ /* and now show the text */
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_select_font_face (cr, "sans",
+ CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, 8.0);
+ cairo_text_extents (cr, text, &te);
+ cairo_move_to (cr,
+ x + lb_width + 3 - te.x_bearing,
+ y + lb_height/2.0 - te.height/2 - te.y_bearing);
+
+ cairo_show_text (cr, text);
+
+ lb_xpos += lb_width + 3 + ceil (te.width) + 12;
+ }
/* measure text on the left y-axis */
- guint y_left_max_width;
- y_left_max_width = 0;
+ left_margin = 0;
for (n = 0; n < n_y_markers_left; n++) {
twidth = ceil (measure_width (cr, graph->priv->y_markers_left[n]));
- if (twidth > y_left_max_width)
- y_left_max_width = twidth;
+ if (twidth > left_margin)
+ left_margin = twidth;
}
/* include half width of first xmarker label */
if (n_x_markers > 0) {
twidth = ceil (measure_width (cr, graph->priv->x_markers[0]));
- if (twidth/2 > y_left_max_width)
- y_left_max_width = twidth/2;
+ if (twidth/2 > left_margin)
+ left_margin = twidth/2;
}
- y_left_max_width += 6; /* padding */
- gx += y_left_max_width;
- gw -= y_left_max_width;
+ left_margin += 6; /* padding */
+ gx += left_margin;
+ gw -= left_margin;
/* measure text on the right y-axis */
- guint y_right_max_width;
- y_right_max_width = 0;
+ right_margin = 0;
for (n = 0; n < n_y_markers_right; n++) {
twidth = ceil (measure_width (cr, graph->priv->y_markers_right[n]));
- if (twidth/2 > y_right_max_width)
- y_right_max_width = twidth/2;
+ if (twidth/2 > right_margin)
+ right_margin = twidth/2;
}
/* include half width of last xmarker label */
if (n_x_markers > 0) {
twidth = ceil (measure_width (cr, graph->priv->x_markers[n_x_markers - 1]));
- y_right_max_width += twidth/2;
+ right_margin += twidth/2;
}
- y_right_max_width += 6; /* padding */
- gw -= y_right_max_width;
+ right_margin += 6; /* padding */
+ gw -= right_margin;
/* draw the box to draw in */
cairo_set_source_rgb (cr, 1, 1, 1);
@@ -358,14 +536,15 @@ gdu_graph_expose_event (GtkWidget *widget,
/* draw markers on the left y-axis */
for (n = 0; n < n_y_markers_left; n++) {
- double pos;
+ gdouble pos;
+ gdouble dashes[1] = {2.0};
+ const gchar *s;
+ cairo_text_extents_t te;
pos = ceil (gy + gh / (n_y_markers_left - 1) * n);
- const char *s;
s = graph->priv->y_markers_left[n_y_markers_left - 1 - n];
- cairo_text_extents_t te;
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_select_font_face (cr, "sans",
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
@@ -378,7 +557,6 @@ gdu_graph_expose_event (GtkWidget *widget,
cairo_show_text (cr, s);
cairo_set_line_width (cr, 1.0);
- double dashes[1] = {2.0};
cairo_set_dash (cr, dashes, 1, 0.0);
cairo_move_to (cr,
gx - 0.5,
@@ -391,55 +569,27 @@ gdu_graph_expose_event (GtkWidget *widget,
/* draw markers on the right y-axis */
for (n = 0; n < n_y_markers_right; n++) {
- double pos;
+ gdouble pos;
+ const gchar *s;
+ cairo_text_extents_t te;
pos = ceil (gy + gh / (n_y_markers_right - 1) * n);
- const char *s;
s = graph->priv->y_markers_right[n_y_markers_right - 1 - n];
- cairo_text_extents_t te;
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_select_font_face (cr, "sans",
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 8.0);
cairo_text_extents (cr, s, &te);
cairo_move_to (cr,
- gx + gw + y_right_max_width/2.0 + 3 - te.width/2 - te.x_bearing,
+ gx + gw + right_margin/2.0 + 3 - te.width/2 - te.x_bearing,
pos - te.height/2 - te.y_bearing);
cairo_show_text (cr, s);
}
- guint64 t_left;
- guint64 t_right;
- GTimeVal now;
-
g_get_current_time (&now);
- /*
- switch (0) {
- default:
- case 0:
- t_left = now.tv_sec - 6 * 60 * 60;
- break;
- case 1:
- t_left = now.tv_sec - 24 * 60 * 60;
- break;
- case 2:
- t_left = now.tv_sec - 3 * 24 * 60 * 60;
- break;
- case 3:
- t_left = now.tv_sec - 12 * 24 * 60 * 60;
- break;
- case 4:
- t_left = now.tv_sec - 36 * 24 * 60 * 60;
- break;
- case 5:
- t_left = now.tv_sec - 96 * 24 * 60 * 60;
- break;
- }
- t_right = now.tv_sec;
- */
t_left = now.tv_sec - 6 * 24 * 60 * 60;
t_right = now.tv_sec;
@@ -463,7 +613,7 @@ gdu_graph_expose_event (GtkWidget *widget,
cairo_text_extents (cr, s, &te);
cairo_move_to (cr,
pos - te.width/2 - te.x_bearing,
- height - 30.0/2 - te.height/2 - te.y_bearing); /* TODO */
+ gy + gh + x_markers_height/2.0 - te.y_bearing);
cairo_show_text (cr, s);
@@ -482,77 +632,92 @@ gdu_graph_expose_event (GtkWidget *widget,
cairo_rectangle (cr, gx, gy, gw, gh);
cairo_clip (cr);
- /* draw all bands */
- for (n = 0; n < graph->priv->bands->len; n++) {
- Curve *c = (Curve *) graph->priv->bands->pdata[n];
+ for (l = curve_list; l != NULL; l = l->next) {
+ GduCurve *c = GDU_CURVE (l->data);
+ GduColor *color;
+ GduColor *fill_color;
+ gdouble width;
+ GduCurveFlags flags;
+ GArray *points;
guint m;
- cairo_new_path (cr);
- cairo_set_line_width (cr, 0.0);
- cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.5);
-
- for (m = 0; m < c->points->len; m+= 2) {
- GduGraphPoint *point;
- gdouble x0, x1;
- gdouble x, width;
- cairo_pattern_t *pat;
-
- point = &g_array_index (c->points, GduGraphPoint, m);
- x0 = gx + gw * point->x;
-
- point = &g_array_index (c->points, GduGraphPoint, m + 1);
- x1 = gx + gw * point->x;
-
- x = x0;
- if (x1 < x0)
- x = x1;
- width = fabs (x1 - x0);
-
- g_debug ("band: %f to %f", x0, x1);
-
- pat = cairo_pattern_create_linear (x, gy,
- x + width, gy);
- cairo_pattern_add_color_stop_rgba (pat, 0.00, 1.00, 1.00, 1.00, 0.00);
- cairo_pattern_add_color_stop_rgba (pat, 0.35, 0.85, 0.85, 0.85, 0.50);
- cairo_pattern_add_color_stop_rgba (pat, 0.65, 0.85, 0.85, 0.85, 0.50);
- cairo_pattern_add_color_stop_rgba (pat, 1.00, 1.00, 1.00, 1.00, 0.00);
- cairo_set_source (cr, pat);
- cairo_pattern_destroy (pat);
-
- cairo_rectangle (cr, x, gy, width, gh);
- cairo_fill (cr);
- }
+ color = gdu_curve_get_color (c);
+ fill_color = gdu_curve_get_fill_color (c);
+ if (fill_color == NULL)
+ fill_color = color;
+ width = gdu_curve_get_width (c);
+ flags = gdu_curve_get_flags (c);
+ points = gdu_curve_get_points (c);
+
+ m = 0;
+ while (m < points->len) {
+ guint first_point_index;
+
+ cairo_new_path (cr);
+
+ first_point_index = m;
+ for (; m < points->len; m++) {
+ GduPoint *point;
+
+ point = &g_array_index (points, GduPoint, m);
+
+ if (point->x == G_MAXDOUBLE &&
+ point->y == G_MAXDOUBLE) {
+ m++;
+ break;
+ }
+
+ x = gx + gw * point->x;
+ y = gy + gh * (1.0f - point->y);
+
+ if (y < gy + 1.0)
+ y = gy;
+
+ if (y > gy + gh - 1.0)
+ y = gy + gh - 1.0;
+
+ cairo_line_to (cr, x, y);
+ }
+
+ /* fill if requested */
+ if (flags & GDU_CURVE_FLAGS_FILLED) {
+ GduPoint *point;
+ gdouble first_x;
+
+ /* first, close the path */
+ cairo_line_to (cr, x, gy + gh);
+ point = &g_array_index (points, GduPoint, first_point_index);
+ first_x = gx + gw * point->x;
+ cairo_line_to (cr, first_x, gy + gh);
+ cairo_close_path (cr);
+
+ if (flags & GDU_CURVE_FLAGS_FADE_EDGES) {
+ set_fade_edges_pattern (cr, first_x, x, fill_color);
+ } else {
+ cairo_set_source_rgba (cr,
+ fill_color->red,
+ fill_color->green,
+ fill_color->blue,
+ fill_color->alpha);
+ }
+ cairo_fill_preserve (cr);
+ }
+
+ /* then draw the curve */
+ cairo_set_dash (cr, NULL, 0, 0.0);
+ cairo_set_line_width (cr, width);
+ cairo_set_source_rgba (cr,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+
+ cairo_stroke (cr);
+
+ } /* process more points */
}
- /* draw all curves */
- for (n = 0; n < graph->priv->curves->len; n++) {
- Curve *c = (Curve *) graph->priv->curves->pdata[n];
- guint m;
-
- cairo_new_path (cr);
- cairo_set_dash (cr, NULL, 0, 0.0);
- cairo_set_line_width (cr, 1.0);
- gdk_cairo_set_source_color (cr, c->color);
-
- for (m = 0; m < c->points->len; m++) {
- GduGraphPoint *point;
- gdouble x, y;
-
- point = &g_array_index (c->points, GduGraphPoint, m);
-
- x = gx + gw * point->x;
- y = gy + gh * (1.0f - point->y);
-
- if (y < gy + 1.0)
- y = gy;
-
- if (y > gy + gh - 1.0)
- y = gy + gh - 1.0;
-
- cairo_line_to (cr, x, y);
- }
- cairo_stroke (cr);
- }
+ g_list_free (curve_list);
/* propagate event further */
return FALSE;
@@ -562,85 +727,26 @@ gboolean
gdu_graph_remove_curve (GduGraph *graph,
const gchar *curve_id)
{
- guint n;
- gboolean found;
-
- found = FALSE;
- for (n = 0; n < graph->priv->curves->len; n++) {
- Curve *c = (Curve *) graph->priv->curves->pdata[n];
- if (g_strcmp0 (curve_id, c->id) == 0) {
- g_ptr_array_remove_index (graph->priv->curves, n);
- found = TRUE;
- break;
- }
- }
-
- return found;
-}
+ gboolean ret;
-void
-gdu_graph_set_curve (GduGraph *graph,
- const gchar *curve_id,
- GdkColor *color,
- GArray *points)
-{
- g_return_if_fail (GDU_IS_GRAPH (graph));
- g_return_if_fail (curve_id != NULL);
- g_return_if_fail (color != NULL);
-
- if (points == NULL) {
- gdu_graph_remove_curve (graph, curve_id);
- } else {
- gdu_graph_remove_curve (graph, curve_id);
- g_ptr_array_add (graph->priv->curves,
- curve_new (curve_id,
- color,
- points));
- }
+ ret = g_hash_table_remove (graph->priv->curves, curve_id);
if (GTK_WIDGET (graph)->window != NULL)
gdk_window_invalidate_rect (GTK_WIDGET (graph)->window, NULL, TRUE);
-}
-gboolean
-gdu_graph_remove_band (GduGraph *graph,
- const gchar *band_id)
-{
- guint n;
- gboolean found;
-
- found = FALSE;
- for (n = 0; n < graph->priv->bands->len; n++) {
- Curve *c = (Curve *) graph->priv->bands->pdata[n];
- if (g_strcmp0 (band_id, c->id) == 0) {
- g_ptr_array_remove_index (graph->priv->bands, n);
- found = TRUE;
- break;
- }
- }
-
- return found;
+ return ret;
}
void
-gdu_graph_set_band (GduGraph *graph,
- const gchar *band_id,
- GdkColor *color,
- GArray *points)
+gdu_graph_add_curve (GduGraph *graph,
+ const gchar *curve_id,
+ GduCurve *curve)
{
g_return_if_fail (GDU_IS_GRAPH (graph));
- g_return_if_fail (band_id != NULL);
- g_return_if_fail (color != NULL);
-
- if (points == NULL) {
- gdu_graph_remove_band (graph, band_id);
- } else {
- gdu_graph_remove_band (graph, band_id);
- g_ptr_array_add (graph->priv->bands,
- curve_new (band_id,
- color,
- points));
- }
+ g_return_if_fail (curve_id != NULL);
+ g_return_if_fail (curve != NULL);
+
+ g_hash_table_insert (graph->priv->curves, g_strdup (curve_id), g_object_ref (curve));
if (GTK_WIDGET (graph)->window != NULL)
gdk_window_invalidate_rect (GTK_WIDGET (graph)->window, NULL, TRUE);
diff --git a/src/gdu-gtk/gdu-graph.h b/src/gdu-gtk/gdu-graph.h
index 92fe0f0..5db40e7 100644
--- a/src/gdu-gtk/gdu-graph.h
+++ b/src/gdu-gtk/gdu-graph.h
@@ -64,30 +64,14 @@ void gdu_graph_set_y_markers_left (GduGraph *graph,
void gdu_graph_set_y_markers_right (GduGraph *graph,
const gchar* const *markers);
-typedef struct GduGraphPoint GduGraphPoint;
-
-struct GduGraphPoint
-{
- gfloat x;
- gfloat y;
- gpointer data;
-};
-
-gboolean gdu_graph_remove_curve (GduGraph *graph,
+GduCurve *gdu_graph_lookup_curve (GduGraph *graph,
const gchar *curve_id);
-void gdu_graph_set_curve (GduGraph *graph,
+void gdu_graph_add_curve (GduGraph *graph,
const gchar *curve_id,
- GdkColor *color,
- GArray *points);
-
-gboolean gdu_graph_remove_band (GduGraph *graph,
- const gchar *band_id);
-
-void gdu_graph_set_band (GduGraph *graph,
- const gchar *band_id,
- GdkColor *color,
- GArray *points);
+ GduCurve *curve);
+gboolean gdu_graph_remove_curve (GduGraph *graph,
+ const gchar *curve_id);
#endif /* GDU_GRAPH_H */
diff --git a/src/gdu-gtk/gdu-gtk-enums.h b/src/gdu-gtk/gdu-gtk-enums.h
new file mode 100644
index 0000000..9c1b49c
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enums.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-gtk-enums.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_GTK_INSIDE_GDU_GTK_H) && !defined (GDU_GTK_COMPILATION)
+#error "Only <gdu-gtk/gdu-gtk.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef GDU_GTK_ENUMS_H
+#define GDU_GTK_ENUMS_H
+
+#include <glib-object.h>
+
+typedef enum
+{
+ GDU_CURVE_FLAGS_NONE = 0,
+ GDU_CURVE_FLAGS_FILLED = (1 << 0),
+ GDU_CURVE_FLAGS_FADE_EDGES = (1 << 1),
+} GduCurveFlags;
+
+#endif /* GDU_GTK_ENUMS_H */
diff --git a/src/gdu-gtk/gdu-gtk-enumtypes.c.template b/src/gdu-gtk/gdu-gtk-enumtypes.c.template
new file mode 100644
index 0000000..9ffe156
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enumtypes.c.template
@@ -0,0 +1,39 @@
+/*** BEGIN file-header ***/
+#include <gdu-gtk/gdu-gtk.h>
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_ type@_register_static (g_intern_static_string ("@EnumName@"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+/*** END file-tail ***/
diff --git a/src/gdu-gtk/gdu-gtk-enumtypes.h.template b/src/gdu-gtk/gdu-gtk-enumtypes.h.template
new file mode 100644
index 0000000..4737f89
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enumtypes.h.template
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef __GDU_GTK_ENUM_TYPES_H__
+#define __GDU_GTK_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name _get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX _TYPE_@ENUMSHORT@ (@enum_name _get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __GDU_GTK_ENUM_TYPES_H__ */
+/*** END file-tail ***/
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index efab698..2be3ac0 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -29,13 +29,16 @@
#include <glib-object.h>
#include <gdu/gdu.h>
#include <gtk/gtk.h>
+#include <gdu-gtk/gdu-gtk-enums.h>
G_BEGIN_DECLS
+typedef struct GduPoint GduPoint;
+typedef struct GduColor GduColor;
+typedef struct GduCurve GduCurve;
typedef struct GduGraph GduGraph;
typedef struct GduTimeLabel GduTimeLabel;
typedef struct GduAtaSmartDialog GduAtaSmartDialog;
-typedef struct GduAtaSmartAttributeDialog GduAtaSmartAttributeDialog;
G_END_DECLS
diff --git a/src/gdu-gtk/gdu-gtk.h b/src/gdu-gtk/gdu-gtk.h
index b530209..f3bce49 100644
--- a/src/gdu-gtk/gdu-gtk.h
+++ b/src/gdu-gtk/gdu-gtk.h
@@ -28,10 +28,11 @@
#define __GDU_GTK_INSIDE_GDU_GTK_H
#include <gdu-gtk/gdu-gtk-types.h>
+#include <gdu-gtk/gdu-gtk-enumtypes.h>
+#include <gdu-gtk/gdu-curve.h>
#include <gdu-gtk/gdu-graph.h>
#include <gdu-gtk/gdu-time-label.h>
#include <gdu-gtk/gdu-ata-smart-dialog.h>
-#include <gdu-gtk/gdu-ata-smart-attribute-dialog.h>
#undef __GDU_GTK_INSIDE_GDU_GTK_H
G_BEGIN_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]