gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r18529 - gnunet-gtk/src/statistics


From: gnunet
Subject: [GNUnet-SVN] r18529 - gnunet-gtk/src/statistics
Date: Fri, 9 Dec 2011 16:16:55 +0100

Author: grothoff
Date: 2011-12-09 16:16:55 +0100 (Fri, 09 Dec 2011)
New Revision: 18529

Modified:
   gnunet-gtk/src/statistics/Makefile.am
   gnunet-gtk/src/statistics/gtk_statistics.c
   gnunet-gtk/src/statistics/gtk_statistics.h
   gnunet-gtk/src/statistics/test.c
Log:
finishing statistics widget

Modified: gnunet-gtk/src/statistics/Makefile.am
===================================================================
--- gnunet-gtk/src/statistics/Makefile.am       2011-12-09 14:48:25 UTC (rev 
18528)
+++ gnunet-gtk/src/statistics/Makefile.am       2011-12-09 15:16:55 UTC (rev 
18529)
@@ -26,7 +26,7 @@
   gtk_statistics.c gtk_statistics.h test.c
 test_LDADD = \
   @GTK_LIBS@ \
-  @GLADE_LIBS@ @GNUNET_LIBS@ \
+  @GLADE_LIBS@ @GNUNET_LIBS@ -lm \
   $(INTLLIBS) 
 test_LDFLAGS = \
   -export-dynamic 
\ No newline at end of file

Modified: gnunet-gtk/src/statistics/gtk_statistics.c
===================================================================
--- gnunet-gtk/src/statistics/gtk_statistics.c  2011-12-09 14:48:25 UTC (rev 
18528)
+++ gnunet-gtk/src/statistics/gtk_statistics.c  2011-12-09 15:16:55 UTC (rev 
18529)
@@ -30,6 +30,19 @@
 #define MAX_HISTORY 1280
 
 /**
+ * Number of ticks on the x-axis.
+ */
+#define XTICKS 4
+
+/**
+ * Number of ticks on the y-axis.
+ */
+#define YTICKS 5
+
+#define BORDER 10.0
+
+
+/**
  * Information about a value we received.
  */
 struct HistoricValue
@@ -58,9 +71,9 @@
   char *label;
 
   /**
-   * Color name.
+   * Color values (rgb).
    */
