]> Pileus Git - ~andy/gtk/blob - gtk/gtkpaned.c
call the base class init fucntions from all parent types upon class
[~andy/gtk] / gtk / gtkpaned.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 "gtkpaned.h"
20
21
22 static void gtk_paned_class_init (GtkPanedClass    *klass);
23 static void gtk_paned_init       (GtkPaned         *paned);
24 static void gtk_paned_realize    (GtkWidget *widget);
25 static void gtk_paned_map        (GtkWidget      *widget);
26 static void gtk_paned_unmap      (GtkWidget      *widget);
27 static void gtk_paned_unrealize  (GtkWidget *widget);
28 static gint gtk_paned_expose     (GtkWidget      *widget,
29                                 GdkEventExpose *event);
30 static void gtk_paned_add        (GtkContainer   *container,
31                                 GtkWidget      *widget);
32 static void gtk_paned_remove     (GtkContainer   *container,
33                                 GtkWidget      *widget);
34 static void gtk_paned_foreach    (GtkContainer   *container,
35                                 GtkCallback     callback,
36                                 gpointer        callback_data);
37 static GtkType gtk_paned_child_type (GtkContainer *container);
38
39
40 static GtkContainerClass *parent_class = NULL;
41
42
43 guint
44 gtk_paned_get_type (void)
45 {
46   static guint paned_type = 0;
47
48   if (!paned_type)
49     {
50       GtkTypeInfo paned_info =
51       {
52         "GtkPaned",
53         sizeof (GtkPaned),
54         sizeof (GtkPanedClass),
55         (GtkClassInitFunc) gtk_paned_class_init,
56         (GtkObjectInitFunc) gtk_paned_init,
57         /* reversed_1 */ NULL,
58         /* reversed_2 */ NULL,
59         (GtkClassInitFunc) NULL,
60       };
61
62       paned_type = gtk_type_unique (gtk_container_get_type (), &paned_info);
63     }
64
65   return paned_type;
66 }
67
68 static void
69 gtk_paned_class_init (GtkPanedClass *class)
70 {
71   GtkObjectClass *object_class;
72   GtkWidgetClass *widget_class;
73   GtkContainerClass *container_class;
74
75   object_class = (GtkObjectClass*) class;
76   widget_class = (GtkWidgetClass*) class;
77   container_class = (GtkContainerClass*) class;
78
79   parent_class = gtk_type_class (gtk_container_get_type ());
80
81   widget_class->realize = gtk_paned_realize;
82   widget_class->map = gtk_paned_map;
83   widget_class->unmap = gtk_paned_unmap;
84   widget_class->unrealize = gtk_paned_unrealize;
85   widget_class->expose_event = gtk_paned_expose;
86
87   container_class->add = gtk_paned_add;
88   container_class->remove = gtk_paned_remove;
89   container_class->foreach = gtk_paned_foreach;
90   container_class->child_type = gtk_paned_child_type;
91 }
92
93 static GtkType
94 gtk_paned_child_type (GtkContainer *container)
95 {
96   if (!GTK_PANED (container)->child1 || !GTK_PANED (container)->child2)
97     return GTK_TYPE_WIDGET;
98   else
99     return GTK_TYPE_NONE;
100 }
101
102 static void
103 gtk_paned_init (GtkPaned *paned)
104 {
105   GTK_WIDGET_UNSET_FLAGS (paned, GTK_NO_WINDOW);
106
107   paned->child1 = NULL;
108   paned->child2 = NULL;
109   paned->handle = NULL;
110   paned->xor_gc = NULL;
111
112   paned->handle_size = 10;
113   paned->gutter_size = 6;
114   paned->position_set = FALSE;
115   paned->in_drag = FALSE;
116
117   paned->handle_xpos = -1;
118   paned->handle_ypos = -1;
119 }
120
121
122 static void
123 gtk_paned_realize (GtkWidget *widget)
124 {
125   GtkPaned *paned;
126   GdkWindowAttr attributes;
127   gint attributes_mask;
128
129   g_return_if_fail (widget != NULL);
130   g_return_if_fail (GTK_IS_PANED (widget));
131
132   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
133   paned = GTK_PANED (widget);
134
135   attributes.x = widget->allocation.x;
136   attributes.y = widget->allocation.y;
137   attributes.width = widget->allocation.width;
138   attributes.height = widget->allocation.height;
139   attributes.window_type = GDK_WINDOW_CHILD;
140   attributes.wclass = GDK_INPUT_OUTPUT;
141   attributes.visual = gtk_widget_get_visual (widget);
142   attributes.colormap = gtk_widget_get_colormap (widget);
143   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
144   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
145
146   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
147                                    &attributes, attributes_mask);
148   gdk_window_set_user_data (widget->window, paned);
149
150   attributes.x = paned->handle_xpos;
151   attributes.y = paned->handle_ypos;
152   attributes.width = paned->handle_size;
153   attributes.height = paned->handle_size;
154   attributes.cursor = paned->cursor = gdk_cursor_new (GDK_CROSS);
155   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
156                             GDK_BUTTON_RELEASE_MASK |
157                             GDK_POINTER_MOTION_MASK |
158                             GDK_POINTER_MOTION_HINT_MASK);
159   attributes_mask |= GDK_WA_CURSOR;
160
161   paned->handle = gdk_window_new (widget->window,
162                                   &attributes, attributes_mask);
163   gdk_window_set_user_data (paned->handle, paned);
164
165   widget->style = gtk_style_attach (widget->style, widget->window);
166
167   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
168   gtk_style_set_background (widget->style, paned->handle, GTK_STATE_NORMAL);
169
170   gdk_window_show (paned->handle);
171 }
172   
173 static void
174 gtk_paned_map (GtkWidget *widget)
175 {
176   GtkPaned *paned;
177
178   g_return_if_fail (widget != NULL);
179   g_return_if_fail (GTK_IS_PANED (widget));
180
181   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
182   paned = GTK_PANED (widget);
183
184   gdk_window_show (widget->window);
185
186   if (paned->child1 &&
187       GTK_WIDGET_VISIBLE (paned->child1) &&
188       !GTK_WIDGET_MAPPED (paned->child1))
189     gtk_widget_map (paned->child1);
190   if (paned->child2 &&
191       GTK_WIDGET_VISIBLE (paned->child2) &&
192       !GTK_WIDGET_MAPPED (paned->child2))
193     gtk_widget_map (paned->child2);
194 }
195
196 static void
197 gtk_paned_unmap (GtkWidget *widget)
198 {
199   g_return_if_fail (widget != NULL);
200   g_return_if_fail (GTK_IS_PANED (widget));
201
202   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
203
204   gdk_window_hide (widget->window);
205 }
206
207 static void
208 gtk_paned_unrealize (GtkWidget *widget)
209 {
210   GtkPaned *paned;
211
212   g_return_if_fail (widget != NULL);
213   g_return_if_fail (GTK_IS_PANED (widget));
214
215   paned = GTK_PANED (widget);
216
217   if (paned->xor_gc)
218     {
219       gdk_gc_destroy (paned->xor_gc);
220       paned->xor_gc = NULL;
221     }
222
223   if (paned->handle)
224     {
225       gdk_window_set_user_data (paned->handle, NULL);
226       gdk_window_destroy (paned->handle);
227       paned->handle = NULL;
228       gdk_cursor_destroy (paned->cursor);
229       paned->cursor = NULL;
230     }
231
232   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
233     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
234 }
235
236 static gint
237 gtk_paned_expose (GtkWidget      *widget,
238                   GdkEventExpose *event)
239 {
240   GtkPaned *paned;
241   GdkEventExpose child_event;
242
243   g_return_val_if_fail (widget != NULL, FALSE);
244   g_return_val_if_fail (GTK_IS_PANED (widget), FALSE);
245   g_return_val_if_fail (event != NULL, FALSE);
246
247   if (GTK_WIDGET_DRAWABLE (widget))
248     {
249       paned = GTK_PANED (widget);
250
251       /* An expose event for the handle */
252       if (event->window == paned->handle)
253         {
254           gdk_window_set_background (paned->handle,
255                                      &widget->style->bg[widget->state]);
256           gdk_window_clear (paned->handle);
257           gtk_draw_shadow (widget->style, paned->handle,
258                            GTK_WIDGET_STATE(widget),
259                            GTK_SHADOW_OUT, 0, 0,
260                            paned->handle_size, paned->handle_size);
261         }
262       else
263         {
264           child_event = *event;
265           if (paned->child1 &&
266               GTK_WIDGET_NO_WINDOW (paned->child1) &&
267               gtk_widget_intersect (paned->child1, &event->area, &child_event.area))
268             gtk_widget_event (paned->child1, (GdkEvent*) &child_event);
269
270           if (paned->child2 &&
271               GTK_WIDGET_NO_WINDOW (paned->child2) &&
272               gtk_widget_intersect (paned->child2, &event->area, &child_event.area))
273             gtk_widget_event (paned->child2, (GdkEvent*) &child_event);
274
275           /* redraw the groove if necessary */
276           if (gdk_rectangle_intersect (&paned->groove_rectangle, 
277                                        &event->area, 
278                                        &child_event.area))
279             gtk_widget_draw (widget, &child_event.area);
280         }
281     }
282   return FALSE;
283 }
284
285 void
286 gtk_paned_add1 (GtkPaned     *paned,
287                 GtkWidget    *widget)
288 {
289   g_return_if_fail (widget != NULL);
290
291   if (!paned->child1)
292     {
293       gtk_widget_set_parent (widget, GTK_WIDGET (paned));
294
295       if (GTK_WIDGET_VISIBLE (widget->parent))
296         {
297           if (GTK_WIDGET_REALIZED (widget->parent) &&
298               !GTK_WIDGET_REALIZED (widget))
299             gtk_widget_realize (widget);
300           
301           if (GTK_WIDGET_MAPPED (widget->parent) &&
302               !GTK_WIDGET_MAPPED (widget))
303             gtk_widget_map (widget);
304         }
305
306       paned->child1 = widget;
307
308       if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (paned))
309         gtk_widget_queue_resize (widget);
310     }
311 }
312
313 void
314 gtk_paned_add2 (GtkPaned  *paned,
315                 GtkWidget *widget)
316 {
317   g_return_if_fail (widget != NULL);
318
319   if (!paned->child2)
320     {
321       gtk_widget_set_parent (widget, GTK_WIDGET (paned));
322
323       if (GTK_WIDGET_VISIBLE (widget->parent))
324         {
325           if (GTK_WIDGET_REALIZED (widget->parent) &&
326               !GTK_WIDGET_REALIZED (widget))
327             gtk_widget_realize (widget);
328           
329           if (GTK_WIDGET_MAPPED (widget->parent) &&
330               !GTK_WIDGET_MAPPED (widget))
331             gtk_widget_map (widget);
332         }
333
334       paned->child2 = widget;
335
336       if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (paned))
337         gtk_widget_queue_resize (widget);
338     }
339 }
340
341 static void
342 gtk_paned_add (GtkContainer *container,
343                GtkWidget    *widget)
344 {
345   GtkPaned *paned;
346
347   g_return_if_fail (container != NULL);
348   g_return_if_fail (GTK_IS_PANED (container));
349   g_return_if_fail (widget != NULL);
350
351   paned = GTK_PANED (container);
352
353   if (!paned->child1)
354     gtk_paned_add1 (GTK_PANED (container),widget);
355   else if (!paned->child2)
356     gtk_paned_add2 (GTK_PANED (container),widget);
357 }
358
359 static void
360 gtk_paned_remove (GtkContainer *container,
361                   GtkWidget    *widget)
362 {
363   GtkPaned *paned;
364   gboolean was_visible;
365
366   g_return_if_fail (container != NULL);
367   g_return_if_fail (GTK_IS_PANED (container));
368   g_return_if_fail (widget != NULL);
369
370   paned = GTK_PANED (container);
371   was_visible = GTK_WIDGET_VISIBLE (widget);
372   
373   if (paned->child1 == widget)
374     {
375       gtk_widget_unparent (widget);
376
377       paned->child1 = NULL;
378
379       if (was_visible && GTK_WIDGET_VISIBLE (container))
380         gtk_widget_queue_resize (GTK_WIDGET (container));
381     }
382   else if (paned->child2 == widget)
383     {
384       gtk_widget_unparent (widget);
385
386       paned->child2 = NULL;
387
388       if (was_visible && GTK_WIDGET_VISIBLE (container))
389         gtk_widget_queue_resize (GTK_WIDGET (container));
390     }
391 }
392
393 static void
394 gtk_paned_foreach (GtkContainer *container,
395                  GtkCallback   callback,
396                  gpointer      callback_data)
397 {
398   GtkPaned *paned;
399
400   g_return_if_fail (container != NULL);
401   g_return_if_fail (GTK_IS_PANED (container));
402   g_return_if_fail (callback != NULL);
403
404   paned = GTK_PANED (container);
405
406   if (paned->child1)
407     (* callback) (paned->child1, callback_data);
408   if (paned->child2)
409     (* callback) (paned->child2, callback_data);
410 }
411
412 void
413 gtk_paned_handle_size (GtkPaned *paned, guint16 size)
414 {
415   gint x,y;
416
417   if (paned->handle)
418     {
419       gdk_window_get_geometry (paned->handle, &x, &y, NULL, NULL, NULL);
420       gdk_window_move_resize (paned->handle,
421                               x + paned->handle_size / 2 - size / 2,
422                               y + paned->handle_size / 2 - size / 2,
423                               size, size);
424     }
425   
426   paned->handle_size = size;
427 }
428
429 void
430 gtk_paned_gutter_size (GtkPaned *paned, guint16 size)
431 {
432   paned->gutter_size = size;
433
434   if (GTK_WIDGET_VISIBLE (GTK_WIDGET (paned)))
435     gtk_widget_queue_resize (GTK_WIDGET (paned));
436 }
437