diff options
author | Owen Taylor <otaylor@redhat.com> | 2005-04-04 20:51:24 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2005-04-04 20:51:24 +0000 |
commit | f15a260ce03d9cbe9a565c5f80b439f6ad4efd29 (patch) | |
tree | 09b37f734c0ca6792c7555729c493fb2412c0922 /gtk/gtkstyle.c | |
parent | 3a51a0bc897cb9012746646f6a78967ccd9a495a (diff) | |
download | gtk+-f15a260ce03d9cbe9a565c5f80b439f6ad4efd29.tar.gz |
Covert expander drawing to Cairo. Also always draw the entire triangle
2005-04-04 Owen Taylor <otaylor@redhat.com>
* gtk/gtkstyle.c (gtk_default_draw_expander): Covert expander
drawing to Cairo. Also always draw the entire triangle instead
of just drawing the center for prelight. (Fixes inconsistent
drawing in GtkTreeView.)
Diffstat (limited to 'gtk/gtkstyle.c')
-rw-r--r-- | gtk/gtkstyle.c | 204 |
1 files changed, 92 insertions, 112 deletions
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index cca2b27b9c..c27b514a46 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -4787,72 +4787,6 @@ gtk_default_draw_handle (GtkStyle *style, } static void -create_expander_affine (gdouble affine[6], - gint degrees, - gint expander_size, - gint x, - gint y) -{ - gdouble s, c; - gdouble width; - gdouble height; - - width = expander_size / 4.0; - height = expander_size / 2.0; - - switch (degrees) - { - case 0: - s = 0.0; - c = 1.0; - break; - case 90: - s = 1.0; - c = 0.0; - break; - case 180: - s = 0.0; - c = -1.0; - break; - default: - s = sin (degrees * G_PI / 180.0); - c = cos (degrees * G_PI / 180.0); - break; - } - - affine[0] = c; - affine[1] = s; - affine[2] = -s; - affine[3] = c; - affine[4] = -width * c - height * -s + x; - affine[5] = -width * s - height * c + y; -} - -static void -apply_affine_on_point (double affine[6], GdkPoint *point) -{ - gdouble x, y; - - x = point->x * affine[0] + point->y * affine[2] + affine[4]; - y = point->x * affine[1] + point->y * affine[3] + affine[5]; - - point->x = floor (x); - point->y = floor (y); -} - -static void -gtk_style_draw_polygon_with_gc (GdkWindow *window, GdkGC *gc, gint line_width, - gboolean do_fill, GdkPoint *points, gint n_points) -{ - gdk_gc_set_line_attributes (gc, line_width, - GDK_LINE_SOLID, - GDK_CAP_BUTT, GDK_JOIN_MITER); - - gdk_draw_polygon (window, gc, do_fill, points, n_points); - gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); -} - -static void gtk_default_draw_expander (GtkStyle *style, GdkWindow *window, GtkStateType state_type, @@ -4863,34 +4797,38 @@ gtk_default_draw_expander (GtkStyle *style, gint y, GtkExpanderStyle expander_style) { +#define DEFAULT_EXPANDER_SIZE 12 + gint expander_size; - GdkPoint points[3]; - gint i; - gint line_width, o; - gdouble affine[6]; + gint line_width; + double vertical_overshoot; + int diameter; + double radius; + double x_double, y_double; gint degrees = 0; - gtk_widget_style_get (widget, - "expander-size", &expander_size, - NULL); - line_width = MAX (1, expander_size/9); - + cairo_t *cr = gdk_drawable_create_cairo_context (window); + if (area) { - gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area); - gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area); + cairo_save (cr); + cairo_rectangle (cr, area->x, area->y, area->width, area->height); + cairo_clip (cr); + cairo_new_path (cr); } - /* a rough estimate of how much the joins of the triangle will overshoot. - * 2.4 ~ 1 / tan (45 / 2) - */ - o = ceil (2.4 * line_width / 2.0); - points[0].x = line_width / 2; - points[0].y = o; - points[1].x = expander_size / 2 + line_width / 2 - o; - points[1].y = expander_size / 2; - points[2].x = line_width / 2; - points[2].y = expander_size - o; + if (widget && + gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget), + "expander-size")) + { + gtk_widget_style_get (widget, + "expander-size", &expander_size, + NULL); + } + else + expander_size = DEFAULT_EXPANDER_SIZE; + + line_width = MAX (1, expander_size/9); switch (expander_style) { @@ -4910,35 +4848,67 @@ gtk_default_draw_expander (GtkStyle *style, g_assert_not_reached (); } - create_expander_affine (affine, degrees, expander_size, x, y); + /* Compute distance that the stroke extends beyonds the end + * of the triangle we draw. + */ + vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8)); - for (i = 0; i < 3; i++) - apply_affine_on_point (affine, &points[i]); + /* For odd line widths, we end the vertical line of the triangle + * at a half pixel, so we round differently. + */ + if (line_width % 2 == 1) + vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5; + else + vertical_overshoot = ceil (vertical_overshoot); + + /* Adjust the size of the triangle we draw so that the entire stroke fits + */ + diameter = MAX (3, expander_size - 2 * vertical_overshoot); + + /* If the line width is odd, we want the diameter to be even, + * and vice versa, so force the sum to be odd + */ + diameter -= (1 - (diameter + line_width) % 2); + + radius = diameter / 2.; + + /* Adjust the center so that the stroke is properly aligned with + * the pixel grid + */ + x_double = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.; + y_double = y + 0.5; + + cairo_translate (cr, x_double, y_double); + cairo_rotate (cr, degrees * M_PI / 180); + + cairo_move_to (cr, - radius / 2., - radius); + cairo_line_to (cr, radius / 2., 0); + cairo_line_to (cr, - radius / 2., radius); + cairo_close_path (cr); + + cairo_set_line_width (cr, line_width); + cairo_save (cr); if (state_type == GTK_STATE_PRELIGHT) - { - gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_PRELIGHT], - 1, TRUE, points, 3); - } + gdk_cairo_set_source_color (cr, + &style->fg[GTK_STATE_PRELIGHT]); else if (state_type == GTK_STATE_ACTIVE) - { - gtk_style_draw_polygon_with_gc (window, style->light_gc[GTK_STATE_ACTIVE], - 1, TRUE, points, 3); - gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL], - line_width, FALSE, points, 3); - } + gdk_cairo_set_source_color (cr, + &style->light[GTK_STATE_ACTIVE]); else - { - gtk_style_draw_polygon_with_gc (window, style->base_gc[GTK_STATE_NORMAL], - 1, TRUE, points, 3); - gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL], - line_width, FALSE, points, 3); - } + gdk_cairo_set_source_color (cr, + &style->base[GTK_STATE_NORMAL]); + + cairo_fill (cr); + cairo_restore (cr); + + gdk_cairo_set_source_color (cr, &style->fg[state_type]); + cairo_stroke (cr); + if (area) - { - gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL); - gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL); - } + cairo_restore (cr); + + cairo_destroy (cr); } typedef struct _ByteRange ByteRange; @@ -6317,9 +6287,19 @@ gtk_paint_handle (GtkStyle *style, * @detail: a style detail (may be %NULL) * @x: the x position to draw the expander at * @y: the y position to draw the expander at - * @expander_style: the style to draw the expander in + * @expander_style: the style to draw the expander in; determines + * whether the expander is collapsed, expanded, or in an + * intermediate state. * - * Draws an expander as used in #GtkTreeView. + * Draws an expander as used in #GtkTreeView. @x and @y specify the + * center the expander. The size of the expander is determined by the + * "expander-size" style property of @widget. (If widget is not + * specified or doesn't have an "expander-size" property, an + * unspecified default size will be used, since the caller doesn't + * have sufficient information to position the expander, this is + * likely not useful.) The expander is expander_size pixels tall + * in the collapsed position and expander_size pixels wide in the + * expanded position. **/ void gtk_paint_expander (GtkStyle *style, |