gtkstyle.c 137 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
Javier Jardon's avatar
Javier Jardon committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * 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/. 
 */

25
#include "config.h"
26 27 28

#define GDK_DISABLE_DEPRECATION_WARNINGS

Elliot Lee's avatar
Elliot Lee committed
29
#include <math.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <gobject/gvaluecollector.h>
33
#include "gtkmarshalers.h"
34
#include "gtkpango.h"
35
#include "gtkrc.h"
36
#include "gtkspinbutton.h"
Elliot Lee's avatar
Elliot Lee committed
37
#include "gtkstyle.h"
38
#include "gtkstylecontextprivate.h"
39
#include "gtkwidget.h"
40
#include "gtkwidgetprivate.h"
41
#include "gtkiconfactory.h"
42
#include "gtkintl.h"
43
#include "gtkdebug.h"
44
#include "gtkrender.h"
Matthias Clasen's avatar
Matthias Clasen committed
45
#include "gtkborder.h"
46
#include "gtkwidgetpath.h"
Elliot Lee's avatar
Elliot Lee committed
47

48 49
/**
 * SECTION:gtkstyle
Matthias Clasen's avatar
Matthias Clasen committed
50 51
 * @Short_description: Deprecated object that holds style information
 *     for widgets
52 53 54
 * @Title: GtkStyle
 *
 * A #GtkStyle object encapsulates the information that provides the look and
Matthias Clasen's avatar
Matthias Clasen committed
55
 * feel for a widget.
Matthias Clasen's avatar
Matthias Clasen committed
56
 *
57 58
 * > In GTK+ 3.0, GtkStyle has been deprecated and replaced by
 * > #GtkStyleContext.
Matthias Clasen's avatar
Matthias Clasen committed
59 60 61 62 63 64 65 66 67 68 69
 *
 * 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.
70 71 72
 */


Elliot Lee's avatar
Elliot Lee committed
73 74 75
#define LIGHTNESS_MULT  1.3
#define DARKNESS_MULT   0.7

76 77 78 79 80 81 82
/* --- typedefs & structures --- */
typedef struct {
  GType       widget_type;
  GParamSpec *pspec;
  GValue      value;
} PropertyValue;

83
typedef struct {
84
  GtkStyleContext *context;
85
  gulong context_changed_id;
86 87 88
} GtkStylePrivate;

#define GTK_STYLE_GET_PRIVATE(obj) ((GtkStylePrivate *) gtk_style_get_instance_private ((GtkStyle *) (obj)))
89 90 91 92

enum {
  PROP_0,
  PROP_CONTEXT
93 94
};

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

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

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

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

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

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

345 346 347 348 349 350 351 352
#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
353

354
/* --- variables --- */
355 356 357 358 359
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 };
360

361 362 363 364 365 366 367
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
368

369 370
static GQuark quark_default_style;

371 372 373
/* --- signals --- */
static guint realize_signal = 0;
static guint unrealize_signal = 0;
374

375
G_DEFINE_TYPE_WITH_PRIVATE (GtkStyle, gtk_style, G_TYPE_OBJECT)
Matthias Clasen's avatar
Matthias Clasen committed
376

377
/* --- functions --- */
Elliot Lee's avatar
Elliot Lee committed
378

379 380 381 382
static void
gtk_style_init (GtkStyle *style)
{
  gint i;
383 384 385

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

Elliot Lee's avatar
Elliot Lee committed
386
  style->attach_count = 0;
387
  
Elliot Lee's avatar
Elliot Lee committed
388 389 390
  style->black.red = 0;
  style->black.green = 0;
  style->black.blue = 0;
391
  
Elliot Lee's avatar
Elliot Lee committed
392 393 394
  style->white.red = 65535;
  style->white.green = 65535;
  style->white.blue = 65535;
395
  
Elliot Lee's avatar
Elliot Lee committed
396 397 398 399 400
  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;
401
  
Elliot Lee's avatar
Elliot Lee committed
402 403 404 405 406
  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;
407
  
408
  for (i = 0; i < 4; i++)
Elliot Lee's avatar
Elliot Lee committed
409 410 411 412
    {
      style->text[i] = style->fg[i];
      style->base[i] = style->white;
    }
Havoc Pennington's avatar
Havoc Pennington committed
413

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

  style->property_cache = NULL;
427 428 429 430 431 432 433 434
}

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

