[patch] Save/restore position in GdlDock



Hi Dave & others,

This patch adds some functionality to GdlDock to save and restore the docked position of an item.  This is used when docking/undocking from the popup menu, but should be used in the Anjuta layout managment dialog (yet to be written) too.  Also removes the location menu options from the popup.

The save/restore operations use hinted positions relative to other named items (e.g. "item1" was docked on left of "item2").  The main reason behind this is that non-named (anonymous) item containers are destroyed and created when changing the layout.  Only named ones are guaranteed to always be bound to the dock.  As far as I tested the restore operation is robust, but has the drawback of not always restoring the item's position as the user might expect.  If somebody has an idea on how to improve this I would like to hear it.

May I commit?

Thanks,
Gustavo

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gdl/ChangeLog,v
retrieving revision 1.38
diff -u -r1.38 ChangeLog
--- ChangeLog	2001/11/21 23:04:55	1.38
+++ ChangeLog	2001/12/02 08:20:40
@@ -1,3 +1,30 @@
+2001-12-02  Gustavo Giráldez  <gustavo giraldez gmx net>
+
+	* gdl/TODO.gdl-dock: Updated
+	* gdl/gdl-dock-item.[ch]:
+	Removed location menu option functions and struct fields.
+	Removed some (already fixed) FIXMEs.
+	(gdl_dock_item_save_position, gdl_dock_item_restore_position):
+	New docked position save/restore functions.
+	(gdl_dock_item_get_pos_hint): New class virtual method to support 
+	position saving: returns a hinted relative position of the item to 
+	another	named item.
+	(gdl_dock_item_{dock,undock}_cb): Dock/Undock menu items
+	callbacks.
+	(gdl_dock_item_dock_to): Save docked position if item wants to
+	float.  Containers can no longer be nested inside notebooks: the
+	item is docked relative to the container notebook in such case.
+	(gdl_dock_item_hide): Save current dock position.
+	(gdl_dock_item_show): New function, to show a previously hidden,
+	via gdl_dock_item_hide, item.
+	* gdl/gdl-dock-notebook.c: Implemented get_pos_hint virtual.
+	(gdl_dock_notebook_add): create default label from long name if
+	available.
+	* gdl/gdl-dock-paned.c: Implemented get_pos_hint virtual.
+	* gdl/gdl-dock-tablabel.c (gdl_dock_tablabel_size_allocate):
+	Fixed allocation bug related to unsigned arithmetic operations.
+	* gdl/gdl-dock.[ch] (gdl_dock_get_named_items): New function.
+	
 2001-11-18  Gustavo Giráldez  <gustavo giraldez gmx net>
 
 	* gdl/gdl-dock.c (gdl_dock_layout_load): Test if we have docked
