2 * gtkpanel.c - implementation of the `Panels' GTK layout container.
7 static void panels_init(Panels
*panels
);
8 static void panels_class_init(PanelsClass
*klass
);
9 static void panels_map(GtkWidget
*widget
);
10 static void panels_unmap(GtkWidget
*widget
);
11 static void panels_draw(GtkWidget
*widget
, GdkRectangle
*area
);
12 static gint
panels_expose(GtkWidget
*widget
, GdkEventExpose
*event
);
13 static void panels_base_add(GtkContainer
*container
, GtkWidget
*widget
);
14 static void panels_remove(GtkContainer
*container
, GtkWidget
*widget
);
15 static void panels_forall(GtkContainer
*container
, gboolean include_internals
,
16 GtkCallback callback
, gpointer callback_data
);
17 static GtkType
panels_child_type(GtkContainer
*container
);
18 static void panels_size_request(GtkWidget
*widget
, GtkRequisition
*req
);
19 static void panels_size_allocate(GtkWidget
*widget
, GtkAllocation
*alloc
);
21 static GtkContainerClass
*parent_class
= NULL
;
23 GtkType
panels_get_type(void)
25 static GtkType panels_type
= 0;
28 static const GtkTypeInfo panels_info
= {
32 (GtkClassInitFunc
) panels_class_init
,
33 (GtkObjectInitFunc
) panels_init
,
34 /* reserved_1 */ NULL
,
35 /* reserved_2 */ NULL
,
36 (GtkClassInitFunc
) NULL
,
39 panels_type
= gtk_type_unique(GTK_TYPE_CONTAINER
, &panels_info
);
45 static void panels_class_init(PanelsClass
*klass
)
47 GtkObjectClass
*object_class
;
48 GtkWidgetClass
*widget_class
;
49 GtkContainerClass
*container_class
;
51 object_class
= (GtkObjectClass
*)klass
;
52 widget_class
= (GtkWidgetClass
*)klass
;
53 container_class
= (GtkContainerClass
*)klass
;
55 parent_class
= gtk_type_class(GTK_TYPE_CONTAINER
);
58 * FIXME: do we have to do all this faffing with set_arg,
59 * get_arg and child_arg_type? Ick.
62 widget_class
->map
= panels_map
;
63 widget_class
->unmap
= panels_unmap
;
64 widget_class
->draw
= panels_draw
;
65 widget_class
->expose_event
= panels_expose
;
66 widget_class
->size_request
= panels_size_request
;
67 widget_class
->size_allocate
= panels_size_allocate
;
69 container_class
->add
= panels_base_add
;
70 container_class
->remove
= panels_remove
;
71 container_class
->forall
= panels_forall
;
72 container_class
->child_type
= panels_child_type
;
75 static void panels_init(Panels
*panels
)
77 GTK_WIDGET_SET_FLAGS(panels
, GTK_NO_WINDOW
);
79 panels
->children
= NULL
;
83 * These appear to be thoroughly tedious functions; the only reason
84 * we have to reimplement them at all is because we defined our own
85 * format for our GList of children...
87 static void panels_map(GtkWidget
*widget
)
93 g_return_if_fail(widget
!= NULL
);
94 g_return_if_fail(IS_PANELS(widget
));
96 panels
= PANELS(widget
);
97 GTK_WIDGET_SET_FLAGS(panels
, GTK_MAPPED
);
99 for (children
= panels
->children
;
100 children
&& (child
= children
->data
);
101 children
= children
->next
) {
103 GTK_WIDGET_VISIBLE(child
) &&
104 !GTK_WIDGET_MAPPED(child
))
105 gtk_widget_map(child
);
108 static void panels_unmap(GtkWidget
*widget
)
114 g_return_if_fail(widget
!= NULL
);
115 g_return_if_fail(IS_PANELS(widget
));
117 panels
= PANELS(widget
);
118 GTK_WIDGET_UNSET_FLAGS(panels
, GTK_MAPPED
);
120 for (children
= panels
->children
;
121 children
&& (child
= children
->data
);
122 children
= children
->next
) {
124 GTK_WIDGET_VISIBLE(child
) &&
125 GTK_WIDGET_MAPPED(child
))
126 gtk_widget_unmap(child
);
129 static void panels_draw(GtkWidget
*widget
, GdkRectangle
*area
)
134 GdkRectangle child_area
;
136 g_return_if_fail(widget
!= NULL
);
137 g_return_if_fail(IS_PANELS(widget
));
139 if (GTK_WIDGET_DRAWABLE(widget
)) {
140 panels
= PANELS(widget
);
142 for (children
= panels
->children
;
143 children
&& (child
= children
->data
);
144 children
= children
->next
) {
146 GTK_WIDGET_DRAWABLE(child
) &&
147 gtk_widget_intersect(child
, area
, &child_area
))
148 gtk_widget_draw(child
, &child_area
);
152 static gint
panels_expose(GtkWidget
*widget
, GdkEventExpose
*event
)
157 GdkEventExpose child_event
;
159 g_return_val_if_fail(widget
!= NULL
, FALSE
);
160 g_return_val_if_fail(IS_PANELS(widget
), FALSE
);
161 g_return_val_if_fail(event
!= NULL
, FALSE
);
163 if (GTK_WIDGET_DRAWABLE(widget
)) {
164 panels
= PANELS(widget
);
165 child_event
= *event
;
167 for (children
= panels
->children
;
168 children
&& (child
= children
->data
);
169 children
= children
->next
) {
171 GTK_WIDGET_DRAWABLE(child
) &&
172 GTK_WIDGET_NO_WINDOW(child
) &&
173 gtk_widget_intersect(child
, &event
->area
,
175 gtk_widget_event(child
, (GdkEvent
*)&child_event
);
181 static void panels_base_add(GtkContainer
*container
, GtkWidget
*widget
)
185 g_return_if_fail(container
!= NULL
);
186 g_return_if_fail(IS_PANELS(container
));
187 g_return_if_fail(widget
!= NULL
);
189 panels
= PANELS(container
);
191 panels_add(panels
, widget
);
194 static void panels_remove(GtkContainer
*container
, GtkWidget
*widget
)
199 gboolean was_visible
;
201 g_return_if_fail(container
!= NULL
);
202 g_return_if_fail(IS_PANELS(container
));
203 g_return_if_fail(widget
!= NULL
);
205 panels
= PANELS(container
);
207 for (children
= panels
->children
;
208 children
&& (child
= children
->data
);
209 children
= children
->next
) {
213 was_visible
= GTK_WIDGET_VISIBLE(widget
);
214 gtk_widget_unparent(widget
);
215 panels
->children
= g_list_remove_link(panels
->children
, children
);
216 g_list_free(children
);
218 gtk_widget_queue_resize(GTK_WIDGET(container
));
223 static void panels_forall(GtkContainer
*container
, gboolean include_internals
,
224 GtkCallback callback
, gpointer callback_data
)
230 g_return_if_fail(container
!= NULL
);
231 g_return_if_fail(IS_PANELS(container
));
232 g_return_if_fail(callback
!= NULL
);
234 panels
= PANELS(container
);
236 for (children
= panels
->children
;
237 children
&& (child
= children
->data
);
238 children
= children
->next
)
240 callback(child
, callback_data
);
243 static GtkType
panels_child_type(GtkContainer
*container
)
245 return GTK_TYPE_WIDGET
;
248 GtkWidget
*panels_new(void)
252 panels
= gtk_type_new(panels_get_type());
254 return GTK_WIDGET(panels
);
257 void panels_add(Panels
*panels
, GtkWidget
*child
)
259 g_return_if_fail(panels
!= NULL
);
260 g_return_if_fail(IS_PANELS(panels
));
261 g_return_if_fail(child
!= NULL
);
262 g_return_if_fail(child
->parent
== NULL
);
264 panels
->children
= g_list_append(panels
->children
, child
);
266 gtk_widget_set_parent(child
, GTK_WIDGET(panels
));
268 if (GTK_WIDGET_REALIZED(panels
))
269 gtk_widget_realize(child
);
271 if (GTK_WIDGET_VISIBLE(panels
)) {
272 if (GTK_WIDGET_MAPPED(panels
))
273 gtk_widget_map(child
);
274 gtk_widget_queue_resize(child
);
278 void panels_switch_to(Panels
*panels
, GtkWidget
*target
)
284 g_return_if_fail(panels
!= NULL
);
285 g_return_if_fail(IS_PANELS(panels
));
286 g_return_if_fail(target
!= NULL
);
287 g_return_if_fail(target
->parent
== GTK_WIDGET(panels
));
289 for (children
= panels
->children
;
290 children
&& (child
= children
->data
);
291 children
= children
->next
) {
296 if (child
== target
) {
297 if (!GTK_WIDGET_VISIBLE(child
)) {
298 gtk_widget_show(child
);
302 if (GTK_WIDGET_VISIBLE(child
)) {
303 gtk_widget_hide(child
);
309 gtk_widget_queue_resize(child
);
313 * Now here comes the interesting bit. The actual layout part is
314 * done in the following two functions:
316 * panels_size_request() examines the list of widgets held in the
317 * Panels, and returns a requisition stating the absolute minimum
318 * size it can bear to be.
320 * panels_size_allocate() is given an allocation telling it what
321 * size the whole container is going to be, and it calls
322 * gtk_widget_size_allocate() on all of its (visible) children to
323 * set their size and position relative to the top left of the
327 static void panels_size_request(GtkWidget
*widget
, GtkRequisition
*req
)
333 g_return_if_fail(widget
!= NULL
);
334 g_return_if_fail(IS_PANELS(widget
));
335 g_return_if_fail(req
!= NULL
);
337 panels
= PANELS(widget
);
342 for (children
= panels
->children
;
343 children
&& (child
= children
->data
);
344 children
= children
->next
) {
347 gtk_widget_size_request(child
, &creq
);
348 if (req
->width
< creq
.width
)
349 req
->width
= creq
.width
;
350 if (req
->height
< creq
.height
)
351 req
->height
= creq
.height
;
354 req
->width
+= 2*GTK_CONTAINER(panels
)->border_width
;
355 req
->height
+= 2*GTK_CONTAINER(panels
)->border_width
;
358 static void panels_size_allocate(GtkWidget
*widget
, GtkAllocation
*alloc
)
365 g_return_if_fail(widget
!= NULL
);
366 g_return_if_fail(IS_PANELS(widget
));
367 g_return_if_fail(alloc
!= NULL
);
369 panels
= PANELS(widget
);
370 widget
->allocation
= *alloc
;
371 border
= GTK_CONTAINER(panels
)->border_width
;
373 for (children
= panels
->children
;
374 children
&& (child
= children
->data
);
375 children
= children
->next
) {
378 /* Only take visible widgets into account. */
379 if (!GTK_WIDGET_VISIBLE(child
))
382 call
.x
= alloc
->x
+ border
;
383 call
.width
= alloc
->width
- 2*border
;
384 call
.y
= alloc
->y
+ border
;
385 call
.height
= alloc
->height
- 2*border
;
387 gtk_widget_size_allocate(child
, &call
);