439 440 441 442 443 444
  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;
445 446
  klass->render_icon = gtk_default_render_icon;

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
  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;
463 464
  klass->draw_expander = gtk_default_draw_expander;
  klass->draw_layout = gtk_default_draw_layout;
Owen Taylor's avatar
Owen Taylor committed
465
  klass->draw_resize_grip = gtk_default_draw_resize_grip;
466
  klass->draw_spinner = gtk_default_draw_spinner;
467

468 469 470 471 472 473
  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,
474
                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
475

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

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

  g_return_if_fail (style->attach_count == 0);

523 524 525 526 527 528 529
  /* 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.
   */
530 531 532
  if (style->styles)
    {
      if (style->styles->data != style)
533
        style->styles = g_slist_remove (style->styles, style);
534 535 536 537 538 539
      else
        {
          GSList *tmp_list = style->styles->next;
	  
          while (tmp_list)
            {
540
              GTK_STYLE (tmp_list->data)->styles = style->styles->next;
541 542 543 544 545
              tmp_list = tmp_list->next;
            }
          g_slist_free_1 (style->styles);
        }
    }
546

Matthias Clasen's avatar
Matthias Clasen committed
547
  g_slist_free_full (style->icon_factories, g_object_unref);
548

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

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

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

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

      g_object_unref (priv->context);
    }
564

565 566 567 568 569 570
  for (i = 0; i < 5; i++)
    {
      if (style->background[i])
        cairo_pattern_destroy (style->background[i]);
    }

Matthias Clasen's avatar
Matthias Clasen committed
571
  G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
572 573
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
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;
    }
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
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;
    }
}

616 617 618 619 620
static gboolean
set_color_from_context (GtkStyle *style,
                        GtkStateType state,
                        GtkStyleContext *context,
                        GtkRcFlags prop)
621
{
622 623
  GdkRGBA *color = NULL;
  GdkColor *dest = { 0 }; /* Shut up gcc */
624 625 626
  GtkStateFlags flags;

  flags = gtk_style_context_get_state (context);
627 628 629 630

  switch (prop)
    {
    case GTK_RC_BG:
Carlos Garnacho's avatar
Carlos Garnacho committed
631
      gtk_style_context_get (context, flags,
632 633
                             "background-color", &color,
                             NULL);
634
      dest = &style->bg[state];
635 636
      break;
    case GTK_RC_FG:
Carlos Garnacho's avatar
Carlos Garnacho committed
637
      gtk_style_context_get (context, flags,
638
                             "color", &color,
639
                             NULL);
640
      dest = &style->fg[state];
641 642
      break;
    case GTK_RC_TEXT:
Carlos Garnacho's avatar
Carlos Garnacho committed
643
      gtk_style_context_get (context, flags,
644
                             "color", &color,
645
                             NULL);
646
      dest = &style->text[state];
647 648
      break;
    case GTK_RC_BASE:
Carlos Garnacho's avatar
Carlos Garnacho committed
649
      gtk_style_context_get (context, flags,
650
                             "background-color", &color,
651
                             NULL);
652
      dest = &style->base[state];
653 654 655
      break;
    }

656
  if (!color)
657 658
    return FALSE;

659 660 661 662 663 664
  if (!(color->alpha > 0.01))
    {
      gdk_rgba_free (color);
      return FALSE;
    }

665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
  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);

  return TRUE;
}

static void
set_color (GtkStyle        *style,
           GtkStyleContext *context,
           GtkStateType     state,
           GtkRcFlags       prop)
{
  /* Try to fill in the values from the associated GtkStyleContext.
   * Since fully-transparent black is a very common default (e.g. for 
   * background-color properties), and we must store the result in a GdkColor
   * to retain API compatibility, in case the fetched color is fully transparent
   * we give themes a fallback style class they can style, before using the
   * hardcoded default values.
   */
687
  if (!set_color_from_context (style, state, context, prop))
688
    {
689 690
      gtk_style_context_save (context);
      gtk_style_context_add_class (context, "gtkstyle-fallback");
691
      set_color_from_context (style, state, context, prop);
692
      gtk_style_context_restore (context);
693
    }
694 695 696 697 698 699 700
}