Index: gdl/TODO.gdl-dock
===================================================================
RCS file: /cvs/gnome/gdl/gdl/TODO.gdl-dock,v
retrieving revision 1.1
diff -u -r1.1 TODO.gdl-dock
--- gdl/TODO.gdl-dock	2001/10/10 13:09:14	1.1
+++ gdl/TODO.gdl-dock	2001/12/02 08:20:40
@@ -1,17 +1,9 @@
-* Popup menu for the dragbar
-
 * In GdlDockPaned (drag_request): decide which child to pass the request to in function of the coordinate
 
 * Keyboard navigation in floating items: if the parent window has the focus, the keyboard works (sawfish, follow-focus mode) and the item is still in the "tab ring" (don't know the exact name).
 
-* XML layout saving/restoring.  Idea: make a per-item function which asks for the layout, and make nested calls to build the tree/XML stream
-
 * Floating window size negotiation.  See GnomeDockItem's implementation (preferred_width/height arguments).  Also, if the item is resizable, provide some mechanism for doing that without the aid of the window manager.
 
-* Fix the undock final position.  This is related to the relative sizes of the item (the docked vs. the floating sizes)
-
-* Emit "layout_changed" signal in the dock.
-
 * When docking with paned, split the paned according to previous relative sizes or something like that.
 
 * Dock to floating items (is this really useful/intuitive?)
@@ -24,8 +16,6 @@
 
 * Make a nicer dragbar for the items, with buttons for undocking, closing, hidding, etc. (See sodipodi, kdevelop)
 
-* Decide whether to use signals for drag_{begin,motion,end} in the items, or just call gdl_dock_* directly.  Signal pros: API hide, possibility to hook other functions, "compatibility" with GnomeDock.  Signal cons: slower (?), less clear.
-
 * Virtualize reorder (?): don't know if this would be useful.
 
 * Virtualize dock_to: don't know either.  Would allow implementing different docking behavior.  Contrast with next item...
@@ -33,8 +23,6 @@
 * Make a dock_to counterpart: dock_from or something like that.  The basic idea is that if an item doesn't know how to solve a docking request, it transfers the task to the target.  This way, both functions are complementary from a semantic point of view.  This also allows for easier extensibility, as new docking ways are implemented in the "host" dockitem.
 
 * Click to hide in paned handle: basically what mozilla and nautilus do.  Should only be enabled if the "hideable" property (see above) is enabled.
-
-* GdlDockNotebook: self-explanatory, I think.
 
 * GdlDockBand: implement a dockitem which can hold items the same way as GnomeDockBand does.
 
Index: gdl/gdl-dock-item.c
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock-item.c,v
retrieving revision 1.3
diff -u -r1.3 gdl-dock-item.c
--- gdl/gdl-dock-item.c	2001/11/10 14:52:24	1.3
+++ gdl/gdl-dock-item.c	2001/12/02 08:20:53
@@ -38,8 +38,6 @@
 static void  gdl_dock_item_set_floating  (GdlDockItem *item, 
                                           gboolean val);
 
-static void  gdl_dock_item_location        (GtkWidget   *widget,
-                                            GdlDockItem *item);
 static void  gdl_dock_item_dock_drag_start (GdlDockItem *item);
 
 static gint  gdl_dock_item_button_changed (GtkWidget *widget,
@@ -58,7 +56,11 @@
 static void  gdl_dock_item_hide_cb       (GtkWidget   *widget,
                                           GdlDockItem *item);
 
+static void  gdl_dock_item_save_position (GdlDockItem *item,
+                                          gboolean     save_floating);
 
+static void  gdl_dock_item_restore_position (GdlDockItem *item);
+
 /* Class variables and definitions */
 
 enum {
@@ -91,8 +93,6 @@
 struct DockItemMenu {
     GtkWidget *dock, *undock;
     GtkWidget *hide;
-    GtkWidget *location_menu, *location;
-    GtkWidget *left, *right, *top, *bottom, *center;
     GtkWidget *first_option;
 };
 
@@ -209,6 +209,7 @@
     klass->set_orientation = NULL;
     klass->save_layout = NULL;
     klass->item_hide = NULL;
+    klass->get_pos_hint = NULL;
 }
 
 static void
@@ -236,6 +237,9 @@
     item->in_resize = FALSE;
     item->handle_shown = TRUE;
     item->drag_handle_size = DEFAULT_DRAG_HANDLE_SIZE;
+
+    item->last_pos.position = GDL_DOCK_FLOATING;
+    item->last_pos.peer = NULL;
 }
 
 static void
@@ -345,6 +349,7 @@
     };
     g_free (item->name);
     g_free (item->long_name);
+    g_free (item->last_pos.peer);
 
     if (item->menu) {
         gtk_widget_destroy (item->menu);
@@ -870,21 +875,6 @@
 }
 
 static void
-gdl_dock_item_location (GtkWidget *widget,
-                        GdlDockItem *item)
-{
-    guint position;
-    GtkWidget *parent;
-    
-    /* Reposition item. */
-    position = GPOINTER_TO_UINT (gtk_object_get_data (GTK_OBJECT (widget), "position"));    
-    GDL_DOCK_ITEM_GET_PARENT (item, parent);
-    gdl_dock_item_dock_to (item, GDL_DOCK_ITEM (parent), position, -1);
-
-    /* FIXME: emit layout_changed signal on the dock */
-}
-
-static void
 gdl_dock_item_dock_drag_start (GdlDockItem *item)
 {
     GtkWidget *widget;
@@ -942,6 +932,33 @@
 }
 
 static void
