~ubuntu-branches/debian/sid/bijiben/sid

« back to all changes in this revision

Viewing changes to libgd/libgd/gd-revealer.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng
  • Date: 2013-03-26 21:19:36 UTC
  • Revision ID: package-import@ubuntu.com-20130326211936-tu8mpy82juohw8m2
Tags: upstream-3.8.0
ImportĀ upstreamĀ versionĀ 3.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/*
 
3
 * Copyright (c) 2013 Red Hat, Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU Lesser General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or (at your
 
8
 * option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
12
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
13
 * License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public License
 
16
 * along with this program; if not, write to the Free Software Foundation,
 
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 * Author: Alexander Larsson <alexl@redhat.com>
 
20
 *
 
21
 */
 
22
 
 
23
#include <gtk/gtk.h>
 
24
#include "gd-revealer.h"
 
25
#include <math.h>
 
26
 
 
27
enum  {
 
28
  PROP_0,
 
29
  PROP_ORIENTATION,
 
30
  PROP_DURATION,
 
31
  PROP_REVEAL_CHILD,
 
32
  PROP_CHILD_REVEALED
 
33
};
 
34
 
 
35
#define FRAME_TIME_MSEC 17 /* 17 msec => 60 fps */
 
36
 
 
37
struct _GdRevealerPrivate {
 
38
  GtkOrientation orientation;
 
39
  gint duration;
 
40
 
 
41
  GdkWindow* bin_window;
 
42
  GdkWindow* view_window;
 
43
 
 
44
  gdouble current_pos;
 
45
  gdouble source_pos;
 
46
  gdouble target_pos;
 
47
 
 
48
  guint tick_id;
 
49
  gint64 start_time;
 
50
  gint64 end_time;
 
51
};
 
52
 
 
53
#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
 
54
#define GD_REVEALER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GD_TYPE_REVEALER, GdRevealerPrivate))
 
55
 
 
56
static void     gd_revealer_real_realize                        (GtkWidget     *widget);
 
57
static void     gd_revealer_real_unrealize                      (GtkWidget     *widget);
 
58
static void     gd_revealer_real_add                            (GtkContainer  *widget,
 
59
                                                                 GtkWidget     *child);
 
60
static void     gd_revealer_real_style_updated                  (GtkWidget     *widget);
 
61
static void     gd_revealer_real_size_allocate                  (GtkWidget     *widget,
 
62
                                                                 GtkAllocation *allocation);
 
63
static void     gd_revealer_real_map                            (GtkWidget     *widget);
 
64
static void     gd_revealer_real_unmap                          (GtkWidget     *widget);
 
65
static gboolean gd_revealer_real_draw                           (GtkWidget     *widget,
 
66
                                                                 cairo_t       *cr);
 
67
static void     gd_revealer_real_get_preferred_height           (GtkWidget     *widget,
 
68
                                                                 gint          *minimum_height,
 
69
                                                                 gint          *natural_height);
 
70
static void     gd_revealer_real_get_preferred_height_for_width (GtkWidget     *widget,
 
71
                                                                 gint           width,
 
72
                                                                 gint          *minimum_height,
 
73
                                                                 gint          *natural_height);
 
74
static void     gd_revealer_real_get_preferred_width            (GtkWidget     *widget,
 
75
                                                                 gint          *minimum_width,
 
76
                                                                 gint          *natural_width);
 
77
static void     gd_revealer_real_get_preferred_width_for_height (GtkWidget     *widget,
 
78
                                                                 gint           height,
 
79
                                                                 gint          *minimum_width,
 
80
                                                                 gint          *natural_width);
 
81
 
 
82
G_DEFINE_TYPE(GdRevealer, gd_revealer, GTK_TYPE_BIN);
 
83
 
 
84
static void
 
85
gd_revealer_init (GdRevealer *revealer)
 