static void
gtk_style_update_from_context (GtkStyle *style)
{
  GtkStylePrivate *priv;
  GtkStateType state;
701
  GtkStateFlags flags;
702
  GtkBorder padding;
703
  gint i;
704 705 706 707 708

  priv = GTK_STYLE_GET_PRIVATE (style);

  for (state = GTK_STATE_NORMAL; state <= GTK_STATE_INSENSITIVE; state++)
    {
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
      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;
        }

      gtk_style_context_save (priv->context);
      gtk_style_context_set_state (priv->context, flags);

730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
      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);
        }
752 753

      gtk_style_context_restore (priv->context);
754 755
    }

756 757 758
  if (style->font_desc)
    pango_font_description_free (style->font_desc);

759 760
  flags = gtk_style_context_get_state (priv->context);
  gtk_style_context_get (priv->context, flags,
761 762
                         "font", &style->font_desc,
                         NULL);
763
  gtk_style_context_get_padding (priv->context, flags, &padding);
764

765 766
  style->xthickness = padding.left;
  style->ythickness = padding.top;
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790

  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++)
Carlos Garnacho's avatar
Carlos Garnacho committed
791 792 793 794 795 796 797 798
    {
      if (style->background[i])
        cairo_pattern_destroy (style->background[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);
    }
799 800
}

801 802 803 804 805 806 807
static void
style_context_changed (GtkStyleContext *context,
                       gpointer         user_data)
{
  gtk_style_update_from_context (GTK_STYLE (user_data));
}

808 809 810 811 812 813 814 815 816 817 818
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));

819 820
      priv->context_changed_id = g_signal_connect (priv->context, "changed",
                                                   G_CALLBACK (style_context_changed), object);
821 822
    }
}
823

Matthias Clasen's avatar
Matthias Clasen committed
824 825 826 827 828 829
/**
 * gtk_style_copy:
 * @style: a #GtkStyle
 *
 * Creates a copy of the passed in #GtkStyle object.
 *
830
 * Returns: (transfer full): a copy of @style
831 832
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
Matthias Clasen's avatar
Matthias Clasen committed
833
 */
834 835 836 837 838
GtkStyle*
gtk_style_copy (GtkStyle *style)
{
  GtkStyle *new_style;
  
839
  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
840
  
841 842
  new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
  GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
843 844 845 846

  return new_style;
}

847 848
GtkStyle*
_gtk_style_new_for_path (GdkScreen     *screen,
849
                         GtkWidgetPath *path)
850 851 852 853 854
{
  GtkStyleContext *context;
  GtkStyle *style;

  context = gtk_style_context_new ();
855 856 857

  if (screen)
    gtk_style_context_set_screen (context, screen);
858

859 860 861 862 863 864 865 866 867 868 869
  gtk_style_context_set_path (context, path);

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

  g_object_unref (context);

  return style;
}

Matthias Clasen's avatar
Matthias Clasen committed
870 871 872 873
/**
 * gtk_style_new:
 *
 * Creates a new #GtkStyle.
874
 *
Matthias Clasen's avatar
Matthias Clasen committed
875 876
 * Returns: a new #GtkStyle.
 *
877
 * Deprecated: 3.0: Use #GtkStyleContext
Matthias Clasen's avatar
Matthias Clasen committed
878
 */
879 880 881
GtkStyle*
gtk_style_new (void)
{
882
  GtkWidgetPath *path;
883
  GtkStyle *style;
884 885 886 887

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

888
  style = _gtk_style_new_for_path (gdk_screen_get_default (), path);
889 890 891

  gtk_widget_path_free (path);

Elliot Lee's avatar
Elliot Lee committed
892 893 894
  return style;
}