+gdl_dock_item_dock_cb (GtkWidget   *widget,
+                       GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    /* force docking even if saved position is floating */
+    if (item->last_pos.position == GDL_DOCK_FLOATING)
+        item->last_pos.position = GDL_DOCK_TOP;
+
+    gdl_dock_item_restore_position (item);
+
+    /* layout has changed */
+    gtk_signal_emit_by_name (GTK_OBJECT (item->dock), "layout_changed");
+}
+
+static void
+gdl_dock_item_undock_cb (GtkWidget   *widget,
+                         GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    /* current position is saved in dock_to when the item floats */
+    gdl_dock_item_dock_to (item, NULL, GDL_DOCK_FLOATING, -1);
+    gtk_signal_emit_by_name (GTK_OBJECT (item->dock), "layout_changed");
+}
+
+static void
 gdl_dock_item_popup_menu (GdlDockItem  *item, 
                           gint          button,
                           guint32       time)
@@ -962,6 +979,10 @@
         /* Dock/Undock menuitem. */
         menu_data->dock = gtk_menu_item_new_with_label (_("Dock"));
         menu_data->undock = gtk_menu_item_new_with_label (_("Undock"));
+        gtk_signal_connect (GTK_OBJECT (menu_data->dock), "activate", 
+                            GTK_SIGNAL_FUNC (gdl_dock_item_dock_cb), item);
+        gtk_signal_connect (GTK_OBJECT (menu_data->undock), "activate", 
+                            GTK_SIGNAL_FUNC (gdl_dock_item_undock_cb), item);
         gtk_widget_ref (menu_data->dock);
         gtk_widget_ref (menu_data->undock);
         menu_data->first_option = NULL;
@@ -972,58 +993,6 @@
         gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
                             GTK_SIGNAL_FUNC (gdl_dock_item_hide_cb), item);
 
-        /* Horizontal line. */
-        gtk_menu_append (GTK_MENU (item->menu), gtk_menu_item_new ());
-
-        /* Location menu. */
-        mitem = menu_data->location = 
-            gtk_menu_item_new_with_label (_("Location"));
-        gtk_menu_append (GTK_MENU (item->menu), mitem);
-
-        menu_data->location_menu = gtk_menu_new ();
-        gtk_menu_item_set_submenu (GTK_MENU_ITEM (mitem), 
-                                   menu_data->location_menu);
-        
-        /* Top. */
-        mitem = menu_data->top = gtk_menu_item_new_with_label (_("Top"));
-        gtk_menu_append (GTK_MENU (menu_data->location_menu), mitem);
-        gtk_object_set_data (GTK_OBJECT (mitem), "position", 
-                             GUINT_TO_POINTER (GDL_DOCK_TOP));
-        gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
-                            GTK_SIGNAL_FUNC (gdl_dock_item_location), item);
-
-        /* Left. */
-        mitem = menu_data->left = gtk_menu_item_new_with_label (_("Left"));
-        gtk_menu_append (GTK_MENU (menu_data->location_menu), mitem);
-        gtk_object_set_data (GTK_OBJECT (mitem), "position", 
-                             GUINT_TO_POINTER (GDL_DOCK_LEFT));
-        gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
-                            GTK_SIGNAL_FUNC (gdl_dock_item_location), item);
-        
-        /* Center. */                    
-        mitem = menu_data->center = gtk_menu_item_new_with_label (_("Center"));
-        gtk_menu_append (GTK_MENU (menu_data->location_menu), mitem);
-        gtk_object_set_data (GTK_OBJECT (mitem), "position", 
-                             GUINT_TO_POINTER (GDL_DOCK_CENTER));
-        gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
-                            GTK_SIGNAL_FUNC (gdl_dock_item_location), item);
-        
-        /* Right */
-        mitem = menu_data->right = gtk_menu_item_new_with_label (_("Right"));
-        gtk_menu_append (GTK_MENU (menu_data->location_menu), mitem);
-        gtk_object_set_data (GTK_OBJECT (mitem), "position", 
-                             GUINT_TO_POINTER (GDL_DOCK_RIGHT));
-        gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
-                            GTK_SIGNAL_FUNC (gdl_dock_item_location), item);
-
-        /* Bottom. */
-        mitem = menu_data->bottom = gtk_menu_item_new_with_label (_("Bottom"));
-        gtk_menu_append (GTK_MENU (menu_data->location_menu), mitem);
-        gtk_object_set_data (GTK_OBJECT (mitem), "position", 
-                             GUINT_TO_POINTER (GDL_DOCK_BOTTOM));
-        gtk_signal_connect (GTK_OBJECT (mitem), "activate", 
-                            GTK_SIGNAL_FUNC (gdl_dock_item_location), item);
-
     } else
         menu_data = gtk_object_get_user_data (GTK_OBJECT (item->menu));
 
