Code

OCAL. Fix for Bug #638844 (Errors printed to console if openclipart search fails).
[inkscape.git] / src / libgdl / gdl-dock-paned.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * gdl-dock-paned.h
4  *
5  * This file is part of the GNOME Devtools Libraries.
6  *
7  * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include "gdl-i18n.h"
29 #include <string.h>
30 #include <gtk/gtkhpaned.h>
31 #include <gtk/gtkvpaned.h>
33 #include "gdl-tools.h"
34 #include "gdl-dock-paned.h"
37 /* Private prototypes */
39 static void     gdl_dock_paned_class_init     (GdlDockPanedClass *klass);
40 static void     gdl_dock_paned_instance_init  (GdlDockPaned      *paned);
41 static GObject *gdl_dock_paned_constructor    (GType              type,
42                                                guint              n_construct_properties,
43                                                GObjectConstructParam *construct_param);
44 static void     gdl_dock_paned_set_property   (GObject           *object,
45                                                guint              prop_id,
46                                                const GValue      *value,
47                                                GParamSpec        *pspec);
48 static void     gdl_dock_paned_get_property   (GObject           *object,
49                                                guint              prop_id,
50                                                GValue            *value,
51                                                GParamSpec        *pspec);
53 static void     gdl_dock_paned_destroy        (GtkObject         *object);
55 static void     gdl_dock_paned_add            (GtkContainer      *container,
56                                                GtkWidget         *widget);
57 static void     gdl_dock_paned_forall         (GtkContainer      *container,
58                                                gboolean           include_internals,
59                                                GtkCallback        callback,
60                                                gpointer           callback_data);
61 static GType    gdl_dock_paned_child_type     (GtkContainer      *container);
63 static gboolean gdl_dock_paned_dock_request   (GdlDockObject     *object, 
64                                                gint               x,
65                                                gint               y, 
66                                                GdlDockRequest    *request);
67 static void     gdl_dock_paned_dock           (GdlDockObject    *object,
68                                                GdlDockObject    *requestor,
69                                                GdlDockPlacement  position,
70                                                GValue           *other_data);
72 static void     gdl_dock_paned_set_orientation (GdlDockItem    *item,
73                                                 GtkOrientation  orientation);
75 static gboolean gdl_dock_paned_child_placement (GdlDockObject    *object,
76                                                 GdlDockObject    *child,
77                                                 GdlDockPlacement *placement);
80 /* ----- Class variables and definitions ----- */
82 #define SPLIT_RATIO  0.3
84 enum {
85     PROP_0,
86     PROP_POSITION
87 };
90 /* ----- Private functions ----- */
92 GDL_CLASS_BOILERPLATE (GdlDockPaned, gdl_dock_paned, GdlDockItem, GDL_TYPE_DOCK_ITEM);
94 static void
95 gdl_dock_paned_class_init (GdlDockPanedClass *klass)
96 {
97     GObjectClass       *g_object_class;
98     GtkObjectClass     *gtk_object_class;
99     GtkWidgetClass     *widget_class;
100     GtkContainerClass  *container_class;
101     GdlDockObjectClass *object_class;
102     GdlDockItemClass   *item_class;
104     g_object_class = G_OBJECT_CLASS (klass);
105     gtk_object_class = GTK_OBJECT_CLASS (klass);
106     widget_class = GTK_WIDGET_CLASS (klass);
107     container_class = GTK_CONTAINER_CLASS (klass);
108     object_class = GDL_DOCK_OBJECT_CLASS (klass);
109     item_class = GDL_DOCK_ITEM_CLASS (klass);
111     g_object_class->set_property = gdl_dock_paned_set_property;
112     g_object_class->get_property = gdl_dock_paned_get_property;
113     g_object_class->constructor = gdl_dock_paned_constructor;
114     
115     gtk_object_class->destroy = gdl_dock_paned_destroy;
117     container_class->add = gdl_dock_paned_add;
118     container_class->forall = gdl_dock_paned_forall;
119     container_class->child_type = gdl_dock_paned_child_type;
120     
121     object_class->is_compound = TRUE;
122     
123     object_class->dock_request = gdl_dock_paned_dock_request;
124     object_class->dock = gdl_dock_paned_dock;
125     object_class->child_placement = gdl_dock_paned_child_placement;
126     
127     item_class->has_grip = FALSE;
128     item_class->set_orientation = gdl_dock_paned_set_orientation;    
130     g_object_class_install_property (
131         g_object_class, PROP_POSITION,
132         g_param_spec_uint ("position", _("Position"),
133                            _("Position of the divider in pixels"),
134                            0, G_MAXINT, 0,
135                            G_PARAM_READWRITE |
136                            GDL_DOCK_PARAM_EXPORT | GDL_DOCK_PARAM_AFTER));
139 static void
140 gdl_dock_paned_instance_init (GdlDockPaned *paned)
142     paned->position_changed = FALSE;
143     paned->in_drag = FALSE;
144     paned->last_drag_position = -1;
147 static void
148 gdl_dock_paned_resize_paned_ancestors (GdlDockPaned       *paned, 
149                                        GdlDockExpansionDirection  expansion_direction,
150                                        gint                diff)
152      GtkWidget *widget, *last_widget;
154      g_return_if_fail (GDL_IS_DOCK_PANED (paned));
156      last_widget = GTK_WIDGET (paned);
158      /* make sure resizing only can be done in the drag direction */
159      if (expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_NONE ||
160          ((expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_DOWN || 
161            expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_UP) && 
162           !GTK_IS_VPANED (GDL_DOCK_ITEM (paned)->child)) ||
163          ((expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_LEFT || 
164            expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_RIGHT) && 
165           !GTK_IS_HPANED (GDL_DOCK_ITEM (paned)->child)))
166      {         
167          return;
168      }
170      for (widget = GTK_WIDGET (paned)->parent; widget != NULL; 
171           widget = widget->parent) {
173          if (GTK_IS_PANED (widget)) {
175              GtkPaned *paned = GTK_PANED (widget);
177                  if (last_widget == paned->child1) {
179                      if (!GDL_IS_DOCK_OBJECT(widget->parent)) {
180                          GtkRequisition requisition;
181                          GtkAllocation allocation = paned->child1->allocation;
183                          gtk_widget_size_request (paned->child1, &requisition);
185                          gint new_height =
186                              (allocation.height > requisition.height && diff > 0 ?
187                               allocation.height : requisition.height) + diff;
189                          gtk_widget_set_size_request (paned->child1, -1, new_height);
190                      }
191                      
192                      gtk_paned_set_position (paned, gtk_paned_get_position (paned) + diff);
193                  }
194              
195          } else if (!GDL_IS_DOCK_OBJECT (widget)) {
196              break;
197          }
199          last_widget = widget;
200      }
203 static void 
204 gdl_dock_paned_notify_cb (GObject    *g_object,
205                           GParamSpec *pspec,
206                           gpointer    user_data) 
208     GdlDockPaned *paned;
210     g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data));
211     
212     /* chain the notification to the GdlDockPaned */
213     g_object_notify (G_OBJECT (user_data), pspec->name);
214     
215     paned = GDL_DOCK_PANED (user_data);
216     
217     if (GDL_DOCK_ITEM_USER_ACTION (user_data) && !strcmp (pspec->name, "position")) {
219         GdlDockExpansionDirection expansion_direction;
221         paned->position_changed = TRUE;
223         g_object_get (GDL_DOCK_OBJECT(paned)->master,
224                       "expand-direction", &expansion_direction,
225                       NULL);
227         switch (expansion_direction) {
228         case GDL_DOCK_EXPANSION_DIRECTION_DOWN:
229             if (paned->in_drag) {
230                 gint max_position, position, diff;
231                 g_object_get (GDL_DOCK_ITEM (paned)->child,
232                               "max-position", &max_position,
233                               "position", &position,
234                               NULL);
235  
236                 diff = position - paned->last_drag_position;
237                 paned->last_drag_position = position;
239                 if (diff > 0 && position == max_position) {
240                     gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, diff + 1);
241                 } else {
242                     gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, diff);
243                 }
244                  
245             }
246             break;
247         default:
248             ;
249         }
250     }
253 static gboolean 
254 gdl_dock_paned_button_cb (GtkWidget      *widget,
255                           GdkEventButton *event,
256                           gpointer        user_data)
258     GdlDockPaned *paned;
259     
260     g_return_val_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data), FALSE);
261     
262     paned = GDL_DOCK_PANED (user_data);
263     if (event->button == 1) {
264         if (event->type == GDK_BUTTON_PRESS) {
266             GdlDockExpansionDirection expansion_direction;
268             GDL_DOCK_ITEM_SET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
270             paned->in_drag = TRUE;
272             g_object_get (GDL_DOCK_OBJECT (paned)->master,
273                           "expand-direction", &expansion_direction,
274                           NULL);
276             switch (expansion_direction) {
277             case GDL_DOCK_EXPANSION_DIRECTION_DOWN:
278             {
279                 gint max_position, position;
280                 g_object_get (GDL_DOCK_ITEM (paned)->child,
281                               "max-position", &max_position,
282                               "position", &position,
283                               NULL);
285                 paned->last_drag_position = position;
286                 /* expand the paned's ancestors a bit if the separator is in max position
287                  * to allow dragging in all directions */
288                 if (position == max_position)
289                     gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, 1);
290                 break;
291             }
292             default:
293                 ;
294             }
295         }
296         else if (event->type == GDK_BUTTON_RELEASE) {
297              paned->last_drag_position = -1;
298              paned->in_drag = FALSE;
299         }
300         else {
301             GDL_DOCK_ITEM_UNSET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
302             if (paned->position_changed) {
303                 /* emit pending layout changed signal to track separator position */
304                 if (GDL_DOCK_OBJECT (paned)->master)
305                     g_signal_emit_by_name (GDL_DOCK_OBJECT (paned)->master, "layout-changed");
306                 paned->position_changed = FALSE;
307             }
308         }
309     }
310     
311     return FALSE;
314 static void 
315 gdl_dock_paned_create_child (GdlDockPaned   *paned,
316                              GtkOrientation  orientation) 
318     GdlDockItem *item;
319     
320     item = GDL_DOCK_ITEM (paned);
321     
322     if (item->child)
323         gtk_widget_unparent (GTK_WIDGET (item->child));
324     
325     /* create the container paned */
326     if (orientation == GTK_ORIENTATION_HORIZONTAL)
327         item->child = gtk_hpaned_new ();
328     else
329         item->child = gtk_vpaned_new ();
330     
331     /* get notification for propagation */
332     g_signal_connect (item->child, "notify::position",
333                       (GCallback) gdl_dock_paned_notify_cb, (gpointer) item);
334     g_signal_connect (item->child, "button-press-event",
335                       (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
336     g_signal_connect (item->child, "button-release-event",
337                       (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
338     
339     gtk_widget_set_parent (item->child, GTK_WIDGET (item));
340     gtk_widget_show (item->child);
343 static GObject *
344 gdl_dock_paned_constructor (GType                  type,
345                             guint                  n_construct_properties,
346                             GObjectConstructParam *construct_param)
348     GObject *g_object;
349     
350     g_object = GDL_CALL_PARENT_WITH_DEFAULT (G_OBJECT_CLASS, 
351                                                constructor, 
352                                                (type,
353                                                 n_construct_properties,
354                                                 construct_param),
355                                                NULL);
356     if (g_object) {
357         GdlDockItem *item = GDL_DOCK_ITEM (g_object);
358         
359         if (!item->child)
360             gdl_dock_paned_create_child (GDL_DOCK_PANED (g_object),
361                                          item->orientation);
362         /* otherwise, the orientation was set as a construction
363            parameter and the child is already created */
364     }
365     
366     return g_object;
369 static void
370 gdl_dock_paned_set_property (GObject        *object,
371                              guint           prop_id,
372                              const GValue   *value,
373                              GParamSpec     *pspec)
375     GdlDockItem *item = GDL_DOCK_ITEM (object);
376       
377     switch (prop_id) {
378         case PROP_POSITION:
379             if (item->child && GTK_IS_PANED (item->child))
380                 gtk_paned_set_position (GTK_PANED (item->child),
381                                         g_value_get_uint (value));
382             break;
383         default:
384             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
385             break;
386     }
389 static void
390 gdl_dock_paned_get_property (GObject        *object,
391                              guint           prop_id,
392                              GValue         *value,
393                              GParamSpec     *pspec)
395     GdlDockItem *item = GDL_DOCK_ITEM (object);
396       
397     switch (prop_id) {
398         case PROP_POSITION:
399             if (item->child && GTK_IS_PANED (item->child))
400                 g_value_set_uint (value,
401                                   gtk_paned_get_position (GTK_PANED (item->child)));
402             else
403                 g_value_set_uint (value, 0);
404             break;
405         default:
406             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407             break;
408     }
411 static void
412 gdl_dock_paned_destroy (GtkObject *object)
414     GdlDockItem *item = GDL_DOCK_ITEM (object);
416     /* we need to call the virtual first, since in GdlDockDestroy our
417        children dock objects are detached */
418     GDL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
420     /* after that we can remove the GtkNotebook */
421     if (item->child) {
422         gtk_widget_unparent (item->child);
423         item->child = NULL;
424     };
427 static void
428 gdl_dock_paned_add (GtkContainer *container,
429                     GtkWidget    *widget)
431     GdlDockItem     *item;
432     GtkPaned        *paned;
433     GdlDockPlacement pos = GDL_DOCK_NONE;
434     
435     g_return_if_fail (container != NULL && widget != NULL);
436     g_return_if_fail (GDL_IS_DOCK_PANED (container));
437     g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
439     item = GDL_DOCK_ITEM (container);
440     g_return_if_fail (item->child != NULL);
441     paned = GTK_PANED (item->child);
442     g_return_if_fail (!paned->child1 || !paned->child2);
444     if (!paned->child1)
445         pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
446             GDL_DOCK_LEFT : GDL_DOCK_TOP;
447     else if (!paned->child2)
448         pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
449             GDL_DOCK_RIGHT : GDL_DOCK_BOTTOM;
451     if (pos != GDL_DOCK_NONE)
452         gdl_dock_object_dock (GDL_DOCK_OBJECT (container),
453                               GDL_DOCK_OBJECT (widget),
454                               pos, NULL);
457 static void
458 gdl_dock_paned_forall (GtkContainer *container,
459                        gboolean      include_internals,
460                        GtkCallback   callback,
461                        gpointer      callback_data)
463     GdlDockItem *item;
465     g_return_if_fail (container != NULL);
466     g_return_if_fail (GDL_IS_DOCK_PANED (container));
467     g_return_if_fail (callback != NULL);
469     if (include_internals) {
470         /* use GdlDockItem's forall */
471         GDL_CALL_PARENT (GTK_CONTAINER_CLASS, forall, 
472                            (container, include_internals, callback, callback_data));
473     }
474     else {
475         item = GDL_DOCK_ITEM (container);
476         if (item->child)
477             gtk_container_foreach (GTK_CONTAINER (item->child), callback, callback_data);
478     }
481 static GType
482 gdl_dock_paned_child_type (GtkContainer *container)
484     GdlDockItem *item = GDL_DOCK_ITEM (container);
486     if (gtk_container_child_type (GTK_CONTAINER (item->child)) == G_TYPE_NONE)
487         return G_TYPE_NONE;
488     else
489         return GDL_TYPE_DOCK_ITEM;
492 static void
493 gdl_dock_paned_request_foreach (GdlDockObject *object,
494                                 gpointer       user_data)
496     struct {
497         gint            x, y;
498         GdlDockRequest *request;
499         gboolean        may_dock;
500     } *data = user_data;
501     
502     GdlDockRequest my_request;
503     gboolean       may_dock;
504     
505     my_request = *data->request;
506     may_dock = gdl_dock_object_dock_request (object, data->x, data->y, &my_request);
507     if (may_dock) {
508         data->may_dock = TRUE;
509         *data->request = my_request;
510     }
513 static gboolean
514 gdl_dock_paned_dock_request (GdlDockObject  *object, 
515                              gint            x,
516                              gint            y, 
517                              GdlDockRequest *request)
519     GdlDockItem        *item;
520     guint               bw;
521     gint                rel_x, rel_y;
522     GtkAllocation      *alloc;
523     gboolean            may_dock = FALSE;
524     GdlDockRequest      my_request;
526     g_return_val_if_fail (GDL_IS_DOCK_ITEM (object), FALSE);
528     /* we get (x,y) in our allocation coordinates system */
529     
530     item = GDL_DOCK_ITEM (object);
531     
532     /* Get item's allocation. */
533     alloc = &(GTK_WIDGET (object)->allocation);
534     bw = GTK_CONTAINER (object)->border_width;
536     /* Get coordinates relative to our window. */
537     rel_x = x - alloc->x;
538     rel_y = y - alloc->y;
540     if (request)
541         my_request = *request;
542         
543     /* Check if coordinates are inside the widget. */
544     if (rel_x > 0 && rel_x < alloc->width &&
545         rel_y > 0 && rel_y < alloc->height) {
546         GtkRequisition my, other;
547         gint divider = -1;
548         
549         gdl_dock_item_preferred_size (GDL_DOCK_ITEM (my_request.applicant), &other);
550         gdl_dock_item_preferred_size (GDL_DOCK_ITEM (object), &my);
552         /* It's inside our area. */
553         may_dock = TRUE;
555         /* Set docking indicator rectangle to the widget size. */
556         my_request.rect.x = bw;
557         my_request.rect.y = bw;
558         my_request.rect.width = alloc->width - 2*bw;
559         my_request.rect.height = alloc->height - 2*bw;
561         my_request.target = object;
563         /* See if it's in the border_width band. */
564         if (rel_x < bw) {
565             my_request.position = GDL_DOCK_LEFT;
566             my_request.rect.width *= SPLIT_RATIO;
567             divider = other.width;
568         } else if (rel_x > alloc->width - bw) {
569             my_request.position = GDL_DOCK_RIGHT;
570             my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
571             my_request.rect.width *= SPLIT_RATIO;
572             divider = MAX (0, my.width - other.width);
573         } else if (rel_y < bw) {
574             my_request.position = GDL_DOCK_TOP;
575             my_request.rect.height *= SPLIT_RATIO;
576             divider = other.height;
577         } else if (rel_y > alloc->height - bw) {
578             my_request.position = GDL_DOCK_BOTTOM;
579             my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
580             my_request.rect.height *= SPLIT_RATIO;
581             divider = MAX (0, my.height - other.height);
582             
583         } else { /* Otherwise try our children. */
584             struct {
585                 gint            x, y;
586                 GdlDockRequest *request;
587                 gboolean        may_dock;
588             } data;
590             /* give them coordinates in their allocation system... the
591                GtkPaned has no window, so our children allocation
592                coordinates are our window coordinates */
593             data.x = rel_x;
594             data.y = rel_y;
595             data.request = &my_request;
596             data.may_dock = FALSE;
597             
598             gtk_container_foreach (GTK_CONTAINER (object),
599                                    (GtkCallback) gdl_dock_paned_request_foreach,
600                                    &data);
602             may_dock = data.may_dock;
603             if (!may_dock) {
604                 /* the pointer is on the handle, so snap to top/bottom
605                    or left/right */
606                 may_dock = TRUE;
607                 if (item->orientation == GTK_ORIENTATION_HORIZONTAL) {
608                     if (rel_y < alloc->height / 2) {
609                         my_request.position = GDL_DOCK_TOP;
610                         my_request.rect.height *= SPLIT_RATIO;
611                         divider = other.height;
612                     } else {
613                         my_request.position = GDL_DOCK_BOTTOM;
614                         my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
615                         my_request.rect.height *= SPLIT_RATIO;
616                         divider = MAX (0, my.height - other.height);
617                     }
618                 } else {
619                     if (rel_x < alloc->width / 2) {
620                         my_request.position = GDL_DOCK_LEFT;
621                         my_request.rect.width *= SPLIT_RATIO;
622                         divider = other.width;
623                     } else {
624                         my_request.position = GDL_DOCK_RIGHT;
625                         my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
626                         my_request.rect.width *= SPLIT_RATIO;
627                         divider = MAX (0, my.width - other.width);
628                     }
629                 }
630             }
631         }
633         if (divider >= 0 && my_request.position != GDL_DOCK_CENTER) {
634             if (G_IS_VALUE (&my_request.extra))
635                 g_value_unset (&my_request.extra);
636             g_value_init (&my_request.extra, G_TYPE_UINT);
637             g_value_set_uint (&my_request.extra, (guint) divider);
638         }
639         
640         if (may_dock) {
641             /* adjust returned coordinates so they are relative to
642                our allocation */
643             my_request.rect.x += alloc->x;
644             my_request.rect.y += alloc->y;
645         }
646     }
648     if (may_dock && request)
649         *request = my_request;
650     
651     return may_dock;
654 static void
655 gdl_dock_paned_dock (GdlDockObject    *object,
656                      GdlDockObject    *requestor,
657                      GdlDockPlacement  position,
658                      GValue           *other_data)
660     GtkPaned *paned;
661     gboolean  done = FALSE;
662     gboolean  hresize = FALSE;
663     gboolean  wresize = FALSE;
664     gint      temp = 0;
665     
666     g_return_if_fail (GDL_IS_DOCK_PANED (object));
667     g_return_if_fail (GDL_DOCK_ITEM (object)->child != NULL);
669     paned = GTK_PANED (GDL_DOCK_ITEM (object)->child);
671     if (GDL_IS_DOCK_ITEM (requestor)) {
672         g_object_get (G_OBJECT (requestor), "preferred_height", &temp, NULL);
673         if (temp == -2)
674             hresize = TRUE;
675         temp = 0;
676         g_object_get (G_OBJECT (requestor), "preferred_width", &temp, NULL);
677         if (temp == -2)
678             wresize = TRUE;
679     }
681     /* see if we can dock the item in our paned */
682     switch (GDL_DOCK_ITEM (object)->orientation) {
683         case GTK_ORIENTATION_HORIZONTAL:
684             if (!paned->child1 && position == GDL_DOCK_LEFT) {
685                 gtk_paned_pack1 (paned, GTK_WIDGET (requestor), FALSE, FALSE);
686                 done = TRUE;
687             } else if (!paned->child2 && position == GDL_DOCK_RIGHT) {
688                 gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
689                 done = TRUE;
690             }
691             break;
692         case GTK_ORIENTATION_VERTICAL:
693             if (!paned->child1 && position == GDL_DOCK_TOP) {
694                 gtk_paned_pack1 (paned, GTK_WIDGET (requestor), hresize, FALSE);
695                 done = TRUE;
696             } else if (!paned->child2 && position == GDL_DOCK_BOTTOM) {
697                 gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
698                 done = TRUE;
699             }
700             break;
701         default:
702             break;
703     }
705     if (!done) {
706         /* this will create another paned and reparent us there */
707         GDL_CALL_PARENT (GDL_DOCK_OBJECT_CLASS, dock, (object, requestor, position,
708                                                        other_data));
709     }
710     else {
711         gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor));
712         GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED);
713     }
716 static void
717 gdl_dock_paned_set_orientation (GdlDockItem    *item,
718                                 GtkOrientation  orientation)
720     GtkPaned    *old_paned = NULL, *new_paned;
721     GtkWidget   *child1, *child2;
722     
723     g_return_if_fail (GDL_IS_DOCK_PANED (item));
725     if (item->child) {
726         old_paned = GTK_PANED (item->child);
727         g_object_ref (old_paned);
728         gtk_widget_unparent (GTK_WIDGET (old_paned));
729         item->child = NULL;
730     }
731     
732     gdl_dock_paned_create_child (GDL_DOCK_PANED (item), orientation);
733     
734     if (old_paned) {
735         new_paned = GTK_PANED (item->child);
736         child1 = old_paned->child1;
737         child2 = old_paned->child2;
738     
739         if (child1) {
740             g_object_ref (child1);
741             gtk_container_remove (GTK_CONTAINER (old_paned), child1);
742             gtk_paned_pack1 (new_paned, child1, TRUE, FALSE);
743             g_object_unref (child1);
744         }
745         if (child2) {
746             g_object_ref (child2);
747             gtk_container_remove (GTK_CONTAINER (old_paned), child2);
748             gtk_paned_pack1 (new_paned, child2, TRUE, FALSE);
749             g_object_unref (child2);
750         }
751     }
752     
753     GDL_CALL_PARENT (GDL_DOCK_ITEM_CLASS, set_orientation, (item, orientation));
756 static gboolean 
757 gdl_dock_paned_child_placement (GdlDockObject    *object,
758                                 GdlDockObject    *child,
759                                 GdlDockPlacement *placement)
761     GdlDockItem      *item = GDL_DOCK_ITEM (object);
762     GtkPaned         *paned;
763     GdlDockPlacement  pos = GDL_DOCK_NONE;
764     
765     if (item->child) {
766         paned = GTK_PANED (item->child);
767         if (GTK_WIDGET (child) == paned->child1)
768             pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
769                 GDL_DOCK_LEFT : GDL_DOCK_TOP;
770         else if (GTK_WIDGET (child) == paned->child2)
771             pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
772                 GDL_DOCK_RIGHT : GDL_DOCK_BOTTOM;
773     }
775     if (pos != GDL_DOCK_NONE) {
776         if (placement)
777             *placement = pos;
778         return TRUE;
779     }
780     else
781         return FALSE;
785 /* ----- Public interface ----- */
787 GtkWidget *
788 gdl_dock_paned_new (GtkOrientation orientation)
790     GdlDockPaned *paned;
792     paned = GDL_DOCK_PANED (g_object_new (GDL_TYPE_DOCK_PANED,
793                                           "orientation", orientation, NULL));
794     GDL_DOCK_OBJECT_UNSET_FLAGS (paned, GDL_DOCK_AUTOMATIC);
795     
796     return GTK_WIDGET (paned);