gtkcellrendererprogress.c 20.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* gtkcellrendererprogress.c
 * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
 * heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
 * heavily modified by Marco Pesenti Gritti <marco@gnome.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
Javier Jardón's avatar
Javier Jardón committed
17
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 19
 */
/*
20
 * Modified by the GTK+ Team and others 1997-2007.  See the AUTHORS
21 22 23 24 25 26 27
 * 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/. 
 */

#include "config.h"
#include <stdlib.h>
28

29
#include "gtkcellrendererprogress.h"
30
#include "gtkorientable.h"
31
#include "gtkprivate.h"
32 33 34
#include "gtkintl.h"


35 36 37 38 39 40 41 42 43 44 45 46
/**
 * SECTION:gtkcellrendererprogress
 * @Short_description: Renders numbers as progress bars
 * @Title: GtkCellRendererProgress
 *
 * #GtkCellRendererProgress renders a numeric value as a progress par in a cell.
 * Additionally, it can display a text on top of the progress bar.
 *
 * The #GtkCellRendererProgress cell renderer was added in GTK+ 2.6.
 */


47 48
enum
{
Kristian Rietveld's avatar
Kristian Rietveld committed
49 50
  PROP_0,
  PROP_VALUE,
51
  PROP_TEXT,
52 53
  PROP_PULSE,
  PROP_TEXT_XALIGN,
54
  PROP_TEXT_YALIGN,
55 56 57
  PROP_ORIENTATION,
  PROP_INVERTED
};
58 59 60 61 62 63 64 65

struct _GtkCellRendererProgressPrivate
{
  gint value;
  gchar *text;
  gchar *label;
  gint min_h;
  gint min_w;
66 67
  gint pulse;
  gint offset;
68 69
  gfloat text_xalign;
  gfloat text_yalign;
70 71
  GtkOrientation orientation;
  gboolean inverted;
72 73 74 75 76 77 78 79 80 81 82 83 84 85
};

static void gtk_cell_renderer_progress_finalize     (GObject                 *object);
static void gtk_cell_renderer_progress_get_property (GObject                 *object,
						     guint                    param_id,
						     GValue                  *value,
						     GParamSpec              *pspec);
static void gtk_cell_renderer_progress_set_property (GObject                 *object,
						     guint                    param_id,
						     const GValue            *value,
						     GParamSpec              *pspec);
static void gtk_cell_renderer_progress_set_value    (GtkCellRendererProgress *cellprogress,
						     gint                     value);
static void gtk_cell_renderer_progress_set_text     (GtkCellRendererProgress *cellprogress,
Matthias Clasen's avatar
Matthias Clasen committed
86
						     const gchar             *text);
87 88
static void gtk_cell_renderer_progress_set_pulse    (GtkCellRendererProgress *cellprogress,
						     gint                     pulse);
Matthias Clasen's avatar
Matthias Clasen committed
89 90
static void compute_dimensions                      (GtkCellRenderer         *cell,
						     GtkWidget               *widget,
91 92 93 94 95
						     const gchar             *text,
						     gint                    *width,
						     gint                    *height);
static void gtk_cell_renderer_progress_get_size     (GtkCellRenderer         *cell,
						     GtkWidget               *widget,
96
						     const GdkRectangle      *cell_area,
97 98 99 100 101
						     gint                    *x_offset,
						     gint                    *y_offset,
						     gint                    *width,
						     gint                    *height);
static void gtk_cell_renderer_progress_render       (GtkCellRenderer         *cell,
102
						     cairo_t                 *cr,
103
						     GtkWidget               *widget,
104 105
						     const GdkRectangle      *background_area,
						     const GdkRectangle      *cell_area,
Brian Cameron's avatar
Brian Cameron committed
106
				                     GtkCellRendererState    flags);
107 108

     
109
G_DEFINE_TYPE_WITH_CODE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER,
110
                         G_ADD_PRIVATE (GtkCellRendererProgress)
111
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

