gtkstyle.c 118 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
28
#include <math.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <gobject/gvaluecollector.h>
32
#include "gtkmarshalers.h"
33
#include "gtkpango.h"
34
#include "gtkrc.h"
35
#include "gtkspinbutton.h"
Elliot Lee's avatar
Elliot Lee committed
36
#include "gtkstyle.h"
37
#include "gtkwidget.h"
38
#include "gtkthemes.h"
39
#include "gtkiconfactory.h"
40
#include "gtksettings.h"	/* _gtk_settings_parse_convert() */
Matthias Clasen's avatar
Matthias Clasen committed
41
#include "gtkintl.h"
Matthias Clasen's avatar
Matthias Clasen committed
42
#include "gtkdebug.h"
43
#include "gtkspinner.h"
Matthias Clasen's avatar
Matthias Clasen committed
44
#include "gtkborder.h"
Elliot Lee's avatar
Elliot Lee committed
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/**
 * SECTION:gtkstyle
 * @Short_description: An object that hold style information for widgets
 * @Title: GtkStyle
 *
 * A #GtkStyle object encapsulates the information that provides the look and
 * feel for a widget. Each #GtkWidget has an associated #GTkStyle object that
 * is used when rendering that widget. Also, a #GtkStyle holds information for
 * the five possible widget states though not every widget supports all five
 * states; see #GtkStateType.
 *
 * Usually the #GtkStyle for a widget is the same as the default style that is
 * set by GTK+ and modified the theme engine.
 *
 * Usually applications should not need to use or modify the #GtkStyle of their
 * widgets.
Matthias Clasen's avatar
Matthias Clasen committed
63
 *
Matthias Clasen's avatar
Matthias Clasen committed
64
 * <warning>
Matthias Clasen's avatar
Matthias Clasen committed
65
 * In GTK+ 3.0, GtkStyle has been deprecated and replaced by #GtkStyleContext.
Matthias Clasen's avatar
Matthias Clasen committed
66
 * </warning>
67 68 69
 */


Elliot Lee's avatar
Elliot Lee committed
70 71 72
#define LIGHTNESS_MULT  1.3
#define DARKNESS_MULT   0.7

73 74 75 76 77 78 79
/* --- typedefs & structures --- */
typedef struct {
  GType       widget_type;
  GParamSpec *pspec;
  GValue      value;
} PropertyValue;

80 81 82 83 84
#define GTK_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_STYLE, GtkStylePrivate))

typedef struct _GtkStylePrivate GtkStylePrivate;

struct _GtkStylePrivate {
85
  GtkStyleContext *context;
86
  gulong context_changed_id;
87 88 89 90 91
};

enum {
  PROP_0,
  PROP_CONTEXT
92 93
};

94 95
/* --- prototypes --- */
static void	 gtk_style_finalize		(GObject	*object);
96 97 98 99 100
static void	 gtk_style_constructed		(GObject	*object);
static void      gtk_style_set_property         (GObject        *object,
                                                 guint           prop_id,
                                                 const GValue   *value,
                                                 GParamSpec     *pspec);
101 102 103 104
static void      gtk_style_get_property         (GObject        *object,
                                                 guint           prop_id,
                                                 GValue         *value,
                                                 GParamSpec     *pspec);
105

106 107 108 109 110 111 112 113 114 115
static void      gtk_style_real_realize        (GtkStyle	*style);
static void      gtk_style_real_unrealize      (GtkStyle	*style);
static void      gtk_style_real_copy           (GtkStyle	*style,
						GtkStyle	*src);
static void      gtk_style_real_set_background (GtkStyle	*style,
						GdkWindow	*window,
						GtkStateType	 state_type);
static GtkStyle *gtk_style_real_clone          (GtkStyle	*style);
static void      gtk_style_real_init_from_rc   (GtkStyle	*style,
                                                GtkRcStyle	*rc_style);
116 117 118 119
static GdkPixbuf *gtk_default_render_icon      (GtkStyle            *style,
                                                const GtkIconSource *source,
                                                GtkTextDirection     direction,
                                                GtkStateType         state,
120
                                                GtkIconSize          size,
121 122
                                                GtkWidget           *widget,
                                                const gchar         *detail);
123
static void gtk_default_draw_hline      (GtkStyle        *style,
124
					 cairo_t         *cr,
125 126 127 128 129 130 131
					 GtkStateType     state_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x1,
					 gint             x2,
					 gint             y);
