diff options
author | David Robillard <d@drobilla.net> | 2008-02-03 20:33:49 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-02-03 20:33:49 +0000 |
commit | b4b3278bd8a0406b2ab765f3cacd5208ef607ee6 (patch) | |
tree | 63dca57c175c650878ab5d116dc9b26a0ff16784 /libs | |
parent | bf687f5dc54b8b6bb14b1530610487ed04db81e6 (diff) |
Update clearlooks to fancy new cairo version.
Twiddle colours and throw some gloss in there mostly just to show off.
git-svn-id: svn://localhost/ardour2/branches/3.0@3000 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
22 files changed, 9909 insertions, 4626 deletions
diff --git a/libs/clearlooks/SConscript b/libs/clearlooks/SConscript index 2676f63022..feb4f8eeb5 100644 --- a/libs/clearlooks/SConscript +++ b/libs/clearlooks/SConscript @@ -4,18 +4,25 @@ import os.path import glob libclearlooks_files = [ + 'animation.c', + 'cairo-support.c', 'clearlooks_draw.c', - 'clearlooks_rc_style.c', - 'clearlooks_style.c', - 'clearlooks_theme_main.c', - 'support.c' ] + 'clearlooks_draw_glossy.c', + 'clearlooks_draw_gummy.c', + 'clearlooks_draw_inverted.c', + 'clearlooks_rc_style.c', + 'clearlooks_style.c', + 'clearlooks_theme_main.c', + 'support.c', + 'widget-information.c' + ] Import ('env install_prefix') clearlooks = env.Copy() -clearlooks.Replace(CCFLAGS = ' `pkg-config --cflags gtk+-2.0` ', - LINKFLAGS = ' `pkg-config --libs gtk+-2.0` ') +clearlooks.Replace(CCFLAGS = ' `pkg-config --cflags gtk+-2.0 cairo` ', + LINKFLAGS = ' `pkg-config --libs gtk+-2.0 cairo` ') if env['GTKOSX']: clearlooks.Append (CCFLAGS = '-DGTKOSX') diff --git a/libs/clearlooks/animation.c b/libs/clearlooks/animation.c new file mode 100644 index 0000000000..82af498949 --- /dev/null +++ b/libs/clearlooks/animation.c @@ -0,0 +1,337 @@ +/* Clearlooks theme engine + * + * Copyright (C) 2006 Kulyk Nazar <schamane@myeburg.net> + * Copyright (C) 2006 Benjamin Berg <benjamin@sipsolutions.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* This code is responsible for the clearlooks animation support. The code + * works by forcing a redraw on the animated widget. + */ + +#include "animation.h" + +#ifdef HAVE_ANIMATION +#include <glib/gtimer.h> + +struct _AnimationInfo { + GTimer *timer; + + gdouble start_modifier; + gdouble stop_time; + GtkWidget *widget; +}; +typedef struct _AnimationInfo AnimationInfo; + +struct _SignalInfo { + GtkWidget *widget; + gulong handler_id; +}; +typedef struct _SignalInfo SignalInfo; + +static GSList *connected_widgets = NULL; +static GHashTable *animated_widgets = NULL; +static int animation_timer_id = 0; + + +static gboolean animation_timeout_handler (gpointer data); + +/* This forces a redraw on a widget */ +static void +force_widget_redraw (GtkWidget *widget) +{ + if (GE_IS_PROGRESS_BAR (widget)) + gtk_widget_queue_resize (widget); + else + gtk_widget_queue_draw (widget); +} + +/* ensures that the timer is running */ +static void +start_timer () +{ + if (animation_timer_id == 0) + animation_timer_id = g_timeout_add (ANIMATION_DELAY, animation_timeout_handler, NULL); +} + +/* ensures that the timer is stopped */ +static void +stop_timer () +{ + if (animation_timer_id != 0) + { + g_source_remove(animation_timer_id); + animation_timer_id = 0; + } +} + + +/* destroys an AnimationInfo structure including the GTimer */ +static void +animation_info_destroy (AnimationInfo *animation_info) +{ + g_timer_destroy (animation_info->timer); + g_free (animation_info); +} + + +/* This function does not unref the weak reference, because the object + * is beeing destroyed currently. */ +static void +on_animated_widget_destruction (gpointer data, GObject *object) +{ + /* steal the animation info from the hash table (destroying it would + * result in the weak reference to be unrefed, which does not work + * as the widget is already destroyed. */ + g_hash_table_steal (animated_widgets, object); + animation_info_destroy ((AnimationInfo*) data); +} + +/* This function also needs to unref the weak reference. */ +static void +destroy_animation_info_and_weak_unref (gpointer data) +{ + AnimationInfo *animation_info = data; + + /* force a last redraw. This is so that if the animation is removed, + * the widget is left in a sane state. */ + force_widget_redraw (animation_info->widget); + + g_object_weak_unref (G_OBJECT (animation_info->widget), on_animated_widget_destruction, data); + animation_info_destroy (animation_info); +} + +/* Find and return a pointer to the data linked to this widget, if it exists */ +static AnimationInfo* +lookup_animation_info (const GtkWidget *widget) +{ + if (animated_widgets) + return g_hash_table_lookup (animated_widgets, widget); + + return NULL; +} + +/* Create all the relevant information for the animation, and insert it into the hash table. */ +static void +add_animation (const GtkWidget *widget, gdouble stop_time) +{ + AnimationInfo *value; + + /* object already in the list, do not add it twice */ + if (lookup_animation_info (widget)) + return; + + if (animated_widgets == NULL) + animated_widgets = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, destroy_animation_info_and_weak_unref); + + value = g_new(AnimationInfo, 1); + + value->widget = (GtkWidget*) widget; + + value->timer = g_timer_new (); + value->stop_time= stop_time; + value->start_modifier = 0.0; + + g_object_weak_ref (G_OBJECT (widget), on_animated_widget_destruction, value); + g_hash_table_insert (animated_widgets, (GtkWidget*) widget, value); + + start_timer (); +} + +/* update the animation information for each widget. This will also queue a redraw + * and stop the animation if it is done. */ +static gboolean +update_animation_info (gpointer key, gpointer value, gpointer user_data) +{ + AnimationInfo *animation_info = value; + GtkWidget *widget = key; + + g_assert ((widget != NULL) && (animation_info != NULL)); + + /* remove the widget from the hash table if it is not drawable */ + if (!GTK_WIDGET_DRAWABLE (widget)) + { + return TRUE; + } + + if (GE_IS_PROGRESS_BAR (widget)) + { + gfloat fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (widget)); + + /* stop animation for filled/not filled progress bars */ + if (fraction <= 0.0 || fraction >= 1.0) + return TRUE; + } + + force_widget_redraw (widget); + + /* stop at stop_time */ + if (animation_info->stop_time != 0 && + g_timer_elapsed (animation_info->timer, NULL) > animation_info->stop_time) + return TRUE; + + return FALSE; +} + +/* This gets called by the glib main loop every once in a while. */ +static gboolean +animation_timeout_handler (gpointer data) +{ + /*g_print("** TICK **\n");*/ + + /* enter threads as update_animation_info will use gtk/gdk. */ + gdk_threads_enter (); + g_hash_table_foreach_remove (animated_widgets, update_animation_info, NULL); + /* leave threads again */ + gdk_threads_leave (); + + if(g_hash_table_size(animated_widgets)==0) + { + stop_timer (); + return FALSE; + } + + return TRUE; +} + +static void +on_checkbox_toggle (GtkWidget *widget, gpointer data) +{ + AnimationInfo *animation_info = lookup_animation_info (widget); + + if (animation_info != NULL) + { + gfloat elapsed = g_timer_elapsed (animation_info->timer, NULL); + + animation_info->start_modifier = elapsed - animation_info->start_modifier; + } + else + { + add_animation (widget, CHECK_ANIMATION_TIME); + } +} + +static void +on_connected_widget_destruction (gpointer data, GObject *widget) +{ + connected_widgets = g_slist_remove (connected_widgets, data); + g_free (data); +} + +static void +disconnect_all_signals () +{ + GSList * item = connected_widgets; + while (item != NULL) + { + SignalInfo *signal_info = (SignalInfo*) item->data; + + g_signal_handler_disconnect (signal_info->widget, signal_info->handler_id); + g_object_weak_unref (G_OBJECT (signal_info->widget), on_connected_widget_destruction, signal_info); + g_free (signal_info); + + item = g_slist_next (item); + } + + g_slist_free (connected_widgets); + connected_widgets = NULL; +} + +/* helper function for clearlooks_animation_connect_checkbox */ +static gint +find_signal_info (gconstpointer signal_info, gconstpointer widget) +{ + if (((SignalInfo*)signal_info)->widget == widget) + return 0; + else + return 1; +} + + +/* external interface */ + +/* adds a progress bar */ +void +clearlooks_animation_progressbar_add (GtkWidget *progressbar) +{ + gdouble fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progressbar)); + + if (fraction < 1.0 && fraction > 0.0) + add_animation ((GtkWidget*) progressbar, 0.0); +} + +/* hooks up the signals for check and radio buttons */ +void +clearlooks_animation_connect_checkbox (GtkWidget *widget) +{ + if (GE_IS_CHECK_BUTTON (widget)) + { + if (!g_slist_find_custom (connected_widgets, widget, find_signal_info)) + { + SignalInfo * signal_info = g_new (SignalInfo, 1); + + signal_info->widget = widget; + signal_info->handler_id = g_signal_connect ((GObject*)widget, "toggled", G_CALLBACK (on_checkbox_toggle), NULL); + + connected_widgets = g_slist_append (connected_widgets, signal_info); + g_object_weak_ref (G_OBJECT (widget), on_connected_widget_destruction, signal_info); + } + } +} + +/* returns TRUE if the widget is animated, and FALSE otherwise */ +gboolean +clearlooks_animation_is_animated (GtkWidget *widget) +{ + return lookup_animation_info (widget) != NULL ? TRUE : FALSE; +} + +/* returns the elapsed time for the animation */ +gdouble +clearlooks_animation_elapsed (gpointer data) +{ + AnimationInfo *animation_info = lookup_animation_info (data); + + if (animation_info) + return g_timer_elapsed (animation_info->timer, NULL) + - animation_info->start_modifier; + else + return 0.0; +} + +/* cleans up all resources of the animation system */ +void +clearlooks_animation_cleanup () +{ + disconnect_all_signals (); + + if (animated_widgets != NULL) + { + g_hash_table_destroy (animated_widgets); + animated_widgets = NULL; + } + + stop_timer (); +} +#else /* !HAVE_ANIMATION */ +static void clearlooks_animation_dummy_function_so_wall_shuts_up_when_animations_is_disabled() +{ + clearlooks_animation_dummy_function_so_wall_shuts_up_when_animations_is_disabled(); +} +#endif /* HAVE_ANIMATION */ diff --git a/libs/clearlooks/animation.h b/libs/clearlooks/animation.h new file mode 100644 index 0000000000..da70b6ce66 --- /dev/null +++ b/libs/clearlooks/animation.h @@ -0,0 +1,34 @@ +/* Clearlooks Engine + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifdef HAVE_ANIMATION +#include <gtk/gtk.h> +#include <ge-support.h> + +#define CL_IS_PROGRESS_BAR(widget) GE_IS_PROGRESS_BAR(widget) && widget->allocation.x != -1 && widget->allocation.y != -1 +#define ANIMATION_DELAY 100 +#define CHECK_ANIMATION_TIME 0.5 + +GE_INTERNAL void clearlooks_animation_progressbar_add (GtkWidget *progressbar); +GE_INTERNAL void clearlooks_animation_connect_checkbox (GtkWidget *widget); +GE_INTERNAL gboolean clearlooks_animation_is_animated (GtkWidget *widget); +GE_INTERNAL gdouble clearlooks_animation_elapsed (gpointer data); +GE_INTERNAL void clearlooks_animation_cleanup (); +#endif /* HAVE_ANIMATION */ diff --git a/libs/clearlooks/cairo-support.c b/libs/clearlooks/cairo-support.c new file mode 100644 index 0000000000..dbe6fd3d34 --- /dev/null +++ b/libs/clearlooks/cairo-support.c @@ -0,0 +1,815 @@ +#include <math.h> +#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 (fabs(max - min) < 0.0001) + { + *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 (const GdkColor *c, CairoColor *cc) +{ + gdouble r, g, b; + + g_return_if_fail (c && cc); + + r = c->red / 65535.0; + g = c->green / 65535.0; + b = c->blue / 65535.0; + + cc->r = r; + cc->g = g; + cc->b = b; + cc->a = 1.0; +} + +void +ge_cairo_color_to_gtk (const CairoColor *cc, GdkColor *c) +{ + gdouble r, g, b; + + g_return_if_fail (c && cc); + + r = cc->r * 65535.0; + g = cc->g * 65535.0; + b = cc->b * 65535.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; +} + +void +ge_mix_color (const CairoColor *color1, const CairoColor *color2, + gdouble mix_factor, CairoColor *composite) +{ + g_return_if_fail (color1 && color2 && composite); + + composite->r = color1->r * (1-mix_factor) + color2->r * mix_factor; + composite->g = color1->g * (1-mix_factor) + color2->g * mix_factor; + composite->b = color1->b * (1-mix_factor) + color2->b * mix_factor; + composite->a = 1.0; +} + +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, const CairoColor *color) +{ + g_return_if_fail (cr && color); + + cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a); +} + +void +ge_cairo_set_gdk_color_with_alpha (cairo_t *cr, const GdkColor *color, gdouble alpha) +{ + g_return_if_fail (cr && color); + + cairo_set_source_rgba (cr, color->red / 65535.0, + color->green / 65535.0, + color->blue / 65535.0, + alpha); +} + +void +ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, + gfloat offset, + const 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_pattern_add_color_stop_shade(cairo_pattern_t *pattern, + gdouble offset, + const CairoColor *color, + gdouble shade) +{ + CairoColor shaded; + + g_return_if_fail (pattern && color && (shade >= 0) && (shade <= 3)); + + shaded = *color; + + if (shade != 1) + { + ge_shade_color(color, shade, &shaded); + } + + ge_cairo_pattern_add_color_stop_color(pattern, offset, &shaded); +} + +/* This function will draw a rounded corner at position x,y. If the radius + * is very small (or negative) it will instead just do a line_to. + * ge_cairo_rounded_corner assumes clockwise drawing. */ +void +ge_cairo_rounded_corner (cairo_t *cr, + double x, + double y, + double radius, + CairoCorners corner) +{ + if (radius < 0.0001) + { + cairo_line_to (cr, x, y); + } + else + { + switch (corner) { + case CR_CORNER_NONE: + cairo_line_to (cr, x, y); + break; + case CR_CORNER_TOPLEFT: + cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 3/2); + break; + case CR_CORNER_TOPRIGHT: + cairo_arc (cr, x - radius, y + radius, radius, G_PI * 3/2, G_PI * 2); + break; + case CR_CORNER_BOTTOMRIGHT: + cairo_arc (cr, x - radius, y - radius, radius, 0, G_PI * 1/2); + break; + case CR_CORNER_BOTTOMLEFT: + cairo_arc (cr, x + radius, y - radius, radius, G_PI * 1/2, G_PI); + break; + + default: + /* A bitfield and not a sane value ... */ + g_assert_not_reached (); + cairo_line_to (cr, x, y); + return; + } + } +} + +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 || corners == CR_CORNER_NONE) + { + cairo_rectangle (cr, x, y, w, h); + return; + } +#ifdef DEVELOPMENT + if ((corners == CR_CORNER_ALL) && (radius > w / 2.0 || radius > h / 2.0)) + g_warning ("Radius is too large for width/height in ge_rounded_rectangle.\n"); + else if (radius > w || radius > h) /* This isn't perfect. Assumes that only one corner is set. */ + g_warning ("Radius is too large for width/height in ge_rounded_rectangle.\n"); +#endif + + 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, G_PI * 1.5, G_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, G_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, G_PI * 0.5, G_PI); + else + cairo_line_to (cr, x, y+h); + + if (corners & CR_CORNER_TOPLEFT) + cairo_arc (cr, x+radius, y+radius, radius, G_PI, G_PI * 1.5); + else + cairo_line_to (cr, x, y); +} + + +/* ge_cairo_stroke_rectangle. + * + * A simple function to stroke the rectangle { x, y, w, h}. + * (This function only exists because of a cairo performance bug that + * has been fixed and it may be a good idea to get rid of it again.) + */ +void +ge_cairo_stroke_rectangle (cairo_t *cr, double x, double y, double w, double h) +{ + cairo_rectangle (cr, x, y, w, h); + cairo_stroke (cr); +} + +/*********************************************** + * 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, + const CairoColor * tl, const 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, + const 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, + const 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); + + cairo_translate (cr, *x, *y); + *x = 0; + *y = 0; + + if (mirror & CR_MIRROR_HORIZONTAL) + { + cairo_matrix_scale (&matrix, -1, 1); + *x = -*width; + } + if (mirror & CR_MIRROR_VERTICAL) + { + cairo_matrix_scale (&matrix, 1, -1); + *y = -*height; + } + + cairo_transform (cr, &matrix); +} + +void +ge_cairo_exchange_axis (cairo_t *cr, + gint *x, + gint *y, + gint *width, + gint *height) +{ + gint tmp; + cairo_matrix_t matrix; + + cairo_translate (cr, *x, *y); + cairo_matrix_init (&matrix, 0, 1, 1, 0, 0, 0); + + cairo_transform (cr, &matrix); + + /* swap width/height */ + tmp = *width; + *x = 0; + *y = 0; + *width = *height; + *height = tmp; +} + + +/*********************************************** + * ge_cairo_pattern_fill - + * + * Fill an area with some pattern + * Scaling or tiling if needed + ***********************************************/ +void +ge_cairo_pattern_fill(cairo_t *canvas, + CairoPattern *pattern, + gint x, + gint y, + gint width, + gint height) +{ + cairo_matrix_t original_matrix, current_matrix; + + if (pattern->operator == CAIRO_OPERATOR_DEST) + { + return; + } + + cairo_pattern_get_matrix(pattern->handle, &original_matrix); + current_matrix = original_matrix; + + if (pattern->scale != GE_DIRECTION_NONE) + { + gdouble scale_x = 1.0; + gdouble scale_y = 1.0; + + if ((pattern->scale == GE_DIRECTION_VERTICAL) || (pattern->scale == GE_DIRECTION_BOTH)) + { + scale_x = 1.0/width; + } + + if ((pattern->scale == GE_DIRECTION_HORIZONTAL) || (pattern->scale == GE_DIRECTION_BOTH)) + { + scale_y = 1.0/height; + } + + cairo_matrix_scale(¤t_matrix, scale_x, scale_y); + } + + if (pattern->translate != GE_DIRECTION_NONE) + { + gdouble translate_x = 0; + gdouble translate_y = 0; + + if ((pattern->translate == GE_DIRECTION_VERTICAL) || (pattern->translate == GE_DIRECTION_BOTH)) + { + translate_x = 0.0-x; + } + + if ((pattern->translate == GE_DIRECTION_HORIZONTAL) || (pattern->translate == GE_DIRECTION_BOTH)) + { + translate_y = 0.0-y; + } + + cairo_matrix_translate(¤t_matrix, translate_x, translate_y); + } + + cairo_pattern_set_matrix(pattern->handle, ¤t_matrix); + + cairo_save(canvas); + + cairo_set_source(canvas, pattern->handle); + cairo_set_operator(canvas, pattern->operator); + cairo_rectangle(canvas, x, y, width, height); + + cairo_fill (canvas); + + cairo_restore(canvas); + + cairo_pattern_set_matrix(pattern->handle, &original_matrix); +} + +/*********************************************** + * ge_cairo_color_pattern - + * + * Create A Solid Color Pattern + ***********************************************/ +CairoPattern* +ge_cairo_color_pattern(CairoColor *base) +{ + CairoPattern * result = g_new0(CairoPattern, 1); + + #if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) + result->type = CAIRO_PATTERN_TYPE_SOLID; + #endif + + result->scale = GE_DIRECTION_NONE; + result->translate = GE_DIRECTION_NONE; + + result->handle = cairo_pattern_create_rgba(base->r, + base->g, + base->b, + base->a); + + result->operator = CAIRO_OPERATOR_SOURCE; + + return result; +} + +/*********************************************** + * ge_cairo_pixbuf_pattern - + * + * Create A Tiled Pixbuf Pattern + ***********************************************/ +CairoPattern* +ge_cairo_pixbuf_pattern(GdkPixbuf *pixbuf) +{ + CairoPattern * result = g_new0(CairoPattern, 1); + + cairo_t *canvas; + cairo_surface_t * surface; + gint width, height; + + #if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) + result->type = CAIRO_PATTERN_TYPE_SURFACE; + #endif + + result->scale = GE_DIRECTION_NONE; + result->translate = GE_DIRECTION_BOTH; + + width = gdk_pixbuf_get_width(pixbuf); + height = gdk_pixbuf_get_height(pixbuf); + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + + canvas = cairo_create(surface); + + gdk_cairo_set_source_pixbuf (canvas, pixbuf, 0, 0); + cairo_rectangle (canvas, 0, 0, width, height); + cairo_fill (canvas); + cairo_destroy(canvas); + + result->handle = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy(surface); + + cairo_pattern_set_extend (result->handle, CAIRO_EXTEND_REPEAT); + + result->operator = CAIRO_OPERATOR_SOURCE; + + return result; +} + +/*********************************************** + * ge_cairo_pixmap_pattern - + * + * Create A Tiled Pixmap Pattern + ***********************************************/ +CairoPattern* +ge_cairo_pixmap_pattern(GdkPixmap *pixmap) +{ + CairoPattern * result = NULL; + + GdkPixbuf * pixbuf; + gint width, height; + + gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height); + + pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE (pixmap), + gdk_drawable_get_colormap(GDK_DRAWABLE (pixmap)), + 0, 0, 0, 0, width, height); + + result = ge_cairo_pixbuf_pattern(pixbuf); + + g_object_unref (pixbuf); + + return result; +} + +/*********************************************** + * ge_cairo_linear_shade_gradient_pattern - + * + * Create A Linear Shade Gradient Pattern + * Aka Smooth Shade Gradient, from/to gradient + * With End points defined as shades of the + * base color + ***********************************************/ +CairoPattern * +ge_cairo_linear_shade_gradient_pattern(CairoColor *base, + gdouble shade1, + gdouble shade2, + gboolean vertical) +{ + CairoPattern * result = g_new0(CairoPattern, 1); + + #if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) + result->type = CAIRO_PATTERN_TYPE_LINEAR; + #endif + + if (vertical) + { + result->scale = GE_DIRECTION_VERTICAL; + + result->handle = cairo_pattern_create_linear(0, 0, 1, 0); + } + else + { + result->scale = GE_DIRECTION_HORIZONTAL; + + result->handle = cairo_pattern_create_linear(0, 0, 0, 1); + } + + result->translate = GE_DIRECTION_BOTH; + result->operator = CAIRO_OPERATOR_SOURCE; + + ge_cairo_pattern_add_color_stop_shade(result->handle, 0, base, shade1); + ge_cairo_pattern_add_color_stop_shade(result->handle, 1, base, shade2); + + return result; +} + +void +ge_cairo_pattern_destroy(CairoPattern *pattern) +{ + if (pattern) + { + if (pattern->handle) + cairo_pattern_destroy(pattern->handle); + + g_free(pattern); + } +} + +/* 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. + */ +GE_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/libs/clearlooks/cairo-support.h b/libs/clearlooks/cairo-support.h new file mode 100644 index 0000000000..12163b0469 --- /dev/null +++ b/libs/clearlooks/cairo-support.h @@ -0,0 +1,118 @@ +/* Helpful functions when dealing with cairo in gtk engines */ + +#include <gtk/gtk.h> +#include <math.h> + +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; + +/*****************************/ +/* Pattern Fills */ +/*****************************/ +typedef enum { + GE_DIRECTION_VERTICAL, + GE_DIRECTION_HORIZONTAL, + GE_DIRECTION_BOTH, + GE_DIRECTION_NONE +} GeDirection; + +#if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) +typedef enum _cairo_pattern_type { + CAIRO_PATTERN_TYPE_SOLID, + CAIRO_PATTERN_TYPE_SURFACE, + CAIRO_PATTERN_TYPE_LINEAR, + CAIRO_PATTERN_TYPE_RADIAL +} cairo_pattern_type_t; + +# define CAIRO_PATTERN_TYPE(pattern) pattern->type; +#else +# define CAIRO_PATTERN_TYPE(pattern) cairo_pattern_get_type (pattern->handle); +#endif + +typedef struct +{ +#if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) + cairo_pattern_type_t type; +#endif + GeDirection scale; + GeDirection translate; + + cairo_pattern_t *handle; + cairo_operator_t operator; +} CairoPattern; + +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 (const GdkColor * gc, CairoColor * cc); +GE_INTERNAL void ge_cairo_color_to_gtk (const 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 void ge_mix_color (const CairoColor *color1, const CairoColor *color2, gdouble mix_factor, 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, const CairoColor *color); +GE_INTERNAL void ge_cairo_set_gdk_color_with_alpha (cairo_t *cr, const GdkColor *color, gdouble alpha); +GE_INTERNAL void ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, gfloat offset, const CairoColor *color); +GE_INTERNAL void ge_cairo_pattern_add_color_stop_shade (cairo_pattern_t *pattern, gdouble offset, const CairoColor *color, gdouble shade); + +GE_INTERNAL void ge_cairo_rounded_corner (cairo_t *cr, double x, double y, double radius, CairoCorners corner); +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_stroke_rectangle (cairo_t *cr, double x, double y, double w, double h); +GE_INTERNAL void ge_cairo_simple_border (cairo_t *cr, const CairoColor * tl, const CairoColor * br, gint x, gint y, gint width, gint height, gboolean topleft_overlap); + +GE_INTERNAL void ge_cairo_line (cairo_t *cr, const CairoColor *color, gint x1, gint y1, gint x2, gint y2); +GE_INTERNAL void ge_cairo_polygon (cairo_t *cr, const 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); +GE_INTERNAL void ge_cairo_exchange_axis (cairo_t *cr, gint *x, gint *y, gint *width, gint *height); + +GE_INTERNAL void ge_cairo_pattern_fill(cairo_t *canvas, CairoPattern *pattern, gint x, gint y, gint width, gint height); + +GE_INTERNAL CairoPattern *ge_cairo_color_pattern(CairoColor *base); +GE_INTERNAL CairoPattern *ge_cairo_pixbuf_pattern(GdkPixbuf *pixbuf); +GE_INTERNAL CairoPattern *ge_cairo_pixmap_pattern(GdkPixmap *pixmap); +GE_INTERNAL CairoPattern *ge_cairo_linear_shade_gradient_pattern(CairoColor *base, gdouble shade1, gdouble shade2, gboolean vertical); +GE_INTERNAL void ge_cairo_pattern_destroy(CairoPattern *pattern); diff --git a/libs/clearlooks/clearlooks_draw.c b/libs/clearlooks/clearlooks_draw.c index 144be35152..614317ea3b 100644 --- a/libs/clearlooks/clearlooks_draw.c +++ b/libs/clearlooks/clearlooks_draw.c @@ -1,1293 +1,2279 @@ +/* Clearlooks theme engine + * Copyright (C) 2006 Richard Stellingwerff + * Copyright (C) 2006 Daniel Borgman + * Copyright (C) 2007 Benjamin Berg + * Copyright (C) 2007 Andrea Cimitan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + #include "clearlooks_draw.h" #include "clearlooks_style.h" +#include "clearlooks_types.h" #include "support.h" +#include <ge-support.h> +#include <math.h> + +#include <cairo.h> + +typedef void (*menubar_draw_proto) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const MenuBarParameters *menubar, + int x, int y, int width, int height); + +static void +clearlooks_draw_inset (cairo_t *cr, + const CairoColor *bg_color, + double x, double y, double w, double h, + double radius, uint8 corners) +{ + CairoColor shadow; + CairoColor highlight; + + /* not really sure of shading ratios... we will think */ + ge_shade_color (bg_color, 0.94, &shadow); + ge_shade_color (bg_color, 1.06, &highlight); + + /* highlight */ + cairo_move_to (cr, x + w + (radius * -0.2928932188), y - (radius * -0.2928932188)); /* 0.2928932... 1-sqrt(2)/2 gives middle of curve */ + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.75, G_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, G_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, G_PI * 0.5, G_PI * 0.75); + else + cairo_line_to (cr, x, y + h); + + ge_cairo_set_color (cr, &highlight); + cairo_stroke (cr); + + /* shadow */ + cairo_move_to (cr, x + (radius * 0.2928932188), y + h + (radius * -0.2928932188)); + + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_arc (cr, x + radius, y + h - radius, radius, M_PI * 0.75, 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); -/** WANTED: - FASTER GRADIENT FILL FUNCTION, POSSIBLY USING XRENDER. **/ - -static void cl_draw_borders (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r); - -static void cl_draw_line (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x1, int y1, int x2, int y2, CLBorderType border, - CLRectangle *r); - -static void cl_draw_corner (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, - CLRectangle *r, CLCornerSide corner); - -static void cl_draw_fill (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r); - -void cl_draw_rectangle (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r) + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, M_PI * 1.5, M_PI * 1.75); + else + cairo_line_to (cr, x + w, y); + + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); +} + +static void +clearlooks_draw_shadow (cairo_t *cr, const ClearlooksColors *colors, gfloat radius, int width, int height) { - if (r->fillgc) - { - cl_draw_fill(window, widget, style, x, y, width, height, r); - } + CairoColor shadow; + ge_shade_color (&colors->shade[6], 0.92, &shadow); + + cairo_set_line_width (cr, 1.0); - if (r->bordergc) - { - cl_draw_borders(window, widget, style, x, y, width, height, r); - } -} + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1); + + cairo_move_to (cr, width, radius); + ge_cairo_rounded_corner (cr, width, height, radius, CR_CORNER_BOTTOMRIGHT); + cairo_line_to (cr, radius, height); + cairo_stroke (cr); +} -static void cl_get_coords ( CLBorderType border, - int x, int y, int width, int height, - CLRectangle *r, int *x1, int *y1, int *x2, int *y2) +static void +clearlooks_draw_top_left_highlight (cairo_t *cr, const CairoColor *color, + const WidgetParameters *params, + int width, int height, gdouble radius) { - switch (border) - { - case CL_BORDER_TOP: - *x1 = x + r->corners[CL_CORNER_TOPLEFT]; - *x2 = *x1 + width - r->corners[CL_CORNER_TOPLEFT] - r->corners[CL_CORNER_TOPRIGHT] - 1; - *y1 = *y2 = y; - break; - case CL_BORDER_BOTTOM: - *x1 = x + r->corners[CL_CORNER_BOTTOMLEFT]; - *x2 = *x1 + width - r->corners[CL_CORNER_BOTTOMLEFT] - r->corners[CL_CORNER_BOTTOMRIGHT] - 1; - *y1 = *y2 = y + height - 1; - break; - case CL_BORDER_LEFT: - *x1 = *x2 = x; - *y1 = y + r->corners[CL_CORNER_TOPLEFT]; - *y2 = *y1 + height - r->corners[CL_CORNER_TOPLEFT] - r->corners[CL_CORNER_BOTTOMLEFT] - 1; - break; - case CL_BORDER_RIGHT: - *x1 = *x2 = x + width - 1; - *y1 = y + r->corners[CL_CORNER_TOPRIGHT]; - *y2 = *y1 + height - r->corners[CL_CORNER_TOPRIGHT] - r->corners[CL_CORNER_BOTTOMRIGHT] - 1; - break; - } + CairoColor hilight; + + double light_top = params->ythickness-1, + light_bottom = height - params->ythickness - 1, + light_left = params->xthickness-1, + light_right = width - params->xthickness - 1; + + ge_shade_color (color, 1.3, &hilight); + cairo_move_to (cr, light_left, light_bottom - (int)radius/2); + + ge_cairo_rounded_corner (cr, light_left, light_top, radius, params->corners & CR_CORNER_TOPLEFT); + + cairo_line_to (cr, light_right - (int)radius/2, light_top); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + cairo_stroke (cr); } -void cl_draw_borders (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r) +#ifdef DEVELOPMENT +#warning seems to be very slow in scrollbar_stepper +#endif + +static void +clearlooks_draw_highlight_and_shade (cairo_t *cr, const ClearlooksColors *colors, + const ShadowParameters *params, + int width, int height, gdouble radius) { - int x1, y1, x2, y2, i; + CairoColor hilight; + CairoColor shadow; + uint8 corners = params->corners; + double x = 1.0; + double y = 1.0; - if (r->bordergc == NULL) - return; + ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 1.06, &hilight); + ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 0.94, &shadow); - for ( i=0; i<4; i++) /* draw all four borders + corners */ - { - cl_get_coords (i, x, y, width, height, r, &x1, &y1, &x2, &y2); - cl_draw_line (window, widget, style, x1, y1, x2, y2, i, r); - cl_draw_corner (window, widget, style, x, y, width, height, r, i ); - } -} + width -= 3; + height -= 3; + + cairo_save (cr); + + /* Top/Left highlight */ + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_move_to (cr, x, y+height-radius); + else + cairo_move_to (cr, x, y+height); + + ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT); + if (corners & CR_CORNER_TOPRIGHT) + cairo_line_to (cr, x+width-radius, y); + else + cairo_line_to (cr, x+width, y); + + if (params->shadow & CL_SHADOW_OUT) + ge_cairo_set_color (cr, &hilight); + else + ge_cairo_set_color (cr, &shadow); + + cairo_stroke (cr); + + /* Bottom/Right highlight -- this includes the corners */ + cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */ + ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT); + ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT); + + if (params->shadow & CL_SHADOW_OUT) + ge_cairo_set_color (cr, &shadow); + else + ge_cairo_set_color (cr, &hilight); + + cairo_stroke (cr); + + cairo_restore (cr); +} -static GdkColor cl_gc_get_foreground(GdkGC *gc) +static void +clearlooks_set_border_gradient (cairo_t *cr, const CairoColor *color, double hilight, int width, int height) { - GdkGCValues values; - gdk_gc_get_values (gc, &values); - return values.foreground; + cairo_pattern_t *pattern; + + CairoColor bottom_shade; + ge_shade_color (color, hilight, &bottom_shade); + + pattern = cairo_pattern_create_linear (0, 0, width, height); + cairo_pattern_add_color_stop_rgb (pattern, 0, color->r, color->g, color->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, bottom_shade.r, bottom_shade.g, bottom_shade.b); + + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); } -static void cl_draw_line (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x1, int y1, int x2, int y2, CLBorderType border, - CLRectangle *r) +static void +clearlooks_draw_gripdots (cairo_t *cr, const ClearlooksColors *colors, int x, int y, + int width, int height, int xr, int yr, + float contrast) { - if (r->gradient_type == CL_GRADIENT_NONE || - r->border_gradient.from == NULL || r->border_gradient.to == NULL ) + const CairoColor *dark = &colors->shade[4]; + CairoColor hilight; + int i, j; + int xoff, yoff; + + ge_shade_color (dark, 1.5, &hilight); + + for ( i = 0; i < xr; i++ ) { - gdk_draw_line (window, r->bordergc, x1, y1, x2, y2); + for ( j = 0; j < yr; j++ ) + { + xoff = x -(xr * 3 / 2) + 3 * i; + yoff = y -(yr * 3 / 2) + 3 * j; + + cairo_rectangle (cr, width/2+0.5+xoff, height/2+0.5+yoff, 2, 2); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.8+contrast); + cairo_fill (cr); + cairo_rectangle (cr, width/2+0.5+xoff, height/2+0.5+yoff, 1, 1); + cairo_set_source_rgba (cr, dark->r, dark->g, dark->b, 0.8+contrast); + cairo_fill (cr); + } } - else if (r->gradient_type == CL_GRADIENT_HORIZONTAL && (border == CL_BORDER_TOP || border == CL_BORDER_BOTTOM)) +} + +static void +clearlooks_draw_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + double xoffset = 0, yoffset = 0; + double radius = params->radius; + const CairoColor *fill = &colors->bg[params->state_type]; + const CairoColor *border_normal = &colors->shade[6]; + const CairoColor *border_disabled = &colors->shade[4]; + + CairoColor shadow; + ge_shade_color (border_normal, 0.925, &shadow); + + cairo_save (cr); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + if (params->xthickness == 3 || params->ythickness == 3) { - draw_vgradient (window, r->bordergc, style, - x1, y1, x2-x1+1, 1, - r->border_gradient.from, r->border_gradient.to); + if (params->xthickness == 3) + xoffset = 1; + if (params->ythickness == 3) + yoffset = 1; } - else if (r->gradient_type == CL_GRADIENT_VERTICAL && (border == CL_BORDER_LEFT || border == CL_BORDER_RIGHT)) + + radius = MIN (radius, MIN ((width - 2.0 - xoffset * 2.0) / 2.0, (height - 2.0 - yoffset * 2) / 2.0)); + + if (params->xthickness == 3 || params->ythickness == 3) + { + cairo_translate (cr, 0.5, 0.5); + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners); + cairo_translate (cr, -0.5, -0.5); + } + + ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, + width-(xoffset*2)-2, + height-(yoffset*2)-2, + radius, params->corners); + + if (!params->active) { - draw_hgradient (window, r->bordergc, style, - x1, y1, 1, y2-y1+1, - r->border_gradient.from, r->border_gradient.to); + cairo_pattern_t *pattern; + gdouble shade_size = ((100.0/height)*8.0)/100.0; + CairoColor top_shade, bottom_shade, middle_shade; + + ge_shade_color (fill, 1.1, &top_shade); + ge_shade_color (fill, 0.98, &middle_shade); + ge_shade_color (fill, 0.93, &bottom_shade); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, top_shade.r, top_shade.g, top_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, shade_size, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0 - shade_size, middle_shade.r, middle_shade.g, middle_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, (height-(yoffset*2)-1)/height, bottom_shade.r, bottom_shade.g, bottom_shade.b); + cairo_pattern_add_color_stop_rgba (pattern, (height-(yoffset*2)-1)/height, bottom_shade.r, bottom_shade.g, bottom_shade.b, 0.7); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, bottom_shade.r, bottom_shade.g, bottom_shade.b, 0.7); + + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); } else { - GdkColor tmp_color = cl_gc_get_foreground (r->bordergc); + cairo_pattern_t *pattern; + + ge_cairo_set_color (cr, fill); + cairo_fill_preserve (cr); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 0.4, shadow.r, shadow.g, shadow.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.2); + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + pattern = cairo_pattern_create_linear (0, yoffset+1, 0, 3+yoffset); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, params->disabled ? 0.125 : 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + pattern = cairo_pattern_create_linear (xoffset+1, 0, 3+xoffset, 0); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, params->disabled ? 0.125 : 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } - if (r->gradient_type == CL_GRADIENT_HORIZONTAL && border == CL_BORDER_LEFT || - r->gradient_type == CL_GRADIENT_VERTICAL && border == CL_BORDER_TOP) - gdk_gc_set_foreground (r->bordergc, r->border_gradient.from); - else - gdk_gc_set_foreground (r->bordergc, r->border_gradient.to); - gdk_draw_line (window, r->bordergc, x1, y1, x2, y2); + /* Drawing the border */ + if (!params->active && params->is_default) + { + const CairoColor *l = &colors->shade[4]; + const CairoColor *d = &colors->shade[4]; + ge_cairo_set_color (cr, l); + ge_cairo_stroke_rectangle (cr, 2.5, 2.5, width-5, height-5); + + ge_cairo_set_color (cr, d); + ge_cairo_stroke_rectangle (cr, 3.5, 3.5, width-7, height-7); + } + + ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, width-(xoffset*2)-1, height-(yoffset*2)-1, radius, params->corners); + + if (params->disabled) + ge_cairo_set_color (cr, border_disabled); + else + if (!params->active) + clearlooks_set_border_gradient (cr, border_normal, 1.32, 0, height); + else + ge_cairo_set_color (cr, border_normal); + + cairo_stroke (cr); + + /* Draw the "shadow" */ + if (!params->active) + { + cairo_translate (cr, 0.5, 0.5); + /* Draw right shadow */ + cairo_move_to (cr, width-params->xthickness, params->ythickness - 1); + cairo_line_to (cr, width-params->xthickness, height - params->ythickness - 1); + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1); + cairo_stroke (cr); - gdk_gc_set_foreground (r->bordergc, &tmp_color); + /* Draw topleft shadow */ + clearlooks_draw_top_left_highlight (cr, fill, params, width, height, radius); } + cairo_restore (cr); } -static GdkColor *cl_get_gradient_corner_color (CLRectangle *r, CLCornerSide corner) +static void +clearlooks_draw_entry (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) { - GdkColor *color; + const CairoColor *base = &colors->base[params->state_type]; + CairoColor border = colors->shade[params->disabled ? 4 : 6]; + double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0)); + + if (params->focus) + border = colors->spot[2]; - if (r->border_gradient.from == NULL || r->border_gradient.to == NULL) - { - color = NULL; - } - else if ((r->gradient_type == CL_GRADIENT_HORIZONTAL && (corner == CL_CORNER_TOPLEFT || corner == CL_CORNER_BOTTOMLEFT)) || - (r->gradient_type == CL_GRADIENT_VERTICAL && (corner == CL_CORNER_TOPLEFT || corner == CL_CORNER_TOPRIGHT))) + cairo_translate (cr, x+0.5, y+0.5); + cairo_set_line_width (cr, 1.0); + + /* Fill the background (shouldn't have to) */ + cairo_rectangle (cr, -0.5, -0.5, width, height); + ge_cairo_set_color (cr, ¶ms->parentbg); + cairo_fill (cr); + + /* Fill the entry's base color (why isn't is large enough by default?) */ + cairo_rectangle (cr, 1.5, 1.5, width-4, height-4); + ge_cairo_set_color (cr, base); + cairo_fill (cr); + + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners); + + /* Draw the inner shadow */ + if (params->focus) { - color = r->border_gradient.from; + /* ge_cairo_rounded_rectangle (cr, 2, 2, width-5, height-5, RADIUS-1, params->corners); */ + ge_cairo_set_color (cr, &colors->spot[0]); + ge_cairo_stroke_rectangle (cr, 2, 2, width-5, height-5); } - else /* no gradient or other corner */ + else { - color = r->border_gradient.to; + CairoColor shadow; + ge_shade_color (&border, 0.925, &shadow); + + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, params->disabled ? 0.05 : 0.1); + /* + cairo_move_to (cr, 2, height-3); + cairo_arc (cr, params->xthickness+RADIUS-1, params->ythickness+RADIUS-1, RADIUS, G_PI, 270*(G_PI/180)); + cairo_line_to (cr, width-3, 2);*/ + cairo_move_to (cr, 2, height-3); + cairo_line_to (cr, 2, 2); + cairo_line_to (cr, width-3, 2); + cairo_stroke (cr); } - - return color; + + ge_cairo_rounded_rectangle (cr, 1, 1, width-3, height-3, radius, params->corners); + if (params->focus || params->disabled) + ge_cairo_set_color (cr, &border); + else + clearlooks_set_border_gradient (cr, &border, 1.32, 0, height); + cairo_stroke (cr); } -static void cl_draw_corner (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, - CLRectangle *r, CLCornerSide corner) +static void +clearlooks_draw_spinbutton (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) { - GdkColor *color; - GdkColor aacolor; /* anti-aliasing color */ - GdkGCValues values; - GdkColor tmp; - GdkColor *bgcolor; + const CairoColor *border = &colors->shade[!params->disabled ? 5 : 3]; + CairoColor hilight; - int x1; - int y1; + params->style_functions->draw_button (cr, colors, params, x, y, width, height); - if (r->corners[corner] == CL_CORNER_NONE) - return; + ge_shade_color (border, 1.5, &hilight); + + cairo_translate (cr, x, y); + + cairo_move_to (cr, params->xthickness + 0.5, (height/2) + 0.5); + cairo_line_to (cr, width-params->xthickness - 0.5, (height/2) + 0.5); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + cairo_move_to (cr, params->xthickness + 0.5, (height/2)+1.5); + cairo_line_to (cr, width-params->xthickness - 0.5, (height/2)+1.5); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); +} + +static void +clearlooks_draw_spinbutton_down (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + cairo_pattern_t *pattern; + double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0)); + CairoColor shadow; + ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 0.8, &shadow); + + cairo_translate (cr, x+1, y+1); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-4, height-4, radius, params->corners); + + ge_cairo_set_color (cr, &colors->bg[params->state_type]); + + cairo_fill_preserve (cr); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shadow.r, shadow.g, shadow.b); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); - color = cl_get_gradient_corner_color (r, corner); - gdk_gc_get_values (r->bordergc, &values); + cairo_set_source (cr, pattern); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); +} - if (color == NULL) - { - tmp = values.foreground; - gdk_colormap_query_color (gtk_widget_get_colormap(widget), values.foreground.pixel, &tmp); - color = &tmp; - } +static void +clearlooks_scale_draw_gradient (cairo_t *cr, + const CairoColor *c1, + const CairoColor *c2, + const CairoColor *c3, + int x, int y, int width, int height, + boolean horizontal) +{ + cairo_pattern_t *pattern; - bgcolor = get_parent_bgcolor(widget); + pattern = cairo_pattern_create_linear (0, 0, horizontal ? 0 : width, horizontal ? height : 0); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, c1->r, c1->g, c1->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, c2->r, c2->g, c2->b); - if (bgcolor == NULL) - { - bgcolor = color; - } + cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, c3); + ge_cairo_stroke_rectangle (cr, x, y, width, height); +} - blend (style->colormap, bgcolor, color, &aacolor, 70); +#define TROUGH_SIZE 6 +static void +clearlooks_draw_scale_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + int trough_width, trough_height; + double translate_x, translate_y; - if (r->corners[corner] == CL_CORNER_ROUND) + if (slider->horizontal) { - x1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width - 2; - - y1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height - 2; - - gdk_gc_set_foreground (r->bordergc, color); - gdk_draw_point (window, r->bordergc, x1, y1); + trough_width = width-3; + trough_height = TROUGH_SIZE-2; - gdk_gc_set_foreground (r->bordergc, &aacolor); + translate_x = x + 0.5; + translate_y = y + 0.5 + (height/2) - (TROUGH_SIZE/2); + } + else + { + trough_width = TROUGH_SIZE-2; + trough_height = height-3; - x1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width-2; + translate_x = x + 0.5 + (width/2) - (TROUGH_SIZE/2); + translate_y = y + 0.5; + } - y1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_TOPRIGHT) ? y : y+height-1; - - gdk_draw_point (window, r->bordergc, x1, y1); + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, translate_x, translate_y); + + if (!slider->fill_level) + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0); + + cairo_translate (cr, 1, 1); + + if (!slider->lower && ! slider->fill_level) + clearlooks_scale_draw_gradient (cr, &colors->shade[3], /* top */ + &colors->shade[2], /* bottom */ + &colors->shade[6], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal); + else + clearlooks_scale_draw_gradient (cr, &colors->spot[1], /* top */ + &colors->spot[0], /* bottom */ + &colors->spot[2], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal); +} + +static void +clearlooks_draw_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[params->disabled ? 4 : 6]; + const CairoColor *spot = &colors->spot[1]; + const CairoColor *fill = &colors->shade[2]; + double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0)); + + cairo_pattern_t *pattern; - x1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_BOTTOMLEFT) ? x : x+width-1; + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); - y1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height-2; + if (params->prelight) + border = &colors->spot[2]; - gdk_draw_point (window, r->bordergc, x1, y1); - + /* fill the widget */ + cairo_rectangle (cr, 0.5, 0.5, width-2, height-2); + + /* Fake light */ + if (!params->disabled) + { + const CairoColor *top = &colors->shade[0]; + const CairoColor *bot = &colors->shade[2]; + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, top->r, top->g, top->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bot->r, bot->g, bot->b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); } - else if (r->corners[corner] == CL_CORNER_NARROW) + else { - x1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_BOTTOMLEFT) ? x : x+width-1; + ge_cairo_set_color (cr, fill); + cairo_rectangle (cr, 0.5, 0.5, width-2, height-2); + cairo_fill (cr); + } - y1 = (corner == CL_CORNER_TOPLEFT || - corner == CL_CORNER_TOPRIGHT) ? y : y+height-1; - - gdk_gc_set_foreground (r->bordergc, &aacolor); - gdk_draw_point (window, r->bordergc, x1, y1); - } + /* Set the clip */ + cairo_save (cr); + cairo_rectangle (cr, 0.5, 0.5, 6, height-2); + cairo_rectangle (cr, width-7.5, 0.5, 6 , height-2); + cairo_clip_preserve (cr); - gdk_gc_set_foreground (r->bordergc, &values.foreground); -} + cairo_new_path (cr); -static void cl_draw_fill (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r) -{ - if (r->gradient_type == CL_GRADIENT_NONE || - r->fill_gradient.from == NULL || r->fill_gradient.to == NULL) + /* Draw the handles */ + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners); + pattern = cairo_pattern_create_linear (0.5, 0.5, 0.5, 0.5+height); + + if (params->prelight) { - gdk_draw_rectangle (window, r->fillgc, TRUE, - x+1, y+1, width-2, height-2); + CairoColor highlight; + ge_shade_color (spot, 1.5, &highlight); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, highlight.r, highlight.g, highlight.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, spot->r, spot->g, spot->b); + cairo_set_source (cr, pattern); } - else if (r->gradient_type == CL_GRADIENT_HORIZONTAL) + else { - draw_vgradient (window, r->fillgc, gtk_widget_get_style(widget), - x+1, y+1, width-2, height-2, - r->fill_gradient.from, r->fill_gradient.to); + CairoColor hilight; + ge_shade_color (fill, 1.5, &hilight); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); } - else if (r->gradient_type == CL_GRADIENT_VERTICAL) + + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); + + /* Draw the border */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + if (params->prelight || params->disabled) + ge_cairo_set_color (cr, border); + else + clearlooks_set_border_gradient (cr, border, 1.2, 0, height); + cairo_stroke (cr); + + /* Draw handle lines */ + if (width > 14) { - draw_hgradient (window, r->fillgc, gtk_widget_get_style(widget), - x+1, y+1, width-2, height-2, - r->fill_gradient.from, r->fill_gradient.to); + cairo_move_to (cr, 6, 0.5); + cairo_line_to (cr, 6, height-1); + + cairo_move_to (cr, width-7, 0.5); + cairo_line_to (cr, width-7, height-1); + + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba (cr, border->r, + border->g, + border->b, + 0.3); + cairo_stroke (cr); } } -void cl_rectangle_set_button(CLRectangle *r, GtkStyle *style, - GtkStateType state_type, gboolean has_default, - gboolean has_focus, - CLBorderType tl, CLBorderType tr, - CLBorderType bl, CLBorderType br) +static void +clearlooks_draw_slider_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0; - GdkGC *border_gc = clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type]; + double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + cairo_set_line_width (cr, 1.0); - - cl_rectangle_init (r, style->bg_gc[state_type], - clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type], - tl, tr, bl, br); + if (!slider->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + cairo_translate (cr, x+0.5, y+0.5); + + params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1); + params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2); + + if (width > 24) + params->style_functions->draw_gripdots (cr, colors, 0, 0, width-2, height-2, 3, 3, 0); +} + +static void +clearlooks_draw_progressbar_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[6]; + CairoColor shadow; + cairo_pattern_t *pattern; + double radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0)); + + cairo_save (cr); + + cairo_set_line_width (cr, 1.0); + + /* Fill with bg color */ + ge_cairo_set_color (cr, &colors->bg[params->state_type]); + + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + + /* Create trough box */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + ge_cairo_set_color (cr, &colors->shade[3]); + cairo_fill (cr); + + /* Draw border */ + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width-1, height-1, radius, params->corners); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + /* clip the corners of the shadows */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + cairo_clip (cr); + + ge_shade_color (border, 0.925, &shadow); + + /* Top shadow */ + cairo_rectangle (cr, x+1, y+1, width-2, 4); + pattern = cairo_pattern_create_linear (x, y, x, y+4); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Left shadow */ + cairo_rectangle (cr, x+1, y+1, 4, height-2); + pattern = cairo_pattern_create_linear (x, y, x+4, y); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); +} - if (state_type != GTK_STATE_INSENSITIVE && !has_default) +static void +clearlooks_draw_progressbar_fill (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ProgressBarParameters *progressbar, + int x, int y, int width, int height, + gint offset) +{ + boolean is_horizontal = progressbar->orientation < 2; + double tile_pos = 0; + double stroke_width; + double radius; + int x_step; + + cairo_pattern_t *pattern; + CairoColor bg_shade; + CairoColor border; + CairoColor shadow; + + radius = MAX (0, params->radius - params->xthickness); + + cairo_save (cr); + + if (!is_horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + if ((progressbar->orientation == CL_ORIENTATION_RIGHT_TO_LEFT) || (progressbar->orientation == CL_ORIENTATION_BOTTOM_TO_TOP)) + ge_cairo_mirror (cr, CR_MIRROR_HORIZONTAL, &x, &y, &width, &height); + + /* Clamp the radius so that the _height_ fits ... */ + radius = MIN (radius, height / 2.0); + + stroke_width = height*2; + x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */ + + cairo_translate (cr, x, y); + + cairo_save (cr); + /* This is kind of nasty ... Clip twice from each side in case the length + * of the fill is smaller than twice the radius. */ + ge_cairo_rounded_rectangle (cr, 0, 0, width + radius, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + /* Draw the background gradient */ + ge_shade_color (&colors->spot[1], 1.1, &bg_shade); + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, bg_shade.r, bg_shade.g, bg_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.6, colors->spot[1].r, colors->spot[1].g, colors->spot[1].b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bg_shade.r, bg_shade.g, bg_shade.b); + cairo_set_source (cr, pattern); + cairo_paint (cr); + cairo_pattern_destroy (pattern); + + /* Draw the Strokes */ + while (tile_pos <= width+x_step) { - cl_rectangle_set_gradient (&r->border_gradient, - &clearlooks_style->border[CL_BORDER_UPPER+my_state_type], - &clearlooks_style->border[CL_BORDER_LOWER+my_state_type]); + cairo_move_to (cr, stroke_width/2-x_step, 0); + cairo_line_to (cr, stroke_width-x_step, 0); + cairo_line_to (cr, stroke_width/2-x_step, height); + cairo_line_to (cr, -x_step, height); + + cairo_translate (cr, stroke_width, 0); + tile_pos += stroke_width; } - else if (has_default) - r->bordergc = style->black_gc; + + cairo_set_source_rgba (cr, colors->spot[2].r, + colors->spot[2].g, + colors->spot[2].b, + 0.15); + + cairo_fill (cr); + cairo_restore (cr); /* rounded clip region */ + + /* inner highlight border + * This is again kinda ugly. Draw once from each side, clipping away the other. */ + cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.5); + + /* left side */ + cairo_save (cr); + cairo_rectangle (cr, 0, 0, width / 2, height); + cairo_clip (cr); + + if (progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); else - r->bordergc = clearlooks_style->shade_gc[4]; + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); - r->gradient_type = CL_GRADIENT_VERTICAL; + cairo_stroke (cr); + cairo_restore (cr); /* clip */ - r->topleft = (state_type != GTK_STATE_ACTIVE) ? style->light_gc[state_type] : clearlooks_style->shade_gc[4]; - r->bottomright = (state_type != GTK_STATE_ACTIVE) ? clearlooks_style->shade_gc[1] : NULL; - - shade (&style->bg[state_type], &r->tmp_color, 0.93); + /* right side */ + cairo_save (cr); + cairo_rectangle (cr, width / 2, 0, (width+1) / 2, height); + cairo_clip (cr); + + if (progressbar->value < 1.0 || progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, -1.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + else + ge_cairo_rounded_rectangle (cr, -0.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + + /* Draw the dark lines and the shadow */ + cairo_save (cr); + /* Again, this weird clip area. */ + ge_cairo_rounded_rectangle (cr, -1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius - 1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + border = colors->spot[2]; + border.a = 0.5; + shadow.r = 0.0; + shadow.g = 0.0; + shadow.b = 0.0; + shadow.a = 0.1; + + if (progressbar->pulsing) + { + /* At the beginning of the bar. */ + cairo_move_to (cr, 0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, 0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, -0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, -0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, -0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + if (progressbar->value < 1.0 || progressbar->pulsing) + { + /* At the end of the bar. */ + cairo_move_to (cr, width - 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width - 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width - 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, width + 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width + 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width + 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + cairo_restore (cr); - cl_rectangle_set_gradient (&r->fill_gradient, - &style->bg[state_type], - &r->tmp_color); + cairo_restore (cr); /* rotation, mirroring */ } -void cl_rectangle_set_entry (CLRectangle *r, GtkStyle *style, - GtkStateType state_type, - CLBorderType tl, CLBorderType tr, - CLBorderType bl, CLBorderType br, - gboolean has_focus) +static void +clearlooks_draw_optionmenu (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const OptionMenuParameters *optionmenu, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkGC *bordergc; - - if (has_focus) - bordergc = clearlooks_style->spot3_gc; - else if (state_type != GTK_STATE_INSENSITIVE) - bordergc = clearlooks_style->border_gc[CL_BORDER_LOWER]; - else - bordergc = clearlooks_style->shade_gc[3]; + SeparatorParameters separator; + int offset = params->ythickness + 1; - cl_rectangle_init (r, style->base_gc[state_type], bordergc, - tl, tr, bl, br); - - if (state_type != GTK_STATE_INSENSITIVE ) - r->topleft = (has_focus) ? clearlooks_style->spot1_gc - : style->bg_gc[GTK_STATE_NORMAL]; + params->style_functions->draw_button (cr, colors, params, x, y, width, height); - if (has_focus) - r->bottomright = clearlooks_style->spot1_gc; - else if (state_type == GTK_STATE_INSENSITIVE) - r->bottomright = style->base_gc[state_type]; + separator.horizontal = FALSE; + params->style_functions->draw_separator (cr, colors, params, &separator, x+optionmenu->linepos, y + offset, 2, height - offset*2); } -void cl_draw_shadow(GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r) +static void +clearlooks_draw_menu_item_separator (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SeparatorParameters *separator, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int x1, y1, x2, y2; + cairo_save (cr); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT); + ge_cairo_set_color (cr, &colors->shade[5]); - if (r->bottomright != NULL) - { - x1 = x+1+(r->corners[CL_CORNER_BOTTOMLEFT]/2); - y1 = y2 = y+height-2; - x2 = x+width - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2); - - gdk_draw_line (window, r->bottomright, x1, y1, x2, y2); - - x1 = x2 = x+width-2; - y1 = y+1+(r->corners[CL_CORNER_TOPRIGHT]/2); - y2 = y+height - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2); + if (separator->horizontal) + cairo_rectangle (cr, x, y, width, 1); + else + cairo_rectangle (cr, x, y, 1, height); - gdk_draw_line (window, r->bottomright, x1, y1, x2, y2); - } - - if (r->topleft != NULL) - { - x1 = x+1+(r->corners[CL_CORNER_TOPLEFT]/2); - y1 = y2 = y+1; - x2 = x+width-1-(1+r->corners[CL_CORNER_TOPRIGHT]/2); - - gdk_draw_line (window, r->topleft, x1, y1, x2, y2); - - x1 = x2 = x+1; - y1 = y+1+(r->corners[CL_CORNER_TOPLEFT]/2); - y2 = y+height-1-(1+r->corners[CL_CORNER_BOTTOMLEFT]/2); + cairo_fill (cr); - gdk_draw_line (window, r->topleft, x1, y1, x2, y2); - } + cairo_restore (cr); } -void cl_rectangle_set_color (CLGradient *g, GdkColor *color) +static void +clearlooks_draw_menubar0 (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const MenuBarParameters *menubar, + int x, int y, int width, int height) { - g->from = color; - g->to = color; +/* const CairoColor *light = &colors->shade[0]; */ + const CairoColor *dark = &colors->shade[3]; + + cairo_set_line_width (cr, 1); + cairo_translate (cr, x, y+0.5); + +/* cairo_move_to (cr, 0, 0); */ +/* cairo_line_to (cr, width, 0); */ +/* ge_cairo_set_color (cr, light); */ +/* cairo_stroke (cr); */ + + cairo_move_to (cr, 0, height-1); + cairo_line_to (cr, width, height-1); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); } -void cl_rectangle_set_gradient (CLGradient *g, GdkColor *from, GdkColor *to) +static void +clearlooks_draw_menubar2 (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const MenuBarParameters *menubar, + int x, int y, int width, int height) { - g->from = from; - g->to = to; + CairoColor lower; + cairo_pattern_t *pattern; + + ge_shade_color (&colors->bg[0], 0.96, &lower); + + cairo_translate (cr, x, y); + cairo_rectangle (cr, 0, 0, width, height); + + /* Draw the gradient */ + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, colors->bg[0].r, + colors->bg[0].g, + colors->bg[0].b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r, + lower.g, + lower.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Draw bottom line */ + cairo_set_line_width (cr, 1.0); + cairo_move_to (cr, 0, height-0.5); + cairo_line_to (cr, width, height-0.5); + ge_cairo_set_color (cr, &colors->shade[3]); + cairo_stroke (cr); } -void cl_rectangle_init (CLRectangle *r, - GdkGC *fillgc, GdkGC *bordergc, - int tl, int tr, int bl, int br) +static void +clearlooks_draw_menubar1 (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const MenuBarParameters *menubar, + int x, int y, int width, int height) { - r->gradient_type = CL_GRADIENT_NONE; - - r->border_gradient.from = r->border_gradient.to = NULL; - r->fill_gradient.from = r->fill_gradient.to = NULL; - - r->fillgc = fillgc; - r->bordergc = bordergc; - - r->topleft = NULL; - r->bottomright = NULL; - - r->corners[CL_CORNER_TOPLEFT] = tl; - r->corners[CL_CORNER_TOPRIGHT] = tr; - r->corners[CL_CORNER_BOTTOMLEFT] = bl; - r->corners[CL_CORNER_BOTTOMRIGHT] = br; + const CairoColor *border = &colors->shade[3]; + + clearlooks_draw_menubar2 (cr, colors, params, menubar, + x, y, width, height); + + ge_cairo_set_color (cr, border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); } -void cl_rectangle_set_corners (CLRectangle *r, int tl, int tr, int bl, int br) + +static menubar_draw_proto clearlooks_menubar_draw[3] = +{ + clearlooks_draw_menubar0, + clearlooks_draw_menubar1, + clearlooks_draw_menubar2 +}; + +static void +clearlooks_draw_menubar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const MenuBarParameters *menubar, + int x, int y, int width, int height) { - r->corners[CL_CORNER_TOPLEFT] = tl; - r->corners[CL_CORNER_TOPRIGHT] = tr; - r->corners[CL_CORNER_BOTTOMLEFT] = bl; - r->corners[CL_CORNER_BOTTOMRIGHT] = br; + if (menubar->style < 0 || menubar->style > 3) + return; + + clearlooks_menubar_draw[menubar->style](cr, colors, params, menubar, + x, y, width, height); } -void cl_set_corner_sharpness (const gchar *detail, GtkWidget *widget, CLRectangle *r) +static void +clearlooks_get_frame_gap_clip (int x, int y, int width, int height, + const FrameParameters *frame, + ClearlooksRectangle *bevel, + ClearlooksRectangle *border) { - if (widget->parent && GTK_IS_COMBO_BOX_ENTRY (widget->parent) || GTK_IS_COMBO (widget->parent)) + if (frame->gap_side == CL_GAP_TOP) { - gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL; - int cl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE; - int cr = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND; - - cl_rectangle_set_corners (r, cl, cr, cl, cr); + CLEARLOOKS_RECTANGLE_SET ((*bevel), 1.5 + frame->gap_x, -0.5, + frame->gap_width - 3, 2.0); + CLEARLOOKS_RECTANGLE_SET ((*border), 0.5 + frame->gap_x, -0.5, + frame->gap_width - 2, 2.0); } - else if (detail && !strcmp (detail, "spinbutton_up")) + else if (frame->gap_side == CL_GAP_BOTTOM) { - gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL; - int tl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE; - int tr = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND; - - cl_rectangle_set_corners (r, tl, tr, - CL_CORNER_NONE, CL_CORNER_NONE); + CLEARLOOKS_RECTANGLE_SET ((*bevel), 1.5 + frame->gap_x, height - 2.5, + frame->gap_width - 3, 2.0); + CLEARLOOKS_RECTANGLE_SET ((*border), 0.5 + frame->gap_x, height - 1.5, + frame->gap_width - 2, 2.0); } - else if (detail && !strcmp (detail, "spinbutton_down")) + else if (frame->gap_side == CL_GAP_LEFT) { - gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL; - int bl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE; - int br = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND; - - cl_rectangle_set_corners (r, CL_CORNER_NONE, CL_CORNER_NONE, - bl, br); + CLEARLOOKS_RECTANGLE_SET ((*bevel), -0.5, 1.5 + frame->gap_x, + 2.0, frame->gap_width - 3); + CLEARLOOKS_RECTANGLE_SET ((*border), -0.5, 0.5 + frame->gap_x, + 1.0, frame->gap_width - 2); } - else + else if (frame->gap_side == CL_GAP_RIGHT) { - cl_rectangle_set_corners (r, CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); - }; + CLEARLOOKS_RECTANGLE_SET ((*bevel), width - 2.5, 1.5 + frame->gap_x, + 2.0, frame->gap_width - 3); + CLEARLOOKS_RECTANGLE_SET ((*border), width - 1.5, 0.5 + frame->gap_x, + 1.0, frame->gap_width - 2); + } } -void cl_rectangle_set_clip_rectangle (CLRectangle *r, GdkRectangle *area) +static void +clearlooks_draw_frame (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const FrameParameters *frame, + int x, int y, int width, int height) { - if (area == NULL) + const CairoColor *border = frame->border; + const CairoColor *dark = (CairoColor*)&colors->shade[4]; + ClearlooksRectangle bevel_clip = {0, 0, 0, 0}; + ClearlooksRectangle frame_clip = {0, 0, 0, 0}; + double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + CairoColor hilight; + + ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 1.05, &hilight); + + if (frame->shadow == CL_SHADOW_NONE) return; - if (r->fillgc) - gdk_gc_set_clip_rectangle (r->fillgc, area); + if (frame->gap_x != -1) + clearlooks_get_frame_gap_clip (x, y, width, height, + frame, &bevel_clip, &frame_clip); + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y+0.5); + + /* save everything */ + cairo_save (cr); + /* Set clip for the bevel */ + if (frame->gap_x != -1) + { + /* Set clip for gap */ + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_rectangle (cr, -0.5, -0.5, width, height); + cairo_rectangle (cr, bevel_clip.x, bevel_clip.y, bevel_clip.width, bevel_clip.height); + cairo_clip (cr); + } + + /* Draw the bevel */ + if (frame->shadow == CL_SHADOW_ETCHED_IN || frame->shadow == CL_SHADOW_ETCHED_OUT) + { + ge_cairo_set_color (cr, &hilight); + if (frame->shadow == CL_SHADOW_ETCHED_IN) + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, params->corners); + else + ge_cairo_rounded_rectangle (cr, 0, 0, width-2, height-2, radius, params->corners); + cairo_stroke (cr); + } + else if (frame->shadow != CL_SHADOW_NONE) + { + ShadowParameters shadow; + shadow.corners = params->corners; + shadow.shadow = frame->shadow; + clearlooks_draw_highlight_and_shade (cr, colors, &shadow, width, height, 0); + } - if (r->bordergc) - gdk_gc_set_clip_rectangle (r->bordergc, area); + /* restore the previous clip region */ + cairo_restore (cr); + cairo_save (cr); + if (frame->gap_x != -1) + { + /* Set clip for gap */ + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_rectangle (cr, -0.5, -0.5, width, height); + cairo_rectangle (cr, frame_clip.x, frame_clip.y, frame_clip.width, frame_clip.height); + cairo_clip (cr); + } - if (r->topleft) - gdk_gc_set_clip_rectangle (r->topleft, area); + /* Draw frame */ + if (frame->shadow == CL_SHADOW_ETCHED_IN || frame->shadow == CL_SHADOW_ETCHED_OUT) + { + ge_cairo_set_color (cr, dark); + if (frame->shadow == CL_SHADOW_ETCHED_IN) + ge_cairo_rounded_rectangle (cr, 0, 0, width-2, height-2, radius, params->corners); + else + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, params->corners); + } + else + { + ge_cairo_set_color (cr, border); + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + } + cairo_stroke (cr); - if (r->bottomright) - gdk_gc_set_clip_rectangle (r->bottomright, area); + cairo_restore (cr); } -void cl_rectangle_reset_clip_rectangle (CLRectangle *r) +static void +clearlooks_draw_tab (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const TabParameters *tab, + int x, int y, int width, int height) { - if (r->fillgc) - gdk_gc_set_clip_rectangle (r->fillgc, NULL); + const CairoColor *border1 = &colors->shade[6]; + const CairoColor *border2 = &colors->shade[5]; + const CairoColor *stripe_fill = &colors->spot[1]; + const CairoColor *stripe_border = &colors->spot[2]; + const CairoColor *fill; + CairoColor hilight; + + cairo_pattern_t *pattern; - if (r->bordergc) - gdk_gc_set_clip_rectangle (r->bordergc, NULL); + double radius; + double strip_size; - if (r->topleft) - gdk_gc_set_clip_rectangle (r->topleft, NULL); + radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); - if (r->bottomright) - gdk_gc_set_clip_rectangle (r->bottomright, NULL); -} + /* Set clip */ + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + cairo_new_path (cr); -void cl_rectangle_reset (CLRectangle *r, GtkStyle *style) -{ - cl_rectangle_init (r, - NULL, NULL, - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); -} + /* Translate and set line width */ + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y+0.5); -static void cl_progressbar_points_transform (GdkPoint *points, int npoints, - int offset, gboolean is_horizontal) -{ - int i; - for ( i=0; i<npoints; i++) { - if ( is_horizontal ) - points[i].x += offset; - else - points[i].y += offset; + + /* Make the tabs slightly bigger than they should be, to create a gap */ + /* And calculate the strip size too, while you're at it */ + if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM) + { + height += 3.0; + strip_size = 2.0/height; /* 2 pixel high strip */ + + if (tab->gap_side == CL_GAP_TOP) + cairo_translate (cr, 0.0, -3.0); /* gap at the other side */ } -} + else + { + width += 3.0; + strip_size = 2.0/width; + + if (tab->gap_side == CL_GAP_LEFT) + cairo_translate (cr, -3.0, 0.0); /* gap at the other side */ + } + + /* Set the fill color */ + fill = &colors->bg[params->state_type]; -GdkPixmap* cl_progressbar_tile_new (GdkDrawable *drawable, GtkWidget *widget, - GtkStyle *style, gint height, gint offset) -{ - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int width = height; - int line = 0; - int center = width/2; - int xdir = 1; - int trans; + /* Set tab shape */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, + radius, params->corners); + + /* Draw fill */ + ge_cairo_set_color (cr, fill); + cairo_fill (cr); - int stripe_width = height/2; - int topright = height + stripe_width; - int topright_div_2 = topright/2; - double shift; - GdkPoint points[4]; + ge_shade_color (fill, 1.3, &hilight); - GtkProgressBarOrientation orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget)); - gboolean is_horizontal = (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || orientation == GTK_PROGRESS_RIGHT_TO_LEFT) ? 1 : 0; + /* Draw highlight */ + if (!params->active) + { + ShadowParameters shadow; + + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = params->corners; + + clearlooks_draw_highlight_and_shade (cr, colors, &shadow, + width, + height, radius); + } - GdkPixmap *tmp = gdk_pixmap_new (widget->window, width, height, -1); - GdkColor tmp_color; - shade (&clearlooks_style->spot2, &tmp_color, 0.90); - - if (is_horizontal) - draw_hgradient (tmp, style->black_gc, style, 0, 0, width, height, - &clearlooks_style->spot2, &tmp_color ); - else - draw_vgradient (tmp, style->black_gc, style, 0, 0, width, height, - &tmp_color, &clearlooks_style->spot2); /* TODO: swap for RTL */ - - if (orientation == GTK_PROGRESS_RIGHT_TO_LEFT || - orientation == GTK_PROGRESS_BOTTOM_TO_TOP) + if (params->active) { - offset = -offset; - xdir = -1; + CairoColor shadow; + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-1 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 1, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0 ); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + ge_shade_color (fill, 0.92, &shadow); + + cairo_pattern_add_color_stop_rgba (pattern, 0.0, hilight.r, hilight.g, hilight.b, 0.4); + cairo_pattern_add_color_stop_rgba (pattern, 1.0/height, hilight.r, hilight.g, hilight.b, 0.4); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, fill->r,fill->g,fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shadow.r,shadow.g,shadow.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); } + else + { + /* Draw shade */ + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-2 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 0, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0 ); - if (get_direction (widget) == GTK_TEXT_DIR_RTL) - offset = -offset; + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_fill->r, stripe_fill->g, stripe_fill->b); + cairo_pattern_add_color_stop_rgba (pattern, strip_size, hilight.r, hilight.g, hilight.b, 0.5); + cairo_pattern_add_color_stop_rgba (pattern, 0.8, hilight.r, hilight.g, hilight.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); - if (is_horizontal) + if (params->active) { - points[0] = (GdkPoint){xdir*(topright - stripe_width - topright_div_2), 0}; /* topleft */ - points[1] = (GdkPoint){xdir*(topright - topright_div_2), 0}; /* topright */ - points[2] = (GdkPoint){xdir*(stripe_width - topright_div_2), height}; /* bottomright */ - points[3] = (GdkPoint){xdir*(-topright_div_2), height}; /* bottomleft */ + ge_cairo_set_color (cr, border2); + cairo_stroke (cr); } else { - points[0] = (GdkPoint){height, xdir*(topright - stripe_width - topright_div_2)}; /* topleft */ - points[1] = (GdkPoint){height, xdir*(topright - topright_div_2)}; /* topright */ - points[2] = (GdkPoint){0, xdir*(stripe_width - topright_div_2)}; /* bottomright */ - points[3] = (GdkPoint){0, xdir*(-topright_div_2)}; /* bottomleft */ - } - - - shift = (stripe_width*2)/(double)10; - cl_progressbar_points_transform (points, 4, (offset*shift), is_horizontal); + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-2 : 2, + tab->gap_side == CL_GAP_TOP ? height-2 : 2, + tab->gap_side == CL_GAP_RIGHT ? width : 2, + tab->gap_side == CL_GAP_BOTTOM ? height : 2 ); - trans = (width/2)-1-(stripe_width*2); - cl_progressbar_points_transform (points, 4, trans, is_horizontal); - gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4); - cl_progressbar_points_transform (points, 4, -trans, is_horizontal); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, border1->r, border1->g, border1->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, border2->r, border2->g, border2->b); + cairo_set_source (cr, pattern); + cairo_stroke (cr); + cairo_pattern_destroy (pattern); + } +} - trans = width/2-1; - cl_progressbar_points_transform (points, 4, trans, is_horizontal); - gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4); - cl_progressbar_points_transform (points, 4, -trans, is_horizontal); +static void +clearlooks_draw_separator (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SeparatorParameters *separator, + int x, int y, int width, int height) +{ + CairoColor color = colors->shade[3]; + CairoColor hilight; + ge_shade_color (&color, 1.4, &hilight); - trans = (width/2)-1+(stripe_width*2); - cl_progressbar_points_transform (points, 4, trans, is_horizontal); - gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4); - - return tmp; + cairo_save (cr); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT); + + if (separator->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, 0.0); + ge_cairo_set_color (cr, &color); + cairo_stroke (cr); + + cairo_move_to (cr, 0.0, 1.0); + cairo_line_to (cr, width, 1.0); + ge_cairo_set_color (cr, &hilight); + 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); + ge_cairo_set_color (cr, &color); + cairo_stroke (cr); + + cairo_move_to (cr, 1.0, 0.0); + cairo_line_to (cr, 1.0, height); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); + } + + cairo_restore (cr); } -/* could be improved, I think. */ -void cl_progressbar_fill (GdkDrawable *drawable, GtkWidget *widget, - GtkStyle *style, GdkGC *gc, - gint x, gint y, - gint width, gint height, - guint8 offset, GdkRectangle *area) +static void +clearlooks_draw_list_view_header (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ListViewHeaderParameters *header, + int x, int y, int width, int height) { - GtkProgressBarOrientation orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget)); - gint size = (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || orientation == GTK_PROGRESS_RIGHT_TO_LEFT) ? height : width; - GdkPixmap *tile = cl_progressbar_tile_new (widget->window, widget, style, size, offset); + const CairoColor *border = &colors->shade[5]; + cairo_pattern_t *pattern; + CairoColor hilight; + CairoColor shadow; - gint nx = x, - ny = y, - nwidth = height, - nheight = width; - - gdk_gc_set_clip_rectangle (gc, area); + ge_shade_color (border, 1.5, &hilight); + ge_shade_color (border, 0.925, &shadow); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); - switch (orientation) + /* Draw highlight */ + if (header->order == CL_ORDER_FIRST) { - case GTK_PROGRESS_LEFT_TO_RIGHT: - { - while (nx <= x + width ) - { - if (nx + nwidth > x+width ) nwidth = (x+width) - nx; - gdk_draw_drawable (drawable, gc, tile, 0, 0, nx, y, nwidth, height); - if (height <= 1) - nx += 1; - else - nx += (height-1 + !(height % 2)); - } - break; - } - case GTK_PROGRESS_RIGHT_TO_LEFT: - { - gint src_x = 0, dst_x; - nx += width; - while (nx >= x ) - { - dst_x = nx - height; - if (dst_x < x ) - { - src_x = x - dst_x; - dst_x = x; - } - gdk_draw_drawable (drawable, gc, tile, src_x, 0, dst_x, y, nwidth, height); - if (height <= 1) - nx -= 1; - else - nx -= (height-1 + !(height % 2)); - } - break; - } - case GTK_PROGRESS_TOP_TO_BOTTOM: - { - while (ny <= y + height ) - { - if (ny + nheight > y+height ) nheight = (y+height) - ny; - gdk_draw_drawable (drawable, gc, tile, 0, 0, x, ny, width, nheight); - if (width <= 1) - ny += 1; - else - ny += (width-1 + !(width % 2)); - } - break; - } - case GTK_PROGRESS_BOTTOM_TO_TOP: - { - gint src_y = 0, dst_y; - ny += height; - while (ny >= y ) - { - dst_y = ny - width; - if (dst_y < y ) - { - src_y = y - dst_y; - dst_y = y; - } - gdk_draw_drawable (drawable, gc, tile, 0, src_y, x, dst_y, width, width); - if (width <= 1) - ny -= 1; - else - ny -= (width-1 + !(width % 2)); - } - break; - } + cairo_move_to (cr, 0.5, height-1); + cairo_line_to (cr, 0.5, 0.5); } + else + cairo_move_to (cr, 0.0, 0.5); + + cairo_line_to (cr, width, 0.5); - gdk_gc_set_clip_rectangle (gc, NULL); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); + + /* Draw bottom border */ + cairo_move_to (cr, 0.0, height-0.5); + cairo_line_to (cr, width, height-0.5); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + /* Draw bottom shade */ + pattern = cairo_pattern_create_linear (0.0, height-5.0, 0.0, height-1.0); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.3); + + cairo_rectangle (cr, 0.0, height-5.0, width, 4.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); - g_object_unref (tile); + /* Draw resize grip */ + if ((params->ltr && header->order != CL_ORDER_LAST) || + (!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable) + { + SeparatorParameters separator; + separator.horizontal = FALSE; + + if (params->ltr) + params->style_functions->draw_separator (cr, colors, params, &separator, + width-1.5, 4.0, 2, height-8.0); + else + params->style_functions->draw_separator (cr, colors, params, &separator, + 1.5, 4.0, 2, height-8.0); + } } -GdkColor cl_gc_set_fg_color_shade (GdkGC *gc, GdkColormap *colormap, - GdkColor *from, gfloat s) +/* We can't draw transparent things here, since it will be called on the same + * surface multiple times, when placed on a handlebox_bin or dockitem_bin */ +static void +clearlooks_draw_toolbar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ToolbarParameters *toolbar, + int x, int y, int width, int height) { - GdkColor tmp_color; - GdkGCValues values; - - shade (from, &tmp_color, s); - gdk_gc_get_values (gc, &values); - gdk_rgb_find_color (colormap, &tmp_color); - gdk_gc_set_foreground (gc, &tmp_color); + const CairoColor *fill = &colors->bg[GTK_STATE_NORMAL]; + const CairoColor *dark = &colors->shade[3]; + CairoColor light; + ge_shade_color (fill, 1.1, &light); - return values.foreground; + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + ge_cairo_set_color (cr, fill); + cairo_paint (cr); + + if (!toolbar->topmost) + { + /* Draw highlight */ + cairo_move_to (cr, 0, 0.5); + cairo_line_to (cr, width-1, 0.5); + ge_cairo_set_color (cr, &light); + cairo_stroke (cr); + } + + /* Draw shadow */ + cairo_move_to (cr, 0, height-0.5); + cairo_line_to (cr, width-1, height-0.5); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); } -/* #warning MOVE THIS TO SUPPORT.C/H SO THE DRAW_CORNER FUNCTION CAN USE IT. OR, MAKE DRAW_CORNER USE IT SOME OTHER WAY. */ +static void +clearlooks_draw_menuitem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + CairoColor fill_shade; + CairoColor border = colors->spot[2]; + cairo_pattern_t *pattern; + + ge_shade_color (&border, 1.05, &border); + ge_shade_color (fill, 0.85, &fill_shade); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, widget->radius, widget->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, fill_shade.r, fill_shade.g, fill_shade.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); -static void cl_get_window_style_state (GtkWidget *widget, GtkStyle **style, GtkStateType *state_type) + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); +} + +static void +clearlooks_draw_menubaritem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) { - GtkStyle *windowstyle = NULL; - GtkWidget *tmpwidget = widget; - GtkStateType windowstate; + const CairoColor *fill = &colors->spot[1]; + CairoColor fill_shade; + CairoColor border = colors->spot[2]; + cairo_pattern_t *pattern; - if (widget && GTK_IS_ENTRY (widget)) - tmpwidget = tmpwidget->parent; + ge_shade_color (&border, 1.05, &border); + ge_shade_color (fill, 0.85, &fill_shade); - while (tmpwidget && GTK_WIDGET_NO_WINDOW (tmpwidget) && !GTK_IS_NOTEBOOK(tmpwidget)) - { - tmpwidget = tmpwidget->parent; - } + cairo_set_line_width (cr, 1.0); + ge_cairo_rounded_rectangle (cr, x + 0.5, y + 0.5, width - 1, height, widget->radius, widget->corners); - *style = tmpwidget->style; - *state_type = GTK_WIDGET_STATE(tmpwidget); + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, fill_shade.r, fill_shade.g, fill_shade.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, &border); + cairo_stroke_preserve (cr); } -static GdkGC *cl_get_window_bg_gc (GtkWidget *widget) +static void +clearlooks_draw_selected_cell (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) { - GtkStyle *style; - GtkStateType state_type; + CairoColor upper_color; + CairoColor lower_color; + CairoColor border; + cairo_pattern_t *pattern; + cairo_save (cr); - cl_get_window_style_state (widget, &style, &state_type); + cairo_translate (cr, x, y); + + if (params->focus) + upper_color = colors->base[params->state_type]; + else + upper_color = colors->base[GTK_STATE_ACTIVE]; + + ge_shade_color(&upper_color, 0.92, &lower_color); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, upper_color.r, + upper_color.g, + upper_color.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower_color.r, + lower_color.g, + lower_color.b); + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); - return style->bg_gc[state_type]; + ge_shade_color(&upper_color, 0.8, &border); + + cairo_move_to (cr, 0, 0.5); + cairo_rel_line_to (cr, width, 0); + cairo_move_to (cr, 0, height-0.5); + cairo_rel_line_to (cr, width, 0); + + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_restore (cr); } -/****************************************************************************** - * DRAW THE MIGHTY WIDGETS! * - ******************************************************************************/ -void cl_draw_inset (GtkStyle *style, GdkWindow *window, GtkWidget *widget, - GdkRectangle *area, - gint x, gint y, gint width, gint height, - int tl, int tr, int bl, int br ) +static void +clearlooks_draw_scrollbar_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style); - ClearlooksStyle *clwindowstyle; /* style of the window this widget is on */ - GtkStateType windowstate; - CLRectangle r; + const CairoColor *bg = &colors->shade[2]; + const CairoColor *border = &colors->shade[5]; + CairoColor bg_shade; + cairo_pattern_t *pattern; + + ge_shade_color (bg, 0.95, &bg_shade); + + cairo_set_line_width (cr, 1); + /* cairo_translate (cr, x, y); */ + + if (scrollbar->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x, y); + + /* Draw fill */ + cairo_rectangle (cr, 1, 0, width-2, height); + ge_cairo_set_color (cr, bg); + cairo_fill (cr); + + /* Draw shadow */ + pattern = cairo_pattern_create_linear (1, 0, 3, 0); + cairo_pattern_add_color_stop_rgb (pattern, 0, bg_shade.r, bg_shade.g, bg_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bg->r, bg->g, bg->b); + cairo_rectangle (cr, 1, 0, 4, height); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Draw border */ + ge_cairo_set_color (cr, border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); +} - cl_rectangle_init (&r, NULL, style->black_gc, - tl, tr, bl, br); - - r.gradient_type = CL_GRADIENT_VERTICAL; - - cl_get_window_style_state(widget, (GtkStyle**)&clwindowstyle, &windowstate); - - g_assert (clwindowstyle != NULL); +static void +clearlooks_draw_scrollbar_stepper (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + const ScrollBarStepperParameters *stepper, + int x, int y, int width, int height) +{ + CairoCorners corners = CR_CORNER_NONE; + CairoColor border; + CairoColor s1, s2, s3, s4; + cairo_pattern_t *pattern; + ShadowParameters shadow; + double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + ge_shade_color(&colors->shade[6], 1.05, &border); - if (GTK_WIDGET_HAS_DEFAULT (widget)) + if (scrollbar->horizontal) { - r.bordergc = style->mid_gc[GTK_STATE_NORMAL]; + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; } else { - cl_rectangle_set_gradient (&r.border_gradient, - &clwindowstyle->inset_dark[windowstate], - &clwindowstyle->inset_light[windowstate]); + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT; } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners); + + if (scrollbar->horizontal) + pattern = cairo_pattern_create_linear (0, 0, 0, height); + else + pattern = cairo_pattern_create_linear (0, 0, width, 0); + + s2 = colors->bg[widget->state_type]; + ge_shade_color(&s2, 1.06, &s1); + ge_shade_color(&s2, 0.98, &s3); + ge_shade_color(&s2, 0.94, &s4); + + cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.7, s3.r, s3.g, s3.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, s4.r, s4.g, s4.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_translate (cr, 0.5, 0.5); + clearlooks_draw_top_left_highlight (cr, &s2, widget, width, height, (stepper->stepper == CL_STEPPER_A) ? radius : 0); + cairo_translate (cr, -0.5, -0.5); + + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners); + clearlooks_set_border_gradient (cr, &border, 1.2, (scrollbar->horizontal ? 0 : width), (scrollbar->horizontal ? height: 0)); + cairo_stroke (cr); + + cairo_translate (cr, 0.5, 0.5); + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = corners; + /* + clearlooks_draw_highlight_and_shade (cr, &shadow, + width, + height, params->radius);*/ } -/* Draw a normal (toggle)button. Not spinbuttons.*/ -void cl_draw_button(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) +static void +clearlooks_draw_scrollbar_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style); - int my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0; - GdkGC *bg_gc = NULL; - gboolean is_active = FALSE; - CLRectangle r; - - /* Get the background color of the window we're on */ - bg_gc = cl_get_window_bg_gc(widget); - - cl_rectangle_set_button (&r, style, state_type, - GTK_WIDGET_HAS_DEFAULT (widget), - GTK_WIDGET_HAS_FOCUS (widget), - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); - - if (state_type == GTK_STATE_ACTIVE) - is_active = TRUE; - - if (GTK_IS_TOGGLE_BUTTON(widget) && - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) && - state_type == GTK_STATE_PRELIGHT) + if (scrollbar->junction & CL_JUNCTION_BEGIN) { - cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->shade[1], &clearlooks_style->shade[1]); - r.topleft = clearlooks_style->shade_gc[3]; - r.bottomright = clearlooks_style->shade_gc[1]; - - is_active = TRUE; - } - - if (!is_active) - r.fillgc = NULL; - - if (!GTK_IS_NOTEBOOK (widget->parent)) - { - gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1); - - /* Draw "sunken" look when border thickness is more than 2 pixels. */ - if (style->xthickness > 2 && style->ythickness > 2) - cl_draw_inset (style, window, widget, area, x, y, width, height, - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); + if (scrollbar->horizontal) + { + x -= 1; + width += 1; + } + else + { + y -= 1; + height += 1; + } } - - /* Draw "sunken" look when border thickness is more than 2 pixels.*/ - if (style->xthickness > 2 && style->ythickness > 2) + if (scrollbar->junction & CL_JUNCTION_END) { - x++; - y++; - height-=2; - width-=2; + if (scrollbar->horizontal) + width += 1; + else + height += 1; } - /* Don't draw the normal gradient for normal buttons. */ + if (!scrollbar->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - - - if (!is_active) + cairo_translate (cr, x, y); + + if (scrollbar->has_color) { - int tmp_height = (float)height*0.25; - - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + const CairoColor *border = &colors->shade[7]; + CairoColor fill = scrollbar->color; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + if (widget->prelight) + ge_shade_color (&fill, 1.1, &fill); + + cairo_set_line_width (cr, 1); - draw_hgradient (window, style->bg_gc[state_type], style, - x+2,y+2,width-4,tmp_height, - &clearlooks_style->button_g1[state_type], - &clearlooks_style->button_g2[state_type]); + ge_shade_color (&fill, 1.3, &hilight); + ge_shade_color (&fill, 1.1, &shade1); + ge_shade_color (&fill, 1.05, &shade2); + ge_shade_color (&fill, 0.98, &shade3); - draw_hgradient (window, style->bg_gc[state_type], style, - x+2, y+2+tmp_height, width-4, height-3-tmp_height*2, - &clearlooks_style->button_g2[state_type], - &clearlooks_style->button_g3[state_type]); + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade3.r, shade3.g, shade3.b); + cairo_pattern_add_color_stop_rgb (pattern, 1, fill.r, fill.g, fill.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); - draw_hgradient (window, style->bg_gc[state_type], style, - x+2,y+height-tmp_height-1,width-4,tmp_height, - &clearlooks_style->button_g3[state_type], - &clearlooks_style->button_g4[state_type]); - - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); - } + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); -} - -/* Draw spinbuttons. */ -void cl_draw_spinbutton(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) -{ - CLRectangle r; - GdkRectangle new_area; - - int tl = CL_CORNER_NONE, tr = CL_CORNER_NONE, - bl = CL_CORNER_NONE, br = CL_CORNER_NONE; - - if (area == NULL) - { - new_area.x = x; - new_area.y = y; - new_area.width = width; - new_area.height = height; - area = &new_area; + ge_cairo_set_color (cr, border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); } - - if (!strcmp (detail, "spinbutton")) /* draws the 'back' of the spinbutton */ + else { - GdkGC *bg_gc = cl_get_window_bg_gc(widget); + const CairoColor *dark = &colors->shade[4]; + const CairoColor *light = &colors->shade[0]; + CairoColor border; + CairoColor s1, s2, s3, s4, s5; + cairo_pattern_t *pattern; + int bar_x, i; + + ge_shade_color(&colors->shade[6], 1.05, &border); - gdk_gc_set_clip_rectangle (bg_gc, area); - gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1); - gdk_gc_set_clip_rectangle (bg_gc, NULL); - - if (style->xthickness > 2 && style->ythickness > 2) - cl_draw_inset (style, window, widget, area, x, y, width, height, - CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); + s2 = colors->bg[widget->state_type]; + ge_shade_color(&s2, 1.06, &s1); + ge_shade_color(&s2, 0.98, &s3); + ge_shade_color(&s2, 0.94, &s4); + + pattern = cairo_pattern_create_linear(1, 1, 1, height-1); + cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.7, s3.r, s3.g, s3.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, s4.r, s4.g, s4.b); + + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source(cr, pattern); + cairo_fill(cr); + cairo_pattern_destroy(pattern); - return; - } - - if (!strcmp (detail, "spinbutton_up")) - { - tr = CL_CORNER_ROUND; + clearlooks_set_border_gradient (cr, &border, 1.2, 0, height); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); - (style->xthickness > 2 && style->ythickness > 2) ? y++ : height++; - } - - if (!strcmp (detail, "spinbutton_down")) - { - br = CL_CORNER_ROUND; + cairo_move_to (cr, 1.5, height-1.5); + cairo_line_to (cr, 1.5, 1.5); + cairo_line_to (cr, width-1.5, 1.5); + ge_shade_color (&s2, 1.3, &s5); + cairo_set_source_rgba (cr, s5.r, s5.g, s5.b, 0.5); + cairo_stroke(cr); + + /* draw handles */ + cairo_set_line_width (cr, 1); - if (style->xthickness > 2 && style->ythickness > 2) - height--; + bar_x = width/2 - 4; + cairo_translate(cr, 0.5, 0.5); + for (i=0; i<3; i++) + { + cairo_move_to (cr, bar_x, 4); + cairo_line_to (cr, bar_x, height-5); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); + + cairo_move_to (cr, bar_x+1, 4); + cairo_line_to (cr, bar_x+1, height-5); + ge_cairo_set_color (cr, light); + cairo_stroke (cr); + + bar_x += 3; + } } - cl_rectangle_set_button (&r, style, state_type, - GTK_WIDGET_HAS_DEFAULT (widget), - GTK_WIDGET_HAS_FOCUS (widget), - tl, tr, - bl, br); - width--; - - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); } -void cl_draw_combobox_entry (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) +static void +clearlooks_draw_statusbar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) { - CLRectangle r; + const CairoColor *dark = &colors->shade[3]; + CairoColor hilight; + + ge_shade_color (dark, 1.4, &hilight); + + cairo_set_line_width (cr, 1); + cairo_translate (cr, x, y+0.5); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, width, 0); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); + + cairo_translate (cr, 0, 1); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, width, 0); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); +} + +static void +clearlooks_draw_menu_frame (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[5]; + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); +/* + cairo_set_source_rgba (cr, colors->bg[0].r, colors->bg[0].g, colors->bg[0].b, 0.9); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); +*/ + ge_cairo_set_color (cr, border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); +} + +static void +clearlooks_draw_tooltip (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + CairoColor border; + + ge_shade_color (&colors->bg[widget->state_type], 0.6, &border); + + cairo_save (cr); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + ge_cairo_set_color (cr, &colors->bg[widget->state_type]); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + ge_cairo_set_color (cr, &border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); + + cairo_restore (cr); +} + +static void +clearlooks_draw_handle (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const HandleParameters *handle, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->bg[params->state_type]; + int num_bars = 6; /* shut up gcc warnings */ + int bar_spacing; - gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL; - gboolean has_focus = GTK_WIDGET_HAS_FOCUS (widget); + switch (handle->type) + { + case CL_HANDLE_TOOLBAR: + num_bars = 6; + bar_spacing = 3; + break; + case CL_HANDLE_SPLITTER: + num_bars = 16; + bar_spacing = 3; + break; + } + + if (params->prelight) + { + cairo_rectangle (cr, x, y, width, height); + ge_cairo_set_color (cr, fill); + cairo_fill (cr); + } - int cl = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND, - cr = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE; + cairo_translate (cr, x+0.5, y+0.5); - GdkGC *bg_gc = cl_get_window_bg_gc(widget); + cairo_set_line_width (cr, 1); - if (rtl) + if (handle->horizontal) { - if (!has_focus) - { - x -= 1; - width +=1; - } + params->style_functions->draw_gripdots (cr, colors, 0, 0, width, height, num_bars, 2, 0.1); } else { - width += 2; - if (has_focus) width--; /* this gives us a 2px focus line at the right side. */ + params->style_functions->draw_gripdots (cr, colors, 0, 0, width, height, 2, num_bars, 0.1); } +} + +static void +clearlooks_draw_resize_grip (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ResizeGripParameters *grip, + int x, int y, int width, int height) +{ + const CairoColor *dark = &colors->shade[4]; + CairoColor hilight; + int lx, ly; + int x_down; + int y_down; + int dots; - cl_rectangle_set_entry (&r, style, state_type, - cl, cr, cl, cr, - has_focus); + ge_shade_color (dark, 1.5, &hilight); - gdk_gc_set_clip_rectangle (bg_gc, area); - gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1); - gdk_gc_set_clip_rectangle (bg_gc, NULL); + /* The number of dots fitting into the area. Just hardcoded to 4 right now. */ + /* dots = MIN (width - 2, height - 2) / 3; */ + dots = 4; - /* Draw "sunken" look when border thickness is more than 2 pixels. */ - if (style->xthickness > 2 && style->ythickness > 2) + cairo_save (cr); + + switch (grip->edge) { - cl_draw_inset (style, window, widget, area, x, y, width, height, - cl, cr, cl, cr); + case CL_WINDOW_EDGE_NORTH_EAST: + x_down = 0; + y_down = 0; + cairo_translate (cr, x + width - 3*dots + 2, y + 1); + break; + case CL_WINDOW_EDGE_SOUTH_EAST: + x_down = 0; + y_down = 1; + cairo_translate (cr, x + width - 3*dots + 2, y + height - 3*dots + 2); + break; + case CL_WINDOW_EDGE_SOUTH_WEST: + x_down = 1; + y_down = 1; + cairo_translate (cr, x + 1, y + height - 3*dots + 2); + break; + case CL_WINDOW_EDGE_NORTH_WEST: + x_down = 1; + y_down = 0; + cairo_translate (cr, x + 1, y + 1); + break; + default: + /* Not implemented. */ + return; + } - y++; - x++; - width-=2; - height-=2; + for (lx = 0; lx < dots; lx++) /* horizontally */ + { + for (ly = 0; ly <= lx; ly++) /* vertically */ + { + int mx, my; + mx = x_down * dots + (1 - x_down * 2) * lx - x_down; + my = y_down * dots + (1 - y_down * 2) * ly - y_down; + + ge_cairo_set_color (cr, &hilight); + cairo_rectangle (cr, mx*3-1, my*3-1, 2, 2); + cairo_fill (cr); + + ge_cairo_set_color (cr, dark); + cairo_rectangle (cr, mx*3-1, my*3-1, 1, 1); + cairo_fill (cr); + } } - - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - - cl_rectangle_reset_clip_rectangle (&r); + cairo_restore (cr); } -void cl_draw_combobox_button (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) +static void +clearlooks_draw_radiobutton (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style); - gboolean is_active = FALSE; - gboolean draw_inset = FALSE; - CLRectangle r; - - cl_rectangle_set_button (&r, style, state_type, - GTK_WIDGET_HAS_DEFAULT (widget), - GTK_WIDGET_HAS_FOCUS (widget), - CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); - - if (state_type == GTK_STATE_ACTIVE) - is_active = TRUE; - else - r.fillgc = NULL; - - /* Seriously, why can't non-gtk-apps at least try to be decent citizens? - Take this fscking OpenOffice.org 1.9 for example. The morons responsible - for this utter piece of crap give the clip size wrong values! :'( */ - - if (area) - { - area->x = x; - area->y = y; - area->width = width; - area->height = height; - } - - x--; - width++; - - /* Draw "sunken" look when border thickness is more than 2 pixels. */ - if (GTK_IS_COMBO(widget->parent)) - draw_inset = (widget->parent->style->xthickness > 2 && - widget->parent->style->ythickness > 2); - else - draw_inset = (style->xthickness > 2 && style->ythickness > 2); - - if (draw_inset) + const CairoColor *border; + const CairoColor *dot; + CairoColor shadow; + CairoColor highlight; + cairo_pattern_t *pt; + gboolean inconsistent; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); + + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; + + if (widget->disabled) { - cl_draw_inset (style, window, widget, area, x, y, width, height, - CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); - - x++; - y++; - height-=2; - width-=2; + border = &colors->shade[5]; + dot = &colors->shade[6]; } else { - x++; - width--; + border = &colors->shade[6]; + dot = &colors->text[0]; } - - if (area) - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - - if (!is_active) - { - int tmp_height = (float)height*0.25; - - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); - - draw_hgradient (window, style->bg_gc[state_type], style, - x+2,y+2,width-4,tmp_height, - &clearlooks_style->button_g1[state_type], - &clearlooks_style->button_g2[state_type]); - - draw_hgradient (window, style->bg_gc[state_type], style, - x+2, y+2+tmp_height, width-4, height-3-tmp_height*2, - &clearlooks_style->button_g2[state_type], - &clearlooks_style->button_g3[state_type]); - - draw_hgradient (window, style->bg_gc[state_type], style, - x+2,y+height-tmp_height-1,width-4,tmp_height, - &clearlooks_style->button_g3[state_type], - &clearlooks_style->button_g4[state_type]); + ge_shade_color (&widget->parentbg, 0.9, &shadow); + ge_shade_color (&widget->parentbg, 1.1, &highlight); - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); - } + pt = cairo_pattern_create_linear (0, 0, 13, 13); + cairo_pattern_add_color_stop_rgb (pt, 0.0, shadow.r, shadow.b, shadow.g); + cairo_pattern_add_color_stop_rgba (pt, 0.5, shadow.r, shadow.b, shadow.g, 0.5); + cairo_pattern_add_color_stop_rgba (pt, 0.5, highlight.r, highlight.g, highlight.b, 0.5); + cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - - if (area) - cl_rectangle_reset_clip_rectangle (&r); -} - -/* Draw text Entry */ -void cl_draw_entry (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) -{ - CLRectangle r; - gboolean has_focus = GTK_WIDGET_HAS_FOCUS(widget); - GdkGC *bg_gc = cl_get_window_bg_gc(widget); + cairo_translate (cr, x, y); - gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1); + cairo_set_line_width (cr, 2); + cairo_arc (cr, 7, 7, 6, 0, G_PI*2); + cairo_set_source (cr, pt); + cairo_stroke (cr); + cairo_pattern_destroy (pt); - gtk_style_apply_default_background (style, window, TRUE, state_type, - area, x+1, y+1, width-2, height-2); + cairo_set_line_width (cr, 1); + cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2); - cl_rectangle_set_entry (&r, style, state_type, - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND, - has_focus); - - /* Draw "sunken" look when border thickness is more than 2 pixels. */ - if (style->xthickness > 2 && style->ythickness > 2) + if (!widget->disabled) { - cl_draw_inset (style, window, widget, area, x, y, width, height, - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); - - x++; - y++; - width-=2; - height-=2; + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); -} - -void cl_draw_optionmenu(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) -{ - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style); - GtkRequisition indicator_size; - GtkBorder indicator_spacing; - int line_pos; - - option_menu_get_props (widget, &indicator_size, &indicator_spacing); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); - if (get_direction (widget) == GTK_TEXT_DIR_RTL) - line_pos = x + (indicator_size.width + indicator_spacing.left + indicator_spacing.right) + style->xthickness; - else - line_pos = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness; + if (draw_bullet) + { + if (inconsistent) + { + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, 4); - cl_draw_button (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); - - gdk_draw_line (window, clearlooks_style->shade_gc[3], - line_pos, y + style->ythickness - 1, line_pos, - y + height - style->ythickness); + cairo_move_to(cr, 5, 7); + cairo_line_to(cr, 9, 7); - gdk_draw_line (window, style->light_gc[state_type], - line_pos+1, y + style->ythickness - 1, line_pos+1, - y + height - style->ythickness); + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } + else + { + cairo_arc (cr, 7, 7, 3, 0, G_PI*2); + ge_cairo_set_color (cr, dot); + cairo_fill (cr); + + cairo_arc (cr, 6, 6, 1, 0, G_PI*2); + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + cairo_fill (cr); + } + } } - -void cl_draw_menuitem_button (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int width, int height, CLRectangle *r) +static void +clearlooks_draw_checkbox (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) { - ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style; - gboolean menubar = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE; - int corner = CL_CORNER_NARROW; - GdkColor lower_color; + const CairoColor *border; + const CairoColor *dot; + gboolean inconsistent = FALSE; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); - shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.85); + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; - if (menubar) + if (widget->disabled) { - height++; - corner = CL_CORNER_NONE; - r->bordergc = clearlooks_style->border_gc[CL_BORDER_UPPER]; + border = &colors->shade[5]; + dot = &colors->shade[6]; } else { - r->bordergc = clearlooks_style->spot3_gc; + border = &colors->shade[6]; + dot = &colors->text[GTK_STATE_NORMAL]; } - - cl_rectangle_set_corners (r, corner, corner, corner, corner); - - cl_rectangle_set_gradient (&r->fill_gradient, - &style->base[GTK_STATE_SELECTED], &lower_color); - r->gradient_type = CL_GRADIENT_VERTICAL; - - r->fillgc = clearlooks_style->spot2_gc; - r->topleft = clearlooks_style->spot1_gc; + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); - cl_rectangle_set_clip_rectangle (r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, r); - cl_draw_shadow (window, widget, style, x, y, width, height, r); - cl_rectangle_reset_clip_rectangle (r); -} - -void cl_draw_menuitem_flat (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int width, int height, CLRectangle *r) -{ - ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style; - gboolean menubar = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE; - GdkColor tmp; + if (widget->xthickness > 2 && widget->ythickness > 2) + { + widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5, width-1, height-1, 1, CR_CORNER_ALL); + + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 1.5, 1.5, width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } + else + { + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } - cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW, - CL_CORNER_NARROW, CL_CORNER_NARROW); + if (!widget->disabled) + { + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); + } - tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap, - &style->base[GTK_STATE_PRELIGHT], 0.8); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); - r->bordergc = style->black_gc; - r->fillgc = style->base_gc[GTK_STATE_PRELIGHT]; - - if (menubar) height++; + if (draw_bullet) + { + if (inconsistent) /* Inconsistent */ + { + cairo_set_line_width (cr, 2.0); + cairo_move_to (cr, 3, height*0.5); + cairo_line_to (cr, width-3, height*0.5); + } + else + { + cairo_set_line_width (cr, 1.7); + cairo_move_to (cr, 0.5 + (width*0.2), (height*0.5)); + cairo_line_to (cr, 0.5 + (width*0.4), (height*0.7)); + + cairo_curve_to (cr, 0.5 + (width*0.4), (height*0.7), + 0.5 + (width*0.5), (height*0.4), + 0.5 + (width*0.70), (height*0.25)); - cl_rectangle_set_clip_rectangle (r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, r); - cl_rectangle_reset_clip_rectangle (r); - - gdk_gc_set_foreground (style->black_gc, &tmp); + } + + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } } -void cl_draw_menuitem_gradient (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int width, int height, CLRectangle *r) +static void +clearlooks_draw_normal_arrow (cairo_t *cr, const CairoColor *color, + double x, double y, double width, double height) { - ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style; - gboolean menubar = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE; - GdkColor tmp; - GdkColor lower_color; - - shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.8); - - cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW, - CL_CORNER_NARROW, CL_CORNER_NARROW); - - cl_rectangle_set_gradient (&r->fill_gradient, - &style->base[GTK_STATE_SELECTED], &lower_color); + double arrow_width; + double arrow_height; + double line_width_2; - r->gradient_type = CL_GRADIENT_VERTICAL; - - tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap, - &style->base[GTK_STATE_PRELIGHT], 0.8); + cairo_save (cr); - r->bordergc = style->black_gc; - r->fillgc = style->base_gc[GTK_STATE_PRELIGHT]; + arrow_width = MIN (height * 2.0 + MAX (1.0, ceil (height * 2.0 / 6.0 * 2.0) / 2.0) / 2.0, width); + line_width_2 = MAX (1.0, ceil (arrow_width / 6.0 * 2.0) / 2.0) / 2.0; + arrow_height = arrow_width / 2.0 + line_width_2; - if (menubar) height++; + cairo_translate (cr, x, y - arrow_height / 2.0); - cl_rectangle_set_clip_rectangle (r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, r); - cl_rectangle_reset_clip_rectangle (r); + cairo_move_to (cr, -arrow_width / 2.0, line_width_2); + cairo_line_to (cr, -arrow_width / 2.0 + line_width_2, 0); + /* cairo_line_to (cr, 0, arrow_height - line_width_2); */ + cairo_arc_negative (cr, 0, arrow_height - 2*line_width_2 - 2*line_width_2 * sqrt(2), 2*line_width_2, G_PI_2 + G_PI_4, G_PI_4); + cairo_line_to (cr, arrow_width / 2.0 - line_width_2, 0); + cairo_line_to (cr, arrow_width / 2.0, line_width_2); + cairo_line_to (cr, 0, arrow_height); + cairo_close_path (cr); - gdk_gc_set_foreground (style->black_gc, &tmp); + ge_cairo_set_color (cr, color); + cairo_fill (cr); + + cairo_restore (cr); } -void cl_draw_treeview_header (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) +static void +clearlooks_draw_combo_arrow (cairo_t *cr, const CairoColor *color, + double x, double y, double width, double height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - gint columns = 0, column_index = -1, fill_width = width; - gboolean is_etree = strcmp("ETree", G_OBJECT_TYPE_NAME(widget->parent)) == 0; - gboolean resizable = TRUE; + double arrow_width = MIN (height * 2 / 3.0, width); + double arrow_height = arrow_width / 2.0; + double gap_size = 1.0 * arrow_height; - GdkGC *bottom = clearlooks_style->shade_gc[5]; - - if ( width < 2 || height < 2 ) + cairo_save (cr); + cairo_translate (cr, x, y - (arrow_height + gap_size) / 2.0); + cairo_rotate (cr, G_PI); + clearlooks_draw_normal_arrow (cr, color, 0, 0, arrow_width, arrow_height); + cairo_restore (cr); + + clearlooks_draw_normal_arrow (cr, color, x, y + (arrow_height + gap_size) / 2.0, arrow_width, arrow_height); +} + +static void +_clearlooks_draw_arrow (cairo_t *cr, const CairoColor *color, + ClearlooksDirection dir, ClearlooksArrowType type, + double x, double y, double width, double height) +{ + double rotate; + + if (dir == CL_DIRECTION_LEFT) + rotate = G_PI*1.5; + else if (dir == CL_DIRECTION_RIGHT) + rotate = G_PI*0.5; + else if (dir == CL_DIRECTION_UP) + rotate = G_PI; + else if (dir == CL_DIRECTION_DOWN) + rotate = 0; + else return; - if (GTK_IS_TREE_VIEW (widget->parent)) + if (type == CL_ARROW_NORMAL) { - gtk_treeview_get_header_index (GTK_TREE_VIEW(widget->parent), - widget, &column_index, &columns, - &resizable); + cairo_translate (cr, x, y); + cairo_rotate (cr, -rotate); + clearlooks_draw_normal_arrow (cr, color, 0, 0, width, height); } - else if (GTK_IS_CLIST (widget->parent)) + else if (type == CL_ARROW_COMBO) { - gtk_clist_get_header_index (GTK_CLIST(widget->parent), - widget, &column_index, &columns); + cairo_translate (cr, x, y); + clearlooks_draw_combo_arrow (cr, color, 0, 0, width, height); } +} + +static void +clearlooks_draw_arrow (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ArrowParameters *arrow, + int x, int y, int width, int height) +{ + const CairoColor *color = &colors->fg[widget->state_type]; + gdouble tx, ty; - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], area); - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], area); - } - - if (state_type != GTK_STATE_NORMAL) - fill_width-=2; - - gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, x, y, fill_width, height-(height/3)+1); + tx = x + width/2.0; + ty = y + height/2.0; - draw_hgradient (window, style->bg_gc[state_type], style, - x, 1+y+height-(height/3), fill_width, height/3, - &style->bg[state_type], &clearlooks_style->inset_dark[state_type]); - - if (resizable || (column_index != columns-1)) + if (widget->disabled) { - gdk_draw_line (window, clearlooks_style->shade_gc[4], x+width-2, y+4, x+width-2, y+height-5); - gdk_draw_line (window, clearlooks_style->shade_gc[0], x+width-1, y+4, x+width-1, y+height-5); + _clearlooks_draw_arrow (cr, &colors->shade[0], + arrow->direction, arrow->type, + tx+0.5, ty+0.5, width, height); } + + cairo_identity_matrix (cr); - /* left light line */ - if (column_index == 0) - gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y+1, x, y+height-2); - - /* top light line */ - gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y, x+width-1, y); - - /* bottom dark line */ - if (state_type == GTK_STATE_INSENSITIVE) - bottom = clearlooks_style->shade_gc[3]; - - - gdk_draw_line (window, bottom, x, y+height-1, x+width-1, y+height-1); - - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], NULL); - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], NULL); - } + _clearlooks_draw_arrow (cr, color, arrow->direction, arrow->type, + tx, ty, width, height); +} + +void +clearlooks_register_style_classic (ClearlooksStyleFunctions *functions) +{ + g_assert (functions); + + functions->draw_button = clearlooks_draw_button; + functions->draw_scale_trough = clearlooks_draw_scale_trough; + functions->draw_progressbar_trough = clearlooks_draw_progressbar_trough; + functions->draw_progressbar_fill = clearlooks_draw_progressbar_fill; + functions->draw_slider_button = clearlooks_draw_slider_button; + functions->draw_entry = clearlooks_draw_entry; + functions->draw_spinbutton = clearlooks_draw_spinbutton; + functions->draw_spinbutton_down = clearlooks_draw_spinbutton_down; + functions->draw_optionmenu = clearlooks_draw_optionmenu; + functions->draw_inset = clearlooks_draw_inset; + functions->draw_menubar = clearlooks_draw_menubar; + functions->draw_tab = clearlooks_draw_tab; + functions->draw_frame = clearlooks_draw_frame; + functions->draw_separator = clearlooks_draw_separator; + functions->draw_menu_item_separator = clearlooks_draw_menu_item_separator; + functions->draw_list_view_header = clearlooks_draw_list_view_header; + functions->draw_toolbar = clearlooks_draw_toolbar; + functions->draw_menuitem = clearlooks_draw_menuitem; + functions->draw_menubaritem = clearlooks_draw_menubaritem; + functions->draw_selected_cell = clearlooks_draw_selected_cell; + functions->draw_scrollbar_stepper = clearlooks_draw_scrollbar_stepper; + functions->draw_scrollbar_slider = clearlooks_draw_scrollbar_slider; + functions->draw_scrollbar_trough = clearlooks_draw_scrollbar_trough; + functions->draw_statusbar = clearlooks_draw_statusbar; + functions->draw_menu_frame = clearlooks_draw_menu_frame; + functions->draw_tooltip = clearlooks_draw_tooltip; + functions->draw_handle = clearlooks_draw_handle; + functions->draw_resize_grip = clearlooks_draw_resize_grip; + functions->draw_arrow = clearlooks_draw_arrow; + functions->draw_checkbox = clearlooks_draw_checkbox; + functions->draw_radiobutton = clearlooks_draw_radiobutton; + functions->draw_shadow = clearlooks_draw_shadow; + functions->draw_slider = clearlooks_draw_slider; + functions->draw_gripdots = clearlooks_draw_gripdots; } diff --git a/libs/clearlooks/clearlooks_draw.h b/libs/clearlooks/clearlooks_draw.h index a8cbb3732f..a3f26764da 100644 --- a/libs/clearlooks/clearlooks_draw.h +++ b/libs/clearlooks/clearlooks_draw.h @@ -1,159 +1,17 @@ #ifndef CLEARLOOKS_DRAW_H #define CLEARLOOKS_DRAW_H +#include "clearlooks_types.h" +#include "clearlooks_style.h" + #include <gtk/gtk.h> #include <gdk/gdk.h> -typedef struct -{ - GdkColor *from; - GdkColor *to; -} CLGradient; - -typedef enum -{ - CL_GRADIENT_NONE, - CL_GRADIENT_HORIZONTAL, - CL_GRADIENT_VERTICAL -} CLGradientType; - -typedef struct -{ - CLGradient fill_gradient; - CLGradient border_gradient; - - CLGradientType gradient_type; - - GdkGC *bordergc; - GdkGC *fillgc; - - guint8 corners[4]; - - GdkGC *topleft; /* top + left shadow */ - GdkGC *bottomright; /* bottom + right shadow */ - - GdkColor tmp_color; /* used for gradient */ -} CLRectangle; - -typedef enum /* DON'T CHANGE THE ORDER! */ -{ - CL_CORNER_TOPRIGHT, - CL_CORNER_BOTTOMRIGHT, - CL_CORNER_BOTTOMLEFT, - CL_CORNER_TOPLEFT -} CLCornerSide; - -typedef enum /* DON'T CHANGE THE ORDER! */ -{ - CL_BORDER_TOP, - CL_BORDER_RIGHT, - CL_BORDER_BOTTOM, - CL_BORDER_LEFT -} CLBorderType; - -typedef enum -{ - CL_CORNER_NONE = 0, - CL_CORNER_NARROW = 1, - CL_CORNER_ROUND = 2 -} CLCornerSharpness; - - - -CLRectangle *cl_rectangle_new(GdkGC *fillgc, GdkGC *bordergc, - int tl, int tr, int bl, int br); - -void cl_draw_rectangle (GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r); - -void cl_rectangle_set_color (CLGradient *g, GdkColor *color); -void cl_rectangle_set_gradient (CLGradient *g, GdkColor *from, GdkColor *to); - -void cl_rectangle_set_button (CLRectangle *r, GtkStyle *style, - GtkStateType state_type, gboolean hasdefault, gboolean has_focus, - CLBorderType tl, CLBorderType tr, - CLBorderType bl, CLBorderType br); - -void cl_rectangle_set_entry (CLRectangle *r, GtkStyle *style, - GtkStateType state_type, - CLBorderType tl, CLBorderType tr, - CLBorderType bl, CLBorderType br, - gboolean has_focus); - -void cl_draw_shadow(GdkWindow *window, GtkWidget *widget, GtkStyle *style, - int x, int y, int width, int height, CLRectangle *r); - -void cl_rectangle_set_clip_rectangle (CLRectangle *r, GdkRectangle *area); -void cl_rectangle_reset_clip_rectangle (CLRectangle *r); - -void cl_set_corner_sharpness (const gchar *detail, GtkWidget *widget, CLRectangle *r); - - -void cl_rectangle_set_corners (CLRectangle *r, int tl, int tr, int bl, int br); - -void cl_rectangle_init (CLRectangle *r, GdkGC *fillgc, GdkGC *bordergc, - int tl, int tr, int bl, int br); - -void cl_rectangle_reset (CLRectangle *r, GtkStyle *style); - - -GdkPixmap* cl_progressbar_tile_new (GdkDrawable *drawable, GtkWidget *widget, - GtkStyle *style, gint height, gint offset); - -void cl_progressbar_fill (GdkDrawable *drawable, GtkWidget *widget, - GtkStyle *style, GdkGC *gc, - gint x, gint y, gint width, gint height, - guint8 offset, GdkRectangle *area); - -GdkColor cl_gc_set_fg_color_shade (GdkGC *gc, GdkColormap *colormap, - GdkColor *from, gfloat s); +#include <cairo.h> -void cl_draw_spinbutton(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); - -void cl_draw_button(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); - -void cl_draw_entry (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); - -void cl_draw_combobox_entry (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); - -void cl_draw_combobox_button (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); - -void cl_draw_menuitem_button (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int wiidth, int height, CLRectangle *r); +GE_INTERNAL void clearlooks_register_style_classic (ClearlooksStyleFunctions *functions); +GE_INTERNAL void clearlooks_register_style_glossy (ClearlooksStyleFunctions *functions); +GE_INTERNAL void clearlooks_register_style_gummy (ClearlooksStyleFunctions *functions); +GE_INTERNAL void clearlooks_register_style_inverted (ClearlooksStyleFunctions *functions); -void cl_draw_menuitem_flat (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int wiidth, int height, CLRectangle *r); - -void cl_draw_menuitem_gradient (GdkDrawable *window, GtkWidget *widget, GtkStyle *style, - GdkRectangle *area, GtkStateType state_type, - int x, int y, int wiidth, int height, CLRectangle *r); - -void cl_draw_treeview_header (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); - #endif /* CLEARLOOKS_DRAW_H */ diff --git a/libs/clearlooks/clearlooks_draw_glossy.c b/libs/clearlooks/clearlooks_draw_glossy.c new file mode 100644 index 0000000000..8a5921efc2 --- /dev/null +++ b/libs/clearlooks/clearlooks_draw_glossy.c @@ -0,0 +1,1422 @@ +/* Clearlooks Glossy style + * Copyright (C) 2006 Benjamin Berg + * Copyright (C) 2007 Andrea Cimitan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Written by Andrea Cimitan <andrea.cimitan@gmail.com> + * and Benjamin Berg <benjamin@sipsolutions.net> + * Based on code by Richard Stellingwerff <remenic@gmail.com> + * and Daniel Borgmann <daniel.borgmann@gmail.com> + * from the ubuntulooks engine. + */ + +#include "clearlooks_draw.h" +#include "clearlooks_style.h" +#include "clearlooks_types.h" + +#include "support.h" +#include <ge-support.h> + +#include <cairo.h> + + +static void +clearlooks_draw_glossy_gradient (cairo_t *cr, + double x, double y, int width, int height, + const CairoColor *color, + gboolean disabled, gboolean radius, CairoCorners corners) +{ + CairoColor a, b, c, d; + cairo_pattern_t *pt; + + ge_shade_color (color, disabled? 1.06 : 1.16, &a); + ge_shade_color (color, disabled? 1.02 : 1.08, &b); + ge_shade_color (color, disabled? 0.98 : 1.00, &c); + ge_shade_color (color, disabled? 1.02 : 1.08, &d); + + pt = cairo_pattern_create_linear (x, y, x, y+height); + cairo_pattern_add_color_stop_rgb (pt, 0.0, a.r, a.g, a.b); + cairo_pattern_add_color_stop_rgb (pt, 0.5, b.r, b.g, b.b); + cairo_pattern_add_color_stop_rgb (pt, 0.5, c.r, c.g, c.b); + cairo_pattern_add_color_stop_rgb (pt, 1.0, d.r, d.g, d.b); + + cairo_set_source (cr, pt); + ge_cairo_rounded_rectangle (cr, x, y, width, height, radius, corners); + cairo_fill (cr); + + cairo_pattern_destroy (pt); +} + +static void +clearlooks_set_mixed_color (cairo_t *cr, + const CairoColor *color1, + const CairoColor *color2, + gdouble mix_factor) +{ + CairoColor composite; + + ge_mix_color (color1, color2, mix_factor, &composite); + ge_cairo_set_color (cr, &composite); +} + +static void +clearlooks_glossy_draw_inset (cairo_t *cr, + const CairoColor *bg_color, + double x, double y, double w, double h, + double radius, uint8 corners) +{ + CairoColor shadow; + CairoColor highlight; + + /* not really sure of shading ratios... we will think */ + ge_shade_color (bg_color, 0.93, &shadow); + ge_shade_color (bg_color, 1.07, &highlight); + + /* highlight */ + cairo_move_to (cr, x + w + (radius * -0.2928932188), y - (radius * -0.2928932188)); /* 0.2928932... 1-sqrt(2)/2 gives middle of curve */ + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.75, G_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, G_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, G_PI * 0.5, G_PI * 0.75); + else + cairo_line_to (cr, x, y + h); + + ge_cairo_set_color (cr, &highlight); + cairo_stroke (cr); + + /* shadow */ + cairo_move_to (cr, x + (radius * 0.2928932188), y + h + (radius * -0.2928932188)); + + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_arc (cr, x + radius, y + h - radius, radius, M_PI * 0.75, 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); + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, M_PI * 1.5, M_PI * 1.75); + else + cairo_line_to (cr, x + w, y); + + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_light_inset (cairo_t *cr, + const CairoColor *bg_color, + double x, double y, double w, double h, + double radius, uint8 corners) +{ + CairoColor shadow; + CairoColor highlight; + + /* not really sure of shading ratios... we will think */ + ge_shade_color (bg_color, 0.95, &shadow); + ge_shade_color (bg_color, 1.05, &highlight); + + /* highlight */ + cairo_move_to (cr, x + w + (radius * -0.2928932188), y - (radius * -0.2928932188)); /* 0.2928932... 1-sqrt(2)/2 gives middle of curve */ + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.75, G_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, G_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, G_PI * 0.5, G_PI * 0.75); + else + cairo_line_to (cr, x, y + h); + + ge_cairo_set_color (cr, &highlight); + cairo_stroke (cr); + + /* shadow */ + cairo_move_to (cr, x + (radius * 0.2928932188), y + h + (radius * -0.2928932188)); + + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_arc (cr, x + radius, y + h - radius, radius, M_PI * 0.75, 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); + + if (corners & CR_CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, M_PI * 1.5, M_PI * 1.75); + else + cairo_line_to (cr, x + w, y); + + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_highlight_and_shade (cairo_t *cr, + const CairoColor *bg_color, + const ShadowParameters *params, + int width, int height, gdouble radius) +{ + CairoColor shadow; + CairoColor highlight; + uint8 corners = params->corners; + double x = 1.0; + double y = 1.0; + + /* not really sure of shading ratios... we will think */ + ge_shade_color (bg_color, 0.8, &shadow); + ge_shade_color (bg_color, 1.2, &highlight); + + cairo_save (cr); + + /* Top/Left highlight */ + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_move_to (cr, x, y+height-radius); + else + cairo_move_to (cr, x, y+height); + + ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT); + + if (corners & CR_CORNER_TOPRIGHT) + cairo_line_to (cr, x+width-radius, y); + else + cairo_line_to (cr, x+width, y); + + if (params->shadow & CL_SHADOW_OUT) + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + else + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5); + + cairo_stroke (cr); + + /* Bottom/Right highlight -- this includes the corners */ + cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */ + ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT); + ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT); + + if (params->shadow & CL_SHADOW_OUT) + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5); + else + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + + cairo_stroke (cr); + + cairo_restore (cr); +} + +static void +clearlooks_glossy_draw_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + double xoffset = 0, yoffset = 0; + CairoColor fill = colors->bg[params->state_type]; + CairoColor border_normal = colors->shade[6]; + CairoColor border_disabled = colors->shade[4]; + double radius; + + cairo_pattern_t *pattern; + + cairo_save (cr); + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + /* Shadows and Glow */ + if (params->xthickness == 3 || params->ythickness == 3) + { + if (params->xthickness == 3) + xoffset = 1; + if (params->ythickness == 3) + yoffset = 1; + } + + radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0, (height - 2.0 - 2*yoffset) / 2.0)); + + if (params->xthickness == 3 || params->ythickness == 3) + { + cairo_translate (cr, 0.5, 0.5); + + /* if (params->enable_glow && !params->active && !params->disabled) */ + if (params->prelight && params->enable_glow && !params->active) + { + /* Glow becomes a shadow to have 3d prelight buttons :) */ + CairoColor glow; + + radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0 - 1.0, (height - 2.0 - 2*yoffset) / 2.0 - 1.0)); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius+1, params->corners); + ge_shade_color (¶ms->parentbg, 0.96, &glow); + ge_cairo_set_color (cr, &glow); + cairo_stroke (cr); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius+1, params->corners); + ge_shade_color (¶ms->parentbg, 0.92, &glow); + ge_cairo_set_color (cr, &glow); + cairo_stroke (cr); + } + + /* if (!(params->enable_glow && !params->active && !params->disabled)) */ + if (!(params->prelight && params->enable_glow && !params->active)) + if (!(params->disabled)) + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, params->radius+1, params->corners); + else + /*Draw a lighter inset */ + clearlooks_glossy_draw_light_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, params->radius+1, params->corners); + cairo_translate (cr, -0.5, -0.5); + } + + clearlooks_draw_glossy_gradient (cr, xoffset+1, yoffset+1, + width-(xoffset*2)-2, height-(yoffset*2)-2, + &fill, params->disabled, radius, params->corners); + + /* Pressed button shadow */ + if (params->active) + { + CairoColor shadow; + ge_shade_color (&fill, 0.92, &shadow); + + cairo_save (cr); + + ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, height, radius, params->corners & (CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMLEFT)); + cairo_clip (cr); + cairo_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, 3); + + pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+1, yoffset+4); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_rectangle (cr, xoffset+1, yoffset+1, 3, height-(yoffset*2)-2); + + pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+4, yoffset+1); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); + } + + /* Default button highlight */ + if (params->is_default && !params->active && !params->disabled) + { + const CairoColor *glow = &colors->spot[0]; + double hh = (height-5)/2.0 + 1; + + cairo_rectangle (cr, 3.5, 3.5, width-7, height-7); + ge_cairo_set_color (cr, glow); + cairo_stroke (cr); + + glow = &colors->spot[0]; + cairo_move_to (cr, 2.5, 2.5+hh); cairo_rel_line_to (cr, 0, -hh); + cairo_rel_line_to (cr, width-5, 0); cairo_rel_line_to (cr, 0, hh); + ge_cairo_set_color (cr, glow); + cairo_stroke (cr); + + hh--; + + glow = &colors->spot[1]; + cairo_move_to (cr, 2.5, 2.5+hh); cairo_rel_line_to (cr, 0, hh); + cairo_rel_line_to (cr, width-5, 0); cairo_rel_line_to (cr, 0, -hh); + ge_cairo_set_color (cr, glow); + cairo_stroke (cr); + } + + /* Border */ + if (params->is_default || (params->prelight && params->enable_glow)) + border_normal = colors->spot[2]; + /* ge_mix_color (&border_normal, &colors->spot[2], 0.5, &border_normal); */ + if (params->disabled) + ge_cairo_set_color (cr, &border_disabled); + else + clearlooks_set_mixed_color (cr, &border_normal, &fill, 0.2); + ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, + width-(xoffset*2)-1, height-(yoffset*2)-1, + radius, params->corners); + cairo_stroke (cr); + cairo_restore (cr); +} + +static void +clearlooks_glossy_draw_progressbar_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[6]; + CairoColor shadow; + cairo_pattern_t *pattern; + double radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0)); + + cairo_save (cr); + + cairo_set_line_width (cr, 1.0); + + /* Fill with bg color */ + ge_cairo_set_color (cr, &colors->bg[params->state_type]); + + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + + /* Create trough box */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + ge_cairo_set_color (cr, &colors->shade[2]); + cairo_fill (cr); + + /* Draw border */ + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width-1, height-1, radius, params->corners); + clearlooks_set_mixed_color (cr, border, &colors->shade[2], 0.3); + cairo_stroke (cr); + + /* clip the corners of the shadows */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + cairo_clip (cr); + + ge_shade_color (border, 0.92, &shadow); + + /* Top shadow */ + cairo_rectangle (cr, x+1, y+1, width-2, 4); + pattern = cairo_pattern_create_linear (x, y, x, y+4); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Left shadow */ + cairo_rectangle (cr, x+1, y+1, 4, height-2); + pattern = cairo_pattern_create_linear (x, y, x+4, y); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); +} + +static void +clearlooks_glossy_draw_progressbar_fill (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ProgressBarParameters *progressbar, + int x, int y, int width, int height, + gint offset) +{ + boolean is_horizontal = progressbar->orientation < 2; + double tile_pos = 0; + double stroke_width; + double radius; + int x_step; + + cairo_pattern_t *pattern; + CairoColor a; + CairoColor b; + CairoColor e; + CairoColor border; + CairoColor shadow; + + radius = MAX (0, params->radius - params->xthickness); + + cairo_save (cr); + + if (!is_horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + if ((progressbar->orientation == CL_ORIENTATION_RIGHT_TO_LEFT) || (progressbar->orientation == CL_ORIENTATION_BOTTOM_TO_TOP)) + ge_cairo_mirror (cr, CR_MIRROR_HORIZONTAL, &x, &y, &width, &height); + + /* Clamp the radius so that the _height_ fits ... */ + radius = MIN (radius, height / 2.0); + + stroke_width = height*2; + x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */ + + cairo_translate (cr, x, y); + + cairo_save (cr); + /* This is kind of nasty ... Clip twice from each side in case the length + * of the fill is smaller than twice the radius. */ + ge_cairo_rounded_rectangle (cr, 0, 0, width + radius, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + /* Draw the background gradient */ + ge_shade_color (&colors->spot[1], 1.16, &a); + ge_shade_color (&colors->spot[1], 1.08, &b); + ge_shade_color (&colors->spot[1], 1.08, &e); + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, a.r, a.g, a.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, b.r, b.g, b.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, colors->spot[1].r, colors->spot[1].g, colors->spot[1].b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, e.r, e.g, e.b); + cairo_set_source (cr, pattern); + cairo_paint (cr); + cairo_pattern_destroy (pattern); + + /* Draw the Strokes */ + while (tile_pos <= width+x_step) + { + cairo_move_to (cr, stroke_width/2-x_step, 0); + cairo_line_to (cr, stroke_width-x_step, 0); + cairo_line_to (cr, stroke_width/2-x_step, height); + cairo_line_to (cr, -x_step, height); + + cairo_translate (cr, stroke_width, 0); + tile_pos += stroke_width; + } + + cairo_set_source_rgba (cr, colors->spot[2].r, + colors->spot[2].g, + colors->spot[2].b, + 0.15); + + cairo_fill (cr); + cairo_restore (cr); /* rounded clip region */ + + /* inner highlight border + * This is again kinda ugly. Draw once from each side, clipping away the other. */ + cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.3); + + /* left side */ + cairo_save (cr); + cairo_rectangle (cr, 0, 0, width / 2, height); + cairo_clip (cr); + + if (progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + else + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + /* right side */ + cairo_save (cr); + cairo_rectangle (cr, width / 2, 0, (width+1) / 2, height); + cairo_clip (cr); + + if (progressbar->value < 1.0 || progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, -1.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + else + ge_cairo_rounded_rectangle (cr, -0.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + + /* Draw the dark lines and the shadow */ + cairo_save (cr); + /* Again, this weird clip area. */ + ge_cairo_rounded_rectangle (cr, -1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius - 1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + border = colors->spot[2]; + border.a = 0.5; + ge_shade_color (&colors->shade[6], 0.92, &shadow); + shadow.a = 0.2; + + if (progressbar->pulsing) + { + /* At the beginning of the bar. */ + cairo_move_to (cr, 0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, 0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, -0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, -0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, -0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + if (progressbar->value < 1.0 || progressbar->pulsing) + { + /* At the end of the bar. */ + cairo_move_to (cr, width - 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width - 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width - 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, width + 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width + 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width + 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + + cairo_restore (cr); + + cairo_restore (cr); /* rotation, mirroring */ +} + +static void +clearlooks_glossy_scale_draw_gradient (cairo_t *cr, + const CairoColor *c1, + const CairoColor *c2, + const CairoColor *c3, + int x, int y, int width, int height, + boolean horizontal) +{ + cairo_pattern_t *pattern; + + pattern = cairo_pattern_create_linear (0, 0, horizontal ? 0 : width, horizontal ? height : 0); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, c1->r, c1->g, c1->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, c2->r, c2->g, c2->b); + + cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + clearlooks_set_mixed_color (cr, c3, c1, 0.3); + ge_cairo_stroke_rectangle (cr, x, y, width, height); +} + +#define TROUGH_SIZE 6 +static void +clearlooks_glossy_draw_scale_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + int trough_width, trough_height; + double translate_x, translate_y; + + if (slider->horizontal) + { + trough_width = width-3; + trough_height = TROUGH_SIZE-2; + + translate_x = x + 0.5; + translate_y = y + 0.5 + (height/2) - (TROUGH_SIZE/2); + } + else + { + trough_width = TROUGH_SIZE-2; + trough_height = height-3; + + translate_x = x + 0.5 + (width/2) - (TROUGH_SIZE/2); + translate_y = y + 0.5; + } + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, translate_x, translate_y); + + if (!slider->fill_level) + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0); + + cairo_translate (cr, 1, 1); + + if (!slider->lower && !slider->fill_level) + clearlooks_glossy_scale_draw_gradient (cr, &colors->shade[3], /* top */ + &colors->shade[2], /* bottom */ + &colors->shade[6], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal); + else + clearlooks_glossy_scale_draw_gradient (cr, &colors->spot[1], /* top */ + &colors->spot[0], /* bottom */ + &colors->spot[2], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal); +} + +static void +clearlooks_glossy_draw_tab (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const TabParameters *tab, + int x, int y, int width, int height) +{ + + const CairoColor *border = &colors->shade[5]; + const CairoColor *stripe_fill = &colors->spot[1]; + const CairoColor *stripe_border = &colors->spot[2]; + const CairoColor *fill; + CairoColor hilight; + + cairo_pattern_t *pattern; + + double radius; + double strip_size; + + radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + /* Set clip */ + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + cairo_new_path (cr); + + /* Translate and set line width */ + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y+0.5); + + + /* Make the tabs slightly bigger than they should be, to create a gap */ + /* And calculate the strip size too, while you're at it */ + if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM) + { + height += 3.0; + strip_size = 2.0/height; /* 2 pixel high strip */ + + if (tab->gap_side == CL_GAP_TOP) + cairo_translate (cr, 0.0, -3.0); /* gap at the other side */ + } + else + { + width += 3.0; + strip_size = 2.0/width; + + if (tab->gap_side == CL_GAP_LEFT) + cairo_translate (cr, -3.0, 0.0); /* gap at the other side */ + } + + /* Set the fill color */ + fill = &colors->bg[params->state_type]; + + /* Set tab shape */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, + radius, params->corners); + + /* Draw fill */ + ge_cairo_set_color (cr, fill); + cairo_fill (cr); + + ge_shade_color (fill, 1.3, &hilight); + + /* Draw highlight */ + if (!params->active) + { + ShadowParameters shadow; + + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = params->corners; + + clearlooks_glossy_draw_highlight_and_shade (cr, &colors->bg[0], &shadow, + width, + height, radius); + } + + if (params->active) + { + CairoColor shadow, hilight, f1, f2; + + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-1 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 1, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + ge_shade_color (fill, 1.06, &shadow); + ge_shade_color (fill, 1.18, &hilight); + ge_shade_color (fill, 1.12, &f1); + ge_shade_color (fill, 1.06, &f2); + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, hilight.r, hilight.g, hilight.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, hilight.r, hilight.g, hilight.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, f1.r, f1.g, f1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.45, f2.r, f2.g, f2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.45, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shadow.r, shadow.g, shadow.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + else + { + /* Draw shade */ + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-2 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 0, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + + cairo_pattern_add_color_stop_rgba (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b, 0.5); + cairo_pattern_add_color_stop_rgba (pattern, 0.8, fill->r, fill->g, fill->b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + if (params->active) + { + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + } + else + { + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-2 : 2, + tab->gap_side == CL_GAP_TOP ? height-2 : 2, + tab->gap_side == CL_GAP_RIGHT ? width : 2, + tab->gap_side == CL_GAP_BOTTOM ? height : 2); + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, 0.8, border->r, border->g, border->b); + cairo_set_source (cr, pattern); + cairo_stroke (cr); + cairo_pattern_destroy (pattern); + } +} + +static void +clearlooks_glossy_draw_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[7]; + CairoColor fill; + CairoColor hilight; + CairoColor a, b, c, d; + cairo_pattern_t *pattern; + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + cairo_translate (cr, -0.5, -0.5); + + ge_shade_color (&colors->bg[params->state_type], 1.0, &fill); + if (params->prelight) + ge_shade_color (&fill, 1.1, &fill); + + ge_shade_color (&fill, 1.25, &hilight); + ge_shade_color (&fill, 1.16, &a); + ge_shade_color (&fill, 1.08, &b); + ge_shade_color (&fill, 1.0, &c); + ge_shade_color (&fill, 1.08, &d); + + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb (pattern, 0, a.r, a.g, a.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, b.r, b.g, b.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, c.r, c.g, c.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, d.r, d.g, d.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + clearlooks_set_mixed_color (cr, border, &fill, 0.2); + if (params->prelight) + ge_cairo_set_color (cr, &colors->spot[2]); + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, 2.5, params->corners); + cairo_stroke (cr); + + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + ge_cairo_rounded_rectangle (cr, 1.5, 1.5, width-3, height-3, 2.0, params->corners); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_slider_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0)); + + cairo_set_line_width (cr, 1.0); + + if (!slider->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x+0.5, y+0.5); + + params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1); + params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2); +} + +static void +clearlooks_glossy_draw_scrollbar_stepper (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + const ScrollBarStepperParameters *stepper, + int x, int y, int width, int height) +{ + CairoCorners corners = CR_CORNER_NONE; + const CairoColor *border = &colors->shade[7]; + CairoColor fill, s1, s2, s4; + cairo_pattern_t *pattern; + ShadowParameters shadow; + double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + if (scrollbar->horizontal) + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; + } + else + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT; + } + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners); + + if (scrollbar->horizontal) + pattern = cairo_pattern_create_linear (0, 0, 0, height); + else + pattern = cairo_pattern_create_linear (0, 0, width, 0); + + fill = colors->bg[widget->state_type]; + ge_shade_color(&fill, 1.16, &s1); + ge_shade_color(&fill, 1.08, &s2); + ge_shade_color(&fill, 1.08, &s4); + + cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, s4.r, s4.g, s4.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_translate (cr, 0.5, 0.5); + cairo_translate (cr, -0.5, -0.5); + + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners); + clearlooks_set_mixed_color (cr, border, &fill, 0.2); + if (widget->prelight) + ge_cairo_set_color (cr, &colors->spot[2]); + cairo_stroke (cr); + + cairo_translate (cr, 0.5, 0.5); + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = corners; +} + +static void +clearlooks_glossy_draw_scrollbar_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[7]; + CairoColor fill = scrollbar->color; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + if (scrollbar->junction & CL_JUNCTION_BEGIN) + { + if (scrollbar->horizontal) + { + x -= 1; + width += 1; + } + else + { + y -= 1; + height += 1; + } + } + if (scrollbar->junction & CL_JUNCTION_END) + { + if (scrollbar->horizontal) + width += 1; + else + height += 1; + } + + if (!scrollbar->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x, y); + + if (widget->prelight) + ge_shade_color (&fill, 1.1, &fill); + + cairo_set_line_width (cr, 1); + + ge_shade_color (&fill, 1.25, &hilight); + ge_shade_color (&fill, 1.16, &shade1); + ge_shade_color (&fill, 1.08, &shade2); + ge_shade_color (&fill, 1.08, &shade3); + + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + if (scrollbar->has_color) + { + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3); + } + + clearlooks_set_mixed_color (cr, border, &fill, scrollbar->has_color? 0.4 : 0.2); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); +} + +static void +clearlooks_glossy_draw_list_view_header (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ListViewHeaderParameters *header, + int x, int y, int width, int height) +{ +/* + CairoColor *border = !params->prelight? (CairoColor*)&colors->shade[4] : (CairoColor*)&colors->spot[1]; +*/ + const CairoColor *border = &colors->shade[4]; + const CairoColor *fill = &colors->bg[params->state_type]; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + + cairo_pattern_t *pattern; + + ge_shade_color (fill, 1.2, &hilight); + ge_shade_color (fill, 1.08, &shade1); + ge_shade_color (fill, 1.04, &shade2); + ge_shade_color (fill, 1.04, &shade3); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + /* Draw the fill */ + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0-1.0/height, shade3.r, shade3.g, shade3.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0-1.0/height, border->r, border->g, border->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, border->r, border->g, border->b); + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); + + /* Draw highlight */ + if (header->order == CL_ORDER_FIRST) + { + cairo_move_to (cr, 0.5, height-1); + cairo_line_to (cr, 0.5, 0.5); + } + else + cairo_move_to (cr, 0.0, 0.5); + + cairo_line_to (cr, width, 0.5); + + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + cairo_stroke (cr); + + /* Draw resize grip */ + if ((params->ltr && header->order != CL_ORDER_LAST) || + (!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable) + { + SeparatorParameters separator; + separator.horizontal = FALSE; + + if (params->ltr) + params->style_functions->draw_separator (cr, colors, params, &separator, + width-1.5, 4.0, 2, height-8.0); + else + params->style_functions->draw_separator (cr, colors, params, &separator, + 1.5, 4.0, 2, height-8.0); + } +} + +static void +clearlooks_glossy_draw_toolbar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ToolbarParameters *toolbar, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->bg[GTK_STATE_NORMAL]; + const CairoColor *dark = &colors->shade[3]; + CairoColor light; + ge_shade_color (fill, 1.1, &light); + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + if (toolbar->style == 1) /* Enable Extra features */ + { + cairo_pattern_t *pattern; + CairoColor shade1, shade2, shade3; + + ge_shade_color (fill, 1.08, &shade1); + ge_shade_color (fill, 1.04, &shade2); + ge_shade_color (fill, 1.04, &shade3); + + /* Draw the fill */ + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); + } + else /* Flat */ + { + ge_cairo_set_color (cr, fill); + cairo_paint (cr); + + if (!toolbar->topmost) + { + /* Draw highlight */ + cairo_move_to (cr, 0, 0.5); + cairo_line_to (cr, width-1, 0.5); + ge_cairo_set_color (cr, &light); + cairo_stroke (cr); + } + } + + /* Draw shadow */ + cairo_move_to (cr, 0, height-0.5); + cairo_line_to (cr, width-1, height-0.5); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_menuitem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + const CairoColor *border = &colors->spot[2]; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + ge_shade_color (fill, 1.16, &shade1); + ge_shade_color (fill, 1.08, &shade2); + ge_shade_color (fill, 1.08, &shade3); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, params->radius, params->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_menubaritem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + const CairoColor *border = &colors->spot[2]; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + ge_shade_color (fill, 1.16, &shade1); + ge_shade_color (fill, 1.08, &shade2); + ge_shade_color (fill, 1.08, &shade3); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, params->radius, params->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); +} + +static void +clearlooks_glossy_draw_selected_cell (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + CairoColor color; + + if (params->focus) + color = colors->base[params->state_type]; + else + color = colors->base[GTK_STATE_ACTIVE]; + + clearlooks_draw_glossy_gradient (cr, x, y, width, height, &color, params->disabled, 0.0, CR_CORNER_NONE); +} + + +static void +clearlooks_glossy_draw_radiobutton (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) +{ + const CairoColor *border; + const CairoColor *dot; + CairoColor shadow; + CairoColor highlight; + cairo_pattern_t *pt; + gboolean inconsistent; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); + + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; + + if (widget->disabled) + { + border = &colors->shade[5]; + dot = &colors->shade[6]; + } + else + { + if (widget->prelight) + border = &colors->spot[2]; + else + border = &colors->shade[6]; + dot = &colors->text[0]; + } + + ge_shade_color (&widget->parentbg, 0.9, &shadow); + ge_shade_color (&widget->parentbg, 1.1, &highlight); + + pt = cairo_pattern_create_linear (0, 0, 13, 13); + cairo_pattern_add_color_stop_rgb (pt, 0.0, shadow.r, shadow.b, shadow.g); + cairo_pattern_add_color_stop_rgba (pt, 0.5, shadow.r, shadow.b, shadow.g, 0.5); + cairo_pattern_add_color_stop_rgba (pt, 0.5, highlight.r, highlight.g, highlight.b, 0.5); + cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b); + + cairo_translate (cr, x, y); + + cairo_set_line_width (cr, 2); + cairo_arc (cr, 7, 7, 6, 0, G_PI*2); + cairo_set_source (cr, pt); + cairo_stroke (cr); + cairo_pattern_destroy (pt); + + cairo_set_line_width (cr, 1); + + cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2); + + if (!widget->disabled) + { + if (widget->prelight) + clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5); + else + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); + } + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + if (draw_bullet) + { + if (inconsistent) + { + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, 4); + + cairo_move_to(cr, 5, 7); + cairo_line_to(cr, 9, 7); + + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } + else + { + cairo_arc (cr, 7, 7, 3, 0, G_PI*2); + ge_cairo_set_color (cr, dot); + cairo_fill (cr); + + cairo_arc (cr, 6, 6, 1, 0, G_PI*2); + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + cairo_fill (cr); + } + } +} + +static void +clearlooks_glossy_draw_checkbox (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) +{ + const CairoColor *border; + const CairoColor *dot; + gboolean inconsistent = FALSE; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); + + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; + + if (widget->disabled) + { + border = &colors->shade[5]; + dot = &colors->shade[6]; + } + else + { + if (widget->prelight) + border = &colors->spot[2]; + else + border = &colors->shade[6]; + dot = &colors->text[GTK_STATE_NORMAL]; + } + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + if (widget->xthickness > 2 && widget->ythickness > 2) + { + widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5, + width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 1.5, 1.5, + width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } + else + { + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, + width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } + + if (!widget->disabled) + { + if (widget->prelight) + clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5); + else + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); + } + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + if (draw_bullet) + { + if (inconsistent) /* Inconsistent */ + { + cairo_set_line_width (cr, 2.0); + cairo_move_to (cr, 3, height*0.5); + cairo_line_to (cr, width-3, height*0.5); + } + else + { + cairo_set_line_width (cr, 1.7); + cairo_move_to (cr, 0.5 + (width*0.2), (height*0.5)); + cairo_line_to (cr, 0.5 + (width*0.4), (height*0.7)); + + cairo_curve_to (cr, 0.5 + (width*0.4), (height*0.7), + 0.5 + (width*0.5), (height*0.4), + 0.5 + (width*0.70), (height*0.25)); + + } + + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } +} + +void +clearlooks_register_style_glossy (ClearlooksStyleFunctions *functions) +{ + functions->draw_inset = clearlooks_glossy_draw_inset; + functions->draw_button = clearlooks_glossy_draw_button; + functions->draw_progressbar_trough = clearlooks_glossy_draw_progressbar_trough; + functions->draw_progressbar_fill = clearlooks_glossy_draw_progressbar_fill; + functions->draw_scale_trough = clearlooks_glossy_draw_scale_trough; + functions->draw_tab = clearlooks_glossy_draw_tab; + functions->draw_slider = clearlooks_glossy_draw_slider; + functions->draw_slider_button = clearlooks_glossy_draw_slider_button; + functions->draw_scrollbar_stepper = clearlooks_glossy_draw_scrollbar_stepper; + functions->draw_scrollbar_slider = clearlooks_glossy_draw_scrollbar_slider; + functions->draw_list_view_header = clearlooks_glossy_draw_list_view_header; + functions->draw_toolbar = clearlooks_glossy_draw_toolbar; + functions->draw_menuitem = clearlooks_glossy_draw_menuitem; + functions->draw_menubaritem = clearlooks_glossy_draw_menubaritem; + functions->draw_selected_cell = clearlooks_glossy_draw_selected_cell; + functions->draw_checkbox = clearlooks_glossy_draw_checkbox; + functions->draw_radiobutton = clearlooks_glossy_draw_radiobutton; +} diff --git a/libs/clearlooks/clearlooks_draw_gummy.c b/libs/clearlooks/clearlooks_draw_gummy.c new file mode 100644 index 0000000000..e2a990230b --- /dev/null +++ b/libs/clearlooks/clearlooks_draw_gummy.c @@ -0,0 +1,1524 @@ +/* Clearlooks Gummy style + * Copyright (C) 2007 Andrea Cimitan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Written by Andrea Cimitan <andrea.cimitan@gmail.com> + */ + +#include "clearlooks_draw.h" +#include "clearlooks_style.h" +#include "clearlooks_types.h" + +#include "support.h" +#include <ge-support.h> + +#include <cairo.h> + +/* Normal shadings */ +#define SHADE_TOP 1.08 +#define SHADE_CENTER_TOP 1.02 +#define SHADE_BOTTOM 0.94 + +/* Topleft highlight */ +#define TOPLEFT_HIGHLIGHT_SHADE 1.3 +#define TOPLEFT_HIGHLIGHT_ALPHA 0.4 + +/* Listview */ +#define LISTVIEW_SHADE_TOP 1.06 +#define LISTVIEW_SHADE_CENTER_TOP 1.02 +#define LISTVIEW_SHADE_BOTTOM 0.96 + +/* Toolbar */ +#define TOOLBAR_SHADE_TOP 1.04 +#define TOOLBAR_SHADE_CENTER_TOP 1.01 +#define TOOLBAR_SHADE_BOTTOM 0.97 + + +static void +clearlooks_draw_gummy_gradient (cairo_t *cr, + double x, double y, int width, int height, + const CairoColor *color, + gboolean disabled, gboolean radius, CairoCorners corners) +{ + CairoColor fill; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pt; + + ge_shade_color (color, disabled? 1.04 : SHADE_TOP, &shade1); + ge_shade_color (color, disabled? 1.01 : SHADE_CENTER_TOP, &shade2); + ge_shade_color (color, disabled? 0.99 : 1.0, &fill); + ge_shade_color (color, disabled? 0.96 : SHADE_BOTTOM, &shade3); + + pt = cairo_pattern_create_linear (x, y, x, y+height); + cairo_pattern_add_color_stop_rgb (pt, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pt, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pt, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb (pt, 1.0, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pt); + ge_cairo_rounded_rectangle (cr, x, y, width, height, radius, corners); + cairo_fill (cr); + + cairo_pattern_destroy (pt); +} + +static void +clearlooks_set_mixed_color (cairo_t *cr, + const CairoColor *color1, + const CairoColor *color2, + gdouble mix_factor) +{ + CairoColor composite; + + ge_mix_color (color1, color2, mix_factor, &composite); + ge_cairo_set_color (cr, &composite); +} + +static void +clearlooks_gummy_draw_highlight_and_shade (cairo_t *cr, + const CairoColor *bg_color, + const ShadowParameters *params, + int width, int height, gdouble radius) +{ + CairoColor shadow; + CairoColor highlight; + uint8 corners = params->corners; + double x = 1.0; + double y = 1.0; + + /* not really sure of shading ratios... we will think */ + ge_shade_color (bg_color, 0.8, &shadow); + ge_shade_color (bg_color, 1.2, &highlight); + + cairo_save (cr); + + /* Top/Left highlight */ + if (corners & CR_CORNER_BOTTOMLEFT) + cairo_move_to (cr, x, y+height-radius); + else + cairo_move_to (cr, x, y+height); + + ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT); + + if (corners & CR_CORNER_TOPRIGHT) + cairo_line_to (cr, x+width-radius, y); + else + cairo_line_to (cr, x+width, y); + + if (params->shadow & CL_SHADOW_OUT) + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + else + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5); + + cairo_stroke (cr); + + /* Bottom/Right highlight -- this includes the corners */ + cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */ + ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT); + ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT); + + if (params->shadow & CL_SHADOW_OUT) + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5); + else + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + + cairo_stroke (cr); + + cairo_restore (cr); +} + +static void +clearlooks_gummy_draw_top_left_highlight (cairo_t *cr, const CairoColor *color, + const WidgetParameters *params, + int width, int height, gdouble radius) +{ + CairoColor hilight; + + double light_top = params->ythickness-1, + light_bottom = height - params->ythickness - 1, + light_left = params->xthickness-1, + light_right = width - params->xthickness - 1; + + ge_shade_color (color, TOPLEFT_HIGHLIGHT_SHADE, &hilight); + cairo_move_to (cr, light_left, light_bottom - (int)radius/2); + + ge_cairo_rounded_corner (cr, light_left, light_top, radius, params->corners & CR_CORNER_TOPLEFT); + + cairo_line_to (cr, light_right - (int)radius/2, light_top); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, TOPLEFT_HIGHLIGHT_ALPHA); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + double xoffset = 0, yoffset = 0; + CairoColor fill = colors->bg[params->state_type]; + CairoColor border_normal = colors->shade[6]; + CairoColor border_disabled = colors->shade[4]; + double radius; + + cairo_pattern_t *pattern; + + cairo_save (cr); + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + /* Shadows and Glow */ + if (params->xthickness == 3 || params->ythickness == 3) + { + if (params->xthickness == 3) + xoffset = 1; + if (params->ythickness == 3) + yoffset = 1; + } + + radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0, (height - 2.0 - 2*yoffset) / 2.0)); + + if (params->xthickness == 3 || params->ythickness == 3) + { + cairo_translate (cr, 0.5, 0.5); + + if (params->enable_glow && !params->active && !params->disabled && !params->is_default) + { + CairoColor shadow; + + radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0 - 1.0, (height - 2.0 - 2*yoffset) / 2.0 - 1.0)); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius+1, params->corners); + ge_shade_color (¶ms->parentbg, 0.97, &shadow); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius+1, params->corners); + ge_shade_color (¶ms->parentbg, 0.93, &shadow); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + + if (params->is_default) + { + CairoColor shadow = colors->spot[1]; + + radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0 - 1.0, (height - 2.0 - 2*yoffset) / 2.0 - 1.0)); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius+1, params->corners); + clearlooks_set_mixed_color (cr, ¶ms->parentbg, &shadow, 0.5); + cairo_stroke (cr); + } + + if (!(params->enable_glow && !params->active && !params->disabled)) + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, params->radius+1, params->corners); + cairo_translate (cr, -0.5, -0.5); + } + + clearlooks_draw_gummy_gradient (cr, xoffset+1, yoffset+1, + width-(xoffset*2)-2, height-(yoffset*2)-2, + &fill, params->disabled, radius, params->corners); + + /* Pressed button shadow */ + if (params->active) + { + CairoColor shadow; + ge_shade_color (&fill, 0.92, &shadow); + + cairo_save (cr); + + ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, height, radius, + params->corners & (CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMLEFT)); + cairo_clip (cr); + cairo_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, 3); + + pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+1, yoffset+4); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_rectangle (cr, xoffset+1, yoffset+1, 3, height-(yoffset*2)-2); + + pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+4, yoffset+1); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); + } + + /* Border */ + if (params->is_default) /* || (params->prelight && params->enable_glow)) */ + border_normal = colors->spot[2]; + if (params->disabled) + ge_cairo_set_color (cr, &border_disabled); + else + clearlooks_set_mixed_color (cr, &border_normal, &fill, 0.2); + ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, + width-(xoffset*2)-1, height-(yoffset*2)-1, + radius, params->corners); + cairo_stroke (cr); + + if (!params->active) + { + cairo_translate (cr, 0.5, 0.5); + clearlooks_gummy_draw_top_left_highlight (cr, &fill, params, width, height, radius); + } + cairo_restore (cr); +} + +static void +clearlooks_gummy_draw_entry (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *base = &colors->base[params->state_type]; + CairoColor border = colors->shade[params->disabled ? 4 : 6]; + double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0)); + + if (params->focus) + border = colors->spot[2]; + + cairo_translate (cr, x+0.5, y+0.5); + cairo_set_line_width (cr, 1.0); + + /* Fill the background to get the correct corners. */ + cairo_rectangle (cr, -0.5, -0.5, width, height); + ge_cairo_set_color (cr, ¶ms->parentbg); + cairo_fill (cr); + + /* Fill with the base color, because it was just cleared above */ + cairo_rectangle (cr, 1.5, 1.5, width-4, height-4); + ge_cairo_set_color (cr, base); + cairo_fill (cr); + + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners); + + /* Draw the inner shadow */ + if (params->focus) + { + /* ge_cairo_rounded_rectangle (cr, 2, 2, width-5, height-5, RADIUS-1, params->corners); */ + ge_cairo_set_color (cr, &colors->spot[0]); + ge_cairo_stroke_rectangle (cr, 2, 2, width-5, height-5); + } + else + { + CairoColor shadow; + ge_shade_color (&border, 0.92, &shadow); + + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, params->disabled ? 0.09 : 0.18); + /* + cairo_move_to (cr, 2, height-3); + cairo_arc (cr, params->xthickness+RADIUS-1, params->ythickness+RADIUS-1, RADIUS, G_PI, 270*(G_PI/180)); + cairo_line_to (cr, width-3, 2); + */ + cairo_move_to (cr, 2, height-3); + cairo_line_to (cr, 2, 2); + cairo_line_to (cr, width-3, 2); + cairo_stroke (cr); + } + + ge_cairo_rounded_rectangle (cr, 1, 1, width-3, height-3, radius, params->corners); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_progressbar_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[7]; + CairoColor shadow; + cairo_pattern_t *pattern; + double radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0)); + + cairo_save (cr); + + cairo_set_line_width (cr, 1.0); + + /* Fill with bg color */ + ge_cairo_set_color (cr, &colors->bg[params->state_type]); + + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + + /* Create trough box */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + ge_cairo_set_color (cr, &colors->shade[2]); + cairo_fill (cr); + + /* Draw border */ + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width-1, height-1, radius, params->corners); + clearlooks_set_mixed_color (cr, border, &colors->shade[2], 0.3); + cairo_stroke (cr); + + /* clip the corners of the shadows */ + ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners); + cairo_clip (cr); + + ge_shade_color (border, 0.92, &shadow); + + /* Top shadow */ + cairo_rectangle (cr, x+1, y+1, width-2, 4); + pattern = cairo_pattern_create_linear (x, y, x, y+4); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Left shadow */ + cairo_rectangle (cr, x+1, y+1, 4, height-2); + pattern = cairo_pattern_create_linear (x, y, x+4, y); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); +} + +static void +clearlooks_gummy_draw_progressbar_fill (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ProgressBarParameters *progressbar, + int x, int y, int width, int height, gint offset) +{ + boolean is_horizontal = progressbar->orientation < 2; + double tile_pos = 0; + double stroke_width; + double radius; + int x_step; + + cairo_pattern_t *pattern; + CairoColor shade1, shade2, shade3; + CairoColor border; + CairoColor shadow; + + radius = MAX (0, params->radius - params->xthickness); + + cairo_save (cr); + + if (!is_horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + if ((progressbar->orientation == CL_ORIENTATION_RIGHT_TO_LEFT) || (progressbar->orientation == CL_ORIENTATION_BOTTOM_TO_TOP)) + ge_cairo_mirror (cr, CR_MIRROR_HORIZONTAL, &x, &y, &width, &height); + + /* Clamp the radius so that the _height_ fits ... */ + radius = MIN (radius, height / 2.0); + + stroke_width = height*2; + x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */ + + cairo_translate (cr, x, y); + + cairo_save (cr); + /* This is kind of nasty ... Clip twice from each side in case the length + * of the fill is smaller than twice the radius. */ + ge_cairo_rounded_rectangle (cr, 0, 0, width + radius, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + /* Draw the background gradient */ + ge_shade_color (&colors->spot[1], SHADE_TOP, &shade1); + ge_shade_color (&colors->spot[1], SHADE_CENTER_TOP, &shade2); + ge_shade_color (&colors->spot[1], SHADE_BOTTOM, &shade3); + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, colors->spot[1].r, colors->spot[1].g, colors->spot[1].b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade3.r, shade3.g, shade3.b); + cairo_set_source (cr, pattern); + cairo_paint (cr); + cairo_pattern_destroy (pattern); + + /* Draw the Strokes */ + while (tile_pos <= width+x_step) + { + cairo_move_to (cr, stroke_width/2-x_step, 0); + cairo_line_to (cr, stroke_width-x_step, 0); + cairo_line_to (cr, stroke_width/2-x_step, height); + cairo_line_to (cr, -x_step, height); + + cairo_translate (cr, stroke_width, 0); + tile_pos += stroke_width; + } + + cairo_set_source_rgba (cr, colors->spot[2].r, + colors->spot[2].g, + colors->spot[2].b, + 0.15); + + cairo_fill (cr); + cairo_restore (cr); /* rounded clip region */ + + /* inner highlight border + * This is again kinda ugly. Draw once from each side, clipping away the other. */ + cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.2); + + /* left side */ + cairo_save (cr); + cairo_rectangle (cr, 0, 0, width / 2, height); + cairo_clip (cr); + + if (progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + else + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + /* right side */ + cairo_save (cr); + cairo_rectangle (cr, width / 2, 0, (width+1) / 2, height); + cairo_clip (cr); + + if (progressbar->value < 1.0 || progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, -1.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + else + ge_cairo_rounded_rectangle (cr, -0.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + + /* Draw the dark lines and the shadow */ + cairo_save (cr); + /* Again, this weird clip area. */ + ge_cairo_rounded_rectangle (cr, -1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius - 1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + border = colors->spot[2]; + border.a = 0.6; + ge_shade_color (&colors->shade[7], 0.92, &shadow); + shadow.a = 0.2; + + if (progressbar->pulsing) + { + /* At the beginning of the bar. */ + cairo_move_to (cr, 0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, 0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, -0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, -0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, -0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + if (progressbar->value < 1.0 || progressbar->pulsing) + { + /* At the end of the bar. */ + cairo_move_to (cr, width - 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width - 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width - 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, width + 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width + 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width + 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + + cairo_restore (cr); + + cairo_restore (cr); /* rotation, mirroring */ +} + +static void +clearlooks_gummy_scale_draw_gradient (cairo_t *cr, + const CairoColor *fill, + const CairoColor *border, + int x, int y, int width, int height, + gboolean horizontal, gboolean in) +{ + cairo_pattern_t *pattern; + + CairoColor f1, f2; + + ge_shade_color (fill, in? 0.95 : 1.1, &f1); + ge_shade_color (fill, in? 1.05 : 0.9, &f2); + + pattern = cairo_pattern_create_linear (0, 0, horizontal ? 0 : width, horizontal ? height : 0); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, f1.r, f1.g, f1.b, f1.a); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, f2.r, f2.g, f2.b, f2.a); + + cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + clearlooks_set_mixed_color (cr, border, fill, 0.2); + ge_cairo_stroke_rectangle (cr, x, y, width, height); +} + +#define TROUGH_SIZE 6 +static void +clearlooks_gummy_draw_scale_trough (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + int trough_width, trough_height; + double translate_x, translate_y; + + if (slider->horizontal) + { + trough_width = width-3; + trough_height = TROUGH_SIZE-2; + + translate_x = x + 0.5; + translate_y = y + 0.5 + (height/2) - (TROUGH_SIZE/2); + } + else + { + trough_width = TROUGH_SIZE-2; + trough_height = height-3; + + translate_x = x + 0.5 + (width/2) - (TROUGH_SIZE/2); + translate_y = y + 0.5; + } + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, translate_x, translate_y); + + if (!slider->fill_level) + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0); + + cairo_translate (cr, 1, 1); + + if (!slider->lower && !slider->fill_level) + clearlooks_gummy_scale_draw_gradient (cr, + &colors->shade[2], /* bottom */ + &colors->shade[6], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal, TRUE); + else if (!slider->fill_level) + clearlooks_gummy_scale_draw_gradient (cr, + &colors->spot[1], /* bottom */ + &colors->spot[2], /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal, FALSE); + else { + CairoColor c1 = colors->spot[1]; + CairoColor c2 = colors->spot[2]; + + c1.a = 0.25; + c2.a = 0.25; + + clearlooks_gummy_scale_draw_gradient (cr, + &c1, /* bottom */ + &c2, /* border */ + 0, 0, trough_width, trough_height, + slider->horizontal, FALSE); + } + +} + +static void +clearlooks_gummy_draw_tab (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const TabParameters *tab, + int x, int y, int width, int height) +{ + + const CairoColor *border = &colors->shade[5]; + const CairoColor *stripe_fill = &colors->spot[1]; + const CairoColor *stripe_border = &colors->spot[2]; + const CairoColor *fill; + + cairo_pattern_t *pattern; + + double radius; + double strip_size; + + radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + /* Set clip */ + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + cairo_new_path (cr); + + /* Translate and set line width */ + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y+0.5); + + /* Make the tabs slightly bigger than they should be, to create a gap */ + /* And calculate the strip size too, while you're at it */ + if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM) + { + height += 3.0; + strip_size = 2.0/height; /* 2 pixel high strip */ + + if (tab->gap_side == CL_GAP_TOP) + cairo_translate (cr, 0.0, -3.0); /* gap at the other side */ + } + else + { + width += 3.0; + strip_size = 2.0/width; + + if (tab->gap_side == CL_GAP_LEFT) + cairo_translate (cr, -3.0, 0.0); /* gap at the other side */ + } + + /* Set the fill color */ + fill = &colors->bg[params->state_type]; + + /* Set tab shape */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, + radius, params->corners); + + /* Draw fill */ + ge_cairo_set_color (cr, fill); + cairo_fill (cr); + + /* Draw highlight */ + if (!params->active) + { + ShadowParameters shadow; + + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = params->corners; + + clearlooks_gummy_draw_highlight_and_shade (cr, &colors->bg[0], &shadow, + width, height, radius); + } + + if (params->active) + { + CairoColor hilight; + CairoColor shade1, shade2, shade3; + + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-1 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 1, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + ge_shade_color (fill, 1.14, &hilight); + ge_shade_color (fill, SHADE_TOP, &shade1); + ge_shade_color (fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color (fill, SHADE_BOTTOM, &shade3); + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, hilight.r, hilight.g, hilight.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, hilight.r, hilight.g, hilight.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.45, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.45, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade3.r, shade3.g, shade3.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + else + { + /* Draw shade */ + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-2 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 0, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + cairo_pattern_add_color_stop_rgba (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b, 0.5); + cairo_pattern_add_color_stop_rgba (pattern, 0.8, fill->r, fill->g, fill->b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + if (params->active) + { + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + } + else + { + pattern = cairo_pattern_create_linear (tab->gap_side == CL_GAP_LEFT ? width-2 : 2, + tab->gap_side == CL_GAP_TOP ? height-2 : 2, + tab->gap_side == CL_GAP_RIGHT ? width : 2, + tab->gap_side == CL_GAP_BOTTOM ? height : 2); + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, 0.8, border->r, border->g, border->b); + cairo_set_source (cr, pattern); + cairo_stroke (cr); + cairo_pattern_destroy (pattern); + } +} + +static void +clearlooks_gummy_draw_separator (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SeparatorParameters *separator, + int x, int y, int width, int height) +{ + CairoColor color = colors->shade[3]; + CairoColor hilight; + ge_shade_color (&color, 1.3, &hilight); + + cairo_save (cr); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT); + + if (separator->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, 0.0); + ge_cairo_set_color (cr, &color); + cairo_stroke (cr); + + cairo_move_to (cr, 0.0, 1.0); + cairo_line_to (cr, width, 1.0); + ge_cairo_set_color (cr, &hilight); + 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); + ge_cairo_set_color (cr, &color); + cairo_stroke (cr); + + cairo_move_to (cr, 1.0, 0.0); + cairo_line_to (cr, 1.0, height); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); + } + + cairo_restore (cr); +} + +static void +clearlooks_gummy_draw_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[7]; + CairoColor fill; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + int bar_x, i; + int shift_x; + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + cairo_translate (cr, -0.5, -0.5); + + ge_shade_color (&colors->bg[params->state_type], 1.0, &fill); + if (params->prelight) + ge_shade_color (&fill, 1.04, &fill); + + ge_shade_color (&fill, SHADE_TOP, &shade1); + ge_shade_color (&fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color (&fill, SHADE_BOTTOM, &shade3); + + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb(pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, shade3.r, shade3.g, shade3.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + clearlooks_set_mixed_color (cr, border, &fill, 0.2); + if (params->prelight) + ge_cairo_set_color (cr, &colors->spot[2]); + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, 2.5, params->corners); + cairo_stroke (cr); + + /* Handle */ + shift_x = (width%2 == 0 ? 1 : 0); + bar_x = width/2-3+shift_x; + cairo_translate (cr, 0.5, 0.5); + ge_cairo_set_color (cr, border); + for (i=0; i<3-shift_x; i++) + { + cairo_move_to (cr, bar_x, 4); + cairo_line_to (cr, bar_x, height-5); + bar_x += 3; + } + cairo_stroke (cr); + + clearlooks_gummy_draw_top_left_highlight (cr, &fill, params, width, height, 2.0); +} + +static void +clearlooks_gummy_draw_slider_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0)); + + cairo_set_line_width (cr, 1.0); + + if (!slider->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x+0.5, y+0.5); + + params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1); + params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2); +} + +static void +clearlooks_gummy_draw_scrollbar_stepper (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + const ScrollBarStepperParameters *stepper, + int x, int y, int width, int height) +{ + CairoCorners corners = CR_CORNER_NONE; + const CairoColor *border = &colors->shade[scrollbar->has_color ? 7 : 6]; + CairoColor fill; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + ShadowParameters shadow; + double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + if (scrollbar->horizontal) + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; + } + else + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT; + } + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners); + + if (scrollbar->horizontal) + pattern = cairo_pattern_create_linear (0, 0, 0, height); + else + pattern = cairo_pattern_create_linear (0, 0, width, 0); + + fill = colors->bg[widget->state_type]; + ge_shade_color(&fill, SHADE_TOP, &shade1); + ge_shade_color(&fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color(&fill, SHADE_BOTTOM, &shade3); + + cairo_pattern_add_color_stop_rgb(pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb(pattern, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, shade3.r, shade3.g, shade3.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_translate (cr, 0.5, 0.5); + clearlooks_gummy_draw_top_left_highlight (cr, &fill, widget, width, height, (stepper->stepper == CL_STEPPER_A) ? radius : 0); + cairo_translate (cr, -0.5, -0.5); + + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners); + clearlooks_set_mixed_color (cr, border, &fill, 0.2); + cairo_stroke (cr); + + cairo_translate (cr, 0.5, 0.5); + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = corners; +} + +static void +clearlooks_gummy_draw_scrollbar_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height) +{ + CairoColor fill = scrollbar->color; + CairoColor border, handles; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + int bar_x, i; + + gdouble hue_scroll, brightness_scroll, saturation_scroll; + gdouble hue_bg, brightness_bg, saturation_bg; + + ge_hsb_from_color (&fill, &hue_scroll, &saturation_scroll, &brightness_scroll); + ge_hsb_from_color (&colors->bg[0], &hue_bg, &saturation_bg, &brightness_bg); + + /* Set the right color for border and handles */ + if ((fabs(saturation_scroll - saturation_bg) < 0.30) && + (fabs(brightness_scroll - brightness_bg) < 0.20)) + ge_shade_color (&fill, 0.475, &border); + else + ge_shade_color (&fill, 0.575, &border); + /* The following lines increase contrast when the HUE is between 25 and 195, */ + /* fixing a LOT of colorschemes! */ + if (scrollbar->has_color && (hue_scroll < 195) && (hue_scroll > 25)) + ge_shade_color (&border, 0.85, &border); + + handles = border; + ge_mix_color (&border, &fill, scrollbar->has_color? 0.3 : 0.2, &border); + + if (scrollbar->junction & CL_JUNCTION_BEGIN) + { + if (scrollbar->horizontal) + { + x -= 1; + width += 1; + } + else + { + y -= 1; + height += 1; + } + } + if (scrollbar->junction & CL_JUNCTION_END) + { + if (scrollbar->horizontal) + width += 1; + else + height += 1; + } + + if (!scrollbar->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x, y); + + if (widget->prelight) + ge_shade_color (&fill, 1.04, &fill); + + cairo_set_line_width (cr, 1); + + ge_shade_color (&fill, TOPLEFT_HIGHLIGHT_SHADE, &hilight); + ge_shade_color (&fill, SHADE_TOP, &shade1); + ge_shade_color (&fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color (&fill, SHADE_BOTTOM, &shade3); + + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + if (scrollbar->has_color) + { + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.2); + ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3); + } + else + { + cairo_move_to (cr, 1.5, height-1.5); + cairo_line_to (cr, 1.5, 1.5); + cairo_line_to (cr, width-1.5, 1.5); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, TOPLEFT_HIGHLIGHT_ALPHA); + cairo_stroke(cr); + } + + ge_cairo_set_color (cr, &border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); + + /* Handle */ + bar_x = width/2 - 4; + cairo_translate(cr, 0.5, 0.5); + ge_cairo_set_color (cr, &handles); + for (i=0; i<3; i++) + { + cairo_move_to (cr, bar_x, 5); + cairo_line_to (cr, bar_x, height-6); + bar_x += 3; + } + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_list_view_header (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ListViewHeaderParameters *header, + int x, int y, int width, int height) +{ +/* + CairoColor *border = !params->prelight? (CairoColor*)&colors->shade[4] : (CairoColor*)&colors->spot[1]; +*/ + const CairoColor *border = &colors->shade[4]; + const CairoColor *fill = &colors->bg[params->state_type]; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + + cairo_pattern_t *pattern; + + ge_shade_color (fill, 1.11, &hilight); + ge_shade_color (fill, LISTVIEW_SHADE_TOP, &shade1); + ge_shade_color (fill, LISTVIEW_SHADE_CENTER_TOP, &shade2); + ge_shade_color (fill, LISTVIEW_SHADE_BOTTOM, &shade3); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + /* Draw the fill */ + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0-1.0/height, shade3.r, shade3.g, shade3.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0-1.0/height, border->r, border->g, border->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, border->r, border->g, border->b); + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); + + /* Draw highlight */ + if (header->order == CL_ORDER_FIRST) + { + cairo_move_to (cr, 0.5, height-1.5); + cairo_line_to (cr, 0.5, 0.5); + } + else + cairo_move_to (cr, 0.0, 0.5); + + cairo_line_to (cr, width, 0.5); + + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); + + /* Draw resize grip */ + if ((params->ltr && header->order != CL_ORDER_LAST) || + (!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable) + { + SeparatorParameters separator; + separator.horizontal = FALSE; + + if (params->ltr) + params->style_functions->draw_separator (cr, colors, params, &separator, + width-1.5, 4.0, 2, height-8.0); + else + params->style_functions->draw_separator (cr, colors, params, &separator, + 1.5, 4.0, 2, height-8.0); + } +} + +static void +clearlooks_gummy_draw_toolbar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ToolbarParameters *toolbar, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->bg[GTK_STATE_NORMAL]; + const CairoColor *dark = &colors->shade[3]; + CairoColor light; + ge_shade_color (fill, toolbar->style == 1 ? 1.1 : 1.05, &light); + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + if (toolbar->style == 1) /* Enable Extra features */ + { + cairo_pattern_t *pattern; + CairoColor shade1, shade2, shade3; + + ge_shade_color (fill, TOOLBAR_SHADE_TOP, &shade1); + ge_shade_color (fill, TOOLBAR_SHADE_CENTER_TOP, &shade2); + ge_shade_color (fill, TOOLBAR_SHADE_BOTTOM, &shade3); + + /* Draw the fill */ + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_pattern_destroy (pattern); + } + else /* Flat */ + { + ge_cairo_set_color (cr, fill); + cairo_paint (cr); + } + + if (!toolbar->topmost) + { + /* Draw highlight */ + cairo_move_to (cr, 0, 0.5); + cairo_line_to (cr, width-1, 0.5); + ge_cairo_set_color (cr, &light); + cairo_stroke (cr); + } + + /* Draw shadow */ + cairo_move_to (cr, 0, height-0.5); + cairo_line_to (cr, width-1, height-0.5); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_menuitem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + const CairoColor *border = &colors->spot[2]; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + ge_shade_color (fill, SHADE_TOP, &shade1); + ge_shade_color (fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color (fill, SHADE_BOTTOM, &shade3); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, params->radius, params->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_menubaritem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + const CairoColor *border = &colors->spot[2]; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + ge_shade_color (fill, SHADE_TOP, &shade1); + ge_shade_color (fill, SHADE_CENTER_TOP, &shade2); + ge_shade_color (fill, SHADE_BOTTOM, &shade3); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, params->radius, params->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, fill->r, fill->g, fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, shade3.r, shade3.g, shade3.b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_selected_cell (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + CairoColor color; + + if (params->focus) + color = colors->base[params->state_type]; + else + color = colors->base[GTK_STATE_ACTIVE]; + + clearlooks_draw_gummy_gradient (cr, x, y, width, height, &color, params->disabled, 0.0, CR_CORNER_NONE); +} + +static void +clearlooks_gummy_draw_statusbar (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + const CairoColor *dark = &colors->shade[3]; + CairoColor hilight; + + ge_shade_color (dark, 1.3, &hilight); + + cairo_set_line_width (cr, 1); + cairo_translate (cr, x, y+0.5); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, width, 0); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); + + cairo_translate (cr, 0, 1); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, width, 0); + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); +} + +static void +clearlooks_gummy_draw_radiobutton (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) +{ + const CairoColor *border; + const CairoColor *dot; + CairoColor shadow; + CairoColor highlight; + cairo_pattern_t *pt; + gboolean inconsistent; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); + + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; + + if (widget->disabled) + { + border = &colors->shade[5]; + dot = &colors->shade[6]; + } + else + { + if (widget->prelight) + border = &colors->spot[2]; + else + border = &colors->shade[6]; + dot = &colors->text[0]; + } + + ge_shade_color (&widget->parentbg, 0.9, &shadow); + ge_shade_color (&widget->parentbg, 1.1, &highlight); + + pt = cairo_pattern_create_linear (0, 0, 13, 13); + cairo_pattern_add_color_stop_rgb (pt, 0.0, shadow.r, shadow.b, shadow.g); + cairo_pattern_add_color_stop_rgba (pt, 0.5, shadow.r, shadow.b, shadow.g, 0.5); + cairo_pattern_add_color_stop_rgba (pt, 0.5, highlight.r, highlight.g, highlight.b, 0.5); + cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b); + + cairo_translate (cr, x, y); + + cairo_set_line_width (cr, 2); + cairo_arc (cr, 7, 7, 6, 0, G_PI*2); + cairo_set_source (cr, pt); + cairo_stroke (cr); + cairo_pattern_destroy (pt); + + cairo_set_line_width (cr, 1); + + cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2); + + if (!widget->disabled) + { + if (widget->prelight) + clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5); + else + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); + } + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + if (draw_bullet) + { + if (inconsistent) + { + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, 4); + + cairo_move_to(cr, 5, 7); + cairo_line_to(cr, 9, 7); + + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } + else + { + cairo_arc (cr, 7, 7, 3, 0, G_PI*2); + ge_cairo_set_color (cr, dot); + cairo_fill (cr); + + cairo_arc (cr, 6, 6, 1, 0, G_PI*2); + cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5); + cairo_fill (cr); + } + } +} + +static void +clearlooks_gummy_draw_checkbox (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height) +{ + const CairoColor *border; + const CairoColor *dot; + gboolean inconsistent = FALSE; + gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN); + + inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN); + draw_bullet |= inconsistent; + + if (widget->disabled) + { + border = &colors->shade[5]; + dot = &colors->shade[6]; + } + else + { + if (widget->prelight) + border = &colors->spot[2]; + else + border = &colors->shade[6]; + dot = &colors->text[GTK_STATE_NORMAL]; + } + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + if (widget->xthickness > 2 && widget->ythickness > 2) + { + widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5, + width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 1.5, 1.5, + width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } + else + { + /* Draw the rectangle for the checkbox itself */ + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, + width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL); + } + + if (!widget->disabled) + { + if (widget->prelight) + clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5); + else + ge_cairo_set_color (cr, &colors->base[0]); + cairo_fill_preserve (cr); + } + + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + if (draw_bullet) + { + if (inconsistent) /* Inconsistent */ + { + cairo_set_line_width (cr, 2.0); + cairo_move_to (cr, 3, height*0.5); + cairo_line_to (cr, width-3, height*0.5); + } + else + { + cairo_set_line_width (cr, 1.7); + cairo_move_to (cr, 0.5 + (width*0.2), (height*0.5)); + cairo_line_to (cr, 0.5 + (width*0.4), (height*0.7)); + + cairo_curve_to (cr, 0.5 + (width*0.4), (height*0.7), + 0.5 + (width*0.5), (height*0.4), + 0.5 + (width*0.70), (height*0.25)); + + } + + ge_cairo_set_color (cr, dot); + cairo_stroke (cr); + } +} + +void +clearlooks_register_style_gummy (ClearlooksStyleFunctions *functions) +{ + functions->draw_button = clearlooks_gummy_draw_button; + functions->draw_entry = clearlooks_gummy_draw_entry; + functions->draw_progressbar_trough = clearlooks_gummy_draw_progressbar_trough; + functions->draw_progressbar_fill = clearlooks_gummy_draw_progressbar_fill; + functions->draw_scale_trough = clearlooks_gummy_draw_scale_trough; + functions->draw_tab = clearlooks_gummy_draw_tab; + functions->draw_separator = clearlooks_gummy_draw_separator; + functions->draw_slider = clearlooks_gummy_draw_slider; + functions->draw_slider_button = clearlooks_gummy_draw_slider_button; + functions->draw_scrollbar_stepper = clearlooks_gummy_draw_scrollbar_stepper; + functions->draw_scrollbar_slider = clearlooks_gummy_draw_scrollbar_slider; + functions->draw_list_view_header = clearlooks_gummy_draw_list_view_header; + functions->draw_toolbar = clearlooks_gummy_draw_toolbar; + functions->draw_menuitem = clearlooks_gummy_draw_menuitem; + functions->draw_menubaritem = clearlooks_gummy_draw_menubaritem; + functions->draw_selected_cell = clearlooks_gummy_draw_selected_cell; + functions->draw_statusbar = clearlooks_gummy_draw_statusbar; + functions->draw_checkbox = clearlooks_gummy_draw_checkbox; + functions->draw_radiobutton = clearlooks_gummy_draw_radiobutton; +} diff --git a/libs/clearlooks/clearlooks_draw_inverted.c b/libs/clearlooks/clearlooks_draw_inverted.c new file mode 100644 index 0000000000..2e8ee3bcd7 --- /dev/null +++ b/libs/clearlooks/clearlooks_draw_inverted.c @@ -0,0 +1,1002 @@ +/* Clearlooks Inverted style + * Copyright (C) 2007 Andrea Cimitan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Written by Andrea Cimitan <andrea.cimitan@gmail.com> + */ + +#include "clearlooks_draw.h" +#include "clearlooks_style.h" +#include "clearlooks_types.h" + +#include "support.h" +#include <ge-support.h> + +#include <cairo.h> + + +static void +clearlooks_draw_top_left_highlight (cairo_t *cr, + const CairoColor *color, + const WidgetParameters *params, + int width, int height, gdouble radius) +{ + CairoColor hilight; + + double light_top = params->ythickness-1, + light_bottom = height - params->ythickness - 1, + light_left = params->xthickness-1, + light_right = width - params->xthickness - 1; + + ge_shade_color (color, 1.3, &hilight); + cairo_move_to (cr, light_left, light_bottom - (int)radius/2); + + ge_cairo_rounded_corner (cr, light_left, light_top, radius, params->corners & CR_CORNER_TOPLEFT); + + cairo_line_to (cr, light_right - (int)radius/2, light_top); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.7); + cairo_stroke (cr); +} + +static void +clearlooks_set_border_gradient (cairo_t *cr, const CairoColor *color, double hilight, int width, int height) +{ + cairo_pattern_t *pattern; + + CairoColor bottom_shade; + ge_shade_color (color, hilight, &bottom_shade); + + pattern = cairo_pattern_create_linear (0, 0, width, height); + cairo_pattern_add_color_stop_rgb (pattern, 0, color->r, color->g, color->b); + cairo_pattern_add_color_stop_rgb (pattern, 1, bottom_shade.r, bottom_shade.g, bottom_shade.b); + + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); +} + +static void +clearlooks_inverted_draw_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + double xoffset = 0, yoffset = 0; + double radius = params->radius; + const CairoColor *fill = &colors->bg[params->state_type]; + const CairoColor *border_disabled = &colors->shade[4]; + CairoColor border_normal; + CairoColor shadow; + + ge_shade_color(&colors->shade[6], 1.05, &border_normal); + ge_shade_color (&border_normal, 0.925, &shadow); + + cairo_save (cr); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + if (params->xthickness == 3 || params->ythickness == 3) + { + if (params->xthickness == 3) + xoffset = 1; + if (params->ythickness == 3) + yoffset = 1; + } + + radius = MIN (radius, MIN ((width - 2.0 - xoffset * 2.0) / 2.0, (height - 2.0 - yoffset * 2) / 2.0)); + + if (params->xthickness == 3 || params->ythickness == 3) + { + cairo_translate (cr, 0.5, 0.5); + params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners); + cairo_translate (cr, -0.5, -0.5); + } + + ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, + width-(xoffset*2)-2, + height-(yoffset*2)-2, + radius, params->corners); + + if (!params->active) + { + cairo_pattern_t *pattern; + + CairoColor top_shade, bottom_shade; + ge_shade_color (fill, 0.95, &top_shade); + ge_shade_color (fill, 1.05, &bottom_shade); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, top_shade.r, top_shade.g, top_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bottom_shade.r, bottom_shade.g, bottom_shade.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + else + { + cairo_pattern_t *pattern; + + ge_cairo_set_color (cr, fill); + cairo_fill_preserve (cr); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 0.4, shadow.r, shadow.g, shadow.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.2); + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + pattern = cairo_pattern_create_linear (0, yoffset+1, 0, 3+yoffset); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, params->disabled ? 0.125 : 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + pattern = cairo_pattern_create_linear (xoffset+1, 0, 3+xoffset, 0); + cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, params->disabled ? 0.125 : 0.3); + cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + + /* Drawing the border */ + + if (!params->active && params->is_default) + { + const CairoColor *l = &colors->shade[4]; + const CairoColor *d = &colors->shade[4]; + ge_cairo_set_color (cr, l); + ge_cairo_stroke_rectangle (cr, 2.5, 2.5, width-5, height-5); + + ge_cairo_set_color (cr, d); + ge_cairo_stroke_rectangle (cr, 3.5, 3.5, width-7, height-7); + } + + if (params->disabled) + ge_cairo_set_color (cr, border_disabled); + else + if (!params->active) + clearlooks_set_border_gradient (cr, &border_normal, 1.32, 0, height); + else + ge_cairo_set_color (cr, &border_normal); + + ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, + width-(xoffset*2)-1, height-(yoffset*2)-1, + radius, params->corners); + cairo_stroke (cr); + + /* Draw the "shadow" */ + if (!params->active) + { + cairo_translate (cr, 0.5, 0.5); + /* Draw right shadow */ + cairo_move_to (cr, width-params->xthickness, params->ythickness - 1); + cairo_line_to (cr, width-params->xthickness, height - params->ythickness - 1); + cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1); + cairo_stroke (cr); + + /* Draw topleft shadow */ + clearlooks_draw_top_left_highlight (cr, fill, params, width, height, radius); + } + cairo_restore (cr); +} + +static void +clearlooks_inverted_draw_progressbar_fill (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ProgressBarParameters *progressbar, + int x, int y, int width, int height, + gint offset) +{ + boolean is_horizontal = progressbar->orientation < 2; + double tile_pos = 0; + double stroke_width; + double radius; + int x_step; + + cairo_pattern_t *pattern; + CairoColor bg_shade; + CairoColor border; + CairoColor shadow; + CairoColor top_shade; + + radius = MAX (0, params->radius - params->xthickness); + + cairo_save (cr); + + if (!is_horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + if ((progressbar->orientation == CL_ORIENTATION_RIGHT_TO_LEFT) || (progressbar->orientation == CL_ORIENTATION_BOTTOM_TO_TOP)) + ge_cairo_mirror (cr, CR_MIRROR_HORIZONTAL, &x, &y, &width, &height); + + /* Clamp the radius so that the _height_ fits ... */ + radius = MIN (radius, height / 2.0); + + stroke_width = height*2; + x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */ + + cairo_translate (cr, x, y); + + cairo_save (cr); + /* This is kind of nasty ... Clip twice from each side in case the length + * of the fill is smaller than twice the radius. */ + ge_cairo_rounded_rectangle (cr, 0, 0, width + radius, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + + ge_shade_color (&colors->spot[1], 1.05, &top_shade); + + /* Draw the background gradient */ + ge_shade_color (&colors->spot[1], 0.925, &bg_shade); + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, bg_shade.r, bg_shade.g, bg_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, top_shade.r, top_shade.g, top_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bg_shade.r, bg_shade.g, bg_shade.b); + cairo_set_source (cr, pattern); + cairo_paint (cr); + cairo_pattern_destroy (pattern); + + /* Draw the Strokes */ + while (tile_pos <= width+x_step) + { + cairo_move_to (cr, stroke_width/2-x_step, 0); + cairo_line_to (cr, stroke_width-x_step, 0); + cairo_line_to (cr, stroke_width/2-x_step, height); + cairo_line_to (cr, -x_step, height); + + cairo_translate (cr, stroke_width, 0); + tile_pos += stroke_width; + } + + cairo_set_source_rgba (cr, colors->spot[2].r, + colors->spot[2].g, + colors->spot[2].b, + 0.15); + + cairo_fill (cr); + cairo_restore (cr); /* rounded clip region */ + + /* inner highlight border + * This is again kinda ugly. Draw once from each side, clipping away the other. */ + cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.5); + + /* left side */ + cairo_save (cr); + cairo_rectangle (cr, 0, 0, width / 2, height); + cairo_clip (cr); + + if (progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + else + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + /* right side */ + cairo_save (cr); + cairo_rectangle (cr, width / 2, 0, (width+1) / 2, height); + cairo_clip (cr); + + if (progressbar->value < 1.0 || progressbar->pulsing) + ge_cairo_rounded_rectangle (cr, -1.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + else + ge_cairo_rounded_rectangle (cr, -0.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + + cairo_stroke (cr); + cairo_restore (cr); /* clip */ + + + /* Draw the dark lines and the shadow */ + cairo_save (cr); + /* Again, this weird clip area. */ + ge_cairo_rounded_rectangle (cr, -1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); + cairo_clip (cr); + ge_cairo_rounded_rectangle (cr, -radius - 1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); + cairo_clip (cr); + + border = colors->spot[2]; + border.a = 0.5; + shadow.r = 0.0; + shadow.g = 0.0; + shadow.b = 0.0; + shadow.a = 0.1; + + if (progressbar->pulsing) + { + /* At the beginning of the bar. */ + cairo_move_to (cr, 0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, 0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, -0.5 + radius, height + 0.5); + ge_cairo_rounded_corner (cr, -0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); + ge_cairo_rounded_corner (cr, -0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + if (progressbar->value < 1.0 || progressbar->pulsing) + { + /* At the end of the bar. */ + cairo_move_to (cr, width - 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width - 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width - 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_move_to (cr, width + 0.5 - radius, -0.5); + ge_cairo_rounded_corner (cr, width + 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); + ge_cairo_rounded_corner (cr, width + 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); + ge_cairo_set_color (cr, &shadow); + cairo_stroke (cr); + } + + cairo_restore (cr); + + cairo_restore (cr); /* rotation, mirroring */ +} + +static void +clearlooks_inverted_draw_menuitem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->spot[1]; + CairoColor fill_shade; + CairoColor border = colors->spot[2]; + cairo_pattern_t *pattern; + + ge_shade_color (&border, 1.05, &border); + ge_shade_color (fill, 0.85, &fill_shade); + cairo_set_line_width (cr, 1.0); + + ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width - 1, height - 1, widget->radius, widget->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, fill_shade.r, fill_shade.g, fill_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, fill->r, fill->g, fill->b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); +} + +static void +clearlooks_inverted_draw_menubaritem (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height) +{ + CairoColor *fill = (CairoColor*)&colors->spot[1]; + CairoColor fill_shade; + CairoColor border = colors->spot[2]; + cairo_pattern_t *pattern; + + ge_shade_color (&border, 1.05, &border); + ge_shade_color (fill, 0.85, &fill_shade); + + cairo_set_line_width (cr, 1.0); + ge_cairo_rounded_rectangle (cr, x + 0.5, y + 0.5, width - 1, height, widget->radius, widget->corners); + + pattern = cairo_pattern_create_linear (x, y, x, y + height); + cairo_pattern_add_color_stop_rgb (pattern, 0, fill_shade.r, fill_shade.g, fill_shade.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, fill->r, fill->g, fill->b); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + cairo_pattern_destroy (pattern); + + ge_cairo_set_color (cr, &border); + cairo_stroke_preserve (cr); +} + +static void +clearlooks_inverted_draw_tab (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const TabParameters *tab, + int x, int y, int width, int height) +{ + const CairoColor *border1 = &colors->shade[6]; + const CairoColor *border2 = &colors->shade[5]; + const CairoColor *stripe_fill = &colors->spot[1]; + const CairoColor *stripe_border = &colors->spot[2]; + const CairoColor *fill; + CairoColor hilight; + CairoColor shadow; + + cairo_pattern_t *pattern; + + double radius; + double strip_size; + + radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + /* Set clip */ + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + cairo_new_path (cr); + + /* Translate and set line width */ + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x+0.5, y+0.5); + + + /* Make the tabs slightly bigger than they should be, to create a gap */ + /* And calculate the strip size too, while you're at it */ + if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM) + { + height += 3.0; + strip_size = 2.0/height; /* 2 pixel high strip */ + + if (tab->gap_side == CL_GAP_TOP) + cairo_translate (cr, 0.0, -3.0); /* gap at the other side */ + } + else + { + width += 3.0; + strip_size = 2.0/width; + + if (tab->gap_side == CL_GAP_LEFT) + cairo_translate (cr, -3.0, 0.0); /* gap at the other side */ + } + + /* Set the fill color */ + fill = &colors->bg[params->state_type]; + + /* Set tab shape */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, + radius, params->corners); + + /* Draw fill */ + ge_cairo_set_color (cr, fill); + cairo_fill (cr); + + ge_shade_color (fill, 1.3, &hilight); + + /* Draw highlight */ + if (!params->active) + { + ShadowParameters shadow; + + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = params->corners; + /* + clearlooks_draw_highlight_and_shade (cr, colors, &shadow, + width, + height, radius);*/ + } + + if (params->active) + { + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-1 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 1, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0 ); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + ge_shade_color (fill, 0.92, &shadow); + + cairo_pattern_add_color_stop_rgba (pattern, 0.0, hilight.r, hilight.g, hilight.b, 0.4); + cairo_pattern_add_color_stop_rgba (pattern, 1.0/height, hilight.r, hilight.g, hilight.b, 0.4); + cairo_pattern_add_color_stop_rgb (pattern, 1.0/height, fill->r,fill->g,fill->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shadow.r,shadow.g,shadow.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + else + { + /* Draw shade */ + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-2 : 0, + tab->gap_side == CL_GAP_TOP ? height-2 : 0, + tab->gap_side == CL_GAP_RIGHT ? width : 0, + tab->gap_side == CL_GAP_BOTTOM ? height : 0 ); + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_fill->r, stripe_fill->g, stripe_fill->b); + cairo_pattern_add_color_stop_rgba (pattern, strip_size, hilight.r, hilight.g, hilight.b, 0.0); + cairo_pattern_add_color_stop_rgba (pattern, 0.8, hilight.r, hilight.g, hilight.b, 0.0); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + + if (params->active) + { + ge_cairo_set_color (cr, border2); + cairo_stroke (cr); + } + else + { + pattern = cairo_pattern_create_linear ( tab->gap_side == CL_GAP_LEFT ? width-2 : 2, + tab->gap_side == CL_GAP_TOP ? height-2 : 2, + tab->gap_side == CL_GAP_RIGHT ? width : 2, + tab->gap_side == CL_GAP_BOTTOM ? height : 2 ); + + cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_border->r, stripe_border->g, stripe_border->b); + cairo_pattern_add_color_stop_rgb (pattern, strip_size, border1->r, border1->g, border1->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, border2->r, border2->g, border2->b); + cairo_set_source (cr, pattern); + cairo_stroke (cr); + cairo_pattern_destroy (pattern); + } +} + +static void +clearlooks_inverted_draw_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + const CairoColor *border = &colors->shade[params->disabled ? 4 : 6]; + const CairoColor *spot = &colors->spot[1]; + const CairoColor *fill = &colors->shade[2]; + double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0)); + + cairo_pattern_t *pattern; + + cairo_set_line_width (cr, 1.0); + cairo_translate (cr, x, y); + + if (params->disabled) + border = &colors->shade[4]; + else if (params->prelight) + border = &colors->spot[2]; + else + border = &colors->shade[6]; + + /* fill the widget */ + cairo_rectangle (cr, 0.5, 0.5, width-2, height-2); + + /* Fake light */ + if (!params->disabled) + { + const CairoColor *top = &colors->shade[2]; + const CairoColor *bot = &colors->shade[0]; + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, top->r, top->g, top->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, bot->r, bot->g, bot->b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + } + else + { + ge_cairo_set_color (cr, fill); + cairo_rectangle (cr, 0.5, 0.5, width-2, height-2); + cairo_fill (cr); + } + + /* Set the clip */ + cairo_save (cr); + cairo_rectangle (cr, 0.5, 0.5, 6, height-2); + cairo_rectangle (cr, width-7.5, 0.5, 6 , height-2); + cairo_clip_preserve (cr); + + cairo_new_path (cr); + + /* Draw the handles */ + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners); + pattern = cairo_pattern_create_linear (0.5, 0.5, 0.5, 0.5+height); + + if (params->prelight) + { + CairoColor highlight; + ge_shade_color (spot, 1.5, &highlight); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, spot->r, spot->g, spot->b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, highlight.r, highlight.g, highlight.b); + cairo_set_source (cr, pattern); + } + else { + CairoColor hilight; + ge_shade_color (fill, 1.5, &hilight); + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + } + + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_restore (cr); + + /* Draw the border */ + ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); + if (params->prelight || params->disabled) + ge_cairo_set_color (cr, border); + else + clearlooks_set_border_gradient (cr, border, 1.2, 0, height); + cairo_stroke (cr); + + /* Draw handle lines */ + if (width > 14) + { + cairo_move_to (cr, 6, 0.5); + cairo_line_to (cr, 6, height-1); + + cairo_move_to (cr, width-7, 0.5); + cairo_line_to (cr, width-7, height-1); + + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba (cr, border->r, + border->g, + border->b, + 0.3); + cairo_stroke (cr); + } +} + +static void +clearlooks_inverted_draw_slider_button (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const SliderParameters *slider, + int x, int y, int width, int height) +{ + double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + cairo_set_line_width (cr, 1.0); + + if (!slider->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + cairo_translate (cr, x+0.5, y+0.5); + + params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1); + params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2); + + if (width > 24) + params->style_functions->draw_gripdots (cr, colors, 0, 0, width-2, height-2, 3, 3, 0); +} + +static void +clearlooks_inverted_draw_list_view_header (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + const ListViewHeaderParameters *header, + int x, int y, int width, int height) +{ + const CairoColor *fill = &colors->bg[params->state_type]; + const CairoColor *border = &colors->shade[4]; + cairo_pattern_t *pattern; + CairoColor hilight_header; + CairoColor hilight; + CairoColor shadow; + + ge_shade_color (border, 1.5, &hilight); + ge_shade_color (fill, 1.05, &hilight_header); + ge_shade_color (fill, 0.95, &shadow); + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1.0); + + /* Draw highlight */ + if (header->order == CL_ORDER_FIRST) + { + cairo_move_to (cr, 0.5, height-1); + cairo_line_to (cr, 0.5, 0.5); + } + else + cairo_move_to (cr, 0.0, 0.5); + + cairo_line_to (cr, width, 0.5); + + ge_cairo_set_color (cr, &hilight); + cairo_stroke (cr); + + /* Draw bottom border */ + cairo_move_to (cr, 0.0, height-0.5); + cairo_line_to (cr, width, height-0.5); + ge_cairo_set_color (cr, border); + cairo_stroke (cr); + + /* Draw bottom shade */ + pattern = cairo_pattern_create_linear (0.0, 0, 0.0, height-1.0); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, shadow.r, shadow.g, shadow.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, hilight_header.r, hilight_header.g, hilight_header.b); + + cairo_rectangle (cr, 0, 1, width, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + /* Draw resize grip */ + if ((params->ltr && header->order != CL_ORDER_LAST) || + (!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable) + { + SeparatorParameters separator; + separator.horizontal = FALSE; + + if (params->ltr) + params->style_functions->draw_separator (cr, colors, params, &separator, + width-1.5, 4.0, 2, height-8.0); + else + params->style_functions->draw_separator (cr, colors, params, &separator, + 1.5, 4.0, 2, height-8.0); + } +} + + +static void +clearlooks_inverted_draw_scrollbar_stepper (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + const ScrollBarStepperParameters *stepper, + int x, int y, int width, int height) +{ + CairoCorners corners = CR_CORNER_NONE; + CairoColor border; + CairoColor s1, s2, s3; + cairo_pattern_t *pattern; + ShadowParameters shadow; + double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); + + ge_shade_color(&colors->shade[6], 1.05, &border); + + if (scrollbar->horizontal) + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; + } + else + { + if (stepper->stepper == CL_STEPPER_A) + corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; + else if (stepper->stepper == CL_STEPPER_D) + corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT; + } + + cairo_translate (cr, x, y); + cairo_set_line_width (cr, 1); + + ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners); + + if (scrollbar->horizontal) + pattern = cairo_pattern_create_linear (0, 0, 0, height); + else + pattern = cairo_pattern_create_linear (0, 0, width, 0); + + s1 = colors->bg[widget->state_type]; + ge_shade_color(&s1, 0.95, &s2); + ge_shade_color(&s1, 1.05, &s3); + + cairo_pattern_add_color_stop_rgb(pattern, 0, s2.r, s2.g, s2.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, s3.r, s3.g, s3.b); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + clearlooks_draw_top_left_highlight (cr, &s1, widget, width, height, radius); + + ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners); + clearlooks_set_border_gradient (cr, &border, 1.2, (scrollbar->horizontal ? 0 : width), (scrollbar->horizontal ? height: 0)); + cairo_stroke (cr); + + cairo_translate (cr, 0.5, 0.5); + shadow.shadow = CL_SHADOW_OUT; + shadow.corners = corners; + /* + clearlooks_draw_highlight_and_shade (cr, &shadow, + width, + height, params->radius);*/ +} + +static void +clearlooks_inverted_draw_scrollbar_slider (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height) +{ + if (scrollbar->junction & CL_JUNCTION_BEGIN) + { + if (scrollbar->horizontal) + { + x -= 1; + width += 1; + } + else + { + y -= 1; + height += 1; + } + } + if (scrollbar->junction & CL_JUNCTION_END) + { + if (scrollbar->horizontal) + width += 1; + else + height += 1; + } + + if (!scrollbar->horizontal) + ge_cairo_exchange_axis (cr, &x, &y, &width, &height); + + cairo_translate (cr, x, y); + + if (scrollbar->has_color) + { + const CairoColor *border = &colors->shade[8]; + CairoColor fill = scrollbar->color; + CairoColor hilight; + CairoColor shade1, shade2, shade3; + cairo_pattern_t *pattern; + + if (widget->prelight) + ge_shade_color (&fill, 1.1, &fill); + + cairo_set_line_width (cr, 1); + + ge_shade_color (&fill, 1.3, &hilight); + ge_shade_color (&fill, 1.1, &shade1); + ge_shade_color (&fill, 1.05, &shade2); + ge_shade_color (&fill, 0.98, &shade3); + + pattern = cairo_pattern_create_linear (1, 1, 1, height-2); + cairo_pattern_add_color_stop_rgb (pattern, 0, fill.r, fill.g, fill.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade3.r, shade3.g, shade3.b); + cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade1.r, shade1.g, shade1.b); + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source (cr, pattern); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5); + ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3); + + ge_cairo_set_color (cr, border); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); + } + else + { + CairoColor border; + CairoColor s1, s2, s3; + cairo_pattern_t *pattern; + int bar_x, i; + + const CairoColor *dark = &colors->shade[4]; + const CairoColor *light = &colors->shade[0]; + + ge_shade_color(&colors->shade[6], 1.05, &border); + + pattern = cairo_pattern_create_linear(1, 1, 1, height-1); + + s1 = colors->bg[widget->state_type]; + ge_shade_color(&s1, 0.95, &s2); + ge_shade_color(&s1, 1.05, &s3); + + cairo_pattern_add_color_stop_rgb(pattern, 0, s2.r, s2.g, s2.b); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, s3.r, s3.g, s3.b); + + cairo_rectangle (cr, 1, 1, width-2, height-2); + cairo_set_source(cr, pattern); + cairo_fill(cr); + cairo_pattern_destroy(pattern); + + clearlooks_draw_top_left_highlight (cr, &s2, widget, width, height, 0); + + clearlooks_set_border_gradient (cr, &border, 1.2, 0, height); + ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1); + + /* draw handles */ + cairo_set_line_width (cr, 1); + + bar_x = width/2 - 4; + cairo_translate(cr, 0.5, 0.5); + for (i=0; i<3; i++) + { + cairo_move_to (cr, bar_x, 4); + cairo_line_to (cr, bar_x, height-5); + ge_cairo_set_color (cr, dark); + cairo_stroke (cr); + + cairo_move_to (cr, bar_x+1, 4); + cairo_line_to (cr, bar_x+1, height-5); + ge_cairo_set_color (cr, light); + cairo_stroke (cr); + + bar_x += 3; + } + } +} + +static void +clearlooks_inverted_draw_selected_cell (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *params, + int x, int y, int width, int height) +{ + CairoColor upper_color; + CairoColor lower_color; + CairoColor border; + cairo_pattern_t *pattern; + cairo_save (cr); + + cairo_translate (cr, x, y); + + if (params->focus) + upper_color = colors->base[params->state_type]; + else + upper_color = colors->base[GTK_STATE_ACTIVE]; + + ge_shade_color(&upper_color, 0.9, &lower_color); + + pattern = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, lower_color.r, + lower_color.g, + lower_color.b); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, upper_color.r, + upper_color.g, + upper_color.b); + + + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + cairo_pattern_destroy (pattern); + + ge_shade_color(&upper_color, 0.8, &border); + + cairo_move_to (cr, 0, 0.5); + cairo_rel_line_to (cr, width, 0); + cairo_move_to (cr, 0, height-0.5); + cairo_rel_line_to (cr, width, 0); + + ge_cairo_set_color (cr, &border); + cairo_stroke (cr); + + cairo_restore (cr); +} + +void +clearlooks_register_style_inverted (ClearlooksStyleFunctions *functions) +{ + functions->draw_button = clearlooks_inverted_draw_button; + functions->draw_slider = clearlooks_inverted_draw_slider; + functions->draw_slider_button = clearlooks_inverted_draw_slider_button; + functions->draw_progressbar_fill = clearlooks_inverted_draw_progressbar_fill; + functions->draw_menuitem = clearlooks_inverted_draw_menuitem; + functions->draw_menubaritem = clearlooks_inverted_draw_menubaritem; + functions->draw_tab = clearlooks_inverted_draw_tab; + functions->draw_list_view_header = clearlooks_inverted_draw_list_view_header; + functions->draw_scrollbar_stepper = clearlooks_inverted_draw_scrollbar_stepper; + functions->draw_scrollbar_slider = clearlooks_inverted_draw_scrollbar_slider; + functions->draw_selected_cell = clearlooks_inverted_draw_selected_cell; +} + diff --git a/libs/clearlooks/clearlooks_rc_style.c b/libs/clearlooks/clearlooks_rc_style.c index 1c5f2c495e..f486453339 100644 --- a/libs/clearlooks/clearlooks_rc_style.c +++ b/libs/clearlooks/clearlooks_rc_style.c @@ -19,12 +19,18 @@ * Written by Owen Taylor <otaylor@redhat.com> * and by Alexander Larsson <alexl@redhat.com> * Modified by Richard Stellingwerff <remenic@gmail.com> + * Modified by Kulyk Nazar <schamane@myeburg.net> */ #include "clearlooks_style.h" #include "clearlooks_rc_style.h" +#include "animation.h" + static void clearlooks_rc_style_init (ClearlooksRcStyle *style); +#ifdef HAVE_ANIMATION +static void clearlooks_rc_style_finalize (GObject *object); +#endif static void clearlooks_rc_style_class_init (ClearlooksRcStyleClass *klass); static GtkStyle *clearlooks_rc_style_create_style (GtkRcStyle *rc_style); static guint clearlooks_rc_style_parse (GtkRcStyle *rc_style, @@ -34,56 +40,82 @@ static void clearlooks_rc_style_merge (GtkRcStyle *dest, GtkRcStyle *src); -static GtkRcStyleClass *parent_class; +static GtkRcStyleClass *clearlooks_parent_rc_class; GType clearlooks_type_rc_style = 0; enum { - TOKEN_SPOTCOLOR = G_TOKEN_LAST + 1, - TOKEN_CONTRAST, - TOKEN_SUNKENMENU, - TOKEN_PROGRESSBARSTYLE, - TOKEN_MENUBARSTYLE, - TOKEN_MENUITEMSTYLE, - TOKEN_LISTVIEWITEMSTYLE + TOKEN_SCROLLBARCOLOR = G_TOKEN_LAST + 1, + TOKEN_COLORIZESCROLLBAR, + TOKEN_CONTRAST, + TOKEN_SUNKENMENU, + TOKEN_PROGRESSBARSTYLE, + TOKEN_MENUBARSTYLE, + TOKEN_TOOLBARSTYLE, + TOKEN_MENUITEMSTYLE, + TOKEN_LISTVIEWITEMSTYLE, + TOKEN_ANIMATION, + TOKEN_STYLE, + TOKEN_RADIUS, + + TOKEN_CLASSIC, + TOKEN_GLOSSY, + TOKEN_INVERTED, + TOKEN_GUMMY, + + TOKEN_TRUE, + TOKEN_FALSE }; static struct - { - const gchar *name; - guint token; - } -theme_symbols[] = { - { "spotcolor", TOKEN_SPOTCOLOR }, - { "contrast", TOKEN_CONTRAST }, - { "sunkenmenubar", TOKEN_SUNKENMENU }, - { "progressbarstyle", TOKEN_PROGRESSBARSTYLE }, - { "menubarstyle", TOKEN_MENUBARSTYLE }, - { "menuitemstyle", TOKEN_MENUITEMSTYLE }, - { "listviewitemstyle", TOKEN_LISTVIEWITEMSTYLE } + const gchar *name; + guint token; +} +clearlooks_gtk2_rc_symbols[] = +{ + { "scrollbar_color", TOKEN_SCROLLBARCOLOR }, + { "colorize_scrollbar", TOKEN_COLORIZESCROLLBAR }, + { "contrast", TOKEN_CONTRAST }, + { "sunkenmenubar", TOKEN_SUNKENMENU }, + { "progressbarstyle", TOKEN_PROGRESSBARSTYLE }, + { "menubarstyle", TOKEN_MENUBARSTYLE }, + { "toolbarstyle", TOKEN_TOOLBARSTYLE }, + { "menuitemstyle", TOKEN_MENUITEMSTYLE }, + { "listviewitemstyle", TOKEN_LISTVIEWITEMSTYLE }, + { "animation", TOKEN_ANIMATION }, + { "style", TOKEN_STYLE }, + { "radius", TOKEN_RADIUS }, + + { "CLASSIC", TOKEN_CLASSIC }, + { "GLOSSY", TOKEN_GLOSSY }, + { "INVERTED", TOKEN_INVERTED }, + { "GUMMY", TOKEN_GUMMY }, + + { "TRUE", TOKEN_TRUE }, + { "FALSE", TOKEN_FALSE } }; void clearlooks_rc_style_register_type (GTypeModule *module) { - static const GTypeInfo object_info = - { - sizeof (ClearlooksRcStyleClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) clearlooks_rc_style_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (ClearlooksRcStyle), - 0, /* n_preallocs */ - (GInstanceInitFunc) clearlooks_rc_style_init, - NULL - }; - - clearlooks_type_rc_style = g_type_module_register_type (module, + static const GTypeInfo object_info = + { + sizeof (ClearlooksRcStyleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) clearlooks_rc_style_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (ClearlooksRcStyle), + 0, /* n_preallocs */ + (GInstanceInitFunc) clearlooks_rc_style_init, + NULL + }; + + clearlooks_type_rc_style = g_type_module_register_type (module, GTK_TYPE_RC_STYLE, "ClearlooksRcStyle", &object_info, 0); @@ -92,181 +124,198 @@ clearlooks_rc_style_register_type (GTypeModule *module) static void clearlooks_rc_style_init (ClearlooksRcStyle *clearlooks_rc) { - clearlooks_rc->has_spot_color = FALSE; - clearlooks_rc->contrast = 1.0; - clearlooks_rc->sunkenmenubar = 1; - clearlooks_rc->progressbarstyle = 0; - clearlooks_rc->menubarstyle = 0; - clearlooks_rc->menuitemstyle = 1; - clearlooks_rc->listviewitemstyle = 1; + clearlooks_rc->style = CL_STYLE_CLASSIC; + + clearlooks_rc->flags = 0; + + clearlooks_rc->contrast = 1.0; + clearlooks_rc->menubarstyle = 0; + clearlooks_rc->toolbarstyle = 0; + clearlooks_rc->animation = FALSE; + clearlooks_rc->colorize_scrollbar = FALSE; + clearlooks_rc->radius = 3.0; } +#ifdef HAVE_ANIMATION static void -clearlooks_rc_style_class_init (ClearlooksRcStyleClass *klass) +clearlooks_rc_style_finalize (GObject *object) { - GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); + /* cleanup all the animation stuff */ + clearlooks_animation_cleanup (); - rc_style_class->parse = clearlooks_rc_style_parse; - rc_style_class->create_style = clearlooks_rc_style_create_style; - rc_style_class->merge = clearlooks_rc_style_merge; + if (G_OBJECT_CLASS (clearlooks_parent_rc_class)->finalize != NULL) + G_OBJECT_CLASS (clearlooks_parent_rc_class)->finalize(object); } +#endif -static guint -theme_parse_color(GtkSettings *settings, - GScanner *scanner, - GdkColor *color) + +static void +clearlooks_rc_style_class_init (ClearlooksRcStyleClass *klass) { - guint token; + GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass); +#ifdef HAVE_ANIMATION + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); +#endif - /* Skip 'blah_color' */ - token = g_scanner_get_next_token(scanner); + clearlooks_parent_rc_class = g_type_class_peek_parent (klass); - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_EQUAL_SIGN) - return G_TOKEN_EQUAL_SIGN; + rc_style_class->parse = clearlooks_rc_style_parse; + rc_style_class->create_style = clearlooks_rc_style_create_style; + rc_style_class->merge = clearlooks_rc_style_merge; - return gtk_rc_parse_color (scanner, color); +#ifdef HAVE_ANIMATION + g_object_class->finalize = clearlooks_rc_style_finalize; +#endif } static guint -theme_parse_contrast(GtkSettings *settings, - GScanner *scanner, - double *contrast) +clearlooks_gtk2_rc_parse_boolean (GtkSettings *settings, + GScanner *scanner, + gboolean *retval) { - guint token; + guint token; + token = g_scanner_get_next_token(scanner); + + 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; +} - /* Skip 'contrast' */ - token = g_scanner_get_next_token(scanner); +static guint +clearlooks_gtk2_rc_parse_color(GtkSettings *settings, + GScanner *scanner, + GdkColor *color) +{ + guint token; - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_EQUAL_SIGN) - return G_TOKEN_EQUAL_SIGN; + /* Skip 'blah_color' */ + token = g_scanner_get_next_token(scanner); - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_FLOAT) - return G_TOKEN_FLOAT; + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - *contrast = scanner->value.v_float; - - return G_TOKEN_NONE; + return gtk_rc_parse_color (scanner, color); } static guint -theme_parse_sunkenmenubar(GtkSettings *settings, - GScanner *scanner, - guint8 *sunken) +clearlooks_gtk2_rc_parse_double (GtkSettings *settings, + GScanner *scanner, + gdouble *val) { - guint token; + guint token; - /* Skip 'sunkenmenubar' */ - token = g_scanner_get_next_token(scanner); + /* Skip 'blah' */ + token = g_scanner_get_next_token(scanner); - 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 != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_INT) - return G_TOKEN_INT; + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_FLOAT) + return G_TOKEN_FLOAT; - *sunken = scanner->value.v_int; - - return G_TOKEN_NONE; + *val = scanner->value.v_float; + + return G_TOKEN_NONE; } static guint -theme_parse_progressbarstyle(GtkSettings *settings, - GScanner *scanner, - guint8 *progressbarstyle) +clearlooks_gtk2_rc_parse_int (GtkSettings *settings, + GScanner *scanner, + guint8 *progressbarstyle) { - guint token; + guint token; - /* Skip 'sunkenmenubar' */ - token = g_scanner_get_next_token(scanner); + /* Skip 'sunkenmenubar' */ + token = g_scanner_get_next_token(scanner); - 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 != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_INT) - return G_TOKEN_INT; + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_INT) + return G_TOKEN_INT; - *progressbarstyle = scanner->value.v_int; - - return G_TOKEN_NONE; + *progressbarstyle = scanner->value.v_int; + + return G_TOKEN_NONE; } static guint -theme_parse_menubarstyle(GtkSettings *settings, - GScanner *scanner, - guint8 *menubarstyle) +clearlooks_gtk2_rc_parse_style (GtkSettings *settings, + GScanner *scanner, + ClearlooksStyles *style) { - guint token; + guint token; - /* Skip 'menubarstyle' */ - token = g_scanner_get_next_token(scanner); + g_assert (CL_NUM_STYLES == CL_STYLE_GUMMY + 1); /* so that people don't forget ;-) */ - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_EQUAL_SIGN) - return G_TOKEN_EQUAL_SIGN; + /* Skip 'style' */ + token = g_scanner_get_next_token (scanner); - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_INT) - return G_TOKEN_INT; + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - *menubarstyle = scanner->value.v_int; + token = g_scanner_get_next_token (scanner); - return G_TOKEN_NONE; + switch (token) + { + case TOKEN_CLASSIC: + *style = CL_STYLE_CLASSIC; + break; + case TOKEN_GLOSSY: + *style = CL_STYLE_GLOSSY; + break; + case TOKEN_INVERTED: + *style = CL_STYLE_INVERTED; + break; + case TOKEN_GUMMY: + *style = CL_STYLE_GUMMY; + break; + default: + return TOKEN_CLASSIC; + } + + return G_TOKEN_NONE; } static guint -theme_parse_menuitemstyle(GtkSettings *settings, - GScanner *scanner, - guint8 *menuitemstyle) +clearlooks_gtk2_rc_parse_dummy (GtkSettings *settings, + GScanner *scanner, + gchar *name) { - guint token; + guint token; - /* Skip 'sunkenmenubar' */ - token = g_scanner_get_next_token(scanner); + /* Skip option */ + token = g_scanner_get_next_token (scanner); - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_EQUAL_SIGN) - return G_TOKEN_EQUAL_SIGN; + /* print a warning. Isn't there a way to get the string from the scanner? */ + g_scanner_warn (scanner, "Clearlooks configuration option \"%s\" is not supported and will be ignored.", name); - token = g_scanner_get_next_token(scanner); - if (token != G_TOKEN_INT) - return G_TOKEN_INT; + /* equal sign */ + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - *menuitemstyle = scanner->value.v_int; - - return G_TOKEN_NONE; -} + /* eat whatever comes next */ + token = g_scanner_get_next_token (scanner); -static guint -theme_parse_listviewitemstyle(GtkSettings *settings, - GScanner *scanner, - guint8 *listviewitemstyle) -{ - guint token; - - token = g_scanner_get_next_token(scanner); - - 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 != G_TOKEN_INT) - return G_TOKEN_INT; - - *listviewitemstyle = scanner->value.v_int; - - return G_TOKEN_NONE; -} + return G_TOKEN_NONE; +} static guint clearlooks_rc_style_parse (GtkRcStyle *rc_style, @@ -274,84 +323,107 @@ clearlooks_rc_style_parse (GtkRcStyle *rc_style, GScanner *scanner) { - static GQuark scope_id = 0; - ClearlooksRcStyle *clearlooks_style = CLEARLOOKS_RC_STYLE (rc_style); + static GQuark scope_id = 0; + ClearlooksRcStyle *clearlooks_style = CLEARLOOKS_RC_STYLE (rc_style); - guint old_scope; - guint token; - guint i; - - /* Set up a new scope in this scanner. */ - - if (!scope_id) - scope_id = g_quark_from_string("clearlooks_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 clearlooks_rc_style_parse for the - * same scanner. - */ - - if (!g_scanner_lookup_symbol(scanner, theme_symbols[0].name)) - { - g_scanner_freeze_symbol_table(scanner); - for (i = 0; i < G_N_ELEMENTS (theme_symbols); i++) - g_scanner_scope_add_symbol(scanner, scope_id, - theme_symbols[i].name, - GINT_TO_POINTER(theme_symbols[i].token)); - g_scanner_thaw_symbol_table(scanner); - } - - /* We're ready to go, now parse the top level */ - - token = g_scanner_peek_next_token(scanner); - while (token != G_TOKEN_RIGHT_CURLY) - { - switch (token) + guint old_scope; + guint token; + guint i; + + /* Set up a new scope in this scanner. */ + + if (!scope_id) + scope_id = g_quark_from_string("clearlooks_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 clearlooks_rc_style_parse for the + * same scanner. + */ + + if (!g_scanner_lookup_symbol(scanner, clearlooks_gtk2_rc_symbols[0].name)) { - case TOKEN_SPOTCOLOR: - token = theme_parse_color(settings, scanner, &clearlooks_style->spot_color); - clearlooks_style->has_spot_color = TRUE; - break; - case TOKEN_CONTRAST: - token = theme_parse_contrast(settings, scanner, &clearlooks_style->contrast); - break; - case TOKEN_SUNKENMENU: - token = theme_parse_sunkenmenubar(settings, scanner, &clearlooks_style->sunkenmenubar); - break; - case TOKEN_PROGRESSBARSTYLE: - token = theme_parse_progressbarstyle(settings, scanner, &clearlooks_style->progressbarstyle); - break; - case TOKEN_MENUBARSTYLE: - token = theme_parse_menubarstyle(settings, scanner, &clearlooks_style->menubarstyle); - break; - case TOKEN_MENUITEMSTYLE: - token = theme_parse_menuitemstyle(settings, scanner, &clearlooks_style->menuitemstyle); - break; - case TOKEN_LISTVIEWITEMSTYLE: - token = theme_parse_listviewitemstyle(settings, scanner, &clearlooks_style->listviewitemstyle); - break; - default: - g_scanner_get_next_token(scanner); - token = G_TOKEN_RIGHT_CURLY; - break; + for (i = 0; i < G_N_ELEMENTS (clearlooks_gtk2_rc_symbols); i++) + g_scanner_scope_add_symbol(scanner, scope_id, + clearlooks_gtk2_rc_symbols[i].name, + GINT_TO_POINTER(clearlooks_gtk2_rc_symbols[i].token)); } - if (token != G_TOKEN_NONE) - return token; + /* We're ready to go, now parse the top level */ - token = g_scanner_peek_next_token(scanner); - } + token = g_scanner_peek_next_token(scanner); + while (token != G_TOKEN_RIGHT_CURLY) + { + switch (token) + { + case TOKEN_SCROLLBARCOLOR: + token = clearlooks_gtk2_rc_parse_color (settings, scanner, &clearlooks_style->scrollbar_color); + clearlooks_style->flags |= CL_FLAG_SCROLLBAR_COLOR; + break; + case TOKEN_COLORIZESCROLLBAR: + token = clearlooks_gtk2_rc_parse_boolean (settings, scanner, &clearlooks_style->colorize_scrollbar); + clearlooks_style->flags |= CL_FLAG_COLORIZE_SCROLLBAR; + break; + case TOKEN_CONTRAST: + token = clearlooks_gtk2_rc_parse_double (settings, scanner, &clearlooks_style->contrast); + clearlooks_style->flags |= CL_FLAG_CONTRAST; + break; + case TOKEN_MENUBARSTYLE: + token = clearlooks_gtk2_rc_parse_int (settings, scanner, &clearlooks_style->menubarstyle); + clearlooks_style->flags |= CL_FLAG_MENUBARSTYLE; + break; + case TOKEN_TOOLBARSTYLE: + token = clearlooks_gtk2_rc_parse_int (settings, scanner, &clearlooks_style->toolbarstyle); + clearlooks_style->flags |= CL_FLAG_TOOLBARSTYLE; + break; + case TOKEN_ANIMATION: + token = clearlooks_gtk2_rc_parse_boolean (settings, scanner, &clearlooks_style->animation); + clearlooks_style->flags |= CL_FLAG_ANIMATION; + break; + case TOKEN_STYLE: + token = clearlooks_gtk2_rc_parse_style (settings, scanner, &clearlooks_style->style); + clearlooks_style->flags |= CL_FLAG_STYLE; + break; + case TOKEN_RADIUS: + token = clearlooks_gtk2_rc_parse_double (settings, scanner, &clearlooks_style->radius); + clearlooks_style->flags |= CL_FLAG_RADIUS; + break; + + /* stuff to ignore */ + case TOKEN_SUNKENMENU: + token = clearlooks_gtk2_rc_parse_dummy (settings, scanner, "sunkenmenu"); + break; + case TOKEN_PROGRESSBARSTYLE: + token = clearlooks_gtk2_rc_parse_dummy (settings, scanner, "progressbarstyle"); + break; + case TOKEN_MENUITEMSTYLE: + token = clearlooks_gtk2_rc_parse_dummy (settings, scanner, "menuitemstyle"); + break; + case TOKEN_LISTVIEWITEMSTYLE: + token = clearlooks_gtk2_rc_parse_dummy (settings, scanner, "listviewitemstyle"); + break; + + default: + g_scanner_get_next_token(scanner); + token = G_TOKEN_RIGHT_CURLY; + break; + } + + if (token != G_TOKEN_NONE) + return token; + + token = g_scanner_peek_next_token(scanner); + } - g_scanner_get_next_token(scanner); + g_scanner_get_next_token(scanner); - g_scanner_set_scope(scanner, old_scope); + g_scanner_set_scope(scanner, old_scope); - return G_TOKEN_NONE; + return G_TOKEN_NONE; } static void @@ -359,27 +431,36 @@ clearlooks_rc_style_merge (GtkRcStyle *dest, GtkRcStyle *src) { ClearlooksRcStyle *dest_w, *src_w; - - parent_class->merge (dest, src); - + ClearlooksRcFlags flags; + + clearlooks_parent_rc_class->merge (dest, src); + if (!CLEARLOOKS_IS_RC_STYLE (src)) return; - + src_w = CLEARLOOKS_RC_STYLE (src); dest_w = CLEARLOOKS_RC_STYLE (dest); - - dest_w->contrast = src_w->contrast; - dest_w->sunkenmenubar = src_w->sunkenmenubar; - dest_w->progressbarstyle = src_w->progressbarstyle; - dest_w->menubarstyle = src_w->menubarstyle; - dest_w->menuitemstyle = src_w->menuitemstyle; - dest_w->listviewitemstyle = src_w->listviewitemstyle; - - if (src_w->has_spot_color) - { - dest_w->has_spot_color = TRUE; - dest_w->spot_color = src_w->spot_color; - } + + flags = (~dest_w->flags) & src_w->flags; + + if (flags & CL_FLAG_STYLE) + dest_w->style = src_w->style; + if (flags & CL_FLAG_CONTRAST) + dest_w->contrast = src_w->contrast; + if (flags & CL_FLAG_MENUBARSTYLE) + dest_w->menubarstyle = src_w->menubarstyle; + if (flags & CL_FLAG_TOOLBARSTYLE) + dest_w->toolbarstyle = src_w->toolbarstyle; + if (flags & CL_FLAG_SCROLLBAR_COLOR) + dest_w->scrollbar_color = src_w->scrollbar_color; + if (flags & CL_FLAG_COLORIZE_SCROLLBAR) + dest_w->colorize_scrollbar = src_w->colorize_scrollbar; + if (flags & CL_FLAG_ANIMATION) + dest_w->animation = src_w->animation; + if (flags & CL_FLAG_RADIUS) + dest_w->radius = src_w->radius; + + dest_w->flags |= src_w->flags; } @@ -388,5 +469,5 @@ clearlooks_rc_style_merge (GtkRcStyle *dest, static GtkStyle * clearlooks_rc_style_create_style (GtkRcStyle *rc_style) { - return GTK_STYLE (g_object_new (CLEARLOOKS_TYPE_STYLE, NULL)); + return GTK_STYLE (g_object_new (CLEARLOOKS_TYPE_STYLE, NULL)); } diff --git a/libs/clearlooks/clearlooks_rc_style.h b/libs/clearlooks/clearlooks_rc_style.h index bd8e0ca05d..a80a846000 100644 --- a/libs/clearlooks/clearlooks_rc_style.h +++ b/libs/clearlooks/clearlooks_rc_style.h @@ -19,14 +19,16 @@ * Written by Owen Taylor <otaylor@redhat.com> * and by Alexander Larsson <alexl@redhat.com> * Modified by Richard Stellingwerff <remenic@gmail.com> + * Modified by Kulyk Nazar <schamane@myeburg.net> */ #include <gtk/gtkrc.h> +#include "clearlooks_types.h" typedef struct _ClearlooksRcStyle ClearlooksRcStyle; typedef struct _ClearlooksRcStyleClass ClearlooksRcStyleClass; -extern GType clearlooks_type_rc_style; +GE_INTERNAL extern GType clearlooks_type_rc_style; #define CLEARLOOKS_TYPE_RC_STYLE clearlooks_type_rc_style #define CLEARLOOKS_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), CLEARLOOKS_TYPE_RC_STYLE, ClearlooksRcStyle)) @@ -35,18 +37,33 @@ extern GType clearlooks_type_rc_style; #define CLEARLOOKS_IS_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLEARLOOKS_TYPE_RC_STYLE)) #define CLEARLOOKS_RC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLEARLOOKS_TYPE_RC_STYLE, ClearlooksRcStyleClass)) +/* XXX: needs fixing! */ +typedef enum { + CL_FLAG_STYLE = 1 << 0, + CL_FLAG_SCROLLBAR_COLOR = 1 << 1, + CL_FLAG_COLORIZE_SCROLLBAR = 1 << 2, + CL_FLAG_CONTRAST = 1 << 3, + CL_FLAG_MENUBARSTYLE = 1 << 4, + CL_FLAG_TOOLBARSTYLE = 1 << 5, + CL_FLAG_ANIMATION = 1 << 6, + CL_FLAG_RADIUS = 1 << 7 +} ClearlooksRcFlags; + struct _ClearlooksRcStyle { - GtkRcStyle parent_instance; - - GdkColor spot_color; - gboolean has_spot_color; - double contrast; - guint8 sunkenmenubar; - guint8 progressbarstyle; - guint8 menubarstyle; - guint8 menuitemstyle; - guint8 listviewitemstyle; + GtkRcStyle parent_instance; + + ClearlooksRcFlags flags; + + ClearlooksStyles style; + + GdkColor scrollbar_color; + gboolean colorize_scrollbar; + double contrast; + guint8 menubarstyle; + guint8 toolbarstyle; + gboolean animation; + double radius; }; struct _ClearlooksRcStyleClass @@ -54,4 +71,4 @@ struct _ClearlooksRcStyleClass GtkRcStyleClass parent_class; }; -void clearlooks_rc_style_register_type (GTypeModule *module); +GE_INTERNAL void clearlooks_rc_style_register_type (GTypeModule *module); diff --git a/libs/clearlooks/clearlooks_style.c b/libs/clearlooks/clearlooks_style.c index 074f1604b1..e06b32e1e4 100644 --- a/libs/clearlooks/clearlooks_style.c +++ b/libs/clearlooks/clearlooks_style.c @@ -1,22 +1,38 @@ +/* Clearlooks theme engine + * Copyright (C) 2005 Richard Stellingwerff. + * Copyright (C) 2007 Benjamin Berg <benjamin@sipsolutions.net>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + #include <gtk/gtk.h> +#include <cairo.h> +#include <math.h> +#include <string.h> +#include <ge-support.h> #include "clearlooks_style.h" #include "clearlooks_rc_style.h" #include "clearlooks_draw.h" - -#include <math.h> -#include <string.h> - -#include "bits.c" #include "support.h" -//#include "config.h" /* #define DEBUG 1 */ -#define SCALE_SIZE 5 - #define DETAIL(xx) ((detail) && (!strcmp(xx, detail))) -#define COMPARE_COLORS(a,b) (a.red == b.red && a.green == b.green && a.blue == b.blue) #define DRAW_ARGS GtkStyle *style, \ GdkWindow *window, \ @@ -30,2438 +46,1360 @@ gint width, \ gint height -static GdkGC *realize_color (GtkStyle * style, GdkColor * color); -static GtkStyleClass *parent_class; -static GList *progressbars = NULL; -static gint8 pboffset = 10; -static int timer_id = 0; - -static void cl_progressbar_remove (gpointer data) -{ - if (g_list_find (progressbars, data) == NULL) - return; - - progressbars = g_list_remove (progressbars, data); - g_object_unref (data); - - if (g_list_first(progressbars) == NULL) { - g_source_remove(timer_id); - timer_id = 0; - } -} - -static void update_progressbar (gpointer data, gpointer user_data) -{ - gfloat fraction; - - if (data == NULL) - return; - - fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (data)); - - /* update only if not filled */ - if (fraction < 1.0) - gtk_widget_queue_resize ((GtkWidget*)data); - - if (fraction >= 1.0 || GTK_PROGRESS (data)->activity_mode) - cl_progressbar_remove (data); -} - -static gboolean timer_func (gpointer data) -{ - g_list_foreach (progressbars, update_progressbar, NULL); - if (--pboffset < 0) pboffset = 9; - return (g_list_first(progressbars) != NULL); -} - -static gboolean cl_progressbar_known(gconstpointer data) -{ - return (g_list_find (progressbars, data) != NULL); -} - - -static void cl_progressbar_add (gpointer data) -{ - if (!GTK_IS_PROGRESS_BAR (data)) - return; - - progressbars = g_list_append (progressbars, data); - - g_object_ref (data); - g_signal_connect ((GObject*)data, "unrealize", G_CALLBACK (cl_progressbar_remove), data); - - if (timer_id == 0) - timer_id = g_timeout_add (100, timer_func, NULL); -} +#ifdef HAVE_ANIMATION +#include "animation.h" +#endif -static GdkColor * -clearlooks_get_spot_color (ClearlooksRcStyle *clearlooks_rc) -{ - GtkRcStyle *rc = GTK_RC_STYLE (clearlooks_rc); - - if (clearlooks_rc->has_spot_color) - return &clearlooks_rc->spot_color; - else - return &rc->base[GTK_STATE_SELECTED]; -} +#define STYLE_FUNCTION(function) (clearlooks_style_class->style_functions[CLEARLOOKS_STYLE (style)->style].function) -/**************************************************************************/ +static ClearlooksStyleClass *clearlooks_style_class; +static GtkStyleClass *clearlooks_parent_class; -/* used for optionmenus... */ static void -draw_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) +clearlooks_set_widget_parameters (const GtkWidget *widget, + const GtkStyle *style, + GtkStateType state_type, + WidgetParameters *params) { -#define ARROW_SPACE 2 -#define ARROW_LINE_HEIGHT 2 -#define ARROW_LINE_WIDTH 5 - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GtkRequisition indicator_size; - GtkBorder indicator_spacing; - gint arrow_height; - - option_menu_get_props (widget, &indicator_size, &indicator_spacing); - - indicator_size.width += (indicator_size.width % 2) - 1; - arrow_height = indicator_size.width / 2 + 2; - - x += (width - indicator_size.width) / 2; - y += height/2; - - if (state_type == GTK_STATE_INSENSITIVE) - { - draw_arrow (window, style->light_gc[state_type], area, - GTK_ARROW_UP, 1+x, 1+y-arrow_height, - indicator_size.width, arrow_height); - - draw_arrow (window, style->light_gc[state_type], area, - GTK_ARROW_DOWN, 1+x, 1+y+1, - indicator_size.width, arrow_height); - } - - draw_arrow (window, style->fg_gc[state_type], area, - GTK_ARROW_UP, x, y-arrow_height, - indicator_size.width, arrow_height); - - draw_arrow (window, style->fg_gc[state_type], area, - GTK_ARROW_DOWN, x, y+1, - indicator_size.width, arrow_height); + params->style_functions = &(clearlooks_style_class->style_functions[CLEARLOOKS_STYLE (style)->style]); + + params->active = (state_type == GTK_STATE_ACTIVE); + params->prelight = (state_type == GTK_STATE_PRELIGHT); + params->disabled = (state_type == GTK_STATE_INSENSITIVE); + params->state_type = (ClearlooksStateType)state_type; + params->corners = CR_CORNER_ALL; + params->ltr = ge_widget_is_ltr ((GtkWidget*)widget); + params->focus = widget && GTK_WIDGET_HAS_FOCUS (widget); + params->is_default = widget && GE_WIDGET_HAS_DEFAULT (widget); + params->enable_glow = FALSE; + params->radius = CLEARLOOKS_STYLE (style)->radius; + + if (!params->active && widget && GE_IS_TOGGLE_BUTTON (widget)) + params->active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + + params->xthickness = style->xthickness; + params->ythickness = style->ythickness; + + /* This is used in GtkEntry to fake transparency. The reason to do this + * is that the entry has it's entire background filled with base[STATE]. + * This is not a very good solution as it will eg. fail if one changes + * the background color of a notebook. */ + params->parentbg = CLEARLOOKS_STYLE (style)->colors.bg[state_type]; + clearlooks_get_parent_bg (widget, ¶ms->parentbg); } static void -clearlooks_draw_arrow (GtkStyle *style, - GdkWindow *window, - GtkStateType state, - GtkShadowType shadow, - GdkRectangle *area, - GtkWidget *widget, - const gchar *detail, - GtkArrowType arrow_type, - gboolean fill, - gint x, - gint y, - gint width, - gint height) +clearlooks_style_draw_flat_box (DRAW_ARGS) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - gint original_width, original_x; - GdkGC *gc; - - sanitize_size (window, &width, &height); - - if (is_combo_box (widget)) - { - width = 7; - height = 5; - x+=2; - y+=4; - if (state == GTK_STATE_INSENSITIVE) - { - draw_arrow (window, style->light_gc[state], area, - GTK_ARROW_UP, 1+x, 1+y-height, - width, height); - - draw_arrow (window, style->light_gc[state], area, - GTK_ARROW_DOWN, 1+x, 1+y+1, - width, height); - } - - draw_arrow (window, style->fg_gc[state], area, - GTK_ARROW_UP, x, y-height, - width, height); - - draw_arrow (window, style->fg_gc[state], area, - GTK_ARROW_DOWN, x, y+1, - width, height); - - return; - } - - original_width = width; - original_x = x; - - /* Make spinbutton arrows and arrows in menus - * slightly larger to get the right pixels drawn */ - if (DETAIL ("spinbutton")) - height += 1; - - if (DETAIL("menuitem")) - { - width = 6; - height = 7; - } - - /* Compensate arrow position for "sunken" look */ - if (DETAIL ("spinbutton") && arrow_type == GTK_ARROW_DOWN && - style->xthickness > 2 && style->ythickness > 2) - y -= 1; - - if (widget && widget->parent && GTK_IS_COMBO (widget->parent->parent)) + if (detail && + state_type == GTK_STATE_SELECTED && ( + !strncmp ("cell_even", detail, 9) || + !strncmp ("cell_odd", detail, 8))) { - width -= 2; - height -=2; - x++; - } - - calculate_arrow_geometry (arrow_type, &x, &y, &width, &height); - - if (DETAIL ("menuitem")) - x = original_x + original_width - width; - - if (DETAIL ("spinbutton") && (arrow_type == GTK_ARROW_DOWN)) - y += 1; - - if (state == GTK_STATE_INSENSITIVE) - draw_arrow (window, style->light_gc[state], area, arrow_type, x + 1, y + 1, width, height); + WidgetParameters params; + ClearlooksStyle *clearlooks_style; + ClearlooksColors *colors; + cairo_t *cr; - gc = style->fg_gc[state]; - - draw_arrow (window, gc, area, arrow_type, x, y, width, height); -} + CHECK_ARGS + SANITIZE_SIZE + clearlooks_style = CLEARLOOKS_STYLE (style); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + colors = &clearlooks_style->colors; + cr = ge_gdk_drawable_to_cairo (window, area); -static void -draw_flat_box (DRAW_ARGS) -{ - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + /* XXX: We could expose the side details by setting params->corners accordingly + * or adding another option. */ + STYLE_FUNCTION (draw_selected_cell) (cr, colors, ¶ms, x, y, width, height); - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - sanitize_size (window, &width, &height); - - if (detail && - clearlooks_style->listviewitemstyle == 1 && - state_type == GTK_STATE_SELECTED && ( - !strncmp ("cell_even", detail, strlen ("cell_even")) || - !strncmp ("cell_odd", detail, strlen ("cell_odd")))) + cairo_destroy (cr); + } + else if (DETAIL ("tooltip")) { - GdkGC *gc; - GdkColor lower_color; - GdkColor *upper_color; + WidgetParameters params; + ClearlooksStyle *clearlooks_style; + ClearlooksColors *colors; + cairo_t *cr; - if (GTK_WIDGET_HAS_FOCUS (widget)) - { - gc = style->base_gc[state_type]; - upper_color = &style->base[state_type]; - } - else - { - gc = style->base_gc[GTK_STATE_ACTIVE]; - upper_color = &style->base[GTK_STATE_ACTIVE]; - } - - if (GTK_IS_TREE_VIEW (widget) && 0) - { - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + CHECK_ARGS + SANITIZE_SIZE - if (gtk_tree_selection_count_selected_rows (sel) > 1) - { - parent_class->draw_flat_box (style, window, state_type, shadow_type, - area, widget, detail, - x, y, width, height); - return; - } - } - - shade (upper_color, &lower_color, 0.8); + clearlooks_style = CLEARLOOKS_STYLE (style); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + colors = &clearlooks_style->colors; + cr = ge_gdk_drawable_to_cairo (window, area); - if (area) - gdk_gc_set_clip_rectangle (gc, area); - - draw_hgradient (window, gc, style, - x, y, width, height, upper_color, &lower_color); + STYLE_FUNCTION (draw_tooltip) (cr, colors, ¶ms, x, y, width, height); - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); + cairo_destroy (cr); + } + else if ((CLEARLOOKS_STYLE (style)->style == CL_STYLE_GLOSSY || CLEARLOOKS_STYLE (style)->style == CL_STYLE_GUMMY) && + ((DETAIL("checkbutton") || DETAIL("radiobutton")) && state_type == GTK_STATE_PRELIGHT)) + { + /* XXX: Don't draw any check/radiobutton bg in GLOSSY or GUMMY mode. */ } else { - parent_class->draw_flat_box (style, window, state_type, - shadow_type, - area, widget, detail, - x, y, width, height); + clearlooks_parent_class->draw_flat_box (style, window, state_type, + shadow_type, + area, widget, detail, + x, y, width, height); } } -/**************************************************************************/ static void -draw_shadow (DRAW_ARGS) +clearlooks_style_draw_shadow (DRAW_ARGS) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - CLRectangle r; - - GdkGC *outer_gc = clearlooks_style->shade_gc[4]; - GdkGC *gc1 = NULL; - GdkGC *gc2 = NULL; - gint thickness_light; - gint thickness_dark; - gboolean interior_focus = FALSE; - -#if DEBUG - printf("draw_shadow: %s %d %d %d %d\n", detail, x, y, width, height); -#endif + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + cairo_t *cr = ge_gdk_drawable_to_cairo (window, area); - if (widget == NULL) - { - gdk_draw_rectangle (window, outer_gc, FALSE, - x, y, width - 1, height - 1); - return; - } + CHECK_ARGS + SANITIZE_SIZE - if ((width == -1) && (height == -1)) - gdk_window_get_size (window, &width, &height); - else if (width == -1) - gdk_window_get_size (window, &width, NULL); - else if (height == -1) - gdk_window_get_size (window, NULL, &height); + if ((DETAIL ("entry") && !(widget && widget->parent && GE_IS_TREE_VIEW (widget->parent))) || + (DETAIL ("frame") && ge_is_in_combo_box (widget))) + { + WidgetParameters params; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - cl_rectangle_reset (&r, style); + /* Override the entries state type, because we are too lame to handle this via + * the focus ring, and GtkEntry doesn't even set the INSENSITIVE state ... */ + if (state_type == GTK_STATE_NORMAL && widget && GE_IS_ENTRY (widget)) + params.state_type = GTK_WIDGET_STATE (widget); - if (DETAIL ("frame") && widget->parent && - GTK_IS_STATUSBAR (widget->parent)) - { - gtk_style_apply_default_background (style, window,widget && !GTK_WIDGET_NO_WINDOW (widget), - state_type, area, x, y, width, height); - - if (area) + if (widget && (ge_is_in_combo_box (widget) || GE_IS_SPIN_BUTTON (widget))) { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], area); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area); + width += style->xthickness; + if (!params.ltr) + x -= style->xthickness; + + if (params.ltr) + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + else + params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; } - gdk_draw_line (window, clearlooks_style->shade_gc[3], - x, y, x + width, y); - gdk_draw_line (window, clearlooks_style->shade_gc[0], - x, y + 1, x + width, y + 1); + STYLE_FUNCTION (draw_entry) (cr, &clearlooks_style->colors, ¶ms, + x, y, width, height); + } + else if (DETAIL ("frame") && widget && GE_IS_STATUSBAR (widget->parent)) + { + WidgetParameters params; - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], NULL); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL); - } + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + gtk_style_apply_default_background (style, window, TRUE, state_type, + area, x, y, width, height); + + STYLE_FUNCTION (draw_statusbar) (cr, colors, ¶ms, + x, y, width, height); } - else if (detail && !strcmp (detail, "entry")) + else if (DETAIL ("frame")) { - if ( widget->parent && (GTK_IS_COMBO_BOX_ENTRY (widget->parent) || - GTK_IS_SPIN_BUTTON(widget) || - GTK_IS_COMBO (widget->parent))) - { - cl_draw_combobox_entry (style, window, GTK_WIDGET_STATE(widget), shadow_type, area, widget, detail, x, y, width, height); - } - else - { - cl_draw_entry (style, window, GTK_WIDGET_STATE(widget), shadow_type, area, widget, detail, x, y, width, height); - } + WidgetParameters params; + FrameParameters frame; + frame.shadow = shadow_type; + frame.gap_x = -1; /* No gap will be drawn */ + frame.border = &colors->shade[4]; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_NONE; + + if (widget && !g_str_equal ("XfcePanelWindow", gtk_widget_get_name (gtk_widget_get_toplevel (widget)))) + STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame, + x, y, width, height); } - else if (DETAIL ("viewport") || DETAIL ("scrolled_window")) + else if (DETAIL ("scrolled_window") || DETAIL ("viewport") || detail == NULL) { - gdk_draw_rectangle (window, clearlooks_style->shade_gc[4], FALSE, - x, y, width - 1, height - 1); + CairoColor *border = (CairoColor*)&colors->shade[5]; + cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1); + ge_cairo_set_color (cr, border); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); } else { - if (DETAIL ("menuitem")) - outer_gc = clearlooks_style->spot3_gc; - else - outer_gc = clearlooks_style->shade_gc[4]; - - if (shadow_type == GTK_SHADOW_IN) - gdk_draw_rectangle (window, outer_gc, FALSE, - x, y, width - 1, height - 1); - else if (shadow_type == GTK_SHADOW_OUT) - { - gdk_draw_rectangle (window, outer_gc, FALSE, - x, y, width - 1, height - 1); - gdk_draw_line (window, style->light_gc[state_type], - x+1, y+1, x+width-2, y+1); - gdk_draw_line (window, style->light_gc[state_type], - x+1, y+1, x+1, y+height-2); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) - { - GdkGC *a = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 0 : 3]; - GdkGC *b = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 3 : 0]; - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - - r.bordergc = a; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r); - cl_rectangle_reset_clip_rectangle (&r); - - r.bordergc = b; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r); - cl_rectangle_reset_clip_rectangle (&r); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) - { - GdkGC *a = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 3 : 0]; - GdkGC *b = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 0 : 3]; - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); + WidgetParameters params; + FrameParameters frame; - r.bordergc = a; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r); - cl_rectangle_reset_clip_rectangle (&r); - - r.bordergc = b; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r); - cl_rectangle_reset_clip_rectangle (&r); - } - else - parent_class->draw_shadow (style, window, state_type, shadow_type, - area, widget, detail, - x, y, width, height); + frame.shadow = shadow_type; + frame.gap_x = -1; + frame.border = &colors->shade[5]; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_ALL; + + STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame, x, y, width, height); } + + cairo_destroy (cr); } -#define GDK_RECTANGLE_SET(rect,a,b,c,d) rect.x = a; \ - rect.y = b; \ - rect.width = c; \ - rect.height = d; - - static void -draw_box_gap (DRAW_ARGS, - GtkPositionType gap_side, - gint gap_x, - gint gap_width) +clearlooks_style_draw_box_gap (DRAW_ARGS, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - CLRectangle r; - - GdkRegion *area_region = NULL, - *gap_region = NULL; - GdkRectangle light_rect; - GdkRectangle dark_rect; - -#if DEBUG - printf("draw_box_gap: %s %d %d %d %d\n", detail, x, y, width, height); -#endif - - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - sanitize_size (window, &width, &height); + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + cairo_t *cr; - cl_rectangle_reset (&r, style); + CHECK_ARGS + SANITIZE_SIZE - r.bordergc = clearlooks_style->shade_gc[5]; + cr = ge_gdk_drawable_to_cairo (window, area); - r.topleft = style->light_gc[state_type]; - r.bottomright = clearlooks_style->shade_gc[1]; - - if (area) - area_region = gdk_region_rectangle (area); - else + if (DETAIL ("notebook")) { - GdkRectangle tmp = { x, y, width, height }; - area_region = gdk_region_rectangle (&tmp); - } - - switch (gap_side) - { - case GTK_POS_TOP: - { - GdkRectangle rect = { x+gap_x+1, y, gap_width-2, 2 }; - gap_region = gdk_region_rectangle (&rect); + WidgetParameters params; + FrameParameters frame; + gboolean start, end; + + frame.shadow = shadow_type; + frame.gap_side = gap_side; + frame.gap_x = gap_x; + frame.gap_width = gap_width; + frame.border = &colors->shade[5]; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - GDK_RECTANGLE_SET (light_rect, x+gap_x+1, y, x+gap_x+1, y+1); - GDK_RECTANGLE_SET (dark_rect, x+gap_x+gap_width-2, y, x+gap_x+gap_width-2, y); - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_ROUND); + clearlooks_get_notebook_tab_position (widget, &start, &end); + params.corners = CR_CORNER_ALL; + switch (gap_side) { + case GTK_POS_LEFT: + if (start) + params.corners ^= CR_CORNER_TOPLEFT; + if (end) + params.corners ^= CR_CORNER_BOTTOMLEFT; break; - } - case GTK_POS_BOTTOM: - { - GdkRectangle rect = { x+gap_x+1, y+height-2, gap_width-2, 2 }; - gap_region = gdk_region_rectangle (&rect); - - GDK_RECTANGLE_SET (light_rect, x+gap_x+1, y+height-2, x+gap_x+1, y+height-1); - GDK_RECTANGLE_SET (dark_rect, x+gap_x+gap_width-2, y+height-2, x+gap_x+gap_width-2, y+height-1); - - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_NONE); - + case GTK_POS_RIGHT: + if (start) + params.corners ^= CR_CORNER_TOPRIGHT; + if (end) + params.corners ^= CR_CORNER_BOTTOMRIGHT; break; - } - case GTK_POS_LEFT: - { - GdkRectangle rect = { x, y+gap_x+1, 2, gap_width-2 }; - gap_region = gdk_region_rectangle (&rect); - - GDK_RECTANGLE_SET (light_rect, x, y+gap_x+1, x+1, y+gap_x+1); - GDK_RECTANGLE_SET (dark_rect, x, y+gap_x+gap_width-2, x, y+gap_x+gap_width-2); - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); + case GTK_POS_TOP: + if (ge_widget_is_ltr (widget)) { + if (start) + params.corners ^= CR_CORNER_TOPLEFT; + if (end) + params.corners ^= CR_CORNER_TOPRIGHT; + } else { + if (start) + params.corners ^= CR_CORNER_TOPRIGHT; + if (end) + params.corners ^= CR_CORNER_TOPLEFT; + } break; - } - case GTK_POS_RIGHT: - { - GdkRectangle rect = { x+width-2, y+gap_x+1, 2, gap_width-2 }; - gap_region = gdk_region_rectangle (&rect); - - GDK_RECTANGLE_SET (light_rect, x+width-2, y+gap_x+1, x+width-1, y+gap_x+1); - GDK_RECTANGLE_SET (dark_rect, x+width-2, y+gap_x+gap_width-2, x+width-1, y+gap_x+gap_width-2); - - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_NONE); + case GTK_POS_BOTTOM: + if (ge_widget_is_ltr (widget)) { + if (start) + params.corners ^= CR_CORNER_BOTTOMLEFT; + if (end) + params.corners ^= CR_CORNER_BOTTOMRIGHT; + } else { + if (start) + params.corners ^= CR_CORNER_BOTTOMRIGHT; + if (end) + params.corners ^= CR_CORNER_BOTTOMLEFT; + } break; - } - } - - gdk_region_subtract (area_region, gap_region); - - gdk_gc_set_clip_region (r.bordergc, area_region); - gdk_gc_set_clip_region (r.topleft, area_region); - gdk_gc_set_clip_region (r.bottomright, area_region); - - gdk_region_destroy (area_region); - gdk_region_destroy (gap_region); - - gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, x, y, width, height); - - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - - cl_draw_shadow (window, widget, style, x, y, width, height, &r); + } - gdk_gc_set_clip_region (r.bordergc, NULL); - gdk_gc_set_clip_region (r.topleft, NULL); - gdk_gc_set_clip_region (r.bottomright, NULL); + /* Fill the background with bg[NORMAL] */ + ge_cairo_rounded_rectangle (cr, x, y, width, height, params.radius, params.corners); + ge_cairo_set_color (cr, &colors->bg[GTK_STATE_NORMAL]); + cairo_fill (cr); + + STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame, + x, y, width, height); + } + else + { + clearlooks_parent_class->draw_box_gap (style, window, state_type, shadow_type, + area, widget, detail, + x, y, width, height, + gap_side, gap_x, gap_width); + } - /* it's a semi hack */ - gdk_draw_line (window, style->light_gc[state_type], - light_rect.x, light_rect.y, - light_rect.width, light_rect.height); - - gdk_draw_line (window, clearlooks_style->shade_gc[1], - dark_rect.x, dark_rect.y, - dark_rect.width, dark_rect.height); + cairo_destroy (cr); } -/**************************************************************************/ - static void -draw_extension (DRAW_ARGS, GtkPositionType gap_side) +clearlooks_style_draw_extension (DRAW_ARGS, GtkPositionType gap_side) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0; - CLRectangle r; + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + cairo_t *cr; -#if DEBUG - printf("draw_extension: %s %d %d %d %d\n", detail, x, y, width, height); -#endif + CHECK_ARGS + SANITIZE_SIZE - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - sanitize_size (window, &width, &height); + cr = ge_gdk_drawable_to_cairo (window, area); if (DETAIL ("tab")) { - GdkRectangle new_area; - GdkColor tmp_color; - - cl_rectangle_set_button (&r, style, state_type, FALSE, FALSE, - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); + WidgetParameters params; + TabParameters tab; - if (state_type == GTK_STATE_ACTIVE) - shade (&style->bg[state_type], &tmp_color, 1.08); - else - shade (&style->bg[state_type], &tmp_color, 1.05); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - if (area) - { - new_area = *area; - } - else - { - new_area.x = x; - new_area.y = y; - new_area.width = width; - new_area.height = height; - } + tab.gap_side = (ClearlooksGapSide)gap_side; switch (gap_side) { - case GTK_POS_BOTTOM: - height+=2; - new_area.y = y; - new_area.height = height-2; - r.gradient_type = CL_GRADIENT_VERTICAL; - cl_rectangle_set_gradient (&r.fill_gradient, &tmp_color, &style->bg[state_type]); - cl_rectangle_set_gradient (&r.border_gradient, - &clearlooks_style->border[CL_BORDER_UPPER+my_state_type], - &clearlooks_style->border[CL_BORDER_LOWER+my_state_type]); + case CL_GAP_BOTTOM: + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; break; - case GTK_POS_TOP: - y-=2; - height+=2; - new_area.y = y+2; - new_area.height = height; - r.gradient_type = CL_GRADIENT_VERTICAL; - cl_rectangle_set_gradient (&r.fill_gradient, &style->bg[state_type], &tmp_color); - cl_rectangle_set_gradient (&r.border_gradient, - &clearlooks_style->border[CL_BORDER_LOWER+my_state_type], - &clearlooks_style->border[CL_BORDER_UPPER+my_state_type]); + case CL_GAP_TOP: + params.corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT; break; - case GTK_POS_LEFT: - x-=2; - width+=2; - new_area.x = x+2; - new_area.width = width; - r.gradient_type = CL_GRADIENT_HORIZONTAL; - cl_rectangle_set_gradient (&r.fill_gradient, &style->bg[state_type], &tmp_color); - cl_rectangle_set_gradient (&r.border_gradient, - &clearlooks_style->border[CL_BORDER_LOWER+my_state_type], - &clearlooks_style->border[CL_BORDER_UPPER+my_state_type]); + case CL_GAP_RIGHT: + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; break; - case GTK_POS_RIGHT: - width+=2; - new_area.x = x; - new_area.width = width-2; - r.gradient_type = CL_GRADIENT_HORIZONTAL; - cl_rectangle_set_gradient (&r.fill_gradient, &tmp_color, &style->bg[state_type]); - cl_rectangle_set_gradient (&r.border_gradient, - &clearlooks_style->border[CL_BORDER_UPPER+my_state_type], - &clearlooks_style->border[CL_BORDER_LOWER+my_state_type]); - break; - } - - r.topleft = style->light_gc[state_type]; - r.bottomright = (state_type == GTK_STATE_NORMAL) ? clearlooks_style->shade_gc[1] : NULL; - - cl_rectangle_set_clip_rectangle (&r, &new_area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); - - /* draw the selection stripe */ - if (state_type != GTK_STATE_ACTIVE) { - cl_rectangle_set_gradient (&r.fill_gradient, NULL, NULL); - r.fillgc = clearlooks_style->spot2_gc; - - switch (gap_side) - { - case GTK_POS_BOTTOM: - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_NONE); - cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->spot3, &clearlooks_style->spot2); - r.gradient_type = CL_GRADIENT_VERTICAL; - - cl_rectangle_set_clip_rectangle (&r, &new_area); - cl_draw_rectangle (window, widget, style, x, y, width, 3, &r); - cl_rectangle_reset_clip_rectangle (&r); - break; - case GTK_POS_TOP: - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_ROUND); - cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->spot2, &clearlooks_style->spot3); - r.gradient_type = CL_GRADIENT_VERTICAL; - - cl_rectangle_set_clip_rectangle (&r, &new_area); - cl_draw_rectangle (window, widget, style, x, y + height - 3, width, 3, &r); - cl_rectangle_reset_clip_rectangle (&r); - break; - case GTK_POS_LEFT: - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); - cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->spot2, &clearlooks_style->spot3); - r.gradient_type = CL_GRADIENT_HORIZONTAL; - - cl_rectangle_set_clip_rectangle (&r, &new_area); - cl_draw_rectangle (window, widget, style, x + width - 3, y, 3, height, &r); - cl_rectangle_reset_clip_rectangle (&r); - break; - case GTK_POS_RIGHT: - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_NONE); - cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->spot3, &clearlooks_style->spot2); - r.gradient_type = CL_GRADIENT_HORIZONTAL; - - cl_rectangle_set_clip_rectangle (&r, &new_area); - cl_draw_rectangle (window, widget, style, x, y, 3, height, &r); - cl_rectangle_reset_clip_rectangle (&r); - break; - } + case CL_GAP_LEFT: + params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; } - + STYLE_FUNCTION(draw_tab) (cr, colors, ¶ms, &tab, + x, y, width, height); } else { - parent_class->draw_extension (style, window, state_type, shadow_type, area, + clearlooks_parent_class->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side); + } + + cairo_destroy (cr); } - - -/**************************************************************************/ static void -draw_handle (DRAW_ARGS, GtkOrientation orientation) +clearlooks_style_draw_handle (DRAW_ARGS, GtkOrientation orientation) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - gint xx, yy; - gint xthick, ythick; - GdkGC *light_gc, *dark_gc; - GdkRectangle rect; - GdkRectangle dest; - gint intersect; - gint h; - int i; - int n_lines; - int offset; + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + cairo_t *cr; + gboolean is_horizontal; -#if DEBUG - printf("draw_handle: %s %d %d %d %d\n", detail, x, y, width, height); -#endif - - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); + CHECK_ARGS + SANITIZE_SIZE - sanitize_size (window, &width, &height); + cr = ge_gdk_drawable_to_cairo (window, area); - if (state_type == GTK_STATE_PRELIGHT) - gtk_style_apply_default_background (style, window, - widget && !GTK_WIDGET_NO_WINDOW (widget), - state_type, area, x, y, width, height); - - /* orientation is totally bugged, but this actually works... */ - orientation = (width > height) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; - - if (!strcmp (detail, "paned")) - { - /* we want to ignore the shadow border in paned widgets */ - xthick = 0; - ythick = 0; - } - else + /* Evil hack to work around broken orientation for toolbars */ + is_horizontal = (width > height); + + if (DETAIL ("handlebox")) { - xthick = style->xthickness; - ythick = style->ythickness; - } + WidgetParameters params; + HandleParameters handle; - if ( ((DETAIL ("handlebox") && widget && GTK_IS_HANDLE_BOX (widget)) || DETAIL ("dockitem")) && - orientation == GTK_ORIENTATION_VERTICAL ) - { - /* The line in the toolbar */ - - light_gc = style->light_gc[state_type]; - dark_gc = clearlooks_style->shade_gc[3]; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + handle.type = CL_HANDLE_TOOLBAR; + handle.horizontal = is_horizontal; - if (area) - { - gdk_gc_set_clip_rectangle (light_gc, area); - gdk_gc_set_clip_rectangle (dark_gc, area); - } - - if (area) + /* Is this ever true? -Daniel */ + if (GE_IS_TOOLBAR (widget) && shadow_type != GTK_SHADOW_NONE) { - gdk_gc_set_clip_rectangle (light_gc, NULL); - gdk_gc_set_clip_rectangle (dark_gc, NULL); - } + ToolbarParameters toolbar; - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], area); - } - - gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y, x + width, y); - gdk_draw_line (window, clearlooks_style->shade_gc[3], x, y + height - 1, x + width, y + height - 1); - - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], NULL); + clearlooks_set_toolbar_parameters (&toolbar, widget, window, x, y); + + toolbar.style = clearlooks_style->toolbarstyle; + + cairo_save (cr); + STYLE_FUNCTION(draw_toolbar) (cr, colors, ¶ms, &toolbar, x, y, width, height); + cairo_restore (cr); } + + STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle, + x, y, width, height); } - - light_gc = clearlooks_style->shade_gc[0]; - dark_gc = clearlooks_style->shade_gc[4]; - - rect.x = x + xthick; - rect.y = y + ythick; - rect.width = width - (xthick * 2); - rect.height = height - (ythick * 2); - - if (area) - intersect = gdk_rectangle_intersect (area, &rect, &dest); - else + else if (DETAIL ("paned")) { - intersect = TRUE; - dest = rect; - } - - if (!intersect) - return; - - gdk_gc_set_clip_rectangle (light_gc, &dest); - gdk_gc_set_clip_rectangle (dark_gc, &dest); - - n_lines = (!strcmp (detail, "paned")) ? 21 : 11; + WidgetParameters params; + HandleParameters handle; - if (orientation == GTK_ORIENTATION_VERTICAL) - { - h = width - 2 * xthick; - h = MAX (3, h - 6); - - xx = x + (width - h) / 2; - offset = (height - 2*ythick - 2*n_lines)/2 + 1; - if (offset < 0) - offset = 0; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + handle.type = CL_HANDLE_SPLITTER; + handle.horizontal = orientation == GTK_ORIENTATION_HORIZONTAL; - for (i = 0, yy = y + ythick + offset; yy <= (y + height - ythick - 1) && i < n_lines; yy += 2, i++) - { - gdk_draw_line (window, dark_gc, xx, yy, xx + h, yy); - gdk_draw_line (window, light_gc, xx, yy + 1, xx + h, yy + 1); - } + STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle, + x, y, width, height); } else { - h = height - 2 * ythick; - h = MAX (3, h - 6); - - yy = y + (height - h) / 2; - offset = (width - 2*xthick - 2*n_lines)/2 + 1; - if (offset < 0) - offset = 0; + WidgetParameters params; + HandleParameters handle; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + handle.type = CL_HANDLE_TOOLBAR; + handle.horizontal = is_horizontal; - for (i = 0, xx = x + xthick + offset; i < n_lines; xx += 2, i++) + /* Is this ever true? -Daniel */ + if (GE_IS_TOOLBAR (widget) && shadow_type != GTK_SHADOW_NONE) { - gdk_draw_line (window, dark_gc, xx, yy, xx, yy + h); - gdk_draw_line (window, light_gc, xx + 1, yy, xx + 1, yy + h); + ToolbarParameters toolbar; + + clearlooks_set_toolbar_parameters (&toolbar, widget, window, x, y); + + toolbar.style = clearlooks_style->toolbarstyle; + + cairo_save (cr); + STYLE_FUNCTION(draw_toolbar) (cr, colors, ¶ms, &toolbar, x, y, width, height); + cairo_restore (cr); } + + STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle, + x, y, width, height); } - gdk_gc_set_clip_rectangle (light_gc, NULL); - gdk_gc_set_clip_rectangle (dark_gc, NULL); + cairo_destroy (cr); } -/**************************************************************************/ - static void -draw_box (DRAW_ARGS) +clearlooks_style_draw_box (DRAW_ARGS) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - CLRectangle r; - gboolean false_size = FALSE; + const ClearlooksColors *colors; + cairo_t *cr; -#ifdef DEBUG - printf("draw_box: %s %d %d %d %d\n", detail, x, y, width, height); -#endif - - g_return_if_fail (style != NULL); - g_return_if_fail (window != NULL); + cr = ge_gdk_drawable_to_cairo (window, area); + colors = &clearlooks_style->colors; - if (width == -1 || height == -1) - false_size = TRUE; + CHECK_ARGS + SANITIZE_SIZE + + if (DETAIL ("menubar") && !ge_is_panel_widget_item(widget)) + { + WidgetParameters params; + MenuBarParameters menubar; - if ((width == -1) && (height == -1)) - gdk_window_get_size (window, &width, &height); - else if (width == -1) - gdk_window_get_size (window, &width, NULL); - else if (height == -1) - gdk_window_get_size (window, NULL, &height); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - cl_rectangle_reset (&r, style); + menubar.style = clearlooks_style->menubarstyle; - if (widget == NULL) - return; - - /* listview headers */ - if (widget && DETAIL ("button") && widget->parent && - (GTK_IS_TREE_VIEW(widget->parent) || - GTK_IS_CLIST (widget->parent) || - strcmp(G_OBJECT_TYPE_NAME (widget->parent), "ETree") == 0)) - { - cl_draw_treeview_header (style, window, state_type, shadow_type, - area, widget, detail, x, y, width, height); + STYLE_FUNCTION(draw_menubar) (cr, colors, ¶ms, &menubar, + x, y, width, height); } - else if (detail && (!strcmp (detail, "button") || - !strcmp (detail, "buttondefault"))) + else if (DETAIL ("button") && widget && widget->parent && + (GE_IS_TREE_VIEW(widget->parent) || + GE_IS_CLIST (widget->parent) || + ge_object_is_a (G_OBJECT(widget->parent), "ETree"))) /* ECanvas inside ETree */ { - if (GTK_IS_COMBO_BOX_ENTRY(widget->parent) || GTK_IS_COMBO(widget->parent)) + WidgetParameters params; + ListViewHeaderParameters header; + + gint columns, column_index; + gboolean resizable = TRUE; + + /* XXX: This makes unknown treeview header CL_ORDER_MIDDLE, in need for something nicer */ + columns = 3; + column_index = 1; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + params.corners = CR_CORNER_NONE; + + if (GE_IS_TREE_VIEW (widget->parent)) { - cl_draw_combobox_button (style, window, state_type, shadow_type, - area, widget, - detail, x, y, width, height); + clearlooks_treeview_get_header_index (GTK_TREE_VIEW(widget->parent), + widget, &column_index, &columns, + &resizable); } - else + else if (GE_IS_CLIST (widget->parent)) { - cl_draw_button (style, window, state_type, shadow_type, area, widget, - detail, x, y, width, height); + clearlooks_clist_get_header_index (GTK_CLIST(widget->parent), + widget, &column_index, &columns); } + + header.resizable = resizable; + + if (column_index == 0) + header.order = params.ltr ? CL_ORDER_FIRST : CL_ORDER_LAST; + else if (column_index == columns-1) + header.order = params.ltr ? CL_ORDER_LAST : CL_ORDER_FIRST; + else + header.order = CL_ORDER_MIDDLE; + + gtk_style_apply_default_background (style, window, FALSE, state_type, area, x, y, width, height); + + STYLE_FUNCTION(draw_list_view_header) (cr, colors, ¶ms, &header, + x, y, width, height); } - else if (detail && ( - !strcmp (detail, "spinbutton_up") || - !strcmp (detail, "spinbutton_down") || - !strcmp (detail, "spinbutton"))) - { - cl_draw_spinbutton (style, window, state_type, shadow_type, area, - widget, detail, x, y, width, height); - } - else if (detail && ( - !strcmp (detail, "hscale") || !strcmp (detail, "vscale"))) + else if (DETAIL ("button") || DETAIL ("buttondefault")) { - cl_rectangle_set_button (&r, style, state_type, - GTK_WIDGET_HAS_DEFAULT (widget), GTK_WIDGET_HAS_FOCUS (widget), - CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_ROUND, CL_CORNER_ROUND); + WidgetParameters params; + ShadowParameters shadow = { CR_CORNER_ALL, CL_SHADOW_NONE } ; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - if (!strcmp (detail, "hscale") || !strcmp (detail, "vscale")) + if (ge_is_in_combo_box(widget)) { - r.fill_gradient.to = &clearlooks_style->shade[2]; - r.bottomright = clearlooks_style->shade_gc[2]; - } - - cl_set_corner_sharpness (detail, widget, &r); + if (params.ltr) + params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; + else + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; + + shadow.shadow = CL_SHADOW_IN; - if (!strcmp (detail, "spinbutton_up")) - { - r.border_gradient.to = r.border_gradient.from; - height++; - gtk_style_apply_default_background (style, window, FALSE, state_type, - area, x, y, width, height); + if (params.xthickness > 2) + { + if (params.ltr) + x--; + width++; + } } - else if (!strcmp (detail, "spinbutton_down")) + else { - r.border_gradient.to = r.border_gradient.from; - gtk_style_apply_default_background (style, window, FALSE, state_type, - area, x, y, width, height); - } + params.corners = CR_CORNER_ALL; + /* if (!(ge_is_combo_box (widget, FALSE))) */ + params.enable_glow = TRUE; + } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x+1, y+1, width-2, height-2, &r); - cl_draw_shadow (window, widget, style, x+1, y+1, width-2, height-2, &r); - cl_rectangle_reset_clip_rectangle (&r); + if (GE_IS_TOGGLE_BUTTON (widget) && + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + params.active = TRUE; + + STYLE_FUNCTION(draw_button) (cr, &clearlooks_style->colors, ¶ms, + x, y, width, height); } - else if (DETAIL ("trough") && GTK_IS_PROGRESS_BAR (widget)) + else if (DETAIL ("spinbutton_up") || DETAIL ("spinbutton_down")) { - GdkPoint points[4] = { {x,y}, {x+width-1,y}, {x,y+height-1}, {x+width-1,y+height-1} }; - - gdk_draw_points (window, style->bg_gc[state_type], points, 4); - - r.bordergc = clearlooks_style->shade_gc[5]; - r.fillgc = clearlooks_style->shade_gc[2]; + if (state_type == GTK_STATE_ACTIVE) + { + WidgetParameters params; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - cl_rectangle_set_corners (&r, CL_CORNER_NARROW, CL_CORNER_NARROW, - CL_CORNER_NARROW, CL_CORNER_NARROW); - - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + if (style->xthickness == 3) + { + width++; + if (params.ltr) + x--; + } + + if (DETAIL ("spinbutton_up")) + { + height+=2; + if (params.ltr) + params.corners = CR_CORNER_TOPRIGHT; + else + params.corners = CR_CORNER_TOPLEFT; + } + else + { + if (params.ltr) + params.corners = CR_CORNER_BOTTOMRIGHT; + else + params.corners = CR_CORNER_BOTTOMLEFT; + } + + STYLE_FUNCTION(draw_spinbutton_down) (cr, &clearlooks_style->colors, ¶ms, x, y, width, height); + } } - else if (DETAIL ("trough") && - (GTK_IS_VSCALE (widget) || GTK_IS_HSCALE (widget))) + else if (DETAIL ("spinbutton")) { - GdkGC *inner = clearlooks_style->shade_gc[3], - *outer = clearlooks_style->shade_gc[5], - *shadow = clearlooks_style->shade_gc[4]; - GdkColor upper_color = *clearlooks_get_spot_color (CLEARLOOKS_RC_STYLE (style->rc_style)), - lower_color; - - GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (widget)); + WidgetParameters params; - GtkOrientation orientation = GTK_RANGE (widget)->orientation; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - gint fill_size = (orientation ? height : width) * - (1 / ((adjustment->upper - adjustment->lower) / - (adjustment->value - adjustment->lower))); - - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - y += (height - SCALE_SIZE) / 2; - height = SCALE_SIZE; - } + if (params.ltr) + params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT; else - { - x += (width - SCALE_SIZE) / 2; - width = SCALE_SIZE; - } + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT; - if (state_type == GTK_STATE_INSENSITIVE) + if (style->xthickness == 3) { - outer = clearlooks_style->shade_gc[4]; - inner = clearlooks_style->shade_gc[2]; - shadow = clearlooks_style->shade_gc[3]; + if (params.ltr) + x--; + width++; } - cl_rectangle_init (&r, inner, outer, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE ); + STYLE_FUNCTION(draw_spinbutton) (cr, &clearlooks_style->colors, ¶ms, + x, y, width, height); + } + else if (detail && g_str_has_prefix (detail, "trough") && GE_IS_SCALE (widget)) + { + WidgetParameters params; + SliderParameters slider; - r.topleft = shadow; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_NONE; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + slider.lower = DETAIL ("trough-lower"); + slider.fill_level = DETAIL ("trough-fill-level") || DETAIL ("trough-fill-level-full"); - /* DRAW FILL */ - shade (&upper_color, &lower_color, 1.3); - - r.bordergc = clearlooks_style->spot3_gc; - r.fillgc = style->bg_gc[state_type]; + slider.horizontal = (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL); - r.gradient_type = (orientation == GTK_ORIENTATION_HORIZONTAL ) ? CL_GRADIENT_VERTICAL - : CL_GRADIENT_HORIZONTAL; + STYLE_FUNCTION(draw_scale_trough) (cr, &clearlooks_style->colors, + ¶ms, &slider, + x, y, width, height); + } + else if (DETAIL ("trough") && widget && GE_IS_PROGRESS_BAR (widget)) + { + WidgetParameters params; - cl_rectangle_set_gradient (&r.fill_gradient, &upper_color, &lower_color); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - cl_rectangle_set_clip_rectangle (&r, area); - if (orientation == GTK_ORIENTATION_HORIZONTAL && fill_size > 1) - { - if (gtk_range_get_inverted(GTK_RANGE(widget)) != (get_direction(widget) == GTK_TEXT_DIR_RTL)) - cl_draw_rectangle (window, widget, style, x+width-fill_size, y, fill_size, height, &r); - else - cl_draw_rectangle (window, widget, style, x, y, fill_size, height, &r); - } - else if (fill_size > 1) - { - if (gtk_range_get_inverted (GTK_RANGE (widget))) - cl_draw_rectangle (window, widget, style, x, y+height-fill_size, width, fill_size, &r); - else - cl_draw_rectangle (window, widget, style, x, y, width, fill_size, &r); - } - cl_rectangle_reset_clip_rectangle (&r); + STYLE_FUNCTION(draw_progressbar_trough) (cr, colors, ¶ms, + x, y, width, height); } - else if (DETAIL ("trough")) + else if (DETAIL ("trough") && widget && (GE_IS_VSCROLLBAR (widget) || GE_IS_HSCROLLBAR (widget))) { - GdkGC *inner = clearlooks_style->shade_gc[3], - *outer = clearlooks_style->shade_gc[5]; + WidgetParameters params; + ScrollBarParameters scrollbar; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_NONE; - cl_rectangle_init (&r, inner, outer, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE ); + scrollbar.horizontal = TRUE; + scrollbar.junction = clearlooks_scrollbar_get_junction (widget); - if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_VERTICAL) + if (GE_IS_RANGE (widget)) + scrollbar.horizontal = GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL; + + if (scrollbar.horizontal) { - y+=1; - height-=2; + x += 2; + width -= 4; } else { - x+=1; - width-=2; + y += 2; + height -= 4; } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + STYLE_FUNCTION(draw_scrollbar_trough) (cr, colors, ¶ms, &scrollbar, + x, y, width, height); } - else if (detail && (!strcmp (detail, "vscrollbar") || - !strcmp (detail, "hscrollbar") || - !strcmp (detail, "stepper"))) + else if (DETAIL ("bar")) { - ClScrollButtonType button_type = CL_SCROLLBUTTON_OTHER; - gboolean horizontal = TRUE; - - if (GTK_IS_VSCROLLBAR(widget)) - { - if (y == widget->allocation.y) - button_type = CL_SCROLLBUTTON_BEGIN; - else if (y+height == widget->allocation.y+widget->allocation.height) - button_type = CL_SCROLLBUTTON_END; + WidgetParameters params; + ProgressBarParameters progressbar; + gdouble elapsed = 0.0; - horizontal = FALSE; - } - else if (GTK_IS_HSCROLLBAR(widget)) - { - if (x == widget->allocation.x) - button_type = CL_SCROLLBUTTON_BEGIN; - else if (x+width == widget->allocation.x+widget->allocation.width) - button_type = CL_SCROLLBUTTON_END; +#ifdef HAVE_ANIMATION + if(clearlooks_style->animation && CL_IS_PROGRESS_BAR (widget)) + { + gboolean activity_mode = GTK_PROGRESS (widget)->activity_mode; + + if (!activity_mode) + clearlooks_animation_progressbar_add ((gpointer)widget); } - cl_rectangle_set_button (&r, style, state_type, FALSE, FALSE, 0,0,0,0); - - cl_rectangle_set_gradient (&r.fill_gradient, NULL, NULL); - cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->inset_light[state_type], - &clearlooks_style->inset_dark[state_type]); - - - r.gradient_type = horizontal ? CL_GRADIENT_VERTICAL - : CL_GRADIENT_HORIZONTAL; - - r.bottomright = clearlooks_style->shade_gc[1]; - r.border_gradient.to = r.border_gradient.from; - - if (button_type == CL_SCROLLBUTTON_OTHER) - { - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - } - else if (button_type == CL_SCROLLBUTTON_BEGIN) + elapsed = clearlooks_animation_elapsed (widget); +#endif + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + if (widget && GE_IS_PROGRESS_BAR (widget)) { - if (horizontal) - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_NONE); - else - cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_NONE); + progressbar.orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget)); + progressbar.value = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(widget)); + progressbar.pulsing = GTK_PROGRESS (widget)->activity_mode; } else { - if (horizontal) - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_ROUND, - CL_CORNER_NONE, CL_CORNER_ROUND); - else - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_ROUND, CL_CORNER_ROUND); + progressbar.orientation = CL_ORIENTATION_LEFT_TO_RIGHT; + progressbar.value = 0; + progressbar.pulsing = FALSE; } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + if (!params.ltr) + { + if (progressbar.orientation == GTK_PROGRESS_LEFT_TO_RIGHT) + progressbar.orientation = GTK_PROGRESS_RIGHT_TO_LEFT; + else if (progressbar.orientation == GTK_PROGRESS_RIGHT_TO_LEFT) + progressbar.orientation = GTK_PROGRESS_LEFT_TO_RIGHT; + } - } - else if (DETAIL ("slider")) - { - if (DETAIL("slider") && widget && GTK_IS_RANGE (widget)) + /* Following is a hack to have a larger clip area, the one passed in + * does not allow for the shadow. */ + if (area) { - GtkAdjustment *adj = GTK_RANGE (widget)->adjustment; - - if (adj->value <= adj->lower && - (GTK_RANGE (widget)->has_stepper_a || GTK_RANGE (widget)->has_stepper_b)) + GdkRectangle tmp = *area; + if (!progressbar.pulsing) { - if (GTK_IS_VSCROLLBAR (widget)) + switch (progressbar.orientation) { - y-=1; - height+=1; - } - else if (GTK_IS_HSCROLLBAR (widget)) - { - x-=1; - width+=1; + case GTK_PROGRESS_RIGHT_TO_LEFT: + tmp.x -= 1; + case GTK_PROGRESS_LEFT_TO_RIGHT: + tmp.width += 1; + break; + case GTK_PROGRESS_BOTTOM_TO_TOP: + tmp.y -= 1; + case GTK_PROGRESS_TOP_TO_BOTTOM: + tmp.height += 1; + break; } } - if (adj->value >= adj->upper - adj->page_size && - (GTK_RANGE (widget)->has_stepper_c || GTK_RANGE (widget)->has_stepper_d)) + else { - if (GTK_IS_VSCROLLBAR (widget)) - height+=1; - else if (GTK_IS_HSCROLLBAR (widget)) - width+=1; + if (progressbar.orientation == GTK_PROGRESS_RIGHT_TO_LEFT || + progressbar.orientation == GTK_PROGRESS_LEFT_TO_RIGHT) + { + tmp.x -= 1; + tmp.width += 2; + } + else + { + tmp.y -= 1; + tmp.height += 2; + } } - } - cl_rectangle_set_button (&r, style, state_type, FALSE, GTK_WIDGET_HAS_FOCUS (widget), - CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - - r.gradient_type = GTK_IS_HSCROLLBAR (widget) ? CL_GRADIENT_VERTICAL - : CL_GRADIENT_HORIZONTAL; - - cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->inset_light[state_type], - &clearlooks_style->inset_dark[state_type]); - - r.bottomright = clearlooks_style->shade_gc[1]; - r.border_gradient.to = r.border_gradient.from; + cairo_reset_clip (cr); + gdk_cairo_rectangle (cr, &tmp); + cairo_clip (cr); + } - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + STYLE_FUNCTION(draw_progressbar_fill) (cr, colors, ¶ms, &progressbar, + x, y, width, height, + 10 - (int)(elapsed * 10.0) % 10); } - else if (detail && !strcmp (detail, "optionmenu")) /* supporting deprecated */ + else if (DETAIL ("optionmenu")) { - cl_draw_optionmenu(style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); + WidgetParameters params; + OptionMenuParameters optionmenu; + + GtkRequisition indicator_size; + GtkBorder indicator_spacing; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + params.enable_glow = TRUE; + + ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing); + + if (ge_widget_is_ltr (widget)) + optionmenu.linepos = width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - 1; + else + optionmenu.linepos = (indicator_size.width + indicator_spacing.left + indicator_spacing.right) + 1; + + STYLE_FUNCTION(draw_optionmenu) (cr, colors, ¶ms, &optionmenu, + x, y, width, height); } else if (DETAIL ("menuitem")) { - if (clearlooks_style->menuitemstyle == 0) - { - cl_draw_menuitem_flat (window, widget, style, area, state_type, - x, y, width, height, &r); - } - else if (clearlooks_style->menuitemstyle == 1) + WidgetParameters params; + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + if (widget && GE_IS_MENU_BAR (widget->parent)) { - cl_draw_menuitem_gradient (window, widget, style, area, state_type, - x, y, width, height, &r); + params.corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT; + height += 1; + STYLE_FUNCTION(draw_menubaritem) (cr, colors, ¶ms, x, y, width, height); } else - { - cl_draw_menuitem_button (window, widget, style, area, state_type, - x, y, width, height, &r); + { + params.corners = CR_CORNER_ALL; + STYLE_FUNCTION(draw_menuitem) (cr, colors, ¶ms, x, y, width, height); } } - else if (DETAIL ("menubar") && (clearlooks_style->sunkenmenubar || clearlooks_style->menubarstyle > 0)) + else if (DETAIL ("hscrollbar") || DETAIL ("vscrollbar")) /* This can't be "stepper" for scrollbars ... */ { - GdkGC *dark = clearlooks_style->shade_gc[2]; - GdkColor upper_color, lower_color; - - /* don't draw sunken menubar on gnome panel - IT'S A HACK! HORRIBLE HACK! HIDEOUS HACK! - BUT IT WORKS FOR ME(tm)! */ - if (widget->parent && - strcmp(G_OBJECT_TYPE_NAME (widget->parent), "PanelWidget") == 0) - return; - - shade(&style->bg[state_type], &upper_color, 1.0); - shade(&style->bg[state_type], &lower_color, 0.95); - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); + WidgetParameters params; + ScrollBarParameters scrollbar; + ScrollBarStepperParameters stepper; + GdkRectangle this_rectangle; - r.fillgc = style->bg_gc[state_type]; - r.bordergc = clearlooks_style->shade_gc[2]; - r.gradient_type = CL_GRADIENT_VERTICAL; + this_rectangle.x = x; + this_rectangle.y = y; + this_rectangle.width = width; + this_rectangle.height = height; - cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->shade[2], - &clearlooks_style->shade[3]); - cl_rectangle_set_gradient (&r.fill_gradient, &upper_color, &lower_color); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_NONE; - /* make vertical and top borders invisible for style 2 */ - if (clearlooks_style->menubarstyle == 2) { - x--; width+=2; - y--; height+=1; + scrollbar.has_color = FALSE; + scrollbar.horizontal = TRUE; + scrollbar.junction = clearlooks_scrollbar_get_junction (widget); + + if (clearlooks_style->colorize_scrollbar || clearlooks_style->has_scrollbar_color) { + scrollbar.has_color = TRUE; } + + scrollbar.horizontal = DETAIL ("hscrollbar"); - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); - } - else if (DETAIL ("menu") && widget->parent && - GDK_IS_WINDOW (widget->parent->window)) - { - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - - r.bordergc = clearlooks_style->border_gc[CL_BORDER_UPPER]; - r.topleft = style->light_gc[state_type]; - r.bottomright = clearlooks_style->shade_gc[1]; - - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); + stepper.stepper = clearlooks_scrollbar_get_stepper (widget, &this_rectangle); - return; + STYLE_FUNCTION(draw_scrollbar_stepper) (cr, colors, ¶ms, &scrollbar, &stepper, + x, y, width, height); } - else if (DETAIL ("bar") && widget && GTK_IS_PROGRESS_BAR (widget)) + else if (DETAIL ("toolbar") || DETAIL ("handlebox_bin") || DETAIL ("dockitem_bin")) { - GdkColor upper_color = *clearlooks_get_spot_color (CLEARLOOKS_RC_STYLE (style->rc_style)), - lower_color, - prev_foreground; - gboolean activity_mode = GTK_PROGRESS (widget)->activity_mode; - -#ifdef HAVE_ANIMATION - if (!activity_mode && gtk_progress_bar_get_fraction (widget) != 1.0 && - !cl_progressbar_known((gconstpointer)widget)) - { - cl_progressbar_add ((gpointer)widget); - } -#endif - cl_progressbar_fill (window, widget, style, style->black_gc, - x, y, width, height, -#ifdef HAVE_ANIMATION - activity_mode ? 0 : pboffset, -#else - 0, -#endif - area); - - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - - r.bordergc = clearlooks_style->spot3_gc; - r.topleft = clearlooks_style->spot2_gc; - - prev_foreground = cl_gc_set_fg_color_shade (clearlooks_style->spot2_gc, - style->colormap, - &clearlooks_style->spot2, - 1.2); + WidgetParameters params; + ToolbarParameters toolbar; - cl_rectangle_set_clip_rectangle (&r, area); - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - cl_rectangle_reset_clip_rectangle (&r); - - gdk_gc_set_foreground (clearlooks_style->spot2_gc, &prev_foreground); - } + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + clearlooks_set_toolbar_parameters (&toolbar, widget, window, x, y); - else if ( widget && (DETAIL ("menubar") || DETAIL ("toolbar") || DETAIL ("dockitem_bin") || DETAIL ("handlebox_bin")) && shadow_type != GTK_SHADOW_NONE) /* Toolbars and menus */ + toolbar.style = clearlooks_style->toolbarstyle; + + /* Only draw the shadows on horizontal toolbars */ + if (shadow_type != GTK_SHADOW_NONE && height < 2*width ) + STYLE_FUNCTION(draw_toolbar) (cr, colors, ¶ms, &toolbar, x, y, width, height); + } + else if (DETAIL ("trough")) { - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], area); - } + + } + else if (DETAIL ("menu")) + { + WidgetParameters params; - gtk_style_apply_default_background (style, window, - widget && !GTK_WIDGET_NO_WINDOW (widget), - state_type, area, x, y, width, height); - - /* we only want the borders on horizontal toolbars */ - if ( DETAIL ("menubar") || height < 2*width ) { - if (!DETAIL ("menubar")) - gdk_draw_line (window, clearlooks_style->shade_gc[0], - x, y, x + width, y); /* top */ - - gdk_draw_line (window, clearlooks_style->shade_gc[3], - x, y + height - 1, x + width, y + height - 1); /* bottom */ - } + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - if (area) - { - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL); - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], NULL); - } + STYLE_FUNCTION(draw_menu_frame) (cr, colors, ¶ms, x, y, width, height); + } + else if (DETAIL ("hseparator") || DETAIL ("vseparator")) + { + gchar *new_detail = detail; + /* Draw a normal separator, we just use this because it gives more control + * over sizing (currently). */ + + /* This isn't nice ... but it seems like the best cleanest way to me right now. + * It will get slightly nicer in the future hopefully. */ + if (GE_IS_MENU_ITEM (widget)) + new_detail = "menuitem"; + + if (DETAIL ("hseparator")) { + gtk_paint_hline (style, window, state_type, area, widget, new_detail, + x, x + width - 1, y + height/2); + } else + gtk_paint_vline (style, window, state_type, area, widget, new_detail, + y, y + height - 1, x + width/2); } else { - parent_class->draw_box (style, window, state_type, shadow_type, area, + clearlooks_parent_class->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); } + + cairo_destroy (cr); } -/**************************************************************************/ - static void -ensure_check_pixmaps (GtkStyle *style, - GtkStateType state, - GdkScreen *screen, - gboolean treeview) +clearlooks_style_draw_slider (DRAW_ARGS, GtkOrientation orientation) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - ClearlooksRcStyle *clearlooks_rc = CLEARLOOKS_RC_STYLE (style->rc_style); - GdkPixbuf *check, *base, *inconsistent, *composite; - GdkColor *spot_color = clearlooks_get_spot_color (clearlooks_rc); - - if (clearlooks_style->check_pixmap_nonactive[state] != NULL) - return; - - if (state == GTK_STATE_ACTIVE || state == GTK_STATE_SELECTED) { - check = generate_bit (check_alpha, &style->text[GTK_STATE_NORMAL], 1.0); - inconsistent = generate_bit (check_inconsistent_alpha, &style->text[GTK_STATE_NORMAL], 1.0); - } else { - check = generate_bit (check_alpha, &style->text[state], 1.0); - inconsistent = generate_bit (check_inconsistent_alpha, &style->text[state], 1.0); - } - - if (state == GTK_STATE_ACTIVE && !treeview) - base = generate_bit (check_base_alpha, &style->bg[state], 1.0); - else - base = generate_bit (check_base_alpha, &style->base[GTK_STATE_NORMAL], 1.0); - - if (treeview) - composite = generate_bit (NULL, &clearlooks_style->shade[6], 1.0); - else - composite = generate_bit (NULL, &clearlooks_style->shade[5], 1.0); - - gdk_pixbuf_composite (base, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); + const ClearlooksColors *colors; + cairo_t *cr; - clearlooks_style->check_pixmap_nonactive[state] = - pixbuf_to_pixmap (style, composite, screen); + cr = ge_gdk_drawable_to_cairo (window, area); + colors = &clearlooks_style->colors; + + CHECK_ARGS + SANITIZE_SIZE - gdk_pixbuf_composite (check, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); + if (DETAIL ("hscale") || DETAIL ("vscale")) + { + WidgetParameters params; + SliderParameters slider; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + slider.horizontal = (orientation == GTK_ORIENTATION_HORIZONTAL); + slider.lower = FALSE; + slider.fill_level = FALSE; + + if (clearlooks_style->style == CL_STYLE_GLOSSY) /* XXX! */ + params.corners = CR_CORNER_ALL; + + STYLE_FUNCTION(draw_slider_button) (cr, &clearlooks_style->colors, + ¶ms, &slider, + x, y, width, height); + } + else if (DETAIL ("slider")) + { + WidgetParameters params; + ScrollBarParameters scrollbar; - clearlooks_style->check_pixmap_active[state] = - pixbuf_to_pixmap (style, composite, screen); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + params.corners = CR_CORNER_NONE; - g_object_unref (composite); + scrollbar.has_color = FALSE; + scrollbar.horizontal = (orientation == GTK_ORIENTATION_HORIZONTAL); + scrollbar.junction = clearlooks_scrollbar_get_junction (widget); - composite = generate_bit (NULL, &clearlooks_style->shade[6], 1.0); + if (clearlooks_style->colorize_scrollbar) { + scrollbar.color = colors->spot[1]; + scrollbar.has_color = TRUE; + } - gdk_pixbuf_composite (base, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - - gdk_pixbuf_composite (inconsistent, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); + /* Set scrollbar color */ + if (clearlooks_style->has_scrollbar_color) + { + ge_gdk_color_to_cairo (&clearlooks_style->scrollbar_color, &scrollbar.color); + scrollbar.has_color = TRUE; + } - clearlooks_style->check_pixmap_inconsistent[state] = - pixbuf_to_pixmap (style, composite, screen); + if ((clearlooks_style->style == CL_STYLE_GLOSSY || clearlooks_style->style == CL_STYLE_GUMMY) + && !scrollbar.has_color) + scrollbar.color = colors->bg[0]; + + STYLE_FUNCTION(draw_scrollbar_slider) (cr, colors, ¶ms, &scrollbar, + x, y, width, height); + } + else + { + clearlooks_parent_class->draw_slider (style, window, state_type, shadow_type, area, + widget, detail, x, y, width, height, orientation); + } - g_object_unref (composite); - g_object_unref (base); - g_object_unref (check); - g_object_unref (inconsistent); + cairo_destroy (cr); } static void -draw_check (DRAW_ARGS) +clearlooks_style_draw_option (DRAW_ARGS) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkGC *gc = style->base_gc[state_type]; - GdkPixmap *pixmap; - gboolean treeview; - - if (DETAIL ("check")) /* Menu item */ - { - parent_class->draw_check (style, window, state_type, shadow_type, area, - widget, detail, x, y, width, height); - return; - } - - treeview = widget && GTK_IS_TREE_VIEW(widget); - ensure_check_pixmaps (style, state_type, gtk_widget_get_screen (widget), treeview); - - if (area) - gdk_gc_set_clip_rectangle (gc, area); - - if (shadow_type == GTK_SHADOW_IN) - pixmap = clearlooks_style->check_pixmap_active[state_type]; - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - pixmap = clearlooks_style->check_pixmap_inconsistent[state_type]; - else - pixmap = clearlooks_style->check_pixmap_nonactive[state_type]; - - x += (width - CHECK_SIZE)/2; - y += (height - CHECK_SIZE)/2; + const ClearlooksColors *colors; + WidgetParameters params; + CheckboxParameters checkbox; + cairo_t *cr; + + CHECK_ARGS + SANITIZE_SIZE - gdk_draw_drawable (window, gc, pixmap, 0, 0, x, y, CHECK_SIZE, CHECK_SIZE); + cr = ge_gdk_drawable_to_cairo (window, area); + colors = &clearlooks_style->colors; - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); + checkbox.shadow_type = shadow_type; + checkbox.in_menu = (widget && GTK_IS_MENU(widget->parent)); + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + STYLE_FUNCTION(draw_radiobutton) (cr, colors, ¶ms, &checkbox, x, y, width, height); + + cairo_destroy (cr); } -/**************************************************************************/ static void -draw_slider (DRAW_ARGS, GtkOrientation orientation) +clearlooks_style_draw_check (DRAW_ARGS) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkGC *shade_gc = clearlooks_style->shade_gc[4]; - GdkGC *white_gc = clearlooks_style->shade_gc[0]; - int x1, y1; + WidgetParameters params; + CheckboxParameters checkbox; + cairo_t *cr; -#if DEBUG - printf("draw_slider: %s %d %d %d %d\n", detail, x, y, width, height); -#endif + CHECK_ARGS + SANITIZE_SIZE - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - sanitize_size (window, &width, &height); + cr = ge_gdk_drawable_to_cairo (window, area); + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + params.corners = CR_CORNER_ALL; + + checkbox.shadow_type = shadow_type; + checkbox.in_cell = DETAIL("cellcheck"); - gtk_paint_box (style, window, state_type, shadow_type, - area, widget, detail, x, y, width, height); + checkbox.in_menu = (widget && widget->parent && GTK_IS_MENU(widget->parent)); - if ((orientation == GTK_ORIENTATION_VERTICAL && height < 20) || - (orientation == GTK_ORIENTATION_HORIZONTAL && width < 20)) - return; + STYLE_FUNCTION(draw_checkbox) (cr, &clearlooks_style->colors, ¶ms, &checkbox, + x, y, width, height); - if (detail && strcmp ("slider", detail) == 0) - { - if (area) - { - gdk_gc_set_clip_rectangle (shade_gc, area); - gdk_gc_set_clip_rectangle (white_gc, area); - } - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - x1 = x + width / 2 - 4; - y1 = y + (height - 6) / 2; - gdk_draw_line (window, shade_gc, x1, y1, x1, y1 + 6); - gdk_draw_line (window, white_gc, x1 + 1, y1, x1 + 1, y1 + 6); - gdk_draw_line (window, shade_gc, x1 + 3, y1, x1 + 3, y1 + 6); - gdk_draw_line (window, white_gc, x1 + 3 + 1, y1, x1 + 3 + 1, y1 + 6); - gdk_draw_line (window, shade_gc, x1 + 3*2, y1, x1 + 3*2, y1 + 6); - gdk_draw_line (window, white_gc, x1 + 3*2 + 1, y1, x1 + 3*2 + 1, y1 + 6); - } - else - { - x1 = x + (width - 6) / 2; - y1 = y + height / 2 - 4; - gdk_draw_line (window, shade_gc, x1 + 6, y1, x1, y1); - gdk_draw_line (window, white_gc, x1 + 6, y1 + 1, x1, y1 + 1); - gdk_draw_line (window, shade_gc, x1 + 6, y1 + 3, x1, y1 + 3); - gdk_draw_line (window, white_gc, x1 + 6, y1 + 3 + 1, x1, y1 + 3 + 1); - gdk_draw_line (window, shade_gc, x1 + 6, y1 + 3*2, x1, y1 + 3*2); - gdk_draw_line (window, white_gc, x1 + 6, y1 + 3*2 + 1, x1, y1 + 3*2 + 1); - } - if (area) - { - gdk_gc_set_clip_rectangle (shade_gc, NULL); - gdk_gc_set_clip_rectangle (white_gc, NULL); - } - } - else if (detail && (strcmp ("hscale", detail) == 0 || strcmp ("vscale", detail) == 0)) - { - if (area) - { - gdk_gc_set_clip_rectangle (shade_gc, area); - gdk_gc_set_clip_rectangle (white_gc, area); - } - - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - x1 = x + width / 2 - 3; - y1 = y + (height - 7) / 2; - gdk_draw_line (window, shade_gc, x1 + 0, y1 + 5, x1 + 0, y1 + 1); - gdk_draw_line (window, white_gc, x1 + 1, y1 + 5, x1 + 1, y1 + 1); - gdk_draw_line (window, shade_gc, x1 + 3, y1 + 5, x1 + 3, y1 + 1); - gdk_draw_line (window, white_gc, x1 + 4, y1 + 5, x1 + 4, y1 + 1); - gdk_draw_line (window, shade_gc, x1 + 6, y1 + 5, x1 + 6, y1 + 1); - gdk_draw_line (window, white_gc, x1 + 7, y1 + 5, x1 + 7, y1 + 1); - } - else - { - x1 = x + (width - 7) / 2; - y1 = y + height / 2 - 3; - gdk_draw_line (window, shade_gc, x1 + 5, y1 + 0, x1 + 1, y1 + 0); - gdk_draw_line (window, white_gc, x1 + 5, y1 + 1, x1 + 1, y1 + 1); - gdk_draw_line (window, shade_gc, x1 + 5, y1 + 3, x1 + 1, y1 + 3); - gdk_draw_line (window, white_gc, x1 + 5, y1 + 4, x1 + 1, y1 + 4); - gdk_draw_line (window, shade_gc, x1 + 5, y1 + 6, x1 + 1, y1 + 6); - gdk_draw_line (window, white_gc, x1 + 5, y1 + 7, x1 + 1, y1 + 7); - } - if (area) - { - gdk_gc_set_clip_rectangle (shade_gc, NULL); - gdk_gc_set_clip_rectangle (white_gc, NULL); - } - } + cairo_destroy (cr); } -/**************************************************************************/ static void -ensure_radio_pixmaps (GtkStyle *style, - GtkStateType state, - GdkScreen *screen) +clearlooks_style_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint y1, + gint y2, + gint x) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - ClearlooksRcStyle *clearlooks_rc = CLEARLOOKS_RC_STYLE (style->rc_style); - GdkPixbuf *dot, *circle, *outline, *inconsistent, *composite; - GdkColor *spot_color = clearlooks_get_spot_color (clearlooks_rc); - GdkColor *composite_color; - - if (clearlooks_style->radio_pixmap_nonactive[state] != NULL) - return; - - if (state == GTK_STATE_ACTIVE || state == GTK_STATE_SELECTED) { - dot = colorize_bit (dot_intensity, dot_alpha, &style->text[GTK_STATE_NORMAL]); - inconsistent = generate_bit (inconsistent_alpha, &style->text[GTK_STATE_NORMAL], 1.0); - } else { - dot = colorize_bit (dot_intensity, dot_alpha, &style->text[state]); - inconsistent = generate_bit (inconsistent_alpha, &style->text[state], 1.0); - } - - outline = generate_bit (outline_alpha, &clearlooks_style->shade[5], 1.0); - - if (clearlooks_style->radio_pixmap_mask == NULL) - { - gdk_pixbuf_render_pixmap_and_mask (outline, - NULL, - &clearlooks_style->radio_pixmap_mask, - 1); - } - - if (state == GTK_STATE_ACTIVE) - { - composite_color = &style->bg[GTK_STATE_PRELIGHT]; - circle = generate_bit (circle_alpha, &style->bg[state], 1.0); - } - else - { - composite_color = &style->bg[state]; - circle = generate_bit (circle_alpha, &style->base[GTK_STATE_NORMAL], 1.0); - } - - composite = generate_bit (NULL, composite_color, 1.0); - - gdk_pixbuf_composite (outline, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - - gdk_pixbuf_composite (circle, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - - clearlooks_style->radio_pixmap_nonactive[state] = - pixbuf_to_pixmap (style, composite, screen); - - gdk_pixbuf_composite (dot, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - - clearlooks_style->radio_pixmap_active[state] = - pixbuf_to_pixmap (style, composite, screen); - - g_object_unref (composite); - - composite = generate_bit (NULL, composite_color,1.0); - - gdk_pixbuf_composite (outline, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - gdk_pixbuf_composite (circle, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - gdk_pixbuf_composite (inconsistent, composite, - 0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0, - 1.0, 1.0, GDK_INTERP_NEAREST, 255); - - clearlooks_style->radio_pixmap_inconsistent[state] = - pixbuf_to_pixmap (style, composite, screen); + const ClearlooksColors *colors; + SeparatorParameters separator = { FALSE }; + cairo_t *cr; + + CHECK_ARGS + + colors = &clearlooks_style->colors; + + cr = ge_gdk_drawable_to_cairo (window, area); + + /* There is no such thing as a vertical menu separator + * (and even if, a normal one should be better on menu bars) */ + STYLE_FUNCTION(draw_separator) (cr, colors, NULL, &separator, + x, y1, 2, y2-y1+1); - g_object_unref (composite); - g_object_unref (circle); - g_object_unref (dot); - g_object_unref (inconsistent); - g_object_unref (outline); + cairo_destroy (cr); } static void -draw_option (DRAW_ARGS) +clearlooks_style_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x1, + gint x2, + gint y) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkGC *gc = style->base_gc[state_type]; - GdkPixmap *pixmap; - - if (DETAIL ("option")) /* Menu item */ - { - parent_class->draw_option (style, window, state_type, shadow_type, - area, widget, detail, x, y, width, height); - return; - } - - ensure_radio_pixmaps (style, state_type, gtk_widget_get_screen (widget)); + const ClearlooksColors *colors; + cairo_t *cr; + SeparatorParameters separator; + + CHECK_ARGS + + colors = &clearlooks_style->colors; + + cr = ge_gdk_drawable_to_cairo (window, area); - if (area) - gdk_gc_set_clip_rectangle (gc, area); + separator.horizontal = TRUE; - if (shadow_type == GTK_SHADOW_IN) - pixmap = clearlooks_style->radio_pixmap_active[state_type]; - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - pixmap = clearlooks_style->radio_pixmap_inconsistent[state_type]; + if (!DETAIL ("menuitem")) + STYLE_FUNCTION(draw_separator) (cr, colors, NULL, &separator, + x1, y, x2-x1+1, 2); else - pixmap = clearlooks_style->radio_pixmap_nonactive[state_type]; + STYLE_FUNCTION(draw_menu_item_separator) (cr, colors, NULL, &separator, + x1, y, x2-x1+1, 2); - x += (width - RADIO_SIZE)/2; - y += (height - RADIO_SIZE)/2; - -#ifndef GTKOSX - gdk_gc_set_clip_mask (gc, clearlooks_style->radio_pixmap_mask); - gdk_gc_set_clip_origin (gc, x, y); -#endif - - gdk_draw_drawable (window, gc, pixmap, 0, 0, x, y, - RADIO_SIZE, RADIO_SIZE); - -#ifndef GTKOSX - gdk_gc_set_clip_origin (gc, 0, 0); - gdk_gc_set_clip_mask (gc, NULL); -#endif - - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); + cairo_destroy (cr); } -/**************************************************************************/ - static void -draw_shadow_gap (DRAW_ARGS, +clearlooks_style_draw_shadow_gap (DRAW_ARGS, GtkPositionType gap_side, gint gap_x, gint gap_width) { - /* I need to improve this function. */ ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - CLRectangle r; - GdkRegion *area_region = NULL, - *gap_region = NULL; + const ClearlooksColors *colors; + cairo_t *cr; -#if DEBUG - printf("draw_shadow_gap: %s %d %d %d %d\n", detail, x, y, width, height); -#endif + CHECK_ARGS + SANITIZE_SIZE - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); + cr = ge_gdk_drawable_to_cairo (window, area); + colors = &clearlooks_style->colors; - sanitize_size (window, &width, &height); - - cl_rectangle_reset (&r, style); - cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE, - CL_CORNER_NONE, CL_CORNER_NONE); - - if (area) + if (DETAIL ("frame")) { - area_region = gdk_region_rectangle (area); - - switch (gap_side) - { - case GTK_POS_TOP: - { - GdkRectangle rect = { x+gap_x, y, gap_width, 2 }; - gap_region = gdk_region_rectangle (&rect); - break; - } - case GTK_POS_BOTTOM: - { - GdkRectangle rect = { x+gap_x, y+height-2, gap_width, 2 }; - gap_region = gdk_region_rectangle (&rect); - break; - } - case GTK_POS_LEFT: - { - GdkRectangle rect = { x, y+gap_x, 2, gap_width }; - gap_region = gdk_region_rectangle (&rect); - break; - } - case GTK_POS_RIGHT: - { - GdkRectangle rect = { x+width-2, y+gap_x, 2, gap_width }; - gap_region = gdk_region_rectangle (&rect); - break; - } - } + WidgetParameters params; + FrameParameters frame; - gdk_region_subtract (area_region, gap_region); - } - - if (shadow_type == GTK_SHADOW_ETCHED_IN || - shadow_type == GTK_SHADOW_ETCHED_OUT) - { - GdkGC *a; - GdkGC *b; - - if (shadow_type == GTK_SHADOW_ETCHED_IN) - { - a = style->light_gc[state_type]; - b = clearlooks_style->shade_gc[3]; - } - else - { - a = clearlooks_style->shade_gc[3]; - b = style->light_gc[state_type]; - } + frame.shadow = shadow_type; + frame.gap_side = gap_side; + frame.gap_x = gap_x; + frame.gap_width = gap_width; + frame.border = &colors->shade[5]; - gdk_gc_set_clip_region (a, area_region); - gdk_gc_set_clip_region (b, area_region); - - r.bordergc = a; - cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r); + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); - r.bordergc = b; - cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r); - - gdk_gc_set_clip_region (a, NULL); - gdk_gc_set_clip_region (b, NULL); + params.corners = CR_CORNER_ALL; + + STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame, + x, y, width, height); } - else if (shadow_type == GTK_SHADOW_IN || shadow_type == GTK_SHADOW_OUT) + else { - r.topleft = (shadow_type == GTK_SHADOW_OUT) ? style->light_gc[state_type] : clearlooks_style->shade_gc[1]; - r.bottomright = (shadow_type == GTK_SHADOW_OUT) ? clearlooks_style->shade_gc[1] : style->light_gc[state_type]; - r.bordergc = clearlooks_style->shade_gc[5]; - - gdk_gc_set_clip_region (r.bordergc, area_region); - gdk_gc_set_clip_region (r.topleft, area_region); - gdk_gc_set_clip_region (r.bottomright, area_region); - - cl_draw_rectangle (window, widget, style, x, y, width, height, &r); - - cl_draw_shadow (window, widget, style, x, y, width, height, &r); - - gdk_gc_set_clip_region (r.bordergc, NULL); - gdk_gc_set_clip_region (r.topleft, NULL); - gdk_gc_set_clip_region (r.bottomright, NULL); + clearlooks_parent_class->draw_shadow_gap (style, window, state_type, shadow_type, area, + widget, detail, x, y, width, height, + gap_side, gap_x, gap_width); } - - if (area_region) - gdk_region_destroy (area_region); + + cairo_destroy (cr); } -/**************************************************************************/ static void -draw_hline (GtkStyle *style, - GdkWindow *window, - GtkStateType state_type, - GdkRectangle *area, - GtkWidget *widget, - const gchar *detail, - gint x1, - gint x2, - gint y) +clearlooks_style_draw_resize_grip (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GdkWindowEdge edge, + gint x, + gint y, + gint width, + gint height) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + cairo_t *cr; + WidgetParameters params; + ResizeGripParameters grip; -#if DEBUG - printf("draw_hline\n"); -#endif + CHECK_ARGS + SANITIZE_SIZE + + grip.edge = (ClearlooksWindowEdge)edge; - g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); - - if (area) - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], area); - - if (detail && !strcmp (detail, "label")) - { - if (state_type == GTK_STATE_INSENSITIVE) - gdk_draw_line (window, style->light_gc[state_type], x1 + 1, y + 1, x2 + 1, y + 1); - - gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y); - } - else - { - gdk_draw_line (window, clearlooks_style->shade_gc[2], x1, y, x2, y); - - /* if (DETAIL ("menuitem")) */ - gdk_draw_line (window, clearlooks_style->shade_gc[0], x1, y+1, x2, y+1); - } - - if (area) - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], NULL); + + cr = ge_gdk_drawable_to_cairo (window, area); + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + STYLE_FUNCTION(draw_resize_grip) (cr, colors, ¶ms, &grip, + x, y, width, height); + + cairo_destroy (cr); } -/**************************************************************************/ static void -draw_vline (GtkStyle *style, - GdkWindow *window, - GtkStateType state_type, - GdkRectangle *area, - GtkWidget *widget, - const gchar *detail, - gint y1, - gint y2, - gint x) +clearlooks_style_draw_tab (DRAW_ARGS) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - gint thickness_light; - gint thickness_dark; + ClearlooksColors *colors = &clearlooks_style->colors; + WidgetParameters params; + ArrowParameters arrow; + cairo_t *cr; -#if DEBUG - printf("draw_vline\n"); -#endif - - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - thickness_light = style->xthickness / 2; - thickness_dark = style->xthickness - thickness_light; - - if (area) - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], area); + CHECK_ARGS + SANITIZE_SIZE - gdk_draw_line (window, clearlooks_style->shade_gc[2], x, y1, x, y2 - 1); - gdk_draw_line (window, clearlooks_style->shade_gc[0], x+1, y1, x+1, y2 - 1); - - if (area) - gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], NULL); + cr = ge_gdk_drawable_to_cairo (window, area); + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + arrow.type = CL_ARROW_COMBO; + arrow.direction = CL_DIRECTION_DOWN; + + STYLE_FUNCTION(draw_arrow) (cr, colors, ¶ms, &arrow, x, y, width, height); + + cairo_destroy (cr); } -/**************************************************************************/ static void -draw_focus (GtkStyle *style, - GdkWindow *window, - GtkStateType state_type, - GdkRectangle *area, - GtkWidget *widget, - const gchar *detail, - gint x, - gint y, - gint width, - gint height) +clearlooks_style_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkPoint points[5]; - GdkGC *gc; - gboolean free_dash_list = FALSE; - gint line_width = 1; - gchar *dash_list = "\1\1"; - gint dash_len; + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + WidgetParameters params; + ArrowParameters arrow; + cairo_t *cr = ge_gdk_drawable_to_cairo (window, area); -#if DEBUG - printf("draw_focus: %s %d %d %d %d\n", detail, x, y, width, height); -#endif - - gc = clearlooks_style->shade_gc[6]; - - if (widget) - { - gtk_widget_style_get (widget, - "focus-line-width", &line_width, - "focus-line-pattern", (gchar *)&dash_list, - NULL); - - free_dash_list = TRUE; + CHECK_ARGS + SANITIZE_SIZE + + if (arrow_type == GTK_ARROW_NONE) { + cairo_destroy (cr); + return; } + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + arrow.type = CL_ARROW_NORMAL; + arrow.direction = (ClearlooksDirection)arrow_type; - sanitize_size (window, &width, &height); - - if (area) - gdk_gc_set_clip_rectangle (gc, area); - - gdk_gc_set_line_attributes (gc, line_width, - dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID, - GDK_CAP_BUTT, GDK_JOIN_MITER); - - - if (detail && !strcmp (detail, "add-mode")) + if (ge_is_combo_box (widget, FALSE) && !ge_is_combo_box_entry (widget)) { - if (free_dash_list) - g_free (dash_list); - - dash_list = "\4\4"; - free_dash_list = FALSE; + arrow.type = CL_ARROW_COMBO; } - points[0].x = x + line_width / 2; - points[0].y = y + line_width / 2; - points[1].x = x + width - line_width + line_width / 2; - points[1].y = y + line_width / 2; - points[2].x = x + width - line_width + line_width / 2; - points[2].y = y + height - line_width + line_width / 2; - points[3].x = x + line_width / 2; - points[3].y = y + height - line_width + line_width / 2; - points[4] = points[0]; - - if (!dash_list[0]) + /* I have no idea why, but the arrow of GtkCombo is larger than in other places. + * Subtracting 3 seems to fix this. */ + if (widget && widget->parent && GE_IS_COMBO (widget->parent->parent)) { - gdk_draw_lines (window, gc, points, 5); - } - else - { - dash_len = strlen (dash_list); - - if (dash_list[0]) - gdk_gc_set_dashes (gc, 0, dash_list, dash_len); - - gdk_draw_lines (window, gc, points, 3); - - points[2].x += 1; - - if (dash_list[0]) - { - gint dash_pixels = 0; - gint i; - - /* Adjust the dash offset for the bottom and left so we - * match up at the upper left. - */ - for (i = 0; i < dash_len; i++) - dash_pixels += dash_list[i]; - - if (dash_len % 2 == 1) - dash_pixels *= 2; - - gdk_gc_set_dashes (gc, - dash_pixels - (width + height - 2 * line_width) % dash_pixels, - dash_list, dash_len); - } - - gdk_draw_lines (window, gc, points + 2, 3); + if (params.ltr) + x += 1; + else + x += 2; + width -= 3; } - gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); + STYLE_FUNCTION(draw_arrow) (cr, colors, ¶ms, &arrow, x, y, width, height); - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); - - if (free_dash_list) - g_free (dash_list); + cairo_destroy (cr); } static void -draw_layout(GtkStyle * style, - GdkWindow * window, - GtkStateType state_type, - gboolean use_text, - GdkRectangle * area, - GtkWidget * widget, - const gchar * detail, gint x, gint y, PangoLayout * layout) +clearlooks_style_init_from_rc (GtkStyle * style, + GtkRcStyle * rc_style) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - g_return_if_fail(GTK_IS_STYLE (style)); - g_return_if_fail(window != NULL); - - parent_class->draw_layout(style, window, state_type, use_text, - area, widget, detail, x, y, layout); - + clearlooks_parent_class->init_from_rc (style, rc_style); -} + g_assert ((CLEARLOOKS_RC_STYLE (rc_style)->style >= 0) && (CLEARLOOKS_RC_STYLE (rc_style)->style < CL_NUM_STYLES)); + clearlooks_style->style = CLEARLOOKS_RC_STYLE (rc_style)->style; + + clearlooks_style->menubarstyle = CLEARLOOKS_RC_STYLE (rc_style)->menubarstyle; + clearlooks_style->toolbarstyle = CLEARLOOKS_RC_STYLE (rc_style)->toolbarstyle; + clearlooks_style->has_scrollbar_color = CLEARLOOKS_RC_STYLE (rc_style)->flags & CL_FLAG_SCROLLBAR_COLOR; + clearlooks_style->colorize_scrollbar = CLEARLOOKS_RC_STYLE (rc_style)->colorize_scrollbar; + clearlooks_style->animation = CLEARLOOKS_RC_STYLE (rc_style)->animation; + clearlooks_style->radius = CLAMP (CLEARLOOKS_RC_STYLE (rc_style)->radius, 0.0, 10.0); -/**************************************************************************/ -static void -draw_resize_grip (GtkStyle *style, - GdkWindow *window, - GtkStateType state_type, - GdkRectangle *area, - GtkWidget *widget, - const gchar *detail, - GdkWindowEdge edge, - gint x, - gint y, - gint width, - gint height) -{ - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - g_return_if_fail (GTK_IS_STYLE (style)); - g_return_if_fail (window != NULL); - - if (area) - { - gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); - gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); - } - - switch (edge) - { - case GDK_WINDOW_EDGE_NORTH_WEST: - /* make it square */ - if (width < height) - { - height = width; - } - else if (height < width) - { - width = height; - } - break; - case GDK_WINDOW_EDGE_NORTH: - if (width < height) - { - height = width; - } - break; - case GDK_WINDOW_EDGE_NORTH_EAST: - /* make it square, aligning to top right */ - if (width < height) - { - height = width; - } - else if (height < width) - { - x += (width - height); - width = height; - } - break; - case GDK_WINDOW_EDGE_WEST: - if (height < width) - { - width = height; - } - break; - case GDK_WINDOW_EDGE_EAST: - /* aligning to right */ - if (height < width) - { - x += (width - height); - width = height; - } - break; - case GDK_WINDOW_EDGE_SOUTH_WEST: - /* make it square, aligning to bottom left */ - if (width < height) - { - y += (height - width); - height = width; - } - else if (height < width) - { - width = height; - } - break; - case GDK_WINDOW_EDGE_SOUTH: - /* align to bottom */ - if (width < height) - { - y += (height - width); - height = width; - } - break; - case GDK_WINDOW_EDGE_SOUTH_EAST: - /* make it square, aligning to bottom right */ - if (width < height) - { - y += (height - width); - height = width; - } - else if (height < width) - { - x += (width - height); - width = height; - } - break; - default: - g_assert_not_reached (); - } - - /* Clear background */ - gtk_style_apply_default_background (style, window, FALSE, - state_type, area, - x, y, width, height); - - switch (edge) - { - case GDK_WINDOW_EDGE_WEST: - case GDK_WINDOW_EDGE_EAST: - { - gint xi; - - xi = x; - - while (xi < x + width) - { - gdk_draw_line (window, - style->light_gc[state_type], - xi, y, - xi, y + height); - - xi++; - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - xi, y, - xi, y + height); - - xi += 2; - } - } - break; - case GDK_WINDOW_EDGE_NORTH: - case GDK_WINDOW_EDGE_SOUTH: - { - gint yi; - - yi = y; - - while (yi < y + height) - { - gdk_draw_line (window, - style->light_gc[state_type], - x, yi, - x + width, yi); - - yi++; - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - x, yi, - x + width, yi); - - yi+= 2; - } - } - break; - case GDK_WINDOW_EDGE_NORTH_WEST: - { - gint xi, yi; - - xi = x + width; - yi = y + height; - - while (xi > x + 3) - { - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - xi, y, - x, yi); - - --xi; - --yi; - - gdk_draw_line (window, - style->light_gc[state_type], - xi, y, - x, yi); - - xi -= 3; - yi -= 3; - - } - } - break; - case GDK_WINDOW_EDGE_NORTH_EAST: - { - gint xi, yi; - - xi = x; - yi = y + height; - - while (xi < (x + width - 3)) - { - gdk_draw_line (window, - style->light_gc[state_type], - xi, y, - x + width, yi); - - ++xi; - --yi; - - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - xi, y, - x + width, yi); - - xi += 3; - yi -= 3; - } - } - break; - case GDK_WINDOW_EDGE_SOUTH_WEST: - { - gint xi, yi; - - xi = x + width; - yi = y; - - while (xi > x + 3) - { - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - x, yi, - xi, y + height); - - --xi; - ++yi; - - gdk_draw_line (window, - style->light_gc[state_type], - x, yi, - xi, y + height); - - xi -= 3; - yi += 3; - - } - } - break; - - case GDK_WINDOW_EDGE_SOUTH_EAST: - { - gint xi, yi; - - xi = x; - yi = y; - - while (xi < (x + width - 3)) - { - gdk_draw_line (window, - style->light_gc[state_type], - xi, y + height, - x + width, yi); - - ++xi; - ++yi; - - gdk_draw_line (window, - clearlooks_style->shade_gc[4], - xi, y + height, - x + width, yi); - - xi += 3; - yi += 3; - } - } - break; - default: - g_assert_not_reached (); - break; - } - - if (area) - { - gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); - gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); - gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); - } + if (clearlooks_style->has_scrollbar_color) + clearlooks_style->scrollbar_color = CLEARLOOKS_RC_STYLE (rc_style)->scrollbar_color; } -/**************************************************************************/ - static void -clearlooks_style_init_from_rc (GtkStyle * style, - GtkRcStyle * rc_style) +clearlooks_style_realize (GtkStyle * style) { ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - GdkColor *spot_color; - double shades[] = {1.065, 0.93, 0.896, 0.85, 0.768, 0.665, 0.4, 0.205}; - int i; + double shades[] = {1.15, 0.95, 0.896, 0.82, 0.7, 0.665, 0.475, 0.45, 0.4}; + CairoColor spot_color; + CairoColor bg_normal; double contrast; + int i; - parent_class->init_from_rc (style, rc_style); - - contrast = CLEARLOOKS_RC_STYLE (rc_style)->contrast; - - clearlooks_style->sunkenmenubar = CLEARLOOKS_RC_STYLE (rc_style)->sunkenmenubar; - clearlooks_style->progressbarstyle = CLEARLOOKS_RC_STYLE (rc_style)->progressbarstyle; - clearlooks_style->menubarstyle = CLEARLOOKS_RC_STYLE (rc_style)->menubarstyle; - clearlooks_style->menuitemstyle = CLEARLOOKS_RC_STYLE (rc_style)->menuitemstyle; - clearlooks_style->listviewitemstyle = CLEARLOOKS_RC_STYLE (rc_style)->listviewitemstyle; + clearlooks_parent_class->realize (style); + + contrast = CLEARLOOKS_RC_STYLE (style->rc_style)->contrast; /* Lighter to darker */ - for (i = 0; i < 8; i++) + ge_gdk_color_to_cairo (&style->bg[GTK_STATE_NORMAL], &bg_normal); + + for (i = 0; i < 9; i++) { - shade (&style->bg[GTK_STATE_NORMAL], &clearlooks_style->shade[i], - (shades[i]-0.7) * contrast + 0.7); + ge_shade_color(&bg_normal, (shades[i]-0.7) * contrast + 0.7, &clearlooks_style->colors.shade[i]); } - spot_color = clearlooks_get_spot_color (CLEARLOOKS_RC_STYLE (rc_style)); + ge_gdk_color_to_cairo (&style->bg[GTK_STATE_SELECTED], &spot_color); - clearlooks_style->spot_color = *spot_color; - shade (&clearlooks_style->spot_color, &clearlooks_style->spot1, 1.42); - shade (&clearlooks_style->spot_color, &clearlooks_style->spot2, 1.05); - shade (&clearlooks_style->spot_color, &clearlooks_style->spot3, 0.65); - - shade (&style->bg[GTK_STATE_NORMAL], &clearlooks_style->border[CL_BORDER_UPPER], 0.5); - shade (&style->bg[GTK_STATE_NORMAL], &clearlooks_style->border[CL_BORDER_LOWER], 0.62); - shade (&style->bg[GTK_STATE_ACTIVE], &clearlooks_style->border[CL_BORDER_UPPER_ACTIVE], 0.5); - shade (&style->bg[GTK_STATE_ACTIVE], &clearlooks_style->border[CL_BORDER_LOWER_ACTIVE], 0.55); -} - -static GdkGC * -realize_color (GtkStyle * style, - GdkColor * color) -{ - GdkGCValues gc_values; - - gdk_colormap_alloc_color (style->colormap, color, FALSE, TRUE); + ge_shade_color(&spot_color, 1.42, &clearlooks_style->colors.spot[0]); + ge_shade_color(&spot_color, 1.05, &clearlooks_style->colors.spot[1]); + ge_shade_color(&spot_color, 0.65, &clearlooks_style->colors.spot[2]); - gc_values.foreground = *color; - - return gtk_gc_get (style->depth, style->colormap, &gc_values, GDK_GC_FOREGROUND); + for (i=0; i<5; i++) + { + ge_gdk_color_to_cairo (&style->fg[i], &clearlooks_style->colors.fg[i]); + ge_gdk_color_to_cairo (&style->bg[i], &clearlooks_style->colors.bg[i]); + ge_gdk_color_to_cairo (&style->base[i], &clearlooks_style->colors.base[i]); + ge_gdk_color_to_cairo (&style->text[i], &clearlooks_style->colors.text[i]); + } } static void -clearlooks_style_realize (GtkStyle * style) +clearlooks_style_draw_focus (GtkStyle *style, GdkWindow *window, GtkStateType state_type, + GdkRectangle *area, GtkWidget *widget, const gchar *detail, + gint x, gint y, gint width, gint height) { - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int i; - - parent_class->realize (style); - - for (i = 0; i < 8; i++) - clearlooks_style->shade_gc[i] = realize_color (style, &clearlooks_style->shade[i]); - - for (i=0; i < CL_BORDER_COUNT; i++) - clearlooks_style->border_gc[i] = realize_color (style, &clearlooks_style->border[i]); - - clearlooks_style->spot1_gc = realize_color (style, &clearlooks_style->spot1); - clearlooks_style->spot2_gc = realize_color (style, &clearlooks_style->spot2); - clearlooks_style->spot3_gc = realize_color (style, &clearlooks_style->spot3); + cairo_t *cr; + gboolean free_dash_list = FALSE; + gint line_width = 1; + gint8 *dash_list = (gint8 *)"\1\1"; - /* set light inset color */ - for (i=0; i<5; i++) + if (widget) { - shade (&style->bg[i], &clearlooks_style->inset_dark[i], 0.93); - gdk_rgb_find_color (style->colormap, &clearlooks_style->inset_dark[i]); + gtk_widget_style_get (widget, + "focus-line-width", &line_width, + "focus-line-pattern", + (gchar *) & dash_list, NULL); - shade (&style->bg[i], &clearlooks_style->inset_light[i], 1.055); - gdk_rgb_find_color (style->colormap, &clearlooks_style->inset_light[i]); + free_dash_list = TRUE; + } - shade (&style->bg[i], &clearlooks_style->listview_bg[i], 1.015); - gdk_rgb_find_color (style->colormap, &clearlooks_style->listview_bg[i]); + if (detail && !strcmp (detail, "add-mode")) + { + if (free_dash_list) + g_free (dash_list); - /* CREATE GRADIENT FOR BUTTONS */ - shade (&style->bg[i], &clearlooks_style->button_g1[i], 1.055); - gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g1[i]); - - shade (&style->bg[i], &clearlooks_style->button_g2[i], 1.005); - gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g2[i]); + dash_list = (gint8 *)"\4\4"; + free_dash_list = FALSE; + } - shade (&style->bg[i], &clearlooks_style->button_g3[i], 0.98); - gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g3[i]); + CHECK_ARGS + SANITIZE_SIZE - shade (&style->bg[i], &clearlooks_style->button_g4[i], 0.91); - gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g4[i]); - } + cr = gdk_cairo_create (window); -} + if (detail && !strcmp (detail, "colorwheel_light")) + cairo_set_source_rgb (cr, 0., 0., 0.); + else if (detail && !strcmp (detail, "colorwheel_dark")) + cairo_set_source_rgb (cr, 1., 1., 1.); + else + ge_cairo_set_gdk_color_with_alpha (cr, &style->fg[state_type], + 0.7); -static void -clearlooks_style_unrealize (GtkStyle * style) -{ - ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); - int i; - - /* We don't free the colors, because we don't know if - * gtk_gc_release() actually freed the GC. FIXME - need - * a way of ref'ing colors explicitely so GtkGC can - * handle things properly. - */ - for (i=0; i < 8; i++) - gtk_gc_release (clearlooks_style->shade_gc[i]); - - gtk_gc_release (clearlooks_style->spot1_gc); - gtk_gc_release (clearlooks_style->spot2_gc); - gtk_gc_release (clearlooks_style->spot3_gc); - - for (i = 0; i < 5; i++) + cairo_set_line_width (cr, line_width); + + if (dash_list[0]) { - if (clearlooks_style->radio_pixmap_nonactive[i] != NULL) - { - g_object_unref (clearlooks_style->radio_pixmap_nonactive[i]); - clearlooks_style->radio_pixmap_nonactive[i] = NULL; - g_object_unref (clearlooks_style->radio_pixmap_active[i]); - clearlooks_style->radio_pixmap_active[i] = NULL; - g_object_unref (clearlooks_style->radio_pixmap_inconsistent[i]); - clearlooks_style->radio_pixmap_inconsistent[i] = NULL; - } - - if (clearlooks_style->check_pixmap_nonactive[i] != NULL) + gint n_dashes = strlen ((gchar *)dash_list); + gdouble *dashes = g_new (gdouble, n_dashes); + gdouble total_length = 0; + gdouble dash_offset; + gint i; + + for (i = 0; i < n_dashes; i++) { - g_object_unref (clearlooks_style->check_pixmap_nonactive[i]); - clearlooks_style->check_pixmap_nonactive[i] = NULL; - g_object_unref (clearlooks_style->check_pixmap_active[i]); - clearlooks_style->check_pixmap_active[i] = NULL; - g_object_unref (clearlooks_style->check_pixmap_inconsistent[i]); - clearlooks_style->check_pixmap_inconsistent[i] = NULL; + dashes[i] = dash_list[i]; + total_length += dash_list[i]; } + + /* The dash offset here aligns the pattern to integer pixels + * by starting the dash at the right side of the left border + * Negative dash offsets in cairo don't work + * (https://bugs.freedesktop.org/show_bug.cgi?id=2729) + */ + dash_offset = -line_width / 2.; + while (dash_offset < 0) + dash_offset += total_length; + + cairo_set_dash (cr, dashes, n_dashes, dash_offset); + g_free (dashes); } - - if (clearlooks_style->radio_pixmap_mask != NULL) - g_object_unref (clearlooks_style->radio_pixmap_mask); - - clearlooks_style->radio_pixmap_mask = NULL; - while (progressbars = g_list_first (progressbars)) - cl_progressbar_remove (progressbars->data); - - if (timer_id != 0) + if (area) { - g_source_remove(timer_id); - timer_id = 0; + gdk_cairo_rectangle (cr, area); + cairo_clip (cr); } - - parent_class->unrealize (style); + + cairo_rectangle (cr, + x + line_width / 2., + y + line_width / 2., + width - line_width, height - line_width); + cairo_stroke (cr); + cairo_destroy (cr); + + if (free_dash_list) + g_free (dash_list); +} + +static void +clearlooks_style_copy (GtkStyle * style, GtkStyle * src) +{ + ClearlooksStyle * cl_style = CLEARLOOKS_STYLE (style); + ClearlooksStyle * cl_src = CLEARLOOKS_STYLE (src); + + cl_style->colors = cl_src->colors; + cl_style->menubarstyle = cl_src->menubarstyle; + cl_style->toolbarstyle = cl_src->toolbarstyle; + cl_style->scrollbar_color = cl_src->scrollbar_color; + cl_style->has_scrollbar_color = cl_src->has_scrollbar_color; + cl_style->colorize_scrollbar = cl_src->colorize_scrollbar; + cl_style->animation = cl_src->animation; + cl_style->radius = cl_src->radius; + cl_style->style = cl_src->style; + + clearlooks_parent_class->copy (style, src); +} + +static void +clearlooks_style_unrealize (GtkStyle * style) +{ + clearlooks_parent_class->unrealize (style); } static GdkPixbuf * @@ -2508,19 +1446,67 @@ scale_or_ref (GdkPixbuf *src, return g_object_ref (src); } else { return gdk_pixbuf_scale_simple (src, - width, height, - GDK_INTERP_BILINEAR); + width, height, + GDK_INTERP_BILINEAR); } } +static void +clearlooks_style_draw_layout (GtkStyle * style, + GdkWindow * window, + GtkStateType state_type, + gboolean use_text, + GdkRectangle * area, + GtkWidget * widget, + const gchar * detail, gint x, gint y, PangoLayout * layout) +{ + GdkGC *gc; + + g_return_if_fail (GTK_IS_STYLE (style)); + g_return_if_fail (window != NULL); + + gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type]; + + if (area) + gdk_gc_set_clip_rectangle (gc, area); + + if (state_type == GTK_STATE_INSENSITIVE) { + ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style); + ClearlooksColors *colors = &clearlooks_style->colors; + + WidgetParameters params; + GdkColor etched; + CairoColor temp; + + clearlooks_set_widget_parameters (widget, style, state_type, ¶ms); + + if (GTK_WIDGET_NO_WINDOW (widget)) + ge_shade_color (¶ms.parentbg, 1.2, &temp); + else + ge_shade_color (&colors->bg[widget->state], 1.2, &temp); + + etched.red = (int) (temp.r * 65535); + etched.green = (int) (temp.g * 65535); + etched.blue = (int) (temp.b * 65535); + + gdk_draw_layout_with_colors (window, gc, x + 1, y + 1, layout, &etched, NULL); + gdk_draw_layout (window, gc, x, y, layout); + } + else + gdk_draw_layout (window, gc, x, y, layout); + + if (area) + gdk_gc_set_clip_rectangle (gc, NULL); +} + static GdkPixbuf * -render_icon (GtkStyle *style, - const GtkIconSource *source, - GtkTextDirection direction, - GtkStateType state, - GtkIconSize size, - GtkWidget *widget, - const char *detail) +clearlooks_style_draw_render_icon (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + GtkIconSize size, + GtkWidget *widget, + const char *detail) { int width = 1; int height = 1; @@ -2569,16 +1555,6 @@ render_icon (GtkStyle *style, if (gtk_icon_source_get_state_wildcarded (source)) { if (state == GTK_STATE_INSENSITIVE) { stated = set_transparency (scaled, 0.3); -#if 0 - stated = - gdk_pixbuf_composite_color_simple (scaled, - gdk_pixbuf_get_width (scaled), - gdk_pixbuf_get_height (scaled), - GDK_INTERP_BILINEAR, 128, - gdk_pixbuf_get_width (scaled), - style->bg[state].pixel, - style->bg[state].pixel); -#endif gdk_pixbuf_saturate_and_pixelate (stated, stated, 0.1, FALSE); @@ -2610,29 +1586,39 @@ clearlooks_style_class_init (ClearlooksStyleClass * klass) { GtkStyleClass *style_class = GTK_STYLE_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); - - style_class->realize = clearlooks_style_realize; - style_class->unrealize = clearlooks_style_unrealize; - style_class->init_from_rc = clearlooks_style_init_from_rc; - style_class->draw_focus = draw_focus; - style_class->draw_resize_grip = draw_resize_grip; - style_class->draw_handle = draw_handle; - style_class->draw_vline = draw_vline; - style_class->draw_hline = draw_hline; - style_class->draw_slider = draw_slider; - style_class->draw_shadow_gap = draw_shadow_gap; - style_class->draw_arrow = clearlooks_draw_arrow; - style_class->draw_check = draw_check; - style_class->draw_tab = draw_tab; - style_class->draw_box = draw_box; - style_class->draw_shadow = draw_shadow; - style_class->draw_box_gap = draw_box_gap; - style_class->draw_extension = draw_extension; - style_class->draw_option = draw_option; - style_class->draw_layout = draw_layout; - style_class->render_icon = render_icon; - style_class->draw_flat_box = draw_flat_box; + clearlooks_style_class = CLEARLOOKS_STYLE_CLASS (klass); + clearlooks_parent_class = g_type_class_peek_parent (klass); + + style_class->copy = clearlooks_style_copy; + style_class->realize = clearlooks_style_realize; + style_class->unrealize = clearlooks_style_unrealize; + style_class->init_from_rc = clearlooks_style_init_from_rc; + style_class->draw_handle = clearlooks_style_draw_handle; + style_class->draw_slider = clearlooks_style_draw_slider; + style_class->draw_shadow_gap = clearlooks_style_draw_shadow_gap; + style_class->draw_focus = clearlooks_style_draw_focus; + style_class->draw_box = clearlooks_style_draw_box; + style_class->draw_shadow = clearlooks_style_draw_shadow; + style_class->draw_box_gap = clearlooks_style_draw_box_gap; + style_class->draw_extension = clearlooks_style_draw_extension; + style_class->draw_option = clearlooks_style_draw_option; + style_class->draw_check = clearlooks_style_draw_check; + style_class->draw_flat_box = clearlooks_style_draw_flat_box; + style_class->draw_vline = clearlooks_style_draw_vline; + style_class->draw_hline = clearlooks_style_draw_hline; + style_class->draw_resize_grip = clearlooks_style_draw_resize_grip; + style_class->draw_tab = clearlooks_style_draw_tab; + style_class->draw_arrow = clearlooks_style_draw_arrow; + style_class->draw_layout = clearlooks_style_draw_layout; + style_class->render_icon = clearlooks_style_draw_render_icon; + + clearlooks_register_style_classic (&clearlooks_style_class->style_functions[CL_STYLE_CLASSIC]); + clearlooks_style_class->style_functions[CL_STYLE_GLOSSY] = clearlooks_style_class->style_functions[CL_STYLE_CLASSIC]; + clearlooks_register_style_glossy (&clearlooks_style_class->style_functions[CL_STYLE_GLOSSY]); + clearlooks_style_class->style_functions[CL_STYLE_INVERTED] = clearlooks_style_class->style_functions[CL_STYLE_CLASSIC]; + clearlooks_register_style_inverted (&clearlooks_style_class->style_functions[CL_STYLE_INVERTED]); + clearlooks_style_class->style_functions[CL_STYLE_GUMMY] = clearlooks_style_class->style_functions[CL_STYLE_CLASSIC]; + clearlooks_register_style_gummy (&clearlooks_style_class->style_functions[CL_STYLE_GUMMY]); } GType clearlooks_type_style = 0; diff --git a/libs/clearlooks/clearlooks_style.h b/libs/clearlooks/clearlooks_style.h index 1e07877bf7..78f3ca1675 100644 --- a/libs/clearlooks/clearlooks_style.h +++ b/libs/clearlooks/clearlooks_style.h @@ -1,5 +1,6 @@ /* Clearlooks Engine * Copyright (C) 2005 Richard Stellingwerff. + * Copyright (C) 2006 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,12 +23,16 @@ */ #include <gtk/gtkstyle.h> -#include "clearlooks_draw.h" +#ifndef CLEARLOOKS_STYLE_H +#define CLEARLOOKS_STYLE_H + +#include "animation.h" +#include "clearlooks_types.h" typedef struct _ClearlooksStyle ClearlooksStyle; typedef struct _ClearlooksStyleClass ClearlooksStyleClass; -extern GType clearlooks_type_style; +GE_INTERNAL extern GType clearlooks_type_style; #define CLEARLOOKS_TYPE_STYLE clearlooks_type_style #define CLEARLOOKS_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), CLEARLOOKS_TYPE_STYLE, ClearlooksStyle)) @@ -36,73 +41,30 @@ extern GType clearlooks_type_style; #define CLEARLOOKS_IS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLEARLOOKS_TYPE_STYLE)) #define CLEARLOOKS_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLEARLOOKS_TYPE_STYLE, ClearlooksStyleClass)) -typedef enum -{ - CL_BORDER_UPPER = 0, - CL_BORDER_LOWER, - CL_BORDER_UPPER_ACTIVE, - CL_BORDER_LOWER_ACTIVE, - CL_BORDER_COUNT -} ClBorderColorType; - -typedef enum -{ - CL_SCROLLBUTTON_BEGIN = 0, - CL_SCROLLBUTTON_END, - CL_SCROLLBUTTON_OTHER -} ClScrollButtonType; - struct _ClearlooksStyle { GtkStyle parent_instance; - - GdkColor shade[9]; - - GdkColor spot_color; - GdkColor spot1; - GdkColor spot2; - GdkColor spot3; - - GdkColor border[CL_BORDER_COUNT]; - - /* from light to dark */ - GdkGC *shade_gc[9]; - GdkGC *border_gc[CL_BORDER_COUNT]; - - GdkGC *spot1_gc; - GdkGC *spot2_gc; - GdkGC *spot3_gc; - - GdkColor inset_light[5]; - GdkColor inset_dark[5]; - - GdkColor button_g1[5]; - GdkColor button_g2[5]; - GdkColor button_g3[5]; - GdkColor button_g4[5]; - - GdkColor listview_bg[5]; - GdkPixmap *radio_pixmap_nonactive[5]; - GdkPixmap *radio_pixmap_active[5]; - GdkPixmap *radio_pixmap_inconsistent[5]; - GdkBitmap *radio_pixmap_mask; /* All masks are the same */ - - GdkPixmap *check_pixmap_nonactive[5]; - GdkPixmap *check_pixmap_active[5]; - GdkPixmap *check_pixmap_inconsistent[5]; - - gboolean sunkenmenubar:1; + ClearlooksColors colors; - guint8 progressbarstyle; + ClearlooksStyles style; + guint8 menubarstyle; - guint8 menuitemstyle; - guint8 listviewitemstyle; + guint8 toolbarstyle; + GdkColor scrollbar_color; + gboolean colorize_scrollbar; + gboolean has_scrollbar_color; + gboolean animation; + gfloat radius; }; struct _ClearlooksStyleClass { - GtkStyleClass parent_class; + GtkStyleClass parent_class; + + ClearlooksStyleFunctions style_functions[CL_NUM_STYLES]; }; -void clearlooks_style_register_type (GTypeModule *module); +GE_INTERNAL void clearlooks_style_register_type (GTypeModule *module); + +#endif /* CLEARLOOKS_STYLE_H */ diff --git a/libs/clearlooks/clearlooks_theme_main.c b/libs/clearlooks/clearlooks_theme_main.c index 5356f915dd..c042fdbac0 100644 --- a/libs/clearlooks/clearlooks_theme_main.c +++ b/libs/clearlooks/clearlooks_theme_main.c @@ -4,34 +4,20 @@ #include "clearlooks_style.h" #include "clearlooks_rc_style.h" -G_MODULE_EXPORT void +GE_EXPORT void theme_init (GTypeModule *module) { clearlooks_rc_style_register_type (module); clearlooks_style_register_type (module); - printf("theme_init() called from internal clearlooks engine\n"); } -G_MODULE_EXPORT void +GE_EXPORT void theme_exit (void) { } -G_MODULE_EXPORT GtkRcStyle * +GE_EXPORT GtkRcStyle * theme_create_rc_style (void) { return GTK_RC_STYLE (g_object_new (CLEARLOOKS_TYPE_RC_STYLE, NULL)); } - -/* 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/libs/clearlooks/clearlooks_types.h b/libs/clearlooks/clearlooks_types.h new file mode 100644 index 0000000000..7caf8a3208 --- /dev/null +++ b/libs/clearlooks/clearlooks_types.h @@ -0,0 +1,455 @@ +#ifndef CLEARLOOKS_TYPES_H +#define CLEARLOOKS_TYPES_H + +#include <ge-support.h> + +typedef unsigned char boolean; +typedef unsigned char uint8; +typedef struct _ClearlooksStyleFunctions ClearlooksStyleFunctions; + +typedef enum +{ + CL_STYLE_CLASSIC = 0, + CL_STYLE_GLOSSY = 1, + CL_STYLE_INVERTED = 2, + CL_STYLE_GUMMY = 3, + CL_NUM_STYLES = 4 +} ClearlooksStyles; + + +typedef enum +{ + CL_STATE_NORMAL, + CL_STATE_ACTIVE, + CL_STATE_SELECTED, + CL_STATE_INSENSITIVE +} ClearlooksStateType; + +typedef enum +{ + CL_JUNCTION_NONE = 0, + CL_JUNCTION_BEGIN = 1, + CL_JUNCTION_END = 2 +} ClearlooksJunction; + +typedef enum +{ + CL_STEPPER_UNKNOWN = 0, + CL_STEPPER_A = 1, + CL_STEPPER_B = 2, + CL_STEPPER_C = 4, + CL_STEPPER_D = 8 +} ClearlooksStepper; + +typedef enum +{ + CL_ORDER_FIRST, + CL_ORDER_MIDDLE, + CL_ORDER_LAST +} ClearlooksOrder; + +typedef enum +{ + CL_ORIENTATION_LEFT_TO_RIGHT, + CL_ORIENTATION_RIGHT_TO_LEFT, + CL_ORIENTATION_BOTTOM_TO_TOP, + CL_ORIENTATION_TOP_TO_BOTTOM +} ClearlooksOrientation; + +typedef enum +{ + CL_GAP_LEFT, + CL_GAP_RIGHT, + CL_GAP_TOP, + CL_GAP_BOTTOM +} ClearlooksGapSide; + +typedef enum +{ + CL_SHADOW_NONE, + CL_SHADOW_IN, + CL_SHADOW_OUT, + CL_SHADOW_ETCHED_IN, + CL_SHADOW_ETCHED_OUT +} ClearlooksShadowType; + +typedef enum +{ + CL_HANDLE_TOOLBAR, + CL_HANDLE_SPLITTER +} ClearlooksHandleType; + +typedef enum +{ + CL_ARROW_NORMAL, + CL_ARROW_COMBO +} ClearlooksArrowType; + +typedef enum +{ + CL_DIRECTION_UP, + CL_DIRECTION_DOWN, + CL_DIRECTION_LEFT, + CL_DIRECTION_RIGHT +} ClearlooksDirection; + +typedef enum +{ + CL_PROGRESSBAR_CONTINUOUS, + CL_PROGRESSBAR_DISCRETE +} ClearlooksProgressBarStyle; + +typedef enum +{ + CL_WINDOW_EDGE_NORTH_WEST, + CL_WINDOW_EDGE_NORTH, + CL_WINDOW_EDGE_NORTH_EAST, + CL_WINDOW_EDGE_WEST, + CL_WINDOW_EDGE_EAST, + CL_WINDOW_EDGE_SOUTH_WEST, + CL_WINDOW_EDGE_SOUTH, + CL_WINDOW_EDGE_SOUTH_EAST +} ClearlooksWindowEdge; + +typedef struct +{ + double x; + double y; + double width; + double height; +} ClearlooksRectangle; + +typedef struct +{ + CairoColor fg[5]; + CairoColor bg[5]; + CairoColor base[5]; + CairoColor text[5]; + + CairoColor shade[9]; + CairoColor spot[3]; +} ClearlooksColors; + +typedef struct +{ + boolean active; + boolean prelight; + boolean disabled; + boolean focus; + boolean is_default; + boolean ltr; + boolean enable_glow; + + gfloat radius; + + ClearlooksStateType state_type; + + uint8 corners; + uint8 xthickness; + uint8 ythickness; + + CairoColor parentbg; + + ClearlooksStyleFunctions *style_functions; +} WidgetParameters; + +typedef struct +{ + boolean lower; + boolean horizontal; + boolean fill_level; +} SliderParameters; + +typedef struct +{ + ClearlooksOrientation orientation; + boolean pulsing; + float value; +} ProgressBarParameters; + +typedef struct +{ + int linepos; +} OptionMenuParameters; + +typedef struct +{ + ClearlooksShadowType shadow; + ClearlooksGapSide gap_side; + int gap_x; + int gap_width; + const CairoColor *border; /* maybe changes this to some other hint ... */ +} FrameParameters; + +typedef struct +{ + ClearlooksGapSide gap_side; +} TabParameters; + +typedef struct +{ + CairoCorners corners; + ClearlooksShadowType shadow; +} ShadowParameters; + +typedef struct +{ + boolean horizontal; +} SeparatorParameters; + +typedef struct +{ + ClearlooksOrder order; /* XXX: rename to position */ + boolean resizable; +} ListViewHeaderParameters; + +typedef struct +{ + CairoColor color; + ClearlooksJunction junction; /* On which sides the slider junctions */ + boolean horizontal; + boolean has_color; +} ScrollBarParameters; + +typedef struct +{ + ClearlooksHandleType type; + boolean horizontal; +} HandleParameters; + +typedef struct +{ + ClearlooksStepper stepper; /* Which stepper to draw */ +} ScrollBarStepperParameters; + +typedef struct +{ + ClearlooksWindowEdge edge; +} ResizeGripParameters; + +typedef struct +{ + int style; +} MenuBarParameters; + +typedef struct +{ + ClearlooksShadowType shadow_type; + boolean in_cell; + boolean in_menu; +} CheckboxParameters; + +typedef struct +{ + ClearlooksArrowType type; + ClearlooksDirection direction; +} ArrowParameters; + +typedef struct +{ + int style; + boolean topmost; +} ToolbarParameters; + +struct _ClearlooksStyleFunctions +{ + void (*draw_button) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_scale_trough) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SliderParameters *slider, + int x, int y, int width, int height); + + void (*draw_progressbar_trough) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_progressbar_fill) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ProgressBarParameters *progressbar, + int x, int y, int width, int height, gint offset); + + void (*draw_slider_button) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SliderParameters *slider, + int x, int y, int width, int height); + + void (*draw_entry) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_spinbutton) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_spinbutton_down) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_optionmenu) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const OptionMenuParameters *optionmenu, + int x, int y, int width, int height); + + void (*draw_inset) (cairo_t *cr, + const CairoColor *bg_color, + double x, double y, double w, double h, + double radius, uint8 corners); + + void (*draw_menubar) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const MenuBarParameters *menubar, + int x, int y, int width, int height); + + void (*draw_tab) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const TabParameters *tab, + int x, int y, int width, int height); + + void (*draw_frame) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const FrameParameters *frame, + int x, int y, int width, int height); + + void (*draw_separator) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SeparatorParameters *separator, + int x, int y, int width, int height); + + void (*draw_menu_item_separator) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const SeparatorParameters *separator, + int x, int y, int width, int height); + + void (*draw_list_view_header) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ListViewHeaderParameters *header, + int x, int y, int width, int height); + + void (*draw_toolbar) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ToolbarParameters *toolbar, + int x, int y, int width, int height); + + void (*draw_menuitem) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_menubaritem) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_selected_cell) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_scrollbar_stepper) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + const ScrollBarStepperParameters *stepper, + int x, int y, int width, int height); + + void (*draw_scrollbar_slider) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height); + + void (*draw_scrollbar_trough) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ScrollBarParameters *scrollbar, + int x, int y, int width, int height); + + void (*draw_statusbar) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_menu_frame) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_tooltip) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_handle) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const HandleParameters *handle, + int x, int y, int width, int height); + + void (*draw_resize_grip) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ResizeGripParameters *grip, + int x, int y, int width, int height); + + void (*draw_arrow) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const ArrowParameters *arrow, + int x, int y, int width, int height); + + void (*draw_checkbox) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height); + + void (*draw_radiobutton) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + const CheckboxParameters *checkbox, + int x, int y, int width, int height); + + /* Style internal functions */ + /* XXX: Only used by slider_button, inline it? */ + void (*draw_shadow) (cairo_t *cr, + const ClearlooksColors *colors, + gfloat radius, + int width, int height); + + void (*draw_slider) (cairo_t *cr, + const ClearlooksColors *colors, + const WidgetParameters *widget, + int x, int y, int width, int height); + + void (*draw_gripdots) (cairo_t *cr, + const ClearlooksColors *colors, int x, int y, + int width, int height, int xr, int yr, + float contrast); +}; + + +#define CLEARLOOKS_RECTANGLE_SET(rect, _x, _y, _w, _h) rect.x = _x; \ + rect.y = _y; \ + rect.width = _w; \ + rect.height = _h; + +#endif /* CLEARLOOKS_TYPES_H */ diff --git a/libs/clearlooks/ge-support.h b/libs/clearlooks/ge-support.h new file mode 100644 index 0000000000..e0a42b6c3d --- /dev/null +++ b/libs/clearlooks/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/libs/clearlooks/general-support.h b/libs/clearlooks/general-support.h new file mode 100644 index 0000000000..25999e2d31 --- /dev/null +++ b/libs/clearlooks/general-support.h @@ -0,0 +1,39 @@ + +#include <gmodule.h> +#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); + +#define GE_EXPORT G_MODULE_EXPORT +#define GE_INTERNAL G_GNUC_INTERNAL + +/* explicitly export with ggc, G_MODULE_EXPORT does not do this, this should + * make it possible to compile with -fvisibility=hidden */ +#ifdef G_HAVE_GNUC_VISIBILITY +# undef GE_EXPORT +# define GE_EXPORT __attribute__((__visibility__("default"))) +#endif + +#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# undef GE_EXPORT +# undef GE_INTERNAL +# define GE_EXPORT __global +# define GE_INTERNAL __hidden +#endif diff --git a/libs/clearlooks/support.c b/libs/clearlooks/support.c index 358c7f43fb..6d4d8a286d 100644 --- a/libs/clearlooks/support.c +++ b/libs/clearlooks/support.c @@ -1,518 +1,33 @@ -#include "support.h" - -/* #define ALWAYS_DITHER_GRADIENTS */ - -GtkTextDirection -get_direction (GtkWidget *widget) -{ - GtkTextDirection dir; - - if (widget) - dir = gtk_widget_get_direction (widget); - else - dir = GTK_TEXT_DIR_LTR; - - return dir; -} - -GdkPixbuf * -generate_bit (unsigned char alpha[], GdkColor *color, double mult) -{ - guint r, g, b; - GdkPixbuf *pixbuf; - unsigned char *pixels; - int w, h, rs; - int x, y; - - r = (color->red >> 8) * mult; - r = MIN(r, 255); - g = (color->green >> 8) * mult; - g = MIN(g, 255); - b = (color->blue >> 8) * mult; - b = MIN(b, 255); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, RADIO_SIZE, RADIO_SIZE); - - w = gdk_pixbuf_get_width (pixbuf); - h = gdk_pixbuf_get_height (pixbuf); - rs = gdk_pixbuf_get_rowstride (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - - - for (y=0; y < h; y++) - { - for (x=0; x < w; x++) - { - pixels[y*rs + x*4 + 0] = r; - pixels[y*rs + x*4 + 1] = g; - pixels[y*rs + x*4 + 2] = b; - if (alpha) - pixels[y*rs + x*4 + 3] = alpha[y*w + x]; - else - pixels[y*rs + x*4 + 3] = 255; - } - } - - return pixbuf; -} - -#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255))) - -GdkPixbuf * -colorize_bit (unsigned char *bit, - unsigned char *alpha, - GdkColor *new_color) -{ - GdkPixbuf *pixbuf; - double intensity; - int x, y; - const guchar *src, *asrc; - guchar *dest; - int dest_rowstride; - int width, height; - guchar *dest_pixels; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, RADIO_SIZE, RADIO_SIZE); - - if (pixbuf == NULL) - return NULL; - - dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - dest_pixels = gdk_pixbuf_get_pixels (pixbuf); - - for (y = 0; y < RADIO_SIZE; y++) - { - src = bit + y * RADIO_SIZE; - asrc = alpha + y * RADIO_SIZE; - dest = dest_pixels + y * dest_rowstride; - - for (x = 0; x < RADIO_SIZE; x++) - { - double dr, dg, db; - - intensity = (src[x] + 0 )/ 255.0; - - if (intensity <= 0.5) - { - /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */ - dr = (new_color->red * intensity * 2.0) / 65535.0; - dg = (new_color->green * intensity * 2.0) / 65535.0; - db = (new_color->blue * intensity * 2.0) / 65535.0; - } - else - { - /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */ - dr = (new_color->red + (65535 - new_color->red) * (intensity - 0.5) * 2.0) / 65535.0; - dg = (new_color->green + (65535 - new_color->green) * (intensity - 0.5) * 2.0) / 65535.0; - db = (new_color->blue + (65535 - new_color->blue) * (intensity - 0.5) * 2.0) / 65535.0; - } - - dest[0] = CLAMP_UCHAR (255 * dr); - dest[1] = CLAMP_UCHAR (255 * dg); - dest[2] = CLAMP_UCHAR (255 * db); - - dest[3] = asrc[x]; - dest += 4; - } - } - - return pixbuf; -} - -GdkPixmap * -pixbuf_to_pixmap (GtkStyle *style, - GdkPixbuf *pixbuf, - GdkScreen *screen) -{ - GdkGC *tmp_gc; - GdkPixmap *pixmap; - - pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen), - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - style->depth); - - gdk_drawable_set_colormap (pixmap, style->colormap); - - tmp_gc = gdk_gc_new (pixmap); - - gdk_pixbuf_render_to_drawable (pixbuf, pixmap, tmp_gc, 0, 0, 0, 0, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - GDK_RGB_DITHER_NORMAL, 0, 0); - - gdk_gc_unref (tmp_gc); - - return pixmap; -} - - -void -rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b) -{ - gdouble min; - gdouble max; - gdouble red; - gdouble green; - gdouble blue; - gdouble h, l, s; - gdouble delta; - - red = *r; - green = *g; - blue = *b; - - if (red > green) - { - if (red > blue) - max = red; - else - max = blue; - - if (green < blue) - min = green; - else - min = blue; - } - else - { - if (green > blue) - max = green; - else - max = blue; - - if (red < blue) - min = red; - else - min = blue; - } - - l = (max + min) / 2; - s = 0; - h = 0; - - if (max != min) - { - if (l <= 0.5) - s = (max - min) / (max + min); - else - s = (max - min) / (2 - max - min); - - delta = max -min; - if (red == max) - h = (green - blue) / delta; - else if (green == max) - h = 2 + (blue - red) / delta; - else if (blue == max) - h = 4 + (red - green) / delta; - - h *= 60; - if (h < 0.0) - h += 360; - } - - *r = h; - *g = l; - *b = s; -} - -void -hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s) -{ - gdouble hue; - gdouble lightness; - gdouble saturation; - gdouble m1, m2; - gdouble r, g, b; - - lightness = *l; - saturation = *s; - - if (lightness <= 0.5) - m2 = lightness * (1 + saturation); - else - m2 = lightness + saturation - lightness * saturation; - - m1 = 2 * lightness - m2; - - if (saturation == 0) - { - *h = lightness; - *l = lightness; - *s = lightness; - } - else - { - hue = *h + 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - r = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - r = m2; - else if (hue < 240) - r = m1 + (m2 - m1) * (240 - hue) / 60; - else - r = m1; - - hue = *h; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - g = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - g = m2; - else if (hue < 240) - g = m1 + (m2 - m1) * (240 - hue) / 60; - else - g = m1; - - hue = *h - 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - b = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - b = m2; - else if (hue < 240) - b = m1 + (m2 - m1) * (240 - hue) / 60; - else - b = m1; - - *h = r; - *l = g; - *s = b; - } -} - -void -shade (GdkColor * a, GdkColor * b, float k) -{ - gdouble red; - gdouble green; - gdouble blue; - - red = (gdouble) a->red / 65535.0; - green = (gdouble) a->green / 65535.0; - blue = (gdouble) a->blue / 65535.0; - - rgb_to_hls (&red, &green, &blue); - - green *= k; - if (green > 1.0) - green = 1.0; - else if (green < 0.0) - green = 0.0; - - blue *= k; - if (blue > 1.0) - blue = 1.0; - else if (blue < 0.0) - blue = 0.0; - - hls_to_rgb (&red, &green, &blue); - - b->red = red * 65535.0; - b->green = green * 65535.0; - b->blue = blue * 65535.0; -} - - -/**************************************************************************/ - -void -arrow_draw_hline (GdkWindow *window, - GdkGC *gc, - int x1, - int x2, - int y, - gboolean last) -{ - if (x2 - x1 < 7 && !last) /* 7 to get garretts pixels, otherwise 6 */ - { - gdk_draw_line (window, gc, x1, y, x2, y); - } - else if (last) - { - /* we don't draw "spikes" for very small arrows */ - if (x2 - x1 <= 9) - { - /*gdk_draw_line (window, gc, x1+1, y, x1+1, y); - gdk_draw_line (window, gc, x2-1, y, x2-1, y);*/ - } - else - { - gdk_draw_line (window, gc, x1+2, y, x1+2, y); - gdk_draw_line (window, gc, x2-2, y, x2-2, y); - } - } - else - { - gdk_draw_line (window, gc, x1, y, x1+2, y); - gdk_draw_line (window, gc, x2-2, y, x2, y); - } -} - -void -arrow_draw_vline (GdkWindow *window, - GdkGC *gc, - int y1, - int y2, - int x, - gboolean last) -{ - if (y2 - y1 < 7 && !last) /* 7 to get garretts pixels */ - gdk_draw_line (window, gc, x, y1, x, y2); - else if (last) - { - /* we don't draw "spikes" for very small arrows */ - if (y2 - y1 > 9) { - gdk_draw_line (window, gc, x, y1+2, x, y1+2); - gdk_draw_line (window, gc, x, y2-2, x, y2-2); - } - } - else - { - gdk_draw_line (window, gc, x, y1, x, y1+2); - gdk_draw_line (window, gc, x, y2-2, x, y2); - } -} - - - -void -draw_arrow (GdkWindow *window, - GdkGC *gc, - GdkRectangle *area, - GtkArrowType arrow_type, - gint x, - gint y, - gint width, - gint height) -{ - gint i, j; - - if (area) - gdk_gc_set_clip_rectangle (gc, area); - - if (arrow_type == GTK_ARROW_DOWN) - { - for (i = 0, j = -1; i < height; i++, j++) - arrow_draw_hline (window, gc, x + j, x + width - j - 1, y + i, i == 0); - - } - else if (arrow_type == GTK_ARROW_UP) - { - for (i = height - 1, j = -1; i >= 0; i--, j++) - arrow_draw_hline (window, gc, x + j, x + width - j - 1, y + i, i == height - 1); - } - else if (arrow_type == GTK_ARROW_LEFT) - { - for (i = width - 1, j = -1; i >= 0; i--, j++) - arrow_draw_vline (window, gc, y + j, y + height - j - 1, x + i, i == width - 1); - } - else if (arrow_type == GTK_ARROW_RIGHT) - { - for (i = 0, j = -1; i < width; i++, j++) - arrow_draw_vline (window, gc, y + j, y + height - j - 1, x + i, i == 0); - } - - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); -} - -void -calculate_arrow_geometry (GtkArrowType arrow_type, - gint *x, - gint *y, - gint *width, - gint *height) -{ - gint w = *width; - gint h = *height; - - switch (arrow_type) - { - case GTK_ARROW_UP: - case GTK_ARROW_DOWN: - w += (w % 2) - 1; - h = (w / 2 + 1) + 1; - - if (h > *height) - { - h = *height; - w = 2 * (h - 1) - 1; - } - - if (arrow_type == GTK_ARROW_DOWN) - { - if (*height % 2 == 1 || h % 2 == 0) - *height += 1; - } - else - { - if (*height % 2 == 0 || h % 2 == 0) - *height -= 1; - } - break; - - case GTK_ARROW_RIGHT: - case GTK_ARROW_LEFT: - h += (h % 2) - 1; - w = (h / 2 + 1) + 1; - - if (w > *width) - { - w = *width; - h = 2 * (w - 1) - 1; - } - - if (arrow_type == GTK_ARROW_RIGHT) - { - if (*width % 2 == 1 || w % 2 == 0) - *width += 1; - } - else - { - if (*width % 2 == 0 || w % 2 == 0) - *width -= 1; - } - break; - - default: - /* should not be reached */ - break; - } - - *x += (*width - w) / 2; - *y += (*height - h) / 2; - *height = h; - *width = w; -} +/* Clearlooks theme engine + * Copyright (C) 2005 Richard Stellingwerff. + * Copyright (C) 2007 Benjamin Berg <benjamin@sipsolutions.net>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "support.h" -void gtk_treeview_get_header_index (GtkTreeView *tv, GtkWidget *header, - gint *column_index, gint *columns, -gboolean *resizable) +void clearlooks_treeview_get_header_index (GtkTreeView *tv, GtkWidget *header, + gint *column_index, gint *columns, + gboolean *resizable) { - GList *list; + GList *list, *list_start; *column_index = *columns = 0; - list = gtk_tree_view_get_columns (tv); + list_start = list = gtk_tree_view_get_columns (tv); do { @@ -525,13 +40,15 @@ gboolean *resizable) if ( column->visible ) (*columns)++; } while ((list = g_list_next(list))); + + g_list_free (list_start); } -void gtk_clist_get_header_index (GtkCList *clist, GtkWidget *button, +void clearlooks_clist_get_header_index (GtkCList *clist, GtkWidget *button, gint *column_index, gint *columns) { - *columns = clist->columns; int i; + *columns = clist->columns; for (i=0; i<*columns; i++) { @@ -543,439 +60,228 @@ void gtk_clist_get_header_index (GtkCList *clist, GtkWidget *button, } } -gboolean -sanitize_size (GdkWindow *window, - gint *width, - gint *height) +void +clearlooks_get_parent_bg (const GtkWidget *widget, CairoColor *color) { - gboolean set_bg = FALSE; + GtkStateType state_type; + const GtkWidget *parent; + GdkColor *gcolor; - if ((*width == -1) && (*height == -1)) - { - set_bg = GDK_IS_WINDOW (window); - gdk_window_get_size (window, width, height); - } - else if (*width == -1) - gdk_window_get_size (window, width, NULL); - else if (*height == -1) - gdk_window_get_size (window, NULL, height); + if (widget == NULL) + return; - return set_bg; -} - -static GtkRequisition default_option_indicator_size = { 7, 13 }; -static GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 }; + parent = widget->parent; + + while (parent && GTK_WIDGET_NO_WINDOW (parent) && !((GTK_IS_NOTEBOOK (parent)) || (GTK_IS_TOOLBAR (parent)))) + parent = parent->parent; -void -option_menu_get_props (GtkWidget *widget, - GtkRequisition *indicator_size, - GtkBorder *indicator_spacing) -{ - GtkRequisition *tmp_size = NULL; - GtkBorder *tmp_spacing = NULL; + if (parent == NULL) + return; - if (widget) - gtk_widget_style_get (widget, "indicator_size", &tmp_size, - "indicator_spacing", &tmp_spacing, NULL); + state_type = GTK_WIDGET_STATE (parent); - if (tmp_size) - { - *indicator_size = *tmp_size; - g_free (tmp_size); - } - else - *indicator_size = default_option_indicator_size; + gcolor = &parent->style->bg[state_type]; - if (tmp_spacing) - { - *indicator_spacing = *tmp_spacing; - g_free (tmp_spacing); - } - else - *indicator_spacing = default_option_indicator_spacing; -} - -GtkWidget *special_get_ancestor(GtkWidget * widget, - GType widget_type) -{ - g_return_val_if_fail(GTK_IS_WIDGET(widget), NULL); - - while (widget && widget->parent - && !g_type_is_a(GTK_WIDGET_TYPE(widget->parent), - widget_type)) - widget = widget->parent; - - if (! - (widget && widget->parent - && g_type_is_a(GTK_WIDGET_TYPE(widget->parent), widget_type))) - return NULL; - - return widget; -} - -/* Dithered Gradient Buffers */ -static void -internel_image_buffer_free_pixels (guchar *pixels, gpointer data) -{ - g_free (pixels); -} - -static GdkPixbuf* -internal_image_buffer_new (gint width, gint height) -{ - guchar *buf; - int rowstride; - - g_return_val_if_fail (width > 0, NULL); - g_return_val_if_fail (height > 0, NULL); - - rowstride = width * 3; - - buf = g_try_malloc (height * rowstride); - - if (!buf) - return NULL; - - return gdk_pixbuf_new_from_data(buf, GDK_COLORSPACE_RGB, - FALSE, 8, - width, height, rowstride, - internel_image_buffer_free_pixels, NULL); + ge_gdk_color_to_cairo (gcolor, color); } -static void -internal_color_get_as_uchars(GdkColor *color, - guchar *red, - guchar *green, - guchar *blue) +ClearlooksStepper +clearlooks_scrollbar_get_stepper (GtkWidget *widget, + GdkRectangle *stepper) { - *red = (guchar) (color->red / 256.0); - *green = (guchar) (color->green / 256.0); - *blue = (guchar) (color->blue / 256.0); -} + ClearlooksStepper value = CL_STEPPER_UNKNOWN; + GdkRectangle tmp; + GdkRectangle check_rectangle; + GtkOrientation orientation; -static GdkPixbuf* -internal_create_horizontal_gradient_image_buffer (gint width, gint height, - GdkColor *from, - GdkColor *to) -{ - int i; - long r, g, b, dr, dg, db; - GdkPixbuf* buffer; - guchar *ptr; - guchar *pixels; - guchar r0, g0, b0; - guchar rf, gf, bf; - int rowstride; + if (!GE_IS_RANGE (widget)) + return CL_STEPPER_UNKNOWN; - buffer = internal_image_buffer_new (width, height); - - if (buffer == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (buffer); - ptr = pixels; - rowstride = gdk_pixbuf_get_rowstride (buffer); - - internal_color_get_as_uchars(from, &r0, &g0, &b0); - internal_color_get_as_uchars(to, &rf, &gf, &bf); - - r = r0 << 16; - g = g0 << 16; - b = b0 << 16; - - dr = ((rf-r0)<<16)/width; - dg = ((gf-g0)<<16)/width; - db = ((bf-b0)<<16)/width; + check_rectangle.x = widget->allocation.x; + check_rectangle.y = widget->allocation.y; + check_rectangle.width = stepper->width; + check_rectangle.height = stepper->height; + + orientation = GTK_RANGE (widget)->orientation; + + if (widget->allocation.x == -1 && widget->allocation.y == -1) + return CL_STEPPER_UNKNOWN; + + if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp)) + value = CL_STEPPER_A; - /* render the first line */ - for (i=0; i<width; i++) + if (value == CL_STEPPER_UNKNOWN) /* Haven't found a match */ { - *(ptr++) = (guchar)(r>>16); - *(ptr++) = (guchar)(g>>16); - *(ptr++) = (guchar)(b>>16); - - r += dr; - g += dg; - b += db; + if (orientation == GTK_ORIENTATION_HORIZONTAL) + check_rectangle.x = widget->allocation.x + stepper->width; + else + check_rectangle.y = widget->allocation.y + stepper->height; + + if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp)) + value = CL_STEPPER_B; } - /* copy the first line to the other lines */ - for (i=1; i<height; i++) + if (value == CL_STEPPER_UNKNOWN) /* Still haven't found a match */ { - memcpy (&(pixels[i*rowstride]), pixels, rowstride); + if (orientation == GTK_ORIENTATION_HORIZONTAL) + check_rectangle.x = widget->allocation.x + widget->allocation.width - (stepper->width * 2); + else + check_rectangle.y = widget->allocation.y + widget->allocation.height - (stepper->height * 2); + + if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp)) + value = CL_STEPPER_C; } - - return buffer; -} - -static GdkPixbuf* -internal_create_vertical_gradient_image_buffer (gint width, gint height, - GdkColor *from, - GdkColor *to) -{ - gint i, j, max_block, last_block; - long r, g, b, dr, dg, db; - GdkPixbuf *buffer; - - guchar *ptr; - guchar point[4]; - - guchar r0, g0, b0; - guchar rf, gf, bf; - - gint rowstride; - guchar *pixels; - - buffer = internal_image_buffer_new (width, height); - - if (buffer == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (buffer); - rowstride = gdk_pixbuf_get_rowstride (buffer); - - internal_color_get_as_uchars(from, &r0, &g0, &b0); - internal_color_get_as_uchars(to, &rf, &gf, &bf); - - r = r0<<16; - g = g0<<16; - b = b0<<16; - - dr = ((rf-r0)<<16)/height; - dg = ((gf-g0)<<16)/height; - db = ((bf-b0)<<16)/height; - - max_block = width/2; - for (i=0; i < height; i++) + if (value == CL_STEPPER_UNKNOWN) /* STILL haven't found a match */ { - ptr = pixels + i * rowstride; - - ptr[0] = r>>16; - ptr[1] = g>>16; - ptr[2] = b>>16; + if (orientation == GTK_ORIENTATION_HORIZONTAL) + check_rectangle.x = widget->allocation.x + widget->allocation.width - stepper->width; + else + check_rectangle.y = widget->allocation.y + widget->allocation.height - stepper->height; - if (width > 1) - { - last_block = 0; - - for (j=1; j <= max_block; j *= 2) - { - memcpy (&(ptr[j*3]), ptr, j*3); - - if ((j*2) >= max_block) - { - last_block = j*2; - } - } - - if ((last_block < width) && (last_block > 0)) - { - memcpy (&(ptr[last_block*3]), ptr, (width - last_block)*3); - } - } - - r += dr; - g += dg; - b += db; + if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp)) + value = CL_STEPPER_D; } - return buffer; + return value; } -void -draw_vgradient (GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height, - GdkColor *left_color, GdkColor *right_color) +ClearlooksStepper +clearlooks_scrollbar_visible_steppers (GtkWidget *widget) { - #ifndef ALWAYS_DITHER_GRADIENTS - gboolean dither = ((style->depth > 0) && (style->depth <= 16)); - #endif - - if ((width <= 0) || (height <= 0)) - return; - - if ( left_color == NULL || right_color == NULL ) - { - gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height); - return; - } - - #ifndef ALWAYS_DITHER_GRADIENTS - if (dither) - #endif - { - GdkPixbuf *image_buffer = NULL; - - image_buffer = internal_create_horizontal_gradient_image_buffer (width, height, left_color, right_color); + ClearlooksStepper steppers = 0; - if (image_buffer) - { - gdk_draw_pixbuf(drawable, gc, image_buffer, 0, 0, x, y, width, height, GDK_RGB_DITHER_MAX, 0, 0); - - g_object_unref(image_buffer); - } - } - #ifndef ALWAYS_DITHER_GRADIENTS - else - { - int i; - GdkColor col; - int dr, dg, db; - GdkGCValues old_values; - - gdk_gc_get_values (gc, &old_values); + if (!GE_IS_RANGE (widget)) + return 0; - if (left_color == right_color ) - { - col = *left_color; - gdk_rgb_find_color (style->colormap, &col); - gdk_gc_set_foreground (gc, &col); - gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height); - gdk_gc_set_foreground (gc, &old_values.foreground); - return; - } + if (GTK_RANGE (widget)->has_stepper_a) + steppers |= CL_STEPPER_A; - col = *left_color; - dr = (right_color->red - left_color->red) / width; - dg = (right_color->green - left_color->green) / width; - db = (right_color->blue - left_color->blue) / width; + if (GTK_RANGE (widget)->has_stepper_b) + steppers |= CL_STEPPER_B; - for (i = 0; i < width; i++) - { - gdk_rgb_find_color (style->colormap, &col); - - gdk_gc_set_foreground (gc, &col); - gdk_draw_line (drawable, gc, x + i, y, x + i, y + height - 1); - - col.red += dr; - col.green += dg; - col.blue += db; - } + if (GTK_RANGE (widget)->has_stepper_c) + steppers |= CL_STEPPER_C; - gdk_gc_set_foreground (gc, &old_values.foreground); - } - #endif + if (GTK_RANGE (widget)->has_stepper_d) + steppers |= CL_STEPPER_D; + + return steppers; } -void -draw_hgradient (GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height, - GdkColor *top_color, GdkColor *bottom_color) +ClearlooksJunction +clearlooks_scrollbar_get_junction (GtkWidget *widget) { - #ifndef ALWAYS_DITHER_GRADIENTS - gboolean dither = ((style->depth > 0) && (style->depth <= 16)); - #endif + GtkAdjustment *adj; + ClearlooksJunction junction = CL_JUNCTION_NONE; - if ((width <= 0) || (height <= 0)) - return; + if (!GE_IS_RANGE (widget)) + return CL_JUNCTION_NONE; - #ifndef ALWAYS_DITHER_GRADIENTS - if (dither) - #endif - { - GdkPixbuf *image_buffer = NULL; - - image_buffer = internal_create_vertical_gradient_image_buffer (width, height, top_color, bottom_color); + adj = GTK_RANGE (widget)->adjustment; - if (image_buffer) - { - gdk_draw_pixbuf(drawable, gc, image_buffer, 0, 0, x, y, width, height, GDK_RGB_DITHER_MAX, 0, 0); - - g_object_unref(image_buffer); - } - } - #ifndef ALWAYS_DITHER_GRADIENTS - else + if (adj->value <= adj->lower && + (GTK_RANGE (widget)->has_stepper_a || GTK_RANGE (widget)->has_stepper_b)) { - int i; - GdkColor col; - int dr, dg, db; - GdkGCValues old_values; - - gdk_gc_get_values (gc, &old_values); - - if (top_color == bottom_color ) - { - col = *top_color; - gdk_rgb_find_color (style->colormap, &col); - gdk_gc_set_foreground (gc, &col); - gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height); - gdk_gc_set_foreground (gc, &old_values.foreground); - return; - } - - col = *top_color; - dr = (bottom_color->red - top_color->red) / height; - dg = (bottom_color->green - top_color->green) / height; - db = (bottom_color->blue - top_color->blue) / height; - - for (i = 0; i < height; i++) - { - gdk_rgb_find_color (style->colormap, &col); + junction |= CL_JUNCTION_BEGIN; + } - gdk_gc_set_foreground (gc, &col); - gdk_draw_line (drawable, gc, x, y + i, x + width - 1, y + i); - - col.red += dr; - col.green += dg; - col.blue += db; - } - - gdk_gc_set_foreground (gc, &old_values.foreground); + if (adj->value >= adj->upper - adj->page_size && + (GTK_RANGE (widget)->has_stepper_c || GTK_RANGE (widget)->has_stepper_d)) + { + junction |= CL_JUNCTION_END; } - #endif -} - -void blend (GdkColormap *colormap, - GdkColor *a, GdkColor *b, GdkColor *c, int alpha) -{ - int inAlpha = 100-alpha; - c->red = (a->red * alpha + b->red * inAlpha) / 100; - c->green = (a->green * alpha + b->green * inAlpha) / 100; - c->blue = (a->blue * alpha + b->blue * inAlpha) / 100; - gdk_rgb_find_color (colormap, c); + return junction; } -GtkWidget *get_parent_window (GtkWidget *widget) +void +clearlooks_set_toolbar_parameters (ToolbarParameters *toolbar, GtkWidget *widget, GdkWindow *window, gint x, gint y) { - GtkWidget *parent = widget->parent; + toolbar->topmost = FALSE; - while (parent && GTK_WIDGET_NO_WINDOW (parent)) - parent = parent->parent; - - return parent; + if (x == 0 && y == 0) { + if (widget && widget->allocation.x == 0 && widget->allocation.y == 0) + { + if (widget->window == window && GE_IS_TOOLBAR (widget)) + { + toolbar->topmost = TRUE; + } + } + } } -GdkColor *get_parent_bgcolor (GtkWidget *widget) +void +clearlooks_get_notebook_tab_position (GtkWidget *widget, + gboolean *start, + gboolean *end) { - GtkWidget *parent = get_parent_window (widget); + /* default value */ + *start = TRUE; + *end = FALSE; + + if (GE_IS_NOTEBOOK (widget)) { + gboolean found_tabs = FALSE; + gint i, n_pages; + GtkNotebook *notebook = GTK_NOTEBOOK (widget); + + /* got a notebook, so walk over all the tabs and decide based + * on that ... + * It works like this: + * - If there is any visible tab that is expanded, set both. + * - Set start/end if there is any visible tab that is at + * the start/end. + * - If one has the child_visibility set to false, arrows + * are present; so none + * The heuristic falls over if there is a notebook that just + * happens to fill up all the available space. ie. All tabs + * are left aligned, but it does not require scrolling. + * (a more complex heuristic could calculate the tabs width + * and add them all up) */ + + n_pages = gtk_notebook_get_n_pages (notebook); + for (i = 0; i < n_pages; i++) { + GtkWidget *tab_child; + GtkWidget *tab_label; + gboolean expand; + GtkPackType pack_type; + + tab_child = gtk_notebook_get_nth_page (notebook, i); + + /* Skip invisible tabs */ + tab_label = gtk_notebook_get_tab_label (notebook, tab_child); + if (!tab_label || !GTK_WIDGET_VISIBLE (tab_label)) + continue; + /* This is the same what the notebook does internally. */ + if (tab_label && !gtk_widget_get_child_visible (tab_label)) { + /* One child is hidden because scroll arrows are present. + * So both corners are rounded. */ + *start = FALSE; + *end = FALSE; + return; + } - if (parent && parent->style) - return &parent->style->bg[GTK_STATE_NORMAL]; + gtk_notebook_query_tab_label_packing (notebook, tab_child, + &expand, + NULL, /* don't need fill */ + &pack_type); - return NULL; -} + if (!found_tabs) { + found_tabs = TRUE; + *start = FALSE; + *end = FALSE; + } -GtkWidget * -find_combo_box_widget (GtkWidget * widget) -{ - GtkWidget *result = NULL; - - if (widget && !GTK_IS_COMBO_BOX_ENTRY (widget)) - { - if (GTK_IS_COMBO_BOX (widget)) - result = widget; - else - result = find_combo_box_widget(widget->parent); + if (expand) { + *start = TRUE; + *end = TRUE; + } else if (pack_type == GTK_PACK_START) { + *start = TRUE; + } else { + *end = TRUE; + } + } } - - return result; } -gboolean -is_combo_box (GtkWidget * widget) -{ - return (find_combo_box_widget(widget) != NULL); -} + diff --git a/libs/clearlooks/support.h b/libs/clearlooks/support.h index a1430b40d0..23e33c58e7 100644 --- a/libs/clearlooks/support.h +++ b/libs/clearlooks/support.h @@ -1,110 +1,38 @@ +#ifndef SUPPORT_H +#define SUPPORT_H + #include <gtk/gtk.h> #include <math.h> #include <string.h> -/* GTK 2.2 compatibility */ -#ifndef GTK_IS_COMBO_BOX_ENTRY - #define GTK_IS_COMBO_BOX_ENTRY(x) 0 -#endif -#ifndef GTK_IS_COMBO_BOX - #define GTK_IS_COMBO_BOX(x) 0 -#endif +#include "clearlooks_types.h" #define RADIO_SIZE 13 #define CHECK_SIZE 13 -GtkTextDirection -get_direction (GtkWidget *widget); - -GdkPixbuf * -generate_bit (unsigned char alpha[], - GdkColor *color, - double mult); - -GdkPixbuf * -colorize_bit (unsigned char *bit, - unsigned char *alpha, - GdkColor *new_color); - -GdkPixmap * -pixbuf_to_pixmap (GtkStyle *style, - GdkPixbuf *pixbuf, - GdkScreen *screen); - -gboolean -sanitize_size (GdkWindow *window, - gint *width, - gint *height); - -void -rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b); - -void -hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s); - -void -shade (GdkColor * a, GdkColor * b, float k); - -void -draw_hgradient (GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height, - GdkColor *top_color, GdkColor *bottom_color); - -void -draw_vgradient (GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height, - GdkColor *left_color, GdkColor *right_color); - -void -arrow_draw_hline (GdkWindow *window, - GdkGC *gc, - int x1, - int x2, - int y, - gboolean last); - -void -arrow_draw_vline (GdkWindow *window, - GdkGC *gc, - int y1, - int y2, - int x, - gboolean last); - -void -draw_arrow (GdkWindow *window, - GdkGC *gc, - GdkRectangle *area, - GtkArrowType arrow_type, - gint x, - gint y, - gint width, - gint height); - -void -calculate_arrow_geometry (GtkArrowType arrow_type, - gint *x, - gint *y, - gint *width, - gint *height); - -GtkWidget *special_get_ancestor(GtkWidget * widget, - GType widget_type); - -void blend (GdkColormap *colormap, - GdkColor *a, GdkColor *b, GdkColor *c, int alpha); - -GtkWidget *get_parent_window (GtkWidget *widget); +GE_INTERNAL void clearlooks_treeview_get_header_index (GtkTreeView *tv, + GtkWidget *header, + gint *column_index, + gint *columns, + gboolean *resizable); + +GE_INTERNAL void clearlooks_clist_get_header_index (GtkCList *clist, + GtkWidget *button, + gint *column_index, + gint *columns); +#ifdef DEVELOPMENT +#warning clearlooks_get_parent_bg is a bad hack - find out why its needed, and figure out a better way. +#endif -GdkColor *get_parent_bgcolor (GtkWidget *widget); +GE_INTERNAL void clearlooks_get_parent_bg (const GtkWidget *widget, + CairoColor *color); -gboolean is_combo_box (GtkWidget * widget); +GE_INTERNAL ClearlooksStepper clearlooks_scrollbar_get_stepper (GtkWidget *widget, + GdkRectangle *stepper); +GE_INTERNAL ClearlooksStepper clearlooks_scrollbar_visible_steppers (GtkWidget *widget); +GE_INTERNAL ClearlooksJunction clearlooks_scrollbar_get_junction (GtkWidget *widget); -GtkWidget *find_combo_box_widget (GtkWidget * widget); +GE_INTERNAL void clearlooks_set_toolbar_parameters (ToolbarParameters *toolbar, GtkWidget *widget, GdkWindow *window, gint x, gint y); +GE_INTERNAL void clearlooks_get_notebook_tab_position (GtkWidget *widget, gboolean *start, gboolean *end); -void gtk_clist_get_header_index (GtkCList *clist, GtkWidget *button, - gint *column_index, gint *columns); +#endif /* SUPPORT_H */ diff --git a/libs/clearlooks/widget-information.c b/libs/clearlooks/widget-information.c new file mode 100644 index 0000000000..cbeb00e291 --- /dev/null +++ b/libs/clearlooks/widget-information.c @@ -0,0 +1,312 @@ +#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; +} + +static gboolean +ge_combo_box_is_using_list (GtkWidget * widget) +{ + gboolean result = FALSE; + + if (GE_IS_COMBO_BOX (widget)) + { + gboolean *tmp = NULL; + + gtk_widget_style_get (widget, "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; +} + +/*********************************************** + * 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; + gtk_requisition_free (tmp_size); + } + else + *indicator_size = default_size; + + if (tmp_spacing) + { + *indicator_spacing = *tmp_spacing; + gtk_border_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; + gtk_border_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/libs/clearlooks/widget-information.h b/libs/clearlooks/widget-information.h new file mode 100644 index 0000000000..55da859d78 --- /dev/null +++ b/libs/clearlooks/widget-information.h @@ -0,0 +1,99 @@ + +/* 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_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 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); + |