static void
gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
  
  object_class->finalize = gtk_cell_renderer_progress_finalize;
  object_class->get_property = gtk_cell_renderer_progress_get_property;
  object_class->set_property = gtk_cell_renderer_progress_set_property;
  
  cell_class->get_size = gtk_cell_renderer_progress_get_size;
  cell_class->render = gtk_cell_renderer_progress_render;
  
  /**
   * GtkCellRendererProgress:value:
128
   *
129
   * The "value" property determines the percentage to which the
130
   * progress bar will be "filled in".
131 132 133 134 135 136 137 138
   *
   * Since: 2.6
   **/
  g_object_class_install_property (object_class,
				   PROP_VALUE,
				   g_param_spec_int ("value",
						     P_("Value"),
						     P_("Value of the progress bar"),
Matthias Clasen's avatar
Matthias Clasen committed
139
						     0, 100, 0,
140
						     GTK_PARAM_READWRITE));
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

  /**
   * GtkCellRendererProgress:text:
   * 
   * The "text" property determines the label which will be drawn
   * over the progress bar. Setting this property to %NULL causes the default 
   * label to be displayed. Setting this property to an empty string causes 
   * no label to be displayed.
   *
   * Since: 2.6
   **/
  g_object_class_install_property (object_class,
				   PROP_TEXT,
				   g_param_spec_string ("text",
							P_("Text"),
							P_("Text on the progress bar"),
							NULL,
158
							GTK_PARAM_READWRITE));
159

160 161 162 163 164
  /**
   * GtkCellRendererProgress:pulse:
   * 
   * Setting this to a non-negative value causes the cell renderer to
   * enter "activity mode", where a block bounces back and forth to 
Kristian Rietveld's avatar
Kristian Rietveld committed
165
   * indicate that some progress is made, without specifying exactly how
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
   * much.
   *
   * Each increment of the property causes the block to move by a little 
   * bit.
   *
   * To indicate that the activity has not started yet, set the property
   * to zero. To indicate completion, set the property to %G_MAXINT.
   *
   * Since: 2.12
   */
  g_object_class_install_property (object_class,
                                   PROP_PULSE,
                                   g_param_spec_int ("pulse",
                                                     P_("Pulse"),
                                                     P_("Set this to positive values to indicate that some progress is made, but you don't know how much."),
                                                     -1, G_MAXINT, -1,
                                                     GTK_PARAM_READWRITE));

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
  /**
   * GtkCellRendererProgress:text-xalign:
   *
   * The "text-xalign" property controls the horizontal alignment of the
   * text in the progress bar.  Valid values range from 0 (left) to 1
   * (right).  Reserved for RTL layouts.
   *
   * Since: 2.12
   */
  g_object_class_install_property (object_class,
                                   PROP_TEXT_XALIGN,
                                   g_param_spec_float ("text-xalign",
                                                       P_("Text x alignment"),
                                                       P_("The horizontal text alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
                                                       0.0, 1.0, 0.5,
                                                       GTK_PARAM_READWRITE));

  /**
   * GtkCellRendererProgress:text-yalign:
   *
   * The "text-yalign" property controls the vertical alignment of the
   * text in the progress bar.  Valid values range from 0 (top) to 1
   * (bottom).
   *
   * Since: 2.12
   */
  g_object_class_install_property (object_class,
                                   PROP_TEXT_YALIGN,
                                   g_param_spec_float ("text-yalign",
                                                       P_("Text y alignment"),
                                                       P_("The vertical text alignment, from 0 (top) to 1 (bottom)."),
                                                       0.0, 1.0, 0.5,
                                                       GTK_PARAM_READWRITE));

218 219 220
  g_object_class_override_property (object_class,
                                    PROP_ORIENTATION,
                                    "orientation");
221

222 223 224 225 226 227 228
  g_object_class_install_property (object_class,
                                   PROP_INVERTED,
                                   g_param_spec_boolean ("inverted",
                                                         P_("Inverted"),
                                                         P_("Invert the direction in which the progress bar grows"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
229 230 231 232 233
}

static void
gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
{
234 235
  GtkCellRendererProgressPrivate *priv;

236
  cellprogress->priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
237
  priv = cellprogress->priv;
238 239 240 241 242 243 244 245 246

  priv->value = 0;
  priv->text = NULL;
  priv->label = NULL;
  priv->min_w = -1;
  priv->min_h = -1;
  priv->pulse = -1;
  priv->offset = 0;

247 248 249
  priv->text_xalign = 0.5;
  priv->text_yalign = 0.5;

250 251
  priv->orientation = GTK_ORIENTATION_HORIZONTAL,
  priv->inverted = FALSE;
252 253 254 255 256 257 258 259
}


/**
 * gtk_cell_renderer_progress_new:
 * 
 * Creates a new #GtkCellRendererProgress. 
 *
260
 * Returns: the new cell renderer
261 262 263 264 265 266
 *
 * Since: 2.6
 **/
GtkCellRenderer*
gtk_cell_renderer_progress_new (void)
{
267
  return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
268 269 270 271 272 273
}

static void
gtk_cell_renderer_progress_finalize (GObject *object)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
274
  GtkCellRendererProgressPrivate *priv = cellprogress->priv;
275
  
276 277
  g_free (priv->text);
  g_free (priv->label);
278 279 280 281 282 283 284 285 286 287 288
  
  G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
}

static void
gtk_cell_renderer_progress_get_property (GObject *object,
					 guint param_id,
					 GValue *value,
					 GParamSpec *pspec)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
289
  GtkCellRendererProgressPrivate *priv = cellprogress->priv;
290 291 292 293
  
  switch (param_id)
    {
    case PROP_VALUE:
294
      g_value_set_int (value, priv->value);
295 296
      break;
    case PROP_TEXT:
297 298 299 300
      g_value_set_string (value, priv->text);
      break;
    case PROP_PULSE:
      g_value_set_int (value, priv->pulse);
301
      break;
302 303 304 305 306 307
    case PROP_TEXT_XALIGN:
      g_value_set_float (value, priv->text_xalign);
      break;
    case PROP_TEXT_YALIGN:
      g_value_set_float (value, priv->text_yalign);
      break;
308 309 310
    case PROP_ORIENTATION:
      g_value_set_enum (value, priv->orientation);
      break;
311 312 313
    case PROP_INVERTED:
      g_value_set_boolean (value, priv->inverted);
      break;
314 315 316 317 318 319 320 321 322 323 324 325
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
    }
}

static void
gtk_cell_renderer_progress_set_property (GObject *object,
					 guint param_id,
					 const GValue *value,
					 GParamSpec   *pspec)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
326
  GtkCellRendererProgressPrivate *priv = cellprogress->priv;
327 328 329 330 331 332 333 334 335 336 337
  
  switch (param_id)
    {
    case PROP_VALUE:
      gtk_cell_renderer_progress_set_value (cellprogress, 
					    g_value_get_int (value));
      break;
    case PROP_TEXT:
      gtk_cell_renderer_progress_set_text (cellprogress,
					   g_value_get_string (value));
      break;
338 339 340 341
    case PROP_PULSE:
      gtk_cell_renderer_progress_set_pulse (cellprogress, 
					    g_value_get_int (value));
      break;
342 343 344 345 346 347
    case PROP_TEXT_XALIGN:
      priv->text_xalign = g_value_get_float (value);
      break;
    case PROP_TEXT_YALIGN:
      priv->text_yalign = g_value_get_float (value);
      break;
348 349 350
    case PROP_ORIENTATION:
      priv->orientation = g_value_get_enum (value);
      break;
351
    case PROP_INVERTED:
352
      priv->inverted = g_value_get_boolean (value);
353
      break;
354 355 356 357 358
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
    }
}