static void gtk_default_draw_vline      (GtkStyle        *style,
132
					 cairo_t         *cr,
133 134 135 136 137 138 139
					 GtkStateType     state_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             y1,
					 gint             y2,
					 gint             x);
static void gtk_default_draw_shadow     (GtkStyle        *style,
140
					 cairo_t         *cr,
141 142 143 144 145 146 147 148 149
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_arrow      (GtkStyle        *style,
150
					 cairo_t         *cr,
151 152 153 154 155 156 157 158 159 160 161
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 GtkArrowType     arrow_type,
					 gboolean         fill,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_diamond    (GtkStyle        *style,
162
					 cairo_t         *cr,
163 164 165 166 167 168 169 170 171
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_box        (GtkStyle        *style,
172
					 cairo_t         *cr,
173 174 175 176 177 178 179 180 181
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_flat_box   (GtkStyle        *style,
182
					 cairo_t         *cr,
183 184 185 186 187 188 189 190 191
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_check      (GtkStyle        *style,
192
					 cairo_t         *cr,
193 194 195 196 197 198 199 200 201
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_option     (GtkStyle        *style,
202
					 cairo_t         *cr,
203 204 205 206 207 208 209 210 211
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_tab        (GtkStyle        *style,
212
					 cairo_t         *cr,
213 214 215 216 217 218 219 220 221
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_shadow_gap (GtkStyle        *style,
222
					 cairo_t         *cr,
223 224 225 226 227 228 229 230 231 232 233 234
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 GtkPositionType  gap_side,
					 gint             gap_x,
					 gint             gap_width);
static void gtk_default_draw_box_gap    (GtkStyle        *style,
235
					 cairo_t         *cr,
236 237 238 239 240 241 242 243 244 245 246 247
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 GtkPositionType  gap_side,
					 gint             gap_x,
					 gint             gap_width);
static void gtk_default_draw_extension  (GtkStyle        *style,
248
					 cairo_t         *cr,
249 250 251 252 253 254 255 256 257 258
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 GtkPositionType  gap_side);
static void gtk_default_draw_focus      (GtkStyle        *style,
259
					 cairo_t         *cr,
260
					 GtkStateType     state_type,
261 262 263 264 265 266 267
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
static void gtk_default_draw_slider     (GtkStyle        *style,
268
					 cairo_t         *cr,
269 270 271 272 273 274 275 276 277 278
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 GtkOrientation   orientation);
static void gtk_default_draw_handle     (GtkStyle        *style,
279
					 cairo_t         *cr,
280 281 282 283 284 285 286 287 288
					 GtkStateType     state_type,
					 GtkShadowType    shadow_type,
					 GtkWidget       *widget,
					 const gchar     *detail,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 GtkOrientation   orientation);
289
static void gtk_default_draw_expander   (GtkStyle        *style,
290
                                         cairo_t         *cr,
291 292 293 294 295
                                         GtkStateType     state_type,
                                         GtkWidget       *widget,
                                         const gchar     *detail,
                                         gint             x,
                                         gint             y,
296
					 GtkExpanderStyle expander_style);
297
static void gtk_default_draw_layout     (GtkStyle        *style,
298
                                         cairo_t         *cr,
299
                                         GtkStateType     state_type,
300
					 gboolean         use_text,
301 302 303 304 305
                                         GtkWidget       *widget,
                                         const gchar     *detail,
                                         gint             x,
                                         gint             y,
                                         PangoLayout     *layout);
Owen Taylor's avatar
Owen Taylor committed
306
static void gtk_default_draw_resize_grip (GtkStyle       *style,
307
                                          cairo_t        *cr,
Owen Taylor's avatar
Owen Taylor committed
308 309 310 311 312 313 314 315
                                          GtkStateType    state_type,
                                          GtkWidget      *widget,
                                          const gchar    *detail,
                                          GdkWindowEdge   edge,
                                          gint            x,
                                          gint            y,
                                          gint            width,
                                          gint            height);
316
static void gtk_default_draw_spinner     (GtkStyle       *style,
317
                                          cairo_t        *cr,
318 319 320 321 322 323 324 325
					  GtkStateType    state_type,
                                          GtkWidget      *widget,
                                          const gchar    *detail,
					  guint           step,
					  gint            x,
					  gint            y,
					  gint            width,
					  gint            height);
Owen Taylor's avatar
Owen Taylor committed
326

327 328 329 330 331 332 333
static void rgb_to_hls			(gdouble	 *r,
					 gdouble	 *g,
					 gdouble	 *b);
static void hls_to_rgb			(gdouble	 *h,
					 gdouble	 *l,
					 gdouble	 *s);

334 335 336
static void transform_detail_string (const gchar     *detail,
                                     GtkStyleContext *context);

337 338 339 340
/*
 * Data for default check and radio buttons
 */

341 342
static const GtkRequisition default_option_indicator_size = { 7, 13 };
static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
343

Soeren Sandmann's avatar
Soeren Sandmann committed
344 345 346 347 348 349 350 351
#define GTK_GRAY		0xdcdc, 0xdada, 0xd5d5
#define GTK_DARK_GRAY		0xc4c4, 0xc2c2, 0xbdbd
#define GTK_LIGHT_GRAY		0xeeee, 0xebeb, 0xe7e7
#define GTK_WHITE		0xffff, 0xffff, 0xffff
#define GTK_BLUE		0x4b4b, 0x6969, 0x8383
#define GTK_VERY_DARK_GRAY	0x9c9c, 0x9a9a, 0x9494
#define GTK_BLACK		0x0000, 0x0000, 0x0000
#define GTK_WEAK_GRAY		0x7530, 0x7530, 0x7530
352

353
/* --- variables --- */
Soeren Sandmann's avatar
Soeren Sandmann committed
354 355 356 357 358
static const GdkColor gtk_default_normal_fg =      { 0, GTK_BLACK };
static const GdkColor gtk_default_active_fg =      { 0, GTK_BLACK };
static const GdkColor gtk_default_prelight_fg =    { 0, GTK_BLACK };
static const GdkColor gtk_default_selected_fg =    { 0, GTK_WHITE };
static const GdkColor gtk_default_insensitive_fg = { 0, GTK_WEAK_GRAY };
359

Soeren Sandmann's avatar
Soeren Sandmann committed
360 361 362 363 364 365 366
static const GdkColor gtk_default_normal_bg =      { 0, GTK_GRAY };
static const GdkColor gtk_default_active_bg =      { 0, GTK_DARK_GRAY };
static const GdkColor gtk_default_prelight_bg =    { 0, GTK_LIGHT_GRAY };
static const GdkColor gtk_default_selected_bg =    { 0, GTK_BLUE };
static const GdkColor gtk_default_insensitive_bg = { 0, GTK_GRAY };
static const GdkColor gtk_default_selected_base =  { 0, GTK_BLUE };
static const GdkColor gtk_default_active_base =    { 0, GTK_VERY_DARK_GRAY };
Elliot Lee's avatar
Elliot Lee committed
367

368 369 370
/* --- signals --- */
static guint realize_signal = 0;
static guint unrealize_signal = 0;
371

Matthias Clasen's avatar
Matthias Clasen committed
372
G_DEFINE_TYPE (GtkStyle, gtk_style, G_TYPE_OBJECT)
Matthias Clasen's avatar
Matthias Clasen committed
373

374
/* --- functions --- */
Elliot Lee's avatar
Elliot Lee committed
375

376 377 378 379
static void
gtk_style_init (GtkStyle *style)
{
  gint i;
380 381 382

  style->font_desc = pango_font_description_from_string ("Sans 10");

Elliot Lee's avatar
Elliot Lee committed
383
  style->attach_count = 0;
384
  
Elliot Lee's avatar
Elliot Lee committed
385 386 387
  style->black.red = 0;
  style->black.green = 0;
  style->black.blue = 0;
388
  
Elliot Lee's avatar
Elliot Lee committed
389 390 391
  style->white.red = 65535;
  style->white.green = 65535;
  style->white.blue = 65535;
392
  
Elliot Lee's avatar
Elliot Lee committed
393 394 395 396 397
  style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
  style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
  style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
  style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
  style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
398
  
Elliot Lee's avatar
Elliot Lee committed
399 400 401 402 403
  style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
  style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
  style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
  style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
  style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
404
  
405
  for (i = 0; i < 4; i++)
Elliot Lee's avatar
Elliot Lee committed
406 407 408 409
    {
      style->text[i] = style->fg[i];
      style->base[i] = style->white;
    }
Havoc Pennington's avatar
Havoc Pennington committed
410

411
  style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
412
  style->text[GTK_STATE_SELECTED] = style->white;
413
  style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
414
  style->text[GTK_STATE_ACTIVE] = style->white;
Owen Taylor's avatar
Owen Taylor committed
415 416
  style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
  style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
417
  
418
  style->rc_style = NULL;
419
  
420 421
  style->xthickness = 2;
  style->ythickness = 2;
422 423

  style->property_cache = NULL;
424 425 426 427 428 429 430 431
}

static void
gtk_style_class_init (GtkStyleClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  
  object_class->finalize = gtk_style_finalize;
432
  object_class->set_property = gtk_style_set_property;
433
  object_class->get_property = gtk_style_get_property;
434
  object_class->constructed = gtk_style_constructed;
435

436 437 438 439 440 441
  klass->clone = gtk_style_real_clone;
  klass->copy = gtk_style_real_copy;
  klass->init_from_rc = gtk_style_real_init_from_rc;
  klass->realize = gtk_style_real_realize;
  klass->unrealize = gtk_style_real_unrealize;
  klass->set_background = gtk_style_real_set_background;
442 443
  klass->render_icon = gtk_default_render_icon;

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
  klass->draw_hline = gtk_default_draw_hline;
  klass->draw_vline = gtk_default_draw_vline;
  klass->draw_shadow = gtk_default_draw_shadow;
  klass->draw_arrow = gtk_default_draw_arrow;
  klass->draw_diamond = gtk_default_draw_diamond;
  klass->draw_box = gtk_default_draw_box;
  klass->draw_flat_box = gtk_default_draw_flat_box;
  klass->draw_check = gtk_default_draw_check;
  klass->draw_option = gtk_default_draw_option;
  klass->draw_tab = gtk_default_draw_tab;
  klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
  klass->draw_box_gap = gtk_default_draw_box_gap;
  klass->draw_extension = gtk_default_draw_extension;
  klass->draw_focus = gtk_default_draw_focus;
  klass->draw_slider = gtk_default_draw_slider;
  klass->draw_handle = gtk_default_draw_handle;
460 461
  klass->draw_expander = gtk_default_draw_expander;
  klass->draw_layout = gtk_default_draw_layout;
Owen Taylor's avatar
Owen Taylor committed
462
  klass->draw_resize_grip = gtk_default_draw_resize_grip;
463
  klass->draw_spinner = gtk_default_draw_spinner;
464

465 466
  g_type_class_add_private (object_class, sizeof (GtkStylePrivate));

467 468 469 470 471 472
  g_object_class_install_property (object_class,
				   PROP_CONTEXT,
				   g_param_spec_object ("context",
 							P_("Style context"),
							P_("GtkStyleContext to get style from"),
                                                        GTK_TYPE_STYLE_CONTEXT,
473
                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
474

475 476 477 478 479
  /**
   * GtkStyle::realize:
   * @style: the object which received the signal
   *
   * Emitted when the style has been initialized for a particular
480
   * visual. Connecting to this signal is probably seldom
481 482
   * useful since most of the time applications and widgets only
   * deal with styles that have been already realized.
483 484
   *
   * Since: 2.4
485
   */
Matthias Clasen's avatar
Matthias Clasen committed
486
  realize_signal = g_signal_new (I_("realize"),
487 488 489 490 491 492 493 494 495 496
				 G_TYPE_FROM_CLASS (object_class),
				 G_SIGNAL_RUN_FIRST,
				 G_STRUCT_OFFSET (GtkStyleClass, realize),
				 NULL, NULL,
				 _gtk_marshal_VOID__VOID,
				 G_TYPE_NONE, 0);
  /**
   * GtkStyle::unrealize:
   * @style: the object which received the signal
   *
497
   * Emitted when the aspects of the style specific to a particular visual
498
   * is being cleaned up. A connection to this signal can be useful
499
   * if a widget wants to cache objects as object data on #GtkStyle.
500
   * This signal provides a convenient place to free such cached objects.
501 502
   *
   * Since: 2.4
503
   */
Matthias Clasen's avatar
Matthias Clasen committed
504
  unrealize_signal = g_signal_new (I_("unrealize"),
505 506 507 508 509 510
				   G_TYPE_FROM_CLASS (object_class),
				   G_SIGNAL_RUN_FIRST,
				   G_STRUCT_OFFSET (GtkStyleClass, unrealize),
				   NULL, NULL,
				   _gtk_marshal_VOID__VOID,
				   G_TYPE_NONE, 0);
511 512
}

513 514 515 516
static void
gtk_style_finalize (GObject *object)
{
  GtkStyle *style = GTK_STYLE (object);
517
  GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
518 519 520

  g_return_if_fail (style->attach_count == 0);

Matthias Clasen's avatar
Matthias Clasen committed
521 522 523 524 525 526 527
  /* All the styles in the list have the same 
   * style->styles pointer. If we delete the 
   * *first* style from the list, we need to update
   * the style->styles pointers from all the styles.
   * Otherwise we simply remove the node from
   * the list.
   */
528 529 530
  if (style->styles)
    {
      if (style->styles->data != style)
531
        style->styles = g_slist_remove (style->styles, style);
532 533 534 535 536 537
      else
        {
          GSList *tmp_list = style->styles->next;
	  
          while (tmp_list)
            {
538
              GTK_STYLE (tmp_list->data)->styles = style->styles->next;
539 540 541 542 543
              tmp_list = tmp_list->next;
            }
          g_slist_free_1 (style->styles);
        }
    }
544

545 546
  g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
  g_slist_free (style->icon_factories);
547

548
  pango_font_description_free (style->font_desc);
549 550 551

  if (style->private_font_desc)
    pango_font_description_free (style->private_font_desc);
552

553
  if (style->rc_style)
554 555
    g_object_unref (style->rc_style);

556
  if (priv->context)
557 558 559 560 561 562
    {
      if (priv->context_changed_id)
        g_signal_handler_disconnect (priv->context, priv->context_changed_id);

      g_object_unref (priv->context);
    }
563

Matthias Clasen's avatar
Matthias Clasen committed
564
  G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
565 566
}

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
static void
gtk_style_set_property (GObject      *object,
                        guint         prop_id,
                        const GValue *value,
                        GParamSpec   *pspec)
{
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (object);

  switch (prop_id)
    {
    case PROP_CONTEXT:
      priv->context = g_value_dup_object (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
static void
gtk_style_get_property (GObject      *object,
                        guint         prop_id,
                        GValue       *value,
                        GParamSpec   *pspec)
{
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (object);

  switch (prop_id)
    {
    case PROP_CONTEXT:
      g_value_set_object (value, priv->context);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

609 610 611 612 613 614
static void
set_color (GtkStyle        *style,
           GtkStyleContext *context,
           GtkStateType     state,
           GtkRcFlags       prop)
{
Carlos Garnacho's avatar
Carlos Garnacho committed
615
  GtkStateFlags flags;
616 617
  GdkRGBA *color = NULL;
  GdkColor *dest = { 0 }; /* Shut up gcc */
618

Carlos Garnacho's avatar
Carlos Garnacho committed
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
  switch (state)
    {
    case GTK_STATE_ACTIVE:
      flags = GTK_STATE_FLAG_ACTIVE;
      break;
    case GTK_STATE_PRELIGHT:
      flags = GTK_STATE_FLAG_PRELIGHT;
      break;
    case GTK_STATE_SELECTED:
      flags = GTK_STATE_FLAG_SELECTED;
      break;
    case GTK_STATE_INSENSITIVE:
      flags = GTK_STATE_FLAG_INSENSITIVE;
      break;
    default:
      flags = 0;
    }

637 638 639
  switch (prop)
    {
    case GTK_RC_BG:
Carlos Garnacho's avatar
Carlos Garnacho committed
640
      gtk_style_context_get (context, flags,
641 642
                             "background-color", &color,
                             NULL);
643
      dest = &style->bg[state];
644 645
      break;
    case GTK_RC_FG:
Carlos Garnacho's avatar
Carlos Garnacho committed
646
      gtk_style_context_get (context, flags,
Carlos Garnacho's avatar
Carlos Garnacho committed
647
                             "color", &color,
648
                             NULL);
649
      dest = &style->fg[state];
650 651
      break;
    case GTK_RC_TEXT:
Carlos Garnacho's avatar
Carlos Garnacho committed
652
      gtk_style_context_get (context, flags,
Carlos Garnacho's avatar
Carlos Garnacho committed
653
                             "color", &color,
654
                             NULL);
655
      dest = &style->text[state];
656 657
      break;
    case GTK_RC_BASE:
Carlos Garnacho's avatar
Carlos Garnacho committed
658
      gtk_style_context_get (context, flags,
Carlos Garnacho's avatar
Carlos Garnacho committed
659
                             "background-color", &color,
660
                             NULL);
661
      dest = &style->base[state];
662 663 664 665
      break;
    }

  if (color)
666 667 668 669 670 671 672
    {
      dest->pixel = 0;
      dest->red = CLAMP ((guint) (color->red * 65535), 0, 65535);
      dest->green = CLAMP ((guint) (color->green * 65535), 0, 65535);
      dest->blue = CLAMP ((guint) (color->blue * 65535), 0, 65535);
      gdk_rgba_free (color);
    }
673 674 675 676 677 678 679
}

static void
gtk_style_update_from_context (GtkStyle *style)
{
  GtkStylePrivate *priv;
  GtkStateType state;
680
  GtkBorder *padding;
681
  gint i;
682 683 684 685 686

  priv = GTK_STYLE_GET_PRIVATE (style);

  for (state = GTK_STATE_NORMAL; state <= GTK_STATE_INSENSITIVE; state++)
    {
Carlos Garnacho's avatar
Carlos Garnacho committed
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
      if (gtk_style_context_has_class (priv->context, "entry"))
        {
          gtk_style_context_save (priv->context);
          gtk_style_context_remove_class (priv->context, "entry");
          set_color (style, priv->context, state, GTK_RC_BG);
          set_color (style, priv->context, state, GTK_RC_FG);
          gtk_style_context_restore (priv->context);

          set_color (style, priv->context, state, GTK_RC_BASE);
          set_color (style, priv->context, state, GTK_RC_TEXT);
        }
      else
        {
          gtk_style_context_save (priv->context);
          gtk_style_context_add_class (priv->context, "entry");
          set_color (style, priv->context, state, GTK_RC_BASE);
          set_color (style, priv->context, state, GTK_RC_TEXT);
          gtk_style_context_restore (priv->context);

          set_color (style, priv->context, state, GTK_RC_BG);
          set_color (style, priv->context, state, GTK_RC_FG);
        }
709 710
    }

711 712 713
  if (style->font_desc)
    pango_font_description_free (style->font_desc);

714
  gtk_style_context_get (priv->context, 0,
715 716 717 718
                         "font", &style->font_desc,
                         "padding", &padding,
                         NULL);

719 720 721 722
  if (padding)
    {
      style->xthickness = padding->left;
      style->ythickness = padding->top;
723

724 725
      gtk_border_free (padding);
    }
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752

  for (i = 0; i < 5; i++)
    {
      _gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
      _gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);

      style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
      style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
      style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;

      style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
      style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
      style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
    }

  style->black.red = 0x0000;
  style->black.green = 0x0000;
  style->black.blue = 0x0000;

  style->white.red = 0xffff;
  style->white.green = 0xffff;
  style->white.blue = 0xffff;

  for (i = 0; i < 5; i++)
    style->background[i] = cairo_pattern_create_rgb (style->bg[i].red / 65535.0,
                                                     style->bg[i].green / 65535.0,
                                                     style->bg[i].blue / 65535.0);
753 754
}

755 756 757 758 759 760 761
static void
style_context_changed (GtkStyleContext *context,
                       gpointer         user_data)
{
  gtk_style_update_from_context (GTK_STYLE (user_data));
}

762 763 764 765 766 767 768 769 770 771 772
static void
gtk_style_constructed (GObject *object)
{
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (object);

  if (priv->context)
    {
      gtk_style_update_from_context (GTK_STYLE (object));

773 774
      priv->context_changed_id = g_signal_connect (priv->context, "changed",
                                                   G_CALLBACK (style_context_changed), object);
775 776
    }
}
777

Matthias Clasen's avatar
Matthias Clasen committed
778 779 780 781 782 783
/**
 * gtk_style_copy:
 * @style: a #GtkStyle
 *
 * Creates a copy of the passed in #GtkStyle object.
 *
Matthias Clasen's avatar
Matthias Clasen committed
784
 * Returns: (transfer full): a copy of @style
785 786
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
Matthias Clasen's avatar
Matthias Clasen committed
787
 */
788 789 790 791 792
GtkStyle*
gtk_style_copy (GtkStyle *style)
{
  GtkStyle *new_style;
  
793
  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
794
  
795 796
  new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
  GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
797 798 799 800

  return new_style;
}

Matthias Clasen's avatar
Matthias Clasen committed
801 802 803 804 805
/**
 * gtk_style_new:
 * @returns: a new #GtkStyle.
 *
 * Creates a new #GtkStyle.
806 807
 *
 * Deprecated: 3.0: Use #GtkStyleContext
Matthias Clasen's avatar
Matthias Clasen committed
808
 **/
809 810 811
GtkStyle*
gtk_style_new (void)
{
812 813
  GtkStyleContext *context;
  GtkWidgetPath *path;
814
  GtkStyle *style;
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829

  context = gtk_style_context_new ();
  gtk_style_context_set_screen (context, gdk_screen_get_default ());

  path = gtk_widget_path_new ();
  gtk_widget_path_append_type (path, GTK_TYPE_WIDGET);
  gtk_style_context_set_path (context, path);

  style = g_object_new (GTK_TYPE_STYLE,
                        "context", context,
                        NULL);

  g_object_unref (context);
  gtk_widget_path_free (path);

Elliot Lee's avatar
Elliot Lee committed
830 831 832
  return style;
}

833 834 835 836 837 838 839 840 841 842
gboolean
gtk_style_has_context (GtkStyle *style)
{
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (style);

  return priv->context != NULL;
}

Matthias Clasen's avatar
Matthias Clasen committed
843
/**
844
 * gtk_style_attach:
Matthias Clasen's avatar
Matthias Clasen committed
845
 * @style: a #GtkStyle.
846
 * @window: a #GdkWindow.
847
 *
Matthias Clasen's avatar
Matthias Clasen committed
848 849
 * Attaches a style to a window; this process allocates the
 * colors and creates the GC's for the style - it specializes
850 851 852
 * it to a particular visual. The process may involve the creation
 * of a new style if the style has already been attached to a
 * window with a different style and visual.
853
 *
Matthias Clasen's avatar
Matthias Clasen committed
854 855
 * Since this function may return a new object, you have to use it
 * in the following way:
856
 * <literal>style = gtk_style_attach (style, window)</literal>
857 858 859 860 861
 *
 * Returns: Either @style, or a newly-created #GtkStyle.
 *   If the style is newly created, the style parameter
 *   will be unref'ed, and the new style will have
 *   a reference count belonging to the caller.
862 863
 *
 * Deprecated:3.0: Use gtk_widget_style_attach() instead
864
 */
865
GtkStyle*
Elliot Lee's avatar
Elliot Lee committed
866
gtk_style_attach (GtkStyle  *style,
867
                  GdkWindow *window)
Elliot Lee's avatar
Elliot Lee committed
868
{
869
  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
Elliot Lee's avatar
Elliot Lee committed
870
  g_return_val_if_fail (window != NULL, NULL);
Matthias Clasen's avatar
Matthias Clasen committed
871

872
  return style;
Elliot Lee's avatar
Elliot Lee committed
873 874
}

875 876 877 878 879 880
/**
 * gtk_style_detach:
 * @style: a #GtkStyle
 *
 * Detaches a style from a window. If the style is not attached
 * to any windows anymore, it is unrealized. See gtk_style_attach().
881 882
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
883
 */
Elliot Lee's avatar
Elliot Lee committed
884 885 886
void
gtk_style_detach (GtkStyle *style)
{
887
  g_return_if_fail (GTK_IS_STYLE (style));
888 889
}

Matthias Clasen's avatar
Matthias Clasen committed
890 891 892 893 894 895 896 897 898 899
/**
 * gtk_style_lookup_icon_set:
 * @style: a #GtkStyle
 * @stock_id: an icon name
 *
 * Looks up @stock_id in the icon factories associated with @style
 * and the default icon factory, returning an icon set if found,
 * otherwise %NULL.
 *
 * Return value: icon set of @stock_id
900 901
 *
 * Deprecated:3.0: Use gtk_style_context_lookup_icon_set() instead
Matthias Clasen's avatar
Matthias Clasen committed
902
 */
903 904 905 906
GtkIconSet*
gtk_style_lookup_icon_set (GtkStyle   *style,
                           const char *stock_id)
{
907
  GtkStylePrivate *priv;
908 909 910 911

  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
  g_return_val_if_fail (stock_id != NULL, NULL);

912 913
  priv = GTK_STYLE_GET_PRIVATE (style);

914 915 916 917
  if (priv->context)
    return gtk_style_context_lookup_icon_set (priv->context, stock_id);

  return gtk_icon_factory_lookup_default (stock_id);
918 919
}

920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
/**
 * gtk_style_lookup_color:
 * @style: a #GtkStyle
 * @color_name: the name of the logical color to look up
 * @color: the #GdkColor to fill in
 *
 * Looks up @color_name in the style's logical color mappings,
 * filling in @color and returning %TRUE if found, otherwise
 * returning %FALSE. Do not cache the found mapping, because
 * it depends on the #GtkStyle and might change when a theme
 * switch occurs.
 *
 * Return value: %TRUE if the mapping was found.
 *
 * Since: 2.10
935 936
 *
 * Deprecated:3.0: Use gtk_style_context_lookup_color() instead
937 938 939 940 941 942 943
 **/
gboolean
gtk_style_lookup_color (GtkStyle   *style,
                        const char *color_name,
                        GdkColor   *color)
{
  GtkStylePrivate *priv;
944 945
  gboolean result;
  GdkRGBA rgba;
946 947 948 949 950 951 952

  g_return_val_if_fail (GTK_IS_STYLE (style), FALSE);
  g_return_val_if_fail (color_name != NULL, FALSE);
  g_return_val_if_fail (color != NULL, FALSE);

  priv = GTK_STYLE_GET_PRIVATE (style);

953 954
  if (!priv->context)
    return FALSE;
955

956 957 958 959 960 961 962 963 964 965 966
  result = gtk_style_context_lookup_color (priv->context, color_name, &rgba);

  if (color)
    {
      color->red = (guint16) (rgba.red * 65535);
      color->green = (guint16) (rgba.green * 65535);
      color->blue = (guint16) (rgba.blue * 65535);
      color->pixel = 0;
    }

  return result;
967 968
}

Matthias Clasen's avatar
Matthias Clasen committed
969 970 971 972 973 974 975 976
/**
 * gtk_style_set_background:
 * @style: a #GtkStyle
 * @window: a #GdkWindow
 * @state_type: a state
 * 
 * Sets the background of @window to the background color or pixmap
 * specified by @style for the given state.
977 978
 *
 * Deprecated:3.0: Use gtk_style_context_set_background() instead
Matthias Clasen's avatar
Matthias Clasen committed
979
 */
980
void
981 982 983
gtk_style_set_background (GtkStyle    *style,
                          GdkWindow   *window,
                          GtkStateType state_type)
984
{
985
  g_return_if_fail (GTK_IS_STYLE (style));
986 987
  g_return_if_fail (window != NULL);
  
988 989 990 991 992 993 994
  GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
}

/* Default functions */
static GtkStyle *
gtk_style_real_clone (GtkStyle *style)
{
995 996 997 998 999 1000 1001
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (style);

  return g_object_new (G_OBJECT_TYPE (style),
                       "context", priv->context,
                       NULL);
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
}

static void
gtk_style_real_copy (GtkStyle *style,
		     GtkStyle *src)
{
  gint i;
  
  for (i = 0; i < 5; i++)
    {
      style->fg[i] = src->fg[i];
      style->bg[i] = src->bg[i];
      style->text[i] = src->text[i];
      style->base[i] = src->base[i];
Matthias Clasen's avatar
Matthias Clasen committed
1016

1017 1018 1019 1020 1021
      if (style->background[i])
	cairo_pattern_destroy (style->background[i]),
      style->background[i] = src->background[i];
      if (style->background[i])
	cairo_pattern_reference (style->background[i]);
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
    }

  if (style->font_desc)
    pango_font_description_free (style->font_desc);
  if (src->font_desc)
    style->font_desc = pango_font_description_copy (src->font_desc);
  else
    style->font_desc = NULL;
  
  style->xthickness = src->xthickness;
  style->ythickness = src->ythickness;

  if (style->rc_style)
1035
    g_object_unref (style->rc_style);
1036 1037
  style->rc_style = src->rc_style;
  if (src->rc_style)
1038
    g_object_ref (src->rc_style);
1039

1040 1041 1042 1043
  g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
  g_slist_free (style->icon_factories);
  style->icon_factories = g_slist_copy (src->icon_factories);
  g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
1044 1045 1046 1047 1048 1049
}

static void
gtk_style_real_init_from_rc (GtkStyle   *style,
			     GtkRcStyle *rc_style)
{
1050 1051
}

1052
/**
1053
 * gtk_style_get_style_property:
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
 * @style: a #GtkStyle
 * @widget_type: the #GType of a descendant of #GtkWidget
 * @property_name: the name of the style property to get
 * @value: a #GValue where the value of the property being
 *     queried will be stored
 *
 * Queries the value of a style property corresponding to a
 * widget class is in the given style.
 *
 * Since: 2.16
 */
void 
1066 1067 1068 1069
gtk_style_get_style_property (GtkStyle     *style,
                              GType        widget_type,
                              const gchar *property_name,
                              GValue      *value)
1070
{
1071
  GtkStylePrivate *priv;
1072 1073