@@ -1040,9 +1009,6 @@
         menu_data->first_option = menu_data->undock;
     };
 
-    gtk_widget_set_sensitive (menu_data->location, 
-                              !GDL_DOCK_ITEM_IS_FLOATING (item));
-
     /* Show popup menu. */
     gtk_widget_show_all (item->menu);
     gtk_menu_popup (GTK_MENU (item->menu), NULL, NULL, NULL, NULL, 
@@ -1270,7 +1236,135 @@
     gtk_signal_emit_by_name (dock, "layout_changed");
 }
 
+/* save the current docked position wrt to a named (i.e. non-anonymous and
+ * bound to the dock) item */
+static void
+gdl_dock_item_save_position (GdlDockItem *item,
+                             gboolean     save_floating)
+{
+    GtkWidget *parent;
+
+    /* don't save floating pos */
+    if (GDL_DOCK_ITEM_IS_FLOATING (item) && !save_floating)
+        return;
+
+    GDL_DOCK_ITEM_GET_PARENT (GTK_WIDGET (item), parent);
+    if (parent) {
+        if (item->last_pos.peer) {
+            g_free (item->last_pos.peer);
+            item->last_pos.peer = NULL;
+        };
+
+        if (GDL_IS_DOCK (parent)) {
+            item->last_pos.position = GDL_DOCK_TOP;
+
+            /* peer NULL means the dock */
+            item->last_pos.peer = NULL;
+
+        } else {
+            item->last_pos.peer = gdl_dock_item_get_pos_hint (
+                GDL_DOCK_ITEM (parent), item, &item->last_pos.position);
+        };
+    };
+
+    return;
+}
+
+static void  
+gdl_dock_item_restore_position (GdlDockItem *item)
+{
+    GtkWidget        *target = GTK_WIDGET (item);
+    GtkWidget        *parent;
+    GdlDockPlacement  new_pos = GDL_DOCK_FLOATING;
+    GdlDockItem      *item_target;
+    
+    g_return_if_fail (item != NULL);
+
+    while (target) {
+        item_target = GDL_DOCK_ITEM (target);
+
+        new_pos = item_target->last_pos.position;
+        /* special cases */
+        if (new_pos == GDL_DOCK_FLOATING) {
+            target = NULL;
+            break;
+        } else if (!item_target->last_pos.peer) {
+            /* there is no saved docking position: dock to the dock :-) */
+            target = item->dock;
+            break;
+        };
+        
+        /* find peer */
+        target = GTK_WIDGET (gdl_dock_get_item_by_name (
+            GDL_DOCK (item->dock), item_target->last_pos.peer));
+
+        if (target) {
+            /* found: check if still docked */
+            GDL_DOCK_ITEM_GET_PARENT (GDL_DOCK_ITEM (target), parent);
+            if (parent)
+                break;
+            
+        } else {
+            /* the peer is no longer bound to the dock... dock it in the top
+               of the hierarchy but respecting the previous position */
+            target = item->dock;
+            break;
+        };
+    };
+
+    if (target == item->dock) {
+        GtkWidget *w;
+
+        /* FIXME: damned special case! we need a more uniform way to do this
+           it's also more or less done in gdl_dock_drag_end */
+        GDL_DOCK_ITEM_GET_PARENT (item, parent);
+
+        w = GTK_WIDGET (item);
+        gtk_widget_ref (w);
+        if (w->parent) {
+            gtk_container_remove (GTK_CONTAINER (w->parent), w);
+            if (GDL_IS_DOCK_ITEM (parent))
+                gdl_dock_item_auto_reduce (GDL_DOCK_ITEM (parent));
+        };
+        gdl_dock_add_item (GDL_DOCK (item->dock), item, new_pos);
+        gtk_widget_unref (w);
+
+    } else {
+        gdl_dock_item_dock_to (item, GDL_DOCK_ITEM (target), new_pos, -1);
+    };
+}
+
 
