1 /* gtkcellrendererprogress.c
2 * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
3 * heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
4 * heavily modified by Marco Pesenti Gritti <marco@gnome.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
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 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24 */
25
26 #include "config.h"
27 #include <stdlib.h>
28
29 #include "gtkcellrendererprogress.h"
30 #include "gtkintl.h"
31 #include "gtkorientable.h"
32 #include "gtkprivate.h"
33 #include "gtkrender.h"
34
35
36 /**
37 * SECTION:gtkcellrendererprogress
38 * @Short_description: Renders numbers as progress bars
39 * @Title: GtkCellRendererProgress
40 *
41 * #GtkCellRendererProgress renders a numeric value as a progress par in a cell.
42 * Additionally, it can display a text on top of the progress bar.
43 *
44 * The #GtkCellRendererProgress cell renderer was added in GTK+ 2.6.
45 */
46
47
48 enum
49 {
50 PROP_0,
51 PROP_VALUE,
52 PROP_TEXT,
53 PROP_PULSE,
54 PROP_TEXT_XALIGN,
55 PROP_TEXT_YALIGN,
56 PROP_ORIENTATION,
57 PROP_INVERTED
58 };
59
60 struct _GtkCellRendererProgressPrivate
61 {
62 gint value;
63 gchar *text;
64 gchar *label;
65 gint min_h;
66 gint min_w;
67 gint pulse;
68 gint offset;
69 gfloat text_xalign;
70 gfloat text_yalign;
71 GtkOrientation orientation;
72 gboolean inverted;
73 };
74
75 static void gtk_cell_renderer_progress_finalize (GObject *object);
76 static void gtk_cell_renderer_progress_get_property (GObject *object,
77 guint param_id,
78 GValue *value,
79 GParamSpec *pspec);
80 static void gtk_cell_renderer_progress_set_property (GObject *object,
81 guint param_id,
82 const GValue *value,
83 GParamSpec *pspec);
84 static void gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
85 gint value);
86 static void gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
87 const gchar *text);
88 static void gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress,
89 gint pulse);
90 static void compute_dimensions (GtkCellRenderer *cell,
91 GtkWidget *widget,
92 const gchar *text,
93 gint *width,
94 gint *height);
95 static void gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
96 GtkWidget *widget,
97 const GdkRectangle *cell_area,
98 gint *x_offset,
99 gint *y_offset,
100 gint *width,
101 gint *height);
102 static void gtk_cell_renderer_progress_render (GtkCellRenderer *cell,
103 cairo_t *cr,
104 GtkWidget *widget,
105 const GdkRectangle *background_area,
106 const GdkRectangle *cell_area,
107 GtkCellRendererState flags);
108
109
G_DEFINE_TYPE_WITH_CODE(GtkCellRendererProgress,gtk_cell_renderer_progress,GTK_TYPE_CELL_RENDERER,G_ADD_PRIVATE (GtkCellRendererProgress)G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,NULL))110 G_DEFINE_TYPE_WITH_CODE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER,
111 G_ADD_PRIVATE (GtkCellRendererProgress)
112 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
113
114 static void
115 gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
116 {
117 GObjectClass *object_class = G_OBJECT_CLASS (klass);
118 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
119
120 object_class->finalize = gtk_cell_renderer_progress_finalize;
121 object_class->get_property = gtk_cell_renderer_progress_get_property;
122 object_class->set_property = gtk_cell_renderer_progress_set_property;
123
124 cell_class->get_size = gtk_cell_renderer_progress_get_size;
125 cell_class->render = gtk_cell_renderer_progress_render;
126
127 /**
128 * GtkCellRendererProgress:value:
129 *
130 * The "value" property determines the percentage to which the
131 * progress bar will be "filled in".
132 *
133 * Since: 2.6
134 **/
135 g_object_class_install_property (object_class,
136 PROP_VALUE,
137 g_param_spec_int ("value",
138 P_("Value"),
139 P_("Value of the progress bar"),
140 0, 100, 0,
141 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
142
143 /**
144 * GtkCellRendererProgress:text:
145 *
146 * The "text" property determines the label which will be drawn
147 * over the progress bar. Setting this property to %NULL causes the default
148 * label to be displayed. Setting this property to an empty string causes
149 * no label to be displayed.
150 *
151 * Since: 2.6
152 **/
153 g_object_class_install_property (object_class,
154 PROP_TEXT,
155 g_param_spec_string ("text",
156 P_("Text"),
157 P_("Text on the progress bar"),
158 NULL,
159 GTK_PARAM_READWRITE));
160
161 /**
162 * GtkCellRendererProgress:pulse:
163 *
164 * Setting this to a non-negative value causes the cell renderer to
165 * enter "activity mode", where a block bounces back and forth to
166 * indicate that some progress is made, without specifying exactly how
167 * much.
168 *
169 * Each increment of the property causes the block to move by a little
170 * bit.
171 *
172 * To indicate that the activity has not started yet, set the property
173 * to zero. To indicate completion, set the property to %G_MAXINT.
174 *
175 * Since: 2.12
176 */
177 g_object_class_install_property (object_class,
178 PROP_PULSE,
179 g_param_spec_int ("pulse",
180 P_("Pulse"),
181 P_("Set this to positive values to indicate that some progress is made, but you don't know how much."),
182 -1, G_MAXINT, -1,
183 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
184
185 /**
186 * GtkCellRendererProgress:text-xalign:
187 *
188 * The "text-xalign" property controls the horizontal alignment of the
189 * text in the progress bar. Valid values range from 0 (left) to 1
190 * (right). Reserved for RTL layouts.
191 *
192 * Since: 2.12
193 */
194 g_object_class_install_property (object_class,
195 PROP_TEXT_XALIGN,
196 g_param_spec_float ("text-xalign",
197 P_("Text x alignment"),
198 P_("The horizontal text alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
199 0.0, 1.0, 0.5,
200 GTK_PARAM_READWRITE));
201
202 /**
203 * GtkCellRendererProgress:text-yalign:
204 *
205 * The "text-yalign" property controls the vertical alignment of the
206 * text in the progress bar. Valid values range from 0 (top) to 1
207 * (bottom).
208 *
209 * Since: 2.12
210 */
211 g_object_class_install_property (object_class,
212 PROP_TEXT_YALIGN,
213 g_param_spec_float ("text-yalign",
214 P_("Text y alignment"),
215 P_("The vertical text alignment, from 0 (top) to 1 (bottom)."),
216 0.0, 1.0, 0.5,
217 GTK_PARAM_READWRITE));
218
219 g_object_class_override_property (object_class,
220 PROP_ORIENTATION,
221 "orientation");
222
223 g_object_class_install_property (object_class,
224 PROP_INVERTED,
225 g_param_spec_boolean ("inverted",
226 P_("Inverted"),
227 P_("Invert the direction in which the progress bar grows"),
228 FALSE,
229 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
230 }
231
232 static void
gtk_cell_renderer_progress_init(GtkCellRendererProgress * cellprogress)233 gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
234 {
235 GtkCellRendererProgressPrivate *priv;
236
237 cellprogress->priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
238 priv = cellprogress->priv;
239
240 priv->value = 0;
241 priv->text = NULL;
242 priv->label = NULL;
243 priv->min_w = -1;
244 priv->min_h = -1;
245 priv->pulse = -1;
246 priv->offset = 0;
247
248 priv->text_xalign = 0.5;
249 priv->text_yalign = 0.5;
250
251 priv->orientation = GTK_ORIENTATION_HORIZONTAL,
252 priv->inverted = FALSE;
253 }
254
255
256 /**
257 * gtk_cell_renderer_progress_new:
258 *
259 * Creates a new #GtkCellRendererProgress.
260 *
261 * Returns: the new cell renderer
262 *
263 * Since: 2.6
264 **/
265 GtkCellRenderer*
gtk_cell_renderer_progress_new(void)266 gtk_cell_renderer_progress_new (void)
267 {
268 return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
269 }
270
271 static void
gtk_cell_renderer_progress_finalize(GObject * object)272 gtk_cell_renderer_progress_finalize (GObject *object)
273 {
274 GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
275 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
276
277 g_free (priv->text);
278 g_free (priv->label);
279
280 G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
281 }
282
283 static void
gtk_cell_renderer_progress_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)284 gtk_cell_renderer_progress_get_property (GObject *object,
285 guint param_id,
286 GValue *value,
287 GParamSpec *pspec)
288 {
289 GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
290 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
291
292 switch (param_id)
293 {
294 case PROP_VALUE:
295 g_value_set_int (value, priv->value);
296 break;
297 case PROP_TEXT:
298 g_value_set_string (value, priv->text);
299 break;
300 case PROP_PULSE:
301 g_value_set_int (value, priv->pulse);
302 break;
303 case PROP_TEXT_XALIGN:
304 g_value_set_float (value, priv->text_xalign);
305 break;
306 case PROP_TEXT_YALIGN:
307 g_value_set_float (value, priv->text_yalign);
308 break;
309 case PROP_ORIENTATION:
310 g_value_set_enum (value, priv->orientation);
311 break;
312 case PROP_INVERTED:
313 g_value_set_boolean (value, priv->inverted);
314 break;
315 default:
316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
317 }
318 }
319
320 static void
gtk_cell_renderer_progress_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)321 gtk_cell_renderer_progress_set_property (GObject *object,
322 guint param_id,
323 const GValue *value,
324 GParamSpec *pspec)
325 {
326 GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
327 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
328
329 switch (param_id)
330 {
331 case PROP_VALUE:
332 gtk_cell_renderer_progress_set_value (cellprogress,
333 g_value_get_int (value));
334 break;
335 case PROP_TEXT:
336 gtk_cell_renderer_progress_set_text (cellprogress,
337 g_value_get_string (value));
338 break;
339 case PROP_PULSE:
340 gtk_cell_renderer_progress_set_pulse (cellprogress,
341 g_value_get_int (value));
342 break;
343 case PROP_TEXT_XALIGN:
344 priv->text_xalign = g_value_get_float (value);
345 break;
346 case PROP_TEXT_YALIGN:
347 priv->text_yalign = g_value_get_float (value);
348 break;
349 case PROP_ORIENTATION:
350 if (priv->orientation != g_value_get_enum (value))
351 {
352 priv->orientation = g_value_get_enum (value);
353 g_object_notify_by_pspec (object, pspec);
354 }
355 break;
356 case PROP_INVERTED:
357 if (priv->inverted != g_value_get_boolean (value))
358 {
359 priv->inverted = g_value_get_boolean (value);
360 g_object_notify_by_pspec (object, pspec);
361 }
362 break;
363 default:
364 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
365 }
366 }
367
368 static void
recompute_label(GtkCellRendererProgress * cellprogress)369 recompute_label (GtkCellRendererProgress *cellprogress)
370 {
371 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
372 gchar *label;
373
374 if (priv->text)
375 label = g_strdup (priv->text);
376 else if (priv->pulse < 0)
377 label = g_strdup_printf (C_("progress bar label", "%d %%"), priv->value);
378 else
379 label = NULL;
380
381 g_free (priv->label);
382 priv->label = label;
383 }
384
385 static void
gtk_cell_renderer_progress_set_value(GtkCellRendererProgress * cellprogress,gint value)386 gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
387 gint value)
388 {
389 if (cellprogress->priv->value != value)
390 {
391 cellprogress->priv->value = value;
392 recompute_label (cellprogress);
393 g_object_notify (G_OBJECT (cellprogress), "value");
394 }
395 }
396
397 static void
gtk_cell_renderer_progress_set_text(GtkCellRendererProgress * cellprogress,const gchar * text)398 gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
399 const gchar *text)
400 {
401 gchar *new_text;
402
403 new_text = g_strdup (text);
404 g_free (cellprogress->priv->text);
405 cellprogress->priv->text = new_text;
406 recompute_label (cellprogress);
407 g_object_notify (G_OBJECT (cellprogress), "text");
408 }
409
410 static void
gtk_cell_renderer_progress_set_pulse(GtkCellRendererProgress * cellprogress,gint pulse)411 gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress,
412 gint pulse)
413 {
414 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
415
416 if (pulse != priv->pulse)
417 {
418 if (pulse <= 0)
419 priv->offset = 0;
420 else
421 priv->offset = pulse;
422 g_object_notify (G_OBJECT (cellprogress), "pulse");
423 }
424
425 priv->pulse = pulse;
426 recompute_label (cellprogress);
427 }
428
429 static void
compute_dimensions(GtkCellRenderer * cell,GtkWidget * widget,const gchar * text,gint * width,gint * height)430 compute_dimensions (GtkCellRenderer *cell,
431 GtkWidget *widget,
432 const gchar *text,
433 gint *width,
434 gint *height)
435 {
436 PangoRectangle logical_rect;
437 PangoLayout *layout;
438 gint xpad, ypad;
439
440 layout = gtk_widget_create_pango_layout (widget, text);
441 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
442
443 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
444
445 if (width)
446 *width = logical_rect.width + xpad * 2;
447
448 if (height)
449 *height = logical_rect.height + ypad * 2;
450
451 g_object_unref (layout);
452 }
453
454 static void
gtk_cell_renderer_progress_get_size(GtkCellRenderer * cell,GtkWidget * widget,const GdkRectangle * cell_area,gint * x_offset,gint * y_offset,gint * width,gint * height)455 gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
456 GtkWidget *widget,
457 const GdkRectangle *cell_area,
458 gint *x_offset,
459 gint *y_offset,
460 gint *width,
461 gint *height)
462 {
463 GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
464 GtkCellRendererProgressPrivate *priv = cellprogress->priv;
465 gint w, h;
466 gchar *text;
467
468 if (priv->min_w < 0)
469 {
470 text = g_strdup_printf (C_("progress bar label", "%d %%"), 100);
471 compute_dimensions (cell, widget, text,
472 &priv->min_w,
473 &priv->min_h);
474 g_free (text);
475 }
476
477 compute_dimensions (cell, widget, priv->label, &w, &h);
478
479 if (width)
480 *width = MAX (priv->min_w, w);
481
482 if (height)
483 *height = MIN (priv->min_h, h);
484
485 /* FIXME: at the moment cell_area is only set when we are requesting
486 * the size for drawing the focus rectangle. We now just return
487 * the last size we used for drawing the progress bar, which will
488 * work for now. Not a really nice solution though.
489 */
490 if (cell_area)
491 {
492 if (width)
493 *width = cell_area->width;
494 if (height)
495 *height = cell_area->height;
496 }
497
498 if (x_offset) *x_offset = 0;
499 if (y_offset) *y_offset = 0;
500 }
501
502 static inline gint
get_bar_size(gint pulse,gint value,gint full_size)503 get_bar_size (gint pulse,
504 gint value,
505 gint full_size)
506 {
507 gint bar_size;
508
509 if (pulse < 0)
510 bar_size = full_size * MAX (0, value) / 100;
511 else if (pulse == 0)
512 bar_size = 0;
513 else if (pulse == G_MAXINT)
514 bar_size = full_size;
515 else
516 bar_size = MAX (2, full_size / 5);
517
518 return bar_size;
519 }
520
521 static inline gint
get_bar_position(gint start,gint full_size,gint bar_size,gint pulse,gint offset,gboolean is_rtl)522 get_bar_position (gint start,
523 gint full_size,
524 gint bar_size,
525 gint pulse,
526 gint offset,
527 gboolean is_rtl)
528 {
529 gint position;
530
531 if (pulse < 0 || pulse == 0 || pulse == G_MAXINT)
532 {
533 position = is_rtl ? (start + full_size - bar_size) : start;
534 }
535 else
536 {
537 position = (is_rtl ? offset + 12 : offset) % 24;
538 if (position > 12)
539 position = 24 - position;
540 position = start + full_size * position / 15;
541 }
542
543 return position;
544 }
545
546 static void
gtk_cell_renderer_progress_render(GtkCellRenderer * cell,cairo_t * cr,GtkWidget * widget,const GdkRectangle * background_area,const GdkRectangle * cell_area,GtkCellRendererState flags)547 gtk_cell_renderer_progress_render (GtkCellRenderer *cell,
548 cairo_t *cr,
549 GtkWidget *widget,
550 const GdkRectangle *background_area,
551 const GdkRectangle *cell_area,
552 GtkCellRendererState flags)
553 {
554 GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
555 GtkCellRendererProgressPrivate *priv= cellprogress->priv;
556 GtkStyleContext *context;
557 GtkBorder padding;
558 PangoLayout *layout;
559 PangoRectangle logical_rect;
560 gint x, y, w, h, x_pos, y_pos, bar_position, bar_size, start, full_size;
561 gint xpad, ypad;
562 GdkRectangle clip;
563 gboolean is_rtl;
564
565 context = gtk_widget_get_style_context (widget);
566 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
567
568 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
569 x = cell_area->x + xpad;
570 y = cell_area->y + ypad;
571 w = cell_area->width - xpad * 2;
572 h = cell_area->height - ypad * 2;
573
574 gtk_style_context_save (context);
575 gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
576
577 gtk_render_background (context, cr, x, y, w, h);
578 gtk_render_frame (context, cr, x, y, w, h);
579
580 gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);
581
582 x += padding.left;
583 y += padding.top;
584 w -= padding.left + padding.right;
585 h -= padding.top + padding.bottom;
586
587 gtk_style_context_restore (context);
588
589 if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
590 {
591 clip.y = y;
592 clip.height = h;
593
594 start = x;
595 full_size = w;
596
597 bar_size = get_bar_size (priv->pulse, priv->value, full_size);
598
599 if (!priv->inverted)
600 bar_position = get_bar_position (start, full_size, bar_size,
601 priv->pulse, priv->offset, is_rtl);
602 else
603 bar_position = get_bar_position (start, full_size, bar_size,
604 priv->pulse, priv->offset, !is_rtl);
605
606 clip.width = bar_size;
607 clip.x = bar_position;
608 }
609 else
610 {
611 clip.x = x;
612 clip.width = w;
613
614 start = y;
615 full_size = h;
616
617 bar_size = get_bar_size (priv->pulse, priv->value, full_size);
618
619 if (priv->inverted)
620 bar_position = get_bar_position (start, full_size, bar_size,
621 priv->pulse, priv->offset, TRUE);
622 else
623 bar_position = get_bar_position (start, full_size, bar_size,
624 priv->pulse, priv->offset, FALSE);
625
626 clip.height = bar_size;
627 clip.y = bar_position;
628 }
629
630 if (bar_size > 0)
631 {
632 gtk_style_context_save (context);
633 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
634
635 gtk_render_background (context, cr, clip.x, clip.y, clip.width, clip.height);
636 gtk_render_frame (context, cr, clip.x, clip.y, clip.width, clip.height);
637
638 gtk_style_context_restore (context);
639 }
640
641 if (priv->label)
642 {
643 gfloat text_xalign;
644
645 layout = gtk_widget_create_pango_layout (widget, priv->label);
646 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
647
648 if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
649 text_xalign = 1.0 - priv->text_xalign;
650 else
651 text_xalign = priv->text_xalign;
652
653 x_pos = x + padding.left + text_xalign *
654 (w - padding.left - padding.right - logical_rect.width);
655
656 y_pos = y + padding.top + priv->text_yalign *
657 (h - padding.top - padding.bottom - logical_rect.height);
658
659 cairo_save (cr);
660 gdk_cairo_rectangle (cr, &clip);
661 cairo_clip (cr);
662
663 gtk_style_context_save (context);
664 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
665
666 gtk_render_layout (context, cr,
667 x_pos, y_pos,
668 layout);
669
670 gtk_style_context_restore (context);
671 cairo_restore (cr);
672
673 gtk_style_context_save (context);
674 gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
675
676 if (bar_position > start)
677 {
678 if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
679 {
680 clip.x = x;
681 clip.width = bar_position - x;
682 }
683 else
684 {
685 clip.y = y;
686 clip.height = bar_position - y;
687 }
688
689 cairo_save (cr);
690 gdk_cairo_rectangle (cr, &clip);
691 cairo_clip (cr);
692
693 gtk_render_layout (context, cr,
694 x_pos, y_pos,
695 layout);
696
697 cairo_restore (cr);
698 }
699
700 if (bar_position + bar_size < start + full_size)
701 {
702 if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
703 {
704 clip.x = bar_position + bar_size;
705 clip.width = x + w - (bar_position + bar_size);
706 }
707 else
708 {
709 clip.y = bar_position + bar_size;
710 clip.height = y + h - (bar_position + bar_size);
711 }
712
713 cairo_save (cr);
714 gdk_cairo_rectangle (cr, &clip);
715 cairo_clip (cr);
716
717 gtk_render_layout (context, cr,
718 x_pos, y_pos,
719 layout);
720
721 cairo_restore (cr);
722 }
723
724 gtk_style_context_restore (context);
725 g_object_unref (layout);
726 }
727 }
728