-  char *color_name;
+  double red, green, blue;
 
   /**
    * Recent values for this number.
@@ -100,7 +113,7 @@
 static void gtk_statistics_finalize          (GObject          *object);
 
 
-G_DEFINE_TYPE (GtkStatistics, gtk_statistics, GTK_TYPE_MISC)
+G_DEFINE_TYPE (GtkStatistics, gtk_statistics, GTK_TYPE_WIDGET)
 
 
 static void
@@ -114,6 +127,7 @@
 
   gobject_class->finalize = gtk_statistics_finalize;
   widget_class->draw = gtk_statistics_draw;
+  
   g_type_class_add_private (class, sizeof (GtkStatisticsPrivate));
 }
 
@@ -152,6 +166,7 @@
   priv = statistics->priv;
   priv->values = NULL;
   priv->num_values = 0;
+
   return GTK_WIDGET (statistics);
 }
 
@@ -165,14 +180,18 @@
 {
   GtkStatisticsPrivate *priv;
   struct ValueHistory *vh;
+  GdkColor c;
 
   g_return_if_fail (GTK_IS_STATISTICS (statistics));
+  g_return_if_fail (gdk_color_parse (color_name, &c));
   priv = statistics->priv;
   priv->values = g_realloc (priv->values,
                            sizeof (struct ValueHistory*) * (1 + 
priv->num_values));
   priv->values[priv->num_values++] = vh = g_malloc (sizeof (struct 
ValueHistory));
   vh->label = strdup (label);
-  vh->color_name = strdup (color_name);
+  vh->red = c.red / 65535.0;
+  vh->green = c.green / 65535.0;
+  vh->blue = c.blue / 65535.0;
 }
 
 
@@ -202,11 +221,6 @@
       vh->history_size++;
     vh->history[vh->last_history_offset].x = x;
     vh->history[vh->last_history_offset].y = y;
-
-    g_object_freeze_notify (G_OBJECT (statistics));
-    g_object_notify (G_OBJECT (statistics), "statistics-value");
-    g_object_thaw_notify (G_OBJECT (statistics));
-  
     widget = GTK_WIDGET (statistics);
     if (gtk_widget_is_drawable (widget))
       gtk_widget_queue_draw (widget);
@@ -214,38 +228,179 @@
 }
 
 
+static void
+num_to_label (unsigned long long num,
+             char *label)
+{
+  if (num > 1000LL * 1000 * 1000 * 3)
+    sprintf (label, "%llu g", num / 1000LL / 1000LL / 1000LL);
+  else if (num > 1000LL * 1000 * 3)
+    sprintf (label, "%llu m", num / 1000LL / 1000LL);
+  else if (num > 1000LL * 3)
+    sprintf (label, "%llu k", num / 1000LL);
+  else
+    sprintf (label, "%llu", num);
+}
+
+
 static gboolean
 gtk_statistics_draw (GtkWidget *widget,
                 cairo_t   *cr)
 {
   GtkStatistics *statistics = GTK_STATISTICS (widget);
   GtkStatisticsPrivate *priv = statistics->priv;
+  int width;
+  int height;
+  uint64_t xmin;
+  uint64_t xmax;
+  uint64_t ymax;
+  unsigned int i;
+  unsigned int j;
+  struct ValueHistory *vh;
+  struct HistoricValue *hv;
+  char label[64];
+  cairo_text_extents_t te;
+  cairo_text_extents_t tex_max;
+  cairo_text_extents_t tey_max;
+  double rx;
+  double ry;
 
-  fprintf (stderr, "DRAW!\n");
-#if 0
-    gdk_color_parse (info[i].color_name, &color);
-    gdk_gc_set_foreground (gc, &color);
-#endif
-  cairo_translate(cr, 0, 7);
+  /* collect basic data */
+  xmin = UINT64_MAX;
+  xmax = 0;
+  ymax = 0;
+  for (i=0;i<priv->num_values;i++)
+  {
+    vh = priv->values[i];
+    for (j=0;j<vh->history_size;j++)
+    {
+      hv = &vh->history[(vh->last_history_offset - j + MAX_HISTORY) % 
MAX_HISTORY];
+      xmin = GNUNET_MIN (hv->x, xmin);
+      xmax = GNUNET_MAX (hv->x, xmax);
+      ymax = GNUNET_MAX (hv->y, ymax);
+    }
+  }
+  /* round to 10x for nicer legends */
+  while (0 != (ymax % 10)) ymax++;
+  while (0 != (xmax % 10)) xmax++;
+  while (0 != (xmin % 10)) xmin--;
 
-  cairo_set_source_rgb(cr, 0, 0, 0);
+  width = gtk_widget_get_allocated_width (widget);
+  height = gtk_widget_get_allocated_height (widget);
+
+  /* fill with black background */
+  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
   cairo_paint(cr);