895 896 897 898 899 900 901 902 903 904
/**
 * gtk_style_has_context:
 * @style: a #GtkStyle
 *
 * Returns whether @style has an associated #GtkStyleContext.
 *
 * Returns: %TRUE if @style has a #GtkStyleContext
 *
 * Since: 3.0
 */
905 906 907 908 909 910 911 912 913 914
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
915
/**
916
 * gtk_style_attach: (skip)
Matthias Clasen's avatar
Matthias Clasen committed
917
 * @style: a #GtkStyle.
918
 * @window: a #GdkWindow.
919
 *
Matthias Clasen's avatar
Matthias Clasen committed
920
 * Attaches a style to a window; this process allocates the
921
 * colors and creates the GC’s for the style - it specializes
922 923 924
 * 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.
925
 *
926 927
 * Since this function may return a new object, you have to use it
 * in the following way:
928
 * `style = gtk_style_attach (style, window)`
929 930 931 932 933
 *
 * 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.
934 935
 *
 * Deprecated:3.0: Use gtk_widget_style_attach() instead
936
 */
937
GtkStyle*
Elliot Lee's avatar
Elliot Lee committed
938
gtk_style_attach (GtkStyle  *style,
939
                  GdkWindow *window)
Elliot Lee's avatar
Elliot Lee committed
940
{
941
  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
Elliot Lee's avatar
Elliot Lee committed
942
  g_return_val_if_fail (window != NULL, NULL);
943

944
  return style;
Elliot Lee's avatar
Elliot Lee committed
945 946
}

947 948 949 950 951 952
/**
 * 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().
953 954
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
955
 */
Elliot Lee's avatar
Elliot Lee committed
956 957 958
void
gtk_style_detach (GtkStyle *style)
{
959
  g_return_if_fail (GTK_IS_STYLE (style));
960 961
}

Matthias Clasen's avatar
Matthias Clasen committed
962 963 964 965 966 967 968 969 970
/**
 * 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.
 *
971
 * Returns: (transfer none): icon set of @stock_id
972 973
 *
 * Deprecated:3.0: Use gtk_style_context_lookup_icon_set() instead
Matthias Clasen's avatar
Matthias Clasen committed
974
 */
975 976 977 978
GtkIconSet*
gtk_style_lookup_icon_set (GtkStyle   *style,
                           const char *stock_id)
{
979
  GtkStylePrivate *priv;
980 981 982 983

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

984 985
  priv = GTK_STYLE_GET_PRIVATE (style);

986 987 988 989
  if (priv->context)
    return gtk_style_context_lookup_icon_set (priv->context, stock_id);

  return gtk_icon_factory_lookup_default (stock_id);
990 991
}

992 993 994 995
/**
 * gtk_style_lookup_color:
 * @style: a #GtkStyle
 * @color_name: the name of the logical color to look up
996
 * @color: (out): the #GdkColor to fill in
997
 *
998
 * Looks up @color_name in the style’s logical color mappings,
999 1000 1001 1002 1003
 * 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.
 *
1004
 * Returns: %TRUE if the mapping was found.
1005 1006
 *
 * Since: 2.10
1007 1008
 *
 * Deprecated:3.0: Use gtk_style_context_lookup_color() instead
1009 1010 1011 1012 1013 1014 1015
 **/
gboolean
gtk_style_lookup_color (GtkStyle   *style,
                        const char *color_name,
                        GdkColor   *color)
{
  GtkStylePrivate *priv;
1016 1017
  gboolean result;
  GdkRGBA rgba;
1018 1019 1020 1021 1022 1023 1024

  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);

1025 1026
  if (!priv->context)
    return FALSE;
1027

1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
  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;
1039 1040
}

1041 1042 1043 1044 1045 1046 1047 1048
/**
 * 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.
1049 1050
 *
 * Deprecated:3.0: Use gtk_style_context_set_background() instead
1051
 */
1052
void
1053 1054 1055
gtk_style_set_background (GtkStyle    *style,
                          GdkWindow   *window,
                          GtkStateType state_type)
1056
{
1057
  g_return_if_fail (GTK_IS_STYLE (style));
1058 1059
  g_return_if_fail (window != NULL);
  
1060 1061 1062 1063 1064 1065 1066
  GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
}