+/* This function returns the name of a peer dockitem to caller and sets
+ * position to the relative position between the items. 
+ * If the caller is NULL, it means the parent has made the call and is
+ * looking for a child's name. */
+gchar *
+gdl_dock_item_get_pos_hint (GdlDockItem      *item,
+                            GdlDockItem      *caller,
+                            GdlDockPlacement *position)
+{
+    GdlDockItemClass *klass;
+
+    g_return_val_if_fail (item != NULL, NULL);
+
+    /* call virtual */
+    klass = GDL_DOCK_ITEM_CLASS (GTK_OBJECT (item)->klass);
+    if (klass->get_pos_hint)
+        return klass->get_pos_hint (item, caller, position);
+
+    if (caller) {
+        /* this would imply a dockitem is docked inside us, which is not 
+           possible */
+        g_warning (_("gdl_dock_item_get_pos_hint called for a regular item "
+                     "in traversing the docking hierarchy up"));
+        return NULL;
+
+    } else
+        return g_strdup (item->name);
+}
+
+
 /* ----------------------------------------------------------------------
  * Public interface 
  * ---------------------------------------------------------------------- */
@@ -1288,8 +1382,6 @@
     item->long_name = g_strdup (long_name);
     item->behavior = behavior;
 
-    /* FIXME: this should create the label using the description 
-       (or translated name) */
     gdl_dock_item_set_tablabel (item, gdl_dock_tablabel_new (item->long_name));
     
     return GTK_WIDGET (item);
@@ -1374,6 +1466,9 @@
 
     /* Item wants to float. */
     if (position == GDL_DOCK_FLOATING || !target_item) {
+        /* save previous docking position */
+        gdl_dock_item_save_position (item, FALSE);
+
         /* Remove widget from current container. */
         if (real_old_parent)           
             gtk_container_remove (GTK_CONTAINER (real_old_parent), widget);
@@ -1388,13 +1483,22 @@
 
     } else {
         GtkWidget *target, *parent, *real_parent;
+        gboolean target_resolved = FALSE;
 
-        target = GTK_WIDGET (target_item);
-
-        real_parent = target->parent;
-        GDL_DOCK_ITEM_GET_PARENT (target, parent);
-        if (!parent)
-            parent = real_parent;
+        do {
+            /* get target and target's parent */
+            target = GTK_WIDGET (target_item);
+            real_parent = target->parent;
+            GDL_DOCK_ITEM_GET_PARENT (target, parent);
+            if (!parent)
+                parent = real_parent;
+
+            if (GDL_IS_DOCK_NOTEBOOK (parent))
+                /* do not allow composite docking inside a notebook */
+                target_item = GDL_DOCK_ITEM (parent);
+            else
+                target_resolved = TRUE;
+        } while (!target_resolved);
 
         /* Unfloat item. */
         if (GDL_DOCK_ITEM_IS_FLOATING (item))
@@ -1408,6 +1512,8 @@
                current item.  Otherwise, we create a GdlDockNotebook and
                add it in place of the target. */
             if (!GDL_IS_DOCK_NOTEBOOK (target)) {
+                /* check if the target is already docked in a notebook
+                   note: this disallows nesting notebooks */
                 gtk_widget_ref (target);
                 gtk_container_remove (GTK_CONTAINER (real_parent), target);
                 nb = gdl_dock_notebook_new ();
@@ -1491,9 +1597,6 @@
         }
     }
     
-    /* Set item placement. */
-    item->placement = position;
-
     /* Decrease refcount (was increased to prevent destruction). */
     gtk_widget_unref (widget);
     
