gtkcellrendererprogress.c 22.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
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
23
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24
25
26
27
 */

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

29
#include "gtkcellrendererprogress.h"
30
#include "gtkintl.h"
31
#include "gtkorientable.h"
32
#include "gtkprivate.h"
33
#include "gtksnapshot.h"
34
#include "gtkstylecontext.h"
35
36


37
/**
38
39
40
 * GtkCellRendererProgress:
 *
 * Renders numbers as progress bars
41
 *
Matthias Clasen's avatar
Matthias Clasen committed
42
 * `GtkCellRendererProgress` renders a numeric value as a progress par in a cell.
43
44
45
46
 * Additionally, it can display a text on top of the progress bar.
 */


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
66
67
68
69
70
71
typedef struct _GtkCellRendererProgressClass    GtkCellRendererProgressClass;
typedef struct _GtkCellRendererProgressPrivate  GtkCellRendererProgressPrivate;

struct _GtkCellRendererProgress
{
  GtkCellRenderer parent_instance;
};

struct _GtkCellRendererProgressClass
{
  GtkCellRendererClass parent_class;
};

72
73
struct _GtkCellRendererProgressPrivate
{
Benjamin Otte's avatar
Benjamin Otte committed
74
  int value;
Benjamin Otte's avatar
Benjamin Otte committed
75
76
  char *text;
  char *label;
Benjamin Otte's avatar
Benjamin Otte committed
77
78
79
80
  int min_h;
  int min_w;
  int pulse;
  int offset;
Benjamin Otte's avatar
Benjamin Otte committed
81
82
  float text_xalign;
  float text_yalign;
83
84
  GtkOrientation orientation;
  gboolean inverted;
85
86
87
88
89
90
91
92
93
94
95
96
};

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,
Benjamin Otte's avatar
Benjamin Otte committed
97
						     int                      value);
98
static void gtk_cell_renderer_progress_set_text     (GtkCellRendererProgress *cellprogress,
Benjamin Otte's avatar
Benjamin Otte committed
99
						     const char              *text);
100
static void gtk_cell_renderer_progress_set_pulse    (GtkCellRendererProgress *cellprogress,
Benjamin Otte's avatar
Benjamin Otte committed
101
						     int                      pulse);
Matthias Clasen's avatar
Matthias Clasen committed
102
103
static void compute_dimensions                      (GtkCellRenderer         *cell,
						     GtkWidget               *widget,
Benjamin Otte's avatar
Benjamin Otte committed
104
						     const char              *text,
Benjamin Otte's avatar
Benjamin Otte committed
105
106
						     int                     *width,
						     int                     *height);
107
108
static void gtk_cell_renderer_progress_snapshot     (GtkCellRenderer         *cell,
						     GtkSnapshot             *snapshot,
109
						     GtkWidget               *widget,
110
111
						     const GdkRectangle      *background_area,
						     const GdkRectangle      *cell_area,
Brian Cameron's avatar
Brian Cameron committed
112
				                     GtkCellRendererState    flags);
113

114

115
G_DEFINE_TYPE_WITH_CODE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER,
116
                         G_ADD_PRIVATE (GtkCellRendererProgress)
117
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
118
119

static void
120
recompute_label (GtkCellRendererProgress *cellprogress)
121
{
122
123
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
  char *label;
124

125
126
127
128
129
130
  if (priv->text)
    label = g_strdup (priv->text);
  else if (priv->pulse < 0)
    label = g_strdup_printf (C_("progress bar label", "%d %%"), priv->value);
  else
    label = NULL;
131

132
133
  g_free (priv->label);
  priv->label = label;
134
135
136
}

static void
137
138
gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
				      int                      value)
139
{
140
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
141

142
143
144
145
146
147
148
  if (priv->value != value)
    {
      priv->value = value;
      recompute_label (cellprogress);
      g_object_notify (G_OBJECT (cellprogress), "value");
    }
}
149

150
151
152
153
154
155
static void
gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
				     const char              *text)
{
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
  char *new_text;
156

157
158
159
160
161
  new_text = g_strdup (text);
  g_free (priv->text);
  priv->text = new_text;
  recompute_label (cellprogress);
  g_object_notify (G_OBJECT (cellprogress), "text");
162
163
}

164
165
166
static void
gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress,
				      int                      pulse)
167
{
168
169
170
171
172
173
174
175
176
177
178
179
180
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);

  if (pulse != priv->pulse)
    {
      if (pulse <= 0)
        priv->offset = 0;
      else
        priv->offset = pulse;
      g_object_notify (G_OBJECT (cellprogress), "pulse");
    }

  priv->pulse = pulse;
  recompute_label (cellprogress);
