]> Pileus Git - ~andy/gtk/blob - gtk/gtkfixed.c
I submitted this patch twice to gtk-devel-list, and received no comments,
[~andy/gtk] / gtk / gtkfixed.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "gtkfixed.h"
20
21
22 static void gtk_fixed_class_init    (GtkFixedClass    *klass);
23 static void gtk_fixed_init          (GtkFixed         *fixed);
24 static void gtk_fixed_map           (GtkWidget        *widget);
25 static void gtk_fixed_realize       (GtkWidget        *widget);
26 static void gtk_fixed_size_request  (GtkWidget        *widget,
27                                      GtkRequisition   *requisition);
28 static void gtk_fixed_size_allocate (GtkWidget        *widget,
29                                      GtkAllocation    *allocation);
30 static void gtk_fixed_paint         (GtkWidget        *widget,
31                                      GdkRectangle     *area);
32 static void gtk_fixed_draw          (GtkWidget        *widget,
33                                      GdkRectangle     *area);
34 static gint gtk_fixed_expose        (GtkWidget        *widget,
35                                      GdkEventExpose   *event);
36 static void gtk_fixed_add           (GtkContainer     *container,
37                                      GtkWidget        *widget);
38 static void gtk_fixed_remove        (GtkContainer     *container,
39                                      GtkWidget        *widget);
40 static void gtk_fixed_forall        (GtkContainer     *container,
41                                      gboolean          include_internals,
42                                      GtkCallback       callback,
43                                      gpointer          callback_data);
44 static GtkType gtk_fixed_child_type (GtkContainer     *container);
45
46
47 static GtkContainerClass *parent_class = NULL;
48
49
50 GtkType
51 gtk_fixed_get_type (void)
52 {
53   static GtkType fixed_type = 0;
54
55   if (!fixed_type)
56     {
57       static const GtkTypeInfo fixed_info =
58       {
59         "GtkFixed",
60         sizeof (GtkFixed),
61         sizeof (GtkFixedClass),
62         (GtkClassInitFunc) gtk_fixed_class_init,
63         (GtkObjectInitFunc) gtk_fixed_init,
64         /* reserved_1 */ NULL,
65         /* reserved_2 */ NULL,
66         (GtkClassInitFunc) NULL,
67       };
68
69       fixed_type = gtk_type_unique (GTK_TYPE_CONTAINER, &fixed_info);
70     }
71
72   return fixed_type;
73 }
74
75 static void
76 gtk_fixed_class_init (GtkFixedClass *class)
77 {
78   GtkObjectClass *object_class;
79   GtkWidgetClass *widget_class;
80   GtkContainerClass *container_class;
81
82   object_class = (GtkObjectClass*) class;
83   widget_class = (GtkWidgetClass*) class;
84   container_class = (GtkContainerClass*) class;
85
86   parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
87
88   widget_class->map = gtk_fixed_map;
89   widget_class->realize = gtk_fixed_realize;
90   widget_class->size_request = gtk_fixed_size_request;
91   widget_class->size_allocate = gtk_fixed_size_allocate;
92   widget_class->draw = gtk_fixed_draw;
93   widget_class->expose_event = gtk_fixed_expose;
94
95   container_class->add = gtk_fixed_add;
96   container_class->remove = gtk_fixed_remove;
97   container_class->forall = gtk_fixed_forall;
98   container_class->child_type = gtk_fixed_child_type;
99 }
100
101 static GtkType
102 gtk_fixed_child_type (GtkContainer     *container)
103 {
104   return GTK_TYPE_WIDGET;
105 }
106
107 static void
108 gtk_fixed_init (GtkFixed *fixed)
109 {
110   GTK_WIDGET_UNSET_FLAGS (fixed, GTK_NO_WINDOW);
111  
112   fixed->children = NULL;
113 }
114
115 GtkWidget*
116 gtk_fixed_new (void)
117 {
118   GtkFixed *fixed;
119
120   fixed = gtk_type_new (GTK_TYPE_FIXED);
121   return GTK_WIDGET (fixed);
122 }
123
124 void
125 gtk_fixed_put (GtkFixed       *fixed,
126                GtkWidget      *widget,
127                gint16         x,
128                gint16         y)
129 {
130   GtkFixedChild *child_info;
131
132   g_return_if_fail (fixed != NULL);
133   g_return_if_fail (GTK_IS_FIXED (fixed));
134   g_return_if_fail (widget != NULL);
135
136   child_info = g_new (GtkFixedChild, 1);
137   child_info->widget = widget;
138   child_info->x = x;
139   child_info->y = y;
140
141   gtk_widget_set_parent (widget, GTK_WIDGET (fixed));
142
143   fixed->children = g_list_append (fixed->children, child_info); 
144
145   if (GTK_WIDGET_REALIZED (fixed) && !GTK_WIDGET_REALIZED (widget))
146     gtk_widget_realize (widget);
147
148   if (GTK_WIDGET_MAPPED (fixed) && !GTK_WIDGET_MAPPED (widget))
149     gtk_widget_map (widget);
150
151   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
152     gtk_widget_queue_resize (GTK_WIDGET (fixed));
153 }
154
155 void
156 gtk_fixed_move (GtkFixed       *fixed,
157                 GtkWidget      *widget,
158                 gint16         x,
159                 gint16         y)
160 {
161   GtkFixedChild *child;
162   GList *children;
163
164   g_return_if_fail (fixed != NULL);
165   g_return_if_fail (GTK_IS_FIXED (fixed));
166   g_return_if_fail (widget != NULL);
167
168   children = fixed->children;
169   while (children)
170     {
171       child = children->data;
172       children = children->next;
173
174       if (child->widget == widget)
175         {
176           child->x = x;
177           child->y = y;
178
179           if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
180             gtk_widget_queue_resize (GTK_WIDGET (fixed));
181
182           break;
183         }
184     }
185 }
186
187 static void
188 gtk_fixed_map (GtkWidget *widget)
189 {
190   GtkFixed *fixed;
191   GtkFixedChild *child;
192   GList *children;
193
194   g_return_if_fail (widget != NULL);
195   g_return_if_fail (GTK_IS_FIXED (widget));
196
197   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
198   fixed = GTK_FIXED (widget);
199
200   gdk_window_show (widget->window);
201
202   children = fixed->children;
203   while (children)
204     {
205       child = children->data;
206       children = children->next;
207
208       if (GTK_WIDGET_VISIBLE (child->widget) &&
209           !GTK_WIDGET_MAPPED (child->widget))
210         gtk_widget_map (child->widget);
211     }
212 }
213
214 static void
215 gtk_fixed_realize (GtkWidget *widget)
216 {
217   GdkWindowAttr attributes;
218   gint attributes_mask;
219
220   g_return_if_fail (widget != NULL);
221   g_return_if_fail (GTK_IS_FIXED (widget));
222
223   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
224
225   attributes.window_type = GDK_WINDOW_CHILD;
226   attributes.x = widget->allocation.x;
227   attributes.y = widget->allocation.y;
228   attributes.width = widget->allocation.width;
229   attributes.height = widget->allocation.height;
230   attributes.wclass = GDK_INPUT_OUTPUT;
231   attributes.visual = gtk_widget_get_visual (widget);
232   attributes.colormap = gtk_widget_get_colormap (widget);
233   attributes.event_mask = gtk_widget_get_events (widget);
234   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
235
236   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
237
238   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, 
239                                    attributes_mask);
240   gdk_window_set_user_data (widget->window, widget);
241
242   widget->style = gtk_style_attach (widget->style, widget->window);
243   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
244 }
245
246 static void
247 gtk_fixed_size_request (GtkWidget      *widget,
248                         GtkRequisition *requisition)
249 {
250   GtkFixed *fixed;  
251   GtkFixedChild *child;
252   GList *children;
253
254   g_return_if_fail (widget != NULL);
255   g_return_if_fail (GTK_IS_FIXED (widget));
256   g_return_if_fail (requisition != NULL);
257
258   fixed = GTK_FIXED (widget);
259   requisition->width = 0;
260   requisition->height = 0;
261
262   children = fixed->children;
263   while (children)
264     {
265       child = children->data;
266       children = children->next;
267
268       if (GTK_WIDGET_VISIBLE (child->widget))
269         {
270           gtk_widget_size_request (child->widget, &child->widget->requisition);
271
272           requisition->height = MAX (requisition->height,
273                                      child->y +
274                                      child->widget->requisition.height);
275           requisition->width = MAX (requisition->width,
276                                     child->x +
277                                     child->widget->requisition.width);
278         }
279     }
280
281   requisition->height += GTK_CONTAINER (fixed)->border_width * 2;
282   requisition->width += GTK_CONTAINER (fixed)->border_width * 2;
283 }
284
285 static void
286 gtk_fixed_size_allocate (GtkWidget     *widget,
287                          GtkAllocation *allocation)
288 {
289   GtkFixed *fixed;
290   GtkFixedChild *child;
291   GtkAllocation child_allocation;
292   GList *children;
293   guint16 border_width;
294
295   g_return_if_fail (widget != NULL);
296   g_return_if_fail (GTK_IS_FIXED(widget));
297   g_return_if_fail (allocation != NULL);
298
299   fixed = GTK_FIXED (widget);
300
301   widget->allocation = *allocation;
302   if (GTK_WIDGET_REALIZED (widget))
303     gdk_window_move_resize (widget->window,
304                             allocation->x, 
305                             allocation->y,
306                             allocation->width, 
307                             allocation->height);
308
309   border_width = GTK_CONTAINER (fixed)->border_width;
310   
311   children = fixed->children;
312   while (children)
313     {
314       child = children->data;
315       children = children->next;
316       
317       if (GTK_WIDGET_VISIBLE (child->widget))
318         {
319           child_allocation.x = child->x + border_width;
320           child_allocation.y = child->y + border_width;
321           child_allocation.width = child->widget->requisition.width;
322           child_allocation.height = child->widget->requisition.height;
323           gtk_widget_size_allocate (child->widget, &child_allocation);
324         }
325     }
326 }
327
328 static void
329 gtk_fixed_paint (GtkWidget    *widget,
330                  GdkRectangle *area)
331 {
332   g_return_if_fail (widget != NULL);
333   g_return_if_fail (GTK_IS_FIXED (widget));
334   g_return_if_fail (area != NULL);
335
336   if (GTK_WIDGET_DRAWABLE (widget))
337     gdk_window_clear_area (widget->window,
338                            area->x, area->y,
339                            area->width, area->height);
340 }
341
342 static void
343 gtk_fixed_draw (GtkWidget    *widget,
344                 GdkRectangle *area)
345 {
346   GtkFixed *fixed;
347   GtkFixedChild *child;
348   GdkRectangle child_area;
349   GList *children;
350
351   g_return_if_fail (widget != NULL);
352   g_return_if_fail (GTK_IS_FIXED (widget));
353
354   if (GTK_WIDGET_DRAWABLE (widget))
355     {
356       fixed = GTK_FIXED (widget);
357       gtk_fixed_paint (widget, area);
358
359       children = fixed->children;
360       while (children)
361         {
362           child = children->data;
363           children = children->next;
364
365           if (gtk_widget_intersect (child->widget, area, &child_area))
366             gtk_widget_draw (child->widget, &child_area);
367         }
368     }
369 }
370
371 static gint
372 gtk_fixed_expose (GtkWidget      *widget,
373                   GdkEventExpose *event)
374 {
375   GtkFixed *fixed;
376   GtkFixedChild *child;
377   GdkEventExpose child_event;
378   GList *children;
379
380   g_return_val_if_fail (widget != NULL, FALSE);
381   g_return_val_if_fail (GTK_IS_FIXED (widget), FALSE);
382   g_return_val_if_fail (event != NULL, FALSE);
383
384   if (GTK_WIDGET_DRAWABLE (widget))
385     {
386       fixed = GTK_FIXED (widget);
387
388       child_event = *event;
389
390       children = fixed->children;
391       while (children)
392         {
393           child = children->data;
394           children = children->next;
395
396           if (GTK_WIDGET_NO_WINDOW (child->widget) &&
397               gtk_widget_intersect (child->widget, &event->area, 
398                                     &child_event.area))
399             gtk_widget_event (child->widget, (GdkEvent*) &child_event);
400         }
401     }
402
403   return FALSE;
404 }
405
406 static void
407 gtk_fixed_add (GtkContainer *container,
408                GtkWidget    *widget)
409 {
410   g_return_if_fail (container != NULL);
411   g_return_if_fail (GTK_IS_FIXED (container));
412   g_return_if_fail (widget != NULL);
413
414   gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
415 }
416
417 static void
418 gtk_fixed_remove (GtkContainer *container,
419                   GtkWidget    *widget)
420 {
421   GtkFixed *fixed;
422   GtkFixedChild *child;
423   GList *children;
424
425   g_return_if_fail (container != NULL);
426   g_return_if_fail (GTK_IS_FIXED (container));
427   g_return_if_fail (widget != NULL);
428
429   fixed = GTK_FIXED (container);
430
431   children = fixed->children;
432   while (children)
433     {
434       child = children->data;
435
436       if (child->widget == widget)
437         {
438           gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
439           
440           gtk_widget_unparent (widget);
441
442           fixed->children = g_list_remove_link (fixed->children, children);
443           g_list_free (children);
444           g_free (child);
445
446           if (was_visible && GTK_WIDGET_VISIBLE (container))
447             gtk_widget_queue_resize (GTK_WIDGET (container));
448
449           break;
450         }
451
452       children = children->next;
453     }
454 }
455
456 static void
457 gtk_fixed_forall (GtkContainer *container,
458                   gboolean      include_internals,
459                   GtkCallback   callback,
460                   gpointer      callback_data)
461 {
462   GtkFixed *fixed;
463   GtkFixedChild *child;
464   GList *children;
465
466   g_return_if_fail (container != NULL);
467   g_return_if_fail (GTK_IS_FIXED (container));
468   g_return_if_fail (callback != NULL);
469
470   fixed = GTK_FIXED (container);
471
472   children = fixed->children;
473   while (children)
474     {
475       child = children->data;
476       children = children->next;
477
478       (* callback) (child->widget, callback_data);
479     }
480 }