gnome-shell-3.6.3.1/src/st/st-adjustment.c

No issues found

  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * st-adjustment.c: Adjustment object
  4  *
  5  * Copyright 2008 OpenedHand
  6  * Copyright 2009 Intel Corporation.
  7  *
  8  * This program is free software; you can redistribute it and/or modify it
  9  * under the terms and conditions of the GNU Lesser General Public License,
 10  * version 2.1, as published by the Free Software Foundation.
 11  *
 12  * This program is distributed in the hope it will be useful, but WITHOUT ANY
 13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 14  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 15  * more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public License
 18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 19  */
 20 
 21 /**
 22  * SECTION:st-adjustment
 23  * @short_description: A GObject representing an adjustable bounded value
 24  *
 25  * The #StAdjustment object represents a range of values bounded between a
 26  * minimum and maximum, together with step and page increments and a page size.
 27  */
 28 
 29 #ifdef HAVE_CONFIG_H
 30 #include "config.h"
 31 #endif
 32 
 33 #include <glib-object.h>
 34 #include <clutter/clutter.h>
 35 
 36 #include "st-adjustment.h"
 37 #include "st-private.h"
 38 
 39 G_DEFINE_TYPE (StAdjustment, st_adjustment, G_TYPE_OBJECT)
 40 
 41 #define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_ADJUSTMENT, StAdjustmentPrivate))
 42 
 43 struct _StAdjustmentPrivate
 44 {
 45   /* Do not sanity-check values while constructing,
 46    * not all properties may be set yet. */
 47   gboolean is_constructing : 1;
 48 
 49   gdouble  lower;
 50   gdouble  upper;
 51   gdouble  value;
 52   gdouble  step_increment;
 53   gdouble  page_increment;
 54   gdouble  page_size;
 55 };
 56 
 57 enum
 58 {
 59   PROP_0,
 60 
 61   PROP_LOWER,
 62   PROP_UPPER,
 63   PROP_VALUE,
 64   PROP_STEP_INC,
 65   PROP_PAGE_INC,
 66   PROP_PAGE_SIZE,
 67 };
 68 
 69 enum
 70 {
 71   CHANGED,
 72 
 73   LAST_SIGNAL
 74 };
 75 
 76 static guint signals[LAST_SIGNAL] = { 0, };
 77 
 78 static gboolean st_adjustment_set_lower          (StAdjustment *adjustment,
 79                                                   gdouble       lower);
 80 static gboolean st_adjustment_set_upper          (StAdjustment *adjustment,
 81                                                   gdouble       upper);
 82 static gboolean st_adjustment_set_step_increment (StAdjustment *adjustment,
 83                                                   gdouble       step);
 84 static gboolean st_adjustment_set_page_increment (StAdjustment *adjustment,
 85                                                   gdouble       page);
 86 static gboolean st_adjustment_set_page_size      (StAdjustment *adjustment,
 87                                                   gdouble       size);
 88 
 89 static void
 90 st_adjustment_constructed (GObject *object)
 91 {
 92   GObjectClass *g_class;
 93   StAdjustment *self = ST_ADJUSTMENT (object);
 94 
 95   g_class = G_OBJECT_CLASS (st_adjustment_parent_class);
 96   /* The docs say we're suppose to chain up, but would crash without
 97    * some extra care. */
 98   if (g_class && g_class->constructed &&
 99       g_class->constructed != st_adjustment_constructed)
100     {
101       g_class->constructed (object);
102     }
103 
104   ST_ADJUSTMENT (self)->priv->is_constructing = FALSE;
105   st_adjustment_clamp_page (self, self->priv->lower, self->priv->upper);
106 }
107 
108 static void
109 st_adjustment_get_property (GObject    *gobject,
110                             guint       prop_id,
111                             GValue     *value,
112                             GParamSpec *pspec)
113 {
114   StAdjustmentPrivate *priv = ST_ADJUSTMENT (gobject)->priv;
115 
116   switch (prop_id)
117     {
118     case PROP_LOWER:
119       g_value_set_double (value, priv->lower);
120       break;
121 
122     case PROP_UPPER:
123       g_value_set_double (value, priv->upper);
124       break;
125 
126     case PROP_VALUE:
127       g_value_set_double (value, priv->value);
128       break;
129 
130     case PROP_STEP_INC:
131       g_value_set_double (value, priv->step_increment);
132       break;
133 
134     case PROP_PAGE_INC:
135       g_value_set_double (value, priv->page_increment);
136       break;
137 
138     case PROP_PAGE_SIZE:
139       g_value_set_double (value, priv->page_size);
140       break;
141 
142     default:
143       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
144       break;
145     }
146 }
147 
148 static void
149 st_adjustment_set_property (GObject      *gobject,
150                             guint         prop_id,
151                             const GValue *value,
152                             GParamSpec   *pspec)
153 {
154   StAdjustment *adj = ST_ADJUSTMENT (gobject);
155 
156   switch (prop_id)
157     {
158     case PROP_LOWER:
159       st_adjustment_set_lower (adj, g_value_get_double (value));
160       break;
161 
162     case PROP_UPPER:
163       st_adjustment_set_upper (adj, g_value_get_double (value));
164       break;
165 
166     case PROP_VALUE:
167       st_adjustment_set_value (adj, g_value_get_double (value));
168       break;
169 
170     case PROP_STEP_INC:
171       st_adjustment_set_step_increment (adj, g_value_get_double (value));
172       break;
173 
174     case PROP_PAGE_INC:
175       st_adjustment_set_page_increment (adj, g_value_get_double (value));
176       break;
177 
178     case PROP_PAGE_SIZE:
179       st_adjustment_set_page_size (adj, g_value_get_double (value));
180       break;
181 
182     default:
183       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
184       break;
185     }
186 }
187 
188 static void
189 st_adjustment_class_init (StAdjustmentClass *klass)
190 {
191   GObjectClass *object_class = G_OBJECT_CLASS (klass);
192 
193   g_type_class_add_private (klass, sizeof (StAdjustmentPrivate));
194 
195   object_class->constructed = st_adjustment_constructed;
196   object_class->get_property = st_adjustment_get_property;
197   object_class->set_property = st_adjustment_set_property;
198 
199   g_object_class_install_property (object_class,
200                                    PROP_LOWER,
201                                    g_param_spec_double ("lower",
202                                                         "Lower",
203                                                         "Lower bound",
204                                                         -G_MAXDOUBLE,
205                                                         G_MAXDOUBLE,
206                                                         0.0,
207                                                         ST_PARAM_READWRITE |
208                                                         G_PARAM_CONSTRUCT));
209   g_object_class_install_property (object_class,
210                                    PROP_UPPER,
211                                    g_param_spec_double ("upper",
212                                                         "Upper",
213                                                         "Upper bound",
214                                                         -G_MAXDOUBLE,
215                                                         G_MAXDOUBLE,
216                                                         0.0,
217                                                         ST_PARAM_READWRITE |
218                                                         G_PARAM_CONSTRUCT));
219   g_object_class_install_property (object_class,
220                                    PROP_VALUE,
221                                    g_param_spec_double ("value",
222                                                         "Value",
223                                                         "Current value",
224                                                         -G_MAXDOUBLE,
225                                                         G_MAXDOUBLE,
226                                                         0.0,
227                                                         ST_PARAM_READWRITE |
228                                                         G_PARAM_CONSTRUCT));
229   g_object_class_install_property (object_class,
230                                    PROP_STEP_INC,
231                                    g_param_spec_double ("step-increment",
232                                                         "Step Increment",
233                                                         "Step increment",
234                                                         0.0,
235                                                         G_MAXDOUBLE,
236                                                         0.0,
237                                                         ST_PARAM_READWRITE |
238                                                         G_PARAM_CONSTRUCT));
239   g_object_class_install_property (object_class,
240                                    PROP_PAGE_INC,
241                                    g_param_spec_double ("page-increment",
242                                                         "Page Increment",
243                                                         "Page increment",
244                                                         0.0,
245                                                         G_MAXDOUBLE,
246                                                         0.0,
247                                                         ST_PARAM_READWRITE |
248                                                         G_PARAM_CONSTRUCT));
249   g_object_class_install_property (object_class,
250                                    PROP_PAGE_SIZE,
251                                    g_param_spec_double ("page-size",
252                                                         "Page Size",
253                                                         "Page size",
254                                                         0.0,
255                                                         G_MAXDOUBLE,
256                                                         0.0,
257                                                         ST_PARAM_READWRITE |
258                                                         G_PARAM_CONSTRUCT));
259   /**
260    * StAdjustment::changed:
261    *
262    * Emitted when any of the adjustment values have changed
263    */
264   signals[CHANGED] =
265     g_signal_new ("changed",
266                   G_TYPE_FROM_CLASS (klass),
267                   G_SIGNAL_RUN_LAST,
268                   G_STRUCT_OFFSET (StAdjustmentClass, changed),
269                   NULL, NULL, NULL,
270                   G_TYPE_NONE, 0);
271 }
272 
273 static void
274 st_adjustment_init (StAdjustment *self)
275 {
276   self->priv = ADJUSTMENT_PRIVATE (self);
277 
278   self->priv->is_constructing = TRUE;
279 }
280 
281 StAdjustment *
282 st_adjustment_new (gdouble value,
283                    gdouble lower,
284                    gdouble upper,
285                    gdouble step_increment,
286                    gdouble page_increment,
287                    gdouble page_size)
288 {
289   return g_object_new (ST_TYPE_ADJUSTMENT,
290                        "value", value,
291                        "lower", lower,
292                        "upper", upper,
293                        "step-increment", step_increment,
294                        "page-increment", page_increment,
295                        "page-size", page_size,
296                        NULL);
297 }
298 
299 gdouble
300 st_adjustment_get_value (StAdjustment *adjustment)
301 {
302   StAdjustmentPrivate *priv;
303 
304   g_return_val_if_fail (ST_IS_ADJUSTMENT (adjustment), 0);
305 
306   priv = adjustment->priv;
307 
308   return priv->value;
309 }
310 
311 void
312 st_adjustment_set_value (StAdjustment *adjustment,
313                          gdouble       value)
314 {
315   StAdjustmentPrivate *priv;
316 
317   g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
318 
319   priv = adjustment->priv;
320 
321   /* Defer clamp until after construction. */
322   if (!priv->is_constructing)
323     {
324       value = CLAMP (value,
325                      priv->lower,
326                      MAX (priv->lower, priv->upper - priv->page_size));
327     }
328 
329   if (priv->value != value)
330     {
331       priv->value = value;
332 
333       g_object_notify (G_OBJECT (adjustment), "value");
334     }
335 }
336 
337 void
338 st_adjustment_clamp_page (StAdjustment *adjustment,
339                           gdouble       lower,
340                           gdouble       upper)
341 {
342   StAdjustmentPrivate *priv;
343   gboolean changed;
344 
345   g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
346 
347   priv = adjustment->priv;
348 
349   lower = CLAMP (lower, priv->lower, priv->upper - priv->page_size);
350   upper = CLAMP (upper, priv->lower + priv->page_size, priv->upper);
351 
352   changed = FALSE;
353 
354   if (priv->value + priv->page_size > upper)
355     {
356       priv->value = upper - priv->page_size;
357       changed = TRUE;
358     }
359 
360   if (priv->value < lower)
361     {
362       priv->value = lower;
363       changed = TRUE;
364     }
365 
366   if (changed)
367     g_object_notify (G_OBJECT (adjustment), "value");
368 }
369 
370 static gboolean
371 st_adjustment_set_lower (StAdjustment *adjustment,
372                          gdouble       lower)
373 {
374   StAdjustmentPrivate *priv = adjustment->priv;
375 
376   if (priv->lower != lower)
377     {
378       priv->lower = lower;
379 
380       g_signal_emit (adjustment, signals[CHANGED], 0);
381 
382       g_object_notify (G_OBJECT (adjustment), "lower");
383 
384       /* Defer clamp until after construction. */
385       if (!priv->is_constructing)
386         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
387 
388       return TRUE;
389     }
390 
391   return FALSE;
392 }
393 
394 static gboolean
395 st_adjustment_set_upper (StAdjustment *adjustment,
396                          gdouble       upper)
397 {
398   StAdjustmentPrivate *priv = adjustment->priv;
399 
400   if (priv->upper != upper)
401     {
402       priv->upper = upper;
403 
404       g_signal_emit (adjustment, signals[CHANGED], 0);
405 
406       g_object_notify (G_OBJECT (adjustment), "upper");
407 
408       /* Defer clamp until after construction. */
409       if (!priv->is_constructing)
410         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
411 
412       return TRUE;
413     }
414 
415   return FALSE;
416 }
417 
418 static gboolean
419 st_adjustment_set_step_increment (StAdjustment *adjustment,
420                                   gdouble       step)
421 {
422   StAdjustmentPrivate *priv = adjustment->priv;
423 
424   if (priv->step_increment != step)
425     {
426       priv->step_increment = step;
427 
428       g_signal_emit (adjustment, signals[CHANGED], 0);
429 
430       g_object_notify (G_OBJECT (adjustment), "step-increment");
431 
432       return TRUE;
433     }
434 
435   return FALSE;
436 }
437 
438 static gboolean
439 st_adjustment_set_page_increment (StAdjustment *adjustment,
440                                   gdouble       page)
441 {
442   StAdjustmentPrivate *priv = adjustment->priv;
443 
444   if (priv->page_increment != page)
445     {
446       priv->page_increment = page;
447 
448       g_signal_emit (adjustment, signals[CHANGED], 0);
449 
450       g_object_notify (G_OBJECT (adjustment), "page-increment");
451 
452       return TRUE;
453     }
454 
455   return FALSE;
456 }
457 
458 static gboolean
459 st_adjustment_set_page_size (StAdjustment *adjustment,
460                              gdouble       size)
461 {
462   StAdjustmentPrivate *priv = adjustment->priv;
463 
464   if (priv->page_size != size)
465     {
466       priv->page_size = size;
467 
468       g_signal_emit (adjustment, signals[CHANGED], 0);
469 
470       g_object_notify (G_OBJECT (adjustment), "page_size");
471 
472       /* Well explicitely clamp after construction. */
473       if (!priv->is_constructing)
474         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
475 
476       return TRUE;
477     }
478 
479   return FALSE;
480 }
481 
482 void
483 st_adjustment_set_values (StAdjustment *adjustment,
484                           gdouble       value,
485                           gdouble       lower,
486                           gdouble       upper,
487                           gdouble       step_increment,
488                           gdouble       page_increment,
489                           gdouble       page_size)
490 {
491   StAdjustmentPrivate *priv;
492   gboolean emit_changed = FALSE;
493 
494   g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
495   g_return_if_fail (page_size >= 0 && page_size <= G_MAXDOUBLE);
496   g_return_if_fail (step_increment >= 0 && step_increment <= G_MAXDOUBLE);
497   g_return_if_fail (page_increment >= 0 && page_increment <= G_MAXDOUBLE);
498 
499   priv = adjustment->priv;
500 
501   emit_changed = FALSE;
502 
503   g_object_freeze_notify (G_OBJECT (adjustment));
504 
505   emit_changed |= st_adjustment_set_lower (adjustment, lower);
506   emit_changed |= st_adjustment_set_upper (adjustment, upper);
507   emit_changed |= st_adjustment_set_step_increment (adjustment, step_increment);
508   emit_changed |= st_adjustment_set_page_increment (adjustment, page_increment);
509   emit_changed |= st_adjustment_set_page_size (adjustment, page_size);
510 
511   if (value != priv->value)
512     {
513       st_adjustment_set_value (adjustment, value);
514       emit_changed = TRUE;
515     }
516 
517   if (emit_changed)
518     g_signal_emit (G_OBJECT (adjustment), signals[CHANGED], 0);
519 
520   g_object_thaw_notify (G_OBJECT (adjustment));
521 }
522 
523 /**
524  * st_adjustment_get_values:
525  * @adjustment: an #StAdjustment
526  * @value: (out): the current value
527  * @lower: (out): the lower bound
528  * @upper: (out): the upper bound
529  * @step_increment: (out): the step increment
530  * @page_increment: (out): the page increment
531  * @page_size: (out): the page size
532  *
533  * Gets all of @adjustment's values at once.
534  */
535 void
536 st_adjustment_get_values (StAdjustment *adjustment,
537                           gdouble      *value,
538                           gdouble      *lower,
539                           gdouble      *upper,
540                           gdouble      *step_increment,
541                           gdouble      *page_increment,
542                           gdouble      *page_size)
543 {
544   StAdjustmentPrivate *priv;
545 
546   g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
547 
548   priv = adjustment->priv;
549 
550   if (lower)
551     *lower = priv->lower;
552 
553   if (upper)
554     *upper = priv->upper;
555 
556   if (value)
557     *value = st_adjustment_get_value (adjustment);
558 
559   if (step_increment)
560     *step_increment = priv->step_increment;
561 
562   if (page_increment)
563     *page_increment = priv->page_increment;
564 
565   if (page_size)
566     *page_size = priv->page_size;
567 }