181
182
183
184
185
186
}

static void
gtk_cell_renderer_progress_finalize (GObject *object)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
187
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
188

189
190
  g_free (priv->text);
  g_free (priv->label);
191

192
193
194
195
  G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
}

static void
196
197
198
gtk_cell_renderer_progress_get_property (GObject    *object,
					 guint       param_id,
					 GValue     *value,
199
200
201
					 GParamSpec *pspec)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
202
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
203

204
205
206
  switch (param_id)
    {
    case PROP_VALUE:
207
      g_value_set_int (value, priv->value);
208
209
      break;
    case PROP_TEXT:
210
211
212
213
      g_value_set_string (value, priv->text);
      break;
    case PROP_PULSE:
      g_value_set_int (value, priv->pulse);
214
      break;
215
216
217
218
219
220
    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;
221
222
223
    case PROP_ORIENTATION:
      g_value_set_enum (value, priv->orientation);
      break;
224
225
226
    case PROP_INVERTED:
      g_value_set_boolean (value, priv->inverted);
      break;
227
228
229
230
231
232
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
    }
}

static void
233
234
gtk_cell_renderer_progress_set_property (GObject      *object,
					 guint         param_id,
235
236
237
238
					 const GValue *value,
					 GParamSpec   *pspec)
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
239
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
240

241
242
243
  switch (param_id)
    {
    case PROP_VALUE:
244
      gtk_cell_renderer_progress_set_value (cellprogress,
245
246
247
248
249
250
					    g_value_get_int (value));
      break;
    case PROP_TEXT:
      gtk_cell_renderer_progress_set_text (cellprogress,
					   g_value_get_string (value));
      break;
251
    case PROP_PULSE:
252
      gtk_cell_renderer_progress_set_pulse (cellprogress,
253
254
					    g_value_get_int (value));
      break;
255
256
257
258
259
260
    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;
261
    case PROP_ORIENTATION:
262
263
264
265
266
      if (priv->orientation != g_value_get_enum (value))
        {
          priv->orientation = g_value_get_enum (value);
          g_object_notify_by_pspec (object, pspec);
        }
267
      break;
268
    case PROP_INVERTED:
269
270
271
272
273
      if (priv->inverted != g_value_get_boolean (value))
        {
          priv->inverted = g_value_get_boolean (value);
          g_object_notify_by_pspec (object, pspec);
        }
274
      break;
275
276
277
278
279
280
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
    }
}

static void
Matthias Clasen's avatar
Matthias Clasen committed
281
compute_dimensions (GtkCellRenderer *cell,
282
283
284
		    GtkWidget       *widget,
		    const char      *text,
		    int             *width,
Benjamin Otte's avatar
Benjamin Otte committed
285
		    int             *height)
286
287
288
{
  PangoRectangle logical_rect;
  PangoLayout *layout;
Benjamin Otte's avatar
Benjamin Otte committed
289
  int xpad, ypad;
290

291
292
  layout = gtk_widget_create_pango_layout (widget, text);
  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
293
294

  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
295

296
  if (width)
297
    *width = logical_rect.width + xpad * 2;
298

299
  if (height)
300
    *height = logical_rect.height + ypad * 2;
301

302
  g_object_unref (layout);
303
304
305
}

static void
306
307
308
309
gtk_cell_renderer_progress_get_preferred_width (GtkCellRenderer *cell,
                                                GtkWidget       *widget,
                                                int             *minimum,
                                                int             *natural)
310
{
311
312
  GtkCellRendererProgress *self = GTK_CELL_RENDERER_PROGRESS (cell);
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (self);
Benjamin Otte's avatar
Benjamin Otte committed
313
  int w, h;
314
  int size;
Matthias Clasen's avatar
Matthias Clasen committed
315

316
  if (priv->min_w < 0)
Matthias Clasen's avatar
Matthias Clasen committed
317
    {
318
      char *text = g_strdup_printf (C_("progress bar label", "%d %%"), 100);
Matthias Clasen's avatar
Matthias Clasen committed
319
      compute_dimensions (cell, widget, text,
320
321
			  &priv->min_w,
			  &priv->min_h);
Matthias Clasen's avatar
Matthias Clasen committed
322
323
      g_free (text);
    }
324

325
  compute_dimensions (cell, widget, priv->label, &w, &h);
326

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  size = MAX (priv->min_w, w);

  if (minimum != NULL)
    *minimum = size;
  if (natural != NULL)
    *natural = size;
}

