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