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