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);