diff options
Diffstat (limited to 'eazel-engine/src/eazel-theme-draw.c.dim')
-rw-r--r-- | eazel-engine/src/eazel-theme-draw.c.dim | 2342 |
1 files changed, 2342 insertions, 0 deletions
diff --git a/eazel-engine/src/eazel-theme-draw.c.dim b/eazel-engine/src/eazel-theme-draw.c.dim new file mode 100644 index 0000000..6062b22 --- /dev/null +++ b/eazel-engine/src/eazel-theme-draw.c.dim @@ -0,0 +1,2342 @@ +/* eazel-theme-draw.c -- replacement drawing `primitives' + + Copyright (C) 2000 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: eazel-theme-draw.c,v 1.21 2001/05/23 04:56:34 jsh Exp $ + + Authors: The Rasterman <raster@redhat.com> + Owen Taylor <otaylor@redhat.com> + John Harper <jsh@eazel.com> */ + +/* Adapted from gtk-engines/notif/notif_theme_draw.c + + Repeat after me: ``the implementation is unimportant, the only thing + that matters is the user-experience'' */ + +#include "eazel-theme.h" +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#define DEBUG 0 + +#define DETAIL(xx) ((detail) != 0 && strcmp (xx, detail) == 0) + + +/* utility functions */ + +static inline void +debug (const char *fmt, ...) +{ + if (DEBUG) + { + va_list args; + va_start (args, fmt); + vfprintf (stderr, fmt, args); + va_end (args); + } +} + +/* adapted from nautilus-gdk-extensions.c */ +static void +interpolate_color (GdkColor *dest, gdouble ratio, + GdkColor *start, GdkColor *end) +{ + g_return_if_fail (ratio >= 0.0); + g_return_if_fail (ratio <= 1.0); + + dest->red = start->red * (1.0 - ratio) + (end->red & 0xFF) * ratio; + dest->green = start->green * (1.0 - ratio) + end->green * ratio; + dest->blue = start->blue * (1.0 - ratio) + end->blue * ratio; +} + +static void +paint_background_area (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + int x, int y, int width, int height) +{ + GdkGC *gc = style->bg_gc[GTK_STATE_NORMAL]; + + if (area != 0) + gdk_gc_set_clip_rectangle (gc, area); + + gdk_draw_rectangle (window, gc, TRUE, x, y, width, height); + + if (area != 0) + gdk_gc_set_clip_rectangle (gc, 0); +} + +static void +paint_stock_image (eazel_theme_data *theme_data, + eazel_engine_stock_image type, + gboolean scaled, gboolean setbg, + GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + gint x, gint y, gint width, gint height) +{ + GdkPixmap *pixmap, *mask; + + if (width == -1 || height == -1) + { + eazel_engine_stock_get_size (theme_data->stock, type, + width == -1 ? &width : 0, + height == -1 ? &height : 0); + } + + if (scaled) + { + eazel_engine_stock_pixmap_and_mask_scaled (theme_data->stock, type, + width, height, + &pixmap, &mask); + } + else + eazel_engine_stock_pixmap_and_mask (theme_data->stock, type, + &pixmap, &mask); + + if (gdk_window_get_type (window) == GDK_WINDOW_PIXMAP) + setbg = FALSE; + + if (setbg) + { + gdk_draw_pixmap (window, style->fg_gc[state_type], pixmap, + 0, 0, x, y, width, height); + if (mask != 0) + gdk_window_shape_combine_mask (window, mask, 0, 0); + } + else + { + int xsrc = 0, ysrc = 0; + + /* Install the mask before clipping.. */ + if (mask != 0) + { + gdk_gc_set_clip_mask (style->fg_gc[state_type], mask); + gdk_gc_set_clip_origin (style->fg_gc[state_type], x, y); + } + + if (area != 0) + { + /* clip by hand to leave gc's clipping for the possible mask */ + GdkRectangle src = { x, y, width, height }, dest; + + if (!gdk_rectangle_intersect (&src, area, &dest)) + return; + + xsrc -= x - dest.x; + ysrc -= y - dest.y; + x = dest.x; + y = dest.y; + width = dest.width; + height = dest.height; + + } + + if (width > 0 && height > 0) + { + gdk_draw_pixmap (window, style->fg_gc[state_type], pixmap, + xsrc, ysrc, x, y, width, height); + } + + if (mask != 0) + { + gdk_gc_set_clip_mask (style->fg_gc[state_type], 0); + gdk_gc_set_clip_origin (style->fg_gc[state_type], 0, 0); + } + } + + eazel_engine_stock_free_pixmaps (theme_data->stock, type, pixmap, mask); +} + +static void +paint_outline (GdkWindow *window, GdkGC *gc, gboolean rounded, + int x, int y, int width, int height) +{ + int corner = rounded ? 1 : 0; + + /* left and top outermost */ + gdk_draw_line (window, gc, x, y + corner, + x, y + height - (corner + 1)); + gdk_draw_line (window, gc, x + corner, y, x + width - (corner + 1), y); + + /* right and bottom outermost */ + gdk_draw_line (window, gc, x + width - 1, y + corner, + x + width - 1, y + height - (corner + 1)); + gdk_draw_line (window, gc, x + corner, y + height - 1, + x + width - (corner + 1), y + height - 1); +} + +static void +paint_shadow (GdkWindow *window, GdkGC *a, GdkGC *b, GdkGC *c, GdkGC *d, + gboolean rounded, int x, int y, int width, int height) +{ + int corner = rounded ? 1 : 0; + + if (a != 0) + { + /* left and top outermost */ + gdk_draw_line (window, a, x, y + corner, + x, y + height - (corner + 1)); + gdk_draw_line (window, a, x + corner, y, x + width - (corner + 1), y); + } + + if (d != 0) + { + /* right and bottom outermost */ + gdk_draw_line (window, d, x + width - 1, y + corner, + x + width - 1, y + height - (corner + 1)); + gdk_draw_line (window, d, x + corner, y + height - 1, + x + width - (corner + 1), y + height - 1); + } + + if (b != 0) + { + /* left and top inner */ + gdk_draw_line (window, b, x + 1, y + 2, x + 1, y + height - 2); + gdk_draw_line (window, b, x + 1, y + 1, x + width - 2, y + 1); + } + + if (c != 0) + { + /* right and bottom outermost */ + gdk_draw_line (window, c, x + width - 2, y + 1, + x + width - 2, y + height - 2); + gdk_draw_line (window, c, x + 1, y + height - 2, + x + width - 2, y + height - 2); + } +} + +static void +paint_entry_shadow (GdkWindow *window, GtkStyle *style, + GtkStateType state_type, + int x, int y, int width, int height) +{ + gdk_draw_rectangle (window, style->black_gc, FALSE, + x + 1, y + 1, width - 3, height - 3); + + gdk_draw_line (window, style->dark_gc[state_type], + x, y, x + width - 1, y); + gdk_draw_line (window, style->dark_gc[state_type], + x, y, x, y + height - 1); + + gdk_draw_line (window, style->white_gc, + x + 1, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, style->white_gc, + x + width - 1, y + 1, x + width - 1, y + height - 1); + + gdk_draw_line (window, style->mid_gc[state_type], + x + 2, y + 2, x + width - 3, y + 2); + gdk_draw_line (window, style->mid_gc[state_type], + x + 2, y + 2, x + 2, y + height - 3); + + gdk_draw_line (window, style->white_gc, + x + 2, y + height - 3, x + width - 3, y + height - 3); + gdk_draw_line (window, style->white_gc, + x + width - 3, y + 2, x + width - 3, y + height - 3); +} + +static void +paint_menuitem_shadow (GdkWindow *window, GtkStyle *style, + int x, int y, int width, int height) +{ + gdk_draw_rectangle (window, style->black_gc, FALSE, + x + 2, y + 1, width - 5, height - 3); + + gdk_draw_line (window, style->dark_gc[GTK_STATE_NORMAL], + x + 1, y, x + width - 3, y); + gdk_draw_line (window, style->dark_gc[GTK_STATE_NORMAL], + x + 1, y, x + 1, y + height - 2); + gdk_draw_line (window, style->white_gc, + x + 2, y + height - 1, x + width - 2, y + height - 1); + gdk_draw_line (window, style->white_gc, + x + width - 2, y + 1, x + width - 2, y + height - 1); +} + +static void +paint_default_highlight (eazel_theme_data *theme_data, + GdkColor *hi_color, GdkColor *bg_color, + GdkWindow *window, GdkGC *gc, int x, int y) +{ + GdkColormap *sys_lut = gdk_colormap_get_system (); + GdkGCValues old_values; + GdkColor spectrum[6]; + int i; + + gdk_gc_get_values (gc, &old_values); + + /* Calculate pixel colors */ + for (i = 0; i < 6; i++) + { + interpolate_color (spectrum + i, 1.0 / 7 * i, hi_color, bg_color); + } + +#define COLOR(i) \ + gdk_colormap_alloc_color (sys_lut, spectrum + i, FALSE, TRUE); \ + gdk_gc_set_foreground (gc, spectrum + i); + +#define PIXEL(a,b) gdk_draw_point (window, gc, x + a, y + b) + + COLOR (0); PIXEL (2, 2); + COLOR (1); PIXEL (3, 2); PIXEL (2, 3); PIXEL (4, 1); PIXEL (1, 4); + COLOR (2); PIXEL (5, 1); PIXEL (1, 5); + COLOR (3); PIXEL (6, 1); PIXEL (1, 6); + COLOR (4); PIXEL (7, 1); PIXEL (1, 7); PIXEL (4, 2); PIXEL (2, 4); + COLOR (5); PIXEL (8, 1); PIXEL (1, 8); + +#undef PIXEL +#undef COLOR + + gdk_gc_set_foreground (gc, &old_values.foreground); +} + +static void +paint_default (eazel_theme_data *theme_data, + GdkWindow *window, GdkGC *gc, GdkColor *bg, + gboolean rounded, gboolean rounded_inner, int thickness, + int x, int y, int width, int height) +{ + int corner = rounded ? ((thickness > 2) ? 3 : 1) : 0; + int window_width, window_height; + int i; + + gdk_window_get_size (window, &window_width, &window_height); + + /* If trying to draw a box that's too big for the dimensions of + the window, iteratively reduce the thickness until a value + is found that won't draw off the window edges */ + while (x < 0 || y < 0 || x + width >= window_width + || y + height >= window_height) + { + if (thickness <= 0 || width <= 0 || height <= 0) + return; + + thickness -= 1; + x += 1; + y += 1; + width -= 2; + height -= 2; + } + + if (rounded) + { + /* XXX this doesn't work, the background of the window + XXX is white, not grey */ + gdk_window_clear_area (window, x, y, 1, 1); + gdk_window_clear_area (window, x + width, y, 1, 1); + gdk_window_clear_area (window, x, y + height, 1, 1); + gdk_window_clear_area (window, x + width, y + height, 1, 1); + } + + for (i = 0; i < thickness; i++) + { + int x_i = x + i; + int y_i = y + i; + int w_i = width - (i * 2); + int h_i = height - (i * 2); + + int d_corner = (corner && i == 0) ? corner : 0; + + gdk_draw_line (window, gc, x_i + d_corner, y_i, + x_i + w_i - d_corner , y_i); + gdk_draw_line (window, gc, x_i + w_i, y_i + d_corner, + x_i + w_i, y_i + h_i - d_corner); + gdk_draw_line (window, gc, x_i + w_i - d_corner, y_i + h_i, + x_i + d_corner, y_i + h_i); + gdk_draw_line (window, gc, x_i, y+i + h_i - d_corner, + x_i, y_i + d_corner); + } + + if (rounded_inner) + { + gdk_draw_point (window, gc, x + thickness, y + thickness); + gdk_draw_point (window, gc, x + thickness, y + height - thickness); + gdk_draw_point (window, gc, x + width - thickness, y + thickness); + gdk_draw_point (window, gc, x + width - thickness, y + height - thickness); + } + + if (thickness >= 3 && rounded) + { + GdkColor white = { 0, 65535, 65535, 65535 }; + paint_default_highlight (theme_data, &white, bg, window, gc, x, y); + } +} + +static void +paint_default_box (eazel_theme_data *theme_data, + GdkWindow *window, GdkGC *gc, + gboolean rounded, gboolean rounded_inner, int thickness, + int x, int y, int width, int height) +{ + GdkColor black = { 0, 0, 0, 0 }; + paint_default (theme_data, window, gc, &black, + rounded, rounded_inner, thickness, + x, y, width, height); +} + +static void +paint_focus_box (eazel_theme_data *theme_data, GdkWindow *window, + GdkGC *gc, gboolean rounded, gboolean rounded_inner, + int thickness, int x, int y, int width, int height) +{ + GdkColormap *sys_lut = gdk_colormap_get_system (); + GdkGCValues old_values; + GdkColor color; + gdk_gc_get_values (gc, &old_values); + + color = theme_data->focus_color; + gdk_colormap_alloc_color (sys_lut, &color, FALSE, TRUE); + gdk_gc_set_foreground (gc, &color); + + paint_default (theme_data, window, gc, &color, rounded, + rounded_inner, thickness, x, y, width, height); + + gdk_gc_set_foreground (gc, &old_values.foreground); +} + +static void +paint_insensitive_box (eazel_theme_data *theme_data, + GdkWindow *window, GdkGC *gc, gboolean rounded, + int x, int y, int width, int height) +{ + GdkColormap *sys_lut = gdk_colormap_get_system (); + GdkGCValues old_values; + GdkColor color; + gdk_gc_get_values (gc, &old_values); + + color = theme_data->insensitive_colors[1]; + gdk_colormap_alloc_color (sys_lut, &color, FALSE, TRUE); + gdk_gc_set_foreground (gc, &color); + gdk_draw_rectangle (window, gc, TRUE, x, y, width, height); + + color = theme_data->insensitive_colors[0]; + gdk_colormap_alloc_color (sys_lut, &color, FALSE, TRUE); + gdk_gc_set_foreground (gc, &color); + paint_default (theme_data, window, gc, &color, rounded, + FALSE, 1, x, y, width - 1, height - 1); + + gdk_gc_set_foreground (gc, &old_values.foreground); +} + +static void +paint_arrow (GdkWindow *window, GdkGC *gc, GtkArrowType arrow_type, + int x, int y, int width, int height) +{ + int half_width, half_height; + int center_x, center_y; + + if ((width & 1) == 0) + width = width - 1; + if ((height & 1) == 0) + height = height - 1; + + half_width = width / 2; + half_height = height / 2; + + center_x = x + half_width; + center_y = y + half_height; + + switch (arrow_type) + { + int i; + static int offset[5] = { 0, -1, -2, -3, -4 }; + static int length[5] = { 0, 2, 4, 6, 8 }; + static const int size = 4; + + case GTK_ARROW_UP: + for (i = 0; i < size; i++) + { + gdk_draw_line (window, gc, + center_x + offset[i], + center_y - 2 + i, + center_x + offset[i] + length[i], + center_y - 2 + i); + } + break; + + case GTK_ARROW_DOWN: + for (i = 0; i < size; i++) + { + gdk_draw_line (window, gc, + center_x + offset[i], + center_y + 2 - i, + center_x + offset[i] + length[i], + center_y + 2 - i); + } + break; + + case GTK_ARROW_LEFT: + for (i = 0; i < size; i++) + { + gdk_draw_line (window, gc, + center_x - 2 + i, + center_y + offset[i], + center_x - 2 + i, + center_y + offset[i] + length[i]); + } + break; + + case GTK_ARROW_RIGHT: + for (i = 0; i < size; i++) + { + gdk_draw_line (window, gc, + center_x + 2 - i, + center_y + offset[i], + center_x + 2 - i, + center_y + offset[i] + length[i]); + } + break; + } +} + +static void +paint_tick (GdkWindow *window, GdkGC *gc, int x, int y) +{ +#define PIXEL(a,b) gdk_draw_point (window, gc, x + a, y + b) + + PIXEL (4, -4); + PIXEL (3, -3); PIXEL (4, -3); PIXEL (5, -3); + PIXEL (-2, -2); + PIXEL (2, -2); PIXEL (3, -2); PIXEL (4, -2); + PIXEL (-3, -1); PIXEL (-2, -1); PIXEL (-1, -1); + PIXEL (1, -1); PIXEL (2, -1); PIXEL (3, -1); + PIXEL (-2, 0); PIXEL (-1, 0); PIXEL (0, 0); PIXEL (1, 0); PIXEL (2, 0); + PIXEL (-1, 1); PIXEL (0, 1); PIXEL (1, 1); + PIXEL (0, 2); + +#undef PIXEL +} + +static void +paint_bullet (GdkWindow *window, GdkGC *gc, int x, int y) +{ +#define PIXEL(a, b) gdk_draw_point (window, gc, x + a, x + b) + + PIXEL (0, 0); PIXEL (0, -1); PIXEL (-1, 0); PIXEL (-1, -1); + PIXEL (1, -1); PIXEL (2, -1); PIXEL (-1, 1); PIXEL (-1, 2); + + PIXEL (0, -2); PIXEL (1, -2); + PIXEL (-2, 0); PIXEL (-2, 1); + PIXEL (1, 0); PIXEL (2, 0); PIXEL (3, 0); + PIXEL (0, 1); PIXEL (1, 1); PIXEL (2, 1); PIXEL (3, 1); + PIXEL (0, 2); PIXEL (1, 2); PIXEL (2, 2); + PIXEL (0, 3); PIXEL (1, 3); + + PIXEL (-1, -2); PIXEL (-2, -1); PIXEL (2, -2); PIXEL (3, -1); + PIXEL (-2, 2); PIXEL (-1, 3); PIXEL (2, 3); PIXEL (3, 2); + +#undef PIXEL +} + + +/* style functions */ + +static void +draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x1, gint x2, gint y) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_hline: detail=%s state=%d x1=%d x2=%d y=%d\n", + detail, state_type, x1, x2, y); + + thickness_light = style->klass->ythickness / 2; + thickness_dark = style->klass->ythickness - thickness_light; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + } + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, + y + i, x2, y + i); + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, + x2 - i - 1, y + i); + } + + y += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, + x1 + thickness_light - i - 1, y + i); + gdk_draw_line (window, style->light_gc[state_type], + x1 + thickness_light - i - 1, y + i, x2, y + i); + } + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + } +} + +static void +draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, gchar *detail, gint y1, gint y2, gint x) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_vline: detail=%s state=%d x=%d y1=%d y2=%d\n", + detail, state_type, x, y1, y2); + + thickness_light = style->klass->xthickness / 2; + thickness_dark = style->klass->xthickness - thickness_light; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + } + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x + i, + y2 - i - 1, x + i, y2); + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, + y2 - i - 1); + } + + x += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, + y1 + thickness_light - i); + gdk_draw_line (window, style->light_gc[state_type], x + i, + y1 + thickness_light - i, x + i, y2); + } + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + } +} + +static void +draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + GdkGC *gc1 = NULL; + GdkGC *gc2 = NULL; + GdkGC *gc3 = NULL; + GdkGC *gc4 = NULL; + GdkGC *gc_a, *gc_b, *gc_c, *gc_d; + gint thickness_light; + gint thickness_dark; + gboolean rounded = FALSE, rounded_inner = FALSE; + gboolean outline = TRUE; + gint i; + + eazel_theme_data *theme_data; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + outline = theme_data->outline_shadow; + + if (widget != 0 && !GTK_WIDGET_IS_SENSITIVE (widget)) + state_type = GTK_STATE_INSENSITIVE; + + debug ("draw_shadow: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + case GTK_SHADOW_ETCHED_IN: + if (theme_data->inverse_shadow) + goto out; + in: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->mid_gc[state_type]; + gc4 = style->bg_gc[state_type]; + break; + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_OUT: + if (theme_data->inverse_shadow) + goto in; + out: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->mid_gc[state_type]; + gc4 = style->bg_gc[state_type]; + break; + } + + gc_a = gc2; + gc_b = gc4; + gc_c = 0; + gc_d = gc1; + + if (DETAIL ("button") || DETAIL ("optionmenu")) + { + /* Clist title buttons have square edges */ + if (widget == 0 || !GTK_IS_CLIST (widget->parent)) + rounded = rounded_inner = TRUE; + } + else if (DETAIL ("menuitem")) + { + paint_menuitem_shadow (window, style, x, y, width, height); + return; + } + else if (DETAIL ("entry") || DETAIL ("text")) + { + if (widget == 0 || GTK_WIDGET_IS_SENSITIVE (widget)) + { + paint_entry_shadow (window, style, state_type, + x, y, width, height); + return; + } + } + else if (DETAIL ("spinbutton")) + { + gc_a = gc2; + gc_b = 0; + outline = FALSE; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + if ((shadow_type == GTK_SHADOW_IN) || (shadow_type == GTK_SHADOW_OUT)) + { + gdk_gc_set_clip_rectangle (style->black_gc, area); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + } + } + switch (shadow_type) + { + case GTK_SHADOW_NONE: + break; + + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + if (state_type == GTK_STATE_INSENSITIVE) + { + paint_insensitive_box (theme_data, window, + style->bg_gc[state_type], + rounded, x, y, width, height); + } + else if (outline) + { + paint_outline (window, style->black_gc, rounded, + x, y, width, height); + if (!theme_data->no_shadow) + { + paint_shadow (window, gc_a, gc_b, gc_c, gc_d, rounded, + x + 1, y + 1, width - 2, height - 2); + } + } + else + { + if (!theme_data->no_shadow) + { + paint_shadow (window, gc_a, gc_b, gc_c, gc_d, rounded, + x, y, width, height); + } + } + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + thickness_light = 1; + thickness_dark = 1; + + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, gc1, + x + i, + y + height - i - 1, + x + width - i - 1, y + height - i - 1); + gdk_draw_line (window, gc1, + x + width - i - 1, + y + i, x + width - i - 1, y + height - i - 1); + + gdk_draw_line (window, gc2, + x + i, y + i, x + width - i - 2, y + i); + gdk_draw_line (window, gc2, + x + i, y + i, x + i, y + height - i - 2); + } + + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + width - thickness_dark - i - 1, + y + thickness_dark + i); + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + thickness_dark + i, + y + height - thickness_dark - i - 1); + + gdk_draw_line (window, gc2, + x + thickness_dark + i, + y + height - thickness_light - i - 1, + x + width - thickness_light - 1, + y + height - thickness_light - i - 1); + gdk_draw_line (window, gc2, + x + width - thickness_light - i - 1, + y + thickness_dark + i, + x + width - thickness_light - i - 1, + y + height - thickness_light - 1); + } + break; + } + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + if ((shadow_type == GTK_SHADOW_IN) || (shadow_type == GTK_SHADOW_OUT)) + { + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + } + } +} + +static void +draw_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + gboolean add_shadow = FALSE; + eazel_theme_data *theme_data; + gboolean set_bg = FALSE; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + { + gdk_window_get_size (window, &width, &height); + if (gdk_window_get_type (window) != GDK_WINDOW_PIXMAP) + set_bg = TRUE; + } + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (widget != 0 && !GTK_WIDGET_IS_SENSITIVE (widget)) + state_type = GTK_STATE_INSENSITIVE; + + debug ("draw_box: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + if ((!style->bg_pixmap[state_type]) || + (gdk_window_get_type (window) == GDK_WINDOW_PIXMAP)) + { + if (area) + { + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->black_gc, area); + } + + if (DETAIL ("trough")) + { + if (GTK_IS_PROGRESS_BAR (widget)) + { + if (state_type != GTK_STATE_INSENSITIVE) + { + paint_stock_image (theme_data, + EAZEL_ENGINE_PROGRESS_TROUGH, + TRUE, FALSE, + style, window, state_type, area, + widget, x, y, width, height); + } + else + { + paint_insensitive_box (theme_data, window, + style->fg_gc[state_type], + FALSE, x, y, width, height); + } + } + else if (GTK_IS_SCALE (widget)) + { + gboolean focused = GTK_WIDGET_HAS_FOCUS (widget); + paint_background_area (style, window, state_type, area, + x, y, width, height); + paint_stock_image (theme_data, + width > height + ? (focused + ? EAZEL_ENGINE_H_SLIDER_TROUGH_ACTIVE + : EAZEL_ENGINE_H_SLIDER_TROUGH) + : (focused + ? EAZEL_ENGINE_V_SLIDER_TROUGH_ACTIVE + : EAZEL_ENGINE_V_SLIDER_TROUGH), + TRUE, FALSE, style, window, state_type, + area, widget, x, y, width, height); + } + else + { + paint_stock_image (theme_data, + width > height ? EAZEL_ENGINE_H_TROUGH + : EAZEL_ENGINE_V_TROUGH, TRUE, FALSE, + style, window, state_type, area, + widget, x, y, width, height); + } + } + else if (DETAIL ("slider")) + { + int thumb_x, thumb_y; + gboolean focused; + + focused = eazel_engine_widget_in_focused_window_p (widget); + + /* XXX could be a gradient? */ + paint_stock_image (theme_data, + width > height + ? (state_type == GTK_STATE_PRELIGHT + ? EAZEL_ENGINE_H_SCROLLBAR_HI + : !focused + ? EAZEL_ENGINE_H_SCROLLBAR_INACTIVE + : EAZEL_ENGINE_H_SCROLLBAR) + : (state_type == GTK_STATE_PRELIGHT + ? EAZEL_ENGINE_V_SCROLLBAR_HI + : !focused + ? EAZEL_ENGINE_V_SCROLLBAR_INACTIVE + : EAZEL_ENGINE_V_SCROLLBAR), + TRUE, FALSE, style, window, state_type, area, + widget, x, y, width, height); + if (width > height) + { + /* XXX `4' is 1/2 width of thumb */ + thumb_x = x + width / 2 - 4; + thumb_y = y; + } + else + { + thumb_x = x; + /* XXX `4' is 1/2 height of thumb */ + thumb_y = y + height / 2 - 4; + } + + paint_stock_image (theme_data, + width > height + ? (state_type == GTK_STATE_PRELIGHT + ? EAZEL_ENGINE_H_SCROLLBAR_THUMB_HI + : !focused + ? EAZEL_ENGINE_H_SCROLLBAR_THUMB_INACTIVE + : EAZEL_ENGINE_H_SCROLLBAR_THUMB) + : (state_type == GTK_STATE_PRELIGHT + ? EAZEL_ENGINE_V_SCROLLBAR_THUMB_HI + : !focused + ? EAZEL_ENGINE_V_SCROLLBAR_THUMB_INACTIVE + : EAZEL_ENGINE_V_SCROLLBAR_THUMB), + FALSE, FALSE, style, window, state_type, area, + widget, thumb_x, thumb_y, -1, -1); + } + else if (DETAIL ("vscrollbar")) + { + } + else if (DETAIL ("hscrollbar")) + { + } + else if (DETAIL ("bar")) + { + if (state_type != GTK_STATE_INSENSITIVE) + { + gboolean focused; + focused = eazel_engine_widget_in_focused_window_p (widget); + paint_stock_image (theme_data, + focused ? EAZEL_ENGINE_PROGRESS_BAR + : EAZEL_ENGINE_PROGRESS_BAR_INACTIVE, + TRUE, FALSE, style, window, state_type, + area, widget, x, y, width, height); + if (x > style->klass->xthickness) + { + paint_stock_image (theme_data, + EAZEL_ENGINE_PROGRESS_BAR_LEFT, + TRUE, FALSE, style, window, state_type, + area, widget, x - 2, y, -1, height); + } + if (widget != 0 + && x + width < widget->allocation.width - style->klass->xthickness - 3) + { + paint_stock_image (theme_data, + EAZEL_ENGINE_PROGRESS_BAR_RIGHT, + TRUE, FALSE, style, window, + state_type, area, widget, + x + width, y, -1, height); + } + } + else + { + paint_insensitive_box (theme_data, window, + style->fg_gc[state_type], + FALSE, x, y, width, height); + } + } + else if (DETAIL ("optionmenutab")) + { + int real_width, real_height; + int y1, y2; + int center_x, center_y; + + gdk_window_get_size (window, &real_width, &real_height); + + y1 = style->klass->ythickness + 1; + y2 = real_height - style->klass->ythickness - 2; + gdk_draw_line (window, style->dark_gc[state_type] + , x, y1, x, y2); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y1, x +1, y2); + + center_x = x + (real_width - x) / 2; + center_y = real_height / 2; + + paint_arrow (window, style->fg_gc[state_type], GTK_ARROW_UP, + center_x - 4, center_y - 6, 7, 7); + paint_arrow (window, style->fg_gc[state_type], GTK_ARROW_DOWN, + center_x - 4, center_y - 1, 7, 7); + } + else if (DETAIL ("buttondefault")) + { + /* Don't draw default markings. */ + } + else + { + GdkRectangle full; + + eazel_engine_gradient *gradient = theme_data->gradients[state_type]; + add_shadow = (shadow_type != GTK_SHADOW_NONE); + + if (DETAIL ("button") && widget != 0 + && GTK_WIDGET_HAS_FOCUS (widget) + && GTK_WIDGET_CAN_DEFAULT (widget)) + { + x -= 1; + y -= 1; + width += 2; + height += 2; + } + + full.x = x; + full.y = y; + full.width = width; + full.height = height; + + if (DETAIL ("menuitem")) + { + full.x++; full.y++; + full.width -= 2; full.height -= 2; + } + + if (gradient != NULL && gradient->direction != GRADIENT_NONE) + { + if (!set_bg) + { + eazel_engine_draw_gradient (window, + style->bg_gc[state_type], + &full, &full, gradient); + } + else + { + GdkRectangle dest; + if (area != 0) + gdk_rectangle_intersect (&full, area, &dest); + else + dest = full; + eazel_engine_set_bg_gradient (window, gradient); + gdk_window_clear_area (window, dest.x, dest.y, + dest.width, dest.height); + } + } + else + { + if (!set_bg) + { + gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, + x, y, width, height); + } + else + { + GdkRectangle dest; + if (area != 0) + gdk_rectangle_intersect (&full, area, &dest); + else + dest = full; + gdk_window_set_background (window, &style->bg[state_type]); + gdk_window_clear_area (window, dest.x, dest.y, + dest.width, dest.height); + } + } + + if (DETAIL ("button") && widget != 0 + && GTK_WIDGET_HAS_DEFAULT (widget)) + { + void (*fun) (eazel_theme_data *, GdkWindow *, GdkGC *, gboolean, gboolean, int, int, int, int, int) = paint_default_box; + + if (GTK_WIDGET_HAS_FOCUS (widget)) + fun = paint_focus_box; + + fun (theme_data, window, style->black_gc, TRUE, TRUE, + theme_data->default_thickness, + x - (theme_data->default_thickness), + y - (theme_data->default_thickness), + width + theme_data->default_thickness * 2 - 1, + height + theme_data->default_thickness * 2 - 1); + } + } + if (area) + { + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + } + } + else + { + gtk_style_apply_default_pixmap (style, window, state_type, area, x, + y, width, height); + } + + if (add_shadow) + { + gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + } +} + +static void +draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, GdkPoint *points, gint npoints, gint fill) +{ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif /* + * M_PI + */ +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 +#endif /* + * M_PI_4 + */ + + static const gdouble pi_over_4 = M_PI_4; + static const gdouble pi_3_over_4 = M_PI_4 * 3; + + GdkGC *gc1; + GdkGC *gc2; + GdkGC *gc3; + GdkGC *gc4; + gdouble angle; + gint xadjust; + gint yadjust; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + g_return_if_fail (points != NULL); + + debug ("draw_polygon: detail=%s state=%d shadow=%d\n", + detail, state_type, shadow_type); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + default: + return; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + + if (fill) + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, + npoints); + + npoints--; + + for (i = 0; i < npoints; i++) + { + if ((points[i].x == points[i + 1].x) && + (points[i].y == points[i + 1].y)) + { + angle = 0; + } + else + { + angle = atan2 (points[i + 1].y - points[i].y, + points[i + 1].x - points[i].x); + } + + if ((angle > -pi_3_over_4) && (angle < pi_over_4)) + { + if (angle > -pi_over_4) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc1, + points[i].x - xadjust, points[i].y - yadjust, + points[i + 1].x - xadjust, + points[i + 1].y - yadjust); + gdk_draw_line (window, gc3, points[i].x, points[i].y, + points[i + 1].x, points[i + 1].y); + } + else + { + if ((angle < -pi_3_over_4) || (angle > pi_3_over_4)) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc4, + points[i].x + xadjust, points[i].y + yadjust, + points[i + 1].x + xadjust, + points[i + 1].y + yadjust); + gdk_draw_line (window, gc2, points[i].x, points[i].y, + points[i + 1].x, points[i + 1].y); + } + } + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } +} + +static void +draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + GtkArrowType arrow_type, + gint fill, gint x, gint y, gint width, gint height) +{ + eazel_theme_data *theme_data; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + debug ("draw_arrow: detail=%s state=%d shadow=%d arrow_type=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, arrow_type, x, y, width, height); + + if (DETAIL ("vscrollbar") || DETAIL ("hscrollbar")) + { + int type; + switch (arrow_type) + { + case GTK_ARROW_UP: + type = EAZEL_ENGINE_ARROW_UP; + break; + + case GTK_ARROW_DOWN: + type = EAZEL_ENGINE_ARROW_DOWN; + break; + + case GTK_ARROW_LEFT: + type = EAZEL_ENGINE_ARROW_LEFT; + break; + + case GTK_ARROW_RIGHT: + type = EAZEL_ENGINE_ARROW_RIGHT; + break; + } + + type += (state_type == GTK_STATE_ACTIVE ? 2 + : state_type == GTK_STATE_PRELIGHT ? 1 : 0); + + paint_stock_image (theme_data, type, TRUE, FALSE, + style, window, state_type, + area, widget, x, y, width, height); + } + else if (DETAIL ("spinbutton")) + { + int window_width, window_height; + int tem_x, tem_y; + + if (widget != 0 && !GTK_WIDGET_IS_SENSITIVE (widget)) + state_type = GTK_STATE_INSENSITIVE; + + gdk_window_get_size (window, &window_width, &window_height); + + if (state_type != GTK_STATE_INSENSITIVE) + { + draw_box (style, window, state_type, shadow_type, + area, widget, detail, + x, y - (arrow_type == GTK_ARROW_DOWN), + width, height + 1); + } + else if (arrow_type == GTK_ARROW_UP) + { + /* XXX A hack, assumes that up arrow is drawn before + XXX down arrow. (Currently it is) */ + + draw_shadow (style, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, widget, "entry", x - 2, 0, + width + 4, window_height); + } + + tem_x = x + (width / 2); + tem_y = y + (height / 2); + if (arrow_type == GTK_ARROW_UP) + { + int i; + tem_y--; + for (i = 0; i < 4; i++) + { + gdk_draw_line (window, style->fg_gc[state_type], + tem_x - i, tem_y + i, tem_x + i, tem_y + i); + } + } + else + { + int i; + tem_y -= 3; + for (i = 0; i < 4; i++) + { + gdk_draw_line (window, style->fg_gc[state_type], + tem_x - i, tem_y + (4 - i), + tem_x + i, tem_y + (4 - i)); + } + } + + if (state_type != GTK_STATE_INSENSITIVE) + { + draw_shadow (style, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, widget, "entry", x - 2, 0, + width + 4, window_height); + } + } + else + { + if (widget != 0 && !GTK_WIDGET_IS_SENSITIVE (widget)) + state_type = GTK_STATE_INSENSITIVE; + + paint_arrow (window, style->fg_gc[state_type], + arrow_type, x, y, width, height); + } +} + +static void +draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + gint half_width; + gint half_height; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_diamond: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + half_width = width / 2; + half_height = height / 2; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->black_gc, area); + } + switch (shadow_type) + { + case GTK_SHADOW_IN: + gdk_draw_line (window, style->light_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x, y + half_height, x + half_width, y + height); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->dark_gc[state_type], + x + 2, y + half_height, x + half_width, y + 2); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + 2, x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], x + 1, + y + half_height, x + half_width, y + 1); + gdk_draw_line (window, style->dark_gc[state_type], x + half_width, + y + 1, x + width - 1, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], x, + y + half_height, x + half_width, y); + gdk_draw_line (window, style->dark_gc[state_type], x + half_width, + y, x + width, y + half_height); + break; + case GTK_SHADOW_OUT: + gdk_draw_line (window, style->dark_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x, y + half_height, x + half_width, y + height); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->light_gc[state_type], + x + 2, y + half_height, x + half_width, y + 2); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + 2, x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], x + 1, + y + half_height, x + half_width, y + 1); + gdk_draw_line (window, style->light_gc[state_type], x + half_width, + y + 1, x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], x, + y + half_height, x + half_width, y); + gdk_draw_line (window, style->light_gc[state_type], x + half_width, + y, x + width, y + half_height); + break; + default: + break; + } + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + } +} + +static void +draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); +} + +static void +draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_string: detail=%s state=%d x=%d y=%d\n", + detail, state_type, x, y); + + if (area) + { + gdk_gc_set_clip_rectangle (style->white_gc, area); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area); + } + if (state_type == GTK_STATE_INSENSITIVE) + gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, + string); + gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, + string); + if (area) + { + gdk_gc_set_clip_rectangle (style->white_gc, NULL); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL); + } +} + +static void +draw_flat_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + GdkGC *gc1; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + debug ("draw_flat_box: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + gc1 = style->bg_gc[state_type]; + + if (DETAIL ("text") && (state_type == GTK_STATE_SELECTED)) + gc1 = style->bg_gc[GTK_STATE_SELECTED]; + else if (DETAIL ("viewportbin")) + gc1 = style->bg_gc[GTK_STATE_NORMAL]; + else if (DETAIL ("entry_bg")) + gc1 = style->white_gc; + + if ((!style->bg_pixmap[state_type]) + || (gc1 != style->bg_gc[state_type]) + || (gdk_window_get_type (window) == GDK_WINDOW_PIXMAP)) + { + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + } + gdk_draw_rectangle (window, gc1, TRUE, x, y, width, height); + if ((detail) && (!strcmp ("tooltip", detail))) + gdk_draw_rectangle (window, style->black_gc, FALSE, + x, y, width - 1, height - 1); + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + } + } + else + gtk_style_apply_default_pixmap (style, window, state_type, area, x, + y, width, height); +} + +static void +paint_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height, + eazel_engine_stock_image stock_base) +{ + eazel_engine_stock_image type; + gboolean active = (shadow_type != GTK_SHADOW_OUT); + gboolean has_focus = (widget != 0 && GTK_WIDGET_HAS_FOCUS (widget)); + gboolean menu_item = (widget != 0 && gtk_widget_get_ancestor (widget, GTK_TYPE_MENU_ITEM)); + + eazel_theme_data *theme_data; + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + if (DETAIL ("checkbutton") || DETAIL ("radiobutton")) + { + /* correct for braindeath in gtk_real_check_button_draw_indicator */ + if (widget != 0 && GTK_IS_TOGGLE_BUTTON (widget)) + active = GTK_TOGGLE_BUTTON (widget)->active; + if (widget != 0) + { + state_type = GTK_WIDGET_STATE (widget); + /* XXX the widget gives us no way to tell between + XXX checked, and checked-and-clicked states.. */ + if (active && state_type == GTK_STATE_ACTIVE) + state_type = GTK_STATE_NORMAL; + } + } + + if (!menu_item) + { + switch (state_type) + { + case GTK_STATE_INSENSITIVE: + type = (!active ? EAZEL_ENGINE_CHECK_DISABLED + : EAZEL_ENGINE_CHECK_ACTIVE_DISABLED); + break; + + case GTK_STATE_PRELIGHT: + type = (active + ? (has_focus ? EAZEL_ENGINE_CHECK_ACTIVE_HI_FOCUS + : EAZEL_ENGINE_CHECK_ACTIVE_HI) + : (has_focus ? EAZEL_ENGINE_CHECK_HI_FOCUS + : EAZEL_ENGINE_CHECK_HI)); + break; + + case GTK_STATE_ACTIVE: + type = (active + ? (has_focus ? EAZEL_ENGINE_CHECK_ACTIVE_PRESSED_FOCUS + : EAZEL_ENGINE_CHECK_ACTIVE) + : (has_focus ? EAZEL_ENGINE_CHECK_PRESSED_FOCUS + : EAZEL_ENGINE_CHECK_PRESSED)); + break; + + default: + type = (active + ? (has_focus ? EAZEL_ENGINE_CHECK_ACTIVE_FOCUS + : EAZEL_ENGINE_CHECK_ACTIVE) + : (has_focus ? EAZEL_ENGINE_CHECK_FOCUS + : EAZEL_ENGINE_CHECK)); + } + + paint_stock_image (theme_data, type + stock_base, + FALSE, FALSE, style, window, + state_type, area, widget, + x-3, y-3, width+6, height+6); + } + else + { + if (!active) + return; + + if (stock_base == EAZEL_ENGINE_CHECK) + { + paint_tick (window, style->fg_gc[state_type], + x + width / 2, y + width / 2); + } + else + { + paint_bullet (window, style->fg_gc[state_type], + x + width / 2, y + width / 2); + } + } +} + +static void +draw_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + paint_check (style, window, state_type, shadow_type, area, + widget, detail, x, y, width, height, EAZEL_ENGINE_CHECK); +} + +static void +draw_option (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + paint_check (style, window, state_type, shadow_type, area, + widget, detail, x, y, width, height, EAZEL_ENGINE_OPTION); +} + +static void +draw_cross (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); +} + +static void +draw_ramp (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + GtkArrowType arrow_type, gint x, gint y, gint width, gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); +} + +static void +draw_tab (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); +} + +static void +draw_shadow_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width) +{ + GdkRectangle rect; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_shadow_gap: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + switch (gap_side) + { + case GTK_POS_TOP: + rect.x = x + gap_x; + rect.y = y; + rect.width = gap_width; + rect.height = 2; + break; + case GTK_POS_BOTTOM: + rect.x = x + gap_x; + rect.y = y + height - 2; + rect.width = gap_width; + rect.height = 2; + break; + case GTK_POS_LEFT: + rect.x = x; + rect.y = y + gap_x; + rect.width = 2; + rect.height = gap_width; + break; + case GTK_POS_RIGHT: + rect.x = x + width - 2; + rect.y = y + gap_x; + rect.width = 2; + rect.height = gap_width; + break; + } + + gtk_style_apply_default_pixmap (style, window, state_type, area, + rect.x, rect.y, rect.width, rect.height); +} + +static void +draw_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width) +{ + GdkRectangle rect; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_box_gap: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + /* XXX Eavel hack to prevent a hole being draw when the + XXX active tab is on the far left */ + if (gap_x < 1) + { + gap_width -= (1 - gap_x); + gap_x = 1; + } + + switch (gap_side) + { + case GTK_POS_TOP: + rect.x = x + gap_x; + rect.y = y; + rect.width = gap_width; + rect.height = 2; + break; + case GTK_POS_BOTTOM: + rect.x = x + gap_x; + rect.y = y + height - 2; + rect.width = gap_width; + rect.height = 2; + break; + case GTK_POS_LEFT: + rect.x = x; + rect.y = y + gap_x; + rect.width = 2; + rect.height = gap_width; + break; + case GTK_POS_RIGHT: + rect.x = x + width - 2; + rect.y = y + gap_x; + rect.width = 2; + rect.height = gap_width; + break; + } + + gtk_style_apply_default_pixmap (style, window, state_type, area, + rect.x, rect.y, rect.width, rect.height); +} + +static void +draw_extension (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, gint width, gint height, GtkPositionType gap_side) +{ + GdkRectangle rect; + + eazel_theme_data *theme_data; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + debug ("draw_extension: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + + if (DETAIL ("tab")) + { + eazel_engine_stock_image type = 0; + switch (gap_side) + { + case GTK_POS_TOP: + type = ((state_type != GTK_STATE_ACTIVE) + ? EAZEL_ENGINE_TAB_BOTTOM_ACTIVE + : (x < 10) ? EAZEL_ENGINE_TAB_BOTTOM_LEFT + : EAZEL_ENGINE_TAB_BOTTOM); + break; + + case GTK_POS_BOTTOM: + type = ((state_type != GTK_STATE_ACTIVE) + ? EAZEL_ENGINE_TAB_TOP_ACTIVE + : (x < 10) ? EAZEL_ENGINE_TAB_TOP_LEFT + : EAZEL_ENGINE_TAB_TOP); + break; + + default: /* gcc drugging */ + } + paint_background_area (style, window, state_type, area, + x, y, width, height); + if (type != 0) + { + paint_stock_image (theme_data, type, TRUE, FALSE, style, window, + state_type, area, widget, x, y, width, height); + return; + } + } + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + switch (gap_side) + { + case GTK_POS_TOP: + rect.x = x + style->klass->xthickness; + rect.y = y; + rect.width = width - style->klass->xthickness * 2; + rect.height = style->klass->ythickness; + break; + case GTK_POS_BOTTOM: + rect.x = x + style->klass->xthickness; + rect.y = y + height - style->klass->ythickness; + rect.width = width - style->klass->xthickness * 2; + rect.height = style->klass->ythickness; + break; + case GTK_POS_LEFT: + rect.x = x; + rect.y = y + style->klass->ythickness; + rect.width = style->klass->xthickness; + rect.height = height - style->klass->ythickness * 2; + break; + case GTK_POS_RIGHT: + rect.x = x + width - style->klass->xthickness; + rect.y = y + style->klass->ythickness; + rect.width = style->klass->xthickness; + rect.height = height - style->klass->ythickness * 2; + break; + } + + gtk_style_apply_default_pixmap (style, window, state_type, area, + rect.x, rect.y, rect.width, rect.height); +} + +static void +draw_focus (GtkStyle *style, + GdkWindow *window, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, gint x, gint y, gint width, gint height) +{ + eazel_theme_data *theme_data; + gboolean rounded = TRUE, rounded_inner = TRUE; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + debug ("draw_focus: detail=%s x=%d y=%d w=%d h=%d\n", + detail, x, y, width, height); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((DETAIL ("button") && widget != 0 + && GTK_IS_BUTTON (widget) && GTK_WIDGET_HAS_DEFAULT (widget)) + || DETAIL ("checkbutton") || DETAIL ("option") || DETAIL ("slider") + || (widget != 0 && GTK_IS_SCALE (widget)) + /* XXX reenable me */ + || DETAIL ("tab")) + { + return; + } + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, area); + + if (DETAIL ("button")) + { + x--; y--; + width += 2; height += 2; + } + else if (DETAIL ("text") || DETAIL ("entry")) + { + rounded_inner = FALSE; + } + + paint_focus_box (theme_data, window, style->black_gc, + rounded, rounded_inner, theme_data->focus_thickness, + x, y, width, height); + + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, NULL); +} + +static void +draw_slider (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, gint width, gint height, GtkOrientation orientation) +{ + eazel_theme_data *theme_data; + gboolean focused; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + theme_data = STYLE_THEME_DATA (style); + g_assert (theme_data != NULL); + + debug ("draw_slider: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, area); + + focused = (widget != 0) && eazel_engine_widget_in_focused_window_p (widget); + paint_stock_image (theme_data, + orientation == GTK_ORIENTATION_HORIZONTAL + ? (focused ? EAZEL_ENGINE_H_SLIDER_THUMB + : EAZEL_ENGINE_H_SLIDER_THUMB_INACTIVE) + : (focused ? EAZEL_ENGINE_V_SLIDER_THUMB + : EAZEL_ENGINE_V_SLIDER_THUMB_INACTIVE), + TRUE, TRUE, style, window, state_type, + area, widget, x, y, width, height); + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, NULL); +} + +static void +draw_handle (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, gint width, gint height, GtkOrientation orientation) +{ + gint i, yy, xx; + gint xthick, ythick; + GdkGC *light_gc, *dark_gc; + GdkRectangle dest; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + debug ("draw_handle: detail=%s state=%d shadow=%d x=%d y=%d w=%d h=%d\n", + detail, state_type, shadow_type, x, y, width, height); + + /* Protection against broken GTK+ widgets */ + g_return_if_fail (width < 32768); + g_return_if_fail (height < 32768); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (DETAIL ("dockitem") && state_type == GTK_STATE_NORMAL) + state_type = GTK_STATE_ACTIVE; + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + light_gc = style->light_gc[state_type]; + dark_gc = style->dark_gc[state_type]; + + xthick = style->klass->xthickness; + ythick = style->klass->ythickness; + + dest.x = x + xthick; + dest.y = y + ythick; + dest.width = width - (xthick * 2); + dest.height = height - (ythick * 2); + + gdk_gc_set_clip_rectangle (light_gc, &dest); + gdk_gc_set_clip_rectangle (dark_gc, &dest); + + /* ORIENTATION parameters is unreliable */ + if (height > width) + { + yy = y + height / 2 - 5; + for (i = 0; i < 10; i += 2) + { + gdk_draw_line (window, dark_gc, xthick, yy + i, + x + width - xthick, yy + i); + gdk_draw_line (window, light_gc, xthick, yy + i + 1, + x + width - xthick, yy + i + 1); + } + } + else + { + xx = x + width / 2 - 5; + for (i = 0; i < 10; i += 2) + { + gdk_draw_line (window, dark_gc, xx + i, ythick, + xx + i, y + height - ythick); + gdk_draw_line (window, light_gc, xx + i + 1, ythick, + xx + i + 1, y + height - ythick); + } + } + + gdk_gc_set_clip_rectangle (light_gc, NULL); + gdk_gc_set_clip_rectangle (dark_gc, NULL); +} + + +/* + * class struct + */ + +GtkStyleClass eazel_class_0 = { + 0, 0, + draw_hline, + draw_vline, + draw_shadow, + draw_polygon, + draw_arrow, + draw_diamond, + draw_oval, + draw_string, + draw_box, + draw_flat_box, + draw_check, + draw_option, + draw_cross, + draw_ramp, + draw_tab, + draw_shadow_gap, + draw_box_gap, + draw_extension, + draw_focus, + draw_slider, + draw_handle +}; + +GtkStyleClass eazel_class_1 = { + 1, 1, + draw_hline, + draw_vline, + draw_shadow, + draw_polygon, + draw_arrow, + draw_diamond, + draw_oval, + draw_string, + draw_box, + draw_flat_box, + draw_check, + draw_option, + draw_cross, + draw_ramp, + draw_tab, + draw_shadow_gap, + draw_box_gap, + draw_extension, + draw_focus, + draw_slider, + draw_handle +}; + +GtkStyleClass eazel_class_2 = { + 2, 2, + draw_hline, + draw_vline, + draw_shadow, + draw_polygon, + draw_arrow, + draw_diamond, + draw_oval, + draw_string, + draw_box, + draw_flat_box, + draw_check, + draw_option, + draw_cross, + draw_ramp, + draw_tab, + draw_shadow_gap, + draw_box_gap, + draw_extension, + draw_focus, + draw_slider, + draw_handle +}; + +GtkStyleClass eazel_class_3 = { + 3, 3, + draw_hline, + draw_vline, + draw_shadow, + draw_polygon, + draw_arrow, + draw_diamond, + draw_oval, + draw_string, + draw_box, + draw_flat_box, + draw_check, + draw_option, + draw_cross, + draw_ramp, + draw_tab, + draw_shadow_gap, + draw_box_gap, + draw_extension, + draw_focus, + draw_slider, + draw_handle +}; + |