359 360 361 362 363 364 365 366 367
static void
recompute_label (GtkCellRendererProgress *cellprogress)
{
  GtkCellRendererProgressPrivate *priv = cellprogress->priv;
  gchar *label;

  if (priv->text)
    label = g_strdup (priv->text);
  else if (priv->pulse < 0)
368
    label = g_strdup_printf (C_("progress bar label", "%d %%"), priv->value);
369 370 371 372 373 374 375
  else
    label = NULL;
 
  g_free (priv->label);
  priv->label = label;
}

376 377 378 379 380 381
static void
gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress, 
				      gint                     value)
{
  cellprogress->priv->value = value;

382
  recompute_label (cellprogress);
383 384 385 386
}

static void
gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress, 
Matthias Clasen's avatar
Matthias Clasen committed
387
				     const gchar             *text)
388 389 390 391 392 393 394
{
  gchar *new_text;

  new_text = g_strdup (text);
  g_free (cellprogress->priv->text);
  cellprogress->priv->text = new_text;

395 396 397 398 399 400 401 402 403 404 405
  recompute_label (cellprogress);
}

static void
gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress, 
				      gint                     pulse)
{
   GtkCellRendererProgressPrivate *priv = cellprogress->priv;

   if (pulse != priv->pulse)
     {
406
       if (pulse <= 0)
407 408
         priv->offset = 0;
       else
409
         priv->offset = pulse;
410 411 412 413 414
     }

   priv->pulse = pulse;

   recompute_label (cellprogress);
415 416 417
}

static void
Matthias Clasen's avatar
Matthias Clasen committed
418 419 420 421 422
compute_dimensions (GtkCellRenderer *cell,
		    GtkWidget       *widget, 
		    const gchar     *text, 
		    gint            *width, 
		    gint            *height)
