1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #include <gobject/gvaluecollector.h>
32 #include "gtkmarshalers.h"
35 #include "gtkspinbutton.h"
37 #include "gtkwidget.h"
38 #include "gtkthemes.h"
39 #include "gtkiconfactory.h"
40 #include "gtksettings.h" /* _gtk_settings_parse_convert() */
42 #include "gtkspinner.h"
47 * @Short_description: An object that hold style information for widgets
50 * A #GtkStyle object encapsulates the information that provides the look and
51 * feel for a widget. Each #GtkWidget has an associated #GTkStyle object that
52 * is used when rendering that widget. Also, a #GtkStyle holds information for
53 * the five possible widget states though not every widget supports all five
54 * states; see #GtkStateType.
56 * Usually the #GtkStyle for a widget is the same as the default style that is
57 * set by GTK+ and modified the theme engine.
59 * Usually applications should not need to use or modify the #GtkStyle of their
64 #define LIGHTNESS_MULT 1.3
65 #define DARKNESS_MULT 0.7
67 /* --- typedefs & structures --- */
74 #define GTK_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_STYLE, GtkStylePrivate))
76 typedef struct _GtkStylePrivate GtkStylePrivate;
78 struct _GtkStylePrivate {
82 /* --- prototypes --- */
83 static void gtk_style_finalize (GObject *object);
84 static void gtk_style_realize (GtkStyle *style,
85 GdkColormap *colormap);
86 static void gtk_style_real_realize (GtkStyle *style);
87 static void gtk_style_real_unrealize (GtkStyle *style);
88 static void gtk_style_real_copy (GtkStyle *style,
90 static void gtk_style_real_set_background (GtkStyle *style,
92 GtkStateType state_type);
93 static GtkStyle *gtk_style_real_clone (GtkStyle *style);
94 static void gtk_style_real_init_from_rc (GtkStyle *style,
95 GtkRcStyle *rc_style);
96 static GdkPixbuf *gtk_default_render_icon (GtkStyle *style,
97 const GtkIconSource *source,
98 GtkTextDirection direction,
102 const gchar *detail);
103 static void gtk_default_draw_hline (GtkStyle *style,
105 GtkStateType state_type,
112 static void gtk_default_draw_vline (GtkStyle *style,
114 GtkStateType state_type,
121 static void gtk_default_draw_shadow (GtkStyle *style,
123 GtkStateType state_type,
124 GtkShadowType shadow_type,
132 static void gtk_default_draw_arrow (GtkStyle *style,
134 GtkStateType state_type,
135 GtkShadowType shadow_type,
139 GtkArrowType arrow_type,
145 static void gtk_default_draw_diamond (GtkStyle *style,
147 GtkStateType state_type,
148 GtkShadowType shadow_type,
156 static void gtk_default_draw_box (GtkStyle *style,
158 GtkStateType state_type,
159 GtkShadowType shadow_type,
167 static void gtk_default_draw_flat_box (GtkStyle *style,
169 GtkStateType state_type,
170 GtkShadowType shadow_type,
178 static void gtk_default_draw_check (GtkStyle *style,
180 GtkStateType state_type,
181 GtkShadowType shadow_type,
189 static void gtk_default_draw_option (GtkStyle *style,
191 GtkStateType state_type,
192 GtkShadowType shadow_type,
200 static void gtk_default_draw_tab (GtkStyle *style,
202 GtkStateType state_type,
203 GtkShadowType shadow_type,
211 static void gtk_default_draw_shadow_gap (GtkStyle *style,
213 GtkStateType state_type,
214 GtkShadowType shadow_type,
222 GtkPositionType gap_side,
225 static void gtk_default_draw_box_gap (GtkStyle *style,
227 GtkStateType state_type,
228 GtkShadowType shadow_type,
236 GtkPositionType gap_side,
239 static void gtk_default_draw_extension (GtkStyle *style,
241 GtkStateType state_type,
242 GtkShadowType shadow_type,
250 GtkPositionType gap_side);
251 static void gtk_default_draw_focus (GtkStyle *style,
253 GtkStateType state_type,
261 static void gtk_default_draw_slider (GtkStyle *style,
263 GtkStateType state_type,
264 GtkShadowType shadow_type,
272 GtkOrientation orientation);
273 static void gtk_default_draw_handle (GtkStyle *style,
275 GtkStateType state_type,
276 GtkShadowType shadow_type,
284 GtkOrientation orientation);
285 static void gtk_default_draw_expander (GtkStyle *style,
287 GtkStateType state_type,
293 GtkExpanderStyle expander_style);
294 static void gtk_default_draw_layout (GtkStyle *style,
296 GtkStateType state_type,
303 PangoLayout *layout);
304 static void gtk_default_draw_resize_grip (GtkStyle *style,
306 GtkStateType state_type,
315 static void gtk_default_draw_spinner (GtkStyle *style,
317 GtkStateType state_type,
327 static void rgb_to_hls (gdouble *r,
330 static void hls_to_rgb (gdouble *h,
334 static void style_unrealize_cursors (GtkStyle *style);
337 * Data for default check and radio buttons
340 static const GtkRequisition default_option_indicator_size = { 7, 13 };
341 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
343 #define GTK_GRAY 0xdcdc, 0xdada, 0xd5d5
344 #define GTK_DARK_GRAY 0xc4c4, 0xc2c2, 0xbdbd
345 #define GTK_LIGHT_GRAY 0xeeee, 0xebeb, 0xe7e7
346 #define GTK_WHITE 0xffff, 0xffff, 0xffff
347 #define GTK_BLUE 0x4b4b, 0x6969, 0x8383
348 #define GTK_VERY_DARK_GRAY 0x9c9c, 0x9a9a, 0x9494
349 #define GTK_BLACK 0x0000, 0x0000, 0x0000
350 #define GTK_WEAK_GRAY 0x7530, 0x7530, 0x7530
352 /* --- variables --- */
353 static const GdkColor gtk_default_normal_fg = { 0, GTK_BLACK };
354 static const GdkColor gtk_default_active_fg = { 0, GTK_BLACK };
355 static const GdkColor gtk_default_prelight_fg = { 0, GTK_BLACK };
356 static const GdkColor gtk_default_selected_fg = { 0, GTK_WHITE };
357 static const GdkColor gtk_default_insensitive_fg = { 0, GTK_WEAK_GRAY };
359 static const GdkColor gtk_default_normal_bg = { 0, GTK_GRAY };
360 static const GdkColor gtk_default_active_bg = { 0, GTK_DARK_GRAY };
361 static const GdkColor gtk_default_prelight_bg = { 0, GTK_LIGHT_GRAY };
362 static const GdkColor gtk_default_selected_bg = { 0, GTK_BLUE };
363 static const GdkColor gtk_default_insensitive_bg = { 0, GTK_GRAY };
364 static const GdkColor gtk_default_selected_base = { 0, GTK_BLUE };
365 static const GdkColor gtk_default_active_base = { 0, GTK_VERY_DARK_GRAY };
367 /* --- signals --- */
368 static guint realize_signal = 0;
369 static guint unrealize_signal = 0;
371 G_DEFINE_TYPE (GtkStyle, gtk_style, G_TYPE_OBJECT)
373 /* --- functions --- */
376 * _gtk_style_init_for_settings:
377 * @style: a #GtkStyle
378 * @settings: a #GtkSettings
380 * Initializes the font description in @style according to the default
381 * font name of @settings. This is called for gtk_style_new() with
382 * the settings for the default screen (if any); if we are creating
383 * a style for a particular screen, we then call it again in a
384 * location where we know the correct settings.
385 * The reason for this is that gtk_rc_style_create_style() doesn't
386 * take the screen for an argument.
389 _gtk_style_init_for_settings (GtkStyle *style,
390 GtkSettings *settings)
392 const gchar *font_name = _gtk_rc_context_get_default_font_name (settings);
394 if (style->font_desc)
395 pango_font_description_free (style->font_desc);
397 style->font_desc = pango_font_description_from_string (font_name);
399 if (!pango_font_description_get_family (style->font_desc))
401 g_warning ("Default font does not have a family set");
402 pango_font_description_set_family (style->font_desc, "Sans");
404 if (pango_font_description_get_size (style->font_desc) <= 0)
406 g_warning ("Default font does not have a positive size");
407 pango_font_description_set_size (style->font_desc, 10 * PANGO_SCALE);
412 gtk_style_init (GtkStyle *style)
416 GtkSettings *settings = gtk_settings_get_default ();
419 _gtk_style_init_for_settings (style, settings);
421 style->font_desc = pango_font_description_from_string ("Sans 10");
423 style->attach_count = 0;
424 style->colormap = NULL;
427 style->black.red = 0;
428 style->black.green = 0;
429 style->black.blue = 0;
431 style->white.red = 65535;
432 style->white.green = 65535;
433 style->white.blue = 65535;
435 style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
436 style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
437 style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
438 style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
439 style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
441 style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
442 style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
443 style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
444 style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
445 style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
447 for (i = 0; i < 4; i++)
449 style->text[i] = style->fg[i];
450 style->base[i] = style->white;
453 style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
454 style->text[GTK_STATE_SELECTED] = style->white;
455 style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
456 style->text[GTK_STATE_ACTIVE] = style->white;
457 style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
458 style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
460 for (i = 0; i < 5; i++)
461 style->bg_pixmap[i] = NULL;
463 style->rc_style = NULL;
465 style->xthickness = 2;
466 style->ythickness = 2;
468 style->property_cache = NULL;
472 gtk_style_class_init (GtkStyleClass *klass)
474 GObjectClass *object_class = G_OBJECT_CLASS (klass);
476 object_class->finalize = gtk_style_finalize;
478 klass->clone = gtk_style_real_clone;
479 klass->copy = gtk_style_real_copy;
480 klass->init_from_rc = gtk_style_real_init_from_rc;
481 klass->realize = gtk_style_real_realize;
482 klass->unrealize = gtk_style_real_unrealize;
483 klass->set_background = gtk_style_real_set_background;
484 klass->render_icon = gtk_default_render_icon;
486 klass->draw_hline = gtk_default_draw_hline;
487 klass->draw_vline = gtk_default_draw_vline;
488 klass->draw_shadow = gtk_default_draw_shadow;
489 klass->draw_arrow = gtk_default_draw_arrow;
490 klass->draw_diamond = gtk_default_draw_diamond;
491 klass->draw_box = gtk_default_draw_box;
492 klass->draw_flat_box = gtk_default_draw_flat_box;
493 klass->draw_check = gtk_default_draw_check;
494 klass->draw_option = gtk_default_draw_option;
495 klass->draw_tab = gtk_default_draw_tab;
496 klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
497 klass->draw_box_gap = gtk_default_draw_box_gap;
498 klass->draw_extension = gtk_default_draw_extension;
499 klass->draw_focus = gtk_default_draw_focus;
500 klass->draw_slider = gtk_default_draw_slider;
501 klass->draw_handle = gtk_default_draw_handle;
502 klass->draw_expander = gtk_default_draw_expander;
503 klass->draw_layout = gtk_default_draw_layout;
504 klass->draw_resize_grip = gtk_default_draw_resize_grip;
505 klass->draw_spinner = gtk_default_draw_spinner;
507 g_type_class_add_private (object_class, sizeof (GtkStylePrivate));
511 * @style: the object which received the signal
513 * Emitted when the style has been initialized for a particular
514 * colormap and depth. Connecting to this signal is probably seldom
515 * useful since most of the time applications and widgets only
516 * deal with styles that have been already realized.
520 realize_signal = g_signal_new (I_("realize"),
521 G_TYPE_FROM_CLASS (object_class),
523 G_STRUCT_OFFSET (GtkStyleClass, realize),
525 _gtk_marshal_VOID__VOID,
528 * GtkStyle::unrealize:
529 * @style: the object which received the signal
531 * Emitted when the aspects of the style specific to a particular colormap
532 * and depth are being cleaned up. A connection to this signal can be useful
533 * if a widget wants to cache objects as object data on #GtkStyle.
534 * This signal provides a convenient place to free such cached objects.
538 unrealize_signal = g_signal_new (I_("unrealize"),
539 G_TYPE_FROM_CLASS (object_class),
541 G_STRUCT_OFFSET (GtkStyleClass, unrealize),
543 _gtk_marshal_VOID__VOID,
548 clear_property_cache (GtkStyle *style)
550 if (style->property_cache)
554 for (i = 0; i < style->property_cache->len; i++)
556 PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
558 g_param_spec_unref (node->pspec);
559 g_value_unset (&node->value);
561 g_array_free (style->property_cache, TRUE);
562 style->property_cache = NULL;
567 gtk_style_finalize (GObject *object)
569 GtkStyle *style = GTK_STYLE (object);
570 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
572 g_return_if_fail (style->attach_count == 0);
574 clear_property_cache (style);
576 /* All the styles in the list have the same
577 * style->styles pointer. If we delete the
578 * *first* style from the list, we need to update
579 * the style->styles pointers from all the styles.
580 * Otherwise we simply remove the node from
585 if (style->styles->data != style)
586 style->styles = g_slist_remove (style->styles, style);
589 GSList *tmp_list = style->styles->next;
593 GTK_STYLE (tmp_list->data)->styles = style->styles->next;
594 tmp_list = tmp_list->next;
596 g_slist_free_1 (style->styles);
600 g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
601 g_slist_free (style->icon_factories);
603 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
604 g_slist_free (priv->color_hashes);
606 pango_font_description_free (style->font_desc);
608 if (style->private_font_desc)
609 pango_font_description_free (style->private_font_desc);
612 g_object_unref (style->rc_style);
614 G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
620 * @style: a #GtkStyle
622 * Creates a copy of the passed in #GtkStyle object.
624 * Returns: a copy of @style
627 gtk_style_copy (GtkStyle *style)
631 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
633 new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
634 GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
640 gtk_style_duplicate (GtkStyle *style)
644 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
646 new_style = gtk_style_copy (style);
648 /* All the styles in the list have the same
649 * style->styles pointer. When we insert a new
650 * style, we append it to the list to avoid having
651 * to update the existing ones.
653 style->styles = g_slist_append (style->styles, new_style);
654 new_style->styles = style->styles;
661 * @returns: a new #GtkStyle.
663 * Creates a new #GtkStyle.
670 style = g_object_new (GTK_TYPE_STYLE, NULL);
677 * @style: a #GtkStyle.
678 * @window: a #GdkWindow.
680 * Attaches a style to a window; this process allocates the
681 * colors and creates the GC's for the style - it specializes
682 * it to a particular visual and colormap. The process may
683 * involve the creation of a new style if the style has already
684 * been attached to a window with a different style and colormap.
686 * Since this function may return a new object, you have to use it
687 * in the following way:
688 * <literal>style = gtk_style_attach (style, window)</literal>
690 * Returns: Either @style, or a newly-created #GtkStyle.
691 * If the style is newly created, the style parameter
692 * will be unref'ed, and the new style will have
693 * a reference count belonging to the caller.
696 gtk_style_attach (GtkStyle *style,
700 GtkStyle *new_style = NULL;
701 GdkColormap *colormap;
703 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
704 g_return_val_if_fail (window != NULL, NULL);
706 colormap = gdk_drawable_get_colormap (window);
709 style->styles = g_slist_append (NULL, style);
711 styles = style->styles;
714 new_style = styles->data;
716 if (new_style->colormap == colormap)
720 styles = styles->next;
725 styles = style->styles;
729 new_style = styles->data;
731 if (new_style->attach_count == 0)
733 gtk_style_realize (new_style, colormap);
738 styles = styles->next;
744 new_style = gtk_style_duplicate (style);
745 gtk_style_realize (new_style, colormap);
748 /* A style gets a refcount from being attached */
749 if (new_style->attach_count == 0)
750 g_object_ref (new_style);
752 /* Another refcount belongs to the parent */
753 if (style != new_style)
755 g_object_unref (style);
756 g_object_ref (new_style);
759 new_style->attach_count++;
766 * @style: a #GtkStyle
768 * Detaches a style from a window. If the style is not attached
769 * to any windows anymore, it is unrealized. See gtk_style_attach().
773 gtk_style_detach (GtkStyle *style)
775 g_return_if_fail (GTK_IS_STYLE (style));
776 g_return_if_fail (style->attach_count > 0);
778 style->attach_count -= 1;
779 if (style->attach_count == 0)
781 g_signal_emit (style, unrealize_signal, 0);
783 g_object_unref (style->colormap);
784 style->colormap = NULL;
786 if (style->private_font_desc)
788 pango_font_description_free (style->private_font_desc);
789 style->private_font_desc = NULL;
792 g_object_unref (style);
797 gtk_style_realize (GtkStyle *style,
798 GdkColormap *colormap)
800 style->colormap = g_object_ref (colormap);
801 style->depth = gdk_colormap_get_visual (colormap)->depth;
803 g_signal_emit (style, realize_signal, 0);
807 * gtk_style_lookup_icon_set:
808 * @style: a #GtkStyle
809 * @stock_id: an icon name
811 * Looks up @stock_id in the icon factories associated with @style
812 * and the default icon factory, returning an icon set if found,
815 * Return value: icon set of @stock_id
818 gtk_style_lookup_icon_set (GtkStyle *style,
819 const char *stock_id)
823 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
824 g_return_val_if_fail (stock_id != NULL, NULL);
826 iter = style->icon_factories;
829 GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
834 iter = g_slist_next (iter);
837 return gtk_icon_factory_lookup_default (stock_id);
841 * gtk_style_lookup_color:
842 * @style: a #GtkStyle
843 * @color_name: the name of the logical color to look up
844 * @color: the #GdkColor to fill in
846 * Looks up @color_name in the style's logical color mappings,
847 * filling in @color and returning %TRUE if found, otherwise
848 * returning %FALSE. Do not cache the found mapping, because
849 * it depends on the #GtkStyle and might change when a theme
852 * Return value: %TRUE if the mapping was found.
857 gtk_style_lookup_color (GtkStyle *style,
858 const char *color_name,
861 GtkStylePrivate *priv;
864 g_return_val_if_fail (GTK_IS_STYLE (style), FALSE);
865 g_return_val_if_fail (color_name != NULL, FALSE);
866 g_return_val_if_fail (color != NULL, FALSE);
868 priv = GTK_STYLE_GET_PRIVATE (style);
870 for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
872 GHashTable *hash = iter->data;
873 GdkColor *mapping = g_hash_table_lookup (hash, color_name);
877 color->red = mapping->red;
878 color->green = mapping->green;
879 color->blue = mapping->blue;
888 * gtk_style_set_background:
889 * @style: a #GtkStyle
890 * @window: a #GdkWindow
891 * @state_type: a state
893 * Sets the background of @window to the background color or pixmap
894 * specified by @style for the given state.
897 gtk_style_set_background (GtkStyle *style,
899 GtkStateType state_type)
901 g_return_if_fail (GTK_IS_STYLE (style));
902 g_return_if_fail (window != NULL);
904 GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
907 /* Default functions */
909 gtk_style_real_clone (GtkStyle *style)
911 return g_object_new (G_OBJECT_TYPE (style), NULL);
915 gtk_style_real_copy (GtkStyle *style,
918 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
919 GtkStylePrivate *src_priv = GTK_STYLE_GET_PRIVATE (src);
922 for (i = 0; i < 5; i++)
924 style->fg[i] = src->fg[i];
925 style->bg[i] = src->bg[i];
926 style->text[i] = src->text[i];
927 style->base[i] = src->base[i];
929 if (style->bg_pixmap[i])
930 g_object_unref (style->bg_pixmap[i]),
931 style->bg_pixmap[i] = src->bg_pixmap[i];
932 if (style->bg_pixmap[i])
933 g_object_ref (style->bg_pixmap[i]);
936 if (style->font_desc)
937 pango_font_description_free (style->font_desc);
939 style->font_desc = pango_font_description_copy (src->font_desc);
941 style->font_desc = NULL;
943 style->xthickness = src->xthickness;
944 style->ythickness = src->ythickness;
947 g_object_unref (style->rc_style);
948 style->rc_style = src->rc_style;
950 g_object_ref (src->rc_style);
952 g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
953 g_slist_free (style->icon_factories);
954 style->icon_factories = g_slist_copy (src->icon_factories);
955 g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
957 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
958 g_slist_free (priv->color_hashes);
959 priv->color_hashes = g_slist_copy (src_priv->color_hashes);
960 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
962 /* don't copy, just clear cache */
963 clear_property_cache (style);
967 gtk_style_real_init_from_rc (GtkStyle *style,
968 GtkRcStyle *rc_style)
970 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
973 /* cache _should_ be still empty */
974 clear_property_cache (style);
976 if (rc_style->font_desc)
977 pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
979 for (i = 0; i < 5; i++)
981 if (rc_style->color_flags[i] & GTK_RC_FG)
982 style->fg[i] = rc_style->fg[i];
983 if (rc_style->color_flags[i] & GTK_RC_BG)
984 style->bg[i] = rc_style->bg[i];
985 if (rc_style->color_flags[i] & GTK_RC_TEXT)
986 style->text[i] = rc_style->text[i];
987 if (rc_style->color_flags[i] & GTK_RC_BASE)
988 style->base[i] = rc_style->base[i];
991 if (rc_style->xthickness >= 0)
992 style->xthickness = rc_style->xthickness;
993 if (rc_style->ythickness >= 0)
994 style->ythickness = rc_style->ythickness;
996 style->icon_factories = g_slist_copy (rc_style->icon_factories);
997 g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
999 priv->color_hashes = g_slist_copy (_gtk_rc_style_get_color_hashes (rc_style));
1000 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
1004 style_property_values_cmp (gconstpointer bsearch_node1,
1005 gconstpointer bsearch_node2)
1007 const PropertyValue *val1 = bsearch_node1;
1008 const PropertyValue *val2 = bsearch_node2;
1010 if (val1->widget_type == val2->widget_type)
1011 return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1013 return val1->widget_type < val2->widget_type ? -1 : 1;
1017 * gtk_style_get_style_property:
1018 * @style: a #GtkStyle
1019 * @widget_type: the #GType of a descendant of #GtkWidget
1020 * @property_name: the name of the style property to get
1021 * @value: a #GValue where the value of the property being
1022 * queried will be stored
1024 * Queries the value of a style property corresponding to a
1025 * widget class is in the given style.
1030 gtk_style_get_style_property (GtkStyle *style,
1032 const gchar *property_name,
1035 GtkWidgetClass *klass;
1037 GtkRcPropertyParser parser;
1038 const GValue *peek_value;
1040 klass = g_type_class_ref (widget_type);
1041 pspec = gtk_widget_class_find_style_property (klass, property_name);
1042 g_type_class_unref (klass);
1046 g_warning ("%s: widget class `%s' has no property named `%s'",
1048 g_type_name (widget_type),
1053 parser = g_param_spec_get_qdata (pspec,
1054 g_quark_from_static_string ("gtk-rc-property-parser"));
1056 peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1058 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1059 g_value_copy (peek_value, value);
1060 else if (g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1061 g_value_transform (peek_value, value);
1063 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
1065 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1066 G_VALUE_TYPE_NAME (value));
1070 * gtk_style_get_valist:
1071 * @style: a #GtkStyle
1072 * @widget_type: the #GType of a descendant of #GtkWidget
1073 * @first_property_name: the name of the first style property to get
1074 * @var_args: a <type>va_list</type> of pairs of property names and
1075 * locations to return the property values, starting with the
1076 * location for @first_property_name.
1078 * Non-vararg variant of gtk_style_get().
1079 * Used primarily by language bindings.
1084 gtk_style_get_valist (GtkStyle *style,
1086 const gchar *first_property_name,
1089 const char *property_name;
1090 GtkWidgetClass *klass;
1092 g_return_if_fail (GTK_IS_STYLE (style));
1094 klass = g_type_class_ref (widget_type);
1096 property_name = first_property_name;
1097 while (property_name)
1100 GtkRcPropertyParser parser;
1101 const GValue *peek_value;
1104 pspec = gtk_widget_class_find_style_property (klass, property_name);
1108 g_warning ("%s: widget class `%s' has no property named `%s'",
1110 g_type_name (widget_type),
1115 parser = g_param_spec_get_qdata (pspec,
1116 g_quark_from_static_string ("gtk-rc-property-parser"));
1118 peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1119 G_VALUE_LCOPY (peek_value, var_args, 0, &error);
1122 g_warning ("%s: %s", G_STRLOC, error);
1127 property_name = va_arg (var_args, gchar*);
1130 g_type_class_unref (klass);
1135 * @style: a #GtkStyle
1136 * @widget_type: the #GType of a descendant of #GtkWidget
1137 * @first_property_name: the name of the first style property to get
1138 * @Varargs: pairs of property names and locations to
1139 * return the property values, starting with the location for
1140 * @first_property_name, terminated by %NULL.
1142 * Gets the values of a multiple style properties for @widget_type
1148 gtk_style_get (GtkStyle *style,
1150 const gchar *first_property_name,
1155 va_start (var_args, first_property_name);
1156 gtk_style_get_valist (style, widget_type, first_property_name, var_args);
1161 _gtk_style_peek_property_value (GtkStyle *style,
1164 GtkRcPropertyParser parser)
1166 PropertyValue *pcache, key = { 0, NULL, { 0, } };
1167 const GtkRcProperty *rcprop = NULL;
1170 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1171 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1172 g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1173 g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1175 key.widget_type = widget_type;
1178 /* need value cache array */
1179 if (!style->property_cache)
1180 style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1183 pcache = bsearch (&key,
1184 style->property_cache->data, style->property_cache->len,
1185 sizeof (PropertyValue), style_property_values_cmp);
1187 return &pcache->value;
1191 while (i < style->property_cache->len &&
1192 style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1195 g_array_insert_val (style->property_cache, i, key);
1196 pcache = &g_array_index (style->property_cache, PropertyValue, i);
1198 /* cache miss, initialize value type, then set contents */
1199 g_param_spec_ref (pcache->pspec);
1200 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1202 /* value provided by rc style? */
1203 if (style->rc_style)
1205 GQuark prop_quark = g_quark_from_string (pspec->name);
1209 rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1210 g_type_qname (widget_type),
1214 widget_type = g_type_parent (widget_type);
1216 while (g_type_is_a (widget_type, pspec->owner_type));
1219 /* when supplied by rc style, we need to convert */
1220 if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1221 pspec, &pcache->value))
1223 gchar *contents = g_strdup_value_contents (&rcprop->value);
1225 g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1226 rcprop->origin ? rcprop->origin : "(for origin information, set GTK_DEBUG)",
1227 g_type_name (pspec->owner_type), pspec->name,
1228 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1230 G_VALUE_TYPE_NAME (&rcprop->value));
1232 rcprop = NULL; /* needs default */
1235 /* not supplied by rc style (or conversion failed), revert to default */
1237 g_param_value_set_default (pspec, &pcache->value);
1239 return &pcache->value;
1243 load_bg_image (GdkColormap *colormap,
1245 const gchar *filename)
1247 if (strcmp (filename, "<parent>") == 0)
1248 return (GdkPixmap*) GDK_PARENT_RELATIVE;
1254 GdkScreen *screen = gdk_colormap_get_screen (colormap);
1256 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1260 pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
1261 gdk_pixbuf_get_width (pixbuf),
1262 gdk_pixbuf_get_height (pixbuf),
1263 gdk_colormap_get_visual (colormap)->depth);
1264 gdk_drawable_set_colormap (pixmap, colormap);
1266 cr = gdk_cairo_create (pixmap);
1268 gdk_cairo_set_source_color (cr, bg_color);
1271 gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
1275 g_object_unref (pixbuf);
1282 gtk_style_real_realize (GtkStyle *style)
1286 for (i = 0; i < 5; i++)
1288 _gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1289 _gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1291 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1292 style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1293 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1295 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1296 style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1297 style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1300 style->black.red = 0x0000;
1301 style->black.green = 0x0000;
1302 style->black.blue = 0x0000;
1304 style->white.red = 0xffff;
1305 style->white.green = 0xffff;
1306 style->white.blue = 0xffff;
1308 for (i = 0; i < 5; i++)
1310 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1311 style->bg_pixmap[i] = load_bg_image (style->colormap,
1313 style->rc_style->bg_pixmap_name[i]);
1318 gtk_style_real_unrealize (GtkStyle *style)
1322 for (i = 0; i < 5; i++)
1324 if (style->bg_pixmap[i] && style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1326 g_object_unref (style->bg_pixmap[i]);
1327 style->bg_pixmap[i] = NULL;
1332 style_unrealize_cursors (style);
1336 gtk_style_real_set_background (GtkStyle *style,
1338 GtkStateType state_type)
1341 gint parent_relative;
1343 if (style->bg_pixmap[state_type])
1345 if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1348 parent_relative = TRUE;
1352 pixmap = style->bg_pixmap[state_type];
1353 parent_relative = FALSE;
1356 gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1359 gdk_window_set_background (window, &style->bg[state_type]);
1363 * gtk_style_render_icon:
1364 * @style: a #GtkStyle
1365 * @source: the #GtkIconSource specifying the icon to render
1366 * @direction: a text direction
1368 * @size: (type int) the size to render the icon at. A size of
1369 * (GtkIconSize)-1 means render at the size of the source and
1371 * @widget: (allow-none): the widget
1372 * @detail: (allow-none): a style detail
1373 * @returns: a newly-created #GdkPixbuf containing the rendered icon
1375 * Renders the icon specified by @source at the given @size
1376 * according to the given parameters and returns the result in a
1380 gtk_style_render_icon (GtkStyle *style,
1381 const GtkIconSource *source,
1382 GtkTextDirection direction,
1386 const gchar *detail)
1390 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1391 g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1393 pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1394 size, widget, detail);
1396 g_return_val_if_fail (pixbuf != NULL, NULL);
1401 /* Default functions */
1404 * gtk_style_apply_default_background:
1409 * @area: (allow-none):
1416 gtk_style_apply_default_background (GtkStyle *style,
1419 GtkStateType state_type,
1420 const GdkRectangle *area,
1426 GdkRectangle new_rect, old_rect;
1432 old_rect.width = width;
1433 old_rect.height = height;
1435 if (!gdk_rectangle_intersect (area, &old_rect, &new_rect))
1442 new_rect.width = width;
1443 new_rect.height = height;
1446 if (!style->bg_pixmap[state_type] ||
1447 GDK_IS_PIXMAP (window) ||
1448 (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE))
1450 cairo_t *cr = gdk_cairo_create (window);
1452 if (style->bg_pixmap[state_type])
1454 gdk_cairo_set_source_pixmap (cr, style->bg_pixmap[state_type], 0, 0);
1455 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
1458 gdk_cairo_set_source_color (cr, &style->bg[state_type]);
1460 gdk_cairo_rectangle (cr, &new_rect);
1469 if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1470 gdk_window_set_back_pixmap (window, NULL, TRUE);
1472 gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE);
1475 gdk_window_clear_area (window,
1476 new_rect.x, new_rect.y,
1477 new_rect.width, new_rect.height);
1482 scale_or_ref (GdkPixbuf *src,
1486 if (width == gdk_pixbuf_get_width (src) &&
1487 height == gdk_pixbuf_get_height (src))
1489 return g_object_ref (src);
1493 return gdk_pixbuf_scale_simple (src,
1495 GDK_INTERP_BILINEAR);
1500 lookup_icon_size (GtkStyle *style,
1507 GtkSettings *settings;
1509 if (widget && gtk_widget_has_screen (widget))
1511 screen = gtk_widget_get_screen (widget);
1512 settings = gtk_settings_get_for_screen (screen);
1514 else if (style && style->colormap)
1516 screen = gdk_colormap_get_screen (style->colormap);
1517 settings = gtk_settings_get_for_screen (screen);
1521 settings = gtk_settings_get_default ();
1522 GTK_NOTE (MULTIHEAD,
1523 g_warning ("Using the default screen for gtk_default_render_icon()"));
1526 return gtk_icon_size_lookup_for_settings (settings, size, width, height);
1530 gtk_default_render_icon (GtkStyle *style,
1531 const GtkIconSource *source,
1532 GtkTextDirection direction,
1536 const gchar *detail)
1542 GdkPixbuf *base_pixbuf;
1544 /* Oddly, style can be NULL in this function, because
1545 * GtkIconSet can be used without a style and if so
1546 * it uses this function.
1549 base_pixbuf = gtk_icon_source_get_pixbuf (source);
1551 g_return_val_if_fail (base_pixbuf != NULL, NULL);
1553 if (size != (GtkIconSize) -1 && !lookup_icon_size(style, widget, size, &width, &height))
1555 g_warning (G_STRLOC ": invalid icon size '%d'", size);
1559 /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
1562 if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
1563 scaled = scale_or_ref (base_pixbuf, width, height);
1565 scaled = g_object_ref (base_pixbuf);
1567 /* If the state was wildcarded, then generate a state. */
1568 if (gtk_icon_source_get_state_wildcarded (source))
1570 if (state == GTK_STATE_INSENSITIVE)
1572 stated = gdk_pixbuf_copy (scaled);
1574 gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1577 g_object_unref (scaled);
1579 else if (state == GTK_STATE_PRELIGHT)
1581 stated = gdk_pixbuf_copy (scaled);
1583 gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1586 g_object_unref (scaled);
1600 sanitize_size (GdkWindow *window,
1604 if ((*width == -1) && (*height == -1))
1605 gdk_drawable_get_size (window, width, height);
1606 else if (*width == -1)
1607 gdk_drawable_get_size (window, width, NULL);
1608 else if (*height == -1)
1609 gdk_drawable_get_size (window, NULL, height);
1613 _cairo_draw_line (cairo_t *cr,
1622 gdk_cairo_set_source_color (cr, color);
1623 cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
1625 cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
1626 cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
1633 _cairo_draw_rectangle (cairo_t *cr,
1641 gdk_cairo_set_source_color (cr, color);
1645 cairo_rectangle (cr, x, y, width, height);
1650 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
1656 _cairo_draw_point (cairo_t *cr,
1661 gdk_cairo_set_source_color (cr, color);
1662 cairo_rectangle (cr, x, y, 1, 1);
1667 gtk_default_draw_hline (GtkStyle *style,
1669 GtkStateType state_type,
1672 const gchar *detail,
1678 gint thickness_light;
1679 gint thickness_dark;
1682 thickness_light = style->ythickness / 2;
1683 thickness_dark = style->ythickness - thickness_light;
1685 cr = gdk_cairo_create (window);
1686 cairo_set_line_width (cr, 1.0);
1690 gdk_cairo_rectangle (cr, area);
1694 if (detail && !strcmp (detail, "label"))
1696 if (state_type == GTK_STATE_INSENSITIVE)
1697 _cairo_draw_line (cr, &style->white, x1 + 1, y + 1, x2 + 1, y + 1);
1698 _cairo_draw_line (cr, &style->fg[state_type], x1, y, x2, y);
1702 for (i = 0; i < thickness_dark; i++)
1704 _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x2 - i - 1, y + i);
1705 _cairo_draw_line (cr, &style->light[state_type], x2 - i, y + i, x2, y + i);
1708 y += thickness_dark;
1709 for (i = 0; i < thickness_light; i++)
1711 _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
1712 _cairo_draw_line (cr, &style->light[state_type], x1 + thickness_light - i, y + i, x2, y + i);
1721 gtk_default_draw_vline (GtkStyle *style,
1723 GtkStateType state_type,
1726 const gchar *detail,
1732 gint thickness_light;
1733 gint thickness_dark;
1736 thickness_light = style->xthickness / 2;
1737 thickness_dark = style->xthickness - thickness_light;
1739 cr = gdk_cairo_create (window);
1740 cairo_set_line_width (cr, 1.0);
1744 gdk_cairo_rectangle (cr, area);
1748 for (i = 0; i < thickness_dark; i++)
1750 _cairo_draw_line (cr, &style->dark[state_type],
1751 x + i, y1, x + i, y2 - i - 1);
1752 _cairo_draw_line (cr, &style->light[state_type],
1753 x + i, y2 - i, x + i, y2);
1756 x += thickness_dark;
1757 for (i = 0; i < thickness_light; i++)
1759 _cairo_draw_line (cr, &style->dark[state_type],
1760 x + i, y1, x + i, y1 + thickness_light - i - 1);
1761 _cairo_draw_line (cr, &style->light[state_type],
1762 x + i, y1 + thickness_light - i, x + i, y2);
1769 draw_thin_shadow (GtkStyle *style,
1778 GdkColor *gc1, *gc2;
1780 gc1 = &style->light[state];
1781 gc2 = &style->dark[state];
1783 _cairo_draw_line (cr, gc1,
1784 x, y + height - 1, x + width - 1, y + height - 1);
1785 _cairo_draw_line (cr, gc1,
1786 x + width - 1, y, x + width - 1, y + height - 1);
1788 _cairo_draw_line (cr, gc2,
1789 x, y, x + width - 2, y);
1790 _cairo_draw_line (cr, gc2,
1791 x, y, x, y + height - 2);
1795 draw_spinbutton_shadow (GtkStyle *style,
1798 GtkTextDirection direction,
1806 if (direction == GTK_TEXT_DIR_LTR)
1808 _cairo_draw_line (cr, &style->dark[state],
1809 x, y, x + width - 1, y);
1810 _cairo_draw_line (cr, &style->black,
1811 x, y + 1, x + width - 2, y + 1);
1812 _cairo_draw_line (cr, &style->black,
1813 x + width - 2, y + 2, x + width - 2, y + height - 3);
1814 _cairo_draw_line (cr, &style->light[state],
1815 x + width - 1, y + 1, x + width - 1, y + height - 2);
1816 _cairo_draw_line (cr, &style->light[state],
1817 x, y + height - 1, x + width - 1, y + height - 1);
1818 _cairo_draw_line (cr, &style->bg[state],
1819 x, y + height - 2, x + width - 2, y + height - 2);
1820 _cairo_draw_line (cr, &style->black,
1821 x, y + 2, x, y + height - 3);
1825 _cairo_draw_line (cr, &style->dark[state],
1826 x, y, x + width - 1, y);
1827 _cairo_draw_line (cr, &style->dark[state],
1828 x, y + 1, x, y + height - 1);
1829 _cairo_draw_line (cr, &style->black,
1830 x + 1, y + 1, x + width - 1, y + 1);
1831 _cairo_draw_line (cr, &style->black,
1832 x + 1, y + 2, x + 1, y + height - 2);
1833 _cairo_draw_line (cr, &style->black,
1834 x + width - 1, y + 2, x + width - 1, y + height - 3);
1835 _cairo_draw_line (cr, &style->light[state],
1836 x + 1, y + height - 1, x + width - 1, y + height - 1);
1837 _cairo_draw_line (cr, &style->bg[state],
1838 x + 2, y + height - 2, x + width - 1, y + height - 2);
1843 draw_menu_shadow (GtkStyle *style,
1852 if (style->ythickness > 0)
1854 if (style->ythickness > 1)
1856 _cairo_draw_line (cr, &style->dark[state],
1857 x + 1, y + height - 2,
1858 x + width - 2, y + height - 2);
1859 _cairo_draw_line (cr, &style->black,
1860 x, y + height - 1, x + width - 1, y + height - 1);
1864 _cairo_draw_line (cr, &style->dark[state],
1865 x + 1, y + height - 1, x + width - 1, y + height - 1);
1869 if (style->xthickness > 0)
1871 if (style->xthickness > 1)
1873 _cairo_draw_line (cr, &style->dark[state],
1874 x + width - 2, y + 1,
1875 x + width - 2, y + height - 2);
1877 _cairo_draw_line (cr, &style->black,
1878 x + width - 1, y, x + width - 1, y + height - 1);
1882 _cairo_draw_line (cr, &style->dark[state],
1883 x + width - 1, y + 1, x + width - 1, y + height - 1);
1887 /* Light around top and left */
1889 if (style->ythickness > 0)
1890 _cairo_draw_line (cr, &style->black,
1891 x, y, x + width - 2, y);
1892 if (style->xthickness > 0)
1893 _cairo_draw_line (cr, &style->black,
1894 x, y, x, y + height - 2);
1896 if (style->ythickness > 1)
1897 _cairo_draw_line (cr, &style->light[state],
1898 x + 1, y + 1, x + width - 3, y + 1);
1899 if (style->xthickness > 1)
1900 _cairo_draw_line (cr, &style->light[state],
1901 x + 1, y + 1, x + 1, y + height - 3);
1904 static GtkTextDirection
1905 get_direction (GtkWidget *widget)
1907 GtkTextDirection dir;
1910 dir = gtk_widget_get_direction (widget);
1912 dir = GTK_TEXT_DIR_LTR;
1919 gtk_default_draw_shadow (GtkStyle *style,
1921 GtkStateType state_type,
1922 GtkShadowType shadow_type,
1925 const gchar *detail,
1932 GdkColor *gc1 = NULL;
1933 GdkColor *gc2 = NULL;
1934 gint thickness_light;
1935 gint thickness_dark;
1938 sanitize_size (window, &width, &height);
1940 cr = gdk_cairo_create (window);
1941 cairo_set_line_width (cr, 1.0);
1945 gdk_cairo_rectangle (cr, area);
1949 if (shadow_type == GTK_SHADOW_IN)
1951 if (detail && strcmp (detail, "buttondefault") == 0)
1953 _cairo_draw_rectangle (cr, &style->black, FALSE,
1954 x, y, width - 1, height - 1);
1959 if (detail && strcmp (detail, "trough") == 0)
1961 draw_thin_shadow (style, cr, state_type, area,
1962 x, y, width, height);
1967 if (GTK_IS_SPIN_BUTTON (widget) &&
1968 detail && strcmp (detail, "spinbutton") == 0)
1970 draw_spinbutton_shadow (style, cr, state_type,
1971 get_direction (widget), area, x, y, width, height);
1978 if (shadow_type == GTK_SHADOW_OUT && detail && strcmp (detail, "menu") == 0)
1980 draw_menu_shadow (style, cr, state_type, area, x, y, width, height);
1985 switch (shadow_type)
1987 case GTK_SHADOW_NONE:
1991 case GTK_SHADOW_ETCHED_IN:
1992 gc1 = &style->light[state_type];
1993 gc2 = &style->dark[state_type];
1995 case GTK_SHADOW_OUT:
1996 case GTK_SHADOW_ETCHED_OUT:
1997 gc1 = &style->dark[state_type];
1998 gc2 = &style->light[state_type];
2002 switch (shadow_type)
2004 case GTK_SHADOW_NONE:
2008 /* Light around right and bottom edge */
2010 if (style->ythickness > 0)
2011 _cairo_draw_line (cr, gc1,
2012 x, y + height - 1, x + width - 1, y + height - 1);
2013 if (style->xthickness > 0)
2014 _cairo_draw_line (cr, gc1,
2015 x + width - 1, y, x + width - 1, y + height - 1);
2017 if (style->ythickness > 1)
2018 _cairo_draw_line (cr, &style->bg[state_type],
2019 x + 1, y + height - 2, x + width - 2, y + height - 2);
2020 if (style->xthickness > 1)
2021 _cairo_draw_line (cr, &style->bg[state_type],
2022 x + width - 2, y + 1, x + width - 2, y + height - 2);
2024 /* Dark around left and top */
2026 if (style->ythickness > 1)
2027 _cairo_draw_line (cr, &style->black,
2028 x + 1, y + 1, x + width - 2, y + 1);
2029 if (style->xthickness > 1)
2030 _cairo_draw_line (cr, &style->black,
2031 x + 1, y + 1, x + 1, y + height - 2);
2033 if (style->ythickness > 0)
2034 _cairo_draw_line (cr, gc2,
2035 x, y, x + width - 1, y);
2036 if (style->xthickness > 0)
2037 _cairo_draw_line (cr, gc2,
2038 x, y, x, y + height - 1);
2041 case GTK_SHADOW_OUT:
2042 /* Dark around right and bottom edge */
2044 if (style->ythickness > 0)
2046 if (style->ythickness > 1)
2048 _cairo_draw_line (cr, gc1,
2049 x + 1, y + height - 2, x + width - 2, y + height - 2);
2050 _cairo_draw_line (cr, &style->black,
2051 x, y + height - 1, x + width - 1, y + height - 1);
2055 _cairo_draw_line (cr, gc1,
2056 x + 1, y + height - 1, x + width - 1, y + height - 1);
2060 if (style->xthickness > 0)
2062 if (style->xthickness > 1)
2064 _cairo_draw_line (cr, gc1,
2065 x + width - 2, y + 1, x + width - 2, y + height - 2);
2067 _cairo_draw_line (cr, &style->black,
2068 x + width - 1, y, x + width - 1, y + height - 1);
2072 _cairo_draw_line (cr, gc1,
2073 x + width - 1, y + 1, x + width - 1, y + height - 1);
2077 /* Light around top and left */
2079 if (style->ythickness > 0)
2080 _cairo_draw_line (cr, gc2,
2081 x, y, x + width - 2, y);
2082 if (style->xthickness > 0)
2083 _cairo_draw_line (cr, gc2,
2084 x, y, x, y + height - 2);
2086 if (style->ythickness > 1)
2087 _cairo_draw_line (cr, &style->bg[state_type],
2088 x + 1, y + 1, x + width - 3, y + 1);
2089 if (style->xthickness > 1)
2090 _cairo_draw_line (cr, &style->bg[state_type],
2091 x + 1, y + 1, x + 1, y + height - 3);
2094 case GTK_SHADOW_ETCHED_IN:
2095 case GTK_SHADOW_ETCHED_OUT:
2096 if (style->xthickness > 0)
2098 if (style->xthickness > 1)
2100 thickness_light = 1;
2103 for (i = 0; i < thickness_dark; i++)
2105 _cairo_draw_line (cr, gc1,
2109 y + height - i - 1);
2110 _cairo_draw_line (cr, gc2,
2114 y + height - i - 2);
2117 for (i = 0; i < thickness_light; i++)
2119 _cairo_draw_line (cr, gc1,
2120 x + thickness_dark + i,
2121 y + thickness_dark + i,
2122 x + thickness_dark + i,
2123 y + height - thickness_dark - i - 1);
2124 _cairo_draw_line (cr, gc2,
2125 x + width - thickness_light - i - 1,
2126 y + thickness_dark + i,
2127 x + width - thickness_light - i - 1,
2128 y + height - thickness_light - 1);
2133 _cairo_draw_line (cr,
2134 &style->dark[state_type],
2135 x, y, x, y + height);
2136 _cairo_draw_line (cr,
2137 &style->dark[state_type],
2138 x + width, y, x + width, y + height);
2142 if (style->ythickness > 0)
2144 if (style->ythickness > 1)
2146 thickness_light = 1;
2149 for (i = 0; i < thickness_dark; i++)
2151 _cairo_draw_line (cr, gc1,
2155 y + height - i - 1);
2157 _cairo_draw_line (cr, gc2,
2164 for (i = 0; i < thickness_light; i++)
2166 _cairo_draw_line (cr, gc1,
2167 x + thickness_dark + i,
2168 y + thickness_dark + i,
2169 x + width - thickness_dark - i - 2,
2170 y + thickness_dark + i);
2172 _cairo_draw_line (cr, gc2,
2173 x + thickness_dark + i,
2174 y + height - thickness_light - i - 1,
2175 x + width - thickness_light - 1,
2176 y + height - thickness_light - i - 1);
2181 _cairo_draw_line (cr,
2182 &style->dark[state_type],
2183 x, y, x + width, y);
2184 _cairo_draw_line (cr,
2185 &style->dark[state_type],
2186 x, y + height, x + width, y + height);
2193 if (shadow_type == GTK_SHADOW_IN &&
2194 GTK_IS_SPIN_BUTTON (widget) &&
2195 detail && strcmp (detail, "entry") == 0)
2197 if (get_direction (widget) == GTK_TEXT_DIR_LTR)
2199 _cairo_draw_line (cr,
2200 &style->base[state_type],
2201 x + width - 1, y + 2,
2202 x + width - 1, y + height - 3);
2203 _cairo_draw_line (cr,
2204 &style->base[state_type],
2205 x + width - 2, y + 2,
2206 x + width - 2, y + height - 3);
2208 _cairo_draw_point (cr,
2210 x + width - 1, y + 1);
2211 _cairo_draw_point (cr,
2212 &style->bg[state_type],
2213 x + width - 1, y + height - 2);
2217 _cairo_draw_line (cr,
2218 &style->base[state_type],
2221 _cairo_draw_line (cr,
2222 &style->base[state_type],
2224 x + 1, y + height - 3);
2226 _cairo_draw_point (cr,
2230 _cairo_draw_line (cr,
2231 &style->bg[state_type],
2233 x + 1, y + height - 2);
2234 _cairo_draw_point (cr,
2235 &style->light[state_type],
2245 draw_arrow (cairo_t *cr,
2247 GtkArrowType arrow_type,
2253 gdk_cairo_set_source_color (cr, color);
2256 if (arrow_type == GTK_ARROW_DOWN)
2258 cairo_move_to (cr, x, y);
2259 cairo_line_to (cr, x + width, y);
2260 cairo_line_to (cr, x + width / 2., y + height);
2262 else if (arrow_type == GTK_ARROW_UP)
2264 cairo_move_to (cr, x, y + height);
2265 cairo_line_to (cr, x + width / 2., y);
2266 cairo_line_to (cr, x + width, y + height);
2268 else if (arrow_type == GTK_ARROW_LEFT)
2270 cairo_move_to (cr, x + width, y);
2271 cairo_line_to (cr, x + width, y + height);
2272 cairo_line_to (cr, x, y + height / 2.);
2274 else if (arrow_type == GTK_ARROW_RIGHT)
2276 cairo_move_to (cr, x, y);
2277 cairo_line_to (cr, x + width, y + height / 2.);
2278 cairo_line_to (cr, x, y + height);
2281 cairo_close_path (cr);
2288 calculate_arrow_geometry (GtkArrowType arrow_type,
2300 case GTK_ARROW_DOWN:
2310 if (arrow_type == GTK_ARROW_DOWN)
2312 if (*height % 2 == 1 || h % 2 == 0)
2317 if (*height % 2 == 0 || h % 2 == 0)
2322 case GTK_ARROW_RIGHT:
2323 case GTK_ARROW_LEFT:
2333 if (arrow_type == GTK_ARROW_RIGHT)
2335 if (*width % 2 == 1 || w % 2 == 0)
2340 if (*width % 2 == 0 || w % 2 == 0)
2346 /* should not be reached */
2350 *x += (*width - w) / 2;
2351 *y += (*height - h) / 2;
2357 gtk_default_draw_arrow (GtkStyle *style,
2360 GtkShadowType shadow,
2363 const gchar *detail,
2364 GtkArrowType arrow_type,
2373 sanitize_size (window, &width, &height);
2375 calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
2377 if (detail && strcmp (detail, "menu_scroll_arrow_up") == 0)
2380 cr = gdk_cairo_create (window);
2384 gdk_cairo_rectangle (cr, area);
2388 if (state == GTK_STATE_INSENSITIVE)
2389 draw_arrow (cr, &style->white, arrow_type,
2390 x + 1, y + 1, width, height);
2391 draw_arrow (cr, &style->fg[state], arrow_type,
2392 x, y, width, height);
2398 gtk_default_draw_diamond (GtkStyle *style,
2400 GtkStateType state_type,
2401 GtkShadowType shadow_type,
2404 const gchar *detail,
2412 GdkColor *outer_nw = NULL;
2413 GdkColor *outer_ne = NULL;
2414 GdkColor *outer_sw = NULL;
2415 GdkColor *outer_se = NULL;
2416 GdkColor *middle_nw = NULL;
2417 GdkColor *middle_ne = NULL;
2418 GdkColor *middle_sw = NULL;
2419 GdkColor *middle_se = NULL;
2420 GdkColor *inner_nw = NULL;
2421 GdkColor *inner_ne = NULL;
2422 GdkColor *inner_sw = NULL;
2423 GdkColor *inner_se = NULL;
2426 sanitize_size (window, &width, &height);
2428 half_width = width / 2;
2429 half_height = height / 2;
2431 switch (shadow_type)
2434 inner_sw = inner_se = &style->bg[state_type];
2435 middle_sw = middle_se = &style->light[state_type];
2436 outer_sw = outer_se = &style->light[state_type];
2437 inner_nw = inner_ne = &style->black;
2438 middle_nw = middle_ne = &style->dark[state_type];
2439 outer_nw = outer_ne = &style->dark[state_type];
2442 case GTK_SHADOW_OUT:
2443 inner_sw = inner_se = &style->dark[state_type];
2444 middle_sw = middle_se = &style->dark[state_type];
2445 outer_sw = outer_se = &style->black;
2446 inner_nw = inner_ne = &style->bg[state_type];
2447 middle_nw = middle_ne = &style->light[state_type];
2448 outer_nw = outer_ne = &style->light[state_type];
2451 case GTK_SHADOW_ETCHED_IN:
2452 inner_sw = inner_se = &style->bg[state_type];
2453 middle_sw = middle_se = &style->dark[state_type];
2454 outer_sw = outer_se = &style->light[state_type];
2455 inner_nw = inner_ne = &style->bg[state_type];
2456 middle_nw = middle_ne = &style->light[state_type];
2457 outer_nw = outer_ne = &style->dark[state_type];
2460 case GTK_SHADOW_ETCHED_OUT:
2461 inner_sw = inner_se = &style->bg[state_type];
2462 middle_sw = middle_se = &style->light[state_type];
2463 outer_sw = outer_se = &style->dark[state_type];
2464 inner_nw = inner_ne = &style->bg[state_type];
2465 middle_nw = middle_ne = &style->dark[state_type];
2466 outer_nw = outer_ne = &style->light[state_type];
2474 cr = gdk_cairo_create (window);
2477 gdk_cairo_rectangle (cr, area);
2483 _cairo_draw_line (cr, inner_sw,
2484 x + 2, y + half_height,
2485 x + half_width, y + height - 2);
2486 _cairo_draw_line (cr, inner_se,
2487 x + half_width, y + height - 2,
2488 x + width - 2, y + half_height);
2489 _cairo_draw_line (cr, middle_sw,
2490 x + 1, y + half_height,
2491 x + half_width, y + height - 1);
2492 _cairo_draw_line (cr, middle_se,
2493 x + half_width, y + height - 1,
2494 x + width - 1, y + half_height);
2495 _cairo_draw_line (cr, outer_sw,
2497 x + half_width, y + height);
2498 _cairo_draw_line (cr, outer_se,
2499 x + half_width, y + height,
2500 x + width, y + half_height);
2502 _cairo_draw_line (cr, inner_nw,
2503 x + 2, y + half_height,
2504 x + half_width, y + 2);
2505 _cairo_draw_line (cr, inner_ne,
2506 x + half_width, y + 2,
2507 x + width - 2, y + half_height);
2508 _cairo_draw_line (cr, middle_nw,
2509 x + 1, y + half_height,
2510 x + half_width, y + 1);
2511 _cairo_draw_line (cr, middle_ne,
2512 x + half_width, y + 1,
2513 x + width - 1, y + half_height);
2514 _cairo_draw_line (cr, outer_nw,
2517 _cairo_draw_line (cr, outer_ne,
2519 x + width, y + half_height);
2526 option_menu_get_props (GtkWidget *widget,
2527 GtkRequisition *indicator_size,
2528 GtkBorder *indicator_spacing)
2530 GtkRequisition *tmp_size = NULL;
2531 GtkBorder *tmp_spacing = NULL;
2535 *indicator_size = *tmp_size;
2536 gtk_requisition_free (tmp_size);
2539 *indicator_size = default_option_indicator_size;
2543 *indicator_spacing = *tmp_spacing;
2544 gtk_border_free (tmp_spacing);
2547 *indicator_spacing = default_option_indicator_spacing;
2551 gtk_default_draw_box (GtkStyle *style,
2553 GtkStateType state_type,
2554 GtkShadowType shadow_type,
2557 const gchar *detail,
2563 gboolean is_spinbutton_box = FALSE;
2565 sanitize_size (window, &width, &height);
2567 if (GTK_IS_SPIN_BUTTON (widget) && detail)
2569 if (strcmp (detail, "spinbutton_up") == 0)
2575 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2580 is_spinbutton_box = TRUE;
2582 else if (strcmp (detail, "spinbutton_down") == 0)
2587 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2592 is_spinbutton_box = TRUE;
2596 if (!style->bg_pixmap[state_type] ||
2597 GDK_IS_PIXMAP (window))
2600 GdkColor *gc = &style->bg[state_type];
2602 cr = gdk_cairo_create (window);
2604 if (state_type == GTK_STATE_SELECTED && detail && strcmp (detail, "paned") == 0)
2606 if (widget && !gtk_widget_has_focus (widget))
2607 gc = &style->base[GTK_STATE_ACTIVE];
2612 gdk_cairo_rectangle (cr, area);
2616 _cairo_draw_rectangle (cr, gc, TRUE,
2617 x, y, width, height);
2621 gtk_style_apply_default_background (style, window,
2622 widget && gtk_widget_get_has_window (widget),
2623 state_type, area, x, y, width, height);
2625 if (is_spinbutton_box)
2631 cr = gdk_cairo_create (window);
2633 lower = &style->dark[state_type];
2634 if (shadow_type == GTK_SHADOW_OUT)
2635 upper = &style->light[state_type];
2637 upper = &style->dark[state_type];
2641 gdk_cairo_rectangle (cr, area);
2645 _cairo_draw_line (cr, upper, x, y, x + width - 1, y);
2646 _cairo_draw_line (cr, lower, x, y + height - 1, x + width - 1, y + height - 1);
2652 gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
2653 x, y, width, height);
2655 if (detail && strcmp (detail, "optionmenu") == 0)
2657 GtkRequisition indicator_size;
2658 GtkBorder indicator_spacing;
2661 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2663 sanitize_size (window, &width, &height);
2665 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2666 vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
2668 vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
2670 gtk_paint_vline (style, window, state_type, area, widget,
2672 y + style->ythickness + 1,
2673 y + height - style->ythickness - 3,
2679 get_darkened (const GdkColor *color,
2682 GdkColor src = *color;
2683 GdkColor shaded = *color;
2685 while (darken_count)
2687 _gtk_style_shade (&src, &shaded, 0.93);
2692 return gdk_color_copy (&shaded);
2696 gtk_default_draw_flat_box (GtkStyle *style,
2698 GtkStateType state_type,
2699 GtkShadowType shadow_type,
2702 const gchar *detail,
2709 GdkColor *freeme = NULL;
2711 sanitize_size (window, &width, &height);
2715 if (state_type == GTK_STATE_SELECTED)
2717 if (!strcmp ("text", detail))
2718 gc1 = &style->bg[GTK_STATE_SELECTED];
2719 else if (!strcmp ("cell_even", detail) ||
2720 !strcmp ("cell_odd", detail) ||
2721 !strcmp ("cell_even_ruled", detail) ||
2722 !strcmp ("cell_even_ruled_sorted", detail))
2724 /* This has to be really broken; alex made me do it. -jrb */
2725 if (widget && gtk_widget_has_focus (widget))
2726 gc1 = &style->base[state_type];
2728 gc1 = &style->base[GTK_STATE_ACTIVE];
2730 else if (!strcmp ("cell_odd_ruled", detail) ||
2731 !strcmp ("cell_odd_ruled_sorted", detail))
2733 if (widget && gtk_widget_has_focus (widget))
2734 freeme = get_darkened (&style->base[state_type], 1);
2736 freeme = get_darkened (&style->base[GTK_STATE_ACTIVE], 1);
2741 gc1 = &style->bg[state_type];
2746 if (!strcmp ("viewportbin", detail))
2747 gc1 = &style->bg[GTK_STATE_NORMAL];
2748 else if (!strcmp ("entry_bg", detail))
2749 gc1 = &style->base[state_type];
2751 /* For trees: even rows are base color, odd rows are a shade of
2752 * the base color, the sort column is a shade of the original color
2756 else if (!strcmp ("cell_even", detail) ||
2757 !strcmp ("cell_odd", detail) ||
2758 !strcmp ("cell_even_ruled", detail))
2760 GdkColor *color = NULL;
2762 gtk_widget_style_get (widget,
2763 "even-row-color", &color,
2768 freeme = get_darkened (color, 0);
2771 gdk_color_free (color);
2774 gc1 = &style->base[state_type];
2776 else if (!strcmp ("cell_odd_ruled", detail))
2778 GdkColor *color = NULL;
2780 gtk_widget_style_get (widget,
2781 "odd-row-color", &color,
2786 freeme = get_darkened (color, 0);
2789 gdk_color_free (color);
2793 gtk_widget_style_get (widget,
2794 "even-row-color", &color,
2799 freeme = get_darkened (color, 1);
2800 gdk_color_free (color);
2803 freeme = get_darkened (&style->base[state_type], 1);
2807 else if (!strcmp ("cell_even_sorted", detail) ||
2808 !strcmp ("cell_odd_sorted", detail) ||
2809 !strcmp ("cell_even_ruled_sorted", detail))
2811 GdkColor *color = NULL;
2813 if (!strcmp ("cell_odd_sorted", detail))
2814 gtk_widget_style_get (widget,
2815 "odd-row-color", &color,
2818 gtk_widget_style_get (widget,
2819 "even-row-color", &color,
2824 freeme = get_darkened (color, 1);
2827 gdk_color_free (color);
2831 freeme = get_darkened (&style->base[state_type], 1);
2835 else if (!strcmp ("cell_odd_ruled_sorted", detail))
2837 GdkColor *color = NULL;
2839 gtk_widget_style_get (widget,
2840 "odd-row-color", &color,
2845 freeme = get_darkened (color, 1);
2848 gdk_color_free (color);
2852 gtk_widget_style_get (widget,
2853 "even-row-color", &color,
2858 freeme = get_darkened (color, 2);
2859 gdk_color_free (color);
2862 freeme = get_darkened (&style->base[state_type], 2);
2867 gc1 = &style->bg[state_type];
2871 gc1 = &style->bg[state_type];
2873 if (!style->bg_pixmap[state_type] || gc1 != &style->bg[state_type] ||
2874 GDK_IS_PIXMAP (window))
2878 cr = gdk_cairo_create (window);
2879 cairo_set_line_width (cr, 1.0);
2883 gdk_cairo_rectangle (cr, area);
2887 _cairo_draw_rectangle (cr, gc1, TRUE,
2888 x, y, width, height);
2890 if (detail && !strcmp ("tooltip", detail))
2891 _cairo_draw_rectangle (cr, &style->black, FALSE,
2892 x, y, width - 1, height - 1);
2897 gtk_style_apply_default_background (style, window,
2898 widget && gtk_widget_get_has_window (widget),
2899 state_type, area, x, y, width, height);
2903 gdk_color_free (freeme);
2907 gtk_default_draw_check (GtkStyle *style,
2909 GtkStateType state_type,
2910 GtkShadowType shadow_type,
2913 const gchar *detail,
2919 cairo_t *cr = gdk_cairo_create (window);
2920 enum { BUTTON, MENU, CELL } type = BUTTON;
2927 if (strcmp (detail, "cellcheck") == 0)
2929 else if (strcmp (detail, "check") == 0)
2935 gdk_cairo_rectangle (cr, area);
2939 exterior_size = MIN (width, height);
2940 if (exterior_size % 2 == 0) /* Ensure odd */
2943 pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
2944 interior_size = MAX (1, exterior_size - 2 * pad);
2946 if (interior_size < 7)
2949 pad = MAX (0, (exterior_size - interior_size) / 2);
2952 x -= (1 + exterior_size - width) / 2;
2953 y -= (1 + exterior_size - height) / 2;
2960 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2962 gdk_cairo_set_source_color (cr, &style->text[state_type]);
2964 cairo_set_line_width (cr, 1.0);
2965 cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1);
2968 gdk_cairo_set_source_color (cr, &style->base[state_type]);
2969 cairo_rectangle (cr, x + 1, y + 1, exterior_size - 2, exterior_size - 2);
2981 gdk_cairo_set_source_color (cr, &style->text[state_type]);
2984 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2988 if (shadow_type == GTK_SHADOW_IN)
2990 cairo_translate (cr,
2993 cairo_scale (cr, interior_size / 7., interior_size / 7.);
2995 cairo_move_to (cr, 7.0, 0.0);
2996 cairo_line_to (cr, 7.5, 1.0);
2997 cairo_curve_to (cr, 5.3, 2.0,
3000 cairo_curve_to (cr, 3.0, 5.7,
3003 cairo_line_to (cr, 0.2, 3.5);
3004 cairo_curve_to (cr, 1.1, 3.5,
3007 cairo_curve_to (cr, 1.0, 3.9,
3010 cairo_curve_to (cr, 3.5, 3.1,
3016 else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3018 int line_thickness = MAX (1, (3 + interior_size * 2) / 7);
3020 cairo_rectangle (cr,
3022 y + pad + (1 + interior_size - line_thickness) / 2,
3032 gtk_default_draw_option (GtkStyle *style,
3034 GtkStateType state_type,
3035 GtkShadowType shadow_type,
3038 const gchar *detail,
3044 cairo_t *cr = gdk_cairo_create (window);
3045 enum { BUTTON, MENU, CELL } type = BUTTON;
3050 if (strcmp (detail, "radio") == 0)
3052 else if (strcmp (detail, "option") == 0)
3058 gdk_cairo_rectangle (cr, area);
3062 exterior_size = MIN (width, height);
3063 if (exterior_size % 2 == 0) /* Ensure odd */
3066 x -= (1 + exterior_size - width) / 2;
3067 y -= (1 + exterior_size - height) / 2;
3073 gdk_cairo_set_source_color (cr, &style->base[state_type]);
3076 x + exterior_size / 2.,
3077 y + exterior_size / 2.,
3078 (exterior_size - 1) / 2.,
3081 cairo_fill_preserve (cr);
3084 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3086 gdk_cairo_set_source_color (cr, &style->text[state_type]);
3088 cairo_set_line_width (cr, 1.);
3099 gdk_cairo_set_source_color (cr, &style->text[state_type]);
3104 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3108 if (shadow_type == GTK_SHADOW_IN)
3110 int pad = style->xthickness + MAX (1, 2 * (exterior_size - 2 * style->xthickness) / 9);
3111 int interior_size = MAX (1, exterior_size - 2 * pad);
3113 if (interior_size < 5)
3116 pad = MAX (0, (exterior_size - interior_size) / 2);
3120 x + pad + interior_size / 2.,
3121 y + pad + interior_size / 2.,
3126 else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3128 int pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
3129 int interior_size = MAX (1, exterior_size - 2 * pad);
3132 if (interior_size < 7)
3135 pad = MAX (0, (exterior_size - interior_size) / 2);
3138 line_thickness = MAX (1, (3 + interior_size * 2) / 7);
3140 cairo_rectangle (cr,
3142 y + pad + (interior_size - line_thickness) / 2.,
3152 gtk_default_draw_tab (GtkStyle *style,
3154 GtkStateType state_type,
3155 GtkShadowType shadow_type,
3158 const gchar *detail,
3164 #define ARROW_SPACE 4
3167 GtkRequisition indicator_size;
3168 GtkBorder indicator_spacing;
3171 cr = gdk_cairo_create (window);
3175 gdk_cairo_rectangle (cr, area);
3179 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3181 indicator_size.width += (indicator_size.width % 2) - 1;
3182 arrow_height = indicator_size.width / 2 + 1;
3184 x += (width - indicator_size.width) / 2;
3185 y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3187 if (state_type == GTK_STATE_INSENSITIVE)
3189 draw_arrow (cr, &style->white,
3190 GTK_ARROW_UP, x + 1, y + 1,
3191 indicator_size.width, arrow_height);
3193 draw_arrow (cr, &style->white,
3194 GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3195 indicator_size.width, arrow_height);
3198 draw_arrow (cr, &style->fg[state_type],
3200 indicator_size.width, arrow_height);
3203 draw_arrow (cr, &style->fg[state_type],
3204 GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3205 indicator_size.width, arrow_height);
3211 gtk_default_draw_shadow_gap (GtkStyle *style,
3213 GtkStateType state_type,
3214 GtkShadowType shadow_type,
3217 const gchar *detail,
3222 GtkPositionType gap_side,
3226 GdkColor *color1 = NULL;
3227 GdkColor *color2 = NULL;
3228 GdkColor *color3 = NULL;
3229 GdkColor *color4 = NULL;
3232 sanitize_size (window, &width, &height);
3234 switch (shadow_type)
3236 case GTK_SHADOW_NONE:
3240 color1 = &style->dark[state_type];
3241 color2 = &style->black;
3242 color3 = &style->bg[state_type];
3243 color4 = &style->light[state_type];
3245 case GTK_SHADOW_ETCHED_IN:
3246 color1 = &style->dark[state_type];
3247 color2 = &style->light[state_type];
3248 color3 = &style->dark[state_type];
3249 color4 = &style->light[state_type];
3251 case GTK_SHADOW_OUT:
3252 color1 = &style->light[state_type];
3253 color2 = &style->bg[state_type];
3254 color3 = &style->dark[state_type];
3255 color4 = &style->black;
3257 case GTK_SHADOW_ETCHED_OUT:
3258 color1 = &style->light[state_type];
3259 color2 = &style->dark[state_type];
3260 color3 = &style->light[state_type];
3261 color4 = &style->dark[state_type];
3265 cr = gdk_cairo_create (window);
3268 gdk_cairo_rectangle (cr, area);
3272 switch (shadow_type)
3274 case GTK_SHADOW_NONE:
3276 case GTK_SHADOW_OUT:
3277 case GTK_SHADOW_ETCHED_IN:
3278 case GTK_SHADOW_ETCHED_OUT:
3282 _cairo_draw_line (cr, color1,
3283 x, y, x, y + height - 1);
3284 _cairo_draw_line (cr, color2,
3285 x + 1, y, x + 1, y + height - 2);
3287 _cairo_draw_line (cr, color3,
3288 x + 1, y + height - 2, x + width - 2, y + height - 2);
3289 _cairo_draw_line (cr, color3,
3290 x + width - 2, y, x + width - 2, y + height - 2);
3291 _cairo_draw_line (cr, color4,
3292 x, y + height - 1, x + width - 1, y + height - 1);
3293 _cairo_draw_line (cr, color4,
3294 x + width - 1, y, x + width - 1, y + height - 1);
3297 _cairo_draw_line (cr, color1,
3298 x, y, x + gap_x - 1, y);
3299 _cairo_draw_line (cr, color2,
3300 x + 1, y + 1, x + gap_x - 1, y + 1);
3301 _cairo_draw_line (cr, color2,
3302 x + gap_x, y, x + gap_x, y);
3304 if ((width - (gap_x + gap_width)) > 0)
3306 _cairo_draw_line (cr, color1,
3307 x + gap_x + gap_width, y, x + width - 2, y);
3308 _cairo_draw_line (cr, color2,
3309 x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3310 _cairo_draw_line (cr, color2,
3311 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3314 case GTK_POS_BOTTOM:
3315 _cairo_draw_line (cr, color1,
3316 x, y, x + width - 1, y);
3317 _cairo_draw_line (cr, color1,
3318 x, y, x, y + height - 1);
3319 _cairo_draw_line (cr, color2,
3320 x + 1, y + 1, x + width - 2, y + 1);
3321 _cairo_draw_line (cr, color2,
3322 x + 1, y + 1, x + 1, y + height - 1);
3324 _cairo_draw_line (cr, color3,
3325 x + width - 2, y + 1, x + width - 2, y + height - 1);
3326 _cairo_draw_line (cr, color4,
3327 x + width - 1, y, x + width - 1, y + height - 1);
3330 _cairo_draw_line (cr, color4,
3331 x, y + height - 1, x + gap_x - 1, y + height - 1);
3332 _cairo_draw_line (cr, color3,
3333 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3334 _cairo_draw_line (cr, color3,
3335 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3337 if ((width - (gap_x + gap_width)) > 0)
3339 _cairo_draw_line (cr, color4,
3340 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3341 _cairo_draw_line (cr, color3,
3342 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3343 _cairo_draw_line (cr, color3,
3344 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3348 _cairo_draw_line (cr, color1,
3349 x, y, x + width - 1, y);
3350 _cairo_draw_line (cr, color2,
3351 x, y + 1, x + width - 2, y + 1);
3353 _cairo_draw_line (cr, color3,
3354 x, y + height - 2, x + width - 2, y + height - 2);
3355 _cairo_draw_line (cr, color3,
3356 x + width - 2, y + 1, x + width - 2, y + height - 2);
3357 _cairo_draw_line (cr, color4,
3358 x, y + height - 1, x + width - 1, y + height - 1);
3359 _cairo_draw_line (cr, color4,
3360 x + width - 1, y, x + width - 1, y + height - 1);
3363 _cairo_draw_line (cr, color1,
3364 x, y, x, y + gap_x - 1);
3365 _cairo_draw_line (cr, color2,
3366 x + 1, y + 1, x + 1, y + gap_x - 1);
3367 _cairo_draw_line (cr, color2,
3368 x, y + gap_x, x, y + gap_x);
3370 if ((width - (gap_x + gap_width)) > 0)
3372 _cairo_draw_line (cr, color1,
3373 x, y + gap_x + gap_width, x, y + height - 2);
3374 _cairo_draw_line (cr, color2,
3375 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3376 _cairo_draw_line (cr, color2,
3377 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3381 _cairo_draw_line (cr, color1,
3382 x, y, x + width - 1, y);
3383 _cairo_draw_line (cr, color1,
3384 x, y, x, y + height - 1);
3385 _cairo_draw_line (cr, color2,
3386 x + 1, y + 1, x + width - 1, y + 1);
3387 _cairo_draw_line (cr, color2,
3388 x + 1, y + 1, x + 1, y + height - 2);
3390 _cairo_draw_line (cr, color3,
3391 x + 1, y + height - 2, x + width - 1, y + height - 2);
3392 _cairo_draw_line (cr, color4,
3393 x, y + height - 1, x + width - 1, y + height - 1);
3396 _cairo_draw_line (cr, color4,
3397 x + width - 1, y, x + width - 1, y + gap_x - 1);
3398 _cairo_draw_line (cr, color3,
3399 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3400 _cairo_draw_line (cr, color3,
3401 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3403 if ((width - (gap_x + gap_width)) > 0)
3405 _cairo_draw_line (cr, color4,
3406 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3407 _cairo_draw_line (cr, color3,
3408 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3409 _cairo_draw_line (cr, color3,
3410 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3420 gtk_default_draw_box_gap (GtkStyle *style,
3422 GtkStateType state_type,
3423 GtkShadowType shadow_type,
3426 const gchar *detail,
3431 GtkPositionType gap_side,
3441 sanitize_size (window, &width, &height);
3443 gtk_style_apply_default_background (style, window,
3444 widget && gtk_widget_get_has_window (widget),
3445 state_type, area, x, y, width, height);
3447 cr = gdk_cairo_create (window);
3450 gdk_cairo_rectangle (cr, area);
3454 switch (shadow_type)
3456 case GTK_SHADOW_NONE:
3460 color1 = style->dark[state_type];
3461 color2 = style->black;
3462 color3 = style->bg[state_type];
3463 color4 = style->light[state_type];
3465 case GTK_SHADOW_ETCHED_IN:
3466 color1 = style->dark[state_type];
3467 color2 = style->light[state_type];
3468 color3 = style->dark[state_type];
3469 color4 = style->light[state_type];
3471 case GTK_SHADOW_OUT:
3472 color1 = style->light[state_type];
3473 color2 = style->bg[state_type];
3474 color3 = style->dark[state_type];
3475 color4 = style->black;
3477 case GTK_SHADOW_ETCHED_OUT:
3478 color1 = style->light[state_type];
3479 color2 = style->dark[state_type];
3480 color3 = style->light[state_type];
3481 color4 = style->dark[state_type];
3485 cairo_set_line_width (cr, 1.0);
3487 switch (shadow_type)
3489 case GTK_SHADOW_NONE:
3491 case GTK_SHADOW_OUT:
3492 case GTK_SHADOW_ETCHED_IN:
3493 case GTK_SHADOW_ETCHED_OUT:
3497 _cairo_draw_line (cr, &color1,
3498 x, y, x, y + height - 1);
3499 _cairo_draw_line (cr, &color2,
3500 x + 1, y, x + 1, y + height - 2);
3502 _cairo_draw_line (cr, &color3,
3503 x + 1, y + height - 2, x + width - 2, y + height - 2);
3504 _cairo_draw_line (cr, &color3,
3505 x + width - 2, y, x + width - 2, y + height - 2);
3506 _cairo_draw_line (cr, &color4,
3507 x, y + height - 1, x + width - 1, y + height - 1);
3508 _cairo_draw_line (cr, &color4,
3509 x + width - 1, y, x + width - 1, y + height - 1);
3512 _cairo_draw_line (cr, &color1,
3513 x, y, x + gap_x - 1, y);
3514 _cairo_draw_line (cr, &color2,
3515 x + 1, y + 1, x + gap_x - 1, y + 1);
3516 _cairo_draw_line (cr, &color2,
3517 x + gap_x, y, x + gap_x, y);
3519 if ((width - (gap_x + gap_width)) > 0)
3521 _cairo_draw_line (cr, &color1,
3522 x + gap_x + gap_width, y, x + width - 2, y);
3523 _cairo_draw_line (cr, &color2,
3524 x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3525 _cairo_draw_line (cr, &color2,
3526 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3529 case GTK_POS_BOTTOM:
3530 _cairo_draw_line (cr, &color1,
3531 x, y, x + width - 1, y);
3532 _cairo_draw_line (cr, &color1,
3533 x, y, x, y + height - 1);
3534 _cairo_draw_line (cr, &color2,
3535 x + 1, y + 1, x + width - 2, y + 1);
3536 _cairo_draw_line (cr, &color2,
3537 x + 1, y + 1, x + 1, y + height - 1);
3539 _cairo_draw_line (cr, &color3,
3540 x + width - 2, y + 1, x + width - 2, y + height - 1);
3541 _cairo_draw_line (cr, &color4,
3542 x + width - 1, y, x + width - 1, y + height - 1);
3545 _cairo_draw_line (cr, &color4,
3546 x, y + height - 1, x + gap_x - 1, y + height - 1);
3547 _cairo_draw_line (cr, &color3,
3548 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3549 _cairo_draw_line (cr, &color3,
3550 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3552 if ((width - (gap_x + gap_width)) > 0)
3554 _cairo_draw_line (cr, &color4,
3555 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3556 _cairo_draw_line (cr, &color3,
3557 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3558 _cairo_draw_line (cr, &color3,
3559 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3563 _cairo_draw_line (cr, &color1,
3564 x, y, x + width - 1, y);
3565 _cairo_draw_line (cr, &color2,
3566 x, y + 1, x + width - 2, y + 1);
3568 _cairo_draw_line (cr, &color3,
3569 x, y + height - 2, x + width - 2, y + height - 2);
3570 _cairo_draw_line (cr, &color3,
3571 x + width - 2, y + 1, x + width - 2, y + height - 2);
3572 _cairo_draw_line (cr, &color4,
3573 x, y + height - 1, x + width - 1, y + height - 1);
3574 _cairo_draw_line (cr, &color4,
3575 x + width - 1, y, x + width - 1, y + height - 1);
3578 _cairo_draw_line (cr, &color1,
3579 x, y, x, y + gap_x - 1);
3580 _cairo_draw_line (cr, &color2,
3581 x + 1, y + 1, x + 1, y + gap_x - 1);
3582 _cairo_draw_line (cr, &color2,
3583 x, y + gap_x, x, y + gap_x);
3585 if ((height - (gap_x + gap_width)) > 0)
3587 _cairo_draw_line (cr, &color1,
3588 x, y + gap_x + gap_width, x, y + height - 2);
3589 _cairo_draw_line (cr, &color2,
3590 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3591 _cairo_draw_line (cr, &color2,
3592 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3596 _cairo_draw_line (cr, &color1,
3597 x, y, x + width - 1, y);
3598 _cairo_draw_line (cr, &color1,
3599 x, y, x, y + height - 1);
3600 _cairo_draw_line (cr, &color2,
3601 x + 1, y + 1, x + width - 1, y + 1);
3602 _cairo_draw_line (cr, &color2,
3603 x + 1, y + 1, x + 1, y + height - 2);
3605 _cairo_draw_line (cr, &color3,
3606 x + 1, y + height - 2, x + width - 1, y + height - 2);
3607 _cairo_draw_line (cr, &color4,
3608 x, y + height - 1, x + width - 1, y + height - 1);
3611 _cairo_draw_line (cr, &color4,
3612 x + width - 1, y, x + width - 1, y + gap_x - 1);
3613 _cairo_draw_line (cr, &color3,
3614 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3615 _cairo_draw_line (cr, &color3,
3616 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3618 if ((height - (gap_x + gap_width)) > 0)
3620 _cairo_draw_line (cr, &color4,
3621 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3622 _cairo_draw_line (cr, &color3,
3623 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3624 _cairo_draw_line (cr, &color3,
3625 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3636 gtk_default_draw_extension (GtkStyle *style,
3638 GtkStateType state_type,
3639 GtkShadowType shadow_type,
3642 const gchar *detail,
3647 GtkPositionType gap_side)
3655 sanitize_size (window, &width, &height);
3660 gtk_style_apply_default_background (style, window,
3661 widget && gtk_widget_get_has_window (widget),
3668 case GTK_POS_BOTTOM:
3669 gtk_style_apply_default_background (style, window,
3670 widget && gtk_widget_get_has_window (widget),
3678 gtk_style_apply_default_background (style, window,
3679 widget && gtk_widget_get_has_window (widget),
3687 gtk_style_apply_default_background (style, window,
3688 widget && gtk_widget_get_has_window (widget),
3698 cr = gdk_cairo_create (window);
3701 gdk_cairo_rectangle (cr, area);
3705 switch (shadow_type)
3707 case GTK_SHADOW_NONE:
3711 color1 = style->dark[state_type];
3712 color2 = style->black;
3713 color3 = style->bg[state_type];
3714 color4 = style->light[state_type];
3716 case GTK_SHADOW_ETCHED_IN:
3717 color1 = style->dark[state_type];
3718 color2 = style->light[state_type];
3719 color3 = style->dark[state_type];
3720 color4 = style->light[state_type];
3722 case GTK_SHADOW_OUT:
3723 color1 = style->light[state_type];
3724 color2 = style->bg[state_type];
3725 color3 = style->dark[state_type];
3726 color4 = style->black;
3728 case GTK_SHADOW_ETCHED_OUT:
3729 color1 = style->light[state_type];
3730 color2 = style->dark[state_type];
3731 color3 = style->light[state_type];
3732 color4 = style->dark[state_type];
3736 cairo_set_line_width (cr, 1.0);
3738 switch (shadow_type)
3740 case GTK_SHADOW_NONE:
3742 case GTK_SHADOW_OUT:
3743 case GTK_SHADOW_ETCHED_IN:
3744 case GTK_SHADOW_ETCHED_OUT:
3748 _cairo_draw_line (cr, &color1,
3749 x, y, x, y + height - 2);
3750 _cairo_draw_line (cr, &color2,
3751 x + 1, y, x + 1, y + height - 2);
3753 _cairo_draw_line (cr, &color3,
3754 x + 2, y + height - 2, x + width - 2, y + height - 2);
3755 _cairo_draw_line (cr, &color3,
3756 x + width - 2, y, x + width - 2, y + height - 2);
3757 _cairo_draw_line (cr, &color4,
3758 x + 1, y + height - 1, x + width - 2, y + height - 1);
3759 _cairo_draw_line (cr, &color4,
3760 x + width - 1, y, x + width - 1, y + height - 2);
3762 case GTK_POS_BOTTOM:
3763 _cairo_draw_line (cr, &color1,
3764 x + 1, y, x + width - 2, y);
3765 _cairo_draw_line (cr, &color1,
3766 x, y + 1, x, y + height - 1);
3767 _cairo_draw_line (cr, &color2,
3768 x + 1, y + 1, x + width - 2, y + 1);
3769 _cairo_draw_line (cr, &color2,
3770 x + 1, y + 1, x + 1, y + height - 1);
3772 _cairo_draw_line (cr, &color3,
3773 x + width - 2, y + 2, x + width - 2, y + height - 1);
3774 _cairo_draw_line (cr, &color4,
3775 x + width - 1, y + 1, x + width - 1, y + height - 1);
3778 _cairo_draw_line (cr, &color1,
3779 x, y, x + width - 2, y);
3780 _cairo_draw_line (cr, &color2,
3781 x + 1, y + 1, x + width - 2, y + 1);
3783 _cairo_draw_line (cr, &color3,
3784 x, y + height - 2, x + width - 2, y + height - 2);
3785 _cairo_draw_line (cr, &color3,
3786 x + width - 2, y + 2, x + width - 2, y + height - 2);
3787 _cairo_draw_line (cr, &color4,
3788 x, y + height - 1, x + width - 2, y + height - 1);
3789 _cairo_draw_line (cr, &color4,
3790 x + width - 1, y + 1, x + width - 1, y + height - 2);
3793 _cairo_draw_line (cr, &color1,
3794 x + 1, y, x + width - 1, y);
3795 _cairo_draw_line (cr, &color1,
3796 x, y + 1, x, y + height - 2);
3797 _cairo_draw_line (cr, &color2,
3798 x + 1, y + 1, x + width - 1, y + 1);
3799 _cairo_draw_line (cr, &color2,
3800 x + 1, y + 1, x + 1, y + height - 2);
3802 _cairo_draw_line (cr, &color3,
3803 x + 2, y + height - 2, x + width - 1, y + height - 2);
3804 _cairo_draw_line (cr, &color4,
3805 x + 1, y + height - 1, x + width - 1, y + height - 1);
3814 gtk_default_draw_focus (GtkStyle *style,
3816 GtkStateType state_type,
3819 const gchar *detail,
3826 gboolean free_dash_list = FALSE;
3827 gint line_width = 1;
3828 gint8 *dash_list = (gint8 *) "\1\1";
3832 gtk_widget_style_get (widget,
3833 "focus-line-width", &line_width,
3834 "focus-line-pattern", (gchar *)&dash_list,
3837 free_dash_list = TRUE;
3840 if (detail && !strcmp (detail, "add-mode"))
3845 dash_list = (gint8 *) "\4\4";
3846 free_dash_list = FALSE;
3849 sanitize_size (window, &width, &height);
3851 cr = gdk_cairo_create (window);
3853 if (detail && !strcmp (detail, "colorwheel_light"))
3854 cairo_set_source_rgb (cr, 0., 0., 0.);
3855 else if (detail && !strcmp (detail, "colorwheel_dark"))
3856 cairo_set_source_rgb (cr, 1., 1., 1.);
3858 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3860 cairo_set_line_width (cr, line_width);
3864 gint n_dashes = strlen ((const gchar *) dash_list);
3865 gdouble *dashes = g_new (gdouble, n_dashes);
3866 gdouble total_length = 0;
3867 gdouble dash_offset;
3870 for (i = 0; i < n_dashes; i++)
3872 dashes[i] = dash_list[i];
3873 total_length += dash_list[i];
3876 /* The dash offset here aligns the pattern to integer pixels
3877 * by starting the dash at the right side of the left border
3878 * Negative dash offsets in cairo don't work
3879 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
3881 dash_offset = - line_width / 2.;
3882 while (dash_offset < 0)
3883 dash_offset += total_length;
3885 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
3891 gdk_cairo_rectangle (cr, area);
3895 cairo_rectangle (cr,
3896 x + line_width / 2.,
3897 y + line_width / 2.,
3899 height - line_width);
3908 gtk_default_draw_slider (GtkStyle *style,
3910 GtkStateType state_type,
3911 GtkShadowType shadow_type,
3914 const gchar *detail,
3919 GtkOrientation orientation)
3921 sanitize_size (window, &width, &height);
3923 gtk_paint_box (style, window, state_type, shadow_type,
3924 area, widget, detail, x, y, width, height);
3927 (strcmp ("hscale", detail) == 0 ||
3928 strcmp ("vscale", detail) == 0))
3930 if (orientation == GTK_ORIENTATION_HORIZONTAL)
3931 gtk_paint_vline (style, window, state_type, area, widget, detail,
3932 y + style->ythickness,
3933 y + height - style->ythickness - 1, x + width / 2);
3935 gtk_paint_hline (style, window, state_type, area, widget, detail,
3936 x + style->xthickness,
3937 x + width - style->xthickness - 1, y + height / 2);
3942 draw_dot (cairo_t *cr,
3949 size = CLAMP (size, 2, 3);
3953 _cairo_draw_point (cr, light, x, y);
3954 _cairo_draw_point (cr, light, x+1, y+1);
3958 _cairo_draw_point (cr, light, x, y);
3959 _cairo_draw_point (cr, light, x+1, y);
3960 _cairo_draw_point (cr, light, x, y+1);
3961 _cairo_draw_point (cr, dark, x+1, y+2);
3962 _cairo_draw_point (cr, dark, x+2, y+1);
3963 _cairo_draw_point (cr, dark, x+2, y+2);
3968 gtk_default_draw_handle (GtkStyle *style,
3970 GtkStateType state_type,
3971 GtkShadowType shadow_type,
3974 const gchar *detail,
3979 GtkOrientation orientation)
3982 gint xthick, ythick;
3983 GdkColor light, dark;
3986 sanitize_size (window, &width, &height);
3988 gtk_paint_box (style, window, state_type, shadow_type, area, widget,
3989 detail, x, y, width, height);
3991 cr = gdk_cairo_create (window);
3994 gdk_cairo_rectangle (cr, area);
3998 if (detail && !strcmp (detail, "paned"))
4000 /* we want to ignore the shadow border in paned widgets */
4004 if (state_type == GTK_STATE_SELECTED && widget && !gtk_widget_has_focus (widget))
4005 _gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &light,
4008 light = style->light[state_type];
4010 dark = style->black;
4014 xthick = style->xthickness;
4015 ythick = style->ythickness;
4017 light = style->light[state_type];
4018 dark = style->dark[state_type];
4021 cairo_rectangle(cr, x + xthick, y + ythick,
4022 width - (xthick * 2), height - (ythick * 2));
4025 if (detail && !strcmp (detail, "paned"))
4027 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4028 for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4029 draw_dot (cr, &light, &dark, xx, y + height/2 - 1, 3);
4031 for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4032 draw_dot (cr, &light, &dark, x + width/2 - 1, yy, 3);
4036 for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4037 for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4039 draw_dot (cr, &light, &dark, xx, yy, 2);
4040 draw_dot (cr, &light, &dark, xx + 3, yy + 1, 2);
4048 gtk_default_draw_expander (GtkStyle *style,
4050 GtkStateType state_type,
4053 const gchar *detail,
4056 GtkExpanderStyle expander_style)
4058 #define DEFAULT_EXPANDER_SIZE 12
4062 double vertical_overshoot;
4065 double interp; /* interpolation factor for center position */
4066 double x_double_horz, y_double_horz;
4067 double x_double_vert, y_double_vert;
4068 double x_double, y_double;
4071 cairo_t *cr = gdk_cairo_create (window);
4075 gdk_cairo_rectangle (cr, area);
4080 gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
4083 gtk_widget_style_get (widget,
4084 "expander-size", &expander_size,
4088 expander_size = DEFAULT_EXPANDER_SIZE;
4090 line_width = MAX (1, expander_size/9);
4092 switch (expander_style)
4094 case GTK_EXPANDER_COLLAPSED:
4095 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4098 case GTK_EXPANDER_SEMI_COLLAPSED:
4099 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4102 case GTK_EXPANDER_SEMI_EXPANDED:
4103 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4106 case GTK_EXPANDER_EXPANDED:
4111 g_assert_not_reached ();
4114 /* Compute distance that the stroke extends beyonds the end
4115 * of the triangle we draw.
4117 vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
4119 /* For odd line widths, we end the vertical line of the triangle
4120 * at a half pixel, so we round differently.
4122 if (line_width % 2 == 1)
4123 vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
4125 vertical_overshoot = ceil (vertical_overshoot);
4127 /* Adjust the size of the triangle we draw so that the entire stroke fits
4129 diameter = MAX (3, expander_size - 2 * vertical_overshoot);
4131 /* If the line width is odd, we want the diameter to be even,
4132 * and vice versa, so force the sum to be odd. This relationship
4133 * makes the point of the triangle look right.
4135 diameter -= (1 - (diameter + line_width) % 2);
4137 radius = diameter / 2.;
4139 /* Adjust the center so that the stroke is properly aligned with
4140 * the pixel grid. The center adjustment is different for the
4141 * horizontal and vertical orientations. For intermediate positions
4142 * we interpolate between the two.
4144 x_double_vert = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
4145 y_double_vert = y - 0.5;
4147 x_double_horz = x - 0.5;
4148 y_double_horz = floor (y - (radius + line_width) / 2.) + (radius + line_width) / 2.;
4150 x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
4151 y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
4153 cairo_translate (cr, x_double, y_double);
4154 cairo_rotate (cr, degrees * G_PI / 180);
4156 cairo_move_to (cr, - radius / 2., - radius);
4157 cairo_line_to (cr, radius / 2., 0);
4158 cairo_line_to (cr, - radius / 2., radius);
4159 cairo_close_path (cr);
4161 cairo_set_line_width (cr, line_width);
4163 if (state_type == GTK_STATE_PRELIGHT)
4164 gdk_cairo_set_source_color (cr,
4165 &style->fg[GTK_STATE_PRELIGHT]);
4166 else if (state_type == GTK_STATE_ACTIVE)
4167 gdk_cairo_set_source_color (cr,
4168 &style->light[GTK_STATE_ACTIVE]);
4170 gdk_cairo_set_source_color (cr,
4171 &style->base[GTK_STATE_NORMAL]);
4173 cairo_fill_preserve (cr);
4175 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
4182 gtk_default_draw_layout (GtkStyle *style,
4184 GtkStateType state_type,
4188 const gchar *detail,
4191 PangoLayout *layout)
4195 const PangoMatrix *matrix;
4197 cr = gdk_cairo_create (window);
4201 gdk_cairo_rectangle (cr, area);
4205 matrix = pango_context_get_matrix (pango_layout_get_context (layout));
4208 cairo_matrix_t cairo_matrix;
4209 PangoMatrix tmp_matrix;
4210 PangoRectangle rect;
4212 cairo_matrix_init (&cairo_matrix,
4213 matrix->xx, matrix->yx,
4214 matrix->xy, matrix->yy,
4215 matrix->x0, matrix->y0);
4217 pango_layout_get_extents (layout, NULL, &rect);
4218 pango_matrix_transform_rectangle (matrix, &rect);
4219 pango_extents_to_pixels (&rect, NULL);
4221 tmp_matrix = *matrix;
4222 cairo_matrix.x0 += x - rect.x;
4223 cairo_matrix.y0 += y - rect.y;
4225 cairo_set_matrix (cr, &cairo_matrix);
4228 cairo_translate (cr, x, y);
4230 if (state_type == GTK_STATE_INSENSITIVE)
4233 gdk_cairo_set_source_color (cr, &style->white);
4234 cairo_move_to (cr, 1, 1);
4235 _gtk_pango_fill_layout (cr, layout);
4239 gc = use_text ? &style->text[state_type] : &style->fg[state_type];
4241 gdk_cairo_set_source_color (cr, gc);
4243 pango_cairo_show_layout (cr, layout);
4249 gtk_default_draw_resize_grip (GtkStyle *style,
4251 GtkStateType state_type,
4254 const gchar *detail,
4264 cr = gdk_cairo_create (window);
4265 cairo_rectangle (cr, x, y, width, height);
4269 gdk_cairo_rectangle (cr, area);
4273 cairo_set_line_width (cr, 1.0);
4278 case GDK_WINDOW_EDGE_NORTH_WEST:
4279 /* make it square */
4282 else if (height < width)
4286 case GDK_WINDOW_EDGE_NORTH:
4290 case GDK_WINDOW_EDGE_NORTH_EAST:
4291 /* make it square, aligning to top right */
4294 else if (height < width)
4296 x += (width - height);
4301 case GDK_WINDOW_EDGE_WEST:
4305 case GDK_WINDOW_EDGE_EAST:
4306 /* aligning to right */
4309 x += (width - height);
4313 case GDK_WINDOW_EDGE_SOUTH_WEST:
4314 /* make it square, aligning to bottom left */
4317 y += (height - width);
4320 else if (height < width)
4324 case GDK_WINDOW_EDGE_SOUTH:
4325 /* align to bottom */
4328 y += (height - width);
4332 case GDK_WINDOW_EDGE_SOUTH_EAST:
4333 /* make it square, aligning to bottom right */
4336 y += (height - width);
4339 else if (height < width)
4341 x += (width - height);
4347 g_assert_not_reached ();
4352 case GDK_WINDOW_EDGE_WEST:
4353 case GDK_WINDOW_EDGE_EAST:
4359 while (xi < x + width)
4361 _cairo_draw_line (cr,
4362 &style->light[state_type],
4367 _cairo_draw_line (cr,
4368 &style->dark[state_type],
4376 case GDK_WINDOW_EDGE_NORTH:
4377 case GDK_WINDOW_EDGE_SOUTH:
4383 while (yi < y + height)
4385 _cairo_draw_line (cr,
4386 &style->light[state_type],
4391 _cairo_draw_line (cr,
4392 &style->dark[state_type],
4400 case GDK_WINDOW_EDGE_NORTH_WEST:
4409 _cairo_draw_line (cr,
4410 &style->dark[state_type],
4417 _cairo_draw_line (cr,
4418 &style->dark[state_type],
4425 _cairo_draw_line (cr,
4426 &style->light[state_type],
4436 case GDK_WINDOW_EDGE_NORTH_EAST:
4443 while (xi < (x + width - 3))
4445 _cairo_draw_line (cr,
4446 &style->light[state_type],
4453 _cairo_draw_line (cr,
4454 &style->dark[state_type],
4461 _cairo_draw_line (cr,
4462 &style->dark[state_type],
4471 case GDK_WINDOW_EDGE_SOUTH_WEST:
4480 _cairo_draw_line (cr,
4481 &style->dark[state_type],
4488 _cairo_draw_line (cr,
4489 &style->dark[state_type],
4496 _cairo_draw_line (cr,
4497 &style->light[state_type],
4507 case GDK_WINDOW_EDGE_SOUTH_EAST:
4514 while (xi < (x + width - 3))
4516 _cairo_draw_line (cr,
4517 &style->light[state_type],
4524 _cairo_draw_line (cr,
4525 &style->dark[state_type],
4532 _cairo_draw_line (cr,
4533 &style->dark[state_type],
4543 g_assert_not_reached ();
4551 gtk_default_draw_spinner (GtkStyle *style,
4553 GtkStateType state_type,
4556 const gchar *detail,
4572 gtk_style_get (style, GTK_TYPE_SPINNER,
4573 "num-steps", &num_steps,
4575 real_step = step % num_steps;
4577 /* get cairo context */
4578 cr = gdk_cairo_create (window);
4580 /* set a clip region for the expose event */
4581 cairo_rectangle (cr, x, y, width, height);
4584 cairo_translate (cr, x, y);
4586 /* draw clip region */
4587 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
4589 color = &style->fg[state_type];
4592 radius = MIN (width / 2, height / 2);
4593 half = num_steps / 2;
4595 for (i = 0; i < num_steps; i++)
4597 gint inset = 0.7 * radius;
4599 /* transparency is a function of time and intial value */
4600 gdouble t = (gdouble) ((i + num_steps - real_step)
4601 % num_steps) / num_steps;
4605 cairo_set_source_rgba (cr,
4606 color->red / 65535.,
4607 color->green / 65535.,
4608 color->blue / 65535.,
4611 cairo_set_line_width (cr, 2.0);
4613 dx + (radius - inset) * cos (i * G_PI / half),
4614 dy + (radius - inset) * sin (i * G_PI / half));
4616 dx + radius * cos (i * G_PI / half),
4617 dy + radius * sin (i * G_PI / half));
4628 _gtk_style_shade (const GdkColor *a,
4636 red = (gdouble) a->red / 65535.0;
4637 green = (gdouble) a->green / 65535.0;
4638 blue = (gdouble) a->blue / 65535.0;
4640 rgb_to_hls (&red, &green, &blue);
4645 else if (green < 0.0)
4651 else if (blue < 0.0)
4654 hls_to_rgb (&red, &green, &blue);
4656 b->red = red * 65535.0;
4657 b->green = green * 65535.0;
4658 b->blue = blue * 65535.0;
4662 rgb_to_hls (gdouble *r,
4703 l = (max + min) / 2;
4710 s = (max - min) / (max + min);
4712 s = (max - min) / (2 - max - min);
4716 h = (green - blue) / delta;
4717 else if (green == max)
4718 h = 2 + (blue - red) / delta;
4719 else if (blue == max)
4720 h = 4 + (red - green) / delta;
4733 hls_to_rgb (gdouble *h,
4746 if (lightness <= 0.5)
4747 m2 = lightness * (1 + saturation);
4749 m2 = lightness + saturation - lightness * saturation;
4750 m1 = 2 * lightness - m2;
4752 if (saturation == 0)
4767 r = m1 + (m2 - m1) * hue / 60;
4771 r = m1 + (m2 - m1) * (240 - hue) / 60;
4782 g = m1 + (m2 - m1) * hue / 60;
4786 g = m1 + (m2 - m1) * (240 - hue) / 60;
4797 b = m1 + (m2 - m1) * hue / 60;
4801 b = m1 + (m2 - m1) * (240 - hue) / 60;
4814 * @style: a #GtkStyle
4815 * @window: a #GdkWindow
4816 * @state_type: a state
4817 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
4818 * output should not be clipped
4819 * @widget: (allow-none): the widget
4820 * @detail: (allow-none): a style detail
4821 * @x1: the starting x coordinate
4822 * @x2: the ending x coordinate
4823 * @y: the y coordinate
4825 * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
4826 * using the given style and state.
4829 gtk_paint_hline (GtkStyle *style,
4831 GtkStateType state_type,
4832 const GdkRectangle *area,
4834 const gchar *detail,
4839 g_return_if_fail (GTK_IS_STYLE (style));
4840 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4841 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4843 GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type,
4844 (GdkRectangle *) area, widget, detail,
4850 * @style: a #GtkStyle
4851 * @window: a #GdkWindow
4852 * @state_type: a state
4853 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
4854 * output should not be clipped
4855 * @widget: (allow-none): the widget
4856 * @detail: (allow-none): a style detail
4857 * @y1_: the starting y coordinate
4858 * @y2_: the ending y coordinate
4859 * @x: the x coordinate
4861 * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
4862 * using the given style and state.
4865 gtk_paint_vline (GtkStyle *style,
4867 GtkStateType state_type,
4868 const GdkRectangle *area,
4870 const gchar *detail,
4875 g_return_if_fail (GTK_IS_STYLE (style));
4876 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
4877 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4879 GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type,
4880 (GdkRectangle *) area, widget, detail,
4886 * @style: a #GtkStyle
4887 * @window: a #GdkWindow
4888 * @state_type: a state
4889 * @shadow_type: type of shadow to draw
4890 * @area: (allow-none): clip rectangle or %NULL if the
4891 * output should not be clipped
4892 * @widget: (allow-none): the widget
4893 * @detail: (allow-none): a style detail
4894 * @x: x origin of the rectangle
4895 * @y: y origin of the rectangle
4896 * @width: width of the rectangle
4897 * @height: width of the rectangle
4899 * Draws a shadow around the given rectangle in @window
4900 * using the given style and state and shadow type.
4903 gtk_paint_shadow (GtkStyle *style,
4905 GtkStateType state_type,
4906 GtkShadowType shadow_type,
4907 const GdkRectangle *area,
4909 const gchar *detail,
4915 g_return_if_fail (GTK_IS_STYLE (style));
4916 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4917 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4919 GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type,
4920 (GdkRectangle *) area, widget, detail,
4921 x, y, width, height);
4926 * @style: a #GtkStyle
4927 * @window: a #GdkWindow
4928 * @state_type: a state
4929 * @shadow_type: the type of shadow to draw
4930 * @area: (allow-none): clip rectangle, or %NULL if the
4931 * output should not be clipped
4932 * @widget: (allow-none): the widget
4933 * @detail: (allow-none): a style detail
4934 * @arrow_type: the type of arrow to draw
4935 * @fill: %TRUE if the arrow tip should be filled
4936 * @x: x origin of the rectangle to draw the arrow in
4937 * @y: y origin of the rectangle to draw the arrow in
4938 * @width: width of the rectangle to draw the arrow in
4939 * @height: height of the rectangle to draw the arrow in
4941 * Draws an arrow in the given rectangle on @window using the given
4942 * parameters. @arrow_type determines the direction of the arrow.
4945 gtk_paint_arrow (GtkStyle *style,
4947 GtkStateType state_type,
4948 GtkShadowType shadow_type,
4949 const GdkRectangle *area,
4951 const gchar *detail,
4952 GtkArrowType arrow_type,
4959 g_return_if_fail (GTK_IS_STYLE (style));
4960 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
4961 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4963 GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type,
4964 (GdkRectangle *) area, widget, detail,
4965 arrow_type, fill, x, y, width, height);
4969 * gtk_paint_diamond:
4970 * @style: a #GtkStyle
4971 * @window: a #GdkWindow
4972 * @state_type: a state
4973 * @shadow_type: the type of shadow to draw
4974 * @area: (allow-none): clip rectangle, or %NULL if the
4975 * output should not be clipped
4976 * @widget: (allow-none): the widget
4977 * @detail: (allow-none): a style detail
4978 * @x: x origin of the rectangle to draw the diamond in
4979 * @y: y origin of the rectangle to draw the diamond in
4980 * @width: width of the rectangle to draw the diamond in
4981 * @height: height of the rectangle to draw the diamond in
4983 * Draws a diamond in the given rectangle on @window using the given
4987 gtk_paint_diamond (GtkStyle *style,
4989 GtkStateType state_type,
4990 GtkShadowType shadow_type,
4991 const GdkRectangle *area,
4993 const gchar *detail,
4999 g_return_if_fail (GTK_IS_STYLE (style));
5000 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5001 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5003 GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type,
5004 (GdkRectangle *) area, widget, detail,
5005 x, y, width, height);
5010 * @style: a #GtkStyle
5011 * @window: a #GdkWindow
5012 * @state_type: a state
5013 * @shadow_type: the type of shadow to draw
5014 * @area: (allow-none): clip rectangle, or %NULL if the
5015 * output should not be clipped
5016 * @widget: (allow-none): the widget
5017 * @detail: (allow-none): a style detail
5018 * @x: x origin of the box
5019 * @y: y origin of the box
5020 * @width: the width of the box
5021 * @height: the height of the box
5023 * Draws a box on @window with the given parameters.
5026 gtk_paint_box (GtkStyle *style,
5028 GtkStateType state_type,
5029 GtkShadowType shadow_type,
5030 const GdkRectangle *area,
5032 const gchar *detail,
5038 g_return_if_fail (GTK_IS_STYLE (style));
5039 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5040 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5042 GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type,
5043 (GdkRectangle *) area, widget, detail,
5044 x, y, width, height);
5048 * gtk_paint_flat_box:
5049 * @style: a #GtkStyle
5050 * @window: a #GdkWindow
5051 * @state_type: a state
5052 * @shadow_type: the type of shadow to draw
5053 * @area: (allow-none): clip rectangle, or %NULL if the
5054 * output should not be clipped
5055 * @widget: (allow-none): the widget
5056 * @detail: (allow-none): a style detail
5057 * @x: x origin of the box
5058 * @y: y origin of the box
5059 * @width: the width of the box
5060 * @height: the height of the box
5062 * Draws a flat box on @window with the given parameters.
5065 gtk_paint_flat_box (GtkStyle *style,
5067 GtkStateType state_type,
5068 GtkShadowType shadow_type,
5069 const GdkRectangle *area,
5071 const gchar *detail,
5077 g_return_if_fail (GTK_IS_STYLE (style));
5078 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5079 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5081 GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type,
5082 (GdkRectangle *) area, widget, detail,
5083 x, y, width, height);
5088 * @style: a #GtkStyle
5089 * @window: a #GdkWindow
5090 * @state_type: a state
5091 * @shadow_type: the type of shadow to draw
5092 * @area: (allow-none): clip rectangle, or %NULL if the
5093 * output should not be clipped
5094 * @widget: (allow-none): the widget
5095 * @detail: (allow-none): a style detail
5096 * @x: x origin of the rectangle to draw the check in
5097 * @y: y origin of the rectangle to draw the check in
5098 * @width: the width of the rectangle to draw the check in
5099 * @height: the height of the rectangle to draw the check in
5101 * Draws a check button indicator in the given rectangle on @window with
5102 * the given parameters.
5105 gtk_paint_check (GtkStyle *style,
5107 GtkStateType state_type,
5108 GtkShadowType shadow_type,
5109 const GdkRectangle *area,
5111 const gchar *detail,
5117 g_return_if_fail (GTK_IS_STYLE (style));
5118 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
5119 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5121 GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type,
5122 (GdkRectangle *) area, widget, detail,
5123 x, y, width, height);
5128 * @style: a #GtkStyle
5129 * @window: a #GdkWindow
5130 * @state_type: a state
5131 * @shadow_type: the type of shadow to draw
5132 * @area: (allow-none): clip rectangle, or %NULL if the
5133 * output should not be clipped
5134 * @widget: (allow-none): the widget
5135 * @detail: (allow-none): a style detail
5136 * @x: x origin of the rectangle to draw the option in
5137 * @y: y origin of the rectangle to draw the option in
5138 * @width: the width of the rectangle to draw the option in
5139 * @height: the height of the rectangle to draw the option in
5141 * Draws a radio button indicator in the given rectangle on @window with
5142 * the given parameters.
5145 gtk_paint_option (GtkStyle *style,
5147 GtkStateType state_type,
5148 GtkShadowType shadow_type,
5149 const GdkRectangle *area,
5151 const gchar *detail,
5157 g_return_if_fail (GTK_IS_STYLE (style));
5158 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
5159 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5161 GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type,
5162 (GdkRectangle *) area, widget, detail,
5163 x, y, width, height);
5168 * @style: a #GtkStyle
5169 * @window: a #GdkWindow
5170 * @state_type: a state
5171 * @shadow_type: the type of shadow to draw
5172 * @area: (allow-none): clip rectangle, or %NULL if the
5173 * output should not be clipped
5174 * @widget: (allow-none): the widget
5175 * @detail: (allow-none): a style detail
5176 * @x: x origin of the rectangle to draw the tab in
5177 * @y: y origin of the rectangle to draw the tab in
5178 * @width: the width of the rectangle to draw the tab in
5179 * @height: the height of the rectangle to draw the tab in
5181 * Draws an option menu tab (i.e. the up and down pointing arrows)
5182 * in the given rectangle on @window using the given parameters.
5185 gtk_paint_tab (GtkStyle *style,
5187 GtkStateType state_type,
5188 GtkShadowType shadow_type,
5189 const GdkRectangle *area,
5191 const gchar *detail,
5197 g_return_if_fail (GTK_IS_STYLE (style));
5198 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
5199 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5201 GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type,
5202 (GdkRectangle *) area, widget, detail,
5203 x, y, width, height);
5207 * gtk_paint_shadow_gap:
5208 * @style: a #GtkStyle
5209 * @window: a #GdkWindow
5210 * @state_type: a state
5211 * @shadow_type: type of shadow to draw
5212 * @area: (allow-none): clip rectangle, or %NULL if the
5213 * output should not be clipped
5214 * @widget: (allow-none): the widget
5215 * @detail: (allow-none): a style detail
5216 * @x: x origin of the rectangle
5217 * @y: y origin of the rectangle
5218 * @width: width of the rectangle
5219 * @height: width of the rectangle
5220 * @gap_side: side in which to leave the gap
5221 * @gap_x: starting position of the gap
5222 * @gap_width: width of the gap
5224 * Draws a shadow around the given rectangle in @window
5225 * using the given style and state and shadow type, leaving a
5229 gtk_paint_shadow_gap (GtkStyle *style,
5231 GtkStateType state_type,
5232 GtkShadowType shadow_type,
5233 const GdkRectangle *area,
5235 const gchar *detail,
5240 GtkPositionType gap_side,
5244 g_return_if_fail (GTK_IS_STYLE (style));
5245 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
5246 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5248 GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type,
5249 (GdkRectangle *) area, widget, detail,
5250 x, y, width, height, gap_side, gap_x, gap_width);
5255 * gtk_paint_box_gap:
5256 * @style: a #GtkStyle
5257 * @window: a #GdkWindow
5258 * @state_type: a state
5259 * @shadow_type: type of shadow to draw
5260 * @area: (allow-none): clip rectangle, or %NULL if the
5261 * output should not be clipped
5262 * @widget: (allow-none): the widget
5263 * @detail: (allow-none): a style detail
5264 * @x: x origin of the rectangle
5265 * @y: y origin of the rectangle
5266 * @width: width of the rectangle
5267 * @height: width of the rectangle
5268 * @gap_side: side in which to leave the gap
5269 * @gap_x: starting position of the gap
5270 * @gap_width: width of the gap
5272 * Draws a box in @window using the given style and state and shadow type,
5273 * leaving a gap in one side.
5276 gtk_paint_box_gap (GtkStyle *style,
5278 GtkStateType state_type,
5279 GtkShadowType shadow_type,
5280 const GdkRectangle *area,
5282 const gchar *detail,
5287 GtkPositionType gap_side,
5291 g_return_if_fail (GTK_IS_STYLE (style));
5292 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
5293 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5295 GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type,
5296 (GdkRectangle *) area, widget, detail,
5297 x, y, width, height, gap_side, gap_x, gap_width);
5301 * gtk_paint_extension:
5302 * @style: a #GtkStyle
5303 * @window: a #GdkWindow
5304 * @state_type: a state
5305 * @shadow_type: type of shadow to draw
5306 * @area: (allow-none): clip rectangle, or %NULL if the
5307 * output should not be clipped
5308 * @widget: (allow-none): the widget
5309 * @detail: (allow-none): a style detail
5310 * @x: x origin of the extension
5311 * @y: y origin of the extension
5312 * @width: width of the extension
5313 * @height: width of the extension
5314 * @gap_side: the side on to which the extension is attached
5316 * Draws an extension, i.e. a notebook tab.
5319 gtk_paint_extension (GtkStyle *style,
5321 GtkStateType state_type,
5322 GtkShadowType shadow_type,
5323 const GdkRectangle *area,
5325 const gchar *detail,
5330 GtkPositionType gap_side)
5332 g_return_if_fail (GTK_IS_STYLE (style));
5333 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5334 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5336 GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type,
5337 (GdkRectangle *) area, widget, detail,
5338 x, y, width, height, gap_side);
5343 * @style: a #GtkStyle
5344 * @window: a #GdkWindow
5345 * @state_type: a state
5346 * @area: (allow-none): clip rectangle, or %NULL if the
5347 * output should not be clipped
5348 * @widget: (allow-none): the widget
5349 * @detail: (allow-none): a style detail
5350 * @x: the x origin of the rectangle around which to draw a focus indicator
5351 * @y: the y origin of the rectangle around which to draw a focus indicator
5352 * @width: the width of the rectangle around which to draw a focus indicator
5353 * @height: the height of the rectangle around which to draw a focus indicator
5355 * Draws a focus indicator around the given rectangle on @window using the
5359 gtk_paint_focus (GtkStyle *style,
5361 GtkStateType state_type,
5362 const GdkRectangle *area,
5364 const gchar *detail,
5370 g_return_if_fail (GTK_IS_STYLE (style));
5371 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5372 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5374 GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type,
5375 (GdkRectangle *) area, widget, detail,
5376 x, y, width, height);
5381 * @style: a #GtkStyle
5382 * @window: a #GdkWindow
5383 * @state_type: a state
5384 * @shadow_type: a shadow
5385 * @area: (allow-none): clip rectangle, or %NULL if the
5386 * output should not be clipped
5387 * @widget: (allow-none): the widget
5388 * @detail: (allow-none): a style detail
5389 * @x: the x origin of the rectangle in which to draw a slider
5390 * @y: the y origin of the rectangle in which to draw a slider
5391 * @width: the width of the rectangle in which to draw a slider
5392 * @height: the height of the rectangle in which to draw a slider
5393 * @orientation: the orientation to be used
5395 * Draws a slider in the given rectangle on @window using the
5396 * given style and orientation.
5399 gtk_paint_slider (GtkStyle *style,
5401 GtkStateType state_type,
5402 GtkShadowType shadow_type,
5403 const GdkRectangle *area,
5405 const gchar *detail,
5410 GtkOrientation orientation)
5412 g_return_if_fail (GTK_IS_STYLE (style));
5413 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5414 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5416 GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type,
5417 (GdkRectangle *) area, widget, detail,
5418 x, y, width, height, orientation);
5423 * @style: a #GtkStyle
5424 * @window: a #GdkWindow
5425 * @state_type: a state
5426 * @shadow_type: type of shadow to draw
5427 * @area: (allow-none): clip rectangle, or %NULL if the
5428 * output should not be clipped
5429 * @widget: (allow-none): the widget
5430 * @detail: (allow-none): a style detail
5431 * @x: x origin of the handle
5432 * @y: y origin of the handle
5433 * @width: with of the handle
5434 * @height: height of the handle
5435 * @orientation: the orientation of the handle
5437 * Draws a handle as used in #GtkHandleBox and #GtkPaned.
5440 gtk_paint_handle (GtkStyle *style,
5442 GtkStateType state_type,
5443 GtkShadowType shadow_type,
5444 const GdkRectangle *area,
5446 const gchar *detail,
5451 GtkOrientation orientation)
5453 g_return_if_fail (GTK_IS_STYLE (style));
5454 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5455 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5457 GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type,
5458 (GdkRectangle *) area, widget, detail,
5459 x, y, width, height, orientation);
5463 * gtk_paint_expander:
5464 * @style: a #GtkStyle
5465 * @window: a #GdkWindow
5466 * @state_type: a state
5467 * @area: (allow-none): clip rectangle, or %NULL if the
5468 * output should not be clipped
5469 * @widget: (allow-none): the widget
5470 * @detail: (allow-none): a style detail
5471 * @x: the x position to draw the expander at
5472 * @y: the y position to draw the expander at
5473 * @expander_style: the style to draw the expander in; determines
5474 * whether the expander is collapsed, expanded, or in an
5475 * intermediate state.
5477 * Draws an expander as used in #GtkTreeView. @x and @y specify the
5478 * center the expander. The size of the expander is determined by the
5479 * "expander-size" style property of @widget. (If widget is not
5480 * specified or doesn't have an "expander-size" property, an
5481 * unspecified default size will be used, since the caller doesn't
5482 * have sufficient information to position the expander, this is
5483 * likely not useful.) The expander is expander_size pixels tall
5484 * in the collapsed position and expander_size pixels wide in the
5485 * expanded position.
5488 gtk_paint_expander (GtkStyle *style,
5490 GtkStateType state_type,
5491 const GdkRectangle *area,
5493 const gchar *detail,
5496 GtkExpanderStyle expander_style)
5498 g_return_if_fail (GTK_IS_STYLE (style));
5499 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5500 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5502 GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type,
5503 (GdkRectangle *) area, widget, detail,
5504 x, y, expander_style);
5509 * @style: a #GtkStyle
5510 * @window: a #GdkWindow
5511 * @state_type: a state
5512 * @use_text: whether to use the text or foreground
5513 * graphics context of @style
5514 * @area: (allow-none): clip rectangle, or %NULL if the
5515 * output should not be clipped
5516 * @widget: (allow-none): the widget
5517 * @detail: (allow-none): a style detail
5520 * @layout: the layout to draw
5522 * Draws a layout on @window using the given parameters.
5525 gtk_paint_layout (GtkStyle *style,
5527 GtkStateType state_type,
5529 const GdkRectangle *area,
5531 const gchar *detail,
5534 PangoLayout *layout)
5536 g_return_if_fail (GTK_IS_STYLE (style));
5537 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5538 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5540 GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text,
5541 (GdkRectangle *) area, widget, detail,
5546 * gtk_paint_resize_grip:
5547 * @style: a #GtkStyle
5548 * @window: a #GdkWindow
5549 * @state_type: a state
5550 * @area: (allow-none): clip rectangle, or %NULL if the
5551 * output should not be clipped
5552 * @widget: (allow-none): the widget
5553 * @detail: (allow-none): a style detail
5554 * @edge: the edge in which to draw the resize grip
5555 * @x: the x origin of the rectangle in which to draw the resize grip
5556 * @y: the y origin of the rectangle in which to draw the resize grip
5557 * @width: the width of the rectangle in which to draw the resize grip
5558 * @height: the height of the rectangle in which to draw the resize grip
5560 * Draws a resize grip in the given rectangle on @window using the given
5564 gtk_paint_resize_grip (GtkStyle *style,
5566 GtkStateType state_type,
5567 const GdkRectangle *area,
5569 const gchar *detail,
5577 g_return_if_fail (GTK_IS_STYLE (style));
5578 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
5579 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5581 GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
5582 (GdkRectangle *) area, widget, detail,
5583 edge, x, y, width, height);
5587 * gtk_paint_spinner:
5588 * @style: a #GtkStyle
5589 * @window: a #GdkWindow
5590 * @state_type: a state
5591 * @area: (allow-none): clip rectangle, or %NULL if the
5592 * output should not be clipped
5593 * @widget: (allow-none): the widget (may be %NULL)
5594 * @detail: (allow-none): a style detail (may be %NULL)
5595 * @step: the nth step, a value between 0 and #GtkSpinner:num-steps
5596 * @x: the x origin of the rectangle in which to draw the spinner
5597 * @y: the y origin of the rectangle in which to draw the spinner
5598 * @width: the width of the rectangle in which to draw the spinner
5599 * @height: the height of the rectangle in which to draw the spinner
5601 * Draws a spinner on @window using the given parameters.
5606 gtk_paint_spinner (GtkStyle *style,
5608 GtkStateType state_type,
5609 const GdkRectangle *area,
5611 const gchar *detail,
5618 g_return_if_fail (GTK_IS_STYLE (style));
5619 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_spinner != NULL);
5620 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5622 GTK_STYLE_GET_CLASS (style)->draw_spinner (style, window, state_type,
5623 (GdkRectangle *)area, widget, detail,
5624 step, x, y, width, height);
5630 * Allocates a new #GtkBorder structure and initializes its elements to zero.
5632 * Returns: a new empty #GtkBorder. The newly allocated #GtkBorder should be
5633 * freed with gtk_border_free()
5638 gtk_border_new (void)
5640 return g_slice_new0 (GtkBorder);
5645 * @border_: a #GtkBorder.
5646 * @returns: a copy of @border_.
5648 * Copies a #GtkBorder structure.
5651 gtk_border_copy (const GtkBorder *border)
5653 g_return_val_if_fail (border != NULL, NULL);
5655 return g_slice_dup (GtkBorder, border);
5660 * @border_: a #GtkBorder.
5662 * Frees a #GtkBorder structure.
5665 gtk_border_free (GtkBorder *border)
5667 g_slice_free (GtkBorder, border);
5670 G_DEFINE_BOXED_TYPE (GtkBorder, gtk_border,
5674 typedef struct _CursorInfo CursorInfo;
5684 style_unrealize_cursors (GtkStyle *style)
5688 cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5691 g_free (cursor_info);
5692 g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
5696 static const GdkColor *
5697 get_insertion_cursor_color (GtkWidget *widget,
5698 gboolean is_primary)
5700 CursorInfo *cursor_info;
5702 GdkColor *cursor_color;
5704 style = gtk_widget_get_style (widget);
5706 cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5709 cursor_info = g_new0 (CursorInfo, 1);
5710 g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), cursor_info);
5711 cursor_info->for_type = G_TYPE_INVALID;
5714 /* We have to keep track of the type because gtk_widget_style_get()
5715 * can return different results when called on the same property and
5716 * same style but for different widgets. :-(. That is,
5717 * GtkEntry::cursor-color = "red" in a style will modify the cursor
5718 * color for entries but not for text view.
5720 if (cursor_info->for_type != G_OBJECT_TYPE (widget))
5722 cursor_info->for_type = G_OBJECT_TYPE (widget);
5724 /* Cursors in text widgets are drawn only in NORMAL state,
5725 * so we can use text[GTK_STATE_NORMAL] as text color here */
5726 gtk_widget_style_get (widget, "cursor-color", &cursor_color, NULL);
5729 cursor_info->primary = *cursor_color;
5730 gdk_color_free (cursor_color);
5734 cursor_info->primary = style->text[GTK_STATE_NORMAL];
5737 gtk_widget_style_get (widget, "secondary-cursor-color", &cursor_color, NULL);
5740 cursor_info->secondary = *cursor_color;
5741 gdk_color_free (cursor_color);
5745 /* text_aa is the average of text and base colors,
5746 * in usual black-on-white case it's grey. */
5747 cursor_info->secondary = style->text_aa[GTK_STATE_NORMAL];
5752 return &cursor_info->primary;
5754 return &cursor_info->secondary;
5758 _gtk_widget_get_cursor_color (GtkWidget *widget,
5761 GdkColor *style_color;
5763 g_return_if_fail (GTK_IS_WIDGET (widget));
5764 g_return_if_fail (color != NULL);
5766 gtk_widget_style_get (widget, "cursor-color", &style_color, NULL);
5770 *color = *style_color;
5771 gdk_color_free (style_color);
5774 *color = gtk_widget_get_style (widget)->text[GTK_STATE_NORMAL];
5778 draw_insertion_cursor (GtkWidget *widget,
5780 const GdkRectangle *location,
5781 GtkTextDirection direction,
5782 gboolean draw_arrow)
5787 gfloat cursor_aspect_ratio;
5790 /* When changing the shape or size of the cursor here,
5791 * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
5794 gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
5796 stem_width = location->height * cursor_aspect_ratio + 1;
5797 arrow_width = stem_width + 1;
5799 /* put (stem_width % 2) on the proper side of the cursor */
5800 if (direction == GTK_TEXT_DIR_LTR)
5801 offset = stem_width / 2;
5803 offset = stem_width - stem_width / 2;
5805 cairo_rectangle (cr,
5806 location->x - offset, location->y,
5807 stem_width, location->height);
5812 if (direction == GTK_TEXT_DIR_RTL)
5814 x = location->x - offset - 1;
5815 y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5817 cairo_move_to (cr, x, y + 1);
5818 cairo_line_to (cr, x - arrow_width, y + arrow_width);
5819 cairo_line_to (cr, x, y + 2 * arrow_width);
5822 else if (direction == GTK_TEXT_DIR_LTR)
5824 x = location->x + stem_width - offset;
5825 y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5827 cairo_move_to (cr, x, y + 1);
5828 cairo_line_to (cr, x + arrow_width, y + arrow_width);
5829 cairo_line_to (cr, x, y + 2 * arrow_width);
5836 * gtk_draw_insertion_cursor:
5837 * @widget: a #GtkWidget
5838 * @drawable: a #GdkDrawable
5839 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
5840 * output should not be clipped
5841 * @location: location where to draw the cursor (@location->width is ignored)
5842 * @is_primary: if the cursor should be the primary cursor color.
5843 * @direction: whether the cursor is left-to-right or
5844 * right-to-left. Should never be #GTK_TEXT_DIR_NONE
5845 * @draw_arrow: %TRUE to draw a directional arrow on the
5846 * cursor. Should be %FALSE unless the cursor is split.
5848 * Draws a text caret on @drawable at @location. This is not a style function
5849 * but merely a convenience function for drawing the standard cursor shape.
5854 gtk_draw_insertion_cursor (GtkWidget *widget,
5855 GdkDrawable *drawable,
5856 const GdkRectangle *area,
5857 const GdkRectangle *location,
5858 gboolean is_primary,
5859 GtkTextDirection direction,
5860 gboolean draw_arrow)
5864 g_return_if_fail (GTK_IS_WIDGET (widget));
5865 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
5866 g_return_if_fail (location != NULL);
5867 g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
5869 cr = gdk_cairo_create (drawable);
5872 gdk_cairo_rectangle (cr, area);
5876 gdk_cairo_set_source_color (cr, get_insertion_cursor_color (widget, is_primary));
5877 draw_insertion_cursor (widget, cr, location, direction, draw_arrow);