@@ -1792,6 +1895,9 @@
 {
     GdlDockItemClass *klass;
 
+    /* save current docking position */
+    gdl_dock_item_save_position (item, TRUE);
+
     /* auto_reduce barrier to avoid reentrancy problems */
     item->disable_auto_reduce = TRUE;
 
@@ -1821,6 +1927,16 @@
 
     item->disable_auto_reduce = FALSE;
 }
+
+
+void
+gdl_dock_item_show (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    gdl_dock_item_restore_position (item);
+}
+
 
 void
 gdl_dock_item_save_layout (GdlDockItem *item,
Index: gdl/gdl-dock-item.h
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock-item.h,v
retrieving revision 1.2
diff -u -r1.2 gdl-dock-item.h
--- gdl/gdl-dock-item.h	2001/10/10 13:09:14	1.2
+++ gdl/gdl-dock-item.h	2001/12/02 08:20:55
@@ -14,6 +14,7 @@
 #define GDL_IS_DOCK_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_ITEM))
 
 #define GDL_DOCK_ITEM_IS_FLOATING(item) ((item)->is_floating)
+#define GDL_DOCK_ITEM_IS_SHOWN(item)  (GTK_WIDGET (item)->parent)
 
 #define GDL_DOCK_ITEM_IS_BOUND(item)  ((item)->dock != NULL)
 
@@ -64,9 +65,6 @@
     gchar               *long_name;
 
     GdlDockItemBehavior  behavior;
-    /* FIXME: this should go away and be replaced using layout managment
-       functions */
-    GdlDockPlacement     placement;
     GtkOrientation       orientation;
     GtkWidget           *dock;
     GtkWidget           *tab_label;
@@ -87,6 +85,11 @@
 
     /* these should be gint and not guint... trust me */
     gint       float_width, float_height;
+
+    struct {
+        GdlDockPlacement  position;
+        gchar            *peer;
+    } last_pos;
 };
 
 /* structure for drag_request return information */
@@ -98,6 +101,7 @@
     GdkRectangle      rect;  /* where will the item dock */
 };
 
+
 struct _GdlDockItemClass {
     GtkBinClass parent_class;
 
@@ -122,6 +126,10 @@
                                    xmlNodePtr   node);
 
     void     (* item_hide)        (GdlDockItem *item);
+
+    gchar *  (* get_pos_hint)     (GdlDockItem      *item,
+                                   GdlDockItem      *caller,
+                                   GdlDockPlacement *position);
 };
 
 
@@ -166,8 +174,13 @@
 
 void           gdl_dock_item_hide              (GdlDockItem *item);
 
+void           gdl_dock_item_show              (GdlDockItem *item);
+
 void           gdl_dock_item_save_layout       (GdlDockItem *item,
                                                 xmlNodePtr   node);
 
+gchar         *gdl_dock_item_get_pos_hint      (GdlDockItem      *item,
+                                                GdlDockItem      *caller,
+                                                GdlDockPlacement *position);
 
 #endif
Index: gdl/gdl-dock-notebook.c
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock-notebook.c,v
retrieving revision 1.3
diff -u -r1.3 gdl-dock-notebook.c
--- gdl/gdl-dock-notebook.c	2001/11/10 14:52:24	1.3
+++ gdl/gdl-dock-notebook.c	2001/12/02 08:20:56
@@ -36,6 +36,10 @@
 static void  gdl_dock_notebook_hide_foreach  (GtkWidget *widget,
                                               gpointer   data);
 
+static gchar *gdl_dock_notebook_get_pos_hint (GdlDockItem      *item,
+                                              GdlDockItem      *caller,
+                                              GdlDockPlacement *position);
+
 /* Class variables and definitions */
 
 static GdlDockItemClass *parent_class = NULL;
@@ -66,6 +70,7 @@
     item_class->set_orientation = gdl_dock_notebook_set_orientation;    
     item_class->save_layout = gdl_dock_notebook_layout_save;
     item_class->item_hide = gdl_dock_notebook_hide;
+    item_class->get_pos_hint = gdl_dock_notebook_get_pos_hint;
 }
 
 static void
@@ -95,10 +100,12 @@
         gdl_dock_item_window_sink (item);
 
     label = gdl_dock_item_get_tablabel (item);