423 424 425
{
  PangoRectangle logical_rect;
  PangoLayout *layout;
426
  gint xpad, ypad;
427 428 429
  
  layout = gtk_widget_create_pango_layout (widget, text);
  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
430 431

  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
432 433
  
  if (width)
434
    *width = logical_rect.width + xpad * 2;
435 436
  
  if (height)
437
    *height = logical_rect.height + ypad * 2;
438

439
  g_object_unref (layout);
440 441 442
}

static void
443 444 445 446 447 448 449
gtk_cell_renderer_progress_get_size (GtkCellRenderer    *cell,
				     GtkWidget          *widget,
				     const GdkRectangle *cell_area,
				     gint               *x_offset,
				     gint               *y_offset,
				     gint               *width,
				     gint               *height)
450 451
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
452
  GtkCellRendererProgressPrivate *priv = cellprogress->priv;
453
  gint w, h;
Matthias Clasen's avatar
Matthias Clasen committed
454 455
  gchar *text;

456
  if (priv->min_w < 0)
Matthias Clasen's avatar
Matthias Clasen committed
457
    {
458
      text = g_strdup_printf (C_("progress bar label", "%d %%"), 100);
Matthias Clasen's avatar
Matthias Clasen committed
459
      compute_dimensions (cell, widget, text,
460 461
			  &priv->min_w,
			  &priv->min_h);
Matthias Clasen's avatar
Matthias Clasen committed
462 463
      g_free (text);
    }
464
  
465
  compute_dimensions (cell, widget, priv->label, &w, &h);
466 467
  
  if (width)
468
    *width = MAX (priv->min_w, w);
469 470
  
  if (height)
471
    *height = MIN (priv->min_h, h);
472 473 474 475 476 477 478 479 480 481 482 483 484

  /* FIXME: at the moment cell_area is only set when we are requesting
   * the size for drawing the focus rectangle. We now just return
   * the last size we used for drawing the progress bar, which will
   * work for now. Not a really nice solution though.
   */
  if (cell_area)
    {
      if (width)
        *width = cell_area->width;
      if (height)
        *height = cell_area->height;
    }
485 486 487

  if (x_offset) *x_offset = 0;
  if (y_offset) *y_offset = 0;
488 489
}

490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
static inline gint
get_bar_size (gint pulse,
	      gint value,
	      gint full_size)
{
  gint bar_size;

  if (pulse < 0)
    bar_size = full_size * MAX (0, value) / 100;
  else if (pulse == 0)
    bar_size = 0;
  else if (pulse == G_MAXINT)
    bar_size = full_size;
  else
    bar_size = MAX (2, full_size / 5);

  return bar_size;
}

static inline gint
get_bar_position (gint     start,
		  gint     full_size,
		  gint     bar_size,
		  gint     pulse,
		  gint     offset,
		  gboolean is_rtl)
{
  gint position;

  if (pulse < 0 || pulse == 0 || pulse == G_MAXINT)
    {
      position = is_rtl ? (start + full_size - bar_size) : start;
    }
  else
    {
      position = (is_rtl ? offset + 12 : offset) % 24;
      if (position > 12)
	position = 24 - position;
      position = start + full_size * position / 15;
    }

  return position;
}

534
static void
535 536 537 538 539 540
gtk_cell_renderer_progress_render (GtkCellRenderer      *cell,
                                   cairo_t              *cr,
				   GtkWidget            *widget,
				   const GdkRectangle   *background_area,
				   const GdkRectangle   *cell_area,
				   GtkCellRendererState  flags)
541 542
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
543 544
  GtkCellRendererProgressPrivate *priv= cellprogress->priv;
  GtkStyleContext *context;
545
  GtkBorder padding;
546 547
  PangoLayout *layout;
  PangoRectangle logical_rect;
548
  gint x, y, w, h, x_pos, y_pos, bar_position, bar_size, start, full_size;
549
  gint xpad, ypad;
550 551 552
  GdkRectangle clip;
  gboolean is_rtl;

553
  context = gtk_widget_get_style_context (widget);
554
  is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
555 556 557 558 559 560

  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
  x = cell_area->x + xpad;
  y = cell_area->y + ypad;
  w = cell_area->width - xpad * 2;
  h = cell_area->height - ypad * 2;
561