/* Default functions */
static GtkStyle *
gtk_style_real_clone (GtkStyle *style)
{
1067 1068 1069 1070 1071 1072 1073
  GtkStylePrivate *priv;

  priv = GTK_STYLE_GET_PRIVATE (style);

  return g_object_new (G_OBJECT_TYPE (style),
                       "context", priv->context,
                       NULL);
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
}

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];
1088

1089 1090 1091 1092 1093
      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]);
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
    }

  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)
1107
    g_object_unref (style->rc_style);
1108 1109
  style->rc_style = src->rc_style;
  if (src->rc_style)
1110
    g_object_ref (src->rc_style);
1111

Matthias Clasen's avatar
Matthias Clasen committed
1112
  g_slist_free_full (style->icon_factories, g_object_unref);
1113 1114
  style->icon_factories = g_slist_copy (src->icon_factories);
  g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
1115 1116 1117 1118 1119 1120
}

static void
gtk_style_real_init_from_rc (GtkStyle   *style,
			     GtkRcStyle *rc_style)
{
1121 1122
}

1123
/**
1124
 * gtk_style_get_style_property:
1125 1126 1127
 * @style: a #GtkStyle
 * @widget_type: the #GType of a descendant of #GtkWidget
 * @property_name: the name of the style property to get
1128
 * @value: (out): a #GValue where the value of the property being
1129 1130 1131 1132 1133 1134 1135 1136
 *     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 
1137 1138 1139 1140
gtk_style_get_style_property (GtkStyle     *style,
                              GType        widget_type,
                              const gchar *property_name,
                              GValue      *value)
1141
{
1142
  GtkStylePrivate *priv;
1143 1144 1145 1146
  GtkWidgetClass *klass;
  GParamSpec *pspec;
  const GValue *peek_value;

1147
  klass = g_type_class_ref (widget_type);
1148
  pspec = gtk_widget_class_find_style_property (klass, property_name);
1149
  g_type_class_unref (klass);
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

  if (!pspec)
    {
      g_warning ("%s: widget class `%s' has no property named `%s'",
                 G_STRLOC,
                 g_type_name (widget_type),
                 property_name);
      return;
    }

1160 1161 1162
  priv = GTK_STYLE_GET_PRIVATE (style);
  peek_value = _gtk_style_context_peek_style_property (priv->context,
                                                       widget_type,
1163
                                                       pspec);
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180

  if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
    g_value_copy (peek_value, value);
  else if (g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
    g_value_transform (peek_value, value);
  else
    g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
               pspec->name,
               g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
               G_VALUE_TYPE_NAME (value));
}

/**
 * gtk_style_get_valist:
 * @style: a #GtkStyle
 * @widget_type: the #GType of a descendant of #GtkWidget
 * @first_property_name: the name of the first style property to get
1181
 * @var_args: a va_list of pairs of property names and
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
 *     locations to return the property values, starting with the
 *     location for @first_property_name.
 *
 * Non-vararg variant of gtk_style_get().
 * Used primarily by language bindings.
 *
 * Since: 2.16
 */
void 
gtk_style_get_valist (GtkStyle    *style,
                      GType        widget_type,
                      const gchar *first_property_name,
                      va_list      var_args)
{
1196
  GtkStylePrivate *priv;
1197 1198 1199 1200 1201 1202 1203
  const char *property_name;
  GtkWidgetClass *klass;

  g_return_if_fail (GTK_IS_STYLE (style));

  klass = g_type_class_ref (widget_type);

1204
  priv = GTK_STYLE_GET_PRIVATE (style);
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
  property_name = first_property_name;
  while (property_name)
    {
      GParamSpec *pspec;
      const GValue *peek_value;
      gchar *error;

      pspec = gtk_widget_class_find_style_property (klass, property_name);

      if (!pspec)
        {
          g_warning ("%s: widget class `%s' has no property named `%s'",
                     G_STRLOC,
                     g_type_name (widget_type),
                     property_name);
          break;
        }

1223
      peek_value = _gtk_style_context_peek_style_property (priv->context, widget_type,
1224
                                                           pspec);
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
      G_VALUE_LCOPY (peek_value, var_args, 0, &error);
      if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
          g_free (error);
          break;
        }

      property_name = va_arg (var_args, gchar*);
    }

  g_type_class_unref (klass);
}