static void
gtk_cell_renderer_progress_get_preferred_height (GtkCellRenderer *cell,
                                                 GtkWidget       *widget,
                                                 int             *minimum,
                                                 int             *natural)
{
  GtkCellRendererProgress *self = GTK_CELL_RENDERER_PROGRESS (cell);
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (self);
  int w, h;
  int size;

  if (priv->min_w < 0)
347
    {
348
349
350
351
352
      char *text = g_strdup_printf (C_("progress bar label", "%d %%"), 100);
      compute_dimensions (cell, widget, text,
			  &priv->min_w,
			  &priv->min_h);
      g_free (text);
353
    }
354

355
356
357
358
359
360
361
362
  compute_dimensions (cell, widget, priv->label, &w, &h);

  size = MIN (priv->min_h, h);

  if (minimum != NULL)
    *minimum = size;
  if (natural != NULL)
    *natural = size;
363
364
}

Benjamin Otte's avatar
Benjamin Otte committed
365
366
367
368
static inline int
get_bar_size (int pulse,
	      int value,
	      int full_size)
369
{
Benjamin Otte's avatar
Benjamin Otte committed
370
  int bar_size;
371
372
373
374
375
376
377
378
379
380
381
382
383

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

Benjamin Otte's avatar
Benjamin Otte committed
384
385
386
387
388
389
static inline int
get_bar_position (int      start,
		  int      full_size,
		  int      bar_size,
		  int      pulse,
		  int      offset,
390
391
		  gboolean is_rtl)
{
Benjamin Otte's avatar
Benjamin Otte committed
392
  int position;
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

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

409
static void
410
411
412
413
414
415
gtk_cell_renderer_progress_snapshot (GtkCellRenderer      *cell,
                                     GtkSnapshot          *snapshot,
                                     GtkWidget            *widget,
                                     const GdkRectangle   *background_area,
                                     const GdkRectangle   *cell_area,
                                     GtkCellRendererState  flags)
416
417
{
  GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
418
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
419
  GtkStyleContext *context;
420
  GtkBorder padding;
421
422
  PangoLayout *layout;
  PangoRectangle logical_rect;
Benjamin Otte's avatar
Benjamin Otte committed
423
424
  int x, y, w, h, x_pos, y_pos, bar_position, bar_size, start, full_size;
  int xpad, ypad;
425
426
427
  GdkRectangle clip;
  gboolean is_rtl;

428
  context = gtk_widget_get_style_context (widget);
429
  is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
430
431
432
433
434
435

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

437
  gtk_style_context_save (context);
Matthias Clasen's avatar
Matthias Clasen committed
438
  gtk_style_context_add_class (context, "trough");
439

440
441
  gtk_snapshot_render_background (snapshot, context, x, y, w, h);
  gtk_snapshot_render_frame (snapshot, context, x, y, w, h);
442

443
  gtk_style_context_get_padding (context, &padding);
444

445
446
447
448
  x += padding.left;
  y += padding.top;
  w -= padding.left + padding.right;
  h -= padding.top + padding.bottom;
449
450

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

452
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
453
    {
454
455
456
457
458
459
460
461
      clip.y = y;
      clip.height = h;

      start = x;
      full_size = w;

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

462
      if (!priv->inverted)
463
464
465
466
467
468
469
470
	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;
471
    }
472
  else
473
474
475
    {
      clip.x = x;
      clip.width = w;
476
477
478
479
480
481

      start = y;
      full_size = h;

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

482
      if (priv->inverted)
483
484
485
486
487
488
489
490
	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;
491
    }
Kristian Rietveld's avatar
Kristian Rietveld committed
492

493
  if (bar_size > 0)
494
495
    {
      gtk_style_context_save (context);
Matthias Clasen's avatar
Matthias Clasen committed
496
      gtk_style_context_add_class (context, "progressbar");
497

498
499
      gtk_snapshot_render_background (snapshot, context, clip.x, clip.y, clip.width, clip.height);
      gtk_snapshot_render_frame (snapshot, context, clip.x, clip.y, clip.width, clip.height);
500
501
502

      gtk_style_context_restore (context);
    }
Kristian Rietveld's avatar
Kristian Rietveld committed
503

504
505
  if (priv->label)
    {
Benjamin Otte's avatar
Benjamin Otte committed
506
      float text_xalign;
507

508
509
      layout = gtk_widget_create_pango_layout (widget, priv->label);
      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
510
511
512
513
514
515

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

516
517
      x_pos = x + padding.left + text_xalign *
	(w - padding.left - padding.right - logical_rect.width);
518

519
520
      y_pos = y + padding.top + priv->text_yalign *
	(h - padding.top - padding.bottom - logical_rect.height);
521

522
523
524
525
      gtk_snapshot_push_clip (snapshot,
                              &GRAPHENE_RECT_INIT(
                                  clip.x, clip.y,
                                  clip.width, clip.height
Benjamin Otte's avatar
Benjamin Otte committed
526
                              ));
527

528
      gtk_style_context_save (context);
Matthias Clasen's avatar
Matthias Clasen committed
529
      gtk_style_context_add_class (context, "progressbar");
530

531
532
533
      gtk_snapshot_render_layout (snapshot, context,
                                  x_pos, y_pos,
                                  layout);
534

535
      gtk_style_context_restore (context);
Benjamin Otte's avatar
Benjamin Otte committed
536
      gtk_snapshot_pop (snapshot);
537

538
      gtk_style_context_save (context);
Matthias Clasen's avatar
Matthias Clasen committed
539
      gtk_style_context_add_class (context, "trough");
540

541
      if (bar_position > start)
542
        {
543
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
544
545
546
547
548
549
550
551
552
	    {
	      clip.x = x;
	      clip.width = bar_position - x;
	    }
	  else
	    {
	      clip.y = y;
	      clip.height = bar_position - y;
	    }
553

554
555
556
557
          gtk_snapshot_push_clip (snapshot,
                                  &GRAPHENE_RECT_INIT(
                                      clip.x, clip.y,
                                      clip.width, clip.height
Benjamin Otte's avatar
Benjamin Otte committed
558
                                  ));
559

560
561
562
          gtk_snapshot_render_layout (snapshot, context,
                                      x_pos, y_pos,
                                      layout);
563

Benjamin Otte's avatar
Benjamin Otte committed
564
          gtk_snapshot_pop (snapshot);
565
566
        }

567
      if (bar_position + bar_size < start + full_size)
568
        {
569
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
570
571
572
573
574
575
576
577
578
	    {
	      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);
	    }
579

580
581
582
583
          gtk_snapshot_push_clip (snapshot,
                                  &GRAPHENE_RECT_INIT(
                                      clip.x, clip.y,
                                      clip.width, clip.height
Benjamin Otte's avatar
Benjamin Otte committed
584
                                  ));
585

586
587
588
          gtk_snapshot_render_layout (snapshot, context,
                                      x_pos, y_pos,
                                      layout);
589

Benjamin Otte's avatar
Benjamin Otte committed
590
          gtk_snapshot_pop (snapshot);
591
592
        }

593
      gtk_style_context_restore (context);
594
595
      g_object_unref (layout);
    }
596
}
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

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_preferred_width = gtk_cell_renderer_progress_get_preferred_width;
  cell_class->get_preferred_height = gtk_cell_renderer_progress_get_preferred_height;
  cell_class->snapshot = gtk_cell_renderer_progress_snapshot;

  /**
   * GtkCellRendererProgress:value:
   *
   * The "value" property determines the percentage to which the
   * progress bar will be "filled in".
   **/
  g_object_class_install_property (object_class,
				   PROP_VALUE,
				   g_param_spec_int ("value",
						     P_("Value"),
						     P_("Value of the progress bar"),
						     0, 100, 0,
						     GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));

  /**
   * 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.
   **/
  g_object_class_install_property (object_class,
				   PROP_TEXT,
				   g_param_spec_string ("text",
							P_("Text"),
							P_("Text on the progress bar"),
							NULL,
							GTK_PARAM_READWRITE));

  /**
   * 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
   * indicate that some progress is made, without specifying exactly how
   * 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.
   */
  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|G_PARAM_EXPLICIT_NOTIFY));

  /**
   * 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.
   */
  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).
   */
  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));

  g_object_class_override_property (object_class,
                                    PROP_ORIENTATION,
                                    "orientation");

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

static void
gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
{
  GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);

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

  priv->text_xalign = 0.5;
  priv->text_yalign = 0.5;

  priv->orientation = GTK_ORIENTATION_HORIZONTAL,
  priv->inverted = FALSE;
}

/**
 * gtk_cell_renderer_progress_new:
 *
Matthias Clasen's avatar
Matthias Clasen committed
730
 * Creates a new `GtkCellRendererProgress`.
731
732
733
734
735
736
737
738
 *
 * Returns: the new cell renderer
 **/
GtkCellRenderer*
gtk_cell_renderer_progress_new (void)
{
  return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
}