-    if (!label)
-        /* FIXME: get long name, and do it with gtk_object_get */
-        label = gtk_label_new (item->name);
-    else if (GDL_IS_DOCK_TABLABEL (label)) {
+    if (!label) {
+        if (item->long_name)
+            label = gtk_label_new (item->long_name);
+        else
+            label = gtk_label_new (item->name);
+    } else if (GDL_IS_DOCK_TABLABEL (label)) {
         gdl_dock_tablabel_deactivate (GDL_DOCK_TABLABEL (label));
         /* hide the item drag handle, as we will use the tablabel's */
         gdl_dock_item_hide_handle (item);
@@ -282,6 +289,61 @@
     
     gdl_dock_item_hide (GDL_DOCK_ITEM (widget));
 }
+
+static gchar *
+gdl_dock_notebook_get_pos_hint (GdlDockItem      *item,
+                                GdlDockItem      *caller,
+                                GdlDockPlacement *position)
+{
+    GdlDockNotebook  *notebook;
+    GList            *pages, *l;
+    gchar            *ret_val = NULL;
+    GdlDockItem      *child;
+    GdlDockPlacement  place;
+
+    g_return_val_if_fail (item != NULL, NULL);
+
+    notebook = GDL_DOCK_NOTEBOOK (item);
+    l = pages = gtk_container_children (GTK_CONTAINER (notebook->notebook));
+
+    if (caller) {
+        gboolean          caller_found = FALSE;
+
+        while (l && !(ret_val && caller_found)) {
+            /* find caller among children and a peer with name */
+            child = GDL_DOCK_ITEM (l->data);
+            if (child == caller)
+                caller_found = TRUE;
+            else if (!ret_val) 
+                ret_val = gdl_dock_item_get_pos_hint (child, NULL, &place);
+            
+            l = l->next;
+        };
+
+        if (caller_found)
+            *position = GDL_DOCK_CENTER;
+        else
+            g_warning (_("gdl_dock_notebook_get_pos_hint called with a caller "
+                         "not among notebook's children"));
+
+    } else {
+        if (item->name)
+            ret_val = g_strdup (item->name);
+        else {
+            /* traverse children looking for a named item */
+            while (l && !ret_val) {
+                child = GDL_DOCK_ITEM (l->data);
+                ret_val = gdl_dock_item_get_pos_hint (child, NULL, &place);
+                l = l->next;
+            };
+        };
+    };
+
+    g_list_free (pages);
+
+    return ret_val;
+}
+
 
 /* Public interface */
 
Index: gdl/gdl-dock-paned.c
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock-paned.c,v
retrieving revision 1.2
diff -u -r1.2 gdl-dock-paned.c
--- gdl/gdl-dock-paned.c	2001/10/10 13:09:14	1.2
+++ gdl/gdl-dock-paned.c	2001/12/02 08:21:00
@@ -106,6 +106,10 @@
                                                 xmlNodePtr   node);
 static void     gdl_dock_paned_hide            (GdlDockItem *item);
 
+static gchar   *gdl_dock_paned_get_pos_hint    (GdlDockItem      *item,
+                                                GdlDockItem      *caller,
+                                                GdlDockPlacement *position);
+
 static GdlDockItemClass *parent_class = NULL;
 
 
@@ -153,7 +157,8 @@
     dock_item_class->set_orientation = gdl_dock_paned_set_orientation;
     dock_item_class->save_layout = gdl_dock_paned_layout_save;
     dock_item_class->item_hide = gdl_dock_paned_hide;