/**
 * gtk_style_get:
 * @style: a #GtkStyle
 * @widget_type: the #GType of a descendant of #GtkWidget
 * @first_property_name: the name of the first style property to get
Matthias Clasen's avatar
Matthias Clasen committed
1244
 * @...: pairs of property names and locations to
1245 1246 1247 1248 1249
 *   return the property values, starting with the location for
 *   @first_property_name, terminated by %NULL.
 *
 * Gets the values of a multiple style properties for @widget_type
 * from @style.
1250 1251
 *
 * Since: 2.16
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
 */
void
gtk_style_get (GtkStyle    *style,
               GType        widget_type,
               const gchar *first_property_name,
               ...)
{
  va_list var_args;

  va_start (var_args, first_property_name);
  gtk_style_get_valist (style, widget_type, first_property_name, var_args);
  va_end (var_args);
}

1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
static void
gtk_style_real_realize (GtkStyle *style)
{
}

static void
gtk_style_real_unrealize (GtkStyle *style)
{
}

static void
gtk_style_real_set_background (GtkStyle    *style,
			       GdkWindow   *window,
			       GtkStateType state_type)
{
1281
  gdk_window_set_background_pattern (window, style->background[state_type]);
1282 1283
}

1284 1285 1286 1287 1288 1289
/**
 * gtk_style_render_icon:
 * @style: a #GtkStyle
 * @source: the #GtkIconSource specifying the icon to render
 * @direction: a text direction
 * @state: a state
1290 1291
 * @size: (type int): the size to render the icon at (#GtkIconSize). A size of
 *     `(GtkIconSize)-1` means render at the size of the source and
1292
 *     don’t scale.
1293 1294
 * @widget: (allow-none): the widget
 * @detail: (allow-none): a style detail
1295
 *
1296 1297
 * Renders the icon specified by @source at the given @size
 * according to the given parameters and returns the result in a
1298
 * pixbuf.
1299
 *
1300
 * Returns: (transfer full): a newly-created #GdkPixbuf
1301
 *     containing the rendered icon
1302 1303
 *
 * Deprecated:3.0: Use gtk_render_icon_pixbuf() instead
1304
 */
1305 1306 1307 1308 1309
GdkPixbuf *
gtk_style_render_icon (GtkStyle            *style,
                       const GtkIconSource *source,
                       GtkTextDirection     direction,
                       GtkStateType         state,
1310
                       GtkIconSize          size,
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
                       GtkWidget           *widget,
                       const gchar         *detail)
{
  GdkPixbuf *pixbuf;
  
  g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
  g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
  
  pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
                                                     size, widget, detail);

  g_return_val_if_fail (pixbuf != NULL, NULL);

  return pixbuf;
}

/* Default functions */
1328 1329 1330 1331

/**
 * gtk_style_apply_default_background:
 * @style:
Matthias Clasen's avatar
Matthias Clasen committed
1332
 * @cr:
1333 1334 1335 1336 1337 1338
 * @window:
 * @state_type:
 * @x:
 * @y:
 * @width:
 * @height:
1339 1340
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
1341
 */
1342
void
1343
gtk_style_apply_default_background (GtkStyle          *style,
1344
                                    cairo_t           *cr,
1345
                                    GdkWindow         *window,
1346 1347 1348 1349 1350
                                    GtkStateType       state_type,
                                    gint               x,
                                    gint               y,
                                    gint               width,
                                    gint               height)