562 563 564 565 566 567 568 569
  gtk_style_context_save (context);
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);

  gtk_render_background (context, cr, x, y, w, h);
  gtk_render_frame (context, cr, x, y, w, h);

  gtk_style_context_get_padding (context, GTK_STATE_FLAG_NORMAL, &padding);

570 571 572 573
  x += padding.left;
  y += padding.top;
  w -= padding.left + padding.right;
  h -= padding.top + padding.bottom;
574 575

  gtk_style_context_restore (context);
Kristian Rietveld's avatar
Kristian Rietveld committed
576

577
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
578
    {
579 580 581 582 583 584 585 586
      clip.y = y;
      clip.height = h;

      start = x;
      full_size = w;

      bar_size = get_bar_size (priv->pulse, priv->value, full_size);

587
      if (!priv->inverted)
588 589 590 591 592 593 594 595
	bar_position = get_bar_position (start, full_size, bar_size,
					 priv->pulse, priv->offset, is_rtl);
      else
	bar_position = get_bar_position (start, full_size, bar_size,
					 priv->pulse, priv->offset, !is_rtl);

      clip.width = bar_size;
      clip.x = bar_position;
596
    }
597
  else
598 599 600
    {
      clip.x = x;
      clip.width = w;
601 602 603 604 605 606

      start = y;
      full_size = h;

      bar_size = get_bar_size (priv->pulse, priv->value, full_size);

607
      if (priv->inverted)
608 609 610 611 612 613 614 615
	bar_position = get_bar_position (start, full_size, bar_size,
					 priv->pulse, priv->offset, TRUE);
      else
	bar_position = get_bar_position (start, full_size, bar_size,
					 priv->pulse, priv->offset, FALSE);

      clip.height = bar_size;
      clip.y = bar_position;
616
    }
Kristian Rietveld's avatar
Kristian Rietveld committed
617

618 619 620
  gtk_style_context_save (context);
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);

621
  if (bar_size > 0)
622 623 624 625 626
    gtk_render_activity (context, cr,
                         clip.x, clip.y,
                         clip.width, clip.height);

  gtk_style_context_restore (context);
Kristian Rietveld's avatar
Kristian Rietveld committed
627

628 629
  if (priv->label)
    {
630 631
      gfloat text_xalign;

632 633
      layout = gtk_widget_create_pango_layout (widget, priv->label);
      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
634 635 636 637 638 639

      if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
	text_xalign = 1.0 - priv->text_xalign;
      else
	text_xalign = priv->text_xalign;

640 641
      x_pos = x + padding.left + text_xalign *
	(w - padding.left - padding.right - logical_rect.width);
642

643 644
      y_pos = y + padding.top + priv->text_yalign *
	(h - padding.top - padding.bottom - logical_rect.height);
645

646 647 648 649
      cairo_save (cr);
      gdk_cairo_rectangle (cr, &clip);
      cairo_clip (cr);

650 651 652 653 654 655
      gtk_style_context_save (context);
      gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);

      gtk_render_layout (context, cr,
                         x_pos, y_pos,
                         layout);
656

657
      gtk_style_context_restore (context);
658
      cairo_restore (cr);
659

660 661 662
      gtk_style_context_save (context);
      gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);

663
      if (bar_position > start)
664
        {
665
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
666 667 668 669 670 671 672 673 674
	    {
	      clip.x = x;
	      clip.width = bar_position - x;
	    }
	  else
	    {
	      clip.y = y;
	      clip.height = bar_position - y;
	    }
675

676 677 678 679
          cairo_save (cr);
          gdk_cairo_rectangle (cr, &clip);
          cairo_clip (cr);

680 681 682
          gtk_render_layout (context, cr,
                             x_pos, y_pos,
                             layout);
683 684

          cairo_restore (cr);
685 686
        }

687
      if (bar_position + bar_size < start + full_size)
688
        {
689
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
690 691 692 693 694 695 696 697 698
	    {
	      clip.x = bar_position + bar_size;
	      clip.width = x + w - (bar_position + bar_size);
	    }
	  else
	    {
	      clip.y = bar_position + bar_size;
	      clip.height = y + h - (bar_position + bar_size);
	    }
699

700 701 702 703
          cairo_save (cr);
          gdk_cairo_rectangle (cr, &clip);
          cairo_clip (cr);

704 705 706 707
          gtk_render_layout (context, cr,
                             x_pos, y_pos,
                             layout);

708
          cairo_restore (cr);
709 710
        }

711
      gtk_style_context_restore (context);
712 713
      g_object_unref (layout);
    }
714
}