-    
+    dock_item_class->get_pos_hint = gdl_dock_paned_get_pos_hint;
+
     gtk_object_add_arg_type("GdlDockPaned::handle_size", GTK_TYPE_UINT,
                             GTK_ARG_READWRITE, ARG_HANDLE_SIZE);
     gtk_object_add_arg_type("GdlDockPaned::quantum", GTK_TYPE_UINT,
@@ -1233,6 +1238,63 @@
     /* Auto reduce parent. */
     if (parent && GDL_IS_DOCK_ITEM (parent))
         gdl_dock_item_auto_reduce (GDL_DOCK_ITEM (parent));
+}
+
+static gchar *
+gdl_dock_paned_get_pos_hint (GdlDockItem      *item,
+                             GdlDockItem      *caller,
+                             GdlDockPlacement *position)
+{
+    GdlDockPaned *paned;
+
+    g_return_val_if_fail (item != NULL, NULL);
+
+    paned = GDL_DOCK_PANED (item);
+    if (caller) {
+        GdlDockPlacement place;
+
+        /* going up the hierarchy */
+        /* FIXME: handle the case when the item has not been auto_reduced 
+           and propagate the call to the parent */
+        if (GTK_WIDGET (caller) == paned->child1) {
+            if (item->orientation == GTK_ORIENTATION_HORIZONTAL)
+                *position = GDL_DOCK_LEFT;
+            else
+                *position = GDL_DOCK_TOP;
+            return gdl_dock_item_get_pos_hint (GDL_DOCK_ITEM (paned->child2), 
+                                               NULL, &place);
+
+        }
+        else if (GTK_WIDGET (caller) == paned->child2) {
+            if (item->orientation == GTK_ORIENTATION_HORIZONTAL)
+                *position = GDL_DOCK_RIGHT;
+            else
+                *position = GDL_DOCK_BOTTOM;
+            return gdl_dock_item_get_pos_hint (GDL_DOCK_ITEM (paned->child1), 
+                                               NULL, &place);
+
+        }
+        else {
+            g_warning (_("gdl_dock_paned_get_pos_hint called with a "
+                         "contained child"));
+            return NULL;
+        };
+
+    } else {
+        /* going down the hierarchy */
+        if (item->name)
+            return g_strdup (item->name);
+
+        /* try with our children */
+        if (paned->child1)
+            return gdl_dock_item_get_pos_hint (GDL_DOCK_ITEM (paned->child1), 
+                                               NULL, position);
+        else if (paned->child2)
+            return gdl_dock_item_get_pos_hint (GDL_DOCK_ITEM (paned->child2), 
+                                               NULL, position);
+        else 
+            return NULL;
+    };
 }
 
 
Index: gdl/gdl-dock-tablabel.c
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock-tablabel.c,v
retrieving revision 1.1
diff -u -r1.1 gdl-dock-tablabel.c
--- gdl/gdl-dock-tablabel.c	2001/10/10 13:09:14	1.1
+++ gdl/gdl-dock-tablabel.c	2001/12/02 08:21:01
@@ -260,10 +260,12 @@
         child_allocation.y = border_width;
 
         if (tablabel->orientation == GTK_ORIENTATION_HORIZONTAL) {
-            allocation->width -= tablabel->drag_handle_size;
+            allocation->width = MAX (1, (int) allocation->width - 
+                                     (int) tablabel->drag_handle_size);
             child_allocation.x += tablabel->drag_handle_size;
         } else {
-            allocation->height -= tablabel->drag_handle_size;
+            allocation->height = MAX (1, (int) allocation->height - 
+                                      (int) tablabel->drag_handle_size);
         };
 
         child_allocation.width = 
Index: gdl/gdl-dock.c
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock.c,v
retrieving revision 1.5
diff -u -r1.5 gdl-dock.c
--- gdl/gdl-dock.c	2001/11/21 23:05:04	1.5
+++ gdl/gdl-dock.c	2001/12/02 08:21:04
@@ -1025,3 +1025,11 @@
     else
         return NULL;
 }
+
+GList *
+gdl_dock_get_named_items (GdlDock *dock)
+{
+    g_return_val_if_fail (dock != NULL, NULL);
+
+    return g_list_copy (dock->items);
+}
Index: gdl/gdl-dock.h
===================================================================
RCS file: /cvs/gnome/gdl/gdl/gdl-dock.h,v
retrieving revision 1.2
diff -u -r1.2 gdl-dock.h
--- gdl/gdl-dock.h	2001/10/10 13:09:14	1.2
+++ gdl/gdl-dock.h	2001/12/02 08:21:04
@@ -66,4 +66,6 @@
 void           gdl_dock_layout_save       (GdlDock    *dock,
                                            xmlNodePtr  node);
 
+GList         *gdl_dock_get_named_items   (GdlDock    *dock);
+
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]