[evolution] ETableHeader: Rework the header button drawing code for GTK+ 3



commit b73a8f243ea4446f39012d7a64c107c25ff6d854
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Fri Sep 30 11:34:38 2011 -0400

    ETableHeader: Rework the header button drawing code for GTK+ 3
    
    The code in ETable that draws the button headers is outdated, and uses
    deprecated gtk_paint_* functions mixed with cairo.
    
    Port the code to use the GtkStyleContext API, which allows themes to
    give the header the same appearance of a regular GtkTreeView header.

 widgets/table/e-table-field-chooser-item.c |   36 ++-------
 widgets/table/e-table-header-item.c        |   49 ++++++------
 widgets/table/e-table-header-utils.c       |  119 ++++++++++++++--------------
 widgets/table/e-table-header-utils.h       |    4 +-
 widgets/table/e-table-utils.c              |    5 +-
 5 files changed, 93 insertions(+), 120 deletions(-)
---
diff --git a/widgets/table/e-table-field-chooser-item.c b/widgets/table/e-table-field-chooser-item.c
index ecc4148..67fe229 100644
--- a/widgets/table/e-table-field-chooser-item.c
+++ b/widgets/table/e-table-field-chooser-item.c
@@ -491,17 +491,12 @@ etfci_draw (GnomeCanvasItem *item,
 	gint rows;
 	gint y1, y2;
 	gint row;
-	GtkStyle *style;
-	GtkStateType state;
 
 	if (etfci->combined_header == NULL)
 		return;
 
 	rows = e_table_header_count (etfci->combined_header);
 
-	style = gtk_widget_get_style (GTK_WIDGET (canvas));
-	state = gtk_widget_get_state (GTK_WIDGET (canvas));
-
 	y1 = y2 = 0;
 	for (row = 0; row < rows; row++, y1 = y2) {
 		ETableCol *ecol;
@@ -519,17 +514,12 @@ etfci_draw (GnomeCanvasItem *item,
 		if (y2 < y)
 			continue;
 
-		cairo_save (cr);
-
 		e_table_header_draw_button (cr, ecol,
-					    style, state,
 					    GTK_WIDGET (canvas),
 					    -x, y1 - y,
 					    width, height,
 					    etfci->width, y2 - y1,
 					    E_TABLE_COL_ARROW_NONE);
-
-		cairo_restore (cr);
 	}
 }
 
@@ -567,15 +557,11 @@ etfci_start_drag (ETableFieldChooserItem *etfci,
 	GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (etfci)->canvas);
 	GtkTargetList *list;
 	GdkDragContext *context;
-	GdkWindow *window;
-	GtkStyle *style;
-	GtkStateType state;
 	ETableCol *ecol;
 	cairo_surface_t *cs;
 	cairo_t *cr;
 	gint drag_col;
 	gint button_height;
-	GdkPixbuf *pixbuf;
 
 	GtkTargetEntry  etfci_drag_types[] = {
 		{ (gchar *) TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER },
@@ -604,28 +590,18 @@ etfci_start_drag (ETableFieldChooserItem *etfci,
 	g_free ((gpointer) etfci_drag_types[0].target);
 
 	button_height = e_table_header_compute_height (ecol, widget);
-	window = gtk_widget_get_window (widget);
-	cs = gdk_window_create_similar_surface (
-		window, CAIRO_CONTENT_COLOR, etfci->width, button_height);
-
-	style = gtk_widget_get_style (widget);
-	state = gtk_widget_get_state (widget);
-
+	cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+					 etfci->width, button_height);
 	cr = cairo_create (cs);
+
 	e_table_header_draw_button (
-		cr, ecol, style,
-		state, widget, 0, 0,
+		cr, ecol,
+		widget, 0, 0,
 		etfci->width, button_height,
 		etfci->width, button_height,
 		E_TABLE_COL_ARROW_NONE);
 
-	pixbuf = gdk_pixbuf_get_from_window (window, 0, 0, etfci->width, button_height);
-	gtk_drag_set_icon_pixbuf (
-		context,
-		pixbuf,
-		etfci->width / 2,
-		button_height / 2);
-	g_object_unref (pixbuf);
+	gtk_drag_set_icon_surface (context, cs);
 
 	cairo_surface_destroy (cs);
 	cairo_destroy (cr);
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c
index 11d8f31..b8aa55f 100644
--- a/widgets/table/e-table-header-item.c
+++ b/widgets/table/e-table-header-item.c
@@ -996,9 +996,7 @@ ethi_draw (GnomeCanvasItem *item,
 	gint x1, x2;
 	gint col;
 	GHashTable *arrows = g_hash_table_new (NULL, NULL);
-	GtkStyle *style;
-
-	style = gtk_widget_get_style (GTK_WIDGET (canvas));
+	GtkStyleContext *context;
 
 	if (ethi->sort_info) {
 		gint length;
@@ -1040,10 +1038,13 @@ ethi_draw (GnomeCanvasItem *item,
 	ethi->width = e_table_header_total_width (ethi->eth) + ethi->group_indent_width;
 	x1 = x2 = 0;
 	x2 += ethi->group_indent_width;
+
+	context = gtk_widget_get_style_context (GTK_WIDGET (canvas));
+
 	for (col = 0; col < cols; col++, x1 = x2) {
 		ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
-		GtkStateType state;
 		gint col_width;
+		GtkRegionFlags flags = 0;
 
 		col_width = ecol->width;
 
@@ -1058,15 +1059,29 @@ ethi_draw (GnomeCanvasItem *item,
 		if (x2 <= x1)
 			continue;
 
-		state = gtk_widget_get_state (GTK_WIDGET (canvas));
+		if (((col + 1) % 2) == 0)
+			flags |= GTK_REGION_EVEN;
+		else
+			flags |= GTK_REGION_ODD;
+
+		if (col == 0)
+			flags |= GTK_REGION_FIRST;
+
+		if (col + 1 == cols)
+			flags |= GTK_REGION_LAST;
+
+		gtk_style_context_save (context);
+		gtk_style_context_add_region (
+			context, GTK_STYLE_REGION_COLUMN_HEADER, flags);
 
 		e_table_header_draw_button (
-			cr, ecol,
-			style, state, GTK_WIDGET (canvas),
+			cr, ecol, GTK_WIDGET (canvas),
 			x1 - x, -y, width, height,
 			x2 - x1, ethi->height,
 			(ETableColArrow) g_hash_table_lookup (
 			arrows, GINT_TO_POINTER (ecol->col_idx)));
+
+		gtk_style_context_restore (context);
 	}
 
 	g_hash_table_destroy (arrows);
@@ -1209,22 +1224,16 @@ ethi_start_drag (ETableHeaderItem *ethi,
 	ETableCol *ecol;
 	gint col_width;
 	cairo_surface_t *s;
-	GdkPixbuf *pixbuf;
 	cairo_t *cr;
 
 	gint group_indent = 0;
 	GHashTable *arrows = g_hash_table_new (NULL, NULL);
-	GtkStateType state;
-	GtkStyle *style;
 
 	GtkTargetEntry  ethi_drag_types[] = {
 		{ (gchar *) TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER },
 	};
 
 	widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas);
-	state = gtk_widget_get_state (widget);
-	style = gtk_widget_get_style (widget);
-
 	ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x);
 
 	if (ethi->drag_col == -1)
@@ -1269,27 +1278,17 @@ ethi_start_drag (ETableHeaderItem *ethi,
 
 	ecol = e_table_header_get_column (ethi->eth, ethi->drag_col);
 	col_width = ecol->width;
-	s = cairo_image_surface_create (CAIRO_FORMAT_A1, col_width, ethi->height);
+	s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, col_width, ethi->height);
 	cr = cairo_create (s);
-	pixbuf = gdk_pixbuf_get_from_surface (
-		s, 0, 0, col_width, ethi->height);
-
-	state = gtk_widget_get_state (widget);
 
 	e_table_header_draw_button (
 		cr, ecol,
-		style, state,
 		widget, 0, 0,
 		col_width, ethi->height,
 		col_width, ethi->height,
 		(ETableColArrow) g_hash_table_lookup (
 			arrows, GINT_TO_POINTER (ecol->col_idx)));
-	gtk_drag_set_icon_pixbuf (
-		context,
-		pixbuf,
-		col_width / 2,
-		ethi->height / 2);
-	g_object_unref (pixbuf);
+	gtk_drag_set_icon_surface (context, s);
 	cairo_surface_destroy (s);
 
 	ethi->maybe_drag = FALSE;
diff --git a/widgets/table/e-table-header-utils.c b/widgets/table/e-table-header-utils.c
index 34f93a7..4310090 100644
--- a/widgets/table/e-table-header-utils.c
+++ b/widgets/table/e-table-header-utils.c
@@ -60,6 +60,23 @@ build_header_layout (GtkWidget *widget,
 	return layout;
 }
 
+static void
+get_button_padding (GtkWidget *widget,
+                    GtkBorder *padding)
+{
+	GtkStyleContext *context;
+	GtkStateFlags state_flags;
+
+	context = gtk_widget_get_style_context (widget);
+	state_flags = gtk_widget_get_state_flags (widget);
+
+	gtk_style_context_save (context);
+	gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
+	gtk_style_context_get_padding (context, state_flags, padding);
+
+	gtk_style_context_restore (context);
+}
+
 /**
  * e_table_header_compute_height:
  * @ecol: Table column description.
@@ -73,15 +90,15 @@ gdouble
 e_table_header_compute_height (ETableCol *ecol,
                                GtkWidget *widget)
 {
-	gint ythick;
 	gint height;
 	PangoLayout *layout;
+	GtkBorder padding;
 
 	g_return_val_if_fail (ecol != NULL, -1);
 	g_return_val_if_fail (E_IS_TABLE_COL (ecol), -1);
 	g_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
 
-	ythick = gtk_widget_get_style (widget)->ythickness;
+	get_button_padding (widget, &padding);
 
 	layout = build_header_layout (widget, ecol->text);
 
@@ -93,8 +110,7 @@ e_table_header_compute_height (ETableCol *ecol,
 	}
 
 	height = MAX (height, MIN_ARROW_SIZE);
-
-	height += 2 * (ythick + HEADER_PADDING);
+	height += padding.top + padding.bottom + 2 * HEADER_PADDING;
 
 	g_object_unref (layout);
 
@@ -102,11 +118,12 @@ e_table_header_compute_height (ETableCol *ecol,
 }
 
 gdouble
-e_table_header_width_extras (GtkStyle *style)
+e_table_header_width_extras (GtkWidget *widget)
 {
-	g_return_val_if_fail (style != NULL, -1);
+	GtkBorder padding;
 
-	return 2 * (style->xthickness + HEADER_PADDING);
+	get_button_padding (widget, &padding);
+	return padding.left + padding.right + 2 * HEADER_PADDING;
 }
 
 /* Creates a pixmap that is a composite of a background color and the upper-left
@@ -233,8 +250,6 @@ make_composite_pixmap (GdkDrawable *drawable,
  * e_table_header_draw_button:
  * @drawable: Destination drawable.
  * @ecol: Table column for the header information.
- * @style: Style to use for drawing the button.
- * @state: State of the table widget.
  * @widget: The table widget.
  * @x: Leftmost coordinate of the button.
  * @y: Topmost coordinate of the button.
@@ -249,8 +264,6 @@ make_composite_pixmap (GdkDrawable *drawable,
 void
 e_table_header_draw_button (cairo_t *cr,
                             ETableCol *ecol,
-                            GtkStyle *style,
-                            GtkStateType state,
                             GtkWidget *widget,
                             gint x,
                             gint y,
@@ -260,58 +273,49 @@ e_table_header_draw_button (cairo_t *cr,
                             gint button_height,
                             ETableColArrow arrow)
 {
-	gint xthick, ythick;
 	gint inner_x, inner_y;
 	gint inner_width, inner_height;
 	gint arrow_width = 0, arrow_height = 0;
 	PangoLayout *layout;
-	static gpointer g_label = NULL;
+	GtkStyleContext *context;
+	GtkBorder padding;
+	GtkStateFlags state_flags;
 
 	g_return_if_fail (cr != NULL);
 	g_return_if_fail (ecol != NULL);
 	g_return_if_fail (E_IS_TABLE_COL (ecol));
-	g_return_if_fail (style != NULL);
 	g_return_if_fail (widget != NULL);
 	g_return_if_fail (GTK_IS_WIDGET (widget));
 	g_return_if_fail (button_width > 0 && button_height > 0);
 
-	if (g_label == NULL) {
-		GtkWidget *button = gtk_button_new_with_label("Hi");
-		GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-		gtk_container_add (GTK_CONTAINER (window), button);
-		gtk_widget_ensure_style (window);
-		gtk_widget_ensure_style (button);
-		g_label = gtk_bin_get_child (GTK_BIN (button));
-		g_object_add_weak_pointer (G_OBJECT (g_label), &g_label);
-		gtk_widget_ensure_style (g_label);
-		gtk_widget_realize (g_label);
-	}
-
-	cairo_save (cr);
-	gdk_cairo_set_source_color (
-		cr, &gtk_widget_get_style (GTK_WIDGET (g_label))->fg[state]);
+	/* Button bevel */
+	context = gtk_widget_get_style_context (widget);
+	state_flags = gtk_widget_get_state_flags (widget);
 
-	xthick = style->xthickness;
-	ythick = style->ythickness;
+	gtk_style_context_save (context);
+	gtk_style_context_set_state (context, state_flags);
+	gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
 
-	/* Button bevel */
+	gtk_style_context_get_padding (context, state_flags, &padding);
 
-	gtk_paint_box (style, cr, state, GTK_SHADOW_OUT,
-		       widget, "button",
-		       x, y, button_width, button_height);
+	gtk_render_background (
+		context, cr, x, y,
+		button_width, button_height);
+	gtk_render_frame (
+		context, cr, x, y,
+		button_width, button_height);
 
 	/* Inside area */
 
-	inner_width = button_width - 2 * (xthick + HEADER_PADDING);
-	inner_height = button_height - 2 * (ythick + HEADER_PADDING);
+	inner_width = button_width - (padding.left + padding.right + 2 * HEADER_PADDING);
+	inner_height = button_height - (padding.top + padding.bottom + 2 * HEADER_PADDING);
 
 	if (inner_width < 1 || inner_height < 1) {
-		cairo_restore (cr);
 		return; /* nothing fits */
 	}
 
-	inner_x = x + xthick + HEADER_PADDING;
-	inner_y = y + ythick + HEADER_PADDING;
+	inner_x = x + padding.left + HEADER_PADDING;
+	inner_y = y + padding.top + HEADER_PADDING;
 
 	/* Arrow space */
 
@@ -328,12 +332,11 @@ e_table_header_draw_button (cairo_t *cr,
 			inner_width -= arrow_width + HEADER_PADDING;
 		break;
 	default:
-		cairo_restore (cr);
 		g_return_if_reached ();
 	}
 
 	if (inner_width < 1) {
-		cairo_restore (cr);
+		gtk_style_context_restore (context);
 		return; /* nothing else fits */
 	}
 
@@ -370,18 +373,19 @@ e_table_header_draw_button (cairo_t *cr,
 				layout, (inner_width - (xpos - inner_x)) *
 				PANGO_SCALE);
 
-			cairo_move_to (cr, xpos + pwidth + 1, ypos);
-			pango_cairo_show_layout (cr, layout);
+			gtk_render_layout (
+				context, cr, xpos + pwidth + 1,
+				ypos, layout);
 		}
 
-		gdk_cairo_set_source_pixbuf (cr, ecol->pixbuf,
-					     xpos, inner_y + (inner_height - clip_height) / 2);
-		cairo_paint (cr);
+		gtk_render_icon (
+			context, cr, ecol->pixbuf, xpos,
+			inner_y + (inner_height - clip_height) / 2);
+
 	} else {
 		pango_layout_set_width (layout, inner_width * PANGO_SCALE);
 
-		cairo_move_to (cr, inner_x, inner_y);
-		pango_cairo_show_layout (cr, layout);
+		gtk_render_layout (context, cr, inner_x, inner_y, layout);
 	}
 
 	switch (arrow) {
@@ -393,21 +397,20 @@ e_table_header_draw_button (cairo_t *cr,
 		if (ecol->icon_name == NULL)
 			inner_width += arrow_width + HEADER_PADDING;
 
-		gtk_paint_arrow (style, cr, state,
-				 GTK_SHADOW_NONE, widget, "header",
-				 (arrow == E_TABLE_COL_ARROW_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN,
-				 (ecol->icon_name == NULL),
-				 inner_x + inner_width - arrow_width,
-				 inner_y + (inner_height - arrow_height) / 2,
-				 arrow_width, arrow_height);
+		gtk_render_arrow (
+			context, cr,
+			(arrow == E_TABLE_COL_ARROW_UP) ? 0 : G_PI,
+			inner_x + inner_width - arrow_width,
+			inner_y + (inner_height - arrow_height) / 2,
+			MAX (arrow_width, arrow_height));
+
 		break;
 	}
 
 	default:
-		cairo_restore (cr);
 		g_return_if_reached ();
 	}
 
 	g_object_unref (layout);
-	cairo_restore (cr);
+	gtk_style_context_restore (context);
 }
diff --git a/widgets/table/e-table-header-utils.h b/widgets/table/e-table-header-utils.h
index c3b2de8..e6d2aab 100644
--- a/widgets/table/e-table-header-utils.h
+++ b/widgets/table/e-table-header-utils.h
@@ -32,11 +32,9 @@ G_BEGIN_DECLS
 
 gdouble		e_table_header_compute_height	(ETableCol *ecol,
 						 GtkWidget *widget);
-gdouble		e_table_header_width_extras	(GtkStyle *style);
+gdouble		e_table_header_width_extras	(GtkWidget *widget);
 void		e_table_header_draw_button	(cairo_t *cr,
 						 ETableCol *ecol,
-						 GtkStyle *style,
-						 GtkStateType state,
 						 GtkWidget *widget,
 						 gint x,
 						 gint y,
diff --git a/widgets/table/e-table-utils.c b/widgets/table/e-table-utils.c
index 0078035..a534f22 100644
--- a/widgets/table/e-table-utils.c
+++ b/widgets/table/e-table-utils.c
@@ -40,7 +40,6 @@ e_table_state_to_header (GtkWidget *widget,
                          ETableState *state)
 {
 	ETableHeader *nh;
-	GtkStyle *style;
 	const gint max_cols = e_table_header_count (full_header);
 	gint column;
 	GValue *val = g_new0 (GValue, 1);
@@ -49,11 +48,9 @@ e_table_state_to_header (GtkWidget *widget,
 	g_return_val_if_fail (full_header, NULL);
 	g_return_val_if_fail (state, NULL);
 
-	style = gtk_widget_get_style (widget);
-
 	nh = e_table_header_new ();
 	g_value_init (val, G_TYPE_DOUBLE);
-	g_value_set_double (val, e_table_header_width_extras (style));
+	g_value_set_double (val, e_table_header_width_extras (widget));
 	g_object_set_property (G_OBJECT(nh), "width_extras", val);
 	g_free (val);
 



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