1#include "demo2layout.h"
2#include "four_point_transform.h"
3
4struct _Demo2Layout
5{
6 GtkLayoutManager parent_instance;
7
8 float position;
9 float offset;
10};
11
12struct _Demo2LayoutClass
13{
14 GtkLayoutManagerClass parent_class;
15};
16
17G_DEFINE_TYPE (Demo2Layout, demo2_layout, GTK_TYPE_LAYOUT_MANAGER)
18
19static void
20demo2_layout_measure (GtkLayoutManager *layout_manager,
21 GtkWidget *widget,
22 GtkOrientation orientation,
23 int for_size,
24 int *minimum,
25 int *natural,
26 int *minimum_baseline,
27 int *natural_baseline)
28{
29 GtkWidget *child;
30 int minimum_size = 0;
31 int natural_size = 0;
32
33 for (child = gtk_widget_get_first_child (widget);
34 child != NULL;
35 child = gtk_widget_get_next_sibling (widget: child))
36 {
37 int child_min = 0, child_nat = 0;
38
39 if (!gtk_widget_should_layout (widget: child))
40 continue;
41
42 gtk_widget_measure (widget: child, orientation, for_size: -1,
43 minimum: &child_min, natural: &child_nat,
44 NULL, NULL);
45 minimum_size = MAX (minimum_size, child_min);
46 natural_size = MAX (natural_size, child_nat);
47 }
48
49 *minimum = minimum_size;
50 *natural = 3 * natural_size;
51}
52
53
54#define RADIANS(angle) ((angle)*M_PI/180.0);
55
56/* Spherical coordinates */
57#define SX(r,t,p) ((r) * sin (t) * cos (p))
58#define SZ(r,t,p) ((r) * sin (t) * sin (p))
59#define SY(r,t,p) ((r) * cos (t))
60
61static double
62map_offset (double x)
63{
64 x = fmod (x: x, y: 180.0);
65 if (x < 0.0)
66 x += 180.0;
67
68 return x;
69}
70
71static void
72demo2_layout_allocate (GtkLayoutManager *layout_manager,
73 GtkWidget *widget,
74 int width,
75 int height,
76 int baseline)
77{
78 GtkWidget *child;
79 GtkRequisition child_req;
80 int i, j, k;
81 float x0, y0;
82 float w, h;
83 graphene_point3d_t p1, p2, p3, p4;
84 graphene_point3d_t q1, q2, q3, q4;
85 double t_1, t_2, p_1, p_2;
86 double r;
87 graphene_matrix_t m;
88 GskTransform *transform;
89 double position = DEMO2_LAYOUT (ptr: layout_manager)->position;
90 double offset = DEMO2_LAYOUT (ptr: layout_manager)->offset;
91
92 /* for simplicity, assume all children are the same size */
93 gtk_widget_get_preferred_size (widget: gtk_widget_get_first_child (widget), minimum_size: &child_req, NULL);
94 w = child_req.width;
95 h = child_req.height;
96
97 r = 300;
98 x0 = y0 = 300;
99
100 for (child = gtk_widget_get_first_child (widget), i = 0;
101 child != NULL;
102 child = gtk_widget_get_next_sibling (widget: child), i++)
103 {
104 j = i / 36;
105 k = i % 36;
106
107 gtk_widget_set_child_visible (widget: child, FALSE);
108
109 graphene_point3d_init (p: &p1, x: w, y: h, z: 1.);
110 graphene_point3d_init (p: &p2, x: w, y: 0., z: 1.);
111 graphene_point3d_init (p: &p3, x: 0., y: 0., z: 1.);
112 graphene_point3d_init (p: &p4, x: 0., y: h, z: 1.);
113
114 t_1 = RADIANS (map_offset (offset + 10 * j));
115 t_2 = RADIANS (map_offset (offset + 10 * (j + 1)));
116 p_1 = RADIANS (position + 10 * k);
117 p_2 = RADIANS (position + 10 * (k + 1));
118
119 if (t_2 < t_1)
120 continue;
121
122 if (SZ (r, t_1, p_1) > 0 ||
123 SZ (r, t_2, p_1) > 0 ||
124 SZ (r, t_1, p_2) > 0 ||
125 SZ (r, t_2, p_2) > 0)
126 continue;
127
128 gtk_widget_set_child_visible (widget: child, TRUE);
129
130 graphene_point3d_init (p: &q1, x: x0 + SX (r, t_1, p_1), y: y0 + SY (r, t_1, p_1), SZ (r, t_1, p_1));
131 graphene_point3d_init (p: &q2, x: x0 + SX (r, t_2, p_1), y: y0 + SY (r, t_2, p_1), SZ (r, t_2, p_1));
132 graphene_point3d_init (p: &q3, x: x0 + SX (r, t_2, p_2), y: y0 + SY (r, t_2, p_2), SZ (r, t_2, p_2));
133 graphene_point3d_init (p: &q4, x: x0 + SX (r, t_1, p_2), y: y0 + SY (r, t_1, p_2), SZ (r, t_1, p_2));
134
135 /* Get a matrix that moves p1 -> q1, p2 -> q2, ... */
136 perspective_3d (p1: &p1, p2: &p2, p3: &p3, p4: &p4,
137 q1: &q1, q2: &q2, q3: &q3, q4: &q4,
138 m: &m);
139
140 transform = gsk_transform_matrix (NULL, matrix: &m);
141
142 /* Since our matrix was built for transforming points with z = 1,
143 * prepend a translation to the z = 1 plane.
144 */
145 transform = gsk_transform_translate_3d (next: transform,
146 point: &GRAPHENE_POINT3D_INIT (0, 0, 1));
147
148 gtk_widget_allocate (widget: child, width: w, height: h, baseline: -1, transform);
149 }
150}
151
152static GtkSizeRequestMode
153demo2_layout_get_request_mode (GtkLayoutManager *layout_manager,
154 GtkWidget *widget)
155{
156 return GTK_SIZE_REQUEST_CONSTANT_SIZE;
157}
158
159static void
160demo2_layout_class_init (Demo2LayoutClass *klass)
161{
162 GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (ptr: klass);
163
164 layout_class->get_request_mode = demo2_layout_get_request_mode;
165 layout_class->measure = demo2_layout_measure;
166 layout_class->allocate = demo2_layout_allocate;
167}
168
169static void
170demo2_layout_init (Demo2Layout *self)
171{
172}
173
174GtkLayoutManager *
175demo2_layout_new (void)
176{
177 return g_object_new (DEMO2_TYPE_LAYOUT, NULL);
178}
179
180void
181demo2_layout_set_position (Demo2Layout *layout,
182 float position)
183{
184 layout->position = position;
185}
186
187float
188demo2_layout_get_position (Demo2Layout *layout)
189{
190 return layout->position;
191}
192
193void
194demo2_layout_set_offset (Demo2Layout *layout,
195 float offset)
196{
197 layout->offset = offset;
198}
199
200float
201demo2_layout_get_offset (Demo2Layout *layout)
202{
203 return layout->offset;
204}
205

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