]> Pileus Git - ~andy/gtk/blob - gtk/gtkfixed.c
Fixed some bugs with set_default_size.
[~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   children = fixed->children;
201   while (children)
202     {
203       child = children->data;
204       children = children->next;
205
206       if (GTK_WIDGET_VISIBLE (child->widget) &&
207           !GTK_WIDGET_MAPPED (child->widget))
208         gtk_widget_map (child->widget);
209     }
210
211   gdk_window_show (widget->window);
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   GtkRequisition child_requisition;
254
255   g_return_if_fail (widget != NULL);
256   g_return_if_fail (GTK_IS_FIXED (widget));
257   g_return_if_fail (requisition != NULL);
258
259   fixed = GTK_FIXED (widget);
260   requisition->width = 0;
261   requisition->height = 0;
262
263   children = fixed->children;
264   while (children)
265     {
266       child = children->data;
267       children = children->next;
268
269       if (GTK_WIDGET_VISIBLE (child->widget))
270         {
271           gtk_widget_size_request (child->widget, &child_requisition);
272
273           requisition->height = MAX (requisition->height,
274                                      child->y +
275                                      child_requisition.height);
276           requisition->width = MAX (requisition->width,
277                                     child->x +
278                                     child_requisition.width);
279         }
280     }
281
282   requisition->height += GTK_CONTAINER (fixed)->border_width * 2;
283   requisition->width += GTK_CONTAINER (fixed)->border_width * 2;
284 }
285
286 static void
287 gtk_fixed_size_allocate (GtkWidget     *widget,
288                          GtkAllocation *allocation)
289 {
290   GtkFixed *fixed;
291   GtkFixedChild *child;
292   GtkAllocation child_allocation;
293   GtkRequisition child_requisition;
294   GList *children;
295   guint16 border_width;
296
297   g_return_if_fail (widget != NULL);
298   g_return_if_fail (GTK_IS_FIXED(widget));
299   g_return_if_fail (allocation != NULL);
300
301   fixed = GTK_FIXED (widget);
302
303   widget->allocation = *allocation;
304   if (GTK_WIDGET_REALIZED (widget))
305     gdk_window_move_resize (widget->window,
306                             allocation->x, 
307                             allocation->y,
308                             allocation->width, 
309                             allocation->height);
310
311   border_width = GTK_CONTAINER (fixed)->border_width;
312   
313   children = fixed->children;
314   while (children)
315     {
316       child = children->data;
317       children = children->next;
318       
319       if (GTK_WIDGET_VISIBLE (child->widget))
320         {
321           gtk_widget_get_child_requisition (child->widget, &child_requisition);
322           child_allocation.x = child->x + border_width;
323           child_allocation.y = child->y + border_width;
324           child_allocation.width = child_requisition.width;
325           child_allocation.height = child_requisition.height;
326           gtk_widget_size_allocate (child->widget, &child_allocation);
327         }
328     }
329 }
330
331 static void
332 gtk_fixed_paint (GtkWidget    *widget,
333                  GdkRectangle *area)
334 {
335   g_return_if_fail (widget != NULL);
336   g_return_if_fail (GTK_IS_FIXED (widget));
337   g_return_if_fail (area != NULL);
338
339   if (GTK_WIDGET_DRAWABLE (widget))
340     gdk_window_clear_area (widget->window,
341                            area->x, area->y,
342                            area->width, area->height);
343 }
344
345 static void
346 gtk_fixed_draw (GtkWidget    *widget,
347                 GdkRectangle *area)
348 {
349   GtkFixed *fixed;
350   GtkFixedChild *child;
351   GdkRectangle child_area;
352   GList *children;
353
354   g_return_if_fail (widget != NULL);
355   g_return_if_fail (GTK_IS_FIXED (widget));
356
357   if (GTK_WIDGET_DRAWABLE (widget))
358     {
359       fixed = GTK_FIXED (widget);
360       gtk_fixed_paint (widget, area);
361
362       children = fixed->children;
363       while (children)
364         {
365           child = children->data;
366           children = children->next;
367
368           if (gtk_widget_intersect (child->widget, area, &child_area))
369             gtk_widget_draw (child->widget, &child_area);
370         }
371     }
372 }
373
374 static gint
375 gtk_fixed_expose (GtkWidget      *widget,
376                   GdkEventExpose *event)
377 {
378   GtkFixed *fixed;
379   GtkFixedChild *child;
380   GdkEventExpose child_event;
381   GList *children;
382
383   g_return_val_if_fail (widget != NULL, FALSE);
384   g_return_val_if_fail (GTK_IS_FIXED (widget), FALSE);
385   g_return_val_if_fail (event != NULL, FALSE);
386
387   if (GTK_WIDGET_DRAWABLE (widget))
388     {
389       fixed = GTK_FIXED (widget);
390
391       child_event = *event;
392
393       children = fixed->children;
394       while (children)
395         {
396           child = children->data;
397           children = children->next;
398
399           if (GTK_WIDGET_NO_WINDOW (child->widget) &&
400               gtk_widget_intersect (child->widget, &event->area, 
401                                     &child_event.area))
402             gtk_widget_event (child->widget, (GdkEvent*) &child_event);
403         }
404     }
405
406   return FALSE;
407 }
408
409 static void
410 gtk_fixed_add (GtkContainer *container,
411                GtkWidget    *widget)
412 {
413   g_return_if_fail (container != NULL);
414   g_return_if_fail (GTK_IS_FIXED (container));
415   g_return_if_fail (widget != NULL);
416
417   gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
418 }
419
420 static void
421 gtk_fixed_remove (GtkContainer *container,
422                   GtkWidget    *widget)
423 {
424   GtkFixed *fixed;
425   GtkFixedChild *child;
426   GList *children;
427
428   g_return_if_fail (container != NULL);
429   g_return_if_fail (GTK_IS_FIXED (container));
430   g_return_if_fail (widget != NULL);
431
432   fixed = GTK_FIXED (container);
433
434   children = fixed->children;
435   while (children)
436     {
437       child = children->data;
438
439       if (child->widget == widget)
440         {
441           gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
442           
443           gtk_widget_unparent (widget);
444
445           fixed->children = g_list_remove_link (fixed->children, children);
446           g_list_free (children);
447           g_free (child);
448
449           if (was_visible && GTK_WIDGET_VISIBLE (container))
450             gtk_widget_queue_resize (GTK_WIDGET (container));
451
452           break;
453         }
454
455       children = children->next;
456     }
457 }
458
459 static void
460 gtk_fixed_forall (GtkContainer *container,
461                   gboolean      include_internals,
462                   GtkCallback   callback,
463                   gpointer      callback_data)
464 {
465   GtkFixed *fixed;
466   GtkFixedChild *child;
467   GList *children;
468
469   g_return_if_fail (container != NULL);
470   g_return_if_fail (GTK_IS_FIXED (container));
471   g_return_if_fail (callback != NULL);
472
473   fixed = GTK_FIXED (container);
474
475   children = fixed->children;
476   while (children)
477     {
478       child = children->data;
479       children = children->next;
480
481       (* callback) (child->widget, callback_data);
482     }
483 }