1#include "demowidget.h"
2#include "demolayout.h"
3
4/* parent widget */
5
6struct _DemoWidget
7{
8 GtkWidget parent_instance;
9
10 gboolean backward; /* whether we go 0 -> 1 or 1 -> 0 */
11 gint64 start_time; /* time the transition started */
12 guint tick_id; /* our tick cb */
13};
14
15struct _DemoWidgetClass
16{
17 GtkWidgetClass parent_class;
18};
19
20G_DEFINE_TYPE (DemoWidget, demo_widget, GTK_TYPE_WIDGET)
21
22/* The widget is controlling the transition by calling
23 * demo_layout_set_position() in a tick callback.
24 *
25 * We take half a second to go from one layout to the other.
26 */
27
28#define DURATION (0.5 * G_TIME_SPAN_SECOND)
29
30static gboolean
31transition (GtkWidget *widget,
32 GdkFrameClock *frame_clock,
33 gpointer data)
34{
35 DemoWidget *self = DEMO_WIDGET (ptr: widget);
36 DemoLayout *demo_layout = DEMO_LAYOUT (ptr: gtk_widget_get_layout_manager (widget));
37 gint64 now = g_get_monotonic_time ();
38
39 gtk_widget_queue_allocate (widget);
40
41 if (self->backward)
42 demo_layout_set_position (layout: demo_layout, position: 1.0 - (now - self->start_time) / DURATION);
43 else
44 demo_layout_set_position (layout: demo_layout, position: (now - self->start_time) / DURATION);
45
46 if (now - self->start_time >= DURATION)
47 {
48 self->backward = !self->backward;
49 demo_layout_set_position (layout: demo_layout, position: self->backward ? 1.0 : 0.0);
50 /* keep things interesting by shuffling the positions */
51 if (!self->backward)
52 demo_layout_shuffle (layout: demo_layout);
53 self->tick_id = 0;
54
55 return G_SOURCE_REMOVE;
56 }
57
58 return G_SOURCE_CONTINUE;
59}
60
61static void
62clicked (GtkGestureClick *gesture,
63 guint n_press,
64 double x,
65 double y,
66 gpointer data)
67{
68 DemoWidget *self = data;
69
70 if (self->tick_id != 0)
71 return;
72
73 self->start_time = g_get_monotonic_time ();
74 self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), callback: transition, NULL, NULL);
75}
76
77static void
78demo_widget_init (DemoWidget *self)
79{
80 GtkGesture *gesture;
81
82 gesture = gtk_gesture_click_new ();
83 g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), self);
84 gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
85}
86
87static void
88demo_widget_dispose (GObject *object)
89{
90 GtkWidget *child;
91
92 while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
93 gtk_widget_unparent (widget: child);
94
95 G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
96}
97
98static void
99demo_widget_class_init (DemoWidgetClass *class)
100{
101 GObjectClass *object_class = G_OBJECT_CLASS (class);
102 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
103
104 object_class->dispose = demo_widget_dispose;
105
106 /* here is where we use our custom layout manager */
107 gtk_widget_class_set_layout_manager_type (widget_class, DEMO_TYPE_LAYOUT);
108}
109
110GtkWidget *
111demo_widget_new (void)
112{
113 return g_object_new (DEMO_TYPE_WIDGET, NULL);
114}
115
116void
117demo_widget_add_child (DemoWidget *self,
118 GtkWidget *child)
119{
120 gtk_widget_set_parent (widget: child, GTK_WIDGET (self));
121}
122

source code of gtk/demos/gtk-demo/demowidget.c