diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | gtk-engine/Makefile.am | 1 | ||||
-rw-r--r-- | gtk-engine/src/Makefile.am | 27 | ||||
-rw-r--r-- | gtk-engine/src/cairo-support.c | 454 | ||||
-rw-r--r-- | gtk-engine/src/cairo-support.h | 81 | ||||
-rw-r--r-- | gtk-engine/src/ge-support.h | 9 | ||||
-rw-r--r-- | gtk-engine/src/general-support.h | 35 | ||||
-rw-r--r-- | gtk-engine/src/olpc_main.c | 23 | ||||
-rw-r--r-- | gtk-engine/src/olpc_misc.c | 325 | ||||
-rw-r--r-- | gtk-engine/src/olpc_misc.h | 39 | ||||
-rw-r--r-- | gtk-engine/src/olpc_rc_style.c | 398 | ||||
-rw-r--r-- | gtk-engine/src/olpc_rc_style.h | 93 | ||||
-rw-r--r-- | gtk-engine/src/olpc_style.h | 29 | ||||
-rw-r--r-- | gtk-engine/src/olpc_theme_draw.c | 1478 | ||||
-rw-r--r-- | gtk-engine/src/widget-information.c | 331 | ||||
-rw-r--r-- | gtk-engine/src/widget-information.h | 104 | ||||
-rw-r--r-- | gtk-engine/theme/Makefile.am | 5 | ||||
-rw-r--r-- | gtk-engine/theme/gtkrc | 102 | ||||
-rw-r--r-- | gtkrc2-default | 1 | ||||
-rwxr-xr-x | setup-user-theme.py | 38 | ||||
-rwxr-xr-x | test/gtk-engine-test.py | 54 |
22 files changed, 3633 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index d74ad4b..b043bfd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = art po matchbox +SUBDIRS = art gtk-engine po matchbox intltool_extra = intltool-extract.in intltool-merge.in intltool-update.in diff --git a/configure.in b/configure.in index e42db42..2ccb498 100644 --- a/configure.in +++ b/configure.in @@ -24,6 +24,8 @@ GDK_PIXBUF2_LIBS=`$PKG_CONFIG --libs gdk-pixbuf-2.0` AC_SUBST(GDK_PIXBUF2_CFLAGS) AC_SUBST(GDK_PIXBUF2_LIBS) +PKG_CHECK_MODULES(ENGINE, gtk+-2.0 >= 2.0 gobject-2.0 >= 2.0 cairo >= 0.1.1) + dnl =========================================================================== dnl Use lots of warning flags with GCC @@ -53,6 +55,9 @@ art/icon-theme/scalable/control/Makefile art/icon-theme/scalable/device/Makefile art/icon-theme/scalable/stock/Makefile art/icon-theme/scalable/object/Makefile +gtk-engine/Makefile +gtk-engine/src/Makefile +gtk-engine/theme/Makefile matchbox/Makefile po/Makefile.in ]) diff --git a/gtk-engine/Makefile.am b/gtk-engine/Makefile.am new file mode 100644 index 0000000..e5b32d9 --- /dev/null +++ b/gtk-engine/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src theme diff --git a/gtk-engine/src/Makefile.am b/gtk-engine/src/Makefile.am new file mode 100644 index 0000000..abda93e --- /dev/null +++ b/gtk-engine/src/Makefile.am @@ -0,0 +1,27 @@ +INCLUDES = \ + -DGTK_DISABLE_DEPRECATED \ + -DGDK_DISABLE_DEPRECATED \ + -DG_DISABLE_DEPRECATED \ + $(ENGINE_CFLAGS) $(WARN_CFLAGS) + +enginedir = $(libdir)/gtk-2.0/$(GTK_VERSION)/engines +engine_LTLIBRARIES = libolpc.la + +libolpc_la_SOURCES = \ + cairo-support.c \ + cairo-support.h \ + general-support.h \ + ge-support.h \ + olpc_main.c \ + olpc_misc.c \ + olpc_misc.h \ + olpc_rc_style.c \ + olpc_rc_style.h \ + olpc_style.h \ + olpc_theme_draw.c \ + widget-information.c \ + widget-information.h + +libolpc_la_LDFLAGS = \ + -avoid-version -no-undefined -module \ + $(ENGINE_LIBS) diff --git a/gtk-engine/src/cairo-support.c b/gtk-engine/src/cairo-support.c new file mode 100644 index 0000000..5c90547 --- /dev/null +++ b/gtk-engine/src/cairo-support.c @@ -0,0 +1,454 @@ +#include "general-support.h" +#include "cairo-support.h" + +/*********************************************** + * ge_hsb_from_color - + * + * Get HSB values from RGB values. + * + * Modified from Smooth but originated in GTK+ + ***********************************************/ +void +ge_hsb_from_color (const CairoColor *color, + gdouble *hue, + gdouble *saturation, + gdouble *brightness) +{ + gdouble min, max, delta; + gdouble red, green, blue; + + red = color->r; + green = color->g; + blue = color->b; + + if (red > green) + { + max = MAX(red, blue); + min = MIN(green, blue); + } + else + { + max = MAX(green, blue); + min = MIN(red, blue); + } + + *brightness = (max + min) / 2; + + if (max == min) + { + *hue = 0; + *saturation = 0; + } + else + { + if (*brightness <= 0.5) + *saturation = (max - min) / (max + min); + else + *saturation = (max - min) / (2 - max - min); + + delta = max -min; + + if (red == max) + *hue = (green - blue) / delta; + else if (green == max) + *hue = 2 + (blue - red) / delta; + else if (blue == max) + *hue = 4 + (red - green) / delta; + + *hue *= 60; + if (*hue < 0.0) + *hue += 360; + } +} + +/*********************************************** + * ge_color_from_hsb - + * + * Get RGB values from HSB values. + * + * Modified from Smooth but originated in GTK+ + ***********************************************/ +#define MODULA(number, divisor) (((gint)number % divisor) + (number - (gint)number)) +void +ge_color_from_hsb (gdouble hue, + gdouble saturation, + gdouble brightness, + CairoColor *color) +{ + gint i; + gdouble hue_shift[3], color_shift[3]; + gdouble m1, m2, m3; + + if (!color) return; + + if (brightness <= 0.5) + m2 = brightness * (1 + saturation); + else + m2 = brightness + saturation - brightness * saturation; + + m1 = 2 * brightness - m2; + + hue_shift[0] = hue + 120; + hue_shift[1] = hue; + hue_shift[2] = hue - 120; + + color_shift[0] = color_shift[1] = color_shift[2] = brightness; + + i = (saturation == 0)?3:0; + + for (; i < 3; i++) + { + m3 = hue_shift[i]; + + if (m3 > 360) + m3 = MODULA(m3, 360); + else if (m3 < 0) + m3 = 360 - MODULA(ABS(m3), 360); + + if (m3 < 60) + color_shift[i] = m1 + (m2 - m1) * m3 / 60; + else if (m3 < 180) + color_shift[i] = m2; + else if (m3 < 240) + color_shift[i] = m1 + (m2 - m1) * (240 - m3) / 60; + else + color_shift[i] = m1; + } + + color->r = color_shift[0]; + color->g = color_shift[1]; + color->b = color_shift[2]; + color->a = 1.0; +} + +void +ge_gdk_color_to_cairo (GdkColor *c, CairoColor *cc) +{ + gdouble r, g, b; + + g_return_if_fail (c && cc); + + r = c->red / 65536.0; + g = c->green / 65536.0; + b = c->blue / 65536.0; + + cc->r = r; + cc->g = g; + cc->b = b; + cc->a = 1.0; +} + +void +ge_cairo_color_to_gtk (CairoColor *cc, GdkColor *c) +{ + gdouble r, g, b; + + g_return_if_fail (c && cc); + + r = cc->r * 65536.0; + g = cc->g * 65536.0; + b = cc->b * 65536.0; + + c->red = r; + c->green = g; + c->blue = b; +} + +void +ge_gtk_style_to_cairo_color_cube (GtkStyle * style, CairoColorCube *cube) +{ + int i; + + g_return_if_fail (style && cube); + + for (i = 0; i < 5; i++) + { + ge_gdk_color_to_cairo (&style->bg[i], &cube->bg[i]); + ge_gdk_color_to_cairo (&style->fg[i], &cube->fg[i]); + + ge_gdk_color_to_cairo (&style->dark[i], &cube->dark[i]); + ge_gdk_color_to_cairo (&style->light[i], &cube->light[i]); + ge_gdk_color_to_cairo (&style->mid[i], &cube->mid[i]); + + ge_gdk_color_to_cairo (&style->base[i], &cube->base[i]); + ge_gdk_color_to_cairo (&style->text[i], &cube->text[i]); + ge_gdk_color_to_cairo (&style->text_aa[i], &cube->text_aa[i]); + } + + cube->black.r = cube->black.g = cube->black.b = 0; + cube->black.a = 1; + + cube->white.r = cube->white.g = cube->white.b = 1; + cube->white.a = 1; +} + +void +ge_shade_color(const CairoColor *base, gdouble shade_ratio, CairoColor *composite) +{ + gdouble hue = 0; + gdouble saturation = 0; + gdouble brightness = 0; + + g_return_if_fail (base && composite); + + ge_hsb_from_color (base, &hue, &saturation, &brightness); + + brightness = MIN(brightness*shade_ratio, 1.0); + brightness = MAX(brightness, 0.0); + + saturation = MIN(saturation*shade_ratio, 1.0); + saturation = MAX(saturation, 0.0); + + ge_color_from_hsb (hue, saturation, brightness, composite); + composite->a = base->a; +} + +void +ge_saturate_color (const CairoColor * base, gdouble saturate_level, CairoColor *composite) +{ + gdouble hue = 0; + gdouble saturation = 0; + gdouble brightness = 0; + + g_return_if_fail (base && composite); + + ge_hsb_from_color (base, &hue, &saturation, &brightness); + + saturation = MIN(saturation*saturate_level, 1.0); + saturation = MAX(saturation, 0.0); + + ge_color_from_hsb (hue, saturation, brightness, composite); + composite->a = base->a; +} + +cairo_t * +ge_gdk_drawable_to_cairo (GdkDrawable *window, GdkRectangle *area) +{ + cairo_t *cr; + + g_return_val_if_fail (window != NULL, NULL); + + cr = (cairo_t*) gdk_cairo_create (window); + cairo_set_line_width (cr, 1.0); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); + + if (area) + { + cairo_rectangle (cr, area->x, area->y, area->width, area->height); + cairo_clip_preserve (cr); + cairo_new_path (cr); + } + + return cr; +} + +void +ge_cairo_set_color (cairo_t *cr, CairoColor *color) +{ + g_return_if_fail (cr && color); + + cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a); +} + +void +ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, gfloat offset, CairoColor *color) +{ + g_return_if_fail (pattern && color); + + cairo_pattern_add_color_stop_rgba (pattern, offset, color->r, color->g, color->b, color->a); +} + +void +ge_cairo_rounded_rectangle (cairo_t *cr, + double x, double y, double w, double h, + double radius, CairoCorners corners) +{ + g_return_if_fail (cr != NULL); + + if (radius < 0.0001) + { + cairo_rectangle (cr, x, y, w, h); + return; + } + + if (corners & CR_CORNER_TOPLEFT) + cairo_move_to (cr, x+radius, y); + else + cairo_move_to (cr, x, y); + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x+w-radius, y+radius, radius, M_PI * 1.5, M_PI * 2); + else + cairo_line_to (cr, x+w, y); + + if (corners & CR_CORNER_BOTTOMRIGHT) + cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, M_PI * 0.5); + else + cairo_line_to (cr, x+w, y+h); + + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_arc (cr, x+radius, y+h-radius, radius, M_PI * 0.5, M_PI); + else + cairo_line_to (cr, x, y+h); + + if (corners & CR_CORNER_TOPLEFT) + cairo_arc (cr, x+radius, y+radius, radius, M_PI, M_PI * 1.5); + else + cairo_line_to (cr, x, y); +} + +/*********************************************** + * ge_cairo_simple_border - + * + * A simple routine to draw thin squared + * borders with a topleft and bottomright color. + * + * It originated in Smooth-Engine. + ***********************************************/ +void +ge_cairo_simple_border (cairo_t *cr, + CairoColor * tl, CairoColor * br, + gint x, gint y, gint width, gint height, + gboolean topleft_overlap) +{ + gboolean solid_color; + + g_return_if_fail (cr != NULL); + g_return_if_fail (tl != NULL); + g_return_if_fail (br != NULL); + + + solid_color = (tl == br) || ((tl->r == br->r) && (tl->g == br->g) && (tl->b == br->b) && (tl->a == br->a)); + + topleft_overlap &= !solid_color; + + cairo_save(cr); + + cairo_set_line_width (cr, 1); + + if (topleft_overlap) + { + ge_cairo_set_color(cr, br); + + cairo_move_to(cr, x + 0.5, y + height - 0.5); + cairo_line_to(cr, x + width - 0.5, y + height - 0.5); + cairo_line_to(cr, x + width - 0.5, y + 0.5); + + cairo_stroke(cr); + } + + ge_cairo_set_color(cr, tl); + + cairo_move_to(cr, x + 0.5, y + height - 0.5); + cairo_line_to(cr, x + 0.5, y + 0.5); + cairo_line_to(cr, x + width - 0.5, y + 0.5); + + if (!topleft_overlap) + { + if (!solid_color) + { + cairo_stroke(cr); + ge_cairo_set_color(cr, br); + } + + cairo_move_to(cr, x + 0.5, y + height - 0.5); + cairo_line_to(cr, x + width - 0.5, y + height - 0.5); + cairo_line_to(cr, x + width - 0.5, y + 0.5); + } + + cairo_stroke(cr); + + cairo_restore(cr); +} + +void ge_cairo_polygon (cairo_t *cr, + CairoColor *color, + GdkPoint *points, + gint npoints) +{ + int i = 0; + + cairo_save(cr); + + ge_cairo_set_color(cr, color); + cairo_move_to(cr, points[0].x, points[0].y); + + for (i = 1; i < npoints; i++) + { + if (!((points[i].x == points[i + 1].x) && + (points[i].y == points[i + 1].y))) + { + cairo_line_to(cr, points[i].x, points[i].y); + } + } + + if ((points[npoints-1].x != points[0].y) || + (points[npoints-1].y != points[0].y)) + { + cairo_line_to(cr, points[0].x, points[0].y); + } + + cairo_fill(cr); + + cairo_restore(cr); +} + +void ge_cairo_line (cairo_t *cr, + CairoColor *color, + gint x1, + gint y1, + gint x2, + gint y2) +{ + cairo_save(cr); + + ge_cairo_set_color(cr, color); + cairo_set_line_width (cr, 1); + + cairo_move_to(cr, x1 + 0.5, y1 + 0.5); + cairo_line_to(cr, x2 + 0.5, y2 + 0.5); + + cairo_stroke(cr); + + cairo_restore(cr); +} + +void +ge_cairo_mirror (cairo_t *cr, + CairoMirror mirror, + gint *x, + gint *y, + gint *width, + gint *height) +{ + cairo_matrix_t matrix; + + cairo_matrix_init_identity (&matrix); + + if (mirror & CR_MIRROR_HORIZONTAL) + { + cairo_matrix_scale (&matrix, -1, 1); + cairo_matrix_translate (&matrix, *width, 0); + } + if (mirror & CR_MIRROR_VERTICAL) + { + cairo_matrix_scale (&matrix, 1, -1); + cairo_matrix_translate (&matrix, 0, *height); + } + + cairo_transform (cr, &matrix); +} + +/* The following function will be called by GTK+ when the module + * is loaded and checks to see if we are compatible with the + * version of GTK+ that loads us. + */ +G_MODULE_EXPORT const gchar* g_module_check_init (GModule *module); +const gchar* +g_module_check_init (GModule *module) +{ + return gtk_check_version (GTK_MAJOR_VERSION, + GTK_MINOR_VERSION, + GTK_MICRO_VERSION - GTK_INTERFACE_AGE); +} diff --git a/gtk-engine/src/cairo-support.h b/gtk-engine/src/cairo-support.h new file mode 100644 index 0000000..2094688 --- /dev/null +++ b/gtk-engine/src/cairo-support.h @@ -0,0 +1,81 @@ +/* Helpful functions when dealing with cairo in gtk engines */ + +#include <gtk/gtk.h> +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 +#endif + +typedef struct +{ + gdouble r; + gdouble g; + gdouble b; + gdouble a; +} CairoColor; + +typedef struct +{ + CairoColor bg[5]; + CairoColor fg[5]; + + CairoColor dark[5]; + CairoColor light[5]; + CairoColor mid[5]; + + CairoColor base[5]; + CairoColor text[5]; + CairoColor text_aa[5]; + + CairoColor black; + CairoColor white; +} CairoColorCube; + +typedef enum +{ + CR_CORNER_NONE = 0, + CR_CORNER_TOPLEFT = 1, + CR_CORNER_TOPRIGHT = 2, + CR_CORNER_BOTTOMLEFT = 4, + CR_CORNER_BOTTOMRIGHT = 8, + CR_CORNER_ALL = 15 +} CairoCorners; + +typedef enum +{ + CR_MIRROR_NONE = 0, + CR_MIRROR_HORIZONTAL = 1 << 0, + CR_MIRROR_VERTICAL = 1 << 1 +} CairoMirror; + +GE_INTERNAL void ge_hsb_from_color (const CairoColor *color, gdouble *hue, gdouble *saturation, gdouble *brightness); +GE_INTERNAL void ge_color_from_hsb (gdouble hue, gdouble saturation, gdouble brightness, CairoColor *color); + +GE_INTERNAL void ge_gdk_color_to_cairo (GdkColor * gc, CairoColor * cc); +GE_INTERNAL void ge_cairo_color_to_gtk (CairoColor *cc, GdkColor *c); +GE_INTERNAL void ge_gtk_style_to_cairo_color_cube (GtkStyle * style, CairoColorCube *cube); + +GE_INTERNAL void ge_shade_color(const CairoColor *base, gdouble shade_ratio, CairoColor *composite); +GE_INTERNAL void ge_saturate_color (const CairoColor * base, gdouble saturate_level, CairoColor *composite); + +GE_INTERNAL cairo_t * ge_gdk_drawable_to_cairo (GdkDrawable *window, GdkRectangle *area); +GE_INTERNAL void ge_cairo_set_color (cairo_t *cr, CairoColor *color); +GE_INTERNAL void ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, gfloat offset, CairoColor *color); + +GE_INTERNAL void ge_cairo_rounded_rectangle (cairo_t *cr, double x, double y, double w, double h, double radius, CairoCorners corners); + +GE_INTERNAL void ge_cairo_simple_border (cairo_t *cr, CairoColor * tl, CairoColor * br, gint x, gint y, gint width, gint height, gboolean topleft_overlap); + +GE_INTERNAL void ge_cairo_line (cairo_t *cr, CairoColor *color, gint x1, gint y1, gint x2, gint y2); +GE_INTERNAL void ge_cairo_polygon (cairo_t *cr, CairoColor *color, GdkPoint *points, gint npoints); + +GE_INTERNAL void ge_cairo_mirror (cairo_t *cr, CairoMirror mirror, gint *x, gint *y, gint *width, gint *height); diff --git a/gtk-engine/src/ge-support.h b/gtk-engine/src/ge-support.h new file mode 100644 index 0000000..e0a42b6 --- /dev/null +++ b/gtk-engine/src/ge-support.h @@ -0,0 +1,9 @@ +#ifndef GE_SUPPORT_H +#define GE_SUPPORT_H + +#include "general-support.h" +#include "cairo-support.h" +#include "widget-information.h" + + +#endif /* GE_SUPPORT_H */ diff --git a/gtk-engine/src/general-support.h b/gtk-engine/src/general-support.h new file mode 100644 index 0000000..d03abde --- /dev/null +++ b/gtk-engine/src/general-support.h @@ -0,0 +1,35 @@ + +#include <glib.h> + +/* macros to make sure that things are sane ... */ + +#define CHECK_DETAIL(detail, value) ((detail) && (!strcmp(value, detail))) + +#define CHECK_ARGS \ + g_return_if_fail (window != NULL); \ + g_return_if_fail (style != NULL); + +#define SANITIZE_SIZE \ + g_return_if_fail (width >= -1); \ + g_return_if_fail (height >= -1); \ + \ + if ((width == -1) && (height == -1)) \ + gdk_drawable_get_size (window, &width, &height); \ + else if (width == -1) \ + gdk_drawable_get_size (window, &width, NULL); \ + else if (height == -1) \ + gdk_drawable_get_size (window, NULL, &height); + +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) +# define GE_EXPORT __attribute__((__visibility__("default"))) +# define GE_HIDDEN __attribute__((__visibility__("hidden"))) +# define GE_INTERNAL __attribute__((__visibility__("internal"))) +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define GE_EXPORT __global +# define GE_HIDDEN __hidden +# define GE_INTERNAL __hidden +#else /* not gcc >= 3.3 and not Sun Studio >= 8 */ +# define GE_EXPORT +# define GE_HIDDEN +# define GE_INTERNAL +#endif diff --git a/gtk-engine/src/olpc_main.c b/gtk-engine/src/olpc_main.c new file mode 100644 index 0000000..0cbfc76 --- /dev/null +++ b/gtk-engine/src/olpc_main.c @@ -0,0 +1,23 @@ +#include <gmodule.h> +#include "olpc_rc_style.h" +#include "olpc_style.h" + +G_MODULE_EXPORT void +theme_init (GTypeModule *module) +{ + olpc_rc_style_register_type (module); + olpc_style_register_type (module); +} + +G_MODULE_EXPORT void +theme_exit (void) +{ +} + +G_MODULE_EXPORT GtkRcStyle * +theme_create_rc_style (void) +{ + void *ptr; + ptr = GTK_RC_STYLE (g_object_new (OLPC_TYPE_RC_STYLE, NULL)); + return (GtkRcStyle *)ptr; +} diff --git a/gtk-engine/src/olpc_misc.c b/gtk-engine/src/olpc_misc.c new file mode 100644 index 0000000..831a736 --- /dev/null +++ b/gtk-engine/src/olpc_misc.c @@ -0,0 +1,325 @@ +#include <math.h> +#include <string.h> +#include <gtk/gtknotebook.h> + +#include "olpc_style.h" +#include "olpc_rc_style.h" +#include "olpc_misc.h" + +GtkShadowType +olpc_shadow_type (GtkStyle *style, const char *detail, GtkShadowType requested) +{ + GtkShadowType retval = GTK_SHADOW_NONE; + + if (requested != GTK_SHADOW_NONE) { + retval = GTK_SHADOW_ETCHED_IN; + } + + if (CHECK_DETAIL (detail, "dockitem") || CHECK_DETAIL (detail, "handlebox_bin") || CHECK_DETAIL (detail, "spinbutton_up") || CHECK_DETAIL (detail, "spinbutton_down")) { + retval = GTK_SHADOW_NONE; + } else if (CHECK_DETAIL (detail, "button") || CHECK_DETAIL (detail, "togglebutton") || CHECK_DETAIL (detail, "notebook") || CHECK_DETAIL (detail, "optionmenu")) { + retval = requested; + } else if (CHECK_DETAIL (detail, "menu")) { + retval = GTK_SHADOW_ETCHED_IN; + } + + return retval; +} + +/*********************************************** + * olpc_arrow- + * + * borrowed from redmond till shareable + ***********************************************/ +void olpc_arrow (cairo_t *canvas, + CairoColor * color, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height) +{ + gint aw = width, ah = height; + GdkPoint points[3]; + + switch (arrow_type) + { + case GTK_ARROW_UP: + case GTK_ARROW_DOWN: + { + gdouble tmp=((aw+1)/2) - ((height%2)?1:0); + + if (tmp > ah) + { + aw = 2*ah - 1 - ((height%2)?1:0); + ah = (aw+1)/2; + } + else + { + ah = (gint) tmp; + aw = 2*ah - 1; + } + + if ((aw < 5) || (ah < 3)) + { + aw = 5; + ah = 3; + } + + x += (width - aw) / 2 ; + y += (height - ah) / 2; + width = aw; + height = ah; + + width += width % 2 - 1; + + points[0].x = x; + points[1].x = x + width - 1; + points[2].x = x + ((height - 1) - (height - (1 + width / 2))); + + points[0].y = points[1].y = y; + points[2].y = y + height - 1; + + if (arrow_type == GTK_ARROW_UP) + { + gint flip = points[1].y; + + points[0].y = points[1].y = points[2].y; + points[2].y = flip; + } + } + break; + + case GTK_ARROW_LEFT: + case GTK_ARROW_RIGHT: + { + gdouble tmp=((ah+1)/2) - ((width%2)?1:0); + + if (tmp > aw) + { + ah = 2*aw - 1 - ((width%2)?1:0); + aw = (ah+1)/2; + } + else + { + aw = (gint) tmp; + ah = 2*aw - 1; + } + + if ((ah < 5) || (aw < 3)) + { + ah = 5; + aw = 3; + } + + x += (width - aw) / 2 ; + y += (height - ah) / 2; + width = aw; + height = ah; + + height += height % 2 - 1; + + points[0].y = y; + points[1].y = y + height - 1; + points[2].y = y + ((width - 1) - (width - (1 + height / 2))); + + points[0].x = points[1].x = x; + points[2].x = x + width - 1; + + if (arrow_type == GTK_ARROW_LEFT) + { + gint flip = points[0].x; + + points[0].x = points[1].x = points[2].x; + points[2].x = flip; + } + } + break; + + default: + { + return; + } + } + + cairo_save(canvas); + + ge_cairo_set_color(canvas, color); + cairo_set_line_width (canvas, 0.5); + + cairo_move_to(canvas, points[0].x + 0.5, points[0].y + 0.5); + cairo_line_to(canvas, points[1].x + 0.5, points[1].y + 0.5); + cairo_line_to(canvas, points[2].x + 0.5, points[2].y + 0.5); + cairo_line_to(canvas, points[0].x + 0.5, points[0].y + 0.5); + + if (fill) + { + cairo_stroke_preserve(canvas); + + cairo_fill(canvas); + } + else + { + cairo_stroke(canvas); + } + + cairo_restore(canvas); +} + +void +olpc_slash_two(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y, + gint width, + gint height) +{ + gdouble centerx, centery, thick; + gint ax1=0,ax2=0,ay1=0,ay2=0; + + centerx = width/2 + x + 0.5; + centery = height/2 + y + 0.5; + if (width > height) + { + ax1 = -2; ax2 = 1; + } + else + { + ay1 = -2; ay2 = 1; + } + + thick = ((width < height?width-1:height-1) >> 1) - 1.5; + + cairo_set_line_width (cr, 1); + + ge_cairo_set_color(cr, color2); + cairo_move_to(cr, centerx - thick + ax1, centery + thick + ay1); + cairo_line_to(cr, centerx + thick + ax1, centery - thick + ay1); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color1); + cairo_move_to(cr, centerx - thick + ax1 + ax2, centery + thick + ay1 + ay2); + cairo_line_to(cr, centerx + thick + ax1 + ax2, centery - thick + ay1 + ay2); + cairo_stroke(cr); + + if (width > height) + { + ax1 = 2; /* ax2 = 1; */ + } + else + { + ay1 = 2; /* ay2 = 1; */ + } + + cairo_set_line_width (cr, 1); + + ge_cairo_set_color(cr, color2); + cairo_move_to(cr, centerx - thick + ax1, centery + thick + ay1); + cairo_line_to(cr, centerx + thick + ax1, centery - thick + ay1); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color1); + cairo_move_to(cr, centerx - thick + ax1 + ax2, centery + thick + ay1 + ay2); + cairo_line_to(cr, centerx + thick + ax1 + ax2, centery - thick + ay1 + ay2); + cairo_stroke(cr); +} + + +void +olpc_slash_one(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y, + gint width, + gint height) +{ + gint centerx, centery, thick; + + centerx = width/2 + x + 0.5; + centery = height/2 + y + 0.5; + + thick = ((width < height?width:height) >> 1) - 1.5; + + cairo_set_line_width (cr, 1); + + ge_cairo_set_color(cr, color2); + cairo_move_to(cr, centerx - thick, centery + thick); + cairo_line_to(cr, centerx + thick, centery - thick); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color2); + cairo_move_to(cr, centerx - thick, centery + thick - 1); + cairo_line_to(cr, centerx + thick - 1, centery - thick); + cairo_stroke(cr); +} + +void +olpc_dot(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y) +{ + cairo_save(cr); + + cairo_set_line_width (cr, 0.5); + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + + ge_cairo_set_color(cr, color2); + + cairo_rectangle (cr, x - 1, y, 0.5, 0.5); + cairo_rectangle (cr, x - 1, y - 1, 0.5, 0.5); + cairo_rectangle (cr, x, y - 1, 0.5, 0.5); + + cairo_stroke(cr); + + ge_cairo_set_color(cr, color1); + + cairo_rectangle (cr, x + 1, y, 0.5, 0.5); + cairo_rectangle (cr, x + 1, y + 1, 0.5, 0.5); + cairo_rectangle (cr, x, y + 1, 0.5, 0.5); + + cairo_stroke(cr); + + cairo_restore(cr); +} + + +void +olpc_draw_separator(cairo_t *cr, gboolean horizontal, + int x, int y, int width, int height) +{ + if (horizontal) + { + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y+0.5); + + cairo_move_to (cr, 0.0, 0.0); + cairo_line_to (cr, width+1, 0.0); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.2); + cairo_stroke (cr); + + cairo_move_to (cr, 0.0, 1.0); + cairo_line_to (cr, width, 1.0); + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.8); + cairo_stroke (cr); + } + else + { + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y); + + cairo_move_to (cr, 0.0, 0.0); + cairo_line_to (cr, 0.0, height); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.2); + cairo_stroke (cr); + + cairo_move_to (cr, 1.0, 0.0); + cairo_line_to (cr, 1.0, height); + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.8); + cairo_stroke (cr); + } +} diff --git a/gtk-engine/src/olpc_misc.h b/gtk-engine/src/olpc_misc.h new file mode 100644 index 0000000..478a485 --- /dev/null +++ b/gtk-engine/src/olpc_misc.h @@ -0,0 +1,39 @@ +GtkShadowType +GE_INTERNAL olpc_shadow_type (GtkStyle *style, const char *detail, GtkShadowType requested); + +GE_INTERNAL void +olpc_slash_two(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y, + gint width, + gint height); + +GE_INTERNAL void +olpc_slash_one(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y, + gint width, + gint height); + +GE_INTERNAL void +olpc_dot(cairo_t *cr, + CairoColor *color1, + CairoColor *color2, + gint x, + gint y); + +GE_INTERNAL void olpc_arrow (cairo_t *canvas, + CairoColor *color, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height); + +GE_INTERNAL void olpc_draw_separator(cairo_t *cr, gboolean horizontal, + int x, int y, int width, int height); diff --git a/gtk-engine/src/olpc_rc_style.c b/gtk-engine/src/olpc_rc_style.c new file mode 100644 index 0000000..8601bdd --- /dev/null +++ b/gtk-engine/src/olpc_rc_style.c @@ -0,0 +1,398 @@ +#include "olpc_rc_style.h" +#include "olpc_style.h" + +static void olpc_rc_style_init (OlpcRcStyle *style); +static void olpc_rc_style_class_init (OlpcRcStyleClass *klass); +static guint olpc_rc_style_parse (GtkRcStyle *rc_style, + GtkSettings *settings, + GScanner *scanner); +static void olpc_rc_style_merge (GtkRcStyle *dest, + GtkRcStyle *src); + +static GtkStyle *olpc_rc_style_create_style (GtkRcStyle *rc_style); + + +static struct + { + gchar *name; + guint token; + } +olpc_rc_symbols[] = +{ + { "rect_scrollbar", TOKEN_RECTSCROLLBAR }, + { "scrollbar_marks", TOKEN_SCROLLBARMARKS }, + { "scroll_button_marks", TOKEN_SCROLLBUTTONMARKS }, + { "handlebox_marks", TOKEN_HANDLEBOXMARKS }, + { "mark_type1", TOKEN_MARKTYPE1 }, + { "mark_type2", TOKEN_MARKTYPE2 }, + { "paned_dots", TOKEN_PANEDDOTS }, + + { "TRUE", TOKEN_TRUE }, + { "FALSE", TOKEN_FALSE }, + + { "NOTHING", TOKEN_NOTHING }, + { "SLASH", TOKEN_SLASH }, + { "INVSLASH", TOKEN_INVSLASH }, + { "DOT", TOKEN_DOT }, + { "INVDOT", TOKEN_INVDOT }, + { "ARROW", TOKEN_ARROW }, + + { "FULL", TOKEN_FULL }, + { "SOME", TOKEN_SOME }, + { "NONE", TOKEN_NONE }, + +}; + +static guint n_olpc_rc_symbols = sizeof(olpc_rc_symbols) / sizeof(olpc_rc_symbols[0]); + +static GtkRcStyleClass *olpc_parent_rc_style_class; + +GType olpc_type_rc_style = 0; + +void +olpc_rc_style_register_type (GTypeModule *module) +{ + static const GTypeInfo object_info = + { + sizeof (OlpcRcStyleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) olpc_rc_style_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (OlpcRcStyle), + 0, /* n_preallocs */ + (GInstanceInitFunc) olpc_rc_style_init, + }; + + olpc_type_rc_style = g_type_module_register_type (module, + GTK_TYPE_RC_STYLE, + "OlpcRcStyle", + &object_info, 0); +} + +static void +olpc_rc_style_init (OlpcRcStyle *style) +{ +} + +static void +olpc_rc_style_class_init (OlpcRcStyleClass *klass) +{ + GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass); + + olpc_parent_rc_style_class = g_type_class_peek_parent (klass); + + rc_style_class->parse = olpc_rc_style_parse; + rc_style_class->merge = olpc_rc_style_merge; + rc_style_class->create_style = olpc_rc_style_create_style; +} + +#if 0 +static guint +olpc_rc_parse_int(GScanner *scanner, + GTokenType wanted_token, + guint *retval) +{ + guint token; + + token = g_scanner_get_next_token(scanner); + if (token != wanted_token) + return wanted_token; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return wanted_token; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_INT) + return G_TOKEN_INT; + + *retval = g_scanner_cur_value(scanner).v_int; + + return G_TOKEN_NONE; +} +#endif + +static guint +olpc_rc_parse_boolean(GScanner *scanner, + GTokenType wanted_token, + guint *retval) +{ + guint token; + + token = g_scanner_get_next_token(scanner); + if (token != wanted_token) + return wanted_token; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; + + token = g_scanner_get_next_token(scanner); + if (token == TOKEN_TRUE) + *retval = TRUE; + else if (token == TOKEN_FALSE) + *retval = FALSE; + else + return TOKEN_TRUE; + + return G_TOKEN_NONE; +} + +static guint +olpc_rc_parse_marktype(GScanner *scanner, + GTokenType wanted_token, + guint *retval) +{ + guint token; + + token = g_scanner_get_next_token(scanner); + if (token != wanted_token) + return wanted_token; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; + + token = g_scanner_get_next_token(scanner); + switch (token) + { + case TOKEN_NOTHING: + *retval = MARKS_NOTHING; + break; + case TOKEN_SLASH: + *retval = MARKS_SLASH; + break; + case TOKEN_INVSLASH: + *retval = MARKS_INVSLASH; + break; + case TOKEN_DOT: + *retval = MARKS_DOT; + break; + case TOKEN_INVDOT: + *retval = MARKS_INVDOT; + break; + case TOKEN_ARROW: + *retval = MARKS_ARROW; + break; + default: + return TOKEN_NOTHING; + } + + return G_TOKEN_NONE; +} + +static guint +olpc_rc_parse_paned(GScanner *scanner, + GTokenType wanted_token, + guint *retval) +{ + guint token; + + token = g_scanner_get_next_token(scanner); + if (token != wanted_token) + return wanted_token; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; + + token = g_scanner_get_next_token(scanner); + switch (token) + { + case TOKEN_NONE: + *retval = PANED_DOTSNONE; + break; + case TOKEN_SOME: + *retval = PANED_DOTSSOME; + break; + case TOKEN_FULL: + *retval = PANED_DOTSFULL; + break; + default: + return TOKEN_NOTHING; + } + + return G_TOKEN_NONE; +} + +static guint +olpc_rc_style_parse (GtkRcStyle *rc_style, + GtkSettings *settings, + GScanner *scanner) +{ + static GQuark scope_id = 0; + OlpcRcStyle *theme_data = OLPC_RC_STYLE (rc_style); + guint old_scope; + guint token; + guint i; + + /* Set up a new scope in this scanner. */ + + /* + g_print("olpc_rc_parse_rc_style(\"%s\")\n", rc_style->name); + */ + if (!scope_id) + scope_id = g_quark_from_string("theme_engine"); + + /* If we bail out due to errors, we *don't* reset the scope, so the + * error messaging code can make sense of our tokens. + */ + old_scope = g_scanner_set_scope(scanner, scope_id); + + /* Now check if we already added our symbols to this scope + * (in some previous call to olpc_rc_parse_rc_style for the + * same scanner. + */ + + if (!g_scanner_lookup_symbol(scanner, olpc_rc_symbols[0].name)) + { + for (i = 0; i < n_olpc_rc_symbols; i++) + { + g_scanner_scope_add_symbol(scanner, scope_id, + olpc_rc_symbols[i].name, + GINT_TO_POINTER(olpc_rc_symbols[i].token)); + } + } + + /* We're ready to go, now parse the top level */ + + /* theme_data = g_new0(OlpcRcStyle, 1); */ + theme_data->scrollbar_type = DEFAULT_SCROLLSHAPE; + theme_data->scrollbar_marks = DEFAULT_SCROLLBARMARKS; + theme_data->scroll_button_marks = DEFAULT_SCROLLBUTTONMARKS; + theme_data->handlebox_marks = DEFAULT_HANDLEBOXMARKS; + theme_data->mark_type1 = DEFAULT_MARKTYPE1; + theme_data->mark_type2 = DEFAULT_MARKTYPE2; + + token = g_scanner_peek_next_token(scanner); + while (token != G_TOKEN_RIGHT_CURLY) + { + switch (token) + { + case TOKEN_RECTSCROLLBAR: + token = olpc_rc_parse_boolean(scanner, TOKEN_RECTSCROLLBAR, &i); + if (token != G_TOKEN_NONE) + break; + if (i == FALSE) + theme_data->scrollbar_type = SCROLL_SHAPED; + else + theme_data->scrollbar_type = SCROLL_RECT; + break; + + case TOKEN_SCROLLBUTTONMARKS: + token = olpc_rc_parse_boolean(scanner, TOKEN_SCROLLBUTTONMARKS, &i); + if (token != G_TOKEN_NONE) + break; + if (i == TRUE) + theme_data->mark_type2 = MARKS_SLASH; + else + theme_data->mark_type2 = MARKS_NOTHING; + /* + if (i == TRUE) + theme_data->scroll_button_marks = MARKS_ON; + else + theme_data->scroll_button_marks = MARKS_OFF; + */ + break; + + case TOKEN_SCROLLBARMARKS: + token = olpc_rc_parse_boolean(scanner, TOKEN_SCROLLBARMARKS, &i); + if (token != G_TOKEN_NONE) + break; + if (i == TRUE) + theme_data->mark_type1 = MARKS_SLASH; + else + theme_data->mark_type1 = MARKS_NOTHING; + /* + if (i == TRUE) + theme_data->scrollbar_marks = MARKS_ON; + else + theme_data->scrollbar_marks = MARKS_OFF; + */ + break; + + case TOKEN_HANDLEBOXMARKS: + token = olpc_rc_parse_boolean(scanner, TOKEN_HANDLEBOXMARKS, &i); + if (token != G_TOKEN_NONE) + break; + if (i == TRUE) + theme_data->handlebox_marks = MARKS_ON; + else + theme_data->handlebox_marks = MARKS_OFF; + break; + + case TOKEN_MARKTYPE1: + token = olpc_rc_parse_marktype(scanner, TOKEN_MARKTYPE1, &i); + if (token != G_TOKEN_NONE) + break; + theme_data->mark_type1 = i; + break; + + case TOKEN_MARKTYPE2: + token = olpc_rc_parse_marktype(scanner, TOKEN_MARKTYPE2, &i); + if (token != G_TOKEN_NONE) + break; + theme_data->mark_type2 = i; + break; + + case TOKEN_PANEDDOTS: + token = olpc_rc_parse_paned(scanner, TOKEN_PANEDDOTS, &i); + if (token != G_TOKEN_NONE) + break; + theme_data->paned_dots = i; + break; + + default: + g_scanner_get_next_token(scanner); + token = G_TOKEN_RIGHT_CURLY; + break; + } + + if (token != G_TOKEN_NONE) + { +// g_free(theme_data); + return token; + } + token = g_scanner_peek_next_token(scanner); + } + + g_scanner_get_next_token(scanner); + + g_scanner_set_scope(scanner, old_scope); + + return G_TOKEN_NONE; +} + +static void +olpc_rc_style_merge (GtkRcStyle * dest, + GtkRcStyle * src) +{ + if (OLPC_IS_RC_STYLE (src)) { + OlpcRcStyle *src_data = OLPC_RC_STYLE (src); + OlpcRcStyle *dest_data = OLPC_RC_STYLE (dest); + + /* + g_print("theme_merge_rc_style(\"%s\", \"%s\")\n", dest->name, src->name); + */ + + dest_data->scrollbar_type = src_data->scrollbar_type; + dest_data->scrollbar_marks = src_data->scrollbar_marks; + dest_data->scroll_button_marks = src_data->scroll_button_marks; + dest_data->handlebox_marks = src_data->handlebox_marks; + dest_data->mark_type1 = src_data->mark_type1; + dest_data->mark_type2 = src_data->mark_type2; + dest_data->paned_dots = src_data->paned_dots; + } + + olpc_parent_rc_style_class->merge (dest, src); +} + +/* Create an empty style suitable to this RC style + */ +static GtkStyle * +olpc_rc_style_create_style (GtkRcStyle *rc_style) +{ + return GTK_STYLE (g_object_new (OLPC_TYPE_STYLE, NULL)); +} diff --git a/gtk-engine/src/olpc_rc_style.h b/gtk-engine/src/olpc_rc_style.h new file mode 100644 index 0000000..6813533 --- /dev/null +++ b/gtk-engine/src/olpc_rc_style.h @@ -0,0 +1,93 @@ +#include <gtk/gtkrc.h> +#include "ge-support.h" + +typedef struct _OlpcRcStyle OlpcRcStyle; +typedef struct _OlpcRcStyleClass OlpcRcStyleClass; + +GE_INTERNAL extern GType olpc_type_rc_style; + +#define OLPC_TYPE_RC_STYLE olpc_type_rc_style +#define OLPC_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), OLPC_TYPE_RC_STYLE, OlpcRcStyle)) +#define OLPC_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OLPC_TYPE_RC_STYLE, OlpcRcStyleClass)) +#define OLPC_IS_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), OLPC_TYPE_RC_STYLE)) +#define OLPC_IS_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OLPC_TYPE_RC_STYLE)) +#define OLPC_RC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OLPC_TYPE_RC_STYLE, OlpcRcStyleClass)) + +struct _OlpcRcStyle +{ + GtkRcStyle parent_instance; + + guint scrollbar_type:1; + guint scrollbar_marks:1; + guint scroll_button_marks:1; + guint handlebox_marks:1; + guint mark_type1; + guint mark_type2; + guint paned_dots; +}; + +struct _OlpcRcStyleClass +{ + GtkRcStyleClass parent_class; +}; + +GE_INTERNAL void olpc_rc_style_register_type (GTypeModule *module); + +/* Default stuff */ +#define DEFAULT_SCROLLSHAPE SCROLL_SHAPED +#define DEFAULT_SCROLLBARMARKS MARKS_ON +#define DEFAULT_SCROLLBUTTONMARKS MARKS_ON +#define DEFAULT_HANDLEBOXMARKS MARKS_ON +#define DEFAULT_MARKTYPE1 MARKS_SLASH +#define DEFAULT_MARKTYPE2 MARKS_INVSLASH +#define DEFAULT_PANEDDOTS PANED_DOTSFULL + +#define DEFAULT_SCROLLTHUMB_SIZE 12 +#define DEFAULT_MIN_SLIDER_SIZE 9 +#define SMALLEST_HANDLE 17 + +enum + { + TOKEN_RECTSCROLLBAR = G_TOKEN_LAST + 1, + TOKEN_SCROLLBARMARKS, + TOKEN_SCROLLBUTTONMARKS, + TOKEN_HANDLEBOXMARKS, + TOKEN_MARKTYPE1, + TOKEN_MARKTYPE2, + TOKEN_PANEDDOTS, + + TOKEN_TRUE, + TOKEN_FALSE, + + TOKEN_NOTHING, + TOKEN_SLASH, + TOKEN_INVSLASH, + TOKEN_DOT, + TOKEN_INVDOT, + TOKEN_ARROW, + + TOKEN_FULL, + TOKEN_SOME, + TOKEN_NONE + }; + +enum + { + SCROLL_RECT = 0, + SCROLL_SHAPED = 1, + + MARKS_OFF = 0, + MARKS_ON = 1, + + MARKS_NOTHING = 0, + MARKS_SLASH = 1, + MARKS_INVSLASH = 2, + MARKS_DOT = 3, + MARKS_INVDOT = 4, + MARKS_ARROW = 5, + + PANED_DOTSFULL = 0, + PANED_DOTSSOME = 1, + PANED_DOTSNONE = 2 + }; + diff --git a/gtk-engine/src/olpc_style.h b/gtk-engine/src/olpc_style.h new file mode 100644 index 0000000..83addf7 --- /dev/null +++ b/gtk-engine/src/olpc_style.h @@ -0,0 +1,29 @@ +#include <gtk/gtkstyle.h> +#include "ge-support.h" + +typedef struct _OlpcStyle OlpcStyle; +typedef struct _OlpcStyleClass OlpcStyleClass; + +GE_INTERNAL extern GType olpc_type_style; + +#define OLPC_TYPE_STYLE olpc_type_style +#define OLPC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), OLPC_TYPE_STYLE, OlpcStyle)) +#define OLPC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OLPC_TYPE_STYLE, OlpcStyleClass)) +#define OLPC_IS_STYLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), OLPC_TYPE_STYLE)) +#define OLPC_IS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OLPC_TYPE_STYLE)) +#define OLPC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OLPC_TYPE_STYLE, OlpcStyleClass)) + +struct _OlpcStyle +{ + GtkStyle parent_instance; + CairoColorCube color_cube; +}; + +struct _OlpcStyleClass +{ + GtkStyleClass parent_class; +}; + +GE_INTERNAL void olpc_style_register_type (GTypeModule *module); + + diff --git a/gtk-engine/src/olpc_theme_draw.c b/gtk-engine/src/olpc_theme_draw.c new file mode 100644 index 0000000..7f347a7 --- /dev/null +++ b/gtk-engine/src/olpc_theme_draw.c @@ -0,0 +1,1478 @@ +/* Olpc theme for gtk, based on raster's Motif theme and the Metal theme. +Authors: Tim Gerla <timg@rrv.net> +Tomas Ögren <stric@ing.umu.se> + */ +/* #define DEBUG 1 */ + +#include <math.h> +#include <string.h> +#include <gtk/gtknotebook.h> + +#include "olpc_style.h" +#include "olpc_rc_style.h" +#include "olpc_misc.h" + +#ifndef max +#define max(x,y) ((x)>=(y)?(x):(y)) +#endif +#ifndef min +#define min(x,y) ((x)<=(y)?(x):(y)) +#endif + +#define DRAW_ARGS GtkStyle *style, \ + GdkWindow *window, \ + GtkStateType state_type, \ + GtkShadowType shadow_type, \ + GdkRectangle *area, \ + GtkWidget *widget, \ + const gchar *detail, \ + gint x, \ + gint y, \ + gint width, \ + gint height + +#define DRAW_VARS style, window, state_type, shadow_type, area, widget, detail, x, y, width, height + +static void olpc_style_init (OlpcStyle *style); +static void olpc_style_class_init (OlpcStyleClass *klass); + +static void +olpc_tab(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + gint orientation); + +static GtkStyleClass *olpc_parent_style_class = NULL; + +static void +olpc_style_draw_hline(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x1, + gint x2, + gint y) +{ + cairo_t *cr; + + CHECK_ARGS + + cr = ge_gdk_drawable_to_cairo (window, area); + + olpc_draw_separator(cr, TRUE, x1, y, x2-x1, 2); + cairo_destroy (cr); +} + +static void +olpc_style_draw_vline(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint y1, + gint y2, + gint x) +{ + cairo_t *cr; + + CHECK_ARGS + + if (ge_is_combo_box(widget, FALSE) && (!ge_is_combo_box_entry(widget))) + return; + + cr = ge_gdk_drawable_to_cairo (window, area); + + olpc_draw_separator(cr, FALSE, x, y1, 2, y2-y1); + + cairo_destroy (cr); +} + +static void +olpc_style_draw_shadow(GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1 = NULL; + CairoColor *color2 = NULL; + cairo_t *cr; + + CHECK_ARGS + + SANITIZE_SIZE + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + if (((x == 1) || (y == 1)) && (CHECK_DETAIL (detail, "entry") || CHECK_DETAIL (detail, "text"))) + { + color1 = color2 = &olpc_style->color_cube.base[state_type]; + break; + } + case GTK_SHADOW_ETCHED_IN: + color1 = &olpc_style->color_cube.light[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + break; + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + break; + } + + if (CHECK_DETAIL (detail, "entry")) + { + cr = ge_gdk_drawable_to_cairo (window, area); + + ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]); + cairo_rectangle(cr, x, y, width, height); + cairo_fill(cr); + + ge_cairo_set_color(cr, &olpc_style->color_cube.base[state_type]); + ge_cairo_rounded_rectangle (cr, x, y, width, height, 12, CR_CORNER_ALL); + cairo_fill(cr); + + cairo_destroy(cr); + + return; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + ge_cairo_set_color(cr, color1); + cairo_rectangle(cr, x + 1.5, y + 1.5, width - 3, height - 3); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color2); + cairo_rectangle(cr, x + 0.5, y + 0.5, width - 3, height - 3); + cairo_stroke(cr); + break; + + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + ge_cairo_simple_border (cr, color2, color1, x, y, width, height, FALSE); + break; + } + + cairo_destroy(cr); +} + +static void +olpc_style_draw_polygon(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const 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; + + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1 = NULL; + CairoColor *color2 = NULL; + CairoColor *color3 = NULL; + CairoColor *color4 = NULL; + cairo_t *cr; + + gdouble angle; + gint xadjust; + gint yadjust; + gint i; + + CHECK_ARGS + g_return_if_fail(points != NULL); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + color1 = &olpc_style->color_cube.light[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + color3 = &olpc_style->color_cube.light[state_type]; + color4 = &olpc_style->color_cube.dark[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + color1 = &olpc_style->color_cube.light[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + color3 = &olpc_style->color_cube.dark[state_type]; + color4 = &olpc_style->color_cube.light[state_type]; + break; + case GTK_SHADOW_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + color3 = &olpc_style->color_cube.dark[state_type]; + color4 = &olpc_style->color_cube.light[state_type]; + break; + case GTK_SHADOW_ETCHED_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + color3 = &olpc_style->color_cube.light[state_type]; + color4 = &olpc_style->color_cube.dark[state_type]; + break; + default: + return; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + + if (fill) + ge_cairo_polygon(cr, &olpc_style->color_cube.bg[state_type], 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; + } + + ge_cairo_line(cr, color1, + points[i].x - xadjust, points[i].y - yadjust, + points[i + 1].x - xadjust, points[i + 1].y - yadjust); + ge_cairo_line(cr, color3, + 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; + } + + ge_cairo_line(cr, color4, + points[i].x + xadjust, points[i].y + yadjust, + points[i + 1].x + xadjust, points[i + 1].y + yadjust); + ge_cairo_line(cr, color2, + points[i].x, points[i].y, + points[i + 1].x, points[i + 1].y); + } + } + + cairo_destroy(cr); +} + +static void +olpc_style_draw_arrow(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + GtkArrowType arrow_type, + gint fill, gint x, gint y, gint width, gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1, *color2, *color3=NULL,*color4=NULL; + gint half_width, half_height; + cairo_t *cr; + + CHECK_ARGS + + if (ge_is_combo_box(widget, FALSE) && (!ge_is_combo_box_entry(widget))) + return; + + SANITIZE_SIZE + + half_width = width / 2; + half_height = height / 2; + + switch (shadow_type) + { + case GTK_SHADOW_IN: + color1 = &olpc_style->color_cube.bg[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + color3 = &olpc_style->color_cube.light[state_type]; + color4 = &olpc_style->color_cube.black; + break; + + case GTK_SHADOW_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + color3 = &olpc_style->color_cube.black; + color4 = &olpc_style->color_cube.bg[state_type]; + break; + + case GTK_SHADOW_ETCHED_IN: + color2 = &olpc_style->color_cube.light[state_type]; + color1 = &olpc_style->color_cube.dark[state_type]; + break; + + case GTK_SHADOW_ETCHED_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + break; + + case GTK_SHADOW_NONE: + color1 = &olpc_style->color_cube.bg[state_type]; + color2 = &olpc_style->color_cube.bg[state_type]; + break; + + default: + return; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + + if (CHECK_DETAIL (detail, "vscrollbar") || CHECK_DETAIL (detail, "hscrollbar")) + { + switch (OLPC_RC_STYLE (style->rc_style)->mark_type2) + { + case MARKS_NOTHING: + break; + + case MARKS_INVSLASH: + olpc_slash_one(cr, color2, color1, x, y, width, height); + break; + + case MARKS_DOT: + olpc_dot(cr, color2, color1, x + half_width, y + half_height); + break; + + case MARKS_INVDOT: + olpc_dot(cr, color1, color2, x + half_width, y + half_height); + break; + + case MARKS_ARROW: + if (state_type == GTK_STATE_INSENSITIVE) + olpc_arrow (cr, &olpc_style->color_cube.white, arrow_type, TRUE, x+1, y+1, width, height); + olpc_arrow (cr, &olpc_style->color_cube.fg[state_type], arrow_type, TRUE, x, y, width, height); + break; + + case MARKS_SLASH: + default: + olpc_slash_one(cr, color1, color2, x, y, width - 1, height - 1); + break; + } + } + else + { + if (state_type == GTK_STATE_INSENSITIVE) + olpc_arrow (cr, &olpc_style->color_cube.white, arrow_type, TRUE, x+1, y+1, width, height); + olpc_arrow (cr, &olpc_style->color_cube.fg[state_type], arrow_type, TRUE, x, y, width, height); + } + + cairo_destroy(cr); +} + +static void +olpc_style_draw_diamond(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + gint half_width; + gint half_height; + cairo_t *cr; + + CHECK_ARGS + + SANITIZE_SIZE + + half_width = width / 2; + half_height = height / 2; + + cr = ge_gdk_drawable_to_cairo (window, area); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x, y + half_height, + x + half_width, y + height); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y + height, + x + width, y + half_height); + + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + 2, y + half_height, + x + half_width, y + 2); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y + 2, + x + width - 2, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x, y + half_height, + x + half_width, y); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y, + x + width, y + half_height); + break; + case GTK_SHADOW_OUT: + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x, y + half_height, + x + half_width, y + height); + ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type], + x + half_width, y + height, + x + width, y + half_height); + + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + 2, y + half_height, + x + half_width, y + 2); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y + 2, + x + width - 2, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x, y + half_height, + x + half_width, y); + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + half_width, y, + x + width, y + half_height); + break; + default: + break; + } + + cairo_destroy(cr); +} + +static void +olpc_style_draw_box(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + cairo_t *canvas; + gboolean draw_border = TRUE; + + /***********************************************/ + /* GTK Sanity Checks */ + /***********************************************/ + CHECK_ARGS + SANITIZE_SIZE + + + /***********************************************/ + /* GTK Special Cases - Ignored Widgets */ + /***********************************************/ + if ((CHECK_DETAIL(detail, "optionmenutab")) || + (CHECK_DETAIL (detail, "vscrollbar")) || + (CHECK_DETAIL (detail, "hscrollbar")) || + (CHECK_DETAIL (detail, "slider")) || + (CHECK_DETAIL (detail, "buttondefault")) || + (CHECK_DETAIL (detail, "bar") && + ((height < 1) && (width < 1)))) + { + return; + } + + + /***********************************************/ + /* GTK Special Cases - adjust Size/Offset */ + /***********************************************/ + if ((CHECK_DETAIL (detail, "bar"))) + { + x += 1; + y += 1; + width -= 2; + height -= 2; + + draw_border=FALSE; + } + else if (CHECK_DETAIL (detail, "handlebox_bin")) + { + draw_border=FALSE; + } + else if (CHECK_DETAIL (detail, "trough")) + { + draw_border = FALSE; + } + + + /***********************************************/ + /* Fill Box */ + /***********************************************/ + if ((!style->bg_pixmap[state_type]) || GDK_IS_PIXMAP(window)) + { + canvas = ge_gdk_drawable_to_cairo (window, area); + + ge_cairo_set_color(canvas, &olpc_style->color_cube.bg[state_type]); + + cairo_rectangle(canvas, x, y, width, height); + + cairo_fill(canvas); + + cairo_destroy(canvas); + } + else + { + gtk_style_apply_default_background(style, window, + widget && !GTK_WIDGET_NO_WINDOW(widget), + state_type, area, + x, y, width, height); + } + + /***********************************************/ + /* Draw Box Border */ + /***********************************************/ + if (draw_border) + { + olpc_style_draw_shadow(style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + } + + /***********************************************/ + /* Draw Widget Specific Sub-Parts */ + /***********************************************/ + if (CHECK_DETAIL (detail, "button")) + { + /* Paint a triangle here instead of in "buttondefault" + which is drawn _behind_ the current button */ + if (widget && GE_WIDGET_HAS_DEFAULT (widget)) + { + canvas = ge_gdk_drawable_to_cairo (window, area); + + ge_cairo_set_color(canvas, &olpc_style->color_cube.bg[GTK_STATE_SELECTED]); + cairo_move_to(canvas, x+2.5, y+2.5); + cairo_line_to(canvas, x+10.5, y+2.5); + cairo_line_to(canvas, x+2.5, y+10.5); + cairo_line_to(canvas, x+2.5, y+2.5); + cairo_fill(canvas); + + ge_cairo_set_color(canvas, &olpc_style->color_cube.dark[state_type]); + cairo_move_to(canvas, x + 2.5, y + 11); + cairo_line_to(canvas, x + 2.5, y + 2.5); + cairo_line_to(canvas, x + 11, y + 2.5); + cairo_stroke(canvas); + + cairo_set_line_width (canvas, 0.5); + ge_cairo_set_color(canvas, &olpc_style->color_cube.light[state_type]); + cairo_move_to(canvas, x+11, y+3); + cairo_line_to(canvas, x+3, y+11); + cairo_stroke(canvas); + + cairo_destroy(canvas); + } + } + + /* Draw Option Menus and Combo Box "Tab" The Same Way Here */ + if (CHECK_DETAIL(detail, "optionmenu") || (CHECK_DETAIL(detail, "button") && + (ge_is_combo_box(widget, FALSE)) && !(ge_is_combo_box_entry(widget)))) + { + GtkRequisition indicator_size; + GtkBorder indicator_spacing; + gint vline_x; + + if (state_type != GTK_STATE_INSENSITIVE) + state_type = GTK_STATE_NORMAL; + + ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing); + + if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)) + vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right; + else + vline_x = x + width - (indicator_size.width + indicator_spacing.left + + indicator_spacing.right) - style->xthickness; + + canvas = ge_gdk_drawable_to_cairo (window, area); + + olpc_draw_separator(canvas, FALSE, vline_x, y + style->ythickness + 1, style->xthickness, height - 2*style->ythickness - 2); + + cairo_destroy(canvas); + + if ((widget) && (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)) + x += indicator_spacing.right + style->xthickness; + else + x += width - indicator_size.width - indicator_spacing.right - style->xthickness; + + y += ((height - indicator_size.height) / 2) + 1; + + width = indicator_size.width; + height = indicator_size.height; + + olpc_style_draw_arrow (style, window, state_type, shadow_type, area, NULL, "optionmenu", + GTK_ARROW_DOWN, TRUE, x, y, width, height); + } +} + +static void +olpc_style_draw_check(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1 = NULL; + cairo_t *cr; + + CHECK_ARGS + SANITIZE_SIZE + + if (shadow_type == GTK_SHADOW_IN) + { + color1 = &olpc_style->color_cube.bg[GTK_STATE_ACTIVE]; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + + if (state_type == GTK_STATE_INSENSITIVE) + { + ge_cairo_set_color(cr, &olpc_style->color_cube.dark[state_type]); + + cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); + + cairo_stroke(cr); + } + else + { + olpc_style_draw_box(style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + if (color1) + { + ge_cairo_set_color(cr, color1); + + cairo_rectangle(cr, x+1, y+1, width-2, height-2); + + cairo_fill(cr); + } + } + + cairo_destroy(cr); +} + + +/* Thanks to Evan Lawrence */ +static void +olpc_style_draw_option(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1 = NULL, *color2 = NULL, *color3 = NULL; + cairo_t *cr; + + gint centerX; + gint centerY; + gint radius; + + CHECK_ARGS + SANITIZE_SIZE + + if (shadow_type == GTK_SHADOW_IN || + shadow_type == GTK_SHADOW_ETCHED_IN) + { + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + color3 = &olpc_style->color_cube.bg[GTK_STATE_ACTIVE]; + } + else + { + color1 = &olpc_style->color_cube.light[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + color3 = &olpc_style->color_cube.bg[state_type]; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + cairo_set_line_width (cr, 0.5); + + centerX = x + floor(width/2); + centerY = y + floor(height/2); + radius = floor(MIN(width, height)/2) - 0.5; + + switch (shadow_type) + { + case GTK_SHADOW_ETCHED_IN: + ge_cairo_set_color(cr, color2); + cairo_arc(cr, centerX + 1, centerY + 1, radius + 1, 0, 2 * M_PI); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color1); + cairo_arc(cr, centerX, centerY, radius + 1, 0, 2 * M_PI); + cairo_stroke(cr); + + break; + case GTK_SHADOW_ETCHED_OUT: + ge_cairo_set_color(cr, color1); + cairo_arc(cr, centerX - 1, centerY - 1, radius + 1, 0, 2 * M_PI); + cairo_stroke(cr); + + ge_cairo_set_color(cr, color2); + cairo_arc(cr, centerX, centerY, radius + 1, 0, 2 * M_PI); + cairo_stroke(cr); + + break; + default: + cairo_set_line_width (cr, 0.5); + + cairo_new_path (cr); + + cairo_move_to(cr, centerX + (radius + 2), centerY + (radius + 2)); + cairo_line_to(cr, centerX + (radius + 2)*sin(M_PI/4.0), centerY - (radius + 2)*cos(M_PI/4.0)); + cairo_line_to(cr, centerX - (radius + 2)*sin(M_PI/4.0), centerY + (radius + 2)*cos(M_PI/4.0)); + cairo_line_to(cr, centerX + (radius + 2), centerY + (radius + 2)); + + cairo_close_path (cr); + + cairo_save(cr); + cairo_clip (cr); + + ge_cairo_set_color(cr, color2); + cairo_arc(cr, centerX, centerY, radius + 1, 0, 2*M_PI); + cairo_fill(cr); + + cairo_restore(cr); + + cairo_new_path (cr); + + cairo_move_to(cr, centerX - (radius + 2), centerY - (radius + 2)); + cairo_line_to(cr, centerX + (radius + 2)*sin(M_PI/4.0), centerY - (radius + 2)*cos(M_PI/4.0)); + cairo_line_to(cr, centerX - (radius + 2)*sin(M_PI/4.0), centerY + (radius + 2)*cos(M_PI/4.0)); + cairo_line_to(cr, centerX - (radius + 2), centerY - (radius + 2)); + + cairo_close_path (cr); + + cairo_save(cr); + + cairo_clip (cr); + + ge_cairo_set_color(cr, color1); + cairo_arc(cr, centerX, centerY, radius + 1, 0, 2*M_PI); + cairo_fill(cr); + + cairo_restore(cr); + + ge_cairo_set_color(cr, color3); + cairo_arc(cr, centerX, centerY, radius, 0, 2 * M_PI); + cairo_fill(cr); + + break; + } + + cairo_destroy(cr); +} + +static void +olpc_style_draw_shadow_gap(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *color1 = NULL, *color2 = NULL; + cairo_t *cr; + + CHECK_ARGS + SANITIZE_SIZE + + shadow_type = olpc_shadow_type (style, detail, shadow_type); + + switch (shadow_type) { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.light[state_type]; + break; + case GTK_SHADOW_OUT: + color1 = &olpc_style->color_cube.light[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + color1 = &olpc_style->color_cube.dark[state_type]; + color2 = &olpc_style->color_cube.dark[state_type]; + } + + cr = ge_gdk_drawable_to_cairo (window, area); + + switch (gap_side) { + case GTK_POS_TOP: + if (gap_x > 0) { + ge_cairo_line (cr, color1, + x, y, + x + gap_x, y); + } + if ((width - (gap_x + gap_width)) > 0) { + ge_cairo_line (cr, color1, + x + gap_x + gap_width - 1, y, + x + width - 1, y); + } + ge_cairo_line (cr, color1, + x, y, + x, y + height - 1); + ge_cairo_line (cr, color2, + x + width - 1, y, + x + width - 1, y + height - 1); + ge_cairo_line (cr, color2, + x, y + height - 1, + x + width - 1, y + height - 1); + break; + case GTK_POS_BOTTOM: + ge_cairo_line (cr, color1, + x, y, + x + width - 1, y); + ge_cairo_line (cr, color1, + x, y, + x, y + height - 1); + ge_cairo_line (cr, color2, + x + width - 1, y, + x + width - 1, y + height - 1); + + if (gap_x > 0) { + ge_cairo_line (cr, color2, + x, y + height - 1, + x + gap_x, y + height - 1); + } + if ((width - (gap_x + gap_width)) > 0) { + ge_cairo_line (cr, color2, + x + gap_x + gap_width - 1, y + height - 1, + x + width - 1, y + height - 1); + } + + break; + case GTK_POS_LEFT: + ge_cairo_line (cr, color1, + x, y, + x + width - 1, y); + if (gap_x > 0) { + ge_cairo_line (cr, color1, + x, y, + x, y + gap_x); + } + if ((height - (gap_x + gap_width)) > 0) { + ge_cairo_line (cr, color1, + x, y + gap_x + gap_width - 1, + x, y + height - 1); + } + + ge_cairo_line (cr, color2, + x + width - 1, y, + x + width - 1, y + height - 1); + ge_cairo_line (cr, color2, + x, y + height - 1, + x + width - 1, y + height - 1); + break; + case GTK_POS_RIGHT: + ge_cairo_line (cr, color1, + x, y, + x + width - 1, y); + ge_cairo_line (cr, color1, + x, y, + x, y + height - 1); + + + if (gap_x > 0) { + ge_cairo_line (cr, color2, + x + width - 1, y, + x + width - 1, y + gap_x); + } + if ((height - (gap_x + gap_width)) > 0) { + ge_cairo_line (cr, color2, + x + width - 1, y + gap_x + gap_width - 1, + x + width - 1, y + height - 1); + } + + ge_cairo_line (cr, color2, + x, y + height - 1, + x + width - 1, y + height - 1); + + } + + cairo_destroy(cr); +} + + +static void +olpc_style_draw_box_gap(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + SANITIZE_SIZE + + gtk_style_apply_default_background(style, window, + widget && !GTK_WIDGET_NO_WINDOW(widget), + state_type, area, + x, y, width, height); + olpc_style_draw_shadow_gap (style, window, state_type, shadow_type, + area, widget, detail, x, y, width, height, + gap_side, gap_x, gap_width); +} + + +static void +olpc_style_draw_extension(DRAW_ARGS, GtkPositionType gap_side) +{ + switch (gap_side) + { + case GTK_POS_TOP: gap_side = GTK_POS_BOTTOM; break; + case GTK_POS_BOTTOM: gap_side = GTK_POS_TOP; break; + case GTK_POS_LEFT: gap_side = GTK_POS_RIGHT; break; + case GTK_POS_RIGHT: gap_side = GTK_POS_LEFT; break; + } + + olpc_tab(DRAW_VARS, gap_side); +} + +static void +olpc_style_draw_slider(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + GdkPoint pointsh[7]; + gint midlines = MARKS_SLASH; + gint modx, mody; + cairo_t *cr; + + CHECK_ARGS + + SANITIZE_SIZE + +#ifdef DEBUG + printf("draw_slider(%s, %d, %d, %d)\n", detail, x, y, orientation); +#endif + +#ifdef DEBUG + printf("Slider... x,y=%d,%d width = %d, height = %d (%d)\n",x,y,width,height, state_type); +#endif + midlines = OLPC_RC_STYLE (style->rc_style)->mark_type1; +#ifdef DEBUG + printf("Midlines = %d\n", midlines); +#endif + + pointsh[0].x = x; pointsh[0].y = y; + pointsh[1].x = x + width - 1; pointsh[1].y = y; + pointsh[2].x = x + width - 1; pointsh[2].y = y + height - 1; + pointsh[3].x = x; pointsh[3].y = y + height - 1; + pointsh[4].x = x; pointsh[4].y = y; + + cr = ge_gdk_drawable_to_cairo (window, area); + + ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]); + + ge_cairo_rounded_rectangle(cr, x + 3, y + 3, width - 6, height - 6, 2, CR_CORNER_ALL); + + cairo_fill(cr); + + //olpc_style_draw_shadow(style, window, state_type, shadow_type, area, + // widget, detail, x, y, width, height); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { modx = 4; mody = 0; } + else + { modx = 0; mody = 4; } + + switch (midlines) + { + case MARKS_NOTHING: + break; + case MARKS_INVSLASH: /* Inverse //:es */ + olpc_slash_two(cr, + &olpc_style->color_cube.dark[state_type], + &olpc_style->color_cube.light[state_type], + x, y, width, height); + break; + case MARKS_DOT: + olpc_dot(cr, + &olpc_style->color_cube.light[state_type], + &olpc_style->color_cube.dark[state_type], + x + width / 2 - modx, + y + height / 2 - mody); + olpc_dot(cr, + &olpc_style->color_cube.light[state_type], + &olpc_style->color_cube.dark[state_type], + x + width / 2, + y + height / 2); + olpc_dot(cr, + &olpc_style->color_cube.light[state_type], + &olpc_style->color_cube.dark[state_type], + x + width / 2 + modx, + y + height / 2 + mody); + break; + case MARKS_INVDOT: /* Inverted */ + olpc_dot(cr, + &olpc_style->color_cube.dark[state_type], + &olpc_style->color_cube.light[state_type], + x + width / 2 - modx, + y + height / 2 - mody); + olpc_dot(cr, + &olpc_style->color_cube.dark[state_type], + &olpc_style->color_cube.light[state_type], + x + width / 2, + y + height / 2); + olpc_dot(cr, + &olpc_style->color_cube.dark[state_type], + &olpc_style->color_cube.light[state_type], + x + width / 2 + modx, + y + height / 2 + mody); + break; + case MARKS_SLASH: + default: + olpc_slash_two(cr, + &olpc_style->color_cube.light[state_type], + &olpc_style->color_cube.dark[state_type], + x, y, width, height); + break; + } + + cairo_destroy(cr); + +} + +static void +olpc_style_draw_handle(GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle * area, + GtkWidget * widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + cairo_t *cr; + CairoColor *light=NULL, *dark=NULL; + GdkRectangle dest; + gint modx, mody; + + CHECK_ARGS + +#ifdef DEBUG + printf("draw_handle(state=%d, shadow=%d, detail=%s, [%d,%d]@[%d,%d]\n", + state_type, shadow_type, detail?detail:"nul",width,height,x,y); +#endif + SANITIZE_SIZE + + cr = ge_gdk_drawable_to_cairo (window, area); + + if (CHECK_DETAIL (detail, "paned")) + { + int i, w; + int start_i, end_i; + + dest.x = x; + dest.y = y; + dest.width = width; + dest.height = height; + + light = &olpc_style->color_cube.light[state_type]; + dark = &olpc_style->color_cube.dark[state_type]; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + w = width; + else + w = height; + switch (OLPC_RC_STYLE (style->rc_style)->paned_dots) { + default: + case PANED_DOTSFULL: + start_i = 5; + end_i = w - 5; + break; + case PANED_DOTSSOME: + start_i = w/2 - 16; + end_i = w/2 + 16; + break; + case PANED_DOTSNONE: + start_i = w; + end_i = 0; + break; + } + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + for (i=x + start_i; i <= x + end_i; i+=8) + { + olpc_dot(cr, light, dark, i, y + height / 2); + } + } + else + { + for (i=y + start_i; i <= y + end_i; i+=8) + { + olpc_dot(cr, light, dark, x + width / 2, i); + } + } + + cairo_destroy(cr); + + return; + } + + olpc_style_draw_box(style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + ge_cairo_line(cr, &olpc_style->color_cube.light[state_type], + x + width, y, x + width, y + height - 2); + + /* Draw something in the box if so wanted */ + if (OLPC_RC_STYLE (style->rc_style)->mark_type1 != MARKS_NOTHING) + { + light = &olpc_style->color_cube.light[state_type]; + dark = &olpc_style->color_cube.dark[state_type]; + + orientation = GTK_ORIENTATION_HORIZONTAL; + if (height > width) + orientation = GTK_ORIENTATION_VERTICAL; + + dest.x = x + style->xthickness; + dest.y = y + style->ythickness; + dest.width = width - (style->xthickness * 2); + dest.height = height - (style->ythickness * 2); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { modx = 4; mody = 0; } + else + { modx = 0; mody = 4; } + + switch (OLPC_RC_STYLE (style->rc_style)->mark_type1) + { + case MARKS_INVSLASH: /* Inverse //:es */ + olpc_slash_two(cr, dark, light, + x, y, width, height); + break; + case MARKS_DOT: /* Dots */ + olpc_dot(cr, light, dark, + x + width / 2 - modx, + y + height / 2 - mody); + olpc_dot(cr, light, dark, + x + width / 2, + y + height / 2); + olpc_dot(cr, light, dark, + x + width / 2 + modx, + y + height / 2 + mody); + break; + case MARKS_INVDOT: /* Inverted dots */ + olpc_dot(cr, dark, light, + x + width / 2 - modx, + y + height / 2 - mody); + olpc_dot(cr, dark, light, + x + width / 2, + y + height / 2); + olpc_dot(cr, dark, light, + x + width / 2 + modx, + y + height / 2 + mody); + break; + case MARKS_SLASH: + default: + olpc_slash_two(cr, light, dark, + x, y, width, height); + break; + } + } + + cairo_destroy(cr); +} + +static void +olpc_tab(DRAW_ARGS, gint orientation) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + CairoColor *light, *dark; + cairo_t *cr; + + CHECK_ARGS + + SANITIZE_SIZE + + light = &olpc_style->color_cube.light[state_type]; + dark = &olpc_style->color_cube.dark[state_type]; + + cr = ge_gdk_drawable_to_cairo (window, area); + + if ((!style->bg_pixmap[state_type]) || GDK_IS_PIXMAP(window)) + { + ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]); + + cairo_rectangle(cr, x, y, width - 1, height - 1); + + cairo_fill(cr); + } + else + { + gtk_style_apply_default_background(style, window, + widget && !GTK_WIDGET_NO_WINDOW(widget), + state_type, area, x, y, width, height); + } + + switch(orientation) + { + case GTK_POS_TOP: + ge_cairo_line(cr, light, + x, y + height, x, y); + ge_cairo_line(cr, light, + x, y, x + width - 2, y); + ge_cairo_line(cr, dark, + x + width - 2, y, x + width - 2, y + height - 1); + break; + case GTK_POS_BOTTOM: + ge_cairo_line(cr, light, + x, y - 1, x, y + height - 1); + ge_cairo_line(cr, dark, + x, y + height - 1, x + width - 2, y + height - 1); + ge_cairo_line(cr, dark, + x + width - 2, y + height - 1, x + width - 2, y); + break; + case GTK_POS_LEFT: + ge_cairo_line(cr, light, + x, y + height - 1, x, y); + ge_cairo_line(cr, light, + x, y, x + width, y); + ge_cairo_line(cr, dark, + x, y + height - 1, x + width - 1, y + height - 1); + break; + case GTK_POS_RIGHT: + ge_cairo_line(cr, light, + x - 1, y, x + width - 1, y); + ge_cairo_line(cr, dark, + x + width - 1, y, x + width - 1, y + height - 1); + ge_cairo_line(cr, dark, + x, y + height - 1, x + width - 1, y + height - 1); + break; + } + + cairo_destroy(cr); +} + +GType olpc_type_style = 0; + +void +olpc_style_register_type (GTypeModule *module) +{ + static const GTypeInfo object_info = + { + sizeof (OlpcStyleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) olpc_style_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (OlpcStyle), + 0, /* n_preallocs */ + (GInstanceInitFunc) olpc_style_init, + }; + + olpc_type_style = g_type_module_register_type (module, + GTK_TYPE_STYLE, + "OlpcStyle", + &object_info, 0); +} + +static void +olpc_style_init (OlpcStyle *style) +{ +} + +static void +olpc_style_realize (GtkStyle * style) +{ + OlpcStyle *olpc_style = OLPC_STYLE (style); + + olpc_parent_style_class->realize (style); + + ge_gtk_style_to_cairo_color_cube (style, &olpc_style->color_cube); +} + +static void +olpc_style_class_init (OlpcStyleClass *klass) +{ + GtkStyleClass *style_class = GTK_STYLE_CLASS (klass); + + olpc_parent_style_class = g_type_class_peek_parent (klass); + + style_class->realize = olpc_style_realize; + + style_class->draw_hline = olpc_style_draw_hline; + style_class->draw_vline = olpc_style_draw_vline; + style_class->draw_shadow = olpc_style_draw_shadow; + style_class->draw_polygon = olpc_style_draw_polygon; + style_class->draw_arrow = olpc_style_draw_arrow; + style_class->draw_diamond = olpc_style_draw_diamond; + style_class->draw_box = olpc_style_draw_box; + style_class->draw_tab = olpc_style_draw_box; + + style_class->draw_check = olpc_style_draw_check; + style_class->draw_option = olpc_style_draw_option; + style_class->draw_shadow_gap = olpc_style_draw_shadow_gap; + style_class->draw_box_gap = olpc_style_draw_box_gap; + style_class->draw_extension = olpc_style_draw_extension; + style_class->draw_slider = olpc_style_draw_slider; + style_class->draw_handle = olpc_style_draw_handle; +} + + +/* +FIXME: file/font selector background OK +FIXME: radioknappar varierar storlek rätt bra.. OK +FIXME: scrollbars OK +FIXME: inconsistent-radioknappar OK +FIXME: paned-pluttarna OK +FIXME: spinbuttons, vid max OK + +FIXME: Blå triangeln vid RTL, WONTFIX? +*/ + diff --git a/gtk-engine/src/widget-information.c b/gtk-engine/src/widget-information.c new file mode 100644 index 0000000..55d260f --- /dev/null +++ b/gtk-engine/src/widget-information.c @@ -0,0 +1,331 @@ +#include <gtk/gtk.h> + +#include "general-support.h" +#include "widget-information.h" +#include <math.h> +#include <string.h> + +/* Widget Type Lookups/Macros + + Based on/modified from functions in + Smooth-Engine. +*/ +gboolean +ge_object_is_a (const GObject * object, const gchar * type_name) +{ + gboolean result = FALSE; + + if ((object)) + { + GType tmp = g_type_from_name (type_name); + + if (tmp) + result = g_type_check_instance_is_a ((GTypeInstance *) object, tmp); + } + + return result; +} + +gboolean +ge_is_combo_box_entry (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget) && (widget->parent)) + { + if (GE_IS_COMBO_BOX_ENTRY (widget->parent)) + result = TRUE; + else + result = ge_is_combo_box_entry (widget->parent); + } + return result; +} + +gboolean +ge_combo_box_is_using_list (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget) && (GE_IS_COMBO_BOX (widget->parent))) + { + gboolean *tmp = NULL; + + gtk_widget_style_get (widget->parent, "appears-as-list", &result, NULL); + + if (tmp) + result = *tmp; + } + + return result; +} + +gboolean +ge_is_combo_box (GtkWidget * widget, gboolean as_list) +{ + gboolean result = FALSE; + + if ((widget) && (widget->parent)) + { + if (GE_IS_COMBO_BOX (widget->parent)) + { + if (as_list) + result = (ge_combo_box_is_using_list(widget->parent)); + else + result = (!ge_combo_box_is_using_list(widget->parent)); + } + else + result = ge_is_combo_box (widget->parent, as_list); + } + return result; +} + +gboolean +ge_is_combo (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget) && (widget->parent)) + { + if (GE_IS_COMBO (widget->parent)) + result = TRUE; + else + result = ge_is_combo (widget->parent); + } + return result; +} + +gboolean +ge_is_in_combo_box (GtkWidget * widget) +{ + return ((ge_is_combo (widget) || ge_is_combo_box (widget, TRUE) || ge_is_combo_box_entry (widget))); +} + +gboolean +ge_is_toolbar_item (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget) && (widget->parent)) { + if ((GE_IS_BONOBO_TOOLBAR (widget->parent)) + || (GE_IS_BONOBO_DOCK_ITEM (widget->parent)) + || (GE_IS_EGG_TOOLBAR (widget->parent)) + || (GE_IS_TOOLBAR (widget->parent)) + || (GE_IS_HANDLE_BOX (widget->parent))) + result = TRUE; + else + result = ge_is_toolbar_item (widget->parent); + } + return result; +} + +gboolean +ge_is_panel_widget_item (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget) && (widget->parent)) + { + if (GE_IS_PANEL_WIDGET (widget->parent)) + result = TRUE; + else + result = ge_is_panel_widget_item (widget->parent); + } + return result; +} + +gboolean +ge_is_bonobo_dock_item (GtkWidget * widget) +{ + gboolean result = FALSE; + + if ((widget)) + { + if (GE_IS_BONOBO_DOCK_ITEM(widget) || GE_IS_BONOBO_DOCK_ITEM (widget->parent)) + result = TRUE; + else if (GE_IS_BOX(widget) || GE_IS_BOX(widget->parent)) + { + GtkContainer *box = GE_IS_BOX(widget)?GTK_CONTAINER(widget):GTK_CONTAINER(widget->parent); + GList *children = NULL, *child = NULL; + + children = gtk_container_get_children(box); + + for (child = g_list_first(children); child; child = g_list_next(child)) + { + if (GE_IS_BONOBO_DOCK_ITEM_GRIP(child->data)) + { + result = TRUE; + child = NULL; + } + } + + if (children) + g_list_free(children); + } + } + return result; +} + +static GtkWidget * +ge_find_combo_box_entry_widget (GtkWidget * widget) +{ + GtkWidget *result = NULL; + + if (widget) + { + if (GE_IS_COMBO_BOX_ENTRY (widget)) + result = widget; + else + result = ge_find_combo_box_entry_widget (widget->parent); + } + + return result; +} + +static GtkWidget * +ge_find_combo_box_widget (GtkWidget * widget, gboolean as_list) +{ + GtkWidget *result = NULL; + + if (widget) + { + if (GE_IS_COMBO_BOX (widget)) + { + if (as_list) + result = (ge_combo_box_is_using_list(widget))?widget:NULL; + else + result = (!ge_combo_box_is_using_list(widget))?widget:NULL; + } + else + result = ge_find_combo_box_widget (widget->parent, as_list); + } + return result; +} + +static GtkWidget * +ge_find_combo_widget (GtkWidget * widget) +{ + GtkWidget *result = NULL; + + if (widget) + { + if (GE_IS_COMBO (widget)) + result = widget; + else + result = ge_find_combo_widget(widget->parent); + } + return result; +} + +GtkWidget* +ge_find_combo_box_widget_parent (GtkWidget * widget) +{ + GtkWidget *result = NULL; + + if (!result) + result = ge_find_combo_widget(widget); + + if (!result) + result = ge_find_combo_box_widget(widget, TRUE); + + if (!result) + result = ge_find_combo_box_entry_widget(widget); + + return result; +} + +gboolean +ge_cell_renderer_toggle_get_inconsistent (GtkWidget * widget) +{ + gboolean result = FALSE; + + g_object_get (widget, "inconsistent", &result, NULL); + + return result; +} + +gboolean +ge_toggle_get_inconsistent (GtkWidget * widget, const gchar *detail, GtkShadowType shadow_type) +{ + return (GE_IS_TOGGLE_BUTTON(widget) && gtk_toggle_button_get_inconsistent(TOGGLE_BUTTON(widget))) + | (GE_IS_CELL_RENDERER_TOGGLE(widget) && ge_cell_renderer_toggle_get_inconsistent (widget)) + | (CHECK_DETAIL(detail, "cellcheck") && (shadow_type == GTK_SHADOW_ETCHED_IN)) + | (CHECK_DETAIL(detail, "cellradio") && (shadow_type == GTK_SHADOW_ETCHED_IN)); +} + +/*********************************************** + * option_menu_get_props - + * + * Find Option Menu Size and Spacing + * + * Taken from Smooth + ***********************************************/ +void +ge_option_menu_get_props (GtkWidget * widget, + GtkRequisition * indicator_size, + GtkBorder * indicator_spacing) +{ + GtkRequisition default_size = { 9, 5 }; + GtkBorder default_spacing = { 7, 5, 2, 2 }; + GtkRequisition *tmp_size = NULL; + GtkBorder *tmp_spacing = NULL; + + if ((widget) && GE_IS_OPTION_MENU(widget)) + gtk_widget_style_get (widget, + "indicator_size", &tmp_size, + "indicator_spacing", &tmp_spacing, NULL); + + if (tmp_size) + { + *indicator_size = *tmp_size; + g_free (tmp_size); + } + else + *indicator_size = default_size; + + if (tmp_spacing) + { + *indicator_spacing = *tmp_spacing; + g_free (tmp_spacing); + } + else + *indicator_spacing = default_spacing; +} + +void +ge_button_get_default_border (GtkWidget *widget, + GtkBorder *border) +{ + GtkBorder default_border = {1, 1, 1, 1}; + GtkBorder *tmp_border = NULL; + + if (widget && GE_IS_BUTTON (widget)) + gtk_widget_style_get (widget, "default-border", &tmp_border, NULL); + + if (tmp_border) + { + *border = *tmp_border; + g_free (tmp_border); + } + else + { + *border = default_border; + } +} + + +gboolean +ge_widget_is_ltr (GtkWidget *widget) +{ + GtkTextDirection dir = GTK_TEXT_DIR_NONE; + + if (GE_IS_WIDGET (widget)) + dir = gtk_widget_get_direction (widget); + + if (dir == GTK_TEXT_DIR_NONE) + dir = gtk_widget_get_default_direction (); + + if (dir == GTK_TEXT_DIR_RTL) + return FALSE; + else + return TRUE; +} diff --git a/gtk-engine/src/widget-information.h b/gtk-engine/src/widget-information.h new file mode 100644 index 0000000..db1d449 --- /dev/null +++ b/gtk-engine/src/widget-information.h @@ -0,0 +1,104 @@ + +/* Object Type Lookups/Macros + + Based on/modified from functions in + Smooth-Engine. +*/ +#define GE_IS_WIDGET(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkWidget")) +#define GE_IS_CONTAINER(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkContainer")) +#define GE_IS_BIN(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkBin")) + +#define GE_IS_ARROW(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkArrow")) + +#define GE_IS_SEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkSeparator")) +#define GE_IS_VSEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVSeparator")) +#define GE_IS_HSEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHSeparator")) + +#define GE_IS_HANDLE_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHandleBox")) +#define GE_IS_HANDLE_BOX_ITEM(object) ((object) && GE_IS_HANDLE_BOX(object->parent)) +#define GE_IS_BONOBO_DOCK_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboDockItem")) +#define GE_IS_BONOBO_DOCK_ITEM_GRIP(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboDockItemGrip")) +#define GE_IS_BONOBO_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboUIToolbar")) +#define GE_IS_EGG_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "Toolbar")) +#define GE_IS_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkToolbar")) +#define GE_IS_PANEL_WIDGET(object) ((object) && (ge_object_is_a ((GObject*)(object), "PanelWidget") || ge_object_is_a ((GObject*)(object), "PanelApplet"))) + +#define GE_IS_COMBO_BOX_ENTRY(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkComboBoxEntry")) +#define GE_IS_COMBO_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkComboBox")) +#define GE_IS_COMBO(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCombo")) +#define GE_IS_OPTION_MENU(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkOptionMenu")) + +#define GE_IS_TOGGLE_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkToggleButton")) +#define GE_IS_CHECK_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCheckButton")) +#define GE_IS_SPIN_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkSpinButton")) + +#define GE_IS_STATUSBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkStatusbar")) +#define GE_IS_PROGRESS_BAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkProgressBar")) + +#define GE_IS_MENU_SHELL(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuShell")) +#define GE_IS_MENU(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenu")) +#define GE_IS_MENU_BAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuBar")) +#define GE_IS_MENU_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuItem")) + +#define GE_IS_CHECK_MENU_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCheckMenuItem")) + +#define GE_IS_RANGE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkRange")) + +#define GE_IS_SCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkScrollbar")) +#define GE_IS_VSCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVScrollbar")) +#define GE_IS_HSCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHScrollbar")) + +#define GE_IS_SCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkScale")) +#define GE_IS_VSCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVScale")) +#define GE_IS_HSCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHScale")) + +#define GE_IS_PANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkPaned")) +#define GE_IS_VPANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVPaned")) +#define GE_IS_HPANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHPaned")) + +#define GE_IS_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkBox")) +#define GE_IS_VBOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVBox")) +#define GE_IS_HBOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHBox")) + +#define GE_IS_CLIST(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCList")) +#define GE_IS_TREE_VIEW(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkTreeView")) +#define GE_IS_ENTRY(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkEntry")) +#define GE_IS_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkButton")) +#define GE_IS_FIXED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkFixed")) + +#define TOGGLE_BUTTON(object) (GE_IS_TOGGLE_BUTTON(object)?(GtkToggleButton *)object:NULL) + +#define GE_IS_NOTEBOOK(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkNotebook")) +#define GE_IS_CELL_RENDERER_TOGGLE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCellRendererToggle")) + +#define GE_WIDGET_HAS_DEFAULT(object) ((object) && GE_IS_WIDGET(object) && GTK_WIDGET_HAS_DEFAULT(object)) + +GE_INTERNAL gboolean ge_object_is_a (const GObject * object, const gchar * type_name); + +GE_INTERNAL gboolean ge_combo_box_is_using_list (GtkWidget * widget); + +GE_INTERNAL gboolean ge_is_combo_box_entry (GtkWidget * widget); +GE_INTERNAL gboolean ge_is_combo_box (GtkWidget * widget, gboolean as_list); +GE_INTERNAL gboolean ge_is_combo (GtkWidget * widget); +GE_INTERNAL gboolean ge_is_in_combo_box (GtkWidget * widget); + +GE_INTERNAL gboolean ge_is_toolbar_item (GtkWidget * widget); + +GE_INTERNAL gboolean ge_is_panel_widget_item (GtkWidget * widget); + +GE_INTERNAL gboolean ge_is_bonobo_dock_item (GtkWidget * widget); + +GE_INTERNAL GtkWidget *ge_find_combo_box_widget_parent (GtkWidget * widget); + +GE_INTERNAL gboolean ge_cell_renderer_toggle_get_inconsistent (GtkWidget * widget); +GE_INTERNAL gboolean ge_toggle_get_inconsistent (GtkWidget * widget, const gchar *detail, GtkShadowType shadow_type); + +GE_INTERNAL void ge_option_menu_get_props (GtkWidget * widget, + GtkRequisition * indicator_size, + GtkBorder * indicator_spacing); + +GE_INTERNAL void ge_button_get_default_border (GtkWidget *widget, + GtkBorder *border); + +GE_INTERNAL gboolean ge_widget_is_ltr (GtkWidget *widget); + diff --git a/gtk-engine/theme/Makefile.am b/gtk-engine/theme/Makefile.am new file mode 100644 index 0000000..1da5d18 --- /dev/null +++ b/gtk-engine/theme/Makefile.am @@ -0,0 +1,5 @@ +themedir = $(datadir)/themes/olpc/gtk-2.0 +theme_DATA = gtkrc + +EXTRA_DIST = \ + $(theme_DATA) diff --git a/gtk-engine/theme/gtkrc b/gtk-engine/theme/gtkrc new file mode 100644 index 0000000..5cac2ec --- /dev/null +++ b/gtk-engine/theme/gtkrc @@ -0,0 +1,102 @@ +style "default" +{ + GtkOptionMenu::indicator_spacing = { 3, 2, 1, 1 } + GtkCheckButton::indicator_size = 10 + GtkCheckMenuItem::indicator_size = 10 + GtkButton::default_border = { 0, 0, 0, 0 } + + fg[NORMAL] = "#000000" + fg[ACTIVE] = "#000000" + fg[PRELIGHT] = "#000000" + fg[SELECTED] = "#FFFFFF" + fg[INSENSITIVE] = "#747474" + bg[NORMAL] = "#D3D3DD" + bg[ACTIVE] = "#C1C1CC" + bg[PRELIGHT] = "#E5E5F7" + bg[SELECTED] = "#336699" + bg[INSENSITIVE] = "#D3D3DD" + base[NORMAL] = "#E5E5F7" + base[ACTIVE] = "#808080" + base[PRELIGHT] = "#E5E5F7" + base[SELECTED] = "#336699" + base[INSENSITIVE] = "#E5E5F7" + text[NORMAL] = "#000000" + text[ACTIVE] = "#FFFFFF" + text[PRELIGHT] = "#000000" + text[SELECTED] = "#FFFFFF" + text[INSENSITIVE] = "#747474" + + engine "olpc" + { + mark_type1 = NOTHING + mark_type2 = NOTHING + } +} + +style "scrollbar" = "default" +{ + GtkRange::slider_width = 12 + GtkRange::stepper_size = 1 + GtkRange::trough-border = 0 + + bg[ACTIVE] = "#E6E6E6" + bg[NORMAL] = "#414141" + bg[PRELIGHT] = "#414141" +} + +style "dark-default" = "default" +{ + fg[NORMAL] = "#FFFFFF" + fg[ACTIVE] = "#FFFFFF" + fg[PRELIGHT] = "#FFFFFF" + fg[SELECTED] = "#FFFFFF" + fg[INSENSITIVE] = "#FFFFFF" + bg[NORMAL] = "#414141" + bg[ACTIVE] = "#000000" + bg[PRELIGHT] = "#000000" + bg[SELECTED] = "#414141" + bg[INSENSITIVE] = "#D3D3DD" + base[NORMAL] = "#646464" + base[ACTIVE] = "#808080" + base[PRELIGHT] = "#E5E5F7" + base[SELECTED] = "#336699" + base[INSENSITIVE] = "#E5E5F7" + text[NORMAL] = "#FFFFFF" + text[ACTIVE] = "#FFFFFF" + text[PRELIGHT] = "#000000" + text[SELECTED] = "#FFFFFF" + text[INSENSITIVE] = "#747474" +} + +style "toolbar" = "dark-default" +{ + GtkToolbar::internal_padding = 0 + GtkToolbar::shadow_type = 0 +} + +style "toolbar-button" = "dark-default" +{ + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outsideborder = { 0, 0, 0, 0 } + GtkButton::inner_border = { 0, 0, 0, 0 } + GtkButton::focus_line_width = 0 + GtkButton::focus_padding = 0 + xthickness = 0 + ythickness = 0 +} + +style "toolbar-entry" = "dark-default" +{ + GtkWidget::cursor_color = "#FFFFFF" + xthickness = 12 + ythickness = 3 + font_name = 'Sans 14' +} + +class "GtkWidget" style "default" +class "GtkScrollbar" style "scrollbar" +class "GtkToolbar" style "toolbar" +class "GtkSocket" style "dark-default" + +widget_class "*.GtkToolbar.*.<GtkButton>" style "toolbar-button" +widget_class "*.GtkToolbar.*.<GtkEntry>" style "toolbar-entry" diff --git a/gtkrc2-default b/gtkrc2-default index b517c0f..7397047 100644 --- a/gtkrc2-default +++ b/gtkrc2-default @@ -1,3 +1,4 @@ +gtk-theme-name = "olpc" gtk-icon-theme-name = "olpc" gtk-cursor-theme-name = "olpc" gtk-cursor-theme-size = 48 diff --git a/setup-user-theme.py b/setup-user-theme.py new file mode 100755 index 0000000..bc5bfe7 --- /dev/null +++ b/setup-user-theme.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +# FIXME Need to handle the case when symlinks already exists + +import os + +theme_dir = os.path.expanduser('~/.themes/olpc/gtk-2.0') +gtkrc_dest = os.path.join(theme_dir, 'gtkrc') + +engine_dir = os.path.expanduser('~/.gtk-2.0/engines') +engine_dest = os.path.join(engine_dir, 'libolpc.so') + +src_dir = os.path.abspath(os.path.dirname(__file__)) + +if not os.path.exists(theme_dir): + try: + os.makedirs(theme_dir) + except OSError, exc: + if exc[0] == 17: # File exists + pass +try: + os.unlink(gtkrc_dest) +except OSError, exc: + pass +os.symlink(os.path.join(src_dir, 'gtk-engine/theme/gtkrc'), gtkrc_dest) + +if not os.path.exists(engine_dest): + try: + os.makedirs(engine_dir) + except OSError, exc: + if exc[0] == 17: # File exists + pass +engine_src = os.path.join(src_dir, 'gtk-engine/src/.libs/libolpc.so') +try: + os.unlink(engine_dest) +except OSError, exc: + pass +os.symlink(engine_src, engine_dest) diff --git a/test/gtk-engine-test.py b/test/gtk-engine-test.py new file mode 100755 index 0000000..4487002 --- /dev/null +++ b/test/gtk-engine-test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +import pygtk +pygtk.require('2.0') +import gtk + +class Base: + def __init__(self): + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + window.set_default_size(300, 200) + + vbox = gtk.VBox(False, 12) + vbox.set_border_width(12) + + hbox = gtk.HBox(False, 12) + + button = gtk.Button("Button") + hbox.pack_start(button, False) + button.show() + + entry = gtk.Entry() + hbox.pack_start(entry, False) + entry.show() + + vbox.pack_start(hbox, False) + hbox.show() + + + sw = gtk.ScrolledWindow() + sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) + sw.set_size_request(150, 120) + + text_view = gtk.TextView() + sw.add(text_view) + text_view.show() + + vbox.pack_start(sw, False) + sw.show() + + window.add(vbox) + vbox.show() + + window.show() + + def main(self): + gtk.main() + +settings = gtk.settings_get_default() + +if settings.get_property('gtk-theme-name') != 'olpc': + settings.set_string_property('gtk-theme-name', 'olpc', '') + +base = Base() +base.main() |