]> Pileus Git - ~andy/gtk/blob - gtk/gtkfixed.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~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 "config.h"
28 #include "gtkfixed.h"
29 #include "gtkprivate.h"
30 #include "gtkintl.h"
31 #include "gtkalias.h"
32 enum {
33   CHILD_PROP_0,
34   CHILD_PROP_X,
35   CHILD_PROP_Y
36 };
37
38 static void gtk_fixed_realize       (GtkWidget        *widget);
39 static void gtk_fixed_size_request  (GtkWidget        *widget,
40                                      GtkRequisition   *requisition);
41 static void gtk_fixed_size_allocate (GtkWidget        *widget,
42                                      GtkAllocation    *allocation);
43 static void gtk_fixed_add           (GtkContainer     *container,
44                                      GtkWidget        *widget);
45 static void gtk_fixed_remove        (GtkContainer     *container,
46                                      GtkWidget        *widget);
47 static void gtk_fixed_forall        (GtkContainer     *container,
48                                      gboolean          include_internals,
49                                      GtkCallback       callback,
50                                      gpointer          callback_data);
51 static GType gtk_fixed_child_type   (GtkContainer     *container);
52
53 static void gtk_fixed_set_child_property (GtkContainer *container,
54                                           GtkWidget    *child,
55                                           guint         property_id,
56                                           const GValue *value,
57                                           GParamSpec   *pspec);
58 static void gtk_fixed_get_child_property (GtkContainer *container,
59                                           GtkWidget    *child,
60                                           guint         property_id,
61                                           GValue       *value,
62                                           GParamSpec   *pspec);
63
64 G_DEFINE_TYPE (GtkFixed, gtk_fixed, GTK_TYPE_CONTAINER)
65
66 static void
67 gtk_fixed_class_init (GtkFixedClass *class)
68 {
69   GtkWidgetClass *widget_class;
70   GtkContainerClass *container_class;
71
72   widget_class = (GtkWidgetClass*) class;
73   container_class = (GtkContainerClass*) class;
74
75   widget_class->realize = gtk_fixed_realize;
76   widget_class->size_request = gtk_fixed_size_request;
77   widget_class->size_allocate = gtk_fixed_size_allocate;
78
79   container_class->add = gtk_fixed_add;
80   container_class->remove = gtk_fixed_remove;
81   container_class->forall = gtk_fixed_forall;
82   container_class->child_type = gtk_fixed_child_type;
83
84   container_class->set_child_property = gtk_fixed_set_child_property;
85   container_class->get_child_property = gtk_fixed_get_child_property;
86
87   gtk_container_class_install_child_property (container_class,
88                                               CHILD_PROP_X,
89                                               g_param_spec_int ("x",
90                                                                 P_("X position"),
91                                                                 P_("X position of child widget"),
92                                                                 G_MININT,
93                                                                 G_MAXINT,
94                                                                 0,
95                                                                 GTK_PARAM_READWRITE));
96
97   gtk_container_class_install_child_property (container_class,
98                                               CHILD_PROP_Y,
99                                               g_param_spec_int ("y",
100                                                                 P_("Y position"),
101                                                                 P_("Y position of child widget"),
102                                                                 G_MININT,
103                                                                 G_MAXINT,
104                                                                 0,
105                                                                 GTK_PARAM_READWRITE));
106 }
107
108 static GType
109 gtk_fixed_child_type (GtkContainer     *container)
110 {
111   return GTK_TYPE_WIDGET;
112 }
113
114 static void
115 gtk_fixed_init (GtkFixed *fixed)
116 {
117   gtk_widget_set_has_window (GTK_WIDGET (fixed), FALSE);
118
119   fixed->children = NULL;
120 }
121
122 GtkWidget*
123 gtk_fixed_new (void)
124 {
125   return g_object_new (GTK_TYPE_FIXED, NULL);
126 }
127
128 static GtkFixedChild*
129 get_child (GtkFixed  *fixed,
130            GtkWidget *widget)
131 {
132   GList *children;
133   
134   children = fixed->children;
135   while (children)
136     {
137       GtkFixedChild *child;
138       
139       child = children->data;
140       children = children->next;
141
142       if (child->widget == widget)
143         return child;
144     }
145
146   return NULL;
147 }
148
149 void
150 gtk_fixed_put (GtkFixed       *fixed,
151                GtkWidget      *widget,
152                gint            x,
153                gint            y)
154 {
155   GtkFixedChild *child_info;
156
157   g_return_if_fail (GTK_IS_FIXED (fixed));
158   g_return_if_fail (GTK_IS_WIDGET (widget));
159
160   child_info = g_new (GtkFixedChild, 1);
161   child_info->widget = widget;
162   child_info->x = x;
163   child_info->y = y;
164
165   gtk_widget_set_parent (widget, GTK_WIDGET (fixed));
166
167   fixed->children = g_list_append (fixed->children, child_info);
168 }
169
170 static void
171 gtk_fixed_move_internal (GtkFixed       *fixed,
172                          GtkWidget      *widget,
173                          gboolean        change_x,
174                          gint            x,
175                          gboolean        change_y,
176                          gint            y)
177 {
178   GtkFixedChild *child;
179   
180   g_return_if_fail (GTK_IS_FIXED (fixed));
181   g_return_if_fail (GTK_IS_WIDGET (widget));
182   g_return_if_fail (widget->parent == GTK_WIDGET (fixed));  
183   
184   child = get_child (fixed, widget);
185
186   g_assert (child);
187
188   gtk_widget_freeze_child_notify (widget);
189   
190   if (change_x)
191     {
192       child->x = x;
193       gtk_widget_child_notify (widget, "x");
194     }
195
196   if (change_y)
197     {
198       child->y = y;
199       gtk_widget_child_notify (widget, "y");
200     }
201
202   gtk_widget_thaw_child_notify (widget);
203   
204   if (gtk_widget_get_visible (widget) &&
205       gtk_widget_get_visible (GTK_WIDGET (fixed)))
206     gtk_widget_queue_resize (GTK_WIDGET (fixed));
207 }
208
209 void
210 gtk_fixed_move (GtkFixed       *fixed,
211                 GtkWidget      *widget,
212                 gint            x,
213                 gint            y)
214 {
215   gtk_fixed_move_internal (fixed, widget, TRUE, x, TRUE, y);
216 }
217
218 static void
219 gtk_fixed_set_child_property (GtkContainer    *container,
220                               GtkWidget       *child,
221                               guint            property_id,
222                               const GValue    *value,
223                               GParamSpec      *pspec)
224 {
225   switch (property_id)
226     {
227     case CHILD_PROP_X:
228       gtk_fixed_move_internal (GTK_FIXED (container),
229                                child,
230                                TRUE, g_value_get_int (value),
231                                FALSE, 0);
232       break;
233     case CHILD_PROP_Y:
234       gtk_fixed_move_internal (GTK_FIXED (container),
235                                child,
236                                FALSE, 0,
237                                TRUE, g_value_get_int (value));
238       break;
239     default:
240       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
241       break;
242     }
243 }
244
245 static void
246 gtk_fixed_get_child_property (GtkContainer *container,
247                               GtkWidget    *child,
248                               guint         property_id,
249                               GValue       *value,
250                               GParamSpec   *pspec)
251 {
252   GtkFixedChild *fixed_child;
253
254   fixed_child = get_child (GTK_FIXED (container), child);
255   
256   switch (property_id)
257     {
258     case CHILD_PROP_X:
259       g_value_set_int (value, fixed_child->x);
260       break;
261     case CHILD_PROP_Y:
262       g_value_set_int (value, fixed_child->y);
263       break;
264     default:
265       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
266       break;
267     }
268 }
269
270 static void
271 gtk_fixed_realize (GtkWidget *widget)
272 {
273   GdkWindowAttr attributes;
274   gint attributes_mask;
275
276   if (!gtk_widget_get_has_window (widget))
277     GTK_WIDGET_CLASS (gtk_fixed_parent_class)->realize (widget);
278   else
279     {
280       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
281
282       attributes.window_type = GDK_WINDOW_CHILD;
283       attributes.x = widget->allocation.x;
284       attributes.y = widget->allocation.y;
285       attributes.width = widget->allocation.width;
286       attributes.height = widget->allocation.height;
287       attributes.wclass = GDK_INPUT_OUTPUT;
288       attributes.visual = gtk_widget_get_visual (widget);
289       attributes.colormap = gtk_widget_get_colormap (widget);
290       attributes.event_mask = gtk_widget_get_events (widget);
291       attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
292       
293       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
294       
295       widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, 
296                                        attributes_mask);
297       gdk_window_set_user_data (widget->window, widget);
298       
299       widget->style = gtk_style_attach (widget->style, widget->window);
300       gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
301     }
302 }
303
304 static void
305 gtk_fixed_size_request (GtkWidget      *widget,
306                         GtkRequisition *requisition)
307 {
308   GtkFixed *fixed;  
309   GtkFixedChild *child;
310   GList *children;
311   GtkRequisition child_requisition;
312
313   fixed = GTK_FIXED (widget);
314   requisition->width = 0;
315   requisition->height = 0;
316
317   children = fixed->children;
318   while (children)
319     {
320       child = children->data;
321       children = children->next;
322
323       if (gtk_widget_get_visible (child->widget))
324         {
325           gtk_widget_size_request (child->widget, &child_requisition);
326
327           requisition->height = MAX (requisition->height,
328                                      child->y +
329                                      child_requisition.height);
330           requisition->width = MAX (requisition->width,
331                                     child->x +
332                                     child_requisition.width);
333         }
334     }
335
336   requisition->height += GTK_CONTAINER (fixed)->border_width * 2;
337   requisition->width += GTK_CONTAINER (fixed)->border_width * 2;
338 }
339
340 static void
341 gtk_fixed_size_allocate (GtkWidget     *widget,
342                          GtkAllocation *allocation)
343 {
344   GtkFixed *fixed;
345   GtkFixedChild *child;
346   GtkAllocation child_allocation;
347   GtkRequisition child_requisition;
348   GList *children;
349   guint16 border_width;
350
351   fixed = GTK_FIXED (widget);
352
353   widget->allocation = *allocation;
354
355   if (gtk_widget_get_has_window (widget))
356     {
357       if (GTK_WIDGET_REALIZED (widget))
358         gdk_window_move_resize (widget->window,
359                                 allocation->x, 
360                                 allocation->y,
361                                 allocation->width, 
362                                 allocation->height);
363     }
364       
365   border_width = GTK_CONTAINER (fixed)->border_width;
366   
367   children = fixed->children;
368   while (children)
369     {
370       child = children->data;
371       children = children->next;
372       
373       if (gtk_widget_get_visible (child->widget))
374         {
375           gtk_widget_get_child_requisition (child->widget, &child_requisition);
376           child_allocation.x = child->x + border_width;
377           child_allocation.y = child->y + border_width;
378
379           if (!gtk_widget_get_has_window (widget))
380             {
381               child_allocation.x += widget->allocation.x;
382               child_allocation.y += widget->allocation.y;
383             }
384           
385           child_allocation.width = child_requisition.width;
386           child_allocation.height = child_requisition.height;
387           gtk_widget_size_allocate (child->widget, &child_allocation);
388         }
389     }
390 }
391
392 static void
393 gtk_fixed_add (GtkContainer *container,
394                GtkWidget    *widget)
395 {
396   gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
397 }
398
399 static void
400 gtk_fixed_remove (GtkContainer *container,
401                   GtkWidget    *widget)
402 {
403   GtkFixed *fixed;
404   GtkFixedChild *child;
405   GtkWidget *widget_container;
406   GList *children;
407
408   fixed = GTK_FIXED (container);
409   widget_container = GTK_WIDGET (container);
410
411   children = fixed->children;
412   while (children)
413     {
414       child = children->data;
415
416       if (child->widget == widget)
417         {
418           gboolean was_visible = gtk_widget_get_visible (widget);
419           
420           gtk_widget_unparent (widget);
421
422           fixed->children = g_list_remove_link (fixed->children, children);
423           g_list_free (children);
424           g_free (child);
425
426           if (was_visible && gtk_widget_get_visible (widget_container))
427             gtk_widget_queue_resize (widget_container);
428
429           break;
430         }
431
432       children = children->next;
433     }
434 }
435
436 static void
437 gtk_fixed_forall (GtkContainer *container,
438                   gboolean      include_internals,
439                   GtkCallback   callback,
440                   gpointer      callback_data)
441 {
442   GtkFixed *fixed = GTK_FIXED (container);
443   GtkFixedChild *child;
444   GList *children;
445
446   children = fixed->children;
447   while (children)
448     {
449       child = children->data;
450       children = children->next;
451
452       (* callback) (child->widget, callback_data);
453     }
454 }
455
456 /**
457  * gtk_fixed_set_has_window:
458  * @fixed: a #GtkFixed
459  * @has_window: %TRUE if a separate window should be created
460  * 
461  * Sets whether a #GtkFixed widget is created with a separate
462  * #GdkWindow for @widget->window or not. (By default, it will be
463  * created with no separate #GdkWindow). This function must be called
464  * while the #GtkFixed is not realized, for instance, immediately after the
465  * window is created.
466  * 
467  * This function was added to provide an easy migration path for
468  * older applications which may expect #GtkFixed to have a separate window.
469  *
470  * Deprecated: 2.20: Use gtk_widget_set_has_window() instead.
471  **/
472 void
473 gtk_fixed_set_has_window (GtkFixed *fixed,
474                           gboolean  has_window)
475 {
476   g_return_if_fail (GTK_IS_FIXED (fixed));
477   g_return_if_fail (!GTK_WIDGET_REALIZED (fixed));
478
479   if (has_window != gtk_widget_get_has_window (GTK_WIDGET (fixed)))
480     {
481       gtk_widget_set_has_window (GTK_WIDGET (fixed), has_window);
482     }
483 }
484
485 /**
486  * gtk_fixed_get_has_window:
487  * @fixed: a #GtkWidget
488  * 
489  * Gets whether the #GtkFixed has its own #GdkWindow.
490  * See gtk_fixed_set_has_window().
491  * 
492  * Return value: %TRUE if @fixed has its own window.
493  *
494  * Deprecated: 2.20: Use gtk_widget_get_has_window() instead.
495  **/
496 gboolean
497 gtk_fixed_get_has_window (GtkFixed *fixed)
498 {
499   g_return_val_if_fail (GTK_IS_FIXED (fixed), FALSE);
500
501   return gtk_widget_get_has_window (GTK_WIDGET (fixed));
502 }
503
504 #define __GTK_FIXED_C__
505 #include "gtkaliasdef.c"