Elliot Lee's avatar
Elliot Lee committed
1351
{
1352 1353
  cairo_save (cr);

1354
  if (style->background[state_type] == NULL)
1355
    {
1356 1357
      GdkWindow *parent = gdk_window_get_parent (window);
      int x_offset, y_offset;
1358

1359
      if (parent)
1360
        {
1361 1362 1363 1364 1365 1366 1367
          gdk_window_get_position (window, &x_offset, &y_offset);
          cairo_translate (cr, -x_offset, -y_offset);
          gtk_style_apply_default_background (style, cr,
                                              parent, state_type,
                                              x + x_offset, y + y_offset,
                                              width, height);
          goto out;
1368
        }
1369 1370
      else
        gdk_cairo_set_source_color (cr, &style->bg[state_type]);
1371
    }
1372
  else
1373
    cairo_set_source (cr, style->background[state_type]);
1374 1375 1376 1377 1378 1379

  cairo_rectangle (cr, x, y, width, height);
  cairo_fill (cr);

out:
  cairo_restore (cr);
Elliot Lee's avatar
Elliot Lee committed
1380 1381
}

1382 1383
static GdkPixbuf *
gtk_default_render_icon (GtkStyle            *style,
1384 1385 1386 1387 1388 1389
                         const GtkIconSource *source,
                         GtkTextDirection     direction,
                         GtkStateType         state,
                         GtkIconSize          size,
                         GtkWidget           *widget,
                         const gchar         *detail)
1390
{
1391 1392
  GtkStyleContext *context;
  GtkStylePrivate *priv;
1393
  GtkStateFlags flags = 0;
1394
  GdkPixbuf *pixbuf;
1395

1396 1397 1398
  if (widget)
    context = gtk_widget_get_style_context (widget);
  else
1399
    {
1400 1401
      priv = GTK_STYLE_GET_PRIVATE (style);
      context = priv->context;
1402 1403
    }

1404 1405
  if (!context)
    return NULL;
1406

1407 1408 1409 1410 1411
  gtk_style_context_save (context);

  if (detail)
    transform_detail_string (detail, context);

1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
  switch (state)
    {
    case GTK_STATE_PRELIGHT:
      flags |= GTK_STATE_FLAG_PRELIGHT;
      break;
    case GTK_STATE_INSENSITIVE:
      flags |= GTK_STATE_FLAG_INSENSITIVE;
      break;
    default:
      break;
    }

  gtk_style_context_set_state (context, flags);

1426 1427 1428 1429 1430
  pixbuf = gtk_render_icon_pixbuf (context, source, size);

  gtk_style_context_restore (context);

  return pixbuf;
1431 1432
}

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
static void
_cairo_draw_line (cairo_t  *cr,
                  GdkColor *color,
                  gint      x1,
                  gint      y1,
                  gint      x2,
                  gint      y2)
{
  cairo_save (cr);

  gdk_cairo_set_source_color (cr, color);
  cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);

  cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
  cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
  cairo_stroke (cr);

  cairo_restore (cr);
}

Elliot Lee's avatar
Elliot Lee committed
1453
static void
1454 1455 1456 1457 1458 1459 1460
transform_detail_string (const gchar     *detail,
			 GtkStyleContext *context)
{
  if (!detail)
    return;

  if (strcmp (detail, "arrow") == 0)
1461
    gtk_style_context_add_class (context, "arrow");
1462
  else if (strcmp (detail, "button") == 0)
1463
    gtk_style_context_add_class (context, "button");
1464 1465
  else if (strcmp (detail, "buttondefault") == 0)
    {
1466 1467
      gtk_style_context_add_class (context, "button");
      gtk_style_context_add_class (context, "default");
1468 1469
    }
  else if (strcmp (detail, "calendar") == 0)
1470
    gtk_style_context_add_class (context, "calendar");
1471 1472
  else if (strcmp (detail, "cellcheck") == 0)
    {
1473 1474
      gtk_style_context_add_class (context, "cell");
      gtk_style_context_add_class (context, "check");
1475 1476 1477
    }
  else if (strcmp (detail, "cellradio") == 0)
    {
1478 1479
      gtk_style_context_add_class (context, "cell");
      gtk_style_context_add_class (context, "radio");
1480 1481
    }
  else if (strcmp (detail, "checkbutton") == 0)
1482
    gtk_style_context_add_class (context, "check");
1483 1484
  else if (strcmp (detail, "check") == 0)
    {