]> Pileus Git - ~andy/gtk/blob - gtk/gtkfixed.c
added rc-style argument GtkSpinButton::shadow_type. removed
[~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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gtkfixed.h"
28
29
30 static void gtk_fixed_class_init    (GtkFixedClass    *klass);
31 static void gtk_fixed_init          (GtkFixed         *fixed);
32 static void gtk_fixed_map           (GtkWidget        *widget);
33 static void gtk_fixed_realize       (GtkWidget        *widget);
34 static void gtk_fixed_size_request  (GtkWidget        *widget,
35                                      GtkRequisition   *requisition);
36 static void gtk_fixed_size_allocate (GtkWidget        *widget,
37                                      GtkAllocation    *allocation);
38 static void gtk_fixed_add           (GtkContainer     *container,
39                                      GtkWidget        *widget);
40 static void gtk_fixed_remove        (GtkContainer     *container,
41                                      GtkWidget        *widget);
42 static void gtk_fixed_forall        (GtkContainer     *container,
43                                      gboolean          include_internals,
44                                      GtkCallback       callback,
45                                      gpointer          callback_data);
46 static GtkType gtk_fixed_child_type (GtkContainer     *container);
47
48
49 static GtkContainerClass *parent_class = NULL;
50
51
52 GtkType
53 gtk_fixed_get_type (void)
54 {
55   static GtkType fixed_type = 0;
56
57   if (!fixed_type)
58     {
59       static const GtkTypeInfo fixed_info =
60       {
61         "GtkFixed",
62         sizeof (GtkFixed),
63         sizeof (GtkFixedClass),
64         (GtkClassInitFunc) gtk_fixed_class_init,
65         (GtkObjectInitFunc) gtk_fixed_init,
66         /* reserved_1 */ NULL,
67         /* reserved_2 */ NULL,
68         (GtkClassInitFunc) NULL,
69       };
70
71       fixed_type = gtk_type_unique (GTK_TYPE_CONTAINER, &fixed_info);
72     }
73
74   return fixed_type;
75 }
76
77 static void
78 gtk_fixed_class_init (GtkFixedClass *class)
79 {
80   GtkObjectClass *object_class;
81   GtkWidgetClass *widget_class;
82   GtkContainerClass *container_class;
83
84   object_class = (GtkObjectClass*) class;
85   widget_class = (GtkWidgetClass*) class;
86   container_class = (GtkContainerClass*) class;
87
88   parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
89
90   widget_class->map = gtk_fixed_map;
91   widget_class->realize = gtk_fixed_realize;
92   widget_class->size_request = gtk_fixed_size_request;
93   widget_class->size_allocate = gtk_fixed_size_allocate;
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))
146     gtk_widget_realize (widget);
147
148   if (GTK_WIDGET_VISIBLE (fixed) && GTK_WIDGET_VISIBLE (widget))
149     {
150       if (GTK_WIDGET_MAPPED (fixed))
151         gtk_widget_map (widget);
152       
153       gtk_widget_queue_resize (GTK_WIDGET (fixed));
154     }
155 }
156
157 void
158 gtk_fixed_move (GtkFixed       *fixed,
159                 GtkWidget      *widget,
160                 gint16         x,
161                 gint16         y)
162 {
163   GtkFixedChild *child;
164   GList *children;
165
166   g_return_if_fail (fixed != NULL);
167   g_return_if_fail (GTK_IS_FIXED (fixed));
168   g_return_if_fail (widget != NULL);
169
170   children = fixed->children;
171   while (children)
172     {
173       child = children->data;
174       children = children->next;
175
176       if (child->widget == widget)
177         {
178           child->x = x;
179           child->y = y;
180
181           if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
182             gtk_widget_queue_resize (GTK_WIDGET (fixed));
183
184           break;
185         }
186     }
187 }
188
189 static void
190 gtk_fixed_map (GtkWidget *widget)
191 {
192   GtkFixed *fixed;
193   GtkFixedChild *child;
194   GList *children;
195
196   g_return_if_fail (widget != NULL);
197   g_return_if_fail (GTK_IS_FIXED (widget));
198
199   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
200   fixed = GTK_FIXED (widget);
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   gdk_window_show (widget->window);
214 }
215
216 static void
217 gtk_fixed_realize (GtkWidget *widget)
218 {
219   GdkWindowAttr attributes;
220   gint attributes_mask;
221
222   g_return_if_fail (widget != NULL);
223   g_return_if_fail (GTK_IS_FIXED (widget));
224
225   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
226
227   attributes.window_type = GDK_WINDOW_CHILD;
228   attributes.x = widget->allocation.x;
229   attributes.y = widget->allocation.y;
230   attributes.width = widget->allocation.width;
231   attributes.height = widget->allocation.height;
232   attributes.wclass = GDK_INPUT_OUTPUT;
233   attributes.visual = gtk_widget_get_visual (widget);
234   attributes.colormap = gtk_widget_get_colormap (widget);
235   attributes.event_mask = gtk_widget_get_events (widget);
236   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
237
238   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
239
240   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, 
241                                    attributes_mask);
242   gdk_window_set_user_data (widget->window, widget);
243
244   widget->style = gtk_style_attach (widget->style, widget->window);
245   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
246 }
247
248 static void
249 gtk_fixed_size_request (GtkWidget      *widget,
250                         GtkRequisition *requisition)
251 {
252   GtkFixed *fixed;  
253   GtkFixedChild *child;
254   GList *children;
255   GtkRequisition child_requisition;
256
257   g_return_if_fail (widget != NULL);
258   g_return_if_fail (GTK_IS_FIXED (widget));
259   g_return_if_fail (requisition != NULL);
260
261   fixed = GTK_FIXED (widget);
262   requisition->width = 0;
263   requisition->height = 0;
264
265   children = fixed->children;
266   while (children)
267     {
268       child = children->data;
269       children = children->next;
270
271       if (GTK_WIDGET_VISIBLE (child->widget))
272         {
273           gtk_widget_size_request (child->widget, &child_requisition);
274
275           requisition->height = MAX (requisition->height,
276                                      child->y +
277                                      child_requisition.height);
278           requisition->width = MAX (requisition->width,
279                                     child->x +
280                                     child_requisition.width);
281         }
282     }
283
284   requisition->height += GTK_CONTAINER (fixed)->border_width * 2;
285   requisition->width += GTK_CONTAINER (fixed)->border_width * 2;
286 }
287
288 static void
289 gtk_fixed_size_allocate (GtkWidget     *widget,
290                          GtkAllocation *allocation)
291 {
292   GtkFixed *fixed;
293   GtkFixedChild *child;
294   GtkAllocation child_allocation;
295   GtkRequisition child_requisition;
296   GList *children;
297   guint16 border_width;
298
299   g_return_if_fail (widget != NULL);
300   g_return_if_fail (GTK_IS_FIXED(widget));
301   g_return_if_fail (allocation != NULL);
302
303   fixed = GTK_FIXED (widget);
304
305   widget->allocation = *allocation;
306   if (GTK_WIDGET_REALIZED (widget))
307     gdk_window_move_resize (widget->window,
308                             allocation->x, 
309                             allocation->y,
310                             allocation->width, 
311                             allocation->height);
312
313   border_width = GTK_CONTAINER (fixed)->border_width;
314   
315   children = fixed->children;
316   while (children)
317     {
318       child = children->data;
319       children = children->next;
320       
321       if (GTK_WIDGET_VISIBLE (child->widget))
322         {
323           gtk_widget_get_child_requisition (child->widget, &child_requisition);
324           child_allocation.x = child->x + border_width;
325           child_allocation.y = child->y + border_width;
326           child_allocation.width = child_requisition.width;
327           child_allocation.height = child_requisition.height;
328           gtk_widget_size_allocate (child->widget, &child_allocation);
329         }
330     }
331 }
332
333 static void
334 gtk_fixed_add (GtkContainer *container,
335                GtkWidget    *widget)
336 {
337   g_return_if_fail (container != NULL);
338   g_return_if_fail (GTK_IS_FIXED (container));
339   g_return_if_fail (widget != NULL);
340
341   gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
342 }
343
344 static void
345 gtk_fixed_remove (GtkContainer *container,
346                   GtkWidget    *widget)
347 {
348   GtkFixed *fixed;
349   GtkFixedChild *child;
350   GList *children;
351
352   g_return_if_fail (container != NULL);
353   g_return_if_fail (GTK_IS_FIXED (container));
354   g_return_if_fail (widget != NULL);
355
356   fixed = GTK_FIXED (container);
357
358   children = fixed->children;
359   while (children)
360     {
361       child = children->data;
362
363       if (child->widget == widget)
364         {
365           gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
366           
367           gtk_widget_unparent (widget);
368
369           fixed->children = g_list_remove_link (fixed->children, children);
370           g_list_free (children);
371           g_free (child);
372
373           if (was_visible && GTK_WIDGET_VISIBLE (container))
374             gtk_widget_queue_resize (GTK_WIDGET (container));
375
376           break;
377         }
378
379       children = children->next;
380     }
381 }
382
383 static void
384 gtk_fixed_forall (GtkContainer *container,
385                   gboolean      include_internals,
386                   GtkCallback   callback,
387                   gpointer      callback_data)
388 {
389   GtkFixed *fixed;
390   GtkFixedChild *child;
391   GList *children;
392
393   g_return_if_fail (container != NULL);
394   g_return_if_fail (GTK_IS_FIXED (container));
395   g_return_if_fail (callback != NULL);
396
397   fixed = GTK_FIXED (container);
398
399   children = fixed->children;
400   while (children)
401     {
402       child = children->data;
403       children = children->next;
404
405       (* callback) (child->widget, callback_data);
406     }
407 }