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