Index: src/load-graph.cpp
===================================================================
--- src/load-graph.cpp	(révision 2203)
+++ src/load-graph.cpp	(copie de travail)
@@ -44,6 +44,7 @@
 	gint type;
 	guint speed;
 	guint draw_width, draw_height;
+        gint graph_width, graph_height;
 
 	GdkColor *colors;
 
@@ -54,7 +55,8 @@
 	GtkWidget *disp;
 
 	cairo_surface_t *buffer;
-
+        cairo_surface_t *background;
+        
 	guint timer_index;
 
 	gboolean draw;
@@ -81,111 +83,180 @@
 };
 
 
+#define FRAME_WIDTH     6
+#define FONT_SIZE   11
 
-#define FRAME_WIDTH 4
+/* paints the (complex) background to a cached background surface */
+static void
+paint_background (LoadGraph *g)
+{
+        cairo_t *cr;
+        cairo_pattern_t *highlight_grad;
+        cairo_pattern_t *glass_grad;
+        cairo_text_extents_t labels_extents;
+        int labels_line_height;
+        double graph_width, graph_height;
+	int real_graph_height;
+        double graph_left;
+        int width, height;
+	int delta_y;
+	int i;
+	int n_bars;
+        
+        cr = cairo_create (g->background);
+        
+        /* clear with background color */
+        cairo_set_source_rgb (cr, 0.45, 0.63, 0.81); // Sky blue
+        //cairo_set_source_rgb (cr, 0.31, 0.60, 0.02); // Chameleon
+        //cairo_set_source_rgb (cr, 0.53, 0.54, 0.52); // Aluminium
+        //cairo_set_source_rgb (cr, 0.68, 0.50, 0.66); // Plum
+        //cairo_set_source_rgb (cr, 0.76, 0.49, 0.07); // Chocolate
+        cairo_paint (cr);
 
+        /* compute label sizes */
+     	cairo_select_font_face (cr,
+			        "sans",
+			        CAIRO_FONT_SLANT_NORMAL,
+			        CAIRO_FONT_WEIGHT_NORMAL);
+	cairo_set_font_size (cr, FONT_SIZE);
+        cairo_text_extents (cr, "100 %", &labels_extents);
 
-/* Redraws the backing buffer for the load graph and updates the window */
-void
-load_graph_draw (LoadGraph *g)
-{
-	const double fontsize = 12.0;
-	const double rmargin = 3.5 * fontsize;
-	cairo_t *cr;
-	int dely;
-	double delx;
-	int real_draw_height;
-	guint i, j;
-	unsigned num_bars;
+        /* highlight */
+        width = g->draw_width;
+        height = g->draw_height;
+        graph_left = labels_extents.width + 2*FRAME_WIDTH;
+        graph_width = width - 3*FRAME_WIDTH - labels_extents.width;
+        graph_height = height - 2*FRAME_WIDTH;
+        g->graph_width = static_cast<int> (graph_width);
 
-	cr = cairo_create (g->buffer);
+        cairo_move_to (cr, 0.0, 0.0);
+        cairo_line_to (cr, width, 0.0);
+        cairo_line_to (cr, width, 0.15 * graph_height);
+        cairo_curve_to (cr, 0.66 * graph_width, 0.15 * graph_height,
+                            0.33 * graph_width, 0.4  * graph_height,
+                            0.0,                0.4  * graph_height);
+        cairo_close_path (cr);
 
-	/* clear */
-	gdk_cairo_set_source_color (cr, &(g->colors [0]));
-	cairo_paint (cr);
+        highlight_grad = cairo_pattern_create_linear (0.0, 0.0, 0.0, 0.4*height);
+        cairo_pattern_add_color_stop_rgba (highlight_grad, 0.0, 1.0, 1.0, 1.0, 0.3);
+        cairo_pattern_add_color_stop_rgba (highlight_grad, 1.0, 1.0, 1.0, 1.0, 0.05);
+        cairo_set_source (cr, highlight_grad);
+        cairo_fill (cr);
+        cairo_pattern_destroy (highlight_grad);
 
-	/* draw frame */
-	cairo_translate (cr, FRAME_WIDTH, FRAME_WIDTH);
-	gdk_cairo_set_source_color (cr, &(g->colors [1]));
-	cairo_set_line_width (cr, 1.0);
-	cairo_select_font_face(cr,
-			       "monospace",
-			       CAIRO_FONT_SLANT_NORMAL,
-			       CAIRO_FONT_WEIGHT_NORMAL);
-	cairo_set_font_size(cr, fontsize);
+        /* graph frame */
+        /* take into account that 0% and 100% are slightly offset */
+        labels_line_height = static_cast<int> (labels_extents.height * 1.5 + 3);
+        n_bars = std::min ((static_cast<int> (graph_height) / labels_line_height) + 1, 6);
+        /* disallow disgracious n_bars = 4 */
+        if (n_bars == 4) {
+            n_bars = 3;
+        }
 
-	// keep 100 % num_bars == 0
-	switch (static_cast<int>(g->draw_height / (fontsize + 3)))
-	  {
-	  case 1:
-	    num_bars = 1;
-	    break;
-	  case 2:
-	  case 3:
-	    num_bars = 2;
-	    break;
-	  case 4:
-	    num_bars = 4;
-	    break;
-	  default:
-	    num_bars = 5;
-	  }
+	delta_y = static_cast<int> (graph_height / (n_bars-1));
+	real_graph_height = delta_y * (n_bars-1);
+        g->graph_height = real_graph_height;
 
-	dely = g->draw_height / num_bars; /* round to int to avoid AA blur */
-	real_draw_height = dely * num_bars;
+        cairo_set_line_width (cr, 1.0);
 
-	for (i = 0; i <= num_bars; ++i) {
+	for (i = 0; i < n_bars; ++i) {
+                cairo_text_extents_t extents;
 		char *caption;
 		double y;
 
-		if (i == 0)
-		  y = 0.5 + fontsize / 2.0;
-		else if (i == num_bars)
-		  y = i * dely + 0.5;
-		else
-		  y = i * dely + fontsize / 2.0;
+		if (i == 0) {
+		        y = 0.5 + labels_extents.height;
+                } else if (i == (n_bars-1)) {
+		        y = i * delta_y + 0.5;
+                } else {
+		        y = i * delta_y + labels_extents.height / 2.0;
+                }
 
-		cairo_move_to(cr, 0.0, y);
-		caption = g_strdup_printf("%3d %%", 100 - i * (100 / num_bars));
-		cairo_show_text(cr, caption);
-		g_free(caption);
-
-		cairo_move_to (cr, rmargin, i * dely + 0.5);
-		cairo_line_to (cr, g->draw_width - 0.5, i * dely + 0.5);
+		caption = g_strdup_printf ("%d %%", 100 - i * (100 / (n_bars-1)));
+                cairo_text_extents (cr, caption, &extents);
+                
+                cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8);
+		cairo_move_to (cr, FRAME_WIDTH + labels_extents.width - extents.width,
+                                   FRAME_WIDTH + y);
+		cairo_show_text (cr, caption);
+		g_free (caption);
+                
+                if ((i == 0) || (i == (n_bars-1))) {
+                    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);
+                } else {
+                    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.25);
+                }
+		cairo_move_to (cr, 2*FRAME_WIDTH + labels_extents.width + 0.5,
+                                   FRAME_WIDTH + i * delta_y + 0.5);
+		cairo_rel_line_to (cr, graph_width - 0.5, 0.0);
+	        cairo_stroke (cr);
 	}
 
-	cairo_move_to (cr, rmargin, 0.5);
-	cairo_line_to (cr, rmargin, real_draw_height + 0.5);
+	cairo_move_to (cr, labels_extents.width + 2*FRAME_WIDTH + 0.5, FRAME_WIDTH + 0.5);
+	cairo_rel_line_to (cr, 0.0, real_graph_height + 0.5);
 
-	cairo_move_to (cr, g->draw_width - 0.5, 0.5);
-	cairo_line_to (cr, g->draw_width - 0.5, real_draw_height + 0.5);
+	cairo_move_to (cr, width - FRAME_WIDTH - 0.5, FRAME_WIDTH + 0.5);
+	cairo_rel_line_to (cr, 0.0, real_graph_height + 0.5);
 
 	cairo_stroke (cr);
 
+        /* glass pane */
+        glass_grad = cairo_pattern_create_linear (0.0, 0.0, 0.0, graph_height);
+        cairo_pattern_add_color_stop_rgba (glass_grad, 0.0, 1.0, 1.0, 1.0, 0.1);
+        cairo_pattern_add_color_stop_rgba (glass_grad, 0.66, 1.0, 1.0, 1.0, 0.0);
+        cairo_pattern_add_color_stop_rgba (glass_grad, 1.0, 1.0, 1.0, 1.0, 0.3);
+        cairo_set_source (cr, glass_grad);
+        cairo_rectangle (cr, graph_left, FRAME_WIDTH, graph_width, real_graph_height); 
+        cairo_fill (cr);
+        cairo_pattern_destroy (glass_grad);
+        
+        cairo_destroy (cr);
+}
+
+
+
+/* Redraws the backing buffer for the load graph and updates the window */
+void
+load_graph_draw (LoadGraph *g)
+{
+	cairo_t *cr;
+	double delta_x;
+	guint i, j;
+        int graph_height;
+
+	cr = cairo_create (g->buffer);
+
+	/* paint cached background */
+        cairo_set_source_surface (cr, g->background, 0.0, 0.0);
+        cairo_paint (cr);
+
 	/* draw the graph */
-	cairo_set_line_width (cr, 2.0);
+	cairo_set_line_width (cr, 1.5);
 	cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
 	cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
 
-	delx = (g->draw_width - 2.0 - rmargin) / (NUM_POINTS - 1);
-
+	delta_x = (g->graph_width - 2.0) / (NUM_POINTS - 1);
+        graph_height = g->graph_height;
+        cairo_translate (cr, g->draw_width - FRAME_WIDTH, FRAME_WIDTH);
 	for (j = 0; j < g->n; ++j) {
-		cairo_move_to (cr,
-			       g->draw_width - 2.0,
-			       (1.0f - g->data[0][j]) * real_draw_height);
+		cairo_move_to (cr, -2.0, (1.0 - g->data[0][j]) * graph_height);
 		gdk_cairo_set_source_color (cr, &(g->colors [j + 2]));
 
 		for (i = 1; i < NUM_POINTS; ++i) {
+                        double x, x_prev;
+
 			if (g->data[i][j] == -1.0f)
 				continue;
-
+                        
+                        x_prev = - ((i-1.0) * delta_x);
+                        x = - (i * delta_x);
 			cairo_curve_to (cr, 
-				       (g->draw_width - (i-1) * delx) - (delx/2),
-				       (1.0f - g->data[i-1][j]) * real_draw_height,
-				       (g->draw_width - i * delx) + (delx/2),
-				       (1.0f - g->data[i][j]) * real_draw_height,
-				       g->draw_width - i * delx,
-				       (1.0f - g->data[i][j]) * real_draw_height);
+				        x_prev - (delta_x / 2),
+				        (1.0 - g->data[i-1][j]) * graph_height,
+				        x + (delta_x / 2),
+				        (1.0 - g->data[i][j]) * graph_height,
+				        x,
+				        (1.0 - g->data[i][j]) * graph_height);
 		}
 
 		cairo_stroke (cr);
@@ -205,21 +276,32 @@
 	LoadGraph * const g = static_cast<LoadGraph*>(data_ptr);
 	cairo_t *cr;
 
-	g->draw_width = widget->allocation.width - 2 * FRAME_WIDTH;
-	g->draw_height = widget->allocation.height - 2 * FRAME_WIDTH;
+	g->draw_width = widget->allocation.width;
+	g->draw_height = widget->allocation.height;
 
 	cr = gdk_cairo_create (widget->window);
 
 	if (g->buffer)
 		cairo_surface_destroy (g->buffer);
 
+
 	g->buffer = cairo_surface_create_similar (cairo_get_target (cr),
 						  CAIRO_CONTENT_COLOR,
 						  widget->allocation.width,
 						  widget->allocation.height);
 
-	cairo_destroy (cr);
+        if (g->background)
+		cairo_surface_destroy (g->background);
 
+	g->background = cairo_surface_create_similar (cairo_get_target (cr),
+						      CAIRO_CONTENT_COLOR,
+						      widget->allocation.width,
+						      widget->allocation.height);
+        
+        paint_background (g);
+
+        cairo_destroy (cr);
+
 	load_graph_draw (g);
 
 	return TRUE;