+  
+  if (0 == priv->num_values)
+    return FALSE; /* done */
+  /* select font */
+  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+  cairo_select_font_face (cr, "Georgia",
+                         CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+  cairo_set_font_size (cr, 
+                      GNUNET_MIN (20, height / (2 * XTICKS)));
 
-  gint pos = priv->num_values;
-  gint rect = pos / 5;
+  /* find out needed space for axis labels */
+  tex_max.width = 0;
+  tex_max.height = 0;
+  for (i=0;i<XTICKS;i++)
+  {
+    num_to_label ((unsigned long long) (xmin + (xmax - xmin) * ((uint64_t) i) 
/ (XTICKS - 1)),
+                 label);
+    cairo_text_extents (cr, label, &te);
+    tex_max.width = GNUNET_MAX (te.width, tex_max.width);
+    tex_max.height = GNUNET_MAX (te.height, tex_max.height);
+  }
+  tey_max.width = 0;
+  tey_max.height = 0;
+  for (i=0;i<YTICKS;i++)
+  {
+    num_to_label ((unsigned long long) ymax * ((uint64_t) i) / (YTICKS - 1),
+                 label);
+    cairo_text_extents (cr, label, &te);
+    tey_max.width = GNUNET_MAX (te.width, tey_max.width);
+    tey_max.height = GNUNET_MAX (te.height, tey_max.height);
+  }
 
-  cairo_set_source_rgb(cr, 0.2, 0.4, 0);
+  /* draw y-axis labels */
+  for (i=0;i<YTICKS;i++)
+  {
+    num_to_label ((unsigned long long) ymax * ((uint64_t) i) / (YTICKS - 1),
+                 label);
+    cairo_text_extents (cr, label, &te);
+    cairo_move_to (cr, 
+                  BORDER + tey_max.width - te.width,
+                  BORDER + tey_max.height + (YTICKS - i - 1) * (height - 2.0 * 
BORDER - tey_max.height - tex_max.height) / (double) (YTICKS - 1));
+    cairo_show_text (cr, label);
 
-  gint i;
-  for ( i = 1; i <= 20; i++) {
-      if (i > 20 - rect) {
-          cairo_set_source_rgb(cr, 0.6, 1.0, 0);
-      } else {
-          cairo_set_source_rgb(cr, 0.2, 0.4, 0);
+
+    cairo_move_to (cr, 
+                  2.0 * BORDER + tey_max.width,
+                  BORDER + tey_max.height / 2.0 + (YTICKS - i - 1) * (height - 
2.0 * BORDER - tex_max.height - tey_max.height) / (double) (YTICKS - 1));
+    cairo_line_to (cr, 
+                  2.0 * BORDER + tey_max.width + BORDER / 2.0,
+                  BORDER + tey_max.height / 2.0 + (YTICKS - i - 1) * (height - 
2.0 * BORDER - tex_max.height - tey_max.height) / (double) (YTICKS - 1));
+
+    cairo_stroke (cr);
+  }
+
+  /* draw x-axis labels */
+  for (i=0;i<XTICKS;i++)
+  {
+    num_to_label ((unsigned long long) (xmin + (xmax - xmin) * ((uint64_t) i) 
/ (XTICKS - 1)),
+                 label);
+    cairo_text_extents (cr, label, &te);
+    if (i != 0)
+    {
+      cairo_move_to (cr, 
+                    2.0 * BORDER + tey_max.width + (width - tey_max.width - 
tex_max.width / 2.0 - 3.0 * BORDER) * i / (XTICKS - 1.0) - te.width / 2.0,
+                    height - BORDER / 2.0 - tex_max.height / 2.0);
+      cairo_show_text (cr, label);
+    }
+    cairo_move_to (cr, 
+                  2.0 * BORDER + tey_max.width + (width - tey_max.width - 
tex_max.width / 2.0 - 3.0 * BORDER) * i / (XTICKS - 1.0),
+                  height - BORDER - tey_max.height / 2.0 - tex_max.height);
+    cairo_line_to (cr, 
+                  2.0 * BORDER + tey_max.width + (width - tey_max.width - 
tex_max.width / 2.0 - 3.0 * BORDER) * i / (XTICKS - 1.0),
+                  height - BORDER - tey_max.height / 2.0 - tex_max.height - 
BORDER / 2.0);
+
+    cairo_stroke (cr);
+  }
+
+  /* plot border */
+  cairo_set_line_width (cr, 1.0);
+  cairo_rectangle (cr, 
+                  tey_max.width + BORDER * 2.0, 
+                  BORDER + tey_max.height / 2.0, 
+                  width - BORDER * 3.0 - tey_max.width - tex_max.width / 2.0, 
+                  height - BORDER * 2.0 - tey_max.height - tex_max.height);
+  cairo_stroke (cr);
+
+  /* finally, plot lines */
+  cairo_set_line_width (cr, 2.0);
+  for (i=0;i<priv->num_values;i++)
+  {
+    vh = priv->values[i];
+    cairo_set_source_rgb(cr, vh->red, vh->green, vh->blue);
+    for (j=0;j<vh->history_size;j++)
+    {
+      hv = &vh->history[(vh->last_history_offset - j + MAX_HISTORY) % 
MAX_HISTORY];
+      rx = (hv->x - xmin) / (double) (xmax - xmin);
+      ry = hv->y / (double) ymax;
+      
+      rx = tey_max.width + BORDER * 2.0 + (rx * (width - BORDER * 3.0 - 
tey_max.width - tex_max.width / 2.0));
+      ry = BORDER + tex_max.height / 2.0 + (1.0 - ry) * (height - BORDER * 2.0 
- tey_max.height - tex_max.height);
+      if (j == 0)
+      {
+       cairo_move_to (cr, rx, ry);
       }
-      cairo_rectangle(cr, 8, i*4, 30, 3);
-      cairo_rectangle(cr, 42, i*4, 30, 3);
-      cairo_fill(cr);
+      else
+      {
+       cairo_line_to (cr, rx, ry);
+      }
+    }
+    cairo_stroke (cr);
   }
   return FALSE;
 }
@@ -256,9 +411,14 @@
 {
   GtkStatistics *label = GTK_STATISTICS (object);
   GtkStatisticsPrivate *priv = label->priv;
+  unsigned int i;
 
-  g_free (priv->values);
-
+  for (i=0;i<priv->num_values;i++)
+  {
+    g_free (priv->values[i]->label);
+    g_free (priv->values[i]);  
+  }
+  g_free (priv->values);  
   G_OBJECT_CLASS (gtk_statistics_parent_class)->finalize (object);
 }
 

Modified: gnunet-gtk/src/statistics/gtk_statistics.h
===================================================================
--- gnunet-gtk/src/statistics/gtk_statistics.h  2011-12-09 14:48:25 UTC (rev 
18528)
+++ gnunet-gtk/src/statistics/gtk_statistics.h  2011-12-09 15:16:55 UTC (rev 
18529)
@@ -45,7 +45,7 @@
 
 struct _GtkStatistics
 {
-  GtkMisc misc;
+  GtkWidget widget;
 
   /*< private >*/
   GtkStatisticsPrivate *priv;
@@ -53,7 +53,7 @@
 
 struct _GtkStatisticsClass
 {
-  GtkMiscClass parent_class;
+  GtkWidgetClass parent_class;
 
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);

Modified: gnunet-gtk/src/statistics/test.c
===================================================================
--- gnunet-gtk/src/statistics/test.c    2011-12-09 14:48:25 UTC (rev 18528)
+++ gnunet-gtk/src/statistics/test.c    2011-12-09 15:16:55 UTC (rev 18529)
@@ -1,20 +1,64 @@
 
 #include "gtk_statistics.h"
+#include <math.h>
 
+
+/**
+ * Update view (add more points).
+ */
+static gboolean
+update (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+  static unsigned int i = 600;
+  struct GtkStatistics *statistics = user_data;
+
+  gtk_statistics_update_value (GTK_STATISTICS (statistics),
+                              "sin",
+                              i,
+                              (uint64_t) (500 * (1.0 + sin(i/100.0))));
+  gtk_statistics_update_value (GTK_STATISTICS (statistics),
+                              "cos",
+                              i * 2,
+                              (uint64_t) (i * (1.0 + cos(i/100.0))));
+  i++;
+  return FALSE;
+}
+
+
 int main (int argc, char ** argv)
 {
   GtkWidget *window;
   GtkWidget *statistics;
+  unsigned int i;
 
   gtk_init(&argc, &argv);
   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW(window), "STATISTICS widget");
   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
-  gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
+  gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
   g_signal_connect(G_OBJECT(window), "destroy", 
        G_CALLBACK(gtk_main_quit), NULL);
   statistics = gtk_statistics_new();
+  gtk_statistics_add_line (GTK_STATISTICS (statistics),
+                          "sin",
+                          "red");
+  for (i=0;i<600;i++)
+    gtk_statistics_update_value (GTK_STATISTICS (statistics),
+                                "sin",
+                                i,
+                                (uint64_t) (500 * (1.0 + sin(i/100.0))));
+  gtk_statistics_add_line (GTK_STATISTICS (statistics),
+                          "cos",
+                          "blue");
+  for (i=0;i<600;i++)
+    gtk_statistics_update_value (GTK_STATISTICS (statistics),
+                                "cos",
+                                i * 2,
+                                (uint64_t) (i * (1.0 + cos(i/100.0))));
+  g_signal_connect (G_OBJECT(window), "motion-notify-event", G_CALLBACK 
(update), statistics);
   gtk_container_add(GTK_CONTAINER(window), statistics);
+  gtk_widget_add_events (GTK_WIDGET (window), GDK_POINTER_MOTION_MASK);
+
   gtk_widget_show(statistics);
   gtk_widget_show_all(window);
   gtk_main();




reply via email to

[Prev in Thread] Current Thread [Next in Thread]