From b73a8f243ea4446f39012d7a64c107c25ff6d854 Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Fri, 30 Sep 2011 11:34:38 -0400 Subject: 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(-) (limited to 'widgets') diff --git a/widgets/table/e-table-field-chooser-item.c b/widgets/table/e-table-field-chooser-item.c index ecc414853c..67fe22968f 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 11d8f31f81..b8aa55f369 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 34f93a701b..431009016f 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, >k_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 c3b2de89c7..e6d2aaba1d 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 007803585e..a534f22f07 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); -- cgit