86
{
 
87
  GdRevealerPrivate *priv;
 
88
 
 
89
  priv = GD_REVEALER_GET_PRIVATE (revealer);
 
90
  revealer->priv = priv;
 
91
 
 
92
  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
 
93
  priv->duration = 250;
 
94
  priv->current_pos = 0.0;
 
95
  priv->target_pos = 0.0;
 
96
 
 
97
  gtk_widget_set_has_window ((GtkWidget*) revealer, TRUE);
 
98
  gtk_widget_set_redraw_on_allocate ((GtkWidget*) revealer, FALSE);
 
99
}
 
100
 
 
101
static void
 
102
gd_revealer_finalize (GObject* obj)
 
103
{
 
104
  GdRevealer *revealer = GD_REVEALER (obj);
 
105
  GdRevealerPrivate *priv = revealer->priv;
 
106
 
 
107
  if (priv->tick_id != 0)
 
108
    gtk_widget_remove_tick_callback (GTK_WIDGET (revealer), priv->tick_id);
 
109
  priv->tick_id = 0;
 
110
 
 
111
  G_OBJECT_CLASS (gd_revealer_parent_class)->finalize (obj);
 
112
}
 
113
 
 
114
static void
 
115
gd_revealer_get_property (GObject *object,
 
116
                          guint property_id,
 
117
                          GValue *value,
 
118
                          GParamSpec *pspec)
 
119
{
 
120
  GdRevealer *revealer = GD_REVEALER (object);
 
121
 
 
122
  switch (property_id) {
 
123
  case PROP_ORIENTATION:
 
124
    g_value_set_enum (value, gd_revealer_get_orientation (revealer));
 
125
    break;
 
126
  case PROP_DURATION:
 
127
    g_value_set_int (value, gd_revealer_get_duration (revealer));
 
128
    break;
 
129
  case PROP_REVEAL_CHILD:
 
130
    g_value_set_boolean (value, gd_revealer_get_reveal_child (revealer));
 
131
    break;
 
132
  case PROP_CHILD_REVEALED:
 
133
    g_value_set_boolean (value, gd_revealer_get_child_revealed (revealer));
 
134
    break;
 
135
  default:
 
136
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
137
    break;
 
138
  }
 
139
}
 
140
 
 
141
static void
 
142
gd_revealer_set_property (GObject *object,
 
143
                          guint property_id,
 
144
                          const GValue *value,
 
145
                          GParamSpec *pspec)
 
146
{
 
147
  GdRevealer *revealer = GD_REVEALER (object);
 
148
 
 
149
  switch (property_id) {
 
150
  case PROP_ORIENTATION:
 
151
    gd_revealer_set_orientation (revealer, g_value_get_enum (value));
 
152
    break;
 
153
  case PROP_DURATION:
 
154
    gd_revealer_set_duration (revealer, g_value_get_int (value));
 
155
    break;
 
156
  case PROP_REVEAL_CHILD:
 
157
    gd_revealer_set_reveal_child (revealer, g_value_get_boolean (value));
 
158
    break;
 
159
  default:
 
160
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
161
    break;
 
162
  }
 
163
}
 
164
 
 
165
static void
 
166
gd_revealer_class_init (GdRevealerClass * klass)
 
167
{
 
168
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
169
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
 
170
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
171
 
 
172
  object_class->get_property = gd_revealer_get_property;
 
173
  object_class->set_property = gd_revealer_set_property;
 
174
  object_class->finalize = gd_revealer_finalize;
 
175
 
 
176
  widget_class->realize = gd_revealer_real_realize;
 
177
  widget_class->unrealize = gd_revealer_real_unrealize;
 
178
  widget_class->style_updated = gd_revealer_real_style_updated;
 
179
  widget_class->size_allocate = gd_revealer_real_size_allocate;
 
180
  widget_class->map = gd_revealer_real_map;
 
181
  widget_class->unmap = gd_revealer_real_unmap;
 
182
  widget_class->draw = gd_revealer_real_draw;
 
183
  widget_class->get_preferred_height = gd_revealer_real_get_preferred_height;
 
184
  widget_class->get_preferred_height_for_width = gd_revealer_real_get_preferred_height_for_width;
 
185
  widget_class->get_preferred_width = gd_revealer_real_get_preferred_width;
 
186
  widget_class->get_preferred_width_for_height = gd_revealer_real_get_preferred_width_for_height;
 
187
 
 
188
  container_class->add = gd_revealer_real_add;
 
189
 
 
190
  g_object_class_install_property (object_class,
 
191
                                   PROP_ORIENTATION,
 
192
                                   g_param_spec_enum ("orientation", "orientation",
 
193
                                                      "The orientation of the widget",
 
194
                                                      GTK_TYPE_ORIENTATION,
 
195
                                                      GTK_ORIENTATION_HORIZONTAL,
 
196
                                                      GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
197
  g_object_class_install_property (object_class,
 
198
                                   PROP_DURATION,
 
199
                                   g_param_spec_int ("duration", "duration",
 
200
                                                     "The animation duration, in milliseconds",
 
201
                                                     G_MININT, G_MAXINT,
 
202
                                                     250,
 
203
                                                     GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
204
  g_object_class_install_property (object_class,
 
205
                                   PROP_REVEAL_CHILD,
 
206
                                   g_param_spec_boolean ("reveal-child", "Reveal Child",
 
207
                                                         "Whether the container should reveal the child",
 
208
                                                         FALSE,
 
209
                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
210
 
 
211
  g_object_class_install_property (object_class,
 
212
                                   PROP_CHILD_REVEALED,
 
213
                                   g_param_spec_boolean ("child-revealed", "Child Revealed",
 
214
                                                         "Whether the child is revealed and the animation target reached",
 
215
                                                         FALSE,
 
216
                                                         G_PARAM_READABLE));
 
217
 
 
218
  g_type_class_add_private (klass, sizeof (GdRevealerPrivate));
 
219
}
 
220
 
 
221
 
 
222
GtkWidget *
 
223
gd_revealer_new (void)
 
224
{
 
225
  return g_object_new (GD_TYPE_REVEALER, NULL);
 
226
}
 
227
 
 
228
static void
 
229
gd_revealer_get_child_allocation (GdRevealer *revealer,
 
230
                                  GtkAllocation* allocation,
 
231
                                  GtkAllocation* child_allocation)
 
232
{
 
233
  GtkWidget *child;
 
234
  GdRevealerPrivate *priv;
 
235
 
 
236
  g_return_if_fail (revealer != NULL);
 
237
  g_return_if_fail (allocation != NULL);
 
238
 
 
239
  priv = revealer->priv;
 
240
 
 
241
  child_allocation->x = 0;
 
242
  child_allocation->y = 0;
 
243
  child_allocation->width = allocation->width;
 
244
  child_allocation->height = allocation->height;
 
245
 
 
246
  child = gtk_bin_get_child (GTK_BIN (revealer));
 
247
  if (child != NULL && gtk_widget_get_visible (child))
 
248
    {
 
249
      if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 
250
        gtk_widget_get_preferred_height_for_width (child, child_allocation->width, NULL,
 
251
                                                   &child_allocation->height);
 
252
      else
 
253
        gtk_widget_get_preferred_width_for_height (child, child_allocation->height, NULL,
 
254
                                                   &child_allocation->width);
 
255
    }
 
256
}
 
257
 
 
258
static void
 
259
gd_revealer_real_realize (GtkWidget *widget)
 
260
{
 
261
  GdRevealer *revealer = GD_REVEALER (widget);
 
262
  GdRevealerPrivate *priv = revealer->priv;
 
263
  GtkAllocation allocation;
 
264
  GdkWindowAttr attributes = { 0 };
 
265
  GdkWindowAttributesType attributes_mask;
 
266
  GtkAllocation child_allocation;
 
267
  GtkWidget *child;
 
268
  GtkStyleContext *context;
 
269
 
 
270
  gtk_widget_set_realized (widget, TRUE);
 
271
 
 
272
  gtk_widget_get_allocation (widget, &allocation);
 
273
 
 
274
  attributes.x = allocation.x;
 
275
  attributes.y = allocation.y;
 
276
  attributes.width = allocation.width;
 
277
  attributes.height = allocation.height;
 
278
  attributes.window_type = GDK_WINDOW_CHILD;
 
279
  attributes.wclass = GDK_INPUT_OUTPUT;
 
280
  attributes.visual = gtk_widget_get_visual (widget);
 
281
  attributes.event_mask =
 
282
    gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
 
283
  attributes_mask = (GDK_WA_X | GDK_WA_Y) | GDK_WA_VISUAL;
 
284
 
 
285
  priv->view_window =
 
286
    gdk_window_new (gtk_widget_get_parent_window ((GtkWidget*) revealer),
 
287
                    &attributes, attributes_mask);
 
288
  gtk_widget_set_window (widget, priv->view_window);
 
289
  gtk_widget_register_window (widget, priv->view_window);
 
290
 
 
291
  gd_revealer_get_child_allocation (revealer, &allocation, &child_allocation);
 
292
 
 
293
  attributes.x = 0;
 
294
  attributes.y = 0;
 
295
  attributes.width = child_allocation.width;
 
296
  attributes.height = child_allocation.height;
 
297
 
 
298
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 
299
    attributes.y = allocation.height - child_allocation.height;
 
300
  else
 
301
    attributes.x = allocation.width - child_allocation.width;
 
302
 
 
303
  priv->bin_window =
 
304
    gdk_window_new (priv->view_window, &attributes, attributes_mask);
 
305
  gtk_widget_register_window (widget, priv->bin_window);
 
306
 
 
307
  child = gtk_bin_get_child (GTK_BIN (revealer));
 
308
  if (child != NULL)
 
309
    gtk_widget_set_parent_window (child, priv->bin_window);
 
310
 
 
311
  context = gtk_widget_get_style_context (widget);
 
312
  gtk_style_context_set_background (context, priv->view_window);
 
313
  gtk_style_context_set_background (context, priv->bin_window);
 
314
  gdk_window_show (priv->bin_window);
 
315
}
 
316
 
 
317
 
 
318
static void
 
319
gd_revealer_real_unrealize (GtkWidget* widget)
 
320
{
 
321
  GdRevealer *revealer = GD_REVEALER (widget);
 
322
  GdRevealerPrivate *priv = revealer->priv;
 
323
 
 
324
  gtk_widget_unregister_window (widget, priv->bin_window);
 
325
  gdk_window_destroy (priv->bin_window);
 
326
  priv->view_window = NULL;
 
327
 
 
328
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->unrealize (widget);
 
329
}
 
330
 
 
331
 
 
332
static void
 
333
gd_revealer_real_add (GtkContainer* container,
 
334
                      GtkWidget* child)
 
335
{
 
336
  GdRevealer *revealer = GD_REVEALER (container);
 
337
  GdRevealerPrivate *priv = revealer->priv;
 
338
 
 
339
  g_return_if_fail (child != NULL);
 
340
 
 
341
  gtk_widget_set_parent_window (child, priv->bin_window);
 
342
  gtk_widget_set_child_visible (child, priv->current_pos != 0.0);
 
343
 
 
344
  GTK_CONTAINER_CLASS (gd_revealer_parent_class)->add (container, child);
 
345
}
 
346
 
 
347
 
 
348
static void
 
349
gd_revealer_real_style_updated (GtkWidget* widget)
 
350
{
 
351
  GdRevealer *revealer = GD_REVEALER (widget);
 
352
  GdRevealerPrivate *priv = revealer->priv;
 
353
  GtkStyleContext* context;
 
354
 
 
355
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->style_updated (widget);
 
356
 
 
357
  if (gtk_widget_get_realized (widget))
 
358
    {
 
359
      context = gtk_widget_get_style_context (widget);
 
360
      gtk_style_context_set_background (context, priv->bin_window);
 
361
      gtk_style_context_set_background (context, priv->view_window);
 
362
    }
 
363
}
 
364
 
 
365
 
 
366
static void
 
367
gd_revealer_real_size_allocate (GtkWidget* widget,
 
368
                                GtkAllocation* allocation)
 
369
{
 
370
  GdRevealer *revealer = GD_REVEALER (widget);
 
371
  GdRevealerPrivate *priv = revealer->priv;
 
372
  GtkAllocation child_allocation;
 
373
  GtkWidget *child;
 
374
  gboolean window_visible;
 
375
  int bin_x, bin_y;
 
376
 
 
377
  g_return_if_fail (allocation != NULL);
 
378
 
 
379
  gtk_widget_set_allocation (widget, allocation);
 
380
  gd_revealer_get_child_allocation (revealer, allocation, &child_allocation);
 
381
 
 
382
  child = gtk_bin_get_child (GTK_BIN (revealer));
 
383
  if (child != NULL &&
 
384
      gtk_widget_get_visible (child))
 
385
    gtk_widget_size_allocate (child, &child_allocation);
 
386
 
 
387
  if (gtk_widget_get_realized (widget))
 
388
    {
 
389
      if (gtk_widget_get_mapped (widget))
 
390
        {
 
391
          window_visible =
 
392
            allocation->width > 0 && allocation->height > 0;
 
393
 
 
394
          if (!window_visible &&
 
395
              gdk_window_is_visible (priv->view_window))
 
396
            gdk_window_hide (priv->view_window);
 
397
 
 
398
          if (window_visible &&
 
399
              !gdk_window_is_visible (priv->view_window))
 
400
            gdk_window_show (priv->view_window);
 
401
        }
 
402
 
 
403
      gdk_window_move_resize (priv->view_window,
 
404
                              allocation->x, allocation->y,
 
405
                              allocation->width, allocation->height);
 
406
 
 
407
      bin_x = 0;
 
408
      bin_y = 0;
 
409
      if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 
410
        bin_y = allocation->height - child_allocation.height;
 
411
      else
 
412
        bin_x = allocation->width - child_allocation.width;
 
413
 
 
414
      gdk_window_move_resize (priv->bin_window,
 
415
                              bin_x, bin_y,
 
416
                              child_allocation.width, child_allocation.height);
 
417
    }
 
418
}
 
419
 
 
420
 
 
421
static void
 
422
gd_revealer_set_position (GdRevealer *revealer,
 
423
                          gdouble pos)
 
424
{
 
425
  GdRevealerPrivate *priv = revealer->priv;
 
426
  gboolean new_visible;
 
427
  GtkWidget *child;
 
428
 
 
429
  priv->current_pos = pos;
 
430
 
 
431
  /* We check target_pos here too, because we want to ensure we set
 
432
   * child_visible immediately when starting a reveal operation
 
433
   * otherwise the child widgets will not be properly realized
 
434
   * after the reveal returns.
 
435
   */
 
436
  new_visible = priv->current_pos != 0.0 || priv->target_pos != 0.0;
 
437
 
 
438
  child = gtk_bin_get_child (GTK_BIN (revealer));
 
439
  if (child != NULL &&
 
440
      new_visible != gtk_widget_get_child_visible (child))
 
441
    gtk_widget_set_child_visible (child, new_visible);
 
442
 
 
443
  gtk_widget_queue_resize (GTK_WIDGET (revealer));
 
444
 
 
445
  if (priv->current_pos == priv->target_pos)
 
446
    g_object_notify (G_OBJECT (revealer), "child-revealed");
 
447
}
 
448
 
 
449
static gdouble
 
450
ease_out_quad (gdouble t, gdouble d)
 
451
{
 
452
  gdouble p = t / d;
 
453
  return  ((-1.0) * p) * (p - 2);
 
454
}
 
455
 
 
456
static void
 
457
gd_revealer_animate_step (GdRevealer *revealer,
 
458
                          gint64 now)
 
459
{
 
460
  GdRevealerPrivate *priv = revealer->priv;
 
461
  gdouble t;
 
462
 
 
463
  t = 1.0;
 
464
  if (now < priv->end_time)
 
465
      t = (now - priv->start_time) / (double) (priv->end_time - priv->start_time);
 
466
  t = ease_out_quad (t, 1.0);
 
467
 
 
468
  gd_revealer_set_position (revealer,
 
469
                            priv->source_pos + (t * (priv->target_pos - priv->source_pos)));
 
470
}
 
471
 
 
472
static gboolean
 
473
gd_revealer_animate_cb (GdRevealer *revealer,
 
474
                        GdkFrameClock *frame_clock,
 
475
                        gpointer user_data)
 
476
{
 
477
  GdRevealerPrivate *priv = revealer->priv;
 
478
  gint64 now;
 
479
 
 
480
  now = gdk_frame_clock_get_frame_time (frame_clock);
 
481
  gd_revealer_animate_step (revealer, now);
 
482
  if (priv->current_pos == priv->target_pos)
 
483
    {
 
484
      priv->tick_id = 0;
 
485
      return FALSE;
 
486
    }
 
487
 
 
488
  return TRUE;
 
489
}
 
490
 
 
491
static void
 
492
gd_revealer_start_animation (GdRevealer *revealer,
 
493
                             gdouble target)
 
494
{
 
495
  GdRevealerPrivate *priv = revealer->priv;
 
496
  GtkWidget *widget = GTK_WIDGET (revealer);
 
497
 
 
498
  if (priv->target_pos == target)
 
499
    return;
 
500
 
 
501
  priv->target_pos = target;
 
502
  g_object_notify (G_OBJECT (revealer), "reveal-child");
 
503
 
 
504
  if (gtk_widget_get_mapped (widget))
 
505
    {
 
506
      priv->source_pos = priv->current_pos;
 
507
      priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
 
508
      priv->end_time = priv->start_time + (priv->duration * 1000);
 
509
      if (priv->tick_id == 0)
 
510
        priv->tick_id =
 
511
          gtk_widget_add_tick_callback (widget, (GtkTickCallback)gd_revealer_animate_cb, revealer, NULL);
 
512
      gd_revealer_animate_step (revealer, priv->start_time);
 
513
    }
 
514
  else
 
515
    {
 
516
      gd_revealer_set_position (revealer, target);
 
517
    }
 
518
}
 
519
 
 
520
 
 
521
static void
 
522
gd_revealer_stop_animation (GdRevealer *revealer)
 
523
{
 
524
  GdRevealerPrivate *priv = revealer->priv;
 
525
 
 
526
  priv->current_pos = priv->target_pos;
 
527
  if (priv->tick_id != 0)
 
528
    {
 
529
      gtk_widget_remove_tick_callback (GTK_WIDGET (revealer), priv->tick_id);
 
530
      priv->tick_id = 0;
 
531
    }
 
532
}
 
533
 
 
534
 
 
535
static void
 
536
gd_revealer_real_map (GtkWidget *widget)
 
537
{
 
538
  GdRevealer *revealer = GD_REVEALER (widget);
 
539
  GdRevealerPrivate *priv = revealer->priv;
 
540
  GtkAllocation allocation;
 
541
 
 
542
  if (!gtk_widget_get_mapped (widget))
 
543
    {
 
544
      gtk_widget_get_allocation (widget, &allocation);
 
545
 
 
546
      if (allocation.width > 0 && allocation.height > 0)
 
547
        gdk_window_show (priv->view_window);
 
548
 
 
549
      gd_revealer_start_animation (revealer, priv->target_pos);
 
550
    }
 
551
 
 
552
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->map (widget);
 
553
}
 
554
 
 
555
static void
 
556
gd_revealer_real_unmap (GtkWidget *widget)
 
557
{
 
558
  GdRevealer *revealer = GD_REVEALER (widget);
 
559
 
 
560
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->unmap (widget);
 
561
 
 
562
  gd_revealer_stop_animation (revealer);
 
563
}
 
564
 
 
565
 
 
566
static gboolean
 
567
gd_revealer_real_draw (GtkWidget *widget,
 
568
                       cairo_t *cr)
 
569
{
 
570
  GdRevealer *revealer = GD_REVEALER (widget);
 
571
  GdRevealerPrivate *priv = revealer->priv;
 
572
 
 
573
  if (gtk_cairo_should_draw_window (cr, priv->bin_window))
 
574
    GTK_WIDGET_CLASS (gd_revealer_parent_class)->draw (widget, cr);
 
575
 
 
576
  return TRUE;
 
577
}
 
578
 
 
579
void
 
580
gd_revealer_set_reveal_child (GdRevealer *revealer,
 
581
                              gboolean    setting)
 
582
{
 
583
  g_return_if_fail (GD_IS_REVEALER (revealer));
 
584
 
 
585
  if (setting)
 
586
    gd_revealer_start_animation (revealer, 1.0);
 
587
  else
 
588
    gd_revealer_start_animation (revealer, 0.0);
 
589
}
 
590
 
 
591
gboolean
 
592
gd_revealer_get_reveal_child (GdRevealer *revealer)
 
593
{
 
594
  g_return_val_if_fail (GD_IS_REVEALER (revealer), FALSE);
 
595
 
 
596
  return revealer->priv->target_pos != 0.0;
 
597
}
 
598
 
 
599
gboolean
 
600
gd_revealer_get_child_revealed (GdRevealer *revealer)
 
601
{
 
602
  gboolean animation_finished = (revealer->priv->target_pos == revealer->priv->current_pos);
 
603
  gboolean reveal_child = gd_revealer_get_reveal_child (revealer);
 
604
 
 
605
  if (animation_finished)
 
606
    return reveal_child;
 
607
  else
 
608
    return !reveal_child;
 
609
}
 
610
 
 
611
/* These all report only the natural size, ignoring the minimal size,
 
612
 * because its not really possible to allocate the right size during
 
613
 * animation if the child size can change (without the child
 
614
 * re-arranging itself during the animation).
 
615
 */
 
616
 
 
617
static void
 
618
gd_revealer_real_get_preferred_height (GtkWidget* widget,
 
619
                                       gint* minimum_height_out,
 
620
                                       gint* natural_height_out)
 
621
{
 
622
  GdRevealer *revealer = GD_REVEALER (widget);
 
623
  GdRevealerPrivate *priv = revealer->priv;
 
624
  gint minimum_height;
 
625
  gint natural_height;
 
626
 
 
627
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_height (widget, &minimum_height, &natural_height);
 
628
 
 
629
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 
630
    natural_height = round (natural_height * priv->current_pos);
 
631
 
 
632
  minimum_height = natural_height;
 
633
 
 
634
  if (minimum_height_out)
 
635
    *minimum_height_out = minimum_height;
 
636
  if (natural_height_out)
 
637
    *natural_height_out = natural_height;
 
638
}
 
639
 
 
640
static void
 
641
gd_revealer_real_get_preferred_height_for_width (GtkWidget* widget,
 
642
                                                 gint width,
 
643
                                                 gint* minimum_height_out,
 
644
                                                 gint* natural_height_out)
 
645
{
 
646
  GdRevealer *revealer = GD_REVEALER (widget);
 
647
  GdRevealerPrivate *priv = revealer->priv;
 
648
  gint minimum_height;
 
649
  gint natural_height;
 
650
 
 
651
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_height_for_width (widget, width, &minimum_height, &natural_height);
 
652
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 
653
      natural_height = round (natural_height * priv->current_pos);
 
654
 
 
655
  minimum_height = natural_height;
 
656
 
 
657
  if (minimum_height_out)
 
658
    *minimum_height_out = minimum_height;
 
659
  if (natural_height_out)
 
660
    *natural_height_out = natural_height;
 
661
}
 
662
 
 
663
static void
 
664
gd_revealer_real_get_preferred_width (GtkWidget* widget,
 
665
                                      gint* minimum_width_out,
 
666
                                      gint* natural_width_out)
 
667
{
 
668
  GdRevealer *revealer = GD_REVEALER (widget);
 
669
  GdRevealerPrivate *priv = revealer->priv;
 
670
  gint minimum_width;
 
671
  gint natural_width;
 
672
 
 
673
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_width (widget, &minimum_width, &natural_width);
 
674
 
 
675
  if (priv->orientation == GTK_ORIENTATION_VERTICAL)
 
676
    natural_width = round (natural_width * priv->current_pos);
 
677
 
 
678
  minimum_width = natural_width;
 
679
 
 
680
  if (minimum_width_out)
 
681
    *minimum_width_out = minimum_width;
 
682
  if (natural_width_out)
 
683
    *natural_width_out = natural_width;
 
684
}
 
685
 
 
686
static void
 
687
gd_revealer_real_get_preferred_width_for_height (GtkWidget* widget,
 
688
                                                 gint height,
 
689
                                                 gint* minimum_width_out,
 
690
                                                 gint* natural_width_out)
 
691
{
 
692
  GdRevealer *revealer = GD_REVEALER (widget);
 
693
  GdRevealerPrivate *priv = revealer->priv;
 
694
  gint minimum_width;
 
695
  gint natural_width;
 
696
 
 
697
  GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_width_for_height (widget, height, &minimum_width, &natural_width);
 
698
 
 
699
  if (priv->orientation == GTK_ORIENTATION_VERTICAL)
 
700
    natural_width = round (natural_width * priv->current_pos);
 
701
 
 
702
  minimum_width = natural_width;
 
703
 
 
704
  if (minimum_width_out)
 
705
    *minimum_width_out = minimum_width;
 
706
  if (natural_width_out)
 
707
    *natural_width_out = natural_width;
 
708
}
 
709
 
 
710
GtkOrientation
 
711
gd_revealer_get_orientation (GdRevealer *revealer)
 
712
{
 
713
  g_return_val_if_fail (revealer != NULL, 0);
 
714
 
 
715
  return revealer->priv->orientation;
 
716
}
 
717
 
 
718
void
 
719
gd_revealer_set_orientation (GdRevealer *revealer,
 
720
                             GtkOrientation value)
 
721
{
 
722
  g_return_if_fail (revealer != NULL);
 
723
 
 
724
  revealer->priv->orientation = value;
 
725
  g_object_notify (G_OBJECT (revealer), "orientation");
 
726
}
 
727
 
 
728
gint
 
729
gd_revealer_get_duration (GdRevealer *revealer)
 
730
{
 
731
  g_return_val_if_fail (revealer != NULL, 0);
 
732
 
 
733
  return revealer->priv->duration;
 
734
}
 
735
 
 
736
void
 
737
gd_revealer_set_duration (GdRevealer *revealer,
 
738
                          gint value)
 
739
{
 
740
  g_return_if_fail (revealer != NULL);
 
741
 
 
742
  revealer->priv->duration = value;
 
743
  g_object_notify (G_OBJECT (revealer), "duration");
 
744
}