[Monodevelop-patches-list] r734 - in trunk/MonoDevelop: . gdldock gdldock/gdl gdldock/sources gdldock/sources/gdl gdldock/test

commit-watcher at mono-cvs.ximian.com commit-watcher at mono-cvs.ximian.com
Sat Jan 31 14:16:44 EST 2004


Author: jluke
Date: 2004-01-31 14:16:43 -0500 (Sat, 31 Jan 2004)
New Revision: 734

Added:
   trunk/MonoDevelop/gdldock/
   trunk/MonoDevelop/gdldock/Makefile
   trunk/MonoDevelop/gdldock/gdl/
   trunk/MonoDevelop/gdldock/gdl/DockItemFlags.cs
   trunk/MonoDevelop/gdldock/gdl/DockParamFlags.cs
   trunk/MonoDevelop/gdldock/gdl/Gdl.metadata
   trunk/MonoDevelop/gdldock/gdl/Makefile
   trunk/MonoDevelop/gdldock/gdl/gdl-api.xml
   trunk/MonoDevelop/gdldock/sources/
   trunk/MonoDevelop/gdldock/sources/Makefile
   trunk/MonoDevelop/gdldock/sources/gdl-sharp-sources.xml
   trunk/MonoDevelop/gdldock/sources/gdl/
   trunk/MonoDevelop/gdldock/sources/gdl/Makefile
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.h
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.c
   trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.h
   trunk/MonoDevelop/gdldock/test/
   trunk/MonoDevelop/gdldock/test/GdlDockTest.cs
   trunk/MonoDevelop/gdldock/test/Makefile
Log:
initial gdldock wrapper


Added: trunk/MonoDevelop/gdldock/Makefile
===================================================================
--- trunk/MonoDevelop/gdldock/Makefile	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/Makefile	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,3 @@
+all:
+	cd gdl && make
+	cd sources && make

Added: trunk/MonoDevelop/gdldock/gdl/DockItemFlags.cs
===================================================================
--- trunk/MonoDevelop/gdldock/gdl/DockItemFlags.cs	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/gdl/DockItemFlags.cs	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,16 @@
+// This file was generated by the Gtk# code generator.
+// Any changes made will be lost if regenerated.
+
+namespace Gdl {
+
+	using System;
+
+#region Autogenerated code
+	public enum DockItemFlags {
+
+		InDrag = 1,
+		InPredrag = 2,
+		UserAction = 3,
+	}
+#endregion
+}

Added: trunk/MonoDevelop/gdldock/gdl/DockParamFlags.cs
===================================================================
--- trunk/MonoDevelop/gdldock/gdl/DockParamFlags.cs	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/gdl/DockParamFlags.cs	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,15 @@
+// This file was generated by the Gtk# code generator.
+// Any changes made will be lost if regenerated.
+
+namespace Gdl {
+
+	using System;
+
+#region Autogenerated code
+	public enum DockParamFlags {
+
+		Export = 1,
+		After = 2,
+	}
+#endregion
+}

Added: trunk/MonoDevelop/gdldock/gdl/Gdl.metadata
===================================================================
--- trunk/MonoDevelop/gdldock/gdl/Gdl.metadata	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/gdl/Gdl.metadata	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,6 @@
+<metadata>
+  <attr path="/api/namespace/object[@cname='GdlDockObject']/signal[@name='Detach']" name="name">Detached</attr>
+  <attr path="/api/namespace/object[@cname='GdlDockObject']/signal[@name='Dock']" name="name">Docked</attr>
+  <attr path="/api/namespace/enum[@cname='GdlDockItemFlags']" name="hidden">1</attr>
+  <attr path="/api/namespace/enum[@cname='GdlDockParamFlags']" name="hidden">1</attr>
+</metadata>

Added: trunk/MonoDevelop/gdldock/gdl/Makefile
===================================================================
--- trunk/MonoDevelop/gdldock/gdl/Makefile	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/gdl/Makefile	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,26 @@
+MCS = mcs
+RUNTIME = mono
+ASSEMBLY = ../../build/bin/gdl-sharp.dll
+PREFIX ?= $(shell pkg-config --variable=prefix gapi)
+
+INCLUDE_APIS = \
+	$(PREFIX)/share/gapi/gdk-api.xml \
+	$(PREFIX)/share/gapi/gtk-api.xml \
+	$(PREFIX)/share/gapi/atk-api.xml
+			
+all: generated-stamp $(ASSEMBLY)
+
+generated-stamp: gdl-api.xml
+	gapi-fixup --api=gdl-api.xml --metadata=Gdl.metadata && \
+	gapi-codegen --generate gdl-api.xml --include $(INCLUDE_APIS) --outdir=generated --customdir=. --assembly-name=gdl-sharp && touch generated-stamp
+ 
+$(ASSEMBLY): generated-stamp
+	$(MCS) --unsafe --target library \
+	-r glib-sharp.dll -r gtk-sharp.dll -r gdk-sharp.dll \
+	--recurse '*.cs' -o $(ASSEMBLY)
+ 
+clean:
+	rm -f $(ASSEMBLY)
+	rm -f generated-stamp
+	rm -rf generated
+

Added: trunk/MonoDevelop/gdldock/gdl/gdl-api.xml
===================================================================
--- trunk/MonoDevelop/gdldock/gdl/gdl-api.xml	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/gdl/gdl-api.xml	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,569 @@
+<?xml version="1.0"?>
+<api><!--
+
+        This file was automatically generated.
+        Please DO NOT MODIFY THIS FILE, modify .metadata files instead.
+
+-->
+  <namespace name="Gdl" library="gdl-1">
+    <enum name="DockItemBehavior" cname="GdlDockItemBehavior" type="flags">
+      <member cname="GDL_DOCK_ITEM_BEH_NORMAL" name="Normal" />
+      <member cname="GDL_DOCK_ITEM_BEH_NEVER_FLOATING" name="NeverFloating" value="1 &lt;&lt; 0" />
+      <member cname="GDL_DOCK_ITEM_BEH_NEVER_VERTICAL" name="NeverVertical" value="1 &lt;&lt; 1" />
+      <member cname="GDL_DOCK_ITEM_BEH_NEVER_HORIZONTAL" name="NeverHorizontal" value="1 &lt;&lt; 2" />
+      <member cname="GDL_DOCK_ITEM_BEH_LOCKED" name="Locked" value="1 &lt;&lt; 3" />
+      <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_TOP" name="CantDockTop" value="1 &lt;&lt; 4" />
+      <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_BOTTOM" name="CantDockBottom" value="1 &lt;&lt; 5" />
+      <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_LEFT" name="CantDockLeft" value="1 &lt;&lt; 6" />
+      <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_RIGHT" name="CantDockRight" value="1 &lt;&lt; 7" />
+      <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_CENTER" name="CantDockCenter" value="1 &lt;&lt; 8" />
+    </enum>
+    <enum name="DockItemFlags" cname="GdlDockItemFlags" type="enum" hidden="1">
+      <member cname="GDL_DOCK_IN_DRAG" name="InDrag" value="1 &lt;&lt; GDL_DOCK_OBJECT_FLAGS_SHIFT" />
+      <member cname="GDL_DOCK_IN_PREDRAG" name="InPredrag" value="1 &lt;&lt; (GDL_DOCK_OBJECT_FLAGS_SHIFT + 1)" />
+      <member cname="GDL_DOCK_USER_ACTION" name="UserAction" value="1 &lt;&lt; (GDL_DOCK_OBJECT_FLAGS_SHIFT + 2)" />
+    </enum>
+    <enum name="DockObjectFlags" cname="GdlDockObjectFlags" type="flags">
+      <member cname="GDL_DOCK_AUTOMATIC" name="Automatic" value="1 &lt;&lt; 0" />
+      <member cname="GDL_DOCK_ATTACHED" name="Attached" value="1 &lt;&lt; 1" />
+      <member cname="GDL_DOCK_IN_REFLOW" name="InReflow" value="1 &lt;&lt; 2" />
+      <member cname="GDL_DOCK_IN_DETACH" name="InDetach" value="1 &lt;&lt; 3" />
+    </enum>
+    <enum name="DockParamFlags" cname="GdlDockParamFlags" type="enum" hidden="1">
+      <member cname="GDL_DOCK_PARAM_EXPORT" name="Export" value="1 &lt;&lt; G_PARAM_USER_SHIFT" />
+      <member cname="GDL_DOCK_PARAM_AFTER" name="After" value="1 &lt;&lt; (G_PARAM_USER_SHIFT + 1)" />
+    </enum>
+    <enum name="DockPlacement" cname="GdlDockPlacement" type="enum">
+      <member cname="GDL_DOCK_NONE" name="None" />
+      <member cname="GDL_DOCK_TOP" name="Top" />
+      <member cname="GDL_DOCK_BOTTOM" name="Bottom" />
+      <member cname="GDL_DOCK_RIGHT" name="Right" />
+      <member cname="GDL_DOCK_LEFT" name="Left" />
+      <member cname="GDL_DOCK_CENTER" name="Center" />
+      <member cname="GDL_DOCK_FLOATING" name="Floating" />
+    </enum>
+    <object name="Dock" cname="GdlDock" parent="GdlDockObject">
+      <field cname="root" type="GdlDockObject*" />
+      <field cname="_priv" type="GdlDockPrivate*" />
+      <property name="Floating" cname="floating" type="gboolean" readable="true" writeable="true" construct-only="true" />
+      <property name="DefaultTitle" cname="default_title" type="gchar*" readable="true" writeable="true" />
+      <property name="Width" cname="width" type="gint" readable="true" writeable="true" construct-only="true" />
+      <property name="Height" cname="height" type="gint" readable="true" writeable="true" construct-only="true" />
+      <property name="Floatx" cname="floatx" type="gint" readable="true" writeable="true" construct-only="true" />
+      <property name="Floaty" cname="floaty" type="gint" readable="true" writeable="true" construct-only="true" />
+      <signal name="LayoutChanged" cname="layout_changed" when="LAST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDock*" name="dock" />
+        </parameters>
+      </signal>
+      <method name="AddFloatingItem" cname="gdl_dock_add_floating_item">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+          <parameter type="gint" name="x" />
+          <parameter type="gint" name="y" />
+          <parameter type="gint" name="width" />
+          <parameter type="gint" name="height" />
+        </parameters>
+      </method>
+      <method name="AddItem" cname="gdl_dock_add_item">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+          <parameter type="GdlDockPlacement" name="place" />
+        </parameters>
+      </method>
+      <method name="GetItemByName" cname="gdl_dock_get_item_by_name">
+        <return-type type="GdlDockItem*" />
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+        </parameters>
+      </method>
+      <method name="GetNamedItems" cname="gdl_dock_get_named_items">
+        <return-type type="GList*" />
+      </method>
+      <method name="GetPlaceholderByName" cname="gdl_dock_get_placeholder_by_name">
+        <return-type type="GdlDockPlaceholder*" />
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+        </parameters>
+      </method>
+      <method name="GetType" cname="gdl_dock_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_new" />
+      <constructor cname="gdl_dock_new_from">
+        <parameters>
+          <parameter type="GdlDock*" name="original" />
+          <parameter type="gboolean" name="floating" />
+        </parameters>
+      </constructor>
+      <method name="ParamGetType" cname="gdl_dock_param_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="XorRect" cname="gdl_dock_xor_rect">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdkRectangle*" name="rect" />
+        </parameters>
+      </method>
+    </object>
+    <object name="DockItem" cname="GdlDockItem" parent="GdlDockObject">
+      <field cname="child" type="GtkWidget*" />
+      <field cname="behavior" type="GdlDockItemBehavior" />
+      <field cname="orientation" type="GtkOrientation" />
+      <field cname="resize" bits="1" type="guint" />
+      <field cname="dragoff_x" type="gint" />
+      <field cname="dragoff_y" type="gint" />
+      <field cname="fromoutside* /GdlDockItemPrivate* _priv" type="accesible" />
+      <property name="Orientation" cname="orientation" type="GtkOrientation" readable="true" writeable="true" construct-only="true" />
+      <property name="Resize" cname="resize" type="gboolean" readable="true" writeable="true" />
+      <property name="Behavior" cname="behavior" type="GdlDockItemBehavior" readable="true" writeable="true" />
+      <property name="GripSize" cname="grip_size" type="guint" readable="true" writeable="true" />
+      <property name="Locked" cname="locked" type="gboolean" readable="true" writeable="true" />
+      <property name="PreferredWidth" cname="preferred_width" type="gint" readable="true" writeable="true" />
+      <property name="PreferredHeight" cname="preferred_height" type="gint" readable="true" writeable="true" />
+      <signal name="DockDragBegin" cname="dock_drag_begin" when="FIRST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+        </parameters>
+      </signal>
+      <signal name="DockDragMotion" cname="dock_drag_motion" when="FIRST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+          <parameter type="gint" name="x" />
+          <parameter type="gint" name="y" />
+        </parameters>
+      </signal>
+      <signal name="DockDragEnd" cname="dock_drag_end" when="FIRST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+          <parameter type="gboolean" name="cancelled" />
+        </parameters>
+      </signal>
+      <method name="Bind" cname="gdl_dock_item_bind">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GtkWidget*" name="dock" />
+        </parameters>
+      </method>
+      <method name="DockTo" cname="gdl_dock_item_dock_to">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockItem*" name="target" />
+          <parameter type="GdlDockPlacement" name="position" />
+          <parameter type="gint" name="docking_param" />
+        </parameters>
+      </method>
+      <method name="GetTablabel" cname="gdl_dock_item_get_tablabel">
+        <return-type type="GtkWidget*" />
+      </method>
+      <method name="GetType" cname="gdl_dock_item_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="HideGrip" cname="gdl_dock_item_hide_grip">
+        <return-type type="void" />
+      </method>
+      <method name="HideItem" cname="gdl_dock_item_hide_item">
+        <return-type type="void" />
+      </method>
+      <method name="Lock" cname="gdl_dock_item_lock">
+        <return-type type="void" />
+      </method>
+      <constructor cname="gdl_dock_item_new">
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+          <parameter type="const-gchar*" name="long_name" />
+          <parameter type="GdlDockItemBehavior" name="behavior" />
+        </parameters>
+      </constructor>
+      <method name="PreferredSize" cname="gdl_dock_item_preferred_size">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GtkRequisition*" name="req" />
+        </parameters>
+      </method>
+      <method name="SetDefaultPosition" cname="gdl_dock_item_set_default_position">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="reference" />
+        </parameters>
+      </method>
+      <method name="SetOrientation" cname="gdl_dock_item_set_orientation">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GtkOrientation" name="orientation" />
+        </parameters>
+      </method>
+      <method name="SetTablabel" cname="gdl_dock_item_set_tablabel">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GtkWidget*" name="tablabel" />
+        </parameters>
+      </method>
+      <method name="ShowGrip" cname="gdl_dock_item_show_grip">
+        <return-type type="void" />
+      </method>
+      <method name="ShowItem" cname="gdl_dock_item_show_item">
+        <return-type type="void" />
+      </method>
+      <method name="Unbind" cname="gdl_dock_item_unbind">
+        <return-type type="void" />
+      </method>
+      <method name="Unlock" cname="gdl_dock_item_unlock">
+        <return-type type="void" />
+      </method>
+    </object>
+    <object name="DockItemGrip" cname="GdlDockItemGrip" parent="GtkWidget">
+      <field cname="item" type="GdlDockItem*" />
+      <signal name="Activate" cname="activate" when="LAST">
+        <return-type type="GCclosureMarshalVoid_Void" />
+      </signal>
+      <method name="GetType" cname="gdl_dock_item_grip_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_item_grip_new">
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+        </parameters>
+      </constructor>
+    </object>
+    <object name="DockLayout" cname="GdlDockLayout" parent="GObject">
+      <field cname="dirty" type="gboolean" />
+      <field cname="master" type="GdlDockMaster*" />
+      <field cname="_priv" type="GdlDockLayoutPrivate*" />
+      <property name="Master" cname="master" type="GdlDockMaster" readable="true" writeable="true" />
+      <property name="Dirty" cname="dirty" type="gboolean" readable="true" />
+      <method name="Attach" cname="gdl_dock_layout_attach">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockMaster*" name="master" />
+        </parameters>
+      </method>
+      <method name="DeleteLayout" cname="gdl_dock_layout_delete_layout">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+        </parameters>
+      </method>
+      <method name="GetItemsUi" cname="gdl_dock_layout_get_items_ui">
+        <return-type type="GtkWidget*" />
+      </method>
+      <method name="GetLayouts" cname="gdl_dock_layout_get_layouts">
+        <return-type type="GList*" />
+        <parameters>
+          <parameter type="gboolean" name="include_default" />
+        </parameters>
+      </method>
+      <method name="GetLayoutsUi" cname="gdl_dock_layout_get_layouts_ui">
+        <return-type type="GtkWidget*" />
+      </method>
+      <method name="GetType" cname="gdl_dock_layout_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="GetUi" cname="gdl_dock_layout_get_ui">
+        <return-type type="GtkWidget*" />
+      </method>
+      <method name="IsDirty" cname="gdl_dock_layout_is_dirty">
+        <return-type type="gboolean" />
+      </method>
+      <method name="LoadFromFile" cname="gdl_dock_layout_load_from_file">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="const-gchar*" name="filename" />
+        </parameters>
+      </method>
+      <method name="LoadLayout" cname="gdl_dock_layout_load_layout">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+        </parameters>
+      </method>
+      <constructor cname="gdl_dock_layout_new">
+        <parameters>
+          <parameter type="GdlDock*" name="dock" />
+        </parameters>
+      </constructor>
+      <method name="RunManager" cname="gdl_dock_layout_run_manager">
+        <return-type type="void" />
+      </method>
+      <method name="SaveLayout" cname="gdl_dock_layout_save_layout">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+        </parameters>
+      </method>
+      <method name="SaveToFile" cname="gdl_dock_layout_save_to_file">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="const-gchar*" name="filename" />
+        </parameters>
+      </method>
+    </object>
+    <object name="DockMaster" cname="GdlDockMaster" parent="GObject">
+      <field cname="dock_objects" type="GHashTable*" />
+      <field cname="toplevel_docks" type="GList*" />
+      <field cname="controller" type="GdlDockObject*" />
+      <field cname="dock_number" type="gint" />
+      <field cname="_priv" type="GdlDockMasterPrivate*" />
+      <property name="DefaultTitle" cname="default_title" type="gchar*" readable="true" writeable="true" />
+      <property name="Locked" cname="locked" type="gint" readable="true" writeable="true" />
+      <signal name="LayoutChanged" cname="layout_changed" when="LAST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockMaster*" name="master" />
+        </parameters>
+      </signal>
+      <method name="Add" cname="gdl_dock_master_add">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="object" />
+        </parameters>
+      </method>
+      <method name="Foreach" cname="gdl_dock_master_foreach">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GFunc" name="function" />
+          <parameter type="gpointer" name="user_data" />
+        </parameters>
+      </method>
+      <method name="ForeachToplevel" cname="gdl_dock_master_foreach_toplevel">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="gboolean" name="include_controller" />
+          <parameter type="GFunc" name="function" />
+          <parameter type="gpointer" name="user_data" />
+        </parameters>
+      </method>
+      <method name="GetController" cname="gdl_dock_master_get_controller">
+        <return-type type="GdlDockObject*" />
+      </method>
+      <method name="GetObject" cname="gdl_dock_master_get_object">
+        <return-type type="GdlDockObject*" />
+        <parameters>
+          <parameter type="const-gchar*" name="nick_name" />
+        </parameters>
+      </method>
+      <method name="GetType" cname="gdl_dock_master_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="Remove" cname="gdl_dock_master_remove">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="object" />
+        </parameters>
+      </method>
+      <method name="SetController" cname="gdl_dock_master_set_controller">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="new_controller" />
+        </parameters>
+      </method>
+    </object>
+    <object name="DockNotebook" cname="GdlDockNotebook" parent="GdlDockItem">
+      <property name="Page" cname="page" type="gint" readable="true" writeable="true" />
+      <method name="GetType" cname="gdl_dock_notebook_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_notebook_new" />
+    </object>
+    <object name="DockObject" cname="GdlDockObject" parent="GtkContainer">
+      <field cname="flags" type="GdlDockObjectFlags" />
+      <field cname="freeze_count" type="gint" />
+      <field cname="master" type="GObject*" />
+      <field cname="name" type="gchar*" />
+      <field cname="long_name" type="gchar*" />
+      <field cname="reduce_pending" type="gboolean" />
+      <property name="Name" cname="name" type="gchar*" readable="true" writeable="true" construct-only="true" />
+      <property name="LongName" cname="long_name" type="gchar*" readable="true" writeable="true" />
+      <property name="Master" cname="master" type="GdlDockMaster" readable="true" writeable="true" construct-only="true" />
+      <signal cname="detach" when="LAST" name="Detached">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="object" />
+          <parameter type="gboolean" name="recursive" />
+        </parameters>
+      </signal>
+      <signal cname="dock" when="FIRST" name="Docked">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="object" />
+          <parameter type="GdlDockObject*" name="requestor" />
+          <parameter type="GdlDockPlacement" name="position" />
+          <parameter type="GValue*" name="other_data" />
+        </parameters>
+      </signal>
+      <method name="Bind" cname="gdl_dock_object_bind">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GObject*" name="master" />
+        </parameters>
+      </method>
+      <method name="ChildPlacement" cname="gdl_dock_object_child_placement">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="child" />
+          <parameter type="GdlDockPlacement*" name="placement" />
+        </parameters>
+      </method>
+      <method name="Detach" cname="gdl_dock_object_detach">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="gboolean" name="recursive" />
+        </parameters>
+      </method>
+      <method name="Dock" cname="gdl_dock_object_dock">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="requestor" />
+          <parameter type="GdlDockPlacement" name="position" />
+          <parameter type="GValue*" name="other_data" />
+        </parameters>
+      </method>
+      <method name="DockRequest" cname="gdl_dock_object_dock_request">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="gint" name="x" />
+          <parameter type="gint" name="y" />
+          <parameter type="GdlDockRequest*" name="request" />
+        </parameters>
+      </method>
+      <method name="Freeze" cname="gdl_dock_object_freeze">
+        <return-type type="void" />
+      </method>
+      <method name="GetParentObject" cname="gdl_dock_object_get_parent_object">
+        <return-type type="GdlDockObject*" />
+      </method>
+      <method name="GetToplevel" cname="gdl_dock_object_get_toplevel">
+        <return-type type="GdlDock*" />
+      </method>
+      <method name="GetType" cname="gdl_dock_object_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="IsBound" cname="gdl_dock_object_is_bound">
+        <return-type type="gboolean" />
+      </method>
+      <method name="IsCompound" cname="gdl_dock_object_is_compound">
+        <return-type type="gboolean" />
+      </method>
+      <method name="NickFromType" cname="gdl_dock_object_nick_from_type" shared="true">
+        <return-type type="const-gchar*" />
+        <parameters>
+          <parameter type="GType" name="type" />
+        </parameters>
+      </method>
+      <method name="Present" cname="gdl_dock_object_present">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="child" />
+        </parameters>
+      </method>
+      <method name="Reduce" cname="gdl_dock_object_reduce">
+        <return-type type="void" />
+      </method>
+      <method name="Reorder" cname="gdl_dock_object_reorder">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="child" />
+          <parameter type="GdlDockPlacement" name="new_position" />
+          <parameter type="GValue*" name="other_data" />
+        </parameters>
+      </method>
+      <method name="SetTypeForNick" cname="gdl_dock_object_set_type_for_nick" shared="true">
+        <return-type type="GType" />
+        <parameters>
+          <parameter type="const-gchar*" name="nick" />
+          <parameter type="GType" name="type" />
+        </parameters>
+      </method>
+      <method name="Thaw" cname="gdl_dock_object_thaw">
+        <return-type type="void" />
+      </method>
+      <method name="TypeFromNick" cname="gdl_dock_object_type_from_nick" shared="true">
+        <return-type type="GType" />
+        <parameters>
+          <parameter type="const-gchar*" name="nick" />
+        </parameters>
+      </method>
+      <method name="Unbind" cname="gdl_dock_object_unbind">
+        <return-type type="void" />
+      </method>
+    </object>
+    <object name="DockPaned" cname="GdlDockPaned" parent="GdlDockItem">
+      <field cname="position_changed" type="gboolean" />
+      <property name="Position" cname="position" type="guint" readable="true" writeable="true" />
+      <method name="GetType" cname="gdl_dock_paned_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_paned_new">
+        <parameters>
+          <parameter type="GtkOrientation" name="orientation" />
+        </parameters>
+      </constructor>
+    </object>
+    <object name="DockPlaceholder" cname="GdlDockPlaceholder" parent="GdlDockObject">
+      <field cname="_priv" type="GdlDockPlaceholderPrivate*" />
+      <property name="Sticky" cname="sticky" type="gboolean" readable="true" writeable="true" construct-only="true" />
+      <property name="Host" cname="host" type="GdlDockObject" readable="true" writeable="true" />
+      <property name="NextPlacement" cname="next_placement" type="GdlDockPlacement" readable="true" writeable="true" />
+      <method name="Attach" cname="gdl_dock_placeholder_attach">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockObject*" name="object" />
+        </parameters>
+      </method>
+      <method name="GetType" cname="gdl_dock_placeholder_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_placeholder_new">
+        <parameters>
+          <parameter type="gchar*" name="name" />
+          <parameter type="GdlDockObject*" name="object" />
+          <parameter type="GdlDockPlacement" name="position" />
+          <parameter type="gboolean" name="sticky" />
+        </parameters>
+      </constructor>
+    </object>
+    <object name="DockTablabel" cname="GdlDockTablabel" parent="GtkBin">
+      <field cname="drag_handle_size" type="guint" />
+      <field cname="item" type="GtkWidget*" />
+      <field cname="event_window" type="GdkWindow*" />
+      <field cname="active" type="gboolean" />
+      <field cname="drag_start_event" type="GdkEventButton" />
+      <field cname="pre_drag" type="gboolean" />
+      <property name="Item" cname="item" type="GdlDockItem" readable="true" writeable="true" />
+      <signal name="ButtonPressedHandle" cname="button_pressed_handle" when="LAST">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GdlDockTablabel*" name="tablabel" />
+          <parameter type="GdkEventButton*" name="event" />
+        </parameters>
+      </signal>
+      <method name="Activate" cname="gdl_dock_tablabel_activate">
+        <return-type type="void" />
+      </method>
+      <method name="Deactivate" cname="gdl_dock_tablabel_deactivate">
+        <return-type type="void" />
+      </method>
+      <method name="GetType" cname="gdl_dock_tablabel_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <constructor cname="gdl_dock_tablabel_new">
+        <parameters>
+          <parameter type="GdlDockItem*" name="item" />
+        </parameters>
+      </constructor>
+    </object>
+    <struct name="DockRequest" cname="GdlDockRequest">
+      <field cname="applicant" type="GdlDockObject*" />
+      <field cname="target" type="GdlDockObject*" />
+      <field cname="position" type="GdlDockPlacement" />
+      <field cname="rect" type="GdkRectangle" />
+      <field cname="extra" type="GValue" />
+    </struct>
+  </namespace>
+</api>
\ No newline at end of file

Added: trunk/MonoDevelop/gdldock/sources/Makefile
===================================================================
--- trunk/MonoDevelop/gdldock/sources/Makefile	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/Makefile	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,5 @@
+all:
+
+api: gdl/*.h
+	gapi-parser gdl-sharp-sources.xml
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/Makefile
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/Makefile	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/Makefile	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,38 @@
+INCLUDES = \
+	-DG_LOG_DOMAIN=\"Gdl\"				\
+	-I$(includedir) -I$(top_srcdir)			\
+	$(WARN_CFLAGS) $(DEPRECATED_FLAGS)		\
+	$(GDL_DEPENDENCIES_CFLAGS) $(XML_CFLAGS)
+
+lib_LTLIBRARIES = libgdl-1.la
+
+libgdl_headers = \
+	gdl.h \
+	gdl-dock-object.h \
+	gdl-dock-master.h \
+	gdl-dock.h \
+	gdl-dock-item.h \
+	gdl-dock-item-grip.h \
+	gdl-dock-notebook.h \
+	gdl-dock-paned.h \
+	gdl-dock-tablabel.h \
+	gdl-dock-layout.h \
+	gdl-dock-placeholder.h \
+
+libgdl_1_la_SOURCES = \
+	$(libgdl_headers) \
+	gdl-dock-object.c \
+	gdl-dock-master.c \
+	gdl-dock.c \
+	gdl-dock-item.c \
+	gdl-dock-item-grip.c \
+	gdl-dock-notebook.c \
+	gdl-dock-paned.c \
+	gdl-dock-tablabel.c \
+	gdl-dock-layout.c \
+	gdl-dock-placeholder.c \
+
+libgdl_1_la_LIBADD = \
+	$(GDL_DEPENDENCIES_LIBS) \
+	$(XML_LIBS)
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,362 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
+/**
+ * gdl-dock-item-grip.c
+ *
+ * Based on bonobo-dock-item-grip.  Original copyright notice follows.
+ *
+ * Author:
+ *    Michael Meeks
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <string.h>
+#include <glib-object.h>
+#include <atk/atkstateset.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkaccessible.h>
+#include <gtk/gtkbindings.h>
+#include <libgnome/gnome-macros.h>
+#include "gdl-dock-item.h"
+#include "gdl-dock-item-grip.h"
+#include "gdl-dock.h"
+#include "gdl-tools.h"
+
+#define A11Y_UNFINISHED
+
+enum {
+    ACTIVATE,
+    LAST_SIGNAL
+};
+static guint signals [LAST_SIGNAL];
+
+GNOME_CLASS_BOILERPLATE (GdlDockItemGrip, gdl_dock_item_grip,
+			 GtkWidget, GTK_TYPE_WIDGET);
+
+static gint
+gdl_dock_item_grip_expose (GtkWidget      *widget,
+			   GdkEventExpose *event)
+{
+    GdkRectangle *clip = &event->area;
+    GdkRectangle *rect = &widget->allocation;
+    GdlDockItemGrip *grip = (GdlDockItemGrip *) widget;
+    GtkShadowType shadow = GTK_SHADOW_OUT;
+
+    gtk_paint_handle (widget->style,
+                      widget->window,
+                      GTK_WIDGET_STATE (widget),
+                      shadow,
+                      clip, widget, "dockitem",
+                      rect->x, rect->y, rect->width, rect->height, 
+                      grip->item->orientation);
+
+    if (GTK_WIDGET_HAS_FOCUS (widget)) {
+        gint focus_width;
+        gint focus_pad;
+        GdkRectangle focus;
+		
+        gtk_widget_style_get (GTK_WIDGET (widget),
+                              "focus-line-width", &focus_width,
+                              "focus-padding", &focus_pad,
+                              NULL); 
+		
+        focus = *rect;
+        focus.x += widget->style->xthickness + focus_pad;
+        focus.y += widget->style->ythickness + focus_pad;
+        focus.width -= 2 * (widget->style->xthickness + focus_pad);
+        focus.height -= 2 * (widget->style->xthickness + focus_pad);
+		
+        gtk_paint_focus (widget->style, widget->window,
+                         GTK_WIDGET_STATE (widget),
+                         clip, widget, "dockitem",
+                         focus.x, focus.y,
+                         focus.width, focus.height);
+    }
+
+    return FALSE;
+}
+
+
+#ifndef A11Y_UNFINISHED
+
+static AtkObjectClass *a11y_parent_class = NULL;
+
+static void
+grip_item_a11y_initialize (AtkObject *accessible, gpointer widget)
+{
+    accessible->role = ATK_ROLE_SEPARATOR;
+    atk_object_set_name (accessible, "grip");
+
+    a11y_parent_class->initialize (accessible, widget);
+}
+
+static AtkStateSet*
+grip_item_a11y_ref_state_set (AtkObject *accessible)
+{
+    AtkStateSet *state_set;
+    GdlDockItemGrip *grip;
+
+    state_set = a11y_parent_class->ref_state_set (accessible);
+    grip = GDL_DOCK_ITEM_GRIP (
+        GTK_ACCESSIBLE (accessible)->widget);
+
+    if (grip == NULL)
+        return state_set;
+
+    if (grip->item->orientation == GTK_ORIENTATION_VERTICAL) {
+        atk_state_set_add_state (state_set, ATK_STATE_VERTICAL);
+        atk_state_set_remove_state (state_set, ATK_STATE_HORIZONTAL);
+    } else {
+        atk_state_set_add_state (state_set, ATK_STATE_HORIZONTAL);
+        atk_state_set_remove_state (state_set, ATK_STATE_VERTICAL);
+    }
+
+    return state_set;
+}
+
+static GdlDock *
+get_dock (GtkWidget *widget)
+{
+    while (widget && !GDL_IS_DOCK (widget))
+        widget = widget->parent;
+
+    return (GdlDock *) widget;
+}
+
+static void
+gdl_dock_item_grip_dock (GdlDockItemGrip *grip)
+{
+    GdlDock *dock;
+
+    g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (grip));
+
+    dock = get_dock (GTK_WIDGET (grip->item));
+    g_return_if_fail (dock != NULL);
+
+    gdl_dock_item_unfloat (grip->item);
+		
+    g_object_ref (G_OBJECT (grip->item));
+    gtk_container_remove (
+        GTK_CONTAINER (
+            GTK_WIDGET (grip->item)->parent),
+        GTK_WIDGET (grip->item));
+    gdl_dock_add_item (
+        dock, grip->item,
+        BONOBO_DOCK_TOP, 2, 0, 0, TRUE);
+    g_object_unref (G_OBJECT (grip->item));
+}
+
+static void
+gdl_dock_item_grip_undock (GdlDockItemGrip *grip)
+{
+    guint x, y;
+
+    g_return_if_fail (BONOBO_IS_DOCK_ITEM_GRIP (grip));
+
+    if (grip->item->is_floating)
+        return;
+
+    gdk_window_get_position (
+        GTK_WIDGET (grip)->window, &x, &y);
+
+    gdl_dock_item_detach (grip->item, x, y);
+}
+
+enum {
+    ACTION_DOCK,
+    ACTION_UNDOCK,
+    ACTION_LAST
+};
+
+static gboolean
+gdl_dock_item_grip_do_action (AtkAction *action,
+			      gint       i)
+{
+    GdlDockItemGrip *grip;
+
+    grip = GDL_DOCK_ITEM_GRIP (
+        GTK_ACCESSIBLE (action)->widget);
+
+    if (grip->item->behavior & GDL_DOCK_ITEM_BEH_LOCKED)
+        return FALSE;
+
+    switch (i) {
+    case ACTION_DOCK:
+        gdl_dock_item_grip_dock (grip);
+        break;
+    case ACTION_UNDOCK:
+        gdl_dock_item_grip_undock (grip);
+        break;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+static gint
+gdl_dock_item_grip_get_n_actions (AtkAction *action)
+{
+    GdlDockItemGrip *grip;
+
+    grip = GDL_DOCK_ITEM_GRIP (
+        GTK_ACCESSIBLE (action)->widget);
+
+    if (grip->item->behavior & GDL_DOCK_ITEM_BEH_LOCKED)
+        return 0;
+    else
+        return ACTION_LAST;
+}
+
+static void
+grip_item_a11y_class_init (AtkObjectClass *klass)
+{
+    a11y_parent_class = g_type_class_peek_parent (klass);
+
+    klass->initialize = grip_item_a11y_initialize;
+    klass->ref_state_set = grip_item_a11y_ref_state_set;
+}
+
+#endif /* A11Y_UNFINISHED */
+
+
+static AtkObject *
+gdl_dock_item_grip_get_accessible (GtkWidget *widget)
+{
+#ifndef A11Y_UNFINISHED
+    AtkObject *accessible;
+    static GType a11y_type = 0;
+
+    if (!a11y_type) {
+        AtkActionIface action_if;
+
+        a11y_type = bonobo_a11y_get_derived_type_for (
+            GDL_TYPE_DOCK_ITEM_GRIP,
+            NULL, grip_item_a11y_class_init);
+
+        memset (&action_if, 0, sizeof (AtkActionIface));
+        action_if.do_action = gdl_dock_item_grip_do_action;
+        action_if.get_n_actions = gdl_dock_item_grip_get_n_actions;
+
+        bonobo_a11y_add_actions_interface (
+            a11y_type, &action_if,
+            ACTION_DOCK,   "dock",   _("Dock the toolbar"),    "<Enter>",
+            ACTION_UNDOCK, "undock", _("Un dock the toolbar"), "<Enter>",
+            -1);
+    }
+
+    if ((accessible = bonobo_a11y_get_atk_object (widget)))
+        return accessible;
+
+    return bonobo_a11y_set_atk_object_ret (
+        widget, g_object_new (a11y_type, NULL));
+#else /* !A11Y_UNFINISHED */
+    return NULL;
+#endif /* A11Y_UNFINISHED */
+}
+
+static void
+gdl_dock_item_grip_activate (GdlDockItemGrip *grip)
+{
+#ifndef A11Y_UNFINISHED
+    if (grip->item->is_floating)
+        gdl_dock_item_grip_dock (grip);
+    else
+        gdl_dock_item_grip_undock (grip);
+#endif /* A11Y_UNFINISHED */
+}
+
+static void
+gdl_dock_item_grip_dispose (GObject *object)
+{
+    GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+}
+
+static void
+gdl_dock_item_grip_instance_init (GdlDockItemGrip *grip)
+{
+    GTK_WIDGET_SET_FLAGS (grip, GTK_CAN_FOCUS);
+    GTK_WIDGET_SET_FLAGS (grip, GTK_NO_WINDOW);
+}
+
+#ifndef A11Y_UNFINISHED
+static BonoboDockBand *
+get_dock_band (GtkWidget *widget)
+{
+    while (widget && !BONOBO_IS_DOCK_BAND (widget))
+        widget = widget->parent;
+
+    return (BonoboDockBand *) widget;
+}
+#endif /* A11Y_UNFINISHED */
+
+static gint
+gdl_dock_item_grip_key_press_event (GtkWidget   *widget,
+                                    GdkEventKey *event)
+{
+#ifndef A11Y_UNFINISHED
+    gboolean had_focus = GTK_WIDGET_HAS_FOCUS (widget);
+    BonoboDockBand *band = get_dock_band (widget);
+    BonoboDockItemGrip *grip = (BonoboDockItemGrip *) widget;
+
+    if (!grip->item->is_floating && band &&
+        bonobo_dock_band_handle_key_nav (band, grip->item, event))
+    {
+        if (had_focus && !GTK_WIDGET_HAS_FOCUS (widget))
+            gtk_widget_grab_focus (widget);
+        return TRUE;
+    }
+#endif /* A11Y_UNFINISHED */
+
+    return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+}
+
+static void
+gdl_dock_item_grip_class_init (GdlDockItemGripClass *klass)
+{
+    GtkBindingSet  *binding_set;
+    GObjectClass   *gobject_class = (GObjectClass *) klass;
+    GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    gobject_class->dispose = gdl_dock_item_grip_dispose;
+
+    widget_class->expose_event = gdl_dock_item_grip_expose;
+    widget_class->get_accessible = gdl_dock_item_grip_get_accessible;
+    widget_class->key_press_event = gdl_dock_item_grip_key_press_event;
+
+    klass->activate = gdl_dock_item_grip_activate;
+
+    binding_set = gtk_binding_set_by_class (klass);
+
+    signals [ACTIVATE] =
+        g_signal_new ("activate",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                      G_STRUCT_OFFSET (
+                          GdlDockItemGripClass, activate),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+    widget_class->activate_signal = signals [ACTIVATE];
+
+    gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
+                                  "activate", 0);
+    gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
+                                  "activate", 0);
+}
+
+GtkWidget *
+gdl_dock_item_grip_new (GdlDockItem *item)
+{
+    GdlDockItemGrip *grip = g_object_new (GDL_TYPE_DOCK_ITEM_GRIP, NULL);
+
+    grip->item = item;
+
+    return GTK_WIDGET (grip);
+}

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item-grip.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,50 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
+/**
+ * gdl-dock-item-grip.h
+ * 
+ * Based on bonobo-dock-item-grip.  Original copyright notice follows.
+ *
+ * Author:
+ *    Michael Meeks
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ */
+
+#ifndef _GDL_DOCK_ITEM_GRIP_H_
+#define _GDL_DOCK_ITEM_GRIP_H_
+
+#include <gtk/gtkwidget.h>
+#include <gdl/gdl-dock-item.h>
+
+G_BEGIN_DECLS
+
+#define GDL_TYPE_DOCK_ITEM_GRIP            (gdl_dock_item_grip_get_type())
+#define GDL_DOCK_ITEM_GRIP(obj)            \
+    (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_ITEM_GRIP, GdlDockItemGrip))
+#define GDL_DOCK_ITEM_GRIP_CLASS(klass)    \
+    (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_ITEM_GRIP, GdlDockItemGripClass))
+#define GDL_IS_DOCK_ITEM_GRIP(obj)         \
+    (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_ITEM_GRIP))
+#define GDL_IS_DOCK_ITEM_GRIP_CLASS(klass) \
+    (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_ITEM_GRIP))
+#define GDL_DOCK_ITEM_GRIP_GET_CLASS(obj)  \
+    (GTK_CHECK_GET_CLASS ((obj), GDL_TYPE_DOCK_ITEM_GRIP, GdlDockItemGripClass))
+
+typedef struct {
+    GtkWidget parent;
+	
+    GdlDockItem *item;
+} GdlDockItemGrip;
+
+typedef struct {
+    GtkWidgetClass parent_class;
+
+    void (*activate) (GdlDockItemGrip *grip);
+} GdlDockItemGripClass;
+
+GType      gdl_dock_item_grip_get_type (void);
+GtkWidget *gdl_dock_item_grip_new      (GdlDockItem *item);
+
+G_END_DECLS
+
+#endif /* _GDL_DOCK_ITEM_GRIP_H_ */

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,1663 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-item.c
+ *
+ * Author: Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * Based on GnomeDockItem/BonoboDockItem.  Original copyright notice follows.
+ *
+ * Copyright (C) 1998 Ettore Perazzoli
+ * Copyright (C) 1998 Elliot Lee
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <string.h>
+#include <libgnome/gnome-macros.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock.h"
+#include "gdl-dock-item.h"
+#include "gdl-dock-item-grip.h"
+#include "gdl-dock-notebook.h"
+#include "gdl-dock-paned.h"
+#include "gdl-dock-tablabel.h"
+#include "gdl-dock-placeholder.h"
+#include "libgdltypebuiltins.h"
+#include "libgdlmarshal.h"
+
+
+/* ----- Private prototypes ----- */
+
+static void  gdl_dock_item_class_init    (GdlDockItemClass *class);
+static void  gdl_dock_item_instance_init (GdlDockItem *item);
+
+static GObject *gdl_dock_item_constructor (GType                  type,
+                                           guint                  n_construct_properties,
+                                           GObjectConstructParam *construct_param);
+
+static void  gdl_dock_item_set_property  (GObject      *object,
+                                          guint         prop_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec);
+static void  gdl_dock_item_get_property  (GObject      *object,
+                                          guint         prop_id,
+                                          GValue       *value,
+                                          GParamSpec   *pspec);
+
+static void  gdl_dock_item_destroy       (GtkObject *object);
+
+static void  gdl_dock_item_add           (GtkContainer *container,
+                                          GtkWidget    *widget);
+static void  gdl_dock_item_remove        (GtkContainer *container,
+                                          GtkWidget    *widget);
+static void  gdl_dock_item_forall        (GtkContainer *container,
+                                          gboolean      include_internals,
+                                          GtkCallback   callback,
+                                          gpointer      callback_data);
+static GtkType gdl_dock_item_child_type  (GtkContainer *container);
+
+static void  gdl_dock_item_size_request  (GtkWidget *widget,
+                                          GtkRequisition *requisition);
+static void  gdl_dock_item_size_allocate (GtkWidget *widget,
+                                          GtkAllocation *allocation);
+static void  gdl_dock_item_map           (GtkWidget *widget);
+static void  gdl_dock_item_unmap         (GtkWidget *widget);
+static void  gdl_dock_item_realize       (GtkWidget *widget);
+static void  gdl_dock_item_style_set     (GtkWidget *widget,
+                                          GtkStyle  *previous_style);
+static gint  gdl_dock_item_expose        (GtkWidget *widget,
+                                          GdkEventExpose *event);
+
+static gint  gdl_dock_item_button_changed (GtkWidget *widget,
+                                           GdkEventButton *event);
+static gint  gdl_dock_item_motion         (GtkWidget *widget,
+                                           GdkEventMotion *event);
+static gboolean  gdl_dock_item_key_press  (GtkWidget *widget,
+                                           GdkEventKey *event);
+
+static gboolean gdl_dock_item_dock_request (GdlDockObject    *object,
+                                            gint              x,
+                                            gint              y,
+                                            GdlDockRequest   *request);
+static void     gdl_dock_item_dock         (GdlDockObject    *object,
+                                            GdlDockObject    *requestor,
+                                            GdlDockPlacement  position,
+                                            GValue           *other_data);
+
+static void  gdl_dock_item_popup_menu    (GdlDockItem *item, 
+                                          guint        button,
+                                          guint32      time);
+static void  gdl_dock_item_drag_start    (GdlDockItem *item);
+static void  gdl_dock_item_drag_end      (GdlDockItem *item,
+                                          gboolean     cancel);
+
+static void  gdl_dock_item_tab_button    (GtkWidget      *widget,
+                                          GdkEventButton *event,
+                                          gpointer        data);
+                                          
+static void  gdl_dock_item_hide_cb       (GtkWidget   *widget,
+                                          GdlDockItem *item);
+
+static void  gdl_dock_item_lock_cb       (GtkWidget   *widget,
+                                          GdlDockItem *item);
+
+static void  gdl_dock_item_showhide_grip (GdlDockItem *item);
+
+static void  gdl_dock_item_real_set_orientation (GdlDockItem    *item,
+                                                 GtkOrientation  orientation);
+
+static void gdl_dock_param_export_gtk_orientation (const GValue *src,
+                                                   GValue       *dst);
+static void gdl_dock_param_import_gtk_orientation (const GValue *src,
+                                                   GValue       *dst);
+
+
+
+/* ----- Class variables and definitions ----- */
+
+enum {
+    PROP_0,
+    PROP_ORIENTATION,
+    PROP_RESIZE,
+    PROP_BEHAVIOR,
+    PROP_GRIP_SIZE,
+    PROP_LOCKED,
+    PROP_PREFERRED_WIDTH,
+    PROP_PREFERRED_HEIGHT
+};
+
+enum {
+    DOCK_DRAG_BEGIN,
+    DOCK_DRAG_MOTION,
+    DOCK_DRAG_END,
+    LAST_SIGNAL
+};
+
+static guint gdl_dock_item_signals [LAST_SIGNAL] = { 0 };
+
+#define DEFAULT_GRIP_SIZE  10
+#define GDL_DOCK_ITEM_NOT_LOCKED(item) !((item)->behavior & GDL_DOCK_ITEM_BEH_LOCKED)
+#define GDL_DOCK_ITEM_GRIP_SHOWN(item) \
+    (GDL_DOCK_ITEM_HAS_GRIP (item) && \
+     GDL_DOCK_ITEM_NOT_LOCKED (item) && \
+     (item)->_priv->grip_shown)
+
+
+struct _GdlDockItemPrivate {
+    GtkWidget *menu;
+
+    gboolean   grip_shown;
+    GtkWidget *grip;
+    guint      grip_size;
+    
+    GtkWidget *tab_label;
+
+    gint       preferred_width;
+    gint       preferred_height;
+
+    GdlDockPlaceholder *ph;
+
+    gint       start_x, start_y;
+};
+
+/* FIXME: implement the rest of the behaviors */
+
+#define SPLIT_RATIO  0.4
+
+
+/* ----- Private functions ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockItem, gdl_dock_item, GdlDockObject, GDL_TYPE_DOCK_OBJECT);
+
+static void
+gdl_dock_item_class_init (GdlDockItemClass *klass)
+{
+    GObjectClass       *g_object_class;
+    GtkObjectClass     *gtk_object_class;
+    GtkWidgetClass     *widget_class;
+    GtkContainerClass  *container_class;
+    GdlDockObjectClass *object_class;
+    
+    g_object_class = G_OBJECT_CLASS (klass);
+    gtk_object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    object_class = GDL_DOCK_OBJECT_CLASS (klass);
+
+    g_object_class->constructor = gdl_dock_item_constructor;
+    g_object_class->set_property = gdl_dock_item_set_property;
+    g_object_class->get_property = gdl_dock_item_get_property;
+
+    gtk_object_class->destroy = gdl_dock_item_destroy;
+
+    widget_class->realize = gdl_dock_item_realize;
+    widget_class->map = gdl_dock_item_map;
+    widget_class->unmap = gdl_dock_item_unmap;
+    widget_class->size_request = gdl_dock_item_size_request;
+    widget_class->size_allocate = gdl_dock_item_size_allocate;
+    widget_class->style_set = gdl_dock_item_style_set;
+    widget_class->expose_event = gdl_dock_item_expose;
+    widget_class->button_press_event = gdl_dock_item_button_changed;
+    widget_class->button_release_event = gdl_dock_item_button_changed;
+    widget_class->motion_notify_event = gdl_dock_item_motion;
+    widget_class->key_press_event = gdl_dock_item_key_press;
+    
+    container_class->add = gdl_dock_item_add;
+    container_class->remove = gdl_dock_item_remove;
+    container_class->forall = gdl_dock_item_forall;
+    container_class->child_type = gdl_dock_item_child_type;
+    
+    object_class->is_compound = FALSE;
+
+    object_class->dock_request = gdl_dock_item_dock_request;
+    object_class->dock = gdl_dock_item_dock;
+
+    /* properties */
+
+    g_object_class_install_property (
+        g_object_class, PROP_ORIENTATION,
+        g_param_spec_enum ("orientation", _("Orientation"),
+                           _("Orientation of the docking item"),
+                           GTK_TYPE_ORIENTATION,
+                           GTK_ORIENTATION_HORIZONTAL,
+                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+                           GDL_DOCK_PARAM_EXPORT));
+
+    /* --- register exporter/importer for GTK_ORIENTATION */
+    g_value_register_transform_func (GTK_TYPE_ORIENTATION, GDL_TYPE_DOCK_PARAM,
+                                     gdl_dock_param_export_gtk_orientation);
+    g_value_register_transform_func (GDL_TYPE_DOCK_PARAM, GTK_TYPE_ORIENTATION,
+                                     gdl_dock_param_import_gtk_orientation);
+    /* --- end of registration */
+    
+    g_object_class_install_property (
+        g_object_class, PROP_RESIZE,
+        g_param_spec_boolean ("resize", _("Resizable"),
+                              _("If set, the dock item can be resized when "
+                                "docked in a paned"),
+                              TRUE,
+                              G_PARAM_READWRITE));
+                                     
+    g_object_class_install_property (
+        g_object_class, PROP_BEHAVIOR,
+        g_param_spec_flags ("behavior", _("Item behavior"),
+                            _("General behavior for the dock item (i.e. "
+                              "whether it can float, if it's locked, etc.)"),
+                            GDL_TYPE_DOCK_ITEM_BEHAVIOR,
+                            GDL_DOCK_ITEM_BEH_NORMAL,
+                            G_PARAM_READWRITE));
+                                     
+    g_object_class_install_property (
+        g_object_class, PROP_GRIP_SIZE,
+        g_param_spec_uint ("grip_size", _("Grip size"),
+                           _("Size in pixels of the grip to drag the dock item"),
+                           0, 100, DEFAULT_GRIP_SIZE,
+                           G_PARAM_READWRITE));
+
+    g_object_class_install_property (
+        g_object_class, PROP_LOCKED,
+        g_param_spec_boolean ("locked", _("Locked"),
+                              _("If set, the dock item cannot be dragged around "
+                                "and it doesn't show a grip"),
+                              FALSE,
+                              G_PARAM_READWRITE |
+                              GDL_DOCK_PARAM_EXPORT));
+
+    g_object_class_install_property (
+        g_object_class, PROP_PREFERRED_WIDTH,
+        g_param_spec_int ("preferred_width", _("Preferred width"),
+                          _("Preferred width for the dock item"),
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE));
+
+    g_object_class_install_property (
+        g_object_class, PROP_PREFERRED_HEIGHT,
+        g_param_spec_int ("preferred_height", _("Preferred height"),
+                          _("Preferred height for the dock item"),
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE));
+
+    /* signals */
+    
+    gdl_dock_item_signals [DOCK_DRAG_BEGIN] = 
+        g_signal_new ("dock_drag_begin",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET (GdlDockItemClass, dock_drag_begin),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__VOID,
+                      G_TYPE_NONE, 
+                      0);
+
+    gdl_dock_item_signals [DOCK_DRAG_MOTION] = 
+        g_signal_new ("dock_drag_motion",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET (GdlDockItemClass, dock_drag_motion),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__INT_INT,
+                      G_TYPE_NONE, 
+                      2,
+                      G_TYPE_INT,
+                      G_TYPE_INT);
+
+    gdl_dock_item_signals [DOCK_DRAG_END] = 
+        g_signal_new ("dock_drag_end",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET (GdlDockItemClass, dock_drag_end),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__BOOLEAN,
+                      G_TYPE_NONE, 
+                      1,
+                      G_TYPE_BOOLEAN);
+
+    klass->has_grip = TRUE;
+    klass->dock_drag_begin = NULL;
+    klass->dock_drag_motion = NULL;
+    klass->dock_drag_end = NULL;
+    klass->set_orientation = gdl_dock_item_real_set_orientation;
+}
+
+static void
+gdl_dock_item_instance_init (GdlDockItem *item)
+{
+    GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_NO_WINDOW);
+
+    item->child = NULL;
+    
+    item->orientation = GTK_ORIENTATION_HORIZONTAL;
+    item->behavior = GDL_DOCK_ITEM_BEH_NORMAL;
+
+    item->resize = TRUE;
+
+    item->dragoff_x = item->dragoff_y = 0;
+
+    item->_priv = g_new0 (GdlDockItemPrivate, 1);
+    item->_priv->menu = NULL;
+
+    item->_priv->preferred_width = item->_priv->preferred_height = -1;
+    item->_priv->grip_size = DEFAULT_GRIP_SIZE;
+    item->_priv->tab_label = NULL;
+
+    item->_priv->ph = NULL;
+}
+
+static GObject *
+gdl_dock_item_constructor (GType                  type,
+                           guint                  n_construct_properties,
+                           GObjectConstructParam *construct_param)
+{
+    GObject *g_object;
+    
+    g_object = GNOME_CALL_PARENT_WITH_DEFAULT (G_OBJECT_CLASS, 
+                                               constructor, 
+                                               (type,
+                                                n_construct_properties,
+                                                construct_param),
+                                               NULL);
+    if (g_object) {
+        GdlDockItem *item = GDL_DOCK_ITEM (g_object);
+
+        if (GDL_DOCK_ITEM_HAS_GRIP (item)) {
+            item->_priv->grip_shown = TRUE;
+            item->_priv->grip = gdl_dock_item_grip_new (item);
+            gtk_widget_set_parent (item->_priv->grip, GTK_WIDGET (item));
+            gtk_widget_show (item->_priv->grip);
+        }
+        else {
+            item->_priv->grip_shown = FALSE;
+        }
+    }
+
+    return g_object;
+}
+
+static void
+gdl_dock_item_set_property  (GObject      *g_object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (g_object);
+
+    switch (prop_id) {
+        case PROP_ORIENTATION:
+            gdl_dock_item_set_orientation (item, g_value_get_enum (value));
+            break;
+        case PROP_RESIZE:
+            item->resize = g_value_get_boolean (value);
+            gtk_widget_queue_resize (GTK_WIDGET (item));
+            break;
+        case PROP_BEHAVIOR:
+        {
+            GdlDockItemBehavior old_beh = item->behavior;
+            item->behavior = g_value_get_flags (value);
+
+            if ((old_beh ^ item->behavior) & GDL_DOCK_ITEM_BEH_LOCKED) {
+                if (GDL_DOCK_OBJECT_GET_MASTER (item))
+                    g_signal_emit_by_name (GDL_DOCK_OBJECT_GET_MASTER (item),
+                                           "layout_changed");
+                g_object_notify (g_object, "locked");
+                gdl_dock_item_showhide_grip (item);
+            }
+            
+            break;
+        }
+        case PROP_GRIP_SIZE:
+            item->_priv->grip_size = g_value_get_uint (value);
+            if (GDL_DOCK_ITEM_GRIP_SHOWN (item))
+                gtk_widget_queue_resize (GTK_WIDGET (item));
+            break;
+        case PROP_LOCKED:
+        {
+            GdlDockItemBehavior old_beh = item->behavior;
+
+            if (g_value_get_boolean (value))
+                item->behavior |= GDL_DOCK_ITEM_BEH_LOCKED;
+            else
+                item->behavior &= ~GDL_DOCK_ITEM_BEH_LOCKED;
+
+            if (old_beh ^ item->behavior) {
+                gdl_dock_item_showhide_grip (item);
+                g_object_notify (g_object, "behavior");
+
+                if (GDL_DOCK_OBJECT_GET_MASTER (item))
+                    g_signal_emit_by_name (GDL_DOCK_OBJECT_GET_MASTER (item),
+                                           "layout_changed");
+            }
+            break;
+        }
+        case PROP_PREFERRED_WIDTH:
+            item->_priv->preferred_width = g_value_get_int (value);
+            break;
+        case PROP_PREFERRED_HEIGHT:
+            item->_priv->preferred_height = g_value_get_int (value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (g_object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_item_get_property  (GObject      *g_object,
+                             guint         prop_id,
+                             GValue       *value,
+                             GParamSpec   *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (g_object);
+    
+    switch (prop_id) {
+        case PROP_ORIENTATION:
+            g_value_set_enum (value, item->orientation);
+            break;
+        case PROP_RESIZE:
+            g_value_set_boolean (value, item->resize);
+            break;
+        case PROP_BEHAVIOR:
+            g_value_set_flags (value, item->behavior);
+            break;
+        case PROP_GRIP_SIZE:
+            g_value_set_uint (value, item->_priv->grip_size);
+            break;
+        case PROP_LOCKED:
+            g_value_set_boolean (value, !GDL_DOCK_ITEM_NOT_LOCKED (item));
+            break;
+        case PROP_PREFERRED_WIDTH:
+            g_value_set_int (value, item->_priv->preferred_width);
+            break;
+        case PROP_PREFERRED_HEIGHT:
+            g_value_set_int (value, item->_priv->preferred_height);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (g_object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_item_destroy (GtkObject *object)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+
+    if (item->_priv) {
+        GdlDockItemPrivate *priv = item->_priv;
+        
+        if (priv->tab_label) {
+            gdl_dock_item_set_tablabel (item, NULL);
+        };
+        if (priv->menu) {
+            gtk_menu_detach (GTK_MENU (priv->menu));
+            priv->menu = NULL;
+        };
+        if (priv->grip) {
+            gtk_container_remove (GTK_CONTAINER (item), priv->grip);
+            priv->grip = NULL;
+        }
+        if (priv->ph) {
+            g_object_unref (priv->ph);
+            priv->ph = NULL;
+        }
+        
+        item->_priv = NULL;
+        g_free (priv);
+    }
+
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
+}
+
+static void 
+gdl_dock_item_add (GtkContainer *container,
+                   GtkWidget    *widget)
+{
+    GdlDockItem *item;
+    
+    g_return_if_fail (GDL_IS_DOCK_ITEM (container));
+
+    item = GDL_DOCK_ITEM (container);
+    if (GDL_IS_DOCK_OBJECT (widget)) {
+        g_warning (_("You can't add a dock object (%p of type %s) inside a %s. "
+                     "Use a GdlDock or some other compound dock object."),
+                   widget, G_OBJECT_TYPE_NAME (widget), G_OBJECT_TYPE_NAME (item));
+        return;
+    }
+
+    if (item->child != NULL) {
+        g_warning (_("Attempting to add a widget with type %s to a %s, "
+                     "but it can only contain one widget at a time; "
+                     "it already contains a widget of type %s"),
+                     G_OBJECT_TYPE_NAME (widget),
+                     G_OBJECT_TYPE_NAME (item),
+                     G_OBJECT_TYPE_NAME (item->child));
+        return;
+    }
+
+    gtk_widget_set_parent (widget, GTK_WIDGET (item));
+    item->child = widget;
+}
+
+static void  
+gdl_dock_item_remove (GtkContainer *container,
+                      GtkWidget    *widget)
+{
+    GdlDockItem *item;
+    gboolean     was_visible;
+    
+    g_return_if_fail (GDL_IS_DOCK_ITEM (container));
+    
+    item = GDL_DOCK_ITEM (container);
+    if (item->_priv && widget == item->_priv->grip) {
+        gboolean grip_was_visible = GTK_WIDGET_VISIBLE (widget);
+        gtk_widget_unparent (widget);
+        item->_priv->grip = NULL;
+        if (grip_was_visible)
+            gtk_widget_queue_resize (GTK_WIDGET (item));
+        return;
+    }
+    
+    if (GDL_DOCK_ITEM_IN_DRAG (item)) {
+        gdl_dock_item_drag_end (item, TRUE);
+    }
+    
+    g_return_if_fail (item->child == widget);
+    
+    was_visible = GTK_WIDGET_VISIBLE (widget);
+
+    gtk_widget_unparent (widget);
+    item->child = NULL;
+    
+    if (was_visible)
+        gtk_widget_queue_resize (GTK_WIDGET (container));
+}
+
+static void
+gdl_dock_item_forall (GtkContainer *container,
+                      gboolean      include_internals,
+                      GtkCallback   callback,
+                      gpointer      callback_data)
+{
+    GdlDockItem *item = (GdlDockItem *) container;
+    
+    g_return_if_fail (callback != NULL);
+    
+    if (include_internals && item->_priv->grip)
+        (* callback) (item->_priv->grip, callback_data);
+    
+    if (item->child)
+        (* callback) (item->child, callback_data);
+}
+
+static GtkType
+gdl_dock_item_child_type (GtkContainer *container)
+{
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (container), G_TYPE_NONE);
+    
+    if (!GDL_DOCK_ITEM (container)->child)
+        return GTK_TYPE_WIDGET;
+    else
+        return G_TYPE_NONE;
+}
+
+static void
+gdl_dock_item_size_request (GtkWidget      *widget,
+                            GtkRequisition *requisition)
+{
+    GtkRequisition  child_requisition;
+    GdlDockItem    *item;
+
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+    g_return_if_fail (requisition != NULL);
+
+    item = GDL_DOCK_ITEM (widget);
+
+    /* If our child is not visible, we still request its size, since
+       we won't have any useful hint for our size otherwise.  */
+    if (item->child)
+        gtk_widget_size_request (item->child, &child_requisition);
+    else {
+        child_requisition.width = 0;
+        child_requisition.height = 0;
+    }
+
+    if (item->orientation == GTK_ORIENTATION_HORIZONTAL) {
+        requisition->width = 
+            GDL_DOCK_ITEM_GRIP_SHOWN (item) ? item->_priv->grip_size : 0;
+        if (item->child) {
+            requisition->width += child_requisition.width;
+            requisition->height = child_requisition.height;
+        } else
+            requisition->height = 0;
+    } else {
+        requisition->height = 
+            GDL_DOCK_ITEM_GRIP_SHOWN (item) ? item->_priv->grip_size : 0;
+        if (item->child) {
+            requisition->width = child_requisition.width;
+            requisition->height += child_requisition.height;
+        } else
+            requisition->width = 0;
+    }
+
+    requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+    requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+
+    widget->requisition = *requisition;
+}
+
+static void
+gdl_dock_item_size_allocate (GtkWidget     *widget,
+                             GtkAllocation *allocation)
+{
+    GdlDockItem *item;
+  
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+    g_return_if_fail (allocation != NULL);
+  
+    item = GDL_DOCK_ITEM (widget);
+
+    widget->allocation = *allocation;
+
+    if (GTK_WIDGET_REALIZED (widget))
+        gdk_window_move_resize (widget->window,
+                                widget->allocation.x,
+                                widget->allocation.y,
+                                widget->allocation.width,
+                                widget->allocation.height);
+
+    if (item->child && GTK_WIDGET_VISIBLE (item->child)) {
+        GtkAllocation  child_allocation;
+        int            border_width;
+
+        border_width = GTK_CONTAINER (widget)->border_width;
+
+        child_allocation.x = border_width;
+        child_allocation.y = border_width;
+        child_allocation.width = allocation->width - 2 * border_width;
+        child_allocation.height = allocation->height - 2 * border_width;
+        
+        if (GDL_DOCK_ITEM_GRIP_SHOWN (item)) {
+            GtkAllocation grip_alloc = *allocation;
+            
+            grip_alloc.x = grip_alloc.y = 0;
+            
+            if (item->orientation == GTK_ORIENTATION_HORIZONTAL) {
+                child_allocation.x += item->_priv->grip_size;
+                child_allocation.width -= item->_priv->grip_size;
+                grip_alloc.width = item->_priv->grip_size;
+            } else {
+                child_allocation.y += item->_priv->grip_size;
+                child_allocation.height -= item->_priv->grip_size;
+                grip_alloc.height = item->_priv->grip_size;
+            }
+            if (item->_priv->grip)
+                gtk_widget_size_allocate (item->_priv->grip, &grip_alloc);
+        };
+        gtk_widget_size_allocate (item->child, &child_allocation);
+    }
+}
+
+static void
+gdl_dock_item_map (GtkWidget *widget)
+{
+    GdlDockItem *item;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+    item = GDL_DOCK_ITEM (widget);
+
+    gdk_window_show (widget->window);
+
+    if (item->child
+        && GTK_WIDGET_VISIBLE (item->child)
+        && !GTK_WIDGET_MAPPED (item->child))
+        gtk_widget_map (item->child);
+
+    if (item->_priv->grip
+        && GTK_WIDGET_VISIBLE (item->_priv->grip)
+        && !GTK_WIDGET_MAPPED (item->_priv->grip))
+        gtk_widget_map (item->_priv->grip);
+}
+
+static void
+gdl_dock_item_unmap (GtkWidget *widget)
+{
+    GdlDockItem *item;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+    
+    item = GDL_DOCK_ITEM (widget);
+
+    gdk_window_hide (widget->window);
+
+    if (item->_priv->grip)
+        gtk_widget_unmap (item->_priv->grip);
+}
+
+static void
+gdl_dock_item_realize (GtkWidget *widget)
+{
+    GdkWindowAttr  attributes;
+    gint           attributes_mask;
+    GdlDockItem   *item;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    item = GDL_DOCK_ITEM (widget);
+
+    GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+    /* widget window */
+    attributes.x = widget->allocation.x;
+    attributes.y = widget->allocation.y;
+    attributes.width = widget->allocation.width;
+    attributes.height = widget->allocation.height;
+    attributes.window_type = GDK_WINDOW_CHILD;
+    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.visual = gtk_widget_get_visual (widget);
+    attributes.colormap = gtk_widget_get_colormap (widget);
+    attributes.event_mask = (gtk_widget_get_events (widget) |
+                             GDK_EXPOSURE_MASK |
+                             GDK_BUTTON1_MOTION_MASK |
+                             GDK_BUTTON_PRESS_MASK |
+                             GDK_BUTTON_RELEASE_MASK);
+    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+    widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), 
+                                     &attributes, attributes_mask);
+    gdk_window_set_user_data (widget->window, widget);
+  
+    widget->style = gtk_style_attach (widget->style, widget->window);
+    gtk_style_set_background (widget->style, widget->window, 
+                              GTK_WIDGET_STATE (item));
+    gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
+
+    if (item->child)
+        gtk_widget_set_parent_window (item->child, widget->window);
+    
+    if (item->_priv->grip)
+        gtk_widget_set_parent_window (item->_priv->grip, widget->window);
+}
+
+static void
+gdl_dock_item_style_set (GtkWidget *widget,
+                         GtkStyle  *previous_style)
+{
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    /* FIXME: maybe remove this method altogether and use the default implementation */
+    if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_NO_WINDOW (widget)) {
+        gtk_style_set_background (widget->style, widget->window,
+                                  widget->state);
+        if (GTK_WIDGET_DRAWABLE (widget))
+            gdk_window_clear (widget->window);
+    }
+}
+
+static void
+gdl_dock_item_paint (GtkWidget      *widget,
+                     GdkEventExpose *event)
+{
+    GdlDockItem  *item;
+
+    item = GDL_DOCK_ITEM (widget);
+
+    gtk_paint_box (widget->style,
+                   widget->window,
+                   GTK_WIDGET_STATE (widget),
+                   GTK_SHADOW_NONE,
+                   &event->area, widget,
+                   "dockitem",
+                   0, 0, -1, -1);
+}
+
+static gint
+gdl_dock_item_expose (GtkWidget      *widget,
+                      GdkEventExpose *event)
+{
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    if (GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window) {
+        gdl_dock_item_paint (widget, event);
+        GNOME_CALL_PARENT (GTK_WIDGET_CLASS, expose_event, (widget, event));
+    }
+  
+    return FALSE;
+}
+
+#define EVENT_IN_TABLABEL_EVENT_WINDOW(ev,tl) \
+    ((tl) != NULL && (ev)->window == GDL_DOCK_TABLABEL (tl)->event_window)
+
+static gint
+gdl_dock_item_button_changed (GtkWidget      *widget,
+                              GdkEventButton *event)
+{
+    GdlDockItem *item;
+    gboolean     event_handled;
+    gboolean     in_handle;
+  
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+    
+    item = GDL_DOCK_ITEM (widget);
+    
+    if (!(event->window == widget->window ||
+          EVENT_IN_TABLABEL_EVENT_WINDOW (event, item->_priv->tab_label)))
+        return FALSE;
+    
+    /* Verify that the item is not locked. */
+    if (!GDL_DOCK_ITEM_NOT_LOCKED (item))
+        return FALSE;
+
+    event_handled = FALSE;
+
+    /* Check if user clicked on the drag handle. */      
+    switch (item->orientation) {
+    case GTK_ORIENTATION_HORIZONTAL:
+        in_handle = event->x < item->_priv->grip_size;
+        break;
+    case GTK_ORIENTATION_VERTICAL:
+        in_handle = event->y < item->_priv->grip_size;
+        break;
+    default:
+        in_handle = FALSE;
+        break;
+    }
+
+    /* Left mousebutton click on dockitem. */
+    if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+        /* Set in_drag flag, grab pointer and call begin drag operation. */      
+        if (in_handle) {
+            item->_priv->start_x = event->x;
+            item->_priv->start_y = event->y;
+
+            GDL_DOCK_ITEM_SET_FLAGS (item, GDL_DOCK_IN_PREDRAG);
+        
+            event_handled = TRUE;
+        };
+        
+    } else if (event->type == GDK_BUTTON_RELEASE && event->button == 1) {
+        if (GDL_DOCK_ITEM_IN_DRAG (item)) {
+            /* User dropped widget somewhere. */
+            gdl_dock_item_drag_end (item, FALSE);
+            event_handled = TRUE;
+        }
+        else if (GDL_DOCK_ITEM_IN_PREDRAG (item)) {
+            GDL_DOCK_ITEM_UNSET_FLAGS (item, GDL_DOCK_IN_PREDRAG);
+            event_handled = TRUE;
+        }
+             
+    } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS && in_handle) {
+        gdl_dock_item_popup_menu (item, event->button, event->time);
+        event_handled = TRUE;    	
+    }
+
+    return event_handled;
+}
+
+static gint
+gdl_dock_item_motion (GtkWidget      *widget,
+                      GdkEventMotion *event)
+{
+    GdlDockItem *item;
+    gint         new_x, new_y;
+
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    item = GDL_DOCK_ITEM (widget);
+
+    if (!(event->window == widget->window ||
+          EVENT_IN_TABLABEL_EVENT_WINDOW (event, item->_priv->tab_label)))
+        return FALSE;
+
+    if (GDL_DOCK_ITEM_IN_PREDRAG (item)) {
+        if (gtk_drag_check_threshold (widget,
+                                      item->_priv->start_x,
+                                      item->_priv->start_y,
+                                      event->x,
+                                      event->y)) {
+            GDL_DOCK_ITEM_UNSET_FLAGS (item, GDL_DOCK_IN_PREDRAG);
+            item->dragoff_x = item->_priv->start_x;
+            item->dragoff_y = item->_priv->start_y;
+
+            gdl_dock_item_drag_start (item);
+        }
+    }
+    
+    if (!GDL_DOCK_ITEM_IN_DRAG (item))
+        return FALSE;
+
+    new_x = event->x_root;
+    new_y = event->y_root;
+    
+    g_signal_emit (item, gdl_dock_item_signals [DOCK_DRAG_MOTION], 
+                   0, new_x, new_y);
+
+    return TRUE;
+}
+
+static gboolean
+gdl_dock_item_key_press (GtkWidget   *widget,
+                         GdkEventKey *event)
+{
+    gboolean event_handled = FALSE;
+    
+    if (GDL_DOCK_ITEM_IN_DRAG (widget)) {
+        if (event->keyval == GDK_Escape) {
+            gdl_dock_item_drag_end (GDL_DOCK_ITEM (widget), TRUE);
+            event_handled = TRUE;
+        }
+    }
+
+    if (event_handled)
+        return TRUE;
+    else
+        return GNOME_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS,
+                                               key_press_event,
+                                               (widget, event),
+                                               FALSE);
+}
+
+static gboolean
+gdl_dock_item_dock_request (GdlDockObject  *object,
+                            gint            x,
+                            gint            y,
+                            GdlDockRequest *request)
+{
+    GtkAllocation *alloc;
+    gint           rel_x, rel_y;
+
+    /* we get (x,y) in our allocation coordinates system */
+    
+    /* Get item's allocation. */
+    alloc = &(GTK_WIDGET (object)->allocation);
+    
+    /* Get coordinates relative to our window. */
+    rel_x = x - alloc->x;
+    rel_y = y - alloc->y;
+
+    /* Location is inside. */
+    if (rel_x > 0 && rel_x < alloc->width &&
+        rel_y > 0 && rel_y < alloc->height) {
+        float rx, ry;
+        GtkRequisition my, other;
+        gint divider = -1;
+        
+        /* this are for calculating the extra docking parameter */
+        gdl_dock_item_preferred_size (GDL_DOCK_ITEM (request->applicant), &other);
+        gdl_dock_item_preferred_size (GDL_DOCK_ITEM (object), &my);
+        
+        /* Calculate location in terms of the available space (0-100%). */
+        rx = (float) rel_x / alloc->width;
+        ry = (float) rel_y / alloc->height;
+
+        /* Determine dock location. */
+        if (rx < SPLIT_RATIO) {
+            request->position = GDL_DOCK_LEFT;
+            divider = other.width;
+        }
+        else if (rx > (1 - SPLIT_RATIO)) {
+            request->position = GDL_DOCK_RIGHT;
+            rx = 1 - rx;
+            divider = MAX (0, my.width - other.width);
+        }
+        else if (ry < SPLIT_RATIO && ry < rx) {
+            request->position = GDL_DOCK_TOP;
+            divider = other.height;
+        }
+        else if (ry > (1 - SPLIT_RATIO) && (1 - ry) < rx) {
+            request->position = GDL_DOCK_BOTTOM;
+            divider = MAX (0, my.height - other.height);
+        }
+        else
+            request->position = GDL_DOCK_CENTER;
+
+        /* Reset rectangle coordinates to entire item. */
+        request->rect.x = 0;
+        request->rect.y = 0;
+        request->rect.width = alloc->width;
+        request->rect.height = alloc->height;
+
+        /* Calculate docking indicator rectangle size for new locations. Only
+           do this when we're not over the item's current location. */
+        if (request->applicant != object) {
+            switch (request->position) {
+                case GDL_DOCK_TOP:
+                    request->rect.height *= SPLIT_RATIO;
+                    break;
+                case GDL_DOCK_BOTTOM:
+                    request->rect.y += request->rect.height * (1 - SPLIT_RATIO);
+                    request->rect.height *= SPLIT_RATIO;
+                    break;
+                case GDL_DOCK_LEFT:
+                    request->rect.width *= SPLIT_RATIO;
+                    break;
+                case GDL_DOCK_RIGHT:
+                    request->rect.x += request->rect.width * (1 - SPLIT_RATIO);
+                    request->rect.width *= SPLIT_RATIO;
+                    break;
+                case GDL_DOCK_CENTER:
+                    request->rect.x = request->rect.width * SPLIT_RATIO/2;
+                    request->rect.y = request->rect.height * SPLIT_RATIO/2;
+                    request->rect.width = (request->rect.width *
+                                           (1 - SPLIT_RATIO/2)) - request->rect.x;
+                    request->rect.height = (request->rect.height *
+                                            (1 - SPLIT_RATIO/2)) - request->rect.y;
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        /* adjust returned coordinates so they are have the same
+           origin as our window */
+        request->rect.x += alloc->x;
+        request->rect.y += alloc->y;
+        
+        /* Set possible target location and return TRUE. */            
+        request->target = object;
+
+        /* fill-in other dock information */
+        if (request->position != GDL_DOCK_CENTER && divider >= 0) {
+            if (G_IS_VALUE (&request->extra))
+                g_value_unset (&request->extra);
+            g_value_init (&request->extra, G_TYPE_UINT);
+            g_value_set_uint (&request->extra, (guint) divider);
+        }
+        
+        return TRUE;         
+    }
+    else /* No docking possible at this location. */            
+        return FALSE;
+}
+
+static void
+gdl_dock_item_dock (GdlDockObject    *object,
+                    GdlDockObject    *requestor,
+                    GdlDockPlacement  position,
+                    GValue           *other_data)
+{
+    GdlDockObject *new_parent, *parent;
+    gboolean       add_ourselves_first;
+    
+    parent = gdl_dock_object_get_parent_object (object);
+
+    switch (position) {
+        case GDL_DOCK_TOP:
+        case GDL_DOCK_BOTTOM:
+            /* get a paned style dock object */
+            new_parent = g_object_new (gdl_dock_object_type_from_nick ("paned"),
+                                       "orientation", GTK_ORIENTATION_VERTICAL,
+                                       NULL);
+            add_ourselves_first = (position == GDL_DOCK_BOTTOM);
+            break;
+        case GDL_DOCK_LEFT:
+        case GDL_DOCK_RIGHT:
+            new_parent = g_object_new (gdl_dock_object_type_from_nick ("paned"),
+                                       "orientation", GTK_ORIENTATION_HORIZONTAL,
+                                       NULL);
+            add_ourselves_first = (position == GDL_DOCK_RIGHT);
+            break;
+        case GDL_DOCK_CENTER:
+            new_parent = g_object_new (gdl_dock_object_type_from_nick ("notebook"),
+                                       NULL);
+            add_ourselves_first = TRUE;
+            break;
+        default: 
+        {
+            GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_ref (GDL_TYPE_DOCK_PLACEMENT));
+            GEnumValue *enum_value = g_enum_get_value (enum_class, position);
+            gchar *name = enum_value ? enum_value->value_name : NULL;
+            
+            g_warning (_("Unsupported docking strategy %s in dock object of type %s"),
+                       name,  G_OBJECT_TYPE_NAME (object));
+            g_type_class_unref (enum_class);
+            return;
+        }
+    }
+
+    /* freeze the parent so it doesn't reduce automatically */
+    if (parent)
+        gdl_dock_object_freeze (parent);
+
+    /* ref ourselves since we could be destroyed when detached */
+    g_object_ref (object);
+    GDL_DOCK_OBJECT_SET_FLAGS (object, GDL_DOCK_IN_REFLOW);
+    gdl_dock_object_detach (object, FALSE);
+
+    /* freeze the new parent, so reduce won't get called before it's
+       actually added to our parent */
+    gdl_dock_object_freeze (new_parent);
+    
+    /* bind the new parent to our master, so the following adds work */
+    gdl_dock_object_bind (new_parent, G_OBJECT (GDL_DOCK_OBJECT_GET_MASTER (object)));
+    
+    /* add the objects */
+    if (add_ourselves_first) {
+        gtk_container_add (GTK_CONTAINER (new_parent), GTK_WIDGET (object));
+        gtk_container_add (GTK_CONTAINER (new_parent), GTK_WIDGET (requestor));
+    } else {
+        gtk_container_add (GTK_CONTAINER (new_parent), GTK_WIDGET (requestor));
+        gtk_container_add (GTK_CONTAINER (new_parent), GTK_WIDGET (object));
+    }
+
+    /* add the new parent to the parent */
+    if (parent)
+        gtk_container_add (GTK_CONTAINER (parent), GTK_WIDGET (new_parent));
+
+    /* show automatic object */
+    if (GTK_WIDGET_VISIBLE (object))
+        gtk_widget_show (GTK_WIDGET (new_parent));
+    
+    /* use extra docking parameter */
+    if (position != GDL_DOCK_CENTER && other_data &&
+        G_VALUE_HOLDS (other_data, G_TYPE_UINT)) {
+        
+        g_object_set (G_OBJECT (new_parent),
+                      "position", g_value_get_uint (other_data),
+                      NULL);
+    }
+    
+    GDL_DOCK_OBJECT_UNSET_FLAGS (object, GDL_DOCK_IN_REFLOW);
+    g_object_unref (object);
+
+    gdl_dock_object_thaw (new_parent);
+    if (parent)
+        gdl_dock_object_thaw (parent);
+}
+
+static void
+gdl_dock_item_detach_menu (GtkWidget *widget,
+                           GtkMenu   *menu)
+{
+    GdlDockItem *item;
+   
+    item = GDL_DOCK_ITEM (widget);
+    item->_priv->menu = NULL;
+}
+
+static void
+gdl_dock_item_popup_menu (GdlDockItem  *item, 
+                          guint         button,
+                          guint32       time)
+{
+    GtkWidget *mitem;
+
+    if (!item->_priv->menu) {
+        /* Create popup menu and attach it to the dock item */
+        item->_priv->menu = gtk_menu_new ();
+        gtk_menu_attach_to_widget (GTK_MENU (item->_priv->menu),
+                                   GTK_WIDGET (item),
+                                   gdl_dock_item_detach_menu);
+        
+        /* Hide menuitem. */
+        mitem = gtk_menu_item_new_with_label (_("Hide"));
+        gtk_menu_shell_append (GTK_MENU_SHELL (item->_priv->menu), mitem);
+        g_signal_connect (mitem, "activate", 
+                          G_CALLBACK (gdl_dock_item_hide_cb), item);
+
+        /* Lock menuitem */
+        mitem = gtk_menu_item_new_with_label (_("Lock"));
+        gtk_menu_shell_append (GTK_MENU_SHELL (item->_priv->menu), mitem);
+        g_signal_connect (mitem, "activate",
+                          G_CALLBACK (gdl_dock_item_lock_cb), item);
+
+    }
+
+    /* Show popup menu. */
+    gtk_widget_show_all (item->_priv->menu);
+    gtk_menu_popup (GTK_MENU (item->_priv->menu), NULL, NULL, NULL, NULL, 
+                    button, time);
+}
+
+static void
+gdl_dock_item_drag_start (GdlDockItem *item)
+{
+    GdkCursor *fleur;
+
+    if (!GTK_WIDGET_REALIZED (item))
+        gtk_widget_realize (GTK_WIDGET (item));
+    
+    GDL_DOCK_ITEM_SET_FLAGS (item, GDL_DOCK_IN_DRAG);
+            
+    /* grab the pointer so we receive all mouse events */
+    fleur = gdk_cursor_new (GDK_FLEUR);
+
+    /* grab the keyboard & pointer */
+    gtk_grab_add (GTK_WIDGET (item));
+    
+    gdk_cursor_unref (fleur);
+            
+    g_signal_emit (item, gdl_dock_item_signals [DOCK_DRAG_BEGIN], 0);
+}
+
+static void
+gdl_dock_item_drag_end (GdlDockItem *item,
+                        gboolean     cancel)
+{
+    /* Release pointer & keyboard. */
+    gtk_grab_remove (gtk_grab_get_current ());
+    
+    g_signal_emit (item, gdl_dock_item_signals [DOCK_DRAG_END], 0, cancel);
+    
+    GDL_DOCK_ITEM_UNSET_FLAGS (item, GDL_DOCK_IN_DRAG);
+}
+
+static void 
+gdl_dock_item_tab_button (GtkWidget      *widget,
+                          GdkEventButton *event,
+                          gpointer        data)
+{
+    GdlDockItem *item;
+
+    item = GDL_DOCK_ITEM (data);
+
+    if (!GDL_DOCK_ITEM_NOT_LOCKED (item))
+        return;
+
+    switch (event->button) {
+    case 1:
+        /* set dragoff_{x,y} as we the user clicked on the middle of the 
+           drag handle */
+        switch (item->orientation) {
+        case GTK_ORIENTATION_HORIZONTAL:
+            item->dragoff_x = item->_priv->grip_size / 2;
+            item->dragoff_y = GTK_WIDGET (data)->allocation.height / 2;
+            break;
+        case GTK_ORIENTATION_VERTICAL:
+            item->dragoff_x = GTK_WIDGET (data)->allocation.width / 2;
+            item->dragoff_y = item->_priv->grip_size / 2;
+            break;
+        };
+        gdl_dock_item_drag_start (item);
+        break;
+
+    case 3:
+        gdl_dock_item_popup_menu (item, event->button, event->time);
+        break;
+
+    default:
+        break;
+    };
+}
+
+static void
+gdl_dock_item_hide_cb (GtkWidget   *widget, 
+                       GdlDockItem *item)
+{
+    GdlDockMaster *master;
+    
+    g_return_if_fail (item != NULL);
+
+    master = GDL_DOCK_OBJECT_GET_MASTER (item);
+    gdl_dock_item_hide_item (item);
+}
+
+static void
+gdl_dock_item_lock_cb (GtkWidget   *widget,
+                       GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    gdl_dock_item_lock (item);
+}
+
+static void
+gdl_dock_item_showhide_grip (GdlDockItem *item)
+{
+    if (item->_priv->grip) {
+        if (GDL_DOCK_ITEM_GRIP_SHOWN (item)) {
+            gtk_widget_show (item->_priv->grip);
+            GTK_WIDGET_SET_FLAGS (item->_priv->grip, GTK_CAN_FOCUS);
+        } else {
+            gtk_widget_hide (item->_priv->grip);
+            GTK_WIDGET_UNSET_FLAGS (item->_priv->grip, GTK_CAN_FOCUS);
+        }
+    }
+    gtk_widget_queue_resize (GTK_WIDGET (item));
+}
+
+static void
+gdl_dock_item_real_set_orientation (GdlDockItem    *item,
+                                    GtkOrientation  orientation)
+{
+    item->orientation = orientation;
+    
+    if (GTK_WIDGET_DRAWABLE (item))
+        gtk_widget_queue_draw (GTK_WIDGET (item));
+    gtk_widget_queue_resize (GTK_WIDGET (item));
+}
+
+
+/* ----- Public interface ----- */
+
+GtkWidget *
+gdl_dock_item_new (const gchar         *name,
+                   const gchar         *long_name,
+                   GdlDockItemBehavior  behavior)
+{
+    GdlDockItem *item;
+
+    item = GDL_DOCK_ITEM (g_object_new (GDL_TYPE_DOCK_ITEM, 
+                                        "name", name, 
+                                        "long_name", long_name,
+                                        "behavior", behavior,
+                                        NULL));
+    GDL_DOCK_OBJECT_UNSET_FLAGS (item, GDL_DOCK_AUTOMATIC);
+    gdl_dock_item_set_tablabel (item, gdl_dock_tablabel_new (item));
+
+    return GTK_WIDGET (item);
+}
+
+/* convenient function (and to preserve source compat) */
+void
+gdl_dock_item_dock_to (GdlDockItem      *item,
+                       GdlDockItem      *target,
+                       GdlDockPlacement  position,
+                       gint              docking_param)
+{
+    g_return_if_fail (item != NULL);
+    g_return_if_fail (item != target);
+    g_return_if_fail (target != NULL || position == GDL_DOCK_FLOATING);
+    
+    if (position == GDL_DOCK_FLOATING || !target) {
+        GdlDockObject *controller;
+        
+        if (!gdl_dock_object_is_bound (GDL_DOCK_OBJECT (item))) {
+            g_warning (_("Attempt to bind an unbound item %p"), item);
+            return;
+        }
+
+        controller = gdl_dock_master_get_controller (GDL_DOCK_OBJECT_GET_MASTER (item));
+        
+        /* FIXME: save previous docking position for later
+           re-docking... does this make sense now? */
+
+        /* Create new floating dock for widget. */
+        item->dragoff_x = item->dragoff_y = 0;
+        gdl_dock_add_floating_item (GDL_DOCK (controller),
+                                    item, 0, 0, -1, -1);
+
+    } else
+        gdl_dock_object_dock (GDL_DOCK_OBJECT (target),
+                              GDL_DOCK_OBJECT (item),
+                              position, NULL);
+}
+
+void
+gdl_dock_item_set_orientation (GdlDockItem    *item,
+                               GtkOrientation  orientation)
+{
+    GParamSpec *pspec;
+
+    g_return_if_fail (item != NULL);
+
+    if (item->orientation != orientation) {
+        /* push the property down the hierarchy if our child supports it */
+        if (item->child != NULL) {
+            pspec = g_object_class_find_property (
+                G_OBJECT_GET_CLASS (item->child), "orientation");
+            if (pspec && pspec->value_type == GTK_TYPE_ORIENTATION)
+                g_object_set (G_OBJECT (item->child),
+                              "orientation", orientation,
+                              NULL);
+        };
+
+        GDL_CALL_VIRTUAL (item, GDL_DOCK_ITEM_GET_CLASS, set_orientation, (item, orientation));
+        g_object_notify (G_OBJECT (item), "orientation");
+    }
+}
+
+GtkWidget *
+gdl_dock_item_get_tablabel (GdlDockItem *item)
+{
+    g_return_val_if_fail (item != NULL, NULL);
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (item), NULL);
+
+    return item->_priv->tab_label;
+}
+
+void
+gdl_dock_item_set_tablabel (GdlDockItem *item,
+                            GtkWidget   *tablabel)
+{
+    g_return_if_fail (item != NULL);
+
+    if (item->_priv->tab_label) {
+        /* disconnect and unref the previous tablabel */
+        if (GDL_IS_DOCK_TABLABEL (item->_priv->tab_label)) {
+            g_signal_handlers_disconnect_matched (item->_priv->tab_label,
+                                                  G_SIGNAL_MATCH_DATA,
+                                                  0, 0, NULL,
+                                                  NULL, item);
+            g_object_set (item->_priv->tab_label, "item", NULL, NULL);
+        }
+        gtk_widget_unref (item->_priv->tab_label);
+        item->_priv->tab_label = NULL;
+    }
+    
+    if (tablabel) {
+        gtk_widget_ref (tablabel);
+        gtk_object_sink (GTK_OBJECT (tablabel));
+        item->_priv->tab_label = tablabel;
+        if (GDL_IS_DOCK_TABLABEL (tablabel)) {
+            g_object_set (tablabel, "item", item, NULL);
+            /* connect to tablabel signal */
+            g_signal_connect (tablabel, "button_pressed_handle",
+                              G_CALLBACK (gdl_dock_item_tab_button), item);
+        }
+    }
+}
+
+void 
+gdl_dock_item_hide_grip (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+    if (item->_priv->grip_shown) {
+        item->_priv->grip_shown = FALSE;
+        gdl_dock_item_showhide_grip (item);
+    };
+}
+
+void
+gdl_dock_item_show_grip (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+    if (!item->_priv->grip_shown) {
+        item->_priv->grip_shown = TRUE;
+        gdl_dock_item_showhide_grip (item);
+    };
+}
+
+/* convenient function (and to preserve source compat) */
+void
+gdl_dock_item_bind (GdlDockItem *item,
+                    GtkWidget   *dock)
+{
+    g_return_if_fail (item != NULL);
+    g_return_if_fail (dock == NULL || GDL_IS_DOCK (dock));
+    
+    gdl_dock_object_bind (GDL_DOCK_OBJECT (item),
+                          G_OBJECT (GDL_DOCK_OBJECT_GET_MASTER (dock)));
+}
+
+/* convenient function (and to preserve source compat) */
+void
+gdl_dock_item_unbind (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
+}
+
+void
+gdl_dock_item_hide_item (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    if (!GDL_DOCK_OBJECT_ATTACHED (item))
+        /* already hidden/detached */
+        return;
+    
+    /* if the object is manual, create a new placeholder to be able to
+       restore the position later */
+    if (!GDL_DOCK_OBJECT_AUTOMATIC (item)) {
+        if (item->_priv->ph)
+            g_object_unref (item->_priv->ph);
+        
+        item->_priv->ph = GDL_DOCK_PLACEHOLDER (
+            g_object_new (GDL_TYPE_DOCK_PLACEHOLDER,
+                          "sticky", FALSE,
+                          "host", item,
+                          NULL));
+        g_object_ref (item->_priv->ph);
+        gtk_object_sink (GTK_OBJECT (item->_priv->ph));
+    }
+    
+    gdl_dock_object_freeze (GDL_DOCK_OBJECT (item));
+    
+    /* hide our children first, so they can also set placeholders */
+    if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (item))) 
+        gtk_container_foreach (GTK_CONTAINER (item),
+                               (GtkCallback) gdl_dock_item_hide_item,
+                               NULL);
+    
+    /* detach the item recursively */
+    gdl_dock_object_detach (GDL_DOCK_OBJECT (item), TRUE);
+
+    gdl_dock_object_thaw (GDL_DOCK_OBJECT (item));
+}
+
+void
+gdl_dock_item_show_item (GdlDockItem *item)
+{
+    g_return_if_fail (item != NULL);
+
+    if (item->_priv->ph) {
+        gtk_container_add (GTK_CONTAINER (item->_priv->ph), GTK_WIDGET (item));
+        g_object_unref (item->_priv->ph);
+        item->_priv->ph = NULL;
+    }
+    else if (gdl_dock_object_is_bound (GDL_DOCK_OBJECT (item))) {
+        GdlDockObject *toplevel = gdl_dock_master_get_controller (
+            GDL_DOCK_OBJECT_GET_MASTER (item));
+        if (toplevel) {
+            gdl_dock_object_dock (toplevel, GDL_DOCK_OBJECT (item),
+                                  GDL_DOCK_FLOATING, NULL);
+        }
+    }
+}
+
+void
+gdl_dock_item_lock (GdlDockItem *item)
+{
+    g_object_set (item, "locked", TRUE, NULL);
+}
+
+void
+gdl_dock_item_unlock (GdlDockItem *item)
+{
+    g_object_set (item, "locked", FALSE, NULL);
+}
+
+void 
+gdl_dock_item_set_default_position (GdlDockItem   *item,
+                                    GdlDockObject *reference)
+{
+    g_return_if_fail (item != NULL);
+
+    if (item->_priv->ph) {
+        g_object_unref (item->_priv->ph);
+        item->_priv->ph = NULL;
+    }
+
+    if (reference && GDL_DOCK_OBJECT_ATTACHED (reference)) {
+        if (GDL_IS_DOCK_PLACEHOLDER (reference)) {
+            g_object_ref (reference);
+            gtk_object_sink (GTK_OBJECT (reference));
+            item->_priv->ph = GDL_DOCK_PLACEHOLDER (reference);
+        }
+        else {
+            item->_priv->ph = GDL_DOCK_PLACEHOLDER (
+                g_object_new (GDL_TYPE_DOCK_PLACEHOLDER,
+                              "sticky", TRUE,
+                              "host", reference,
+                              NULL));
+            g_object_ref (item->_priv->ph);
+            gtk_object_sink (GTK_OBJECT (item->_priv->ph));
+        }
+    }
+}
+
+void 
+gdl_dock_item_preferred_size (GdlDockItem    *item,
+                              GtkRequisition *req)
+{
+    if (!req)
+        return;
+
+    req->width = MAX (item->_priv->preferred_width,
+                      GTK_WIDGET (item)->allocation.width);
+    req->height = MAX (item->_priv->preferred_height,
+                       GTK_WIDGET (item)->allocation.height);
+}
+
+
+/* ----- gtk orientation type exporter/importer ----- */
+
+static void 
+gdl_dock_param_export_gtk_orientation (const GValue *src,
+                                       GValue       *dst)
+{
+    dst->data [0].v_pointer =
+        g_strdup_printf ("%s", (src->data [0].v_int == GTK_ORIENTATION_HORIZONTAL) ?
+                         "horizontal" : "vertical");
+}
+
+static void 
+gdl_dock_param_import_gtk_orientation (const GValue *src,
+                                       GValue       *dst)
+{
+    if (!strcmp (src->data [0].v_pointer, "horizontal"))
+        dst->data [0].v_int = GTK_ORIENTATION_HORIZONTAL;
+    else
+        dst->data [0].v_int = GTK_ORIENTATION_VERTICAL;
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-item.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * gdl-dock-item.h
+ *
+ * Author: Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * Based on GnomeDockItem/BonoboDockItem.  Original copyright notice follows.
+ *
+ * Copyright (C) 1998 Ettore Perazzoli
+ * Copyright (C) 1998 Elliot Lee
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDL_DOCK_ITEM_H__
+#define __GDL_DOCK_ITEM_H__
+
+#include <gdl/gdl-dock-object.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_ITEM            (gdl_dock_item_get_type ())
+#define GDL_DOCK_ITEM(obj)            (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_ITEM, GdlDockItem))
+#define GDL_DOCK_ITEM_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_ITEM, GdlDockItemClass))
+#define GDL_IS_DOCK_ITEM(obj)         (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_ITEM))
+#define GDL_IS_DOCK_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_ITEM))
+#define GDL_DOCK_ITEM_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_ITEM, GdlDockItemClass))
+
+/* data types & structures */
+typedef enum {
+    GDL_DOCK_ITEM_BEH_NORMAL           = 0,
+    GDL_DOCK_ITEM_BEH_NEVER_FLOATING   = 1 << 0,
+    GDL_DOCK_ITEM_BEH_NEVER_VERTICAL   = 1 << 1,
+    GDL_DOCK_ITEM_BEH_NEVER_HORIZONTAL = 1 << 2,
+    GDL_DOCK_ITEM_BEH_LOCKED           = 1 << 3,
+    GDL_DOCK_ITEM_BEH_CANT_DOCK_TOP    = 1 << 4,
+    GDL_DOCK_ITEM_BEH_CANT_DOCK_BOTTOM = 1 << 5,
+    GDL_DOCK_ITEM_BEH_CANT_DOCK_LEFT   = 1 << 6,
+    GDL_DOCK_ITEM_BEH_CANT_DOCK_RIGHT  = 1 << 7,
+    GDL_DOCK_ITEM_BEH_CANT_DOCK_CENTER = 1 << 8
+} GdlDockItemBehavior;
+
+typedef enum {
+    GDL_DOCK_IN_DRAG             = 1 << GDL_DOCK_OBJECT_FLAGS_SHIFT,
+    GDL_DOCK_IN_PREDRAG          = 1 << (GDL_DOCK_OBJECT_FLAGS_SHIFT + 1),
+    /* for general use: indicates the user has started an action on
+       the dock item */
+    GDL_DOCK_USER_ACTION         = 1 << (GDL_DOCK_OBJECT_FLAGS_SHIFT + 2)
+} GdlDockItemFlags;
+
+typedef struct _GdlDockItem        GdlDockItem;
+typedef struct _GdlDockItemClass   GdlDockItemClass;
+typedef struct _GdlDockItemPrivate GdlDockItemPrivate;
+
+struct _GdlDockItem {
+    GdlDockObject        object;
+
+    GtkWidget           *child;
+    GdlDockItemBehavior  behavior;
+    GtkOrientation       orientation;
+
+    guint                resize : 1;
+
+    gint                 dragoff_x, dragoff_y;    /* these need to be
+                                                     accesible from
+                                                     outside */
+    GdlDockItemPrivate  *_priv;
+};
+
+struct _GdlDockItemClass {
+    GdlDockObjectClass  parent_class;
+
+    gboolean            has_grip;
+    
+    /* virtuals */
+    void     (* dock_drag_begin)  (GdlDockItem    *item);
+    void     (* dock_drag_motion) (GdlDockItem    *item,
+                                   gint            x,
+                                   gint            y);
+    void     (* dock_drag_end)    (GdlDockItem    *item,
+                                   gboolean        cancelled);
+                                   
+    void     (* set_orientation)  (GdlDockItem    *item,
+                                   GtkOrientation  orientation);
+};
+
+/* additional macros */
+#define GDL_DOCK_ITEM_FLAGS(item)     (GDL_DOCK_OBJECT (item)->flags)
+#define GDL_DOCK_ITEM_IN_DRAG(item) \
+    ((GDL_DOCK_ITEM_FLAGS (item) & GDL_DOCK_IN_DRAG) != 0)
+#define GDL_DOCK_ITEM_IN_PREDRAG(item) \
+    ((GDL_DOCK_ITEM_FLAGS (item) & GDL_DOCK_IN_PREDRAG) != 0)
+#define GDL_DOCK_ITEM_USER_ACTION(item) \
+    ((GDL_DOCK_ITEM_FLAGS (item) & GDL_DOCK_USER_ACTION) != 0)
+   
+#define GDL_DOCK_ITEM_SET_FLAGS(item,flag) \
+    G_STMT_START { (GDL_DOCK_ITEM_FLAGS (item) |= (flag)); } G_STMT_END
+#define GDL_DOCK_ITEM_UNSET_FLAGS(item,flag) \
+    G_STMT_START { (GDL_DOCK_ITEM_FLAGS (item) &= ~(flag)); } G_STMT_END
+
+#define GDL_DOCK_ITEM_HAS_GRIP(item) (GDL_DOCK_ITEM_GET_CLASS (item)->has_grip)
+
+/* public interface */
+ 
+GtkWidget     *gdl_dock_item_new               (const gchar         *name,
+                                                const gchar         *long_name,
+                                                GdlDockItemBehavior  behavior);
+
+GType          gdl_dock_item_get_type          (void);
+
+void           gdl_dock_item_dock_to           (GdlDockItem      *item,
+                                                GdlDockItem      *target,
+                                                GdlDockPlacement  position,
+                                                gint              docking_param);
+
+void           gdl_dock_item_set_orientation   (GdlDockItem    *item,
+                                                GtkOrientation  orientation);
+
+GtkWidget     *gdl_dock_item_get_tablabel      (GdlDockItem *item);
+void           gdl_dock_item_set_tablabel      (GdlDockItem *item,
+                                                GtkWidget   *tablabel);
+void           gdl_dock_item_hide_grip         (GdlDockItem *item);
+void           gdl_dock_item_show_grip         (GdlDockItem *item);
+
+/* bind and unbind items to a dock */
+void           gdl_dock_item_bind              (GdlDockItem *item,
+                                                GtkWidget   *dock);
+
+void           gdl_dock_item_unbind            (GdlDockItem *item);
+
+void           gdl_dock_item_hide_item         (GdlDockItem *item);
+
+void           gdl_dock_item_show_item         (GdlDockItem *item);
+
+void           gdl_dock_item_lock              (GdlDockItem *item);
+
+void           gdl_dock_item_unlock            (GdlDockItem *item);
+
+void        gdl_dock_item_set_default_position (GdlDockItem      *item,
+                                                GdlDockObject    *reference);
+
+void        gdl_dock_item_preferred_size       (GdlDockItem      *item,
+                                                GtkRequisition   *req);
+
+
+G_END_DECLS
+
+#endif

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,1413 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <libgnome/gnome-macros.h>
+
+#include "gdl-dock-layout.h"
+#include "gdl-tools.h"
+#include "gdl-dock-placeholder.h"
+
+
+/* ----- Private variables ----- */
+
+enum {
+    PROP_0,
+    PROP_MASTER,
+    PROP_DIRTY
+};
+
+#define ROOT_ELEMENT         "dock-layout"
+#define DEFAULT_LAYOUT       "__default__"
+#define LAYOUT_ELEMENT_NAME  "layout"
+#define NAME_ATTRIBUTE_NAME  "name"
+
+#define LAYOUT_GLADE_FILE    "layout.glade"
+
+enum {
+    COLUMN_NAME,
+    COLUMN_SHOW,
+    COLUMN_LOCKED,
+    COLUMN_ITEM
+};
+
+#define COLUMN_EDITABLE COLUMN_SHOW
+
+struct _GdlDockLayoutPrivate {
+    xmlDocPtr         doc;
+
+    /* layout list models */
+    GtkListStore     *items_model;
+    GtkListStore     *layouts_model;
+
+    /* idle control */
+    gboolean          idle_save_pending;
+};
+
+typedef struct _GdlDockLayoutUIData GdlDockLayoutUIData;
+
+struct _GdlDockLayoutUIData {
+    GdlDockLayout    *layout;
+    
+    GtkWidget        *locked_check;
+    GtkTreeSelection *selection;
+};
+
+
+/* ----- Private prototypes ----- */
+
+static void     gdl_dock_layout_class_init      (GdlDockLayoutClass *klass);
+
+static void     gdl_dock_layout_instance_init   (GdlDockLayout      *layout);
+
+static void     gdl_dock_layout_set_property    (GObject            *object,
+                                                 guint               prop_id,
+                                                 const GValue       *value,
+                                                 GParamSpec         *pspec);
+
+static void     gdl_dock_layout_get_property    (GObject            *object,
+                                                 guint               prop_id,
+                                                 GValue             *value,
+                                                 GParamSpec         *pspec);
+
+static void     gdl_dock_layout_dispose         (GObject            *object);
+
+static void     gdl_dock_layout_build_doc       (GdlDockLayout      *layout);
+
+static xmlNodePtr gdl_dock_layout_find_layout   (GdlDockLayout      *layout, 
+                                                 const gchar        *name);
+
+static void     gdl_dock_layout_build_models    (GdlDockLayout      *layout);
+
+
+/* ----- Private implementation ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockLayout, gdl_dock_layout, GObject, G_TYPE_OBJECT);
+
+static void
+gdl_dock_layout_class_init (GdlDockLayoutClass *klass)
+{
+    GObjectClass *g_object_class = (GObjectClass *) klass;
+
+    g_object_class->set_property = gdl_dock_layout_set_property;
+    g_object_class->get_property = gdl_dock_layout_get_property;
+    g_object_class->dispose = gdl_dock_layout_dispose;
+
+    g_object_class_install_property (
+        g_object_class, PROP_MASTER,
+        g_param_spec_object ("master", _("Master"),
+                             _("GdlDockMaster object which the layout object "
+                               "is attached to"),
+                             GDL_TYPE_DOCK_MASTER, 
+                             G_PARAM_READWRITE));
+
+    g_object_class_install_property (
+        g_object_class, PROP_DIRTY,
+        g_param_spec_boolean ("dirty", _("Dirty"),
+                              _("True if the layouts have changed and need to be "
+                                "saved to a file"),
+                              FALSE,
+                              G_PARAM_READABLE));
+}
+
+static void
+gdl_dock_layout_instance_init (GdlDockLayout *layout)
+{
+    layout->master = NULL;
+    layout->dirty = FALSE;
+    layout->_priv = g_new0 (GdlDockLayoutPrivate, 1);
+    layout->_priv->idle_save_pending = FALSE;
+
+    gdl_dock_layout_build_models (layout);
+}
+
+static void
+gdl_dock_layout_set_property (GObject      *object,
+			      guint         prop_id,
+			      const GValue *value,
+			      GParamSpec   *pspec)
+{
+    GdlDockLayout *layout = GDL_DOCK_LAYOUT (object);
+
+    switch (prop_id) {
+        case PROP_MASTER:
+            gdl_dock_layout_attach (layout, g_value_get_object (value));
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    };
+}
+
+static void
+gdl_dock_layout_get_property (GObject    *object,
+			      guint       prop_id,
+			      GValue     *value,
+			      GParamSpec *pspec)
+{
+    GdlDockLayout *layout = GDL_DOCK_LAYOUT (object);
+
+    switch (prop_id) {
+        case PROP_MASTER:
+            g_value_set_object (value, layout->master);
+            break;
+        case PROP_DIRTY:
+            g_value_set_boolean (value, layout->dirty);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    };
+}
+
+static void
+gdl_dock_layout_dispose (GObject *object)
+{
+    GdlDockLayout *layout;
+
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GDL_IS_DOCK_LAYOUT (object));
+
+    layout = GDL_DOCK_LAYOUT (object);
+    
+    if (layout->master)
+        gdl_dock_layout_attach (layout, NULL);
+
+    if (layout->_priv) {
+        if (layout->_priv->idle_save_pending) {
+            layout->_priv->idle_save_pending = FALSE;
+            g_idle_remove_by_data (layout);
+        }
+        
+        if (layout->_priv->doc) {
+            xmlFreeDoc (layout->_priv->doc);
+            layout->_priv->doc = NULL;
+        }
+
+        if (layout->_priv->items_model) {
+            g_object_unref (layout->_priv->items_model);
+            g_object_unref (layout->_priv->layouts_model);
+            layout->_priv->items_model = NULL;
+            layout->_priv->layouts_model = NULL;
+        }
+
+        g_free (layout->_priv);
+        layout->_priv = NULL;
+    }
+}
+
+static void
+gdl_dock_layout_build_doc (GdlDockLayout *layout)
+{
+    g_return_if_fail (layout->_priv->doc == NULL);
+
+    layout->_priv->doc = xmlNewDoc ("1.0");
+    layout->_priv->doc->children = xmlNewDocNode (layout->_priv->doc, NULL, 
+                                                  ROOT_ELEMENT, NULL);
+}
+
+static xmlNodePtr
+gdl_dock_layout_find_layout (GdlDockLayout *layout, 
+                             const gchar   *name)
+{
+    xmlNodePtr node;
+    gboolean   found = FALSE;
+
+    g_return_val_if_fail (layout != NULL, NULL);
+    
+    if (!layout->_priv->doc)
+        return NULL;
+
+    /* get document root */
+    node = layout->_priv->doc->children;
+    for (node = node->children; node; node = node->next) {
+        gchar *layout_name;
+        
+        if (strcmp (node->name, LAYOUT_ELEMENT_NAME))
+            /* skip non-layout element */
+            continue;
+
+        /* we want the first layout */
+        if (!name)
+            break;
+
+        layout_name = xmlGetProp (node, NAME_ATTRIBUTE_NAME);
+        if (!strcmp (name, layout_name))
+            found = TRUE;
+        xmlFree (layout_name);
+
+        if (found)
+            break;
+    };
+    return node;
+}
+
+static void
+gdl_dock_layout_build_models (GdlDockLayout *layout)
+{
+    if (!layout->_priv->items_model) {
+        layout->_priv->items_model = gtk_list_store_new (4, 
+                                                         G_TYPE_STRING, 
+                                                         G_TYPE_BOOLEAN,
+                                                         G_TYPE_BOOLEAN,
+                                                         G_TYPE_POINTER);
+        gtk_tree_sortable_set_sort_column_id (
+            GTK_TREE_SORTABLE (layout->_priv->items_model), 
+            COLUMN_NAME, GTK_SORT_ASCENDING);
+    }
+
+    if (!layout->_priv->layouts_model) {
+        layout->_priv->layouts_model = gtk_list_store_new (2, G_TYPE_STRING,
+                                                           G_TYPE_BOOLEAN);
+        gtk_tree_sortable_set_sort_column_id (
+            GTK_TREE_SORTABLE (layout->_priv->layouts_model),
+            COLUMN_NAME, GTK_SORT_ASCENDING);
+    }
+}
+
+static void
+build_list (GdlDockObject *object, GList **list)
+{
+    /* add only items, not toplevels */
+    if (GDL_IS_DOCK_ITEM (object))
+        *list = g_list_prepend (*list, object);
+}
+
+static void
+update_items_model (GdlDockLayout *layout)
+{
+    GList *items, *l;
+    GtkTreeIter iter;
+    GtkListStore *store;
+    gchar *long_name;
+    gboolean locked;
+    
+    g_return_if_fail (layout != NULL);
+    g_return_if_fail (layout->_priv->items_model != NULL);
+
+    if (!layout->master)
+        return;
+    
+    /* build items list */
+    items = NULL;
+    gdl_dock_master_foreach (layout->master, (GFunc) build_list, &items);
+
+    /* walk the current model */
+    store = layout->_priv->items_model;
+    
+    /* update items model data after a layout load */
+    if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+        gboolean valid = TRUE;
+        
+        while (valid) {
+            GdlDockItem *item;
+            
+            gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                                COLUMN_ITEM, &item,
+                                -1);
+            if (item) {
+                /* look for the object in the items list */
+                for (l = items; l && l->data != item; l = l->next);
+
+                if (l) {
+                    /* found, update data */
+                    g_object_get (item, 
+                                  "long_name", &long_name, 
+                                  "locked", &locked, 
+                                  NULL);
+                    gtk_list_store_set (store, &iter, 
+                                        COLUMN_NAME, long_name,
+                                        COLUMN_SHOW, GDL_DOCK_OBJECT_ATTACHED (item),
+                                        COLUMN_LOCKED, locked,
+                                        -1);
+                    g_free (long_name);
+
+                    /* remove the item from the linked list and keep on walking the model */
+                    items = g_list_delete_link (items, l);
+                    valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+
+                } else {
+                    /* not found, which means the item has been removed */
+                    valid = gtk_list_store_remove (store, &iter);
+                    
+                }
+
+            } else {
+                /* not a valid row */
+                valid = gtk_list_store_remove (store, &iter);
+            }
+        }
+    }
+
+    /* add any remaining objects */
+    for (l = items; l; l = l->next) {
+        GdlDockObject *object = l->data;
+        
+        g_object_get (object, 
+                      "long_name", &long_name, 
+                      "locked", &locked, 
+                      NULL);
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter, 
+                            COLUMN_ITEM, object,
+                            COLUMN_NAME, long_name,
+                            COLUMN_SHOW, GDL_DOCK_OBJECT_ATTACHED (object),
+                            COLUMN_LOCKED, locked,
+                            -1);
+        g_free (long_name);
+    }
+    
+    g_list_free (items);
+}
+
+static void
+update_layouts_model (GdlDockLayout *layout)
+{
+    GList *items, *l;
+    GtkTreeIter iter;
+    
+    g_return_if_fail (layout != NULL);
+    g_return_if_fail (layout->_priv->layouts_model != NULL);
+
+    /* build layouts list */
+    gtk_list_store_clear (layout->_priv->layouts_model);
+    items = gdl_dock_layout_get_layouts (layout, FALSE);
+    for (l = items; l; l = l->next) {
+        gtk_list_store_append (layout->_priv->layouts_model, &iter);
+        gtk_list_store_set (layout->_priv->layouts_model, &iter,
+                            COLUMN_NAME, l->data, COLUMN_EDITABLE, TRUE,
+                            -1);
+        g_free (l->data);
+    };
+    g_list_free (items);
+}
+
+
+/* ------- UI functions & callbacks ------ */
+
+static void 
+load_layout_cb (GtkWidget *w,
+                gpointer   data)
+{
+    GdlDockLayoutUIData *ui_data = (GdlDockLayoutUIData *) data;
+
+    GtkTreeModel  *model;
+    GtkTreeIter    iter;
+    GdlDockLayout *layout = ui_data->layout;
+    gchar         *name;
+
+    g_return_if_fail (layout != NULL);
+    
+    if (gtk_tree_selection_get_selected (ui_data->selection, &model, &iter)) {
+        gtk_tree_model_get (model, &iter,
+                            COLUMN_NAME, &name,
+                            -1);
+        gdl_dock_layout_load_layout (layout, name);
+        g_free (name);
+    }
+}
+
+static void
+delete_layout_cb (GtkWidget *w, gpointer data)
+{
+    GdlDockLayoutUIData *ui_data = (GdlDockLayoutUIData *) data;
+
+    GtkTreeModel  *model;
+    GtkTreeIter    iter;
+    GdlDockLayout *layout = ui_data->layout;
+    gchar         *name;
+
+    g_return_if_fail (layout != NULL);
+    
+    if (gtk_tree_selection_get_selected (ui_data->selection, &model, &iter)) {
+        gtk_tree_model_get (model, &iter,
+                            COLUMN_NAME, &name,
+                            -1);
+        gdl_dock_layout_delete_layout (layout, name);
+        gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+        g_free (name);
+    };
+}
+
+static void
+show_toggled_cb (GtkCellRendererToggle *renderer,
+                 gchar                 *path_str,
+                 gpointer               data)
+{
+    GdlDockLayoutUIData *ui_data = (GdlDockLayoutUIData *) data;
+
+    GdlDockLayout *layout = ui_data->layout;
+    GtkTreeModel  *model;
+    GtkTreeIter    iter;
+    GtkTreePath   *path = gtk_tree_path_new_from_string (path_str);
+    gboolean       value;
+    GdlDockItem   *item;
+
+    g_return_if_fail (layout != NULL);
+    
+    model = GTK_TREE_MODEL (layout->_priv->items_model);
+    gtk_tree_model_get_iter (model, &iter, path);
+    gtk_tree_model_get (model, &iter, 
+                        COLUMN_SHOW, &value, 
+                        COLUMN_ITEM, &item, 
+                        -1);
+
+    value = !value;
+    if (value)
+        gdl_dock_item_show_item (item);
+    else
+        gdl_dock_item_hide_item (item);
+
+    gtk_tree_path_free (path);
+}
+
+static void
+all_locked_toggled_cb (GtkWidget *widget,
+                       gpointer   data)
+{
+    GdlDockLayoutUIData *ui_data = (GdlDockLayoutUIData *) data;
+    GdlDockMaster       *master;
+    gboolean             locked;
+    
+    g_return_if_fail (ui_data->layout != NULL);
+    master = ui_data->layout->master;
+    g_return_if_fail (master != NULL);
+
+    locked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+    g_object_set (master, "locked", locked ? 1 : 0, NULL);
+}
+
+static void
+layout_ui_destroyed (GtkWidget *widget,
+                     gpointer   user_data)
+{
+    GdlDockLayoutUIData *ui_data;
+    
+    /* widget is the GtkContainer */
+    ui_data = g_object_get_data (G_OBJECT (widget), "ui_data");
+    if (ui_data) {
+        if (ui_data->layout) {
+            if (ui_data->layout->master)
+                /* disconnet the notify handler */
+                g_signal_handlers_disconnect_matched (ui_data->layout->master,
+                                                      G_SIGNAL_MATCH_DATA,
+                                                      0, 0, NULL, NULL,
+                                                      ui_data);
+            
+            g_object_remove_weak_pointer (G_OBJECT (ui_data->layout),
+                                          (gpointer *) &ui_data->layout);
+            ui_data->layout = NULL;
+        }
+        g_object_set_data (G_OBJECT (widget), "ui_data", NULL);
+        g_free (ui_data);
+    }
+}
+
+static void
+master_locked_notify_cb (GdlDockMaster *master,
+                         GParamSpec    *pspec,
+                         gpointer       user_data)
+{
+    GdlDockLayoutUIData *ui_data = (GdlDockLayoutUIData *) user_data;
+    gint locked;
+
+    g_object_get (master, "locked", &locked, NULL);
+    if (locked == -1) {
+        gtk_toggle_button_set_inconsistent (
+            GTK_TOGGLE_BUTTON (ui_data->locked_check), TRUE);
+    }
+    else {
+        gtk_toggle_button_set_inconsistent (
+            GTK_TOGGLE_BUTTON (ui_data->locked_check), FALSE);
+        gtk_toggle_button_set_active (
+            GTK_TOGGLE_BUTTON (ui_data->locked_check), (locked == 1));
+    }
+}
+
+static GladeXML *
+load_interface (const gchar *top_widget)
+{
+    GladeXML *gui;
+    gchar    *gui_file;
+
+    /* load ui */
+    gui_file = g_build_filename (GDL_GLADEDIR, LAYOUT_GLADE_FILE, NULL);
+    gui = glade_xml_new (gui_file, top_widget, GETTEXT_PACKAGE);
+    g_free (gui_file);
+    if (!gui) {
+        /* FIXME: pop up an error dialog */
+        g_warning (_("Could not load layout user interface file '%s'"), 
+                   LAYOUT_GLADE_FILE);
+        return NULL;
+    };
+    return gui;
+}
+
+static GtkWidget *
+gdl_dock_layout_construct_items_ui (GdlDockLayout *layout)
+{
+    GladeXML            *gui;
+    GtkWidget           *container;
+    GtkWidget           *items_list;
+    GtkCellRenderer     *renderer;
+    GtkTreeViewColumn   *column;
+
+    GdlDockLayoutUIData *ui_data;
+    
+    /* load the interface if it wasn't provided */
+    gui = load_interface ("items_vbox");
+    
+    if (!gui)
+        return NULL;
+    
+    /* get the container */
+    container = glade_xml_get_widget (gui, "items_vbox");
+
+    ui_data = g_new0 (GdlDockLayoutUIData, 1);
+    ui_data->layout = layout;
+    g_object_add_weak_pointer (G_OBJECT (layout),
+                               (gpointer *) &ui_data->layout);
+    g_object_set_data (G_OBJECT (container), "ui_data", ui_data);
+    
+    /* get ui widget references */
+    ui_data->locked_check = glade_xml_get_widget (gui, "locked_check");
+    items_list = glade_xml_get_widget (gui, "items_list");
+
+    /* locked check connections */
+    g_signal_connect (ui_data->locked_check, "toggled",
+                      (GCallback) all_locked_toggled_cb, ui_data);
+    if (layout->master) {
+        g_signal_connect (layout->master, "notify::locked",
+                          (GCallback) master_locked_notify_cb, ui_data);
+        /* force update now */
+        master_locked_notify_cb (layout->master, NULL, ui_data);
+    }
+    
+    /* set models */
+    gtk_tree_view_set_model (GTK_TREE_VIEW (items_list),
+                             GTK_TREE_MODEL (layout->_priv->items_model));
+
+    /* construct list views */
+    renderer = gtk_cell_renderer_toggle_new ();
+    g_signal_connect (renderer, "toggled", 
+                      G_CALLBACK (show_toggled_cb), ui_data);
+    column = gtk_tree_view_column_new_with_attributes (_("Visible"),
+                                                       renderer,
+                                                       "active", COLUMN_SHOW,
+                                                       NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (items_list), column);
+
+    renderer = gtk_cell_renderer_text_new ();
+    column = gtk_tree_view_column_new_with_attributes (_("Item"),
+                                                       renderer,
+                                                       "text", COLUMN_NAME,
+                                                       NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (items_list), column);
+
+    /* connect signals */
+    g_signal_connect (container, "destroy", (GCallback) layout_ui_destroyed, NULL);
+
+    g_object_unref (gui);
+
+    return container;
+}
+
+static void
+cell_edited_cb (GtkCellRendererText *cell,
+                const gchar         *path_string,
+                const gchar         *new_text,
+                gpointer             data)
+{
+    GdlDockLayoutUIData *ui_data = data;
+    GtkTreeModel *model;
+    GtkTreePath *path;
+    GtkTreeIter iter;
+    gchar *name;
+    xmlNodePtr node;
+
+    model = GTK_TREE_MODEL (ui_data->layout->_priv->layouts_model);
+    path = gtk_tree_path_new_from_string (path_string);
+
+    gtk_tree_model_get_iter (model, &iter, path);
+    gtk_tree_model_get (model, &iter, COLUMN_NAME, &name, -1);
+
+    node = gdl_dock_layout_find_layout (ui_data->layout, name);
+    g_free (name);
+    g_return_if_fail (node != NULL);
+
+    xmlSetProp (node, NAME_ATTRIBUTE_NAME, new_text);
+    gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_NAME, new_text,
+                        COLUMN_EDITABLE, TRUE, -1);
+
+    gdl_dock_layout_save_layout (ui_data->layout, new_text);
+
+    gtk_tree_path_free (path);
+}
+
+static GtkWidget *
+gdl_dock_layout_construct_layouts_ui (GdlDockLayout *layout)
+{
+    GladeXML            *gui;
+    GtkWidget           *container;
+    GtkWidget           *layouts_list;
+    GtkCellRenderer     *renderer;
+    GtkTreeViewColumn   *column;
+
+    GdlDockLayoutUIData *ui_data;
+    
+    /* load the interface if it wasn't provided */
+    gui = load_interface ("layouts_vbox");
+    
+    if (!gui)
+        return NULL;
+    
+    /* get the container */
+    container = glade_xml_get_widget (gui, "layouts_vbox");
+
+    ui_data = g_new0 (GdlDockLayoutUIData, 1);
+    ui_data->layout = layout;
+    g_object_add_weak_pointer (G_OBJECT (layout),
+                               (gpointer *) &ui_data->layout);
+    g_object_set_data (G_OBJECT (container), "ui_data", ui_data);
+    
+    /* get ui widget references */
+    layouts_list = glade_xml_get_widget (gui, "layouts_list");
+
+    /* set models */
+    gtk_tree_view_set_model (GTK_TREE_VIEW (layouts_list),
+                             GTK_TREE_MODEL (layout->_priv->layouts_model));
+
+    /* construct list views */
+    renderer = gtk_cell_renderer_text_new ();
+    g_signal_connect (G_OBJECT (renderer), "edited",
+                      G_CALLBACK (cell_edited_cb), ui_data);
+    column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer,
+                                                       "text", COLUMN_NAME,
+                                                       "editable", COLUMN_EDITABLE,
+                                                       NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (layouts_list), column);
+
+    ui_data->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (layouts_list));
+
+    /* connect signals */
+    glade_xml_signal_connect_data (gui, "on_load_button_clicked",
+                                   GTK_SIGNAL_FUNC (load_layout_cb), ui_data);
+    glade_xml_signal_connect_data (gui, "on_delete_button_clicked",
+                                   GTK_SIGNAL_FUNC (delete_layout_cb), ui_data);
+
+    g_signal_connect (container, "destroy", (GCallback) layout_ui_destroyed, NULL);
+
+    g_object_unref (gui);
+
+    return container;
+}
+
+static GtkWidget *
+gdl_dock_layout_construct_ui (GdlDockLayout *layout)
+{
+    GtkWidget *container, *child;
+    
+    container = gtk_notebook_new ();
+    gtk_widget_show (container);
+    
+    child = gdl_dock_layout_construct_items_ui (layout);
+    if (child)
+        gtk_notebook_append_page (GTK_NOTEBOOK (container),
+                                  child,
+                                  gtk_label_new (_("Dock items")));
+    
+    child = gdl_dock_layout_construct_layouts_ui (layout);
+    if (child)
+        gtk_notebook_append_page (GTK_NOTEBOOK (container),
+                                  child,
+                                  gtk_label_new (_("Saved layouts")));
+
+    gtk_notebook_set_current_page (GTK_NOTEBOOK (container), 0);
+    
+    return container;
+}
+
+/* ----- Save & Load layout functions --------- */
+
+#define GDL_DOCK_PARAM_CONSTRUCTION(p) \
+    (((p)->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) != 0)
+
+static GdlDockObject * 
+gdl_dock_layout_setup_object (GdlDockMaster *master,
+                              xmlNodePtr     node,
+                              gint          *n_after_params,
+                              GParameter   **after_params)
+{
+    GdlDockObject *object = NULL;
+    GType          object_type;
+    xmlChar       *object_name;
+    GObjectClass  *object_class = NULL;
+
+    GParamSpec   **props;
+    gint           n_props, i;
+    GParameter    *params = NULL;
+    gint           n_params = 0;
+    GValue         serialized = { 0, };
+    
+    object_name = xmlGetProp (node, GDL_DOCK_NAME_PROPERTY);
+    if (object_name && strlen (object_name) > 0) {
+        /* the object must already be bound to the master */
+        object = gdl_dock_master_get_object (master, object_name);
+
+        xmlFree (object_name);
+        object_type = object ? G_TYPE_FROM_INSTANCE (object) : G_TYPE_NONE;
+    }
+    else {
+        /* the object should be automatic, so create it by
+           retrieving the object type from the dock registry */
+        object_type = gdl_dock_object_type_from_nick (node->name);
+        if (object_type == G_TYPE_NONE) {
+            g_warning (_("While loading layout: don't know how to create "
+                         "a dock object whose nick is '%s'"), node->name);
+        }
+    }
+    
+    if (object_type == G_TYPE_NONE || !G_TYPE_IS_CLASSED (object_type))
+        return NULL;
+
+    object_class = g_type_class_ref (object_type);
+    props = g_object_class_list_properties (object_class, &n_props);
+        
+    /* create parameter slots */
+    /* extra parameter is the master */
+    params = g_new0 (GParameter, n_props + 1);
+    *after_params = g_new0 (GParameter, n_props);
+    *n_after_params = 0;
+    
+    /* initialize value used for transformations */
+    g_value_init (&serialized, GDL_TYPE_DOCK_PARAM);
+    
+    for (i = 0; i < n_props; i++) {
+        xmlChar *xml_prop;
+
+        /* process all exported properties, skip
+           GDL_DOCK_NAME_PROPERTY, since named items should
+           already by in the master */
+        if (!(props [i]->flags & GDL_DOCK_PARAM_EXPORT) ||
+            !strcmp (props [i]->name, GDL_DOCK_NAME_PROPERTY))
+            continue;
+
+        /* get the property from xml if there is one */
+        xml_prop = xmlGetProp (node, props [i]->name);
+        if (xml_prop) {
+            g_value_set_static_string (&serialized, xml_prop);
+            
+            if (!GDL_DOCK_PARAM_CONSTRUCTION (props [i]) &&
+                (props [i]->flags & GDL_DOCK_PARAM_AFTER)) {
+                (*after_params) [*n_after_params].name = props [i]->name;
+                g_value_init (&((* after_params) [*n_after_params].value),
+                              props [i]->value_type);
+                g_value_transform (&serialized,
+                                   &((* after_params) [*n_after_params].value));
+                (*n_after_params)++;
+            }
+            else if (!object || (!GDL_DOCK_PARAM_CONSTRUCTION (props [i]) && object)) {
+                params [n_params].name = props [i]->name;
+                g_value_init (&(params [n_params].value), props [i]->value_type);
+                g_value_transform (&serialized, &(params [n_params].value));
+                n_params++;
+            }
+            xmlFree (xml_prop);
+        }
+    }
+    g_value_unset (&serialized);
+    g_free (props);
+
+    if (!object) {
+        params [n_params].name = GDL_DOCK_MASTER_PROPERTY;
+        g_value_init (&params [n_params].value, GDL_TYPE_DOCK_MASTER);
+        g_value_set_object (&params [n_params].value, master);
+        n_params++;
+        
+        /* construct the object if we have to */
+        /* set the master, so toplevels are created correctly and
+           other objects are bound */
+        object = g_object_newv (object_type, n_params, params);
+    }
+    else {
+        /* set the parameters to the existing object */
+        for (i = 0; i < n_params; i++)
+            g_object_set_property (G_OBJECT (object),
+                                   params [i].name,
+                                   &params [i].value);
+    }
+
+    /* free the parameters (names are static/const strings) */
+    for (i = 0; i < n_params; i++)
+        g_value_unset (&params [i].value);
+    g_free (params);
+
+    /* finally unref object class */
+    g_type_class_unref (object_class);
+
+    return object;
+}
+
+static void
+gdl_dock_layout_recursive_build (GdlDockMaster *master,
+                                 xmlNodePtr     parent_node,
+                                 GdlDockObject *parent)
+{
+    GdlDockObject *object;
+    xmlNodePtr     node;
+    
+    g_return_if_fail (master != NULL && parent_node != NULL);
+
+    /* if parent is NULL we should build toplevels */
+    for (node = parent_node->children; node; node = node->next) {
+        GParameter *after_params = NULL;
+        gint        n_after_params = 0, i;
+
+        object = gdl_dock_layout_setup_object (master, node,
+                                               &n_after_params,
+                                               &after_params);
+        
+        if (object) {
+            gdl_dock_object_freeze (object);
+
+            /* recurse here to catch placeholders */
+            gdl_dock_layout_recursive_build (master, node, object);
+            
+            if (GDL_IS_DOCK_PLACEHOLDER (object))
+                /* placeholders are later attached to the parent */
+                gdl_dock_object_detach (object, FALSE);
+            
+            /* apply "after" parameters */
+            for (i = 0; i < n_after_params; i++) {
+                g_object_set_property (G_OBJECT (object),
+                                       after_params [i].name,
+                                       &after_params [i].value);
+                /* unset and free the value */
+                g_value_unset (&after_params [i].value);
+            }
+            g_free (after_params);
+            
+            /* add the object to the parent */
+            if (parent) {
+                if (GDL_IS_DOCK_PLACEHOLDER (object))
+                    gdl_dock_placeholder_attach (GDL_DOCK_PLACEHOLDER (object),
+                                                 parent);
+                else if (gdl_dock_object_is_compound (parent)) {
+                    gtk_container_add (GTK_CONTAINER (parent), GTK_WIDGET (object));
+                    if (GTK_WIDGET_VISIBLE (parent))
+                        gtk_widget_show (GTK_WIDGET (object));
+                }
+            }
+            else {
+                GdlDockObject *controller = gdl_dock_master_get_controller (master);
+                if (controller != object && GTK_WIDGET_VISIBLE (controller))
+                    gtk_widget_show (GTK_WIDGET (object));
+            }
+                
+            /* call reduce just in case any child is missing */
+            if (gdl_dock_object_is_compound (object))
+                gdl_dock_object_reduce (object);
+
+            gdl_dock_object_thaw (object);
+        }
+    }
+}
+
+static void
+_gdl_dock_layout_foreach_detach (GdlDockObject *object)
+{
+    gdl_dock_object_detach (object, TRUE);
+}
+
+static void
+gdl_dock_layout_foreach_toplevel_detach (GdlDockObject *object)
+{
+    gtk_container_foreach (GTK_CONTAINER (object),
+                           (GtkCallback) _gdl_dock_layout_foreach_detach,
+                           NULL);
+}
+
+static void
+gdl_dock_layout_load (GdlDockMaster *master, xmlNodePtr node)
+{
+    g_return_if_fail (master != NULL && node != NULL);
+
+    /* start by detaching all items from the toplevels */
+    gdl_dock_master_foreach_toplevel (master, TRUE,
+                                      (GFunc) gdl_dock_layout_foreach_toplevel_detach,
+                                      NULL);
+    
+    gdl_dock_layout_recursive_build (master, node, NULL);
+}
+
+static void 
+gdl_dock_layout_foreach_object_save (GdlDockObject *object,
+                                     gpointer       user_data)
+{
+    struct {
+        xmlNodePtr  where;
+        GHashTable *placeholders;
+    } *info = user_data, info_child;
+
+    xmlNodePtr   node;
+    gint         n_props, i;
+    GParamSpec **props;
+    GValue       attr = { 0, };
+    
+    g_return_if_fail (object != NULL && GDL_IS_DOCK_OBJECT (object));
+    g_return_if_fail (info->where != NULL);
+    
+    node = xmlNewChild (info->where,
+                        NULL,               /* ns */
+                        gdl_dock_object_nick_from_type (G_TYPE_FROM_INSTANCE (object)),
+                        NULL);              /* contents */
+
+    /* get object exported attributes */
+    props = g_object_class_list_properties (G_OBJECT_GET_CLASS (object),
+                                            &n_props);
+    g_value_init (&attr, GDL_TYPE_DOCK_PARAM);
+    for (i = 0; i < n_props; i++) {
+        GParamSpec *p = props [i];
+
+        if (p->flags & GDL_DOCK_PARAM_EXPORT) {
+            GValue v = { 0, };
+            
+            /* export this parameter */
+            /* get the parameter value */
+            g_value_init (&v, p->value_type);
+            g_object_get_property (G_OBJECT (object),
+                                   p->name,
+                                   &v);
+
+            /* only save the object "name" if it is set
+               (i.e. don't save the empty string) */
+            if (strcmp (p->name, GDL_DOCK_NAME_PROPERTY) ||
+                g_value_get_string (&v)) {
+                if (g_value_transform (&v, &attr))
+                    xmlSetProp (node, p->name, g_value_get_string (&attr));
+            }
+            
+            /* free the parameter value */
+            g_value_unset (&v);
+        }
+    }
+    g_value_unset (&attr);
+    g_free (props);
+
+    info_child = *info;
+    info_child.where = node;
+
+    /* save placeholders for the object */
+    if (info->placeholders && !GDL_IS_DOCK_PLACEHOLDER (object)) {
+        GList *lph = g_hash_table_lookup (info->placeholders, object);
+        for (; lph; lph = lph->next)
+            gdl_dock_layout_foreach_object_save (GDL_DOCK_OBJECT (lph->data),
+                                                 (gpointer) &info_child);
+    }
+    
+    /* recurse the object if appropiate */
+    if (gdl_dock_object_is_compound (object)) {
+        gtk_container_foreach (GTK_CONTAINER (object),
+                               (GtkCallback) gdl_dock_layout_foreach_object_save,
+                               (gpointer) &info_child);
+    }
+}
+
+static void
+add_placeholder (GdlDockObject *object,
+                 GHashTable    *placeholders)
+{
+    if (GDL_IS_DOCK_PLACEHOLDER (object)) {
+        GdlDockObject *host;
+        GList *l;
+        
+        g_object_get (object, "host", &host, NULL);
+        if (host) {
+            l = g_hash_table_lookup (placeholders, host);
+            /* add the current placeholder to the list of placeholders
+               for that host */
+            if (l)
+                g_hash_table_steal (placeholders, host);
+            
+            l = g_list_prepend (l, object);
+            g_hash_table_insert (placeholders, host, l);
+            g_object_unref (host);
+        }
+    }
+}
+
+static void 
+gdl_dock_layout_save (GdlDockMaster *master,
+                      xmlNodePtr     where)
+{
+    struct {
+        xmlNodePtr  where;
+        GHashTable *placeholders;
+    } info;
+    
+    GHashTable *placeholders;
+    
+    g_return_if_fail (master != NULL && where != NULL);
+
+    /* build the placeholder's hash: the hash keeps lists of
+     * placeholders associated to each object, so that we can save the
+     * placeholders when we are saving the object (since placeholders
+     * don't show up in the normal widget hierarchy) */
+    placeholders = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                          NULL, (GDestroyNotify) g_list_free);
+    gdl_dock_master_foreach (master, (GFunc) add_placeholder, placeholders);
+    
+    /* save the layout recursively */
+    info.where = where;
+    info.placeholders = placeholders;
+    
+    gdl_dock_master_foreach_toplevel (master, TRUE,
+                                      (GFunc) gdl_dock_layout_foreach_object_save,
+                                      (gpointer) &info);
+
+    g_hash_table_destroy (placeholders);
+}
+
+
+/* ----- Public interface ----- */
+
+GdlDockLayout *
+gdl_dock_layout_new (GdlDock *dock)
+{
+    GdlDockMaster *master = NULL;
+    
+    /* get the master of the given dock */
+    if (dock)
+        master = GDL_DOCK_OBJECT_GET_MASTER (dock);
+    
+    return g_object_new (GDL_TYPE_DOCK_LAYOUT,
+                         "master", master,
+                         NULL);
+}
+
+static gboolean
+gdl_dock_layout_idle_save (GdlDockLayout *layout)
+{
+    /* save default layout */
+    gdl_dock_layout_save_layout (layout, NULL);
+    
+    layout->_priv->idle_save_pending = FALSE;
+    
+    return FALSE;
+}
+
+static void
+gdl_dock_layout_layout_changed_cb (GdlDockMaster *master,
+                                   GdlDockLayout *layout)
+{
+    /* update model */
+    update_items_model (layout);
+
+    if (!layout->_priv->idle_save_pending) {
+        g_idle_add ((GSourceFunc) gdl_dock_layout_idle_save, layout);
+        layout->_priv->idle_save_pending = TRUE;
+    }
+}
+
+void
+gdl_dock_layout_attach (GdlDockLayout *layout,
+                        GdlDockMaster *master)
+{
+    g_return_if_fail (layout != NULL);
+    g_return_if_fail (master == NULL || GDL_IS_DOCK_MASTER (master));
+    
+    if (layout->master) {
+        g_signal_handlers_disconnect_matched (layout->master, G_SIGNAL_MATCH_DATA,
+                                              0, 0, NULL, NULL, layout);
+        g_object_unref (layout->master);
+    }
+    
+    gtk_list_store_clear (layout->_priv->items_model);
+    
+    layout->master = master;
+    if (layout->master) {
+        g_object_ref (layout->master);
+        g_signal_connect (layout->master, "layout_changed",
+                          (GCallback) gdl_dock_layout_layout_changed_cb,
+                          layout);
+    }
+
+    update_items_model (layout);
+}
+
+gboolean
+gdl_dock_layout_load_layout (GdlDockLayout *layout,
+                             const gchar   *name)
+{
+    xmlNodePtr  node;
+    gchar      *layout_name;
+
+    g_return_val_if_fail (layout != NULL, FALSE);
+    
+    if (!layout->_priv->doc || !layout->master)
+        return FALSE;
+
+    if (!name)
+        layout_name = DEFAULT_LAYOUT;
+    else
+        layout_name = (gchar *) name;
+
+    node = gdl_dock_layout_find_layout (layout, layout_name);
+    if (!node && !name)
+        /* return the first layout if the default name failed to load */
+        node = gdl_dock_layout_find_layout (layout, NULL);
+
+    if (node) {
+        gdl_dock_layout_load (layout->master, node);
+        return TRUE;
+    } else
+        return FALSE;
+}
+
+void
+gdl_dock_layout_save_layout (GdlDockLayout *layout,
+                             const gchar   *name)
+{
+    xmlNodePtr  node;
+    gchar      *layout_name;
+
+    g_return_if_fail (layout != NULL);
+    g_return_if_fail (layout->master != NULL);
+    
+    if (!layout->_priv->doc)
+        gdl_dock_layout_build_doc (layout);
+
+    if (!name)
+        layout_name = DEFAULT_LAYOUT;
+    else
+        layout_name = (gchar *) name;
+
+    /* delete any previously node with the same name */
+    node = gdl_dock_layout_find_layout (layout, layout_name);
+    if (node) {
+        xmlUnlinkNode (node);
+        xmlFreeNode (node);
+    };
+
+    /* create the new node */
+    node = xmlNewChild (layout->_priv->doc->children, NULL, 
+                        LAYOUT_ELEMENT_NAME, NULL);
+    xmlSetProp (node, NAME_ATTRIBUTE_NAME, layout_name);
+
+    /* save the layout */
+    gdl_dock_layout_save (layout->master, node);
+    layout->dirty = TRUE;
+    g_object_notify (G_OBJECT (layout), "dirty");
+}
+
+void
+gdl_dock_layout_delete_layout (GdlDockLayout *layout,
+                               const gchar   *name)
+{
+    xmlNodePtr node;
+
+    g_return_if_fail (layout != NULL);
+
+    /* don't allow the deletion of the default layout */
+    if (!name || !strcmp (DEFAULT_LAYOUT, name))
+        return;
+    
+    node = gdl_dock_layout_find_layout (layout, name);
+    if (node) {
+        xmlUnlinkNode (node);
+        xmlFreeNode (node);
+        layout->dirty = TRUE;
+        g_object_notify (G_OBJECT (layout), "dirty");
+    }
+}
+
+void
+gdl_dock_layout_run_manager (GdlDockLayout *layout)
+{
+    GtkWidget *dialog, *container;
+    GtkWidget *parent = NULL;
+    
+    g_return_if_fail (layout != NULL);
+
+    if (!layout->master)
+        /* not attached to a dock yet */
+        return;
+
+    container = gdl_dock_layout_construct_ui (layout);
+    if (!container)
+        return;
+
+    parent = GTK_WIDGET (gdl_dock_master_get_controller (layout->master));
+    if (parent)
+        parent = gtk_widget_get_toplevel (parent);
+    
+    dialog = gtk_dialog_new_with_buttons (_("Layout managment"),
+                                          parent ? GTK_WINDOW (parent) : NULL,
+                                          GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
+                                          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+                                          NULL);
+
+    gtk_window_set_default_size (GTK_WINDOW (dialog), -1, 300);
+    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), container);
+    
+    gtk_dialog_run (GTK_DIALOG (dialog));
+
+    gtk_widget_destroy (dialog);
+}
+
+gboolean
+gdl_dock_layout_load_from_file (GdlDockLayout *layout,
+                                const gchar   *filename)
+{
+    gboolean retval = FALSE;
+
+    if (layout->_priv->doc) {
+        xmlFreeDoc (layout->_priv->doc);
+        layout->_priv->doc = NULL;
+        layout->dirty = FALSE;
+        g_object_notify (G_OBJECT (layout), "dirty");
+    }
+
+    /* FIXME: cannot open symlinks */
+    if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
+        layout->_priv->doc = xmlParseFile (filename);
+        if (layout->_priv->doc) {
+            xmlNodePtr root = layout->_priv->doc->children;
+            /* minimum validation: test the root element */
+            if (root && !strcmp (root->name, ROOT_ELEMENT)) {
+                update_layouts_model (layout);
+                retval = TRUE;
+            } else {
+                xmlFreeDoc (layout->_priv->doc);
+                layout->_priv->doc = NULL;
+            }		
+        }
+    }
+
+    return retval;
+}
+
+gboolean
+gdl_dock_layout_save_to_file (GdlDockLayout *layout,
+                              const gchar   *filename)
+{
+    FILE     *file_handle;
+    int       bytes;
+    gboolean  retval = FALSE;
+
+    g_return_val_if_fail (layout != NULL, FALSE);
+    g_return_val_if_fail (filename != NULL, FALSE);
+
+    /* if there is still no xml doc, create an empty one */
+    if (!layout->_priv->doc)
+        gdl_dock_layout_build_doc (layout);
+
+    file_handle = fopen (filename, "w");
+    if (file_handle) {
+        bytes = xmlDocDump (file_handle, layout->_priv->doc);
+        if (bytes >= 0) {
+            layout->dirty = FALSE;
+            g_object_notify (G_OBJECT (layout), "dirty");
+            retval = TRUE;
+        };
+        fclose (file_handle);
+    };
+
+    return retval;
+}
+
+gboolean
+gdl_dock_layout_is_dirty (GdlDockLayout *layout)
+{
+    g_return_val_if_fail (layout != NULL, FALSE);
+
+    return layout->dirty;
+};
+
+GList *
+gdl_dock_layout_get_layouts (GdlDockLayout *layout,
+                             gboolean       include_default)
+{
+    GList      *retval = NULL;
+    xmlNodePtr  node;
+
+    g_return_val_if_fail (layout != NULL, NULL);
+
+    if (!layout->_priv->doc)
+        return NULL;
+
+    node = layout->_priv->doc->children;
+    for (node = node->children; node; node = node->next) {
+        gchar *name;
+
+        if (strcmp (node->name, LAYOUT_ELEMENT_NAME))
+            continue;
+
+        name = xmlGetProp (node, NAME_ATTRIBUTE_NAME);
+        if (include_default || strcmp (name, DEFAULT_LAYOUT))
+            retval = g_list_prepend (retval, g_strdup (name));
+        xmlFree (name);
+    };
+    retval = g_list_reverse (retval);
+
+    return retval;
+}
+
+GtkWidget *
+gdl_dock_layout_get_ui (GdlDockLayout *layout)
+{
+    GtkWidget *ui;
+
+    g_return_val_if_fail (layout != NULL, NULL);
+    ui = gdl_dock_layout_construct_ui (layout);
+
+    return ui;
+}
+
+GtkWidget *
+gdl_dock_layout_get_items_ui (GdlDockLayout *layout)
+{
+    GtkWidget *ui;
+
+    g_return_val_if_fail (layout != NULL, NULL);
+    ui = gdl_dock_layout_construct_items_ui (layout);
+
+    return ui;
+}
+
+GtkWidget *
+gdl_dock_layout_get_layouts_ui (GdlDockLayout *layout)
+{
+    GtkWidget *ui;
+
+    g_return_val_if_fail (layout != NULL, NULL);
+    ui = gdl_dock_layout_construct_layouts_ui (layout);
+
+    return ui;
+}

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-layout.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+
+#ifndef __GDL_DOCK_LAYOUT_H__
+#define __GDL_DOCK_LAYOUT_H__
+
+#include <glib-object.h>
+#include <gdl/gdl-dock-master.h>
+#include <gdl/gdl-dock.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define	GDL_TYPE_DOCK_LAYOUT		  (gdl_dock_layout_get_type ())
+#define GDL_DOCK_LAYOUT(object)		  (GTK_CHECK_CAST ((object), GDL_TYPE_DOCK_LAYOUT, GdlDockLayout))
+#define GDL_DOCK_LAYOUT_CLASS(klass)	  (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_LAYOUT, GdlDockLayoutClass))
+#define GDL_IS_DOCK_LAYOUT(object)	  (GTK_CHECK_TYPE ((object), GDL_TYPE_DOCK_LAYOUT))
+#define GDL_IS_DOCK_LAYOUT_CLASS(klass)	  (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_LAYOUT))
+#define	GDL_DOCK_LAYOUT_GET_CLASS(object) (GTK_CHECK_GET_CLASS ((object), GDL_TYPE_DOCK_LAYOUT, GdlDockLayoutClass))
+
+/* data types & structures */
+typedef struct _GdlDockLayout GdlDockLayout;
+typedef struct _GdlDockLayoutClass GdlDockLayoutClass;
+typedef struct _GdlDockLayoutPrivate GdlDockLayoutPrivate;
+
+struct _GdlDockLayout {
+    GObject               g_object;
+
+    gboolean              dirty;
+    GdlDockMaster        *master;
+
+    GdlDockLayoutPrivate *_priv;
+};
+
+struct _GdlDockLayoutClass {
+    GObjectClass  g_object_class;
+};
+
+
+/* public interface */
+ 
+GType            gdl_dock_layout_get_type       (void);
+
+GdlDockLayout   *gdl_dock_layout_new            (GdlDock       *dock);
+
+void             gdl_dock_layout_attach         (GdlDockLayout *layout,
+                                                 GdlDockMaster *master);
+
+gboolean         gdl_dock_layout_load_layout    (GdlDockLayout *layout,
+                                                 const gchar   *name);
+
+void             gdl_dock_layout_save_layout    (GdlDockLayout *layout,
+                                                 const gchar   *name);
+
+void             gdl_dock_layout_delete_layout  (GdlDockLayout *layout,
+                                                 const gchar   *name);
+
+GList           *gdl_dock_layout_get_layouts    (GdlDockLayout *layout,
+                                                 gboolean       include_default);
+
+void             gdl_dock_layout_run_manager    (GdlDockLayout *layout);
+
+gboolean         gdl_dock_layout_load_from_file (GdlDockLayout *layout,
+                                                 const gchar   *filename);
+
+gboolean         gdl_dock_layout_save_to_file   (GdlDockLayout *layout,
+                                                 const gchar   *filename);
+
+gboolean         gdl_dock_layout_is_dirty       (GdlDockLayout *layout);
+
+GtkWidget       *gdl_dock_layout_get_ui         (GdlDockLayout *layout);
+GtkWidget       *gdl_dock_layout_get_items_ui   (GdlDockLayout *layout);
+GtkWidget       *gdl_dock_layout_get_layouts_ui (GdlDockLayout *layout);
+
+G_END_DECLS
+
+#endif
+
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,908 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-master.c - Object which manages a dock ring
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <libgnome/gnome-macros.h>
+#include <gdk/gdkx.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock-master.h"
+#include "gdl-dock.h"
+#include "gdl-dock-item.h"
+#include "libgdlmarshal.h"
+
+
+/* ----- Private prototypes ----- */
+
+static void     gdl_dock_master_class_init    (GdlDockMasterClass *klass);
+static void     gdl_dock_master_instance_init (GdlDockMaster      *master);
+
+static void     gdl_dock_master_dispose       (GObject            *g_object);
+static void     gdl_dock_master_set_property  (GObject            *object,
+                                               guint               prop_id,
+                                               const GValue       *value,
+                                               GParamSpec         *pspec);
+static void     gdl_dock_master_get_property  (GObject            *object,
+                                               guint               prop_id,
+                                               GValue             *value,
+                                               GParamSpec         *pspec);
+
+static void     _gdl_dock_master_remove       (GdlDockObject      *object,
+                                               GdlDockMaster      *master);
+
+static void     gdl_dock_master_drag_begin    (GdlDockItem        *item, 
+                                               gpointer            data);
+static void     gdl_dock_master_drag_end      (GdlDockItem        *item,
+                                               gboolean            cancelled,
+                                               gpointer            data);
+static void     gdl_dock_master_drag_motion   (GdlDockItem        *item, 
+                                               gint                x, 
+                                               gint                y,
+                                               gpointer            data);
+
+static void     _gdl_dock_master_foreach      (gpointer            key,
+                                               gpointer            value,
+                                               gpointer            user_data);
+
+static void     gdl_dock_master_xor_rect      (GdlDockMaster      *master);
+
+static void     gdl_dock_master_layout_changed (GdlDockMaster     *master);
+
+/* ----- Private data types and variables ----- */
+
+enum {
+    PROP_0,
+    PROP_DEFAULT_TITLE,
+    PROP_LOCKED
+};
+
+enum {
+    LAYOUT_CHANGED,
+    LAST_SIGNAL
+};
+
+struct _GdlDockMasterPrivate {
+    gint            number;             /* for naming nameless manual objects */
+    gchar          *default_title;
+    
+    GdkGC          *root_xor_gc;
+    gboolean        rect_drawn;
+    GdlDock        *rect_owner;
+    
+    GdlDockRequest *drag_request;
+
+    /* source id for the idle handler to emit a layout_changed signal */
+    guint           idle_layout_changed_id;
+
+    /* hashes to quickly calculate the overall locked status: i.e.
+     * if size(unlocked_items) == 0 then locked = 1
+     * else if size(locked_items) == 0 then locked = 0
+     * else locked = -1
+     */
+    GHashTable     *locked_items;
+    GHashTable     *unlocked_items;
+};
+
+#define COMPUTE_LOCKED(master)                                          \
+    (g_hash_table_size ((master)->_priv->unlocked_items) == 0 ? 1 :     \
+     (g_hash_table_size ((master)->_priv->locked_items) == 0 ? 0 : -1))
+
+static guint master_signals [LAST_SIGNAL] = { 0 };
+
+
+/* ----- Private interface ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockMaster, gdl_dock_master, GObject, G_TYPE_OBJECT);
+
+static void
+gdl_dock_master_class_init (GdlDockMasterClass *klass)
+{
+    GObjectClass      *g_object_class;
+
+    g_object_class = G_OBJECT_CLASS (klass);
+
+    g_object_class->dispose = gdl_dock_master_dispose;
+    g_object_class->set_property = gdl_dock_master_set_property;
+    g_object_class->get_property = gdl_dock_master_get_property;
+
+    g_object_class_install_property (
+        g_object_class, PROP_DEFAULT_TITLE,
+        g_param_spec_string ("default_title", _("Default title"),
+                             _("Default title for newly created floating docks"),
+                             NULL,
+                             G_PARAM_READWRITE));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_LOCKED,
+        g_param_spec_int ("locked", _("Locked"),
+                          _("If is set to 1, all the dock items bound to the master "
+                            "are locked; if it's 0, all are unlocked; -1 indicates "
+                            "inconsistency among the items"),
+                          -1, 1, 0,
+                          G_PARAM_READWRITE));
+
+    master_signals [LAYOUT_CHANGED] = 
+        g_signal_new ("layout_changed", 
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (GdlDockMasterClass, layout_changed),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__VOID,
+                      G_TYPE_NONE, /* return type */
+                      0);
+
+    klass->layout_changed = gdl_dock_master_layout_changed;
+}
+
+static void
+gdl_dock_master_instance_init (GdlDockMaster *master)
+{
+    master->dock_objects = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  g_free, NULL);
+    master->toplevel_docks = NULL;
+    master->controller = NULL;
+    master->dock_number = 1;
+    
+    master->_priv = g_new0 (GdlDockMasterPrivate, 1);
+    master->_priv->number = 1;
+
+    master->_priv->locked_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+    master->_priv->unlocked_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+static void
+_gdl_dock_master_remove (GdlDockObject *object,
+                         GdlDockMaster *master)
+{
+    g_return_if_fail (master != NULL && object != NULL);
+
+    if (GDL_IS_DOCK (object)) {
+        GList *found_link;
+
+        found_link = g_list_find (master->toplevel_docks, object);
+        if (found_link)
+            master->toplevel_docks = g_list_delete_link (master->toplevel_docks,
+                                                         found_link);
+        if (object == master->controller) {
+            GList *last;
+            GdlDockObject *new_controller = NULL;
+            
+            /* now find some other non-automatic toplevel to use as a
+               new controller.  start from the last dock, since it's
+               probably a non-floating and manual */
+            last = g_list_last (master->toplevel_docks);
+            while (last) {
+                if (!GDL_DOCK_OBJECT_AUTOMATIC (last->data)) {
+                    new_controller = GDL_DOCK_OBJECT (last->data);
+                    break;
+                }
+                last = last->prev;
+            };
+
+            if (new_controller) {
+                /* the new controller gets the ref (implicitly of course) */
+                master->controller = new_controller;
+            } else {
+                master->controller = NULL;
+                /* no controller, no master */
+                g_object_unref (master);
+            }
+        }
+    }
+    /* disconnect dock object signals */
+    g_signal_handlers_disconnect_matched (object, G_SIGNAL_MATCH_DATA, 
+                                          0, 0, NULL, NULL, master);
+
+    /* unref the object from the hash if it's there */
+    if (object->name) {
+        GdlDockObject *found_object;
+        found_object = g_hash_table_lookup (master->dock_objects, object->name);
+        if (found_object == object) {
+            g_hash_table_remove (master->dock_objects, object->name);
+            g_object_unref (object);
+        }
+    }
+}
+
+static void
+ht_foreach_build_slist (gpointer  key,
+                        gpointer  value,
+                        GSList  **slist)
+{
+    *slist = g_slist_prepend (*slist, value);
+}
+
+static void
+gdl_dock_master_dispose (GObject *g_object)
+{
+    GdlDockMaster *master;
+    
+    g_return_if_fail (GDL_IS_DOCK_MASTER (g_object));
+
+    master = GDL_DOCK_MASTER (g_object);
+
+    if (master->toplevel_docks) {
+        g_list_foreach (master->toplevel_docks,
+                        (GFunc) gdl_dock_object_unbind, NULL);
+        g_list_free (master->toplevel_docks);
+        master->toplevel_docks = NULL;
+    }
+    
+    if (master->dock_objects) {
+        GSList *alive_docks = NULL;
+        g_hash_table_foreach (master->dock_objects,
+                              (GHFunc) ht_foreach_build_slist, &alive_docks);
+        while (alive_docks) {
+            gdl_dock_object_unbind (GDL_DOCK_OBJECT (alive_docks->data));
+            alive_docks = g_slist_delete_link (alive_docks, alive_docks);
+        }
+        
+        g_hash_table_destroy (master->dock_objects);
+        master->dock_objects = NULL;
+    }
+    
+    if (master->_priv) {
+        if (master->_priv->idle_layout_changed_id)
+            g_source_remove (master->_priv->idle_layout_changed_id);
+        
+        if (master->_priv->root_xor_gc) {
+            g_object_unref (master->_priv->root_xor_gc);
+            master->_priv->root_xor_gc = NULL;
+        }
+        if (master->_priv->drag_request) {
+            if (G_IS_VALUE (&master->_priv->drag_request->extra))
+                g_value_unset (&master->_priv->drag_request->extra);
+            g_free (master->_priv->drag_request);
+            master->_priv->drag_request = NULL;
+        }
+        g_free (master->_priv->default_title);
+        master->_priv->default_title = NULL;
+
+        g_hash_table_destroy (master->_priv->locked_items);
+        master->_priv->locked_items = NULL;
+        g_hash_table_destroy (master->_priv->unlocked_items);
+        master->_priv->unlocked_items = NULL;
+        
+        g_free (master->_priv);
+        master->_priv = NULL;
+    }
+
+    GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (g_object));
+}
+
+static void 
+foreach_lock_unlock (GdlDockItem *item,
+                     gboolean     locked)
+{
+    if (!GDL_IS_DOCK_ITEM (item))
+        return;
+    
+    g_object_set (item, "locked", locked, NULL);
+    if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (item)))
+        gtk_container_foreach (GTK_CONTAINER (item),
+                               (GtkCallback) foreach_lock_unlock,
+                               (gpointer) locked);
+}
+
+static void
+gdl_dock_master_lock_unlock (GdlDockMaster *master,
+                             gboolean       locked)
+{
+    GList *l;
+    
+    for (l = master->toplevel_docks; l; l = l->next) {
+        GdlDock *dock = GDL_DOCK (l->data);
+        if (dock->root)
+            foreach_lock_unlock (GDL_DOCK_ITEM (dock->root), locked);
+    }
+
+    /* just to be sure hidden items are set too */
+    gdl_dock_master_foreach (master,
+                             (GFunc) foreach_lock_unlock,
+                             (gpointer) locked);
+}
+
+static void
+gdl_dock_master_set_property  (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+    GdlDockMaster *master = GDL_DOCK_MASTER (object);
+
+    switch (prop_id) {
+        case PROP_DEFAULT_TITLE:
+            g_free (master->_priv->default_title);
+            master->_priv->default_title = g_value_dup_string (value);
+            break;
+        case PROP_LOCKED:
+            if (g_value_get_int (value) >= 0)
+                gdl_dock_master_lock_unlock (master, (g_value_get_int (value) > 0));
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_master_get_property  (GObject      *object,
+                               guint         prop_id,
+                               GValue       *value,
+                               GParamSpec   *pspec)
+{
+    GdlDockMaster *master = GDL_DOCK_MASTER (object);
+
+    switch (prop_id) {
+        case PROP_DEFAULT_TITLE:
+            g_value_set_string (value, master->_priv->default_title);
+            break;
+        case PROP_LOCKED:
+            g_value_set_int (value, COMPUTE_LOCKED (master));
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_master_drag_begin (GdlDockItem *item,
+                            gpointer     data)
+{
+    GdlDockMaster  *master;
+    GdlDockRequest *request;
+    
+    g_return_if_fail (data != NULL);
+    g_return_if_fail (item != NULL);
+
+    master = GDL_DOCK_MASTER (data);
+
+    if (!master->_priv->drag_request)
+        master->_priv->drag_request = g_new0 (GdlDockRequest, 1);
+
+    request = master->_priv->drag_request;
+    
+    /* Set the target to itself so it won't go floating with just a click. */
+    request->applicant = GDL_DOCK_OBJECT (item);
+    request->target = GDL_DOCK_OBJECT (item);
+    request->position = GDL_DOCK_FLOATING;
+    if (G_IS_VALUE (&request->extra))
+        g_value_unset (&request->extra);
+
+    master->_priv->rect_drawn = FALSE;
+    master->_priv->rect_owner = NULL;
+}
+
+static void
+gdl_dock_master_drag_end (GdlDockItem *item, 
+                          gboolean     cancelled,
+                          gpointer     data)
+{
+    GdlDockMaster  *master;
+    GdlDockRequest *request;
+    
+    g_return_if_fail (data != NULL);
+    g_return_if_fail (item != NULL);
+
+    master = GDL_DOCK_MASTER (data);
+    request = master->_priv->drag_request;
+    
+    g_return_if_fail (GDL_DOCK_OBJECT (item) == request->applicant);
+    
+    /* Erase previously drawn rectangle */
+    if (master->_priv->rect_drawn)
+        gdl_dock_master_xor_rect (master);
+    
+    /* cancel conditions */
+    if (cancelled || request->applicant == request->target)
+        return;
+    
+    /* dock object to the requested position */
+    gdl_dock_object_dock (request->target,
+                          request->applicant,
+                          request->position,
+                          &request->extra);
+    
+    g_signal_emit (master, master_signals [LAYOUT_CHANGED], 0);
+}
+
+static void
+gdl_dock_master_drag_motion (GdlDockItem *item, 
+                             gint         root_x, 
+                             gint         root_y,
+                             gpointer     data)
+{
+    GdlDockMaster  *master;
+    GdlDockRequest  my_request, *request;
+    GdkWindow      *window;
+    gint            win_x, win_y;
+    gint            x, y;
+    GdlDock        *dock = NULL;
+    gboolean        may_dock = FALSE;
+    
+    g_return_if_fail (item != NULL && data != NULL);
+
+    master = GDL_DOCK_MASTER (data);
+    request = master->_priv->drag_request;
+
+    g_return_if_fail (GDL_DOCK_OBJECT (item) == request->applicant);
+    
+    my_request = *request;
+
+    /* first look under the pointer */
+    window = gdk_window_at_pointer (&win_x, &win_y);
+    if (window) {
+        GtkWidget *widget;
+        /* ok, now get the widget who owns that window and see if we can
+           get to a GdlDock by walking up the hierarchy */
+        gdk_window_get_user_data (window, (gpointer) &widget);
+        if (GTK_IS_WIDGET (widget)) {
+            while (widget && !GDL_IS_DOCK (widget))
+                widget = widget->parent;
+            if (widget) {
+                gint win_w, win_h;
+                
+                /* verify that the pointer is still in that dock
+                   (the user could have moved it) */
+                gdk_window_get_geometry (widget->window,
+                                         NULL, NULL, &win_w, &win_h, NULL);
+                gdk_window_get_origin (widget->window, &win_x, &win_y);
+                if (root_x >= win_x && root_x < win_x + win_w &&
+                    root_y >= win_y && root_y < win_y + win_h)
+                    dock = GDL_DOCK (widget);
+            }
+        }
+    }
+
+    if (dock) {
+        /* translate root coordinates into dock object coordinates
+           (i.e. widget coordinates) */
+        gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y);
+        x = root_x - win_x;
+        y = root_y - win_y;
+        may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock),
+                                                 x, y, &my_request);
+    }
+    else {
+        GList *l;
+        
+        /* try to dock the item in all the docks in the ring in turn */
+        for (l = master->toplevel_docks; l; l = l->next) {
+            dock = GDL_DOCK (l->data);
+            /* translate root coordinates into dock object coordinates
+               (i.e. widget coordinates) */
+            gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y);
+            x = root_x - win_x;
+            y = root_y - win_y;
+            may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock),
+                                                     x, y, &my_request);
+            if (may_dock)
+                break;
+        }
+    }
+    
+    if (!may_dock) {
+        GtkRequisition req;
+        
+        dock = NULL;
+        my_request.target = GDL_DOCK_OBJECT (
+            gdl_dock_object_get_toplevel (request->applicant));
+        my_request.position = GDL_DOCK_FLOATING;
+
+        gdl_dock_item_preferred_size (GDL_DOCK_ITEM (request->applicant), &req);
+        my_request.rect.width = req.width;
+        my_request.rect.height = req.height;
+
+        my_request.rect.x = root_x - GDL_DOCK_ITEM (request->applicant)->dragoff_x;
+        my_request.rect.y = root_y - GDL_DOCK_ITEM (request->applicant)->dragoff_y;
+
+        /* setup extra docking information */
+        if (G_IS_VALUE (&my_request.extra))
+            g_value_unset (&my_request.extra);
+
+        g_value_init (&my_request.extra, GDK_TYPE_RECTANGLE);
+        g_value_set_boxed (&my_request.extra, &my_request.rect);
+    };
+
+    if (!(my_request.rect.x == request->rect.x &&
+          my_request.rect.y == request->rect.y &&
+          my_request.rect.width == request->rect.width &&
+          my_request.rect.height == request->rect.height &&
+          dock == master->_priv->rect_owner)) {
+
+        /* erase the previous rectangle */
+        if (master->_priv->rect_drawn)
+            gdl_dock_master_xor_rect (master);
+    }
+
+    /* set the new values */
+    *request = my_request;
+    master->_priv->rect_owner = dock;
+    
+    /* draw the previous rectangle */
+    if (~master->_priv->rect_drawn)
+        gdl_dock_master_xor_rect (master);
+}
+
+static void
+_gdl_dock_master_foreach (gpointer key,
+                          gpointer value,
+                          gpointer user_data)
+{
+    struct {
+        GFunc    function;
+        gpointer user_data;
+    } *data = user_data;
+
+    (* data->function) (GTK_WIDGET (value), data->user_data);
+}
+
+static void
+gdl_dock_master_xor_rect (GdlDockMaster *master)
+{
+    gint8         dash_list [2];
+    GdkWindow    *window;
+    GdkRectangle *rect;
+    
+    if (!master->_priv || !master->_priv->drag_request)
+        return;
+    
+    master->_priv->rect_drawn = ~master->_priv->rect_drawn;
+    
+    if (master->_priv->rect_owner) {
+        gdl_dock_xor_rect (master->_priv->rect_owner,
+                           &master->_priv->drag_request->rect);
+        return;
+    }
+    
+    rect = &master->_priv->drag_request->rect;
+    window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
+
+    if (!master->_priv->root_xor_gc) {
+        GdkGCValues values;
+
+        values.function = GDK_INVERT;
+        values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+        master->_priv->root_xor_gc = gdk_gc_new_with_values (
+            window, &values, GDK_GC_FUNCTION | GDK_GC_SUBWINDOW);
+    };
+
+    gdk_gc_set_line_attributes (master->_priv->root_xor_gc, 1,
+                                GDK_LINE_ON_OFF_DASH,
+                                GDK_CAP_NOT_LAST,
+                                GDK_JOIN_BEVEL);
+    
+    dash_list[0] = 1;
+    dash_list[1] = 1;
+    gdk_gc_set_dashes (master->_priv->root_xor_gc, 1, dash_list, 2);
+
+    gdk_draw_rectangle (window, master->_priv->root_xor_gc, 0, 
+                        rect->x, rect->y,
+                        rect->width, rect->height);
+
+    gdk_gc_set_dashes (master->_priv->root_xor_gc, 0, dash_list, 2);
+
+    gdk_draw_rectangle (window, master->_priv->root_xor_gc, 0, 
+                        rect->x + 1, rect->y + 1,
+                        rect->width - 2, rect->height - 2);
+}
+
+static void
+gdl_dock_master_layout_changed (GdlDockMaster *master)
+{
+    g_return_if_fail (GDL_IS_DOCK_MASTER (master));
+
+    /* emit "layout_changed" on the controller to notify the user who
+     * normally shouldn't have access to us */
+    if (master->controller)
+        g_signal_emit_by_name (master->controller, "layout_changed");
+
+    /* remove the idle handler if there is one */
+    if (master->_priv->idle_layout_changed_id) {
+        g_source_remove (master->_priv->idle_layout_changed_id);
+        master->_priv->idle_layout_changed_id = 0;
+    }
+}
+
+static gboolean
+idle_emit_layout_changed (gpointer user_data)
+{
+    GdlDockMaster *master = user_data;
+
+    g_return_val_if_fail (master && GDL_IS_DOCK_MASTER (master), FALSE);
+
+    master->_priv->idle_layout_changed_id = 0;
+    g_signal_emit (master, master_signals [LAYOUT_CHANGED], 0);
+    
+    return FALSE;
+}
+
+static void 
+item_dock_cb (GdlDockObject    *object,
+              GdlDockObject    *requestor,
+              GdlDockPlacement  position,
+              GValue           *other_data,
+              gpointer          user_data)
+{
+    GdlDockMaster *master = user_data;
+    
+    g_return_if_fail (requestor && GDL_IS_DOCK_OBJECT (requestor));
+    g_return_if_fail (master && GDL_IS_DOCK_MASTER (master));
+
+    /* here we are in fact interested in the requestor, since it's
+     * assumed that object will not change its visibility... for the
+     * requestor, however, could mean that it's being shown */
+    if (!GDL_DOCK_OBJECT_IN_REFLOW (requestor) &&
+        !GDL_DOCK_OBJECT_AUTOMATIC (requestor)) {
+        if (!master->_priv->idle_layout_changed_id)
+            master->_priv->idle_layout_changed_id =
+                g_idle_add (idle_emit_layout_changed, master);
+    }
+}
+
+static void 
+item_detach_cb (GdlDockObject *object,
+                gboolean       recursive,
+                gpointer       user_data)
+{
+    GdlDockMaster *master = user_data;
+    
+    g_return_if_fail (object && GDL_IS_DOCK_OBJECT (object));
+    g_return_if_fail (master && GDL_IS_DOCK_MASTER (master));
+
+    if (!GDL_DOCK_OBJECT_IN_REFLOW (object) &&
+        !GDL_DOCK_OBJECT_AUTOMATIC (object)) {
+        if (!master->_priv->idle_layout_changed_id)
+            master->_priv->idle_layout_changed_id =
+                g_idle_add (idle_emit_layout_changed, master);
+    }
+}
+
+static void
+item_notify_cb (GdlDockObject *object,
+                GParamSpec    *pspec,
+                gpointer       user_data)
+{
+    GdlDockMaster *master = user_data;
+    gint locked = COMPUTE_LOCKED (master);
+    gboolean item_locked;
+    
+    g_object_get (object, "locked", &item_locked, NULL);
+
+    if (item_locked) {
+        g_hash_table_remove (master->_priv->unlocked_items, object);
+        g_hash_table_insert (master->_priv->locked_items, object, NULL);
+    } else {
+        g_hash_table_remove (master->_priv->locked_items, object);
+        g_hash_table_insert (master->_priv->unlocked_items, object, NULL);
+    }
+    
+    if (COMPUTE_LOCKED (master) != locked)
+        g_object_notify (G_OBJECT (master), "locked");
+}
+
+/* ----- Public interface ----- */
+
+void
+gdl_dock_master_add (GdlDockMaster *master,
+                     GdlDockObject *object)
+{
+    g_return_if_fail (master != NULL && object != NULL);
+
+    if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) {
+        GdlDockObject *found_object;
+        
+        /* create a name for the object if it doesn't have one */
+        if (!object->name)
+            /* directly set the name, since it's a construction only
+               property */
+            object->name = g_strdup_printf ("__dock_%u", master->_priv->number++);
+        
+        /* add the object to our hash list */
+        if ((found_object = g_hash_table_lookup (master->dock_objects, object->name))) {
+            g_warning (_("master %p: unable to add object %p[%s] to the hash.  "
+                         "There already is an item with that name (%p)."),
+                       master, object, object->name, found_object);
+        }
+        else {
+            g_object_ref (object);
+            gtk_object_sink (GTK_OBJECT (object));
+            g_hash_table_insert (master->dock_objects, g_strdup (object->name), object);
+        }
+    }
+    
+    if (GDL_IS_DOCK (object)) {
+        gboolean floating;
+        
+        /* if this is the first toplevel we are adding, name it controller */
+        if (!master->toplevel_docks)
+            /* the dock should already have the ref */
+            master->controller = object;
+        
+        /* add dock to the toplevel list */
+        g_object_get (object, "floating", &floating, NULL);
+        if (floating)
+            master->toplevel_docks = g_list_prepend (master->toplevel_docks, object);
+        else
+            master->toplevel_docks = g_list_append (master->toplevel_docks, object);
+
+        /* we are interested in the dock request this toplevel
+         * receives to update the layout */
+        g_signal_connect (object, "dock",
+                          G_CALLBACK (item_dock_cb), master);
+
+    }
+    else if (GDL_IS_DOCK_ITEM (object)) {
+        /* we need to connect the item's signals */
+        g_signal_connect (object, "dock_drag_begin",
+                          G_CALLBACK (gdl_dock_master_drag_begin), master);
+        g_signal_connect (object, "dock_drag_motion",
+                          G_CALLBACK (gdl_dock_master_drag_motion), master);
+        g_signal_connect (object, "dock_drag_end",
+                          G_CALLBACK (gdl_dock_master_drag_end), master);
+        g_signal_connect (object, "dock",
+                          G_CALLBACK (item_dock_cb), master);
+        g_signal_connect (object, "detach",
+                          G_CALLBACK (item_detach_cb), master);
+
+        /* register to "locked" notification if the item has a grip,
+         * and add the item to the corresponding hash */
+        if (GDL_DOCK_ITEM_HAS_GRIP (object)) {
+            g_signal_connect (object, "notify::locked",
+                              G_CALLBACK (item_notify_cb), master);
+            item_notify_cb (object, NULL, master);
+        }
+        
+        /* post a layout_changed emission if the item is not automatic
+         * (since it should be added to the items model) */
+        if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) {
+            if (!master->_priv->idle_layout_changed_id)
+                master->_priv->idle_layout_changed_id =
+                    g_idle_add (idle_emit_layout_changed, master);
+        }
+    }
+}
+
+void
+gdl_dock_master_remove (GdlDockMaster *master,
+                        GdlDockObject *object)
+{
+    g_return_if_fail (master != NULL && object != NULL);
+
+    /* remove from locked/unlocked hashes and property change if
+     * that's the case */
+    if (GDL_IS_DOCK_ITEM (object) && GDL_DOCK_ITEM_HAS_GRIP (object)) {
+        gint locked = COMPUTE_LOCKED (master);
+        if (g_hash_table_remove (master->_priv->locked_items, object) ||
+            g_hash_table_remove (master->_priv->unlocked_items, object)) {
+            if (COMPUTE_LOCKED (master) != locked)
+                g_object_notify (G_OBJECT (master), "locked");
+        }
+    }
+        
+    /* ref the master, since removing the controller could cause master disposal */
+    g_object_ref (master);
+    
+    /* all the interesting stuff happens in _gdl_dock_master_remove */
+    _gdl_dock_master_remove (object, master);
+
+    /* post a layout_changed emission if the item is not automatic
+     * (since it should be removed from the items model) */
+    if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) {
+        if (!master->_priv->idle_layout_changed_id)
+            master->_priv->idle_layout_changed_id =
+                g_idle_add (idle_emit_layout_changed, master);
+    }
+    
+    /* balance ref count */
+    g_object_unref (master);
+}
+
+void
+gdl_dock_master_foreach (GdlDockMaster *master,
+                         GFunc          function,
+                         gpointer       user_data)
+{
+    struct {
+        GFunc    function;
+        gpointer user_data;
+    } data;
+
+    g_return_if_fail (master != NULL && function != NULL);
+
+    data.function = function;
+    data.user_data = user_data;
+    g_hash_table_foreach (master->dock_objects, _gdl_dock_master_foreach, &data);
+}
+
+void
+gdl_dock_master_foreach_toplevel (GdlDockMaster *master,
+                                  gboolean       include_controller,
+                                  GFunc          function,
+                                  gpointer       user_data)
+{
+    GList *l;
+    
+    g_return_if_fail (master != NULL && function != NULL);
+
+    for (l = master->toplevel_docks; l; ) {
+        GdlDockObject *object = GDL_DOCK_OBJECT (l->data);
+        l = l->next;
+        if (object != master->controller || include_controller)
+            (* function) (GTK_WIDGET (object), user_data);
+    }
+}
+
+GdlDockObject *
+gdl_dock_master_get_object (GdlDockMaster *master,
+                            const gchar   *nick_name)
+{
+    gpointer *found;
+    
+    g_return_val_if_fail (master != NULL, NULL);
+
+    if (!nick_name)
+        return NULL;
+
+    found = g_hash_table_lookup (master->dock_objects, nick_name);
+
+    return found ? GDL_DOCK_OBJECT (found) : NULL;
+}
+
+GdlDockObject *
+gdl_dock_master_get_controller (GdlDockMaster *master)
+{
+    g_return_val_if_fail (master != NULL, NULL);
+
+    return master->controller;
+}
+
+void
+gdl_dock_master_set_controller (GdlDockMaster *master,
+                                GdlDockObject *new_controller)
+{
+    g_return_if_fail (master != NULL);
+
+    if (new_controller) {
+        if (GDL_DOCK_OBJECT_AUTOMATIC (new_controller))
+            g_warning (_("The new dock controller %p is automatic.  Only manual "
+                         "dock objects should be named controller."), new_controller);
+        
+        /* check that the controller is in the toplevel list */
+        if (!g_list_find (master->toplevel_docks, new_controller))
+            gdl_dock_master_add (master, new_controller);
+        master->controller = new_controller;
+
+    } else {
+        master->controller = NULL;
+        /* no controller, no master */
+        g_object_unref (master);
+    }
+}

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-master.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-master.h - Object which manages a dock ring
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_MASTER_H__
+#define __GDL_DOCK_MASTER_H__
+
+#include <glib-object.h>
+#include <gtk/gtktypeutils.h>
+#include <gdl/gdl-dock-object.h>
+
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_MASTER             (gdl_dock_master_get_type ())
+#define GDL_DOCK_MASTER(obj)             (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_MASTER, GdlDockMaster))
+#define GDL_DOCK_MASTER_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_MASTER, GdlDockMasterClass))
+#define GDL_IS_DOCK_MASTER(obj)          (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_MASTER))
+#define GDL_IS_DOCK_MASTER_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_MASTER))
+#define GDL_DOCK_MASTER_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_MASTER, GdlDockMasterClass))
+
+/* data types & structures */
+typedef struct _GdlDockMaster        GdlDockMaster;
+typedef struct _GdlDockMasterClass   GdlDockMasterClass;
+typedef struct _GdlDockMasterPrivate GdlDockMasterPrivate;
+
+struct _GdlDockMaster {
+    GObject               object;
+
+    GHashTable           *dock_objects;
+    GList                *toplevel_docks;
+    GdlDockObject        *controller;      /* GUI root object */
+    
+    gint                  dock_number;     /* for toplevel dock numbering */
+    
+    GdlDockMasterPrivate *_priv;
+};
+
+struct _GdlDockMasterClass {
+    GObjectClass parent_class;
+
+    void (* layout_changed) (GdlDockMaster *master);
+};
+
+/* additional macros */
+
+#define GDL_DOCK_OBJECT_GET_MASTER(object) \
+    (GDL_DOCK_OBJECT (object)->master ? \
+        GDL_DOCK_MASTER (GDL_DOCK_OBJECT (object)->master) : NULL)
+
+/* public interface */
+ 
+GType          gdl_dock_master_get_type         (void);
+
+void           gdl_dock_master_add              (GdlDockMaster *master,
+                                                 GdlDockObject *object);
+void           gdl_dock_master_remove           (GdlDockMaster *master,
+                                                 GdlDockObject *object);
+void           gdl_dock_master_foreach          (GdlDockMaster *master,
+                                                 GFunc          function,
+                                                 gpointer       user_data);
+
+void           gdl_dock_master_foreach_toplevel (GdlDockMaster *master,
+                                                 gboolean       include_controller,
+                                                 GFunc          function,
+                                                 gpointer       user_data);
+
+GdlDockObject *gdl_dock_master_get_object       (GdlDockMaster *master,
+                                                 const gchar   *nick_name);
+
+GdlDockObject *gdl_dock_master_get_controller   (GdlDockMaster *master);
+void           gdl_dock_master_set_controller   (GdlDockMaster *master,
+                                                 GdlDockObject *new_controller);
+
+G_END_DECLS
+
+#endif /* __GDL_DOCK_MASTER_H__ */

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,502 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <gtk/gtknotebook.h>
+#include <libgnome/gnome-macros.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock-notebook.h"
+#include "gdl-dock-tablabel.h"
+
+
+/* Private prototypes */
+
+static void  gdl_dock_notebook_class_init    (GdlDockNotebookClass *klass);
+static void  gdl_dock_notebook_instance_init (GdlDockNotebook      *notebook);
+static void  gdl_dock_notebook_set_property  (GObject              *object,
+                                              guint                 prop_id,
+                                              const GValue         *value,
+                                              GParamSpec           *pspec);
+static void  gdl_dock_notebook_get_property  (GObject              *object,
+                                              guint                 prop_id,
+                                              GValue               *value,
+                                              GParamSpec           *pspec);
+
+static void  gdl_dock_notebook_destroy       (GtkObject    *object);
+
+static void  gdl_dock_notebook_add           (GtkContainer *container,
+					      GtkWidget    *widget);
+static void  gdl_dock_notebook_forall        (GtkContainer *container,
+					      gboolean      include_internals,
+					      GtkCallback   callback,
+					      gpointer      callback_data);
+static GType gdl_dock_notebook_child_type    (GtkContainer *container);
+
+static void  gdl_dock_notebook_dock          (GdlDockObject    *object,
+                                              GdlDockObject    *requestor,
+                                              GdlDockPlacement  position,
+                                              GValue           *other_data);
+
+static void  gdl_dock_notebook_switch_page_cb  (GtkNotebook     *nb,
+                                                GtkNotebookPage *page,
+                                                gint             page_num,
+                                                gpointer         data);
+
+static void  gdl_dock_notebook_set_orientation (GdlDockItem     *item,
+                                                GtkOrientation   orientation);
+					       
+static gboolean gdl_dock_notebook_child_placement (GdlDockObject    *object,
+                                                   GdlDockObject    *child,
+                                                   GdlDockPlacement *placement);
+
+static void     gdl_dock_notebook_present         (GdlDockObject    *object,
+                                                   GdlDockObject    *child);
+
+static gboolean gdl_dock_notebook_reorder         (GdlDockObject    *object,
+                                                   GdlDockObject    *requestor,
+                                                   GdlDockPlacement  new_position,
+                                                   GValue           *other_data);
+
+
+/* Class variables and definitions */
+
+enum {
+    PROP_0,
+    PROP_PAGE
+};
+
+
+/* ----- Private functions ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockNotebook, gdl_dock_notebook, GdlDockItem, GDL_TYPE_DOCK_ITEM) ;
+
+static void
+gdl_dock_notebook_class_init (GdlDockNotebookClass *klass)
+{
+    GObjectClass       *g_object_class;
+    GtkObjectClass     *gtk_object_class;
+    GtkWidgetClass     *widget_class;
+    GtkContainerClass  *container_class;
+    GdlDockObjectClass *object_class;
+    GdlDockItemClass   *item_class;
+
+    g_object_class = G_OBJECT_CLASS (klass);
+    gtk_object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    object_class = GDL_DOCK_OBJECT_CLASS (klass);
+    item_class = GDL_DOCK_ITEM_CLASS (klass);
+
+    g_object_class->set_property = gdl_dock_notebook_set_property;
+    g_object_class->get_property = gdl_dock_notebook_get_property;
+    
+    gtk_object_class->destroy = gdl_dock_notebook_destroy;
+
+    container_class->add = gdl_dock_notebook_add;
+    container_class->forall = gdl_dock_notebook_forall;
+    container_class->child_type = gdl_dock_notebook_child_type;
+    
+    object_class->is_compound = TRUE;
+    object_class->dock = gdl_dock_notebook_dock;
+    object_class->child_placement = gdl_dock_notebook_child_placement;
+    object_class->present = gdl_dock_notebook_present;
+    object_class->reorder = gdl_dock_notebook_reorder;
+    
+    item_class->has_grip = TRUE;
+    item_class->set_orientation = gdl_dock_notebook_set_orientation;    
+    
+    g_object_class_install_property (
+        g_object_class, PROP_PAGE,
+        g_param_spec_int ("page", _("Page"),
+                          _("The index of the current page"),
+                          0, G_MAXINT,
+                          0,
+                          G_PARAM_READWRITE |
+                          GDL_DOCK_PARAM_EXPORT | GDL_DOCK_PARAM_AFTER));
+}
+
+static void 
+gdl_dock_notebook_notify_cb (GObject    *g_object,
+                             GParamSpec *pspec,
+                             gpointer    user_data) 
+{
+    g_return_if_fail (user_data != NULL && GDL_IS_DOCK_NOTEBOOK (user_data));
+
+    /* chain the notify signal */
+    g_object_notify (G_OBJECT (user_data), pspec->name);
+}
+
+static gboolean 
+gdl_dock_notebook_button_cb (GtkWidget      *widget,
+                             GdkEventButton *event,
+                             gpointer        user_data)
+{
+    if (event->type == GDK_BUTTON_PRESS)
+        GDL_DOCK_ITEM_SET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
+    else
+        GDL_DOCK_ITEM_UNSET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
+
+    return FALSE;
+}
+    
+static void
+gdl_dock_notebook_instance_init (GdlDockNotebook *notebook)
+{
+    GdlDockItem *item;
+
+    item = GDL_DOCK_ITEM (notebook);
+
+    /* create the container notebook */
+    item->child = gtk_notebook_new ();
+    gtk_widget_set_parent (item->child, GTK_WIDGET (notebook));
+    if (item->orientation == GTK_ORIENTATION_HORIZONTAL)
+        gtk_notebook_set_tab_pos (GTK_NOTEBOOK (item->child), GTK_POS_TOP);
+    else
+        gtk_notebook_set_tab_pos (GTK_NOTEBOOK (item->child), GTK_POS_LEFT);
+    g_signal_connect (item->child, "switch_page",
+                      (GCallback) gdl_dock_notebook_switch_page_cb, (gpointer) item);
+    g_signal_connect (item->child, "notify::page",
+                      (GCallback) gdl_dock_notebook_notify_cb, (gpointer) item);
+    g_signal_connect (item->child, "button-press-event",
+                      (GCallback) gdl_dock_notebook_button_cb, (gpointer) item);
+    g_signal_connect (item->child, "button-release-event",
+                      (GCallback) gdl_dock_notebook_button_cb, (gpointer) item);
+    gtk_notebook_set_scrollable (GTK_NOTEBOOK (item->child), TRUE);
+    gtk_widget_show (item->child);
+}
+
+static void 
+gdl_dock_notebook_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+
+    switch (prop_id) {
+        case PROP_PAGE:
+            if (item->child && GTK_IS_NOTEBOOK (item->child)) {
+                gtk_notebook_set_current_page (GTK_NOTEBOOK (item->child),
+                                               g_value_get_int (value));
+            }
+            
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void 
+gdl_dock_notebook_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+
+    switch (prop_id) {
+        case PROP_PAGE:
+            if (item->child && GTK_IS_NOTEBOOK (item->child)) {
+                g_value_set_int (value, gtk_notebook_get_current_page
+                                 (GTK_NOTEBOOK (item->child)));
+            }
+            
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+
+static void
+gdl_dock_notebook_destroy (GtkObject *object)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+
+    /* we need to call the virtual first, since in GdlDockDestroy our
+       children dock objects are detached */
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
+
+    /* after that we can remove the GtkNotebook */
+    if (item->child) {
+        gtk_widget_unparent (item->child);
+        item->child = NULL;
+    };
+}
+
+static void
+gdl_dock_notebook_switch_page_cb (GtkNotebook     *nb,
+                                  GtkNotebookPage *page,
+                                  gint             page_num,
+                                  gpointer         data)
+{
+    GdlDockNotebook *notebook;
+    GtkWidget       *tablabel;
+
+    notebook = GDL_DOCK_NOTEBOOK (data);
+
+    /* deactivate old tablabel */
+    if (nb->cur_page) {
+        tablabel = gtk_notebook_get_tab_label (
+            nb, gtk_notebook_get_nth_page (
+                nb, gtk_notebook_get_current_page (nb)));
+        if (tablabel && GDL_IS_DOCK_TABLABEL (tablabel))
+            gdl_dock_tablabel_deactivate (GDL_DOCK_TABLABEL (tablabel));
+    };
+
+    /* activate new label */
+    tablabel = gtk_notebook_get_tab_label (
+        nb, gtk_notebook_get_nth_page (nb, page_num));
+    if (tablabel && GDL_IS_DOCK_TABLABEL (tablabel))
+        gdl_dock_tablabel_activate (GDL_DOCK_TABLABEL (tablabel));
+
+    if (GDL_DOCK_ITEM_USER_ACTION (notebook) &&
+        GDL_DOCK_OBJECT (notebook)->master)
+        g_signal_emit_by_name (GDL_DOCK_OBJECT (notebook)->master,
+                               "layout_changed");
+}
+
+static void
+gdl_dock_notebook_add (GtkContainer *container,
+		       GtkWidget    *widget)
+{
+    g_return_if_fail (container != NULL && widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_NOTEBOOK (container));
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    gdl_dock_object_dock (GDL_DOCK_OBJECT (container),
+                          GDL_DOCK_OBJECT (widget),
+                          GDL_DOCK_CENTER,
+                          NULL);
+}
+
+static void
+gdl_dock_notebook_forall (GtkContainer *container,
+			  gboolean      include_internals,
+			  GtkCallback   callback,
+			  gpointer      callback_data)
+{
+    GdlDockItem *item;
+
+    g_return_if_fail (container != NULL);
+    g_return_if_fail (GDL_IS_DOCK_NOTEBOOK (container));
+    g_return_if_fail (callback != NULL);
+
+    if (include_internals) {
+        /* use GdlDockItem's forall */
+        GNOME_CALL_PARENT (GTK_CONTAINER_CLASS, forall, 
+                           (container, include_internals, callback, callback_data));
+    }
+    else {
+        item = GDL_DOCK_ITEM (container);
+        if (item->child)
+            gtk_container_foreach (GTK_CONTAINER (item->child), callback, callback_data);
+    }
+}
+
+static GType
+gdl_dock_notebook_child_type (GtkContainer *container)
+{
+    return GDL_TYPE_DOCK_ITEM;
+}
+    
+static void
+gdl_dock_notebook_dock_child (GdlDockObject *requestor,
+                              gpointer       user_data)
+{
+    struct {
+        GdlDockObject    *object;
+        GdlDockPlacement  position;
+        GValue           *other_data;
+    } *data = user_data;
+
+    gdl_dock_object_dock (data->object, requestor, data->position, data->other_data);
+}
+
+static void
+gdl_dock_notebook_dock (GdlDockObject    *object,
+                        GdlDockObject    *requestor,
+                        GdlDockPlacement  position,
+                        GValue           *other_data)
+{
+    g_return_if_fail (GDL_IS_DOCK_NOTEBOOK (object));
+    g_return_if_fail (GDL_IS_DOCK_ITEM (requestor));
+
+    /* we only add support for GDL_DOCK_CENTER docking strategy here... for the rest
+       use our parent class' method */
+    if (position == GDL_DOCK_CENTER) {
+        /* we can only dock simple (not compound) items */
+        if (gdl_dock_object_is_compound (requestor)) {
+            struct {
+                GdlDockObject    *object;
+                GdlDockPlacement  position;
+                GValue           *other_data;
+            } data;
+
+            gdl_dock_object_freeze (requestor);
+            
+            data.object = object;
+            data.position = position;
+            data.other_data = other_data;
+             
+            gtk_container_foreach (GTK_CONTAINER (requestor),
+                                   (GtkCallback) gdl_dock_notebook_dock_child, &data);
+
+            gdl_dock_object_thaw (requestor);
+        }
+        else {
+            GdlDockItem *item = GDL_DOCK_ITEM (object);
+            GdlDockItem *requestor_item = GDL_DOCK_ITEM (requestor);
+            GtkWidget   *label;
+            gint         position = -1;
+            
+            label = gdl_dock_item_get_tablabel (requestor_item);
+            if (!label) {
+                label = gdl_dock_tablabel_new (requestor_item);
+                gdl_dock_item_set_tablabel (requestor_item, label);
+            }
+            if (GDL_IS_DOCK_TABLABEL (label)) {
+                gdl_dock_tablabel_deactivate (GDL_DOCK_TABLABEL (label));
+                /* hide the item grip, as we will use the tablabel's */
+                gdl_dock_item_hide_grip (requestor_item);
+            }
+
+            if (other_data && G_VALUE_HOLDS (other_data, G_TYPE_INT))
+                position = g_value_get_int (other_data);
+            
+            gtk_notebook_insert_page (GTK_NOTEBOOK (item->child), 
+                                      GTK_WIDGET (requestor), label,
+                                      position);
+            GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED);
+        }
+    }
+    else
+        GNOME_CALL_PARENT (GDL_DOCK_OBJECT_CLASS, dock,
+                           (object, requestor, position, other_data));
+}
+
+static void
+gdl_dock_notebook_set_orientation (GdlDockItem    *item,
+				   GtkOrientation  orientation)
+{
+    if (item->child && GTK_IS_NOTEBOOK (item->child)) {
+        if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            gtk_notebook_set_tab_pos (GTK_NOTEBOOK (item->child), GTK_POS_TOP);
+        else
+            gtk_notebook_set_tab_pos (GTK_NOTEBOOK (item->child), GTK_POS_LEFT);
+    }
+
+    GNOME_CALL_PARENT (GDL_DOCK_ITEM_CLASS, set_orientation, (item, orientation));
+}
+
+static gboolean 
+gdl_dock_notebook_child_placement (GdlDockObject    *object,
+                                   GdlDockObject    *child,
+                                   GdlDockPlacement *placement)
+{
+    GdlDockItem      *item = GDL_DOCK_ITEM (object);
+    GdlDockPlacement  pos = GDL_DOCK_NONE;
+    
+    if (item->child) {
+        GList *children, *l;
+
+        children = gtk_container_get_children (GTK_CONTAINER (item->child));
+        for (l = children; l; l = l->next) {
+            if (l->data == (gpointer) child) {
+                pos = GDL_DOCK_CENTER;
+                break;
+            }
+        }
+        g_list_free (children);
+    }
+
+    if (pos != GDL_DOCK_NONE) {
+        if (placement)
+            *placement = pos;
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+static void
+gdl_dock_notebook_present (GdlDockObject *object,
+                           GdlDockObject *child)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+    int i;
+    
+    i = gtk_notebook_page_num (GTK_NOTEBOOK (item->child),
+                               GTK_WIDGET (child));
+    if (i >= 0)
+        gtk_notebook_set_current_page (GTK_NOTEBOOK (item->child), i);
+
+    GNOME_CALL_PARENT (GDL_DOCK_OBJECT_CLASS, present, (object, child));
+}
+
+static gboolean 
+gdl_dock_notebook_reorder (GdlDockObject    *object,
+                           GdlDockObject    *requestor,
+                           GdlDockPlacement  new_position,
+                           GValue           *other_data)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+    gint         current_position, new_pos = -1;
+    gboolean     handled = FALSE;
+    
+    if (item->child && new_position == GDL_DOCK_CENTER) {
+        current_position = gtk_notebook_page_num (GTK_NOTEBOOK (item->child),
+                                                  GTK_WIDGET (requestor));
+        if (current_position >= 0) {
+            handled = TRUE;
+    
+            if (other_data && G_VALUE_HOLDS (other_data, G_TYPE_INT))
+                new_pos = g_value_get_int (other_data);
+            
+            gtk_notebook_reorder_child (GTK_NOTEBOOK (item->child), 
+                                        GTK_WIDGET (requestor),
+                                        new_pos);
+        }
+    }
+    return handled;
+}
+
+/* ----- Public interface ----- */
+
+GtkWidget *
+gdl_dock_notebook_new (void)
+{
+    GdlDockNotebook *notebook;
+
+    notebook = GDL_DOCK_NOTEBOOK (g_object_new (GDL_TYPE_DOCK_NOTEBOOK, NULL));
+    GDL_DOCK_OBJECT_UNSET_FLAGS (notebook, GDL_DOCK_AUTOMATIC);
+    
+    return GTK_WIDGET (notebook);
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-notebook.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_NOTEBOOK_H__
+#define __GDL_DOCK_NOTEBOOK_H__
+
+#include <gdl/gdl-dock-item.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_NOTEBOOK            (gdl_dock_notebook_get_type ())
+#define GDL_DOCK_NOTEBOOK(obj)            (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_NOTEBOOK, GdlDockNotebook))
+#define GDL_DOCK_NOTEBOOK_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_NOTEBOOK, GdlDockNotebookClass))
+#define GDL_IS_DOCK_NOTEBOOK(obj)         (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_NOTEBOOK))
+#define GDL_IS_DOCK_NOTEBOOK_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_NOTEBOOK))
+#define GDL_DOCK_NOTEBOOK_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_NOTEBOOK, GdlDockNotebookClass))
+
+/* data types & structures */
+typedef struct _GdlDockNotebook        GdlDockNotebook;
+typedef struct _GdlDockNotebookClass   GdlDockNotebookClass;
+
+struct _GdlDockNotebook {
+    GdlDockItem  item;
+};
+
+struct _GdlDockNotebookClass {
+    GdlDockItemClass  parent_class;
+};
+
+
+/* public interface */
+ 
+GtkWidget     *gdl_dock_notebook_new               (void);
+
+GType          gdl_dock_notebook_get_type          (void);
+
+G_END_DECLS
+
+#endif
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,913 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-object.c - Abstract base class for all dock related objects
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <libgnome/gnome-macros.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock-object.h"
+#include "gdl-dock-master.h"
+#include "libgdltypebuiltins.h"
+#include "libgdlmarshal.h"
+
+/* for later use by the registry */
+#include "gdl-dock.h"
+#include "gdl-dock-item.h"
+#include "gdl-dock-paned.h"
+#include "gdl-dock-notebook.h"
+#include "gdl-dock-placeholder.h"
+
+
+/* ----- Private prototypes ----- */
+
+static void     gdl_dock_object_class_init         (GdlDockObjectClass *klass);
+static void     gdl_dock_object_instance_init      (GdlDockObject      *object);
+
+static void     gdl_dock_object_set_property       (GObject            *g_object,
+                                                    guint               prop_id,
+                                                    const GValue       *value,
+                                                    GParamSpec         *pspec);
+static void     gdl_dock_object_get_property       (GObject            *g_object,
+                                                    guint               prop_id,
+                                                    GValue             *value,
+                                                    GParamSpec         *pspec);
+static void     gdl_dock_object_finalize           (GObject            *g_object);
+
+static void     gdl_dock_object_destroy            (GtkObject          *gtk_object);
+
+static void     gdl_dock_object_show               (GtkWidget          *widget);
+static void     gdl_dock_object_hide               (GtkWidget          *widget);
+
+static void     gdl_dock_object_real_detach        (GdlDockObject      *object,
+                                                    gboolean            recursive);
+static void     gdl_dock_object_real_reduce        (GdlDockObject      *object);
+static void     gdl_dock_object_dock_unimplemented (GdlDockObject     *object,
+                                                    GdlDockObject     *requestor,
+                                                    GdlDockPlacement   position,
+                                                    GValue            *other_data);
+static void     gdl_dock_object_real_present       (GdlDockObject     *object,
+                                                    GdlDockObject     *child);
+
+
+/* ----- Private data types and variables ----- */
+
+enum {
+    PROP_0,
+    PROP_NAME,
+    PROP_LONG_NAME,
+    PROP_MASTER,
+    PROP_EXPORT_PROPERTIES
+};
+
+enum {
+    DETACH,
+    DOCK,
+    LAST_SIGNAL
+};
+
+static guint gdl_dock_object_signals [LAST_SIGNAL] = { 0 };
+
+/* ----- Private interface ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockObject, gdl_dock_object, GtkContainer, GTK_TYPE_CONTAINER);
+
+static void
+gdl_dock_object_class_init (GdlDockObjectClass *klass)
+{
+    GObjectClass      *g_object_class;
+    GtkObjectClass    *object_class;
+    GtkWidgetClass    *widget_class;
+    GtkContainerClass *container_class;
+
+    g_object_class = G_OBJECT_CLASS (klass);
+    object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+
+    g_object_class->set_property = gdl_dock_object_set_property;
+    g_object_class->get_property = gdl_dock_object_get_property;
+    g_object_class->finalize = gdl_dock_object_finalize;
+
+    g_object_class_install_property (
+        g_object_class, PROP_NAME,
+        g_param_spec_string (GDL_DOCK_NAME_PROPERTY, _("Name"),
+                             _("Unique name for identifying the dock object"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                             GDL_DOCK_PARAM_EXPORT));
+
+    g_object_class_install_property (
+        g_object_class, PROP_LONG_NAME,
+        g_param_spec_string ("long_name", _("Long name"),
+                             _("Human readable name for the dock object"),
+                             NULL,
+                             G_PARAM_READWRITE));
+
+    g_object_class_install_property (
+        g_object_class, PROP_MASTER,
+        g_param_spec_object ("master", _("Dock master"),
+                             _("Dock master this dock object is bound to"),
+                             GDL_TYPE_DOCK_MASTER,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+    
+    object_class->destroy = gdl_dock_object_destroy;
+    
+    widget_class->show = gdl_dock_object_show;
+    widget_class->hide = gdl_dock_object_hide;
+    
+    klass->is_compound = TRUE;
+    
+    klass->detach = gdl_dock_object_real_detach;
+    klass->reduce = gdl_dock_object_real_reduce;
+    klass->dock_request = NULL;
+    klass->dock = gdl_dock_object_dock_unimplemented;
+    klass->reorder = NULL;
+    klass->present = gdl_dock_object_real_present;
+    klass->child_placement = NULL;
+    
+    gdl_dock_object_signals [DETACH] =
+        g_signal_new ("detach",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (GdlDockObjectClass, detach),
+                      NULL,
+                      NULL,
+                      gdl_marshal_VOID__BOOLEAN,
+                      G_TYPE_NONE,
+                      1,
+                      G_TYPE_BOOLEAN);
+
+    gdl_dock_object_signals [DOCK] =
+        g_signal_new ("dock",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET (GdlDockObjectClass, dock),
+                      NULL,
+                      NULL,
+                      gdl_marshal_VOID__OBJECT_ENUM_BOXED,
+                      G_TYPE_NONE,
+                      3,
+                      GDL_TYPE_DOCK_OBJECT,
+                      GDL_TYPE_DOCK_PLACEMENT,
+                      G_TYPE_VALUE);
+}
+
+static void
+gdl_dock_object_instance_init (GdlDockObject *object)
+{
+    object->flags = GDL_DOCK_AUTOMATIC;
+    object->freeze_count = 0;
+}
+
+static void
+gdl_dock_object_set_property  (GObject      *g_object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+    GdlDockObject *object = GDL_DOCK_OBJECT (g_object);
+
+    switch (prop_id) {
+    case PROP_NAME:
+        g_free (object->name);
+        object->name = g_value_dup_string (value);
+        break;
+    case PROP_LONG_NAME:
+        g_free (object->long_name);
+        object->long_name = g_value_dup_string (value);
+        break;
+    case PROP_MASTER:
+        if (g_value_get_object (value)) 
+            gdl_dock_object_bind (object, g_value_get_object (value));
+        else
+            gdl_dock_object_unbind (object);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gdl_dock_object_get_property  (GObject      *g_object,
+                               guint         prop_id,
+                               GValue       *value,
+                               GParamSpec   *pspec)
+{
+    GdlDockObject *object = GDL_DOCK_OBJECT (g_object);
+
+    switch (prop_id) {
+    case PROP_NAME:
+        g_value_set_string (value, object->name);
+        break;
+    case PROP_LONG_NAME:
+        g_value_set_string (value, object->long_name);
+        break;
+    case PROP_MASTER:
+        g_value_set_object (value, object->master);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gdl_dock_object_finalize (GObject *g_object)
+{
+    GdlDockObject *object;
+    
+    g_return_if_fail (g_object != NULL && GDL_IS_DOCK_OBJECT (g_object));
+
+    object = GDL_DOCK_OBJECT (g_object);
+
+    g_free (object->name);
+    object->name = NULL;
+    g_free (object->long_name);
+    object->long_name = NULL;
+
+    GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (g_object));
+}
+
+static void
+gdl_dock_object_foreach_detach (GdlDockObject *object,
+                                gpointer       user_data)
+{
+    gdl_dock_object_detach (object, TRUE);
+}
+
+static void
+gdl_dock_object_destroy (GtkObject *gtk_object)
+{
+    GdlDockObject *object;
+
+    g_return_if_fail (GDL_IS_DOCK_OBJECT (gtk_object));
+
+    object = GDL_DOCK_OBJECT (gtk_object);
+    if (gdl_dock_object_is_compound (object)) {
+        /* detach our dock object children if we have some, and even
+           if we are not attached, so they can get notification */
+        gdl_dock_object_freeze (object);
+        gtk_container_foreach (GTK_CONTAINER (object),
+                               (GtkCallback) gdl_dock_object_foreach_detach,
+                               NULL);
+        object->reduce_pending = FALSE;
+        gdl_dock_object_thaw (object);
+    }
+    if (GDL_DOCK_OBJECT_ATTACHED (object)) {
+        /* detach ourselves */
+        gdl_dock_object_detach (object, FALSE);
+    }
+    
+    /* finally unbind us */
+    if (object->master)
+        gdl_dock_object_unbind (object);
+        
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (gtk_object));
+}
+
+static void
+gdl_dock_object_foreach_automatic (GdlDockObject *object,
+                                   gpointer       user_data)
+{
+    void (* function) (GtkWidget *) = user_data;
+
+    if (GDL_DOCK_OBJECT_AUTOMATIC (object))
+        (* function) (GTK_WIDGET (object));
+}
+
+static void
+gdl_dock_object_show (GtkWidget *widget)
+{
+    if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (widget))) {
+        gtk_container_foreach (GTK_CONTAINER (widget),
+                               (GtkCallback) gdl_dock_object_foreach_automatic,
+                               gtk_widget_show);
+    }
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, show, (widget));
+}
+
+static void
+gdl_dock_object_hide (GtkWidget *widget)
+{
+    if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (widget))) {
+        gtk_container_foreach (GTK_CONTAINER (widget),
+                               (GtkCallback) gdl_dock_object_foreach_automatic,
+                               gtk_widget_hide);
+    }
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, hide, (widget));
+}
+
+static void
+gdl_dock_object_real_detach (GdlDockObject *object,
+                             gboolean       recursive)
+{
+    GdlDockObject *parent;
+    GtkWidget     *widget;
+    
+    g_return_if_fail (object != NULL);
+
+    /* detach children */
+    if (recursive && gdl_dock_object_is_compound (object)) {
+        gtk_container_foreach (GTK_CONTAINER (object),
+                               (GtkCallback) gdl_dock_object_detach,
+                               (gpointer) recursive);
+    }
+    
+    /* detach the object itself */
+    GDL_DOCK_OBJECT_UNSET_FLAGS (object, GDL_DOCK_ATTACHED);
+    parent = gdl_dock_object_get_parent_object (object);
+    widget = GTK_WIDGET (object);
+    if (widget->parent)
+        gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+    if (parent)
+        gdl_dock_object_reduce (parent);
+}
+
+static void
+gdl_dock_object_real_reduce (GdlDockObject *object)
+{
+    GdlDockObject *parent;
+    GList         *children;
+    
+    g_return_if_fail (object != NULL);
+
+    if (!gdl_dock_object_is_compound (object))
+        return;
+
+    parent = gdl_dock_object_get_parent_object (object);
+    children = gtk_container_get_children (GTK_CONTAINER (object));
+    if (g_list_length (children) <= 1) {
+        GList *l;
+        
+        /* detach ourselves and then re-attach our children to our
+           current parent.  if we are not currently attached, the
+           children are detached */
+        if (parent)
+            gdl_dock_object_freeze (parent);
+        gdl_dock_object_freeze (object);
+        gdl_dock_object_detach (object, FALSE);
+        for (l = children; l; l = l->next) {
+            GdlDockObject *child = GDL_DOCK_OBJECT (l->data);
+
+            g_object_ref (child);
+            GDL_DOCK_OBJECT_SET_FLAGS (child, GDL_DOCK_IN_REFLOW);
+            gdl_dock_object_detach (child, FALSE);
+            if (parent)
+                gtk_container_add (GTK_CONTAINER (parent), GTK_WIDGET (child));
+            GDL_DOCK_OBJECT_UNSET_FLAGS (child, GDL_DOCK_IN_REFLOW);
+            g_object_unref (child);
+        }
+        /* sink the widget, so any automatic floating widget is destroyed */
+        gtk_object_sink (GTK_OBJECT (object));
+        /* don't reenter */
+        object->reduce_pending = FALSE;
+        gdl_dock_object_thaw (object);
+        if (parent)
+            gdl_dock_object_thaw (parent);
+    }
+    g_list_free (children);
+}
+
+static void
+gdl_dock_object_dock_unimplemented (GdlDockObject    *object,
+                                    GdlDockObject    *requestor,
+                                    GdlDockPlacement  position,
+                                    GValue           *other_data)
+{
+    g_warning (_("Call to gdl_dock_object_dock in a dock object %p "
+                 "(object type is %s) which hasn't implemented this method"),
+               object, G_OBJECT_TYPE_NAME (object));
+}
+
+static void 
+gdl_dock_object_real_present (GdlDockObject *object,
+                              GdlDockObject *child)
+{
+    gtk_widget_show (GTK_WIDGET (object));
+}
+
+
+/* ----- Public interface ----- */
+
+gboolean
+gdl_dock_object_is_compound (GdlDockObject *object)
+{
+    GdlDockObjectClass *klass;
+
+    g_return_val_if_fail (object != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_OBJECT (object), FALSE);
+
+    klass = GDL_DOCK_OBJECT_GET_CLASS (object);
+    return klass->is_compound;
+}
+
+void
+gdl_dock_object_detach (GdlDockObject *object,
+                        gboolean       recursive)
+{
+    g_return_if_fail (object != NULL);
+
+    if (!GDL_DOCK_OBJECT_ATTACHED (object))
+        return;
+    
+    /* freeze the object to avoid reducing while detaching children */
+    gdl_dock_object_freeze (object);
+    GDL_DOCK_OBJECT_SET_FLAGS (object, GDL_DOCK_IN_DETACH);
+    g_signal_emit (object, gdl_dock_object_signals [DETACH], 0, recursive);
+    GDL_DOCK_OBJECT_UNSET_FLAGS (object, GDL_DOCK_IN_DETACH);
+    gdl_dock_object_thaw (object);
+}
+
+GdlDockObject *
+gdl_dock_object_get_parent_object (GdlDockObject *object)
+{
+    GtkWidget *parent;
+    
+    g_return_val_if_fail (object != NULL, NULL);
+
+    parent = GTK_WIDGET (object)->parent;
+    while (parent && !GDL_IS_DOCK_OBJECT (parent)) {
+        parent = parent->parent;
+    }
+    
+    return parent ? GDL_DOCK_OBJECT (parent) : NULL;
+}
+
+void
+gdl_dock_object_freeze (GdlDockObject *object)
+{
+    g_return_if_fail (object != NULL);
+    
+    if (object->freeze_count == 0) {
+        g_object_ref (object);   /* dock objects shouldn't be
+                                    destroyed if they are frozen */
+    }
+    object->freeze_count++;
+}
+
+void
+gdl_dock_object_thaw (GdlDockObject *object)
+{
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (object->freeze_count > 0);
+    
+    object->freeze_count--;
+    if (object->freeze_count == 0) {
+        if (object->reduce_pending) {
+            object->reduce_pending = FALSE;
+            gdl_dock_object_reduce (object);
+        }
+        g_object_unref (object);
+    }
+}
+
+void
+gdl_dock_object_reduce (GdlDockObject *object)
+{
+    g_return_if_fail (object != NULL);
+
+    if (GDL_DOCK_OBJECT_FROZEN (object)) {
+        object->reduce_pending = TRUE;
+        return;
+    }
+
+    GDL_CALL_VIRTUAL (object, GDL_DOCK_OBJECT_GET_CLASS, reduce, (object));
+}
+
+gboolean
+gdl_dock_object_dock_request (GdlDockObject  *object,
+                              gint            x,
+                              gint            y,
+                              GdlDockRequest *request)
+{
+    g_return_val_if_fail (object != NULL && request != NULL, FALSE);
+    
+    return GDL_CALL_VIRTUAL_WITH_DEFAULT (object,
+                                          GDL_DOCK_OBJECT_GET_CLASS,
+                                          dock_request,
+                                          (object, x, y, request),
+                                          FALSE);
+}
+
+void
+gdl_dock_object_dock (GdlDockObject    *object,
+                      GdlDockObject    *requestor,
+                      GdlDockPlacement  position,
+                      GValue           *other_data)
+{
+    GdlDockObject *parent;
+    
+    g_return_if_fail (object != NULL && requestor != NULL);
+        
+    if (object == requestor)
+        return;
+    
+    if (!object->master)
+        g_warning (_("Dock operation requested in a non-bound object %p. "
+                     "The application might crash"), object);
+        
+    if (!gdl_dock_object_is_bound (requestor))
+        gdl_dock_object_bind (requestor, object->master);
+
+    if (requestor->master != object->master) {
+        g_warning (_("Cannot dock %p to %p because they belong to different masters"),
+                   requestor, object);
+        return;
+    }
+
+    /* first, see if we can optimize things by reordering */
+    if (position != GDL_DOCK_NONE) {
+        parent = gdl_dock_object_get_parent_object (object);
+        if (gdl_dock_object_reorder (object, requestor, position, other_data) ||
+            (parent && gdl_dock_object_reorder (parent, requestor, position, other_data)))
+            return;
+    }
+    
+    /* freeze the object, since under some conditions it might be destroyed when
+       detaching the requestor */
+    gdl_dock_object_freeze (object);
+
+    /* detach the requestor before docking */
+    g_object_ref (requestor);
+    if (GDL_DOCK_OBJECT_ATTACHED (requestor))
+        gdl_dock_object_detach (requestor, FALSE);
+    
+    if (position != GDL_DOCK_NONE)
+        g_signal_emit (object, gdl_dock_object_signals [DOCK], 0,
+                       requestor, position, other_data);
+
+    g_object_unref (requestor);
+    gdl_dock_object_thaw (object);
+}
+
+void
+gdl_dock_object_bind (GdlDockObject *object,
+                      GObject       *master)
+{
+    g_return_if_fail (object != NULL && master != NULL);
+    g_return_if_fail (GDL_IS_DOCK_MASTER (master));
+    
+    if (object->master == master)
+        /* nothing to do here */
+        return;
+    
+    if (object->master) {
+        g_warning (_("Attempt to bind to %p an already bound dock object %p "
+                     "(current master: %p)"), master, object, object->master);
+        return;
+    }
+
+    gdl_dock_master_add (GDL_DOCK_MASTER (master), object);
+    object->master = master;
+    g_object_add_weak_pointer (master, (gpointer *) &object->master);
+
+    g_object_notify (G_OBJECT (object), "master");
+}
+
+void
+gdl_dock_object_unbind (GdlDockObject *object)
+{
+    g_return_if_fail (object != NULL);
+
+    g_object_ref (object);
+
+    /* detach the object first */
+    if (GDL_DOCK_OBJECT_ATTACHED (object))
+        gdl_dock_object_detach (object, TRUE);
+    
+    if (object->master) {
+        GObject *master = object->master;
+        g_object_remove_weak_pointer (master, (gpointer *) &object->master);
+        object->master = NULL;
+        gdl_dock_master_remove (GDL_DOCK_MASTER (master), object);
+        g_object_notify (G_OBJECT (object), "master");
+    }
+    g_object_unref (object);
+}
+
+gboolean
+gdl_dock_object_is_bound (GdlDockObject *object)
+{
+    g_return_val_if_fail (object != NULL, FALSE);
+    return (object->master != NULL);
+}
+
+gboolean
+gdl_dock_object_reorder (GdlDockObject    *object,
+                         GdlDockObject    *child,
+                         GdlDockPlacement  new_position,
+                         GValue           *other_data)
+{
+    g_return_val_if_fail (object != NULL && child != NULL, FALSE);
+
+    return GDL_CALL_VIRTUAL_WITH_DEFAULT (object,
+                                          GDL_DOCK_OBJECT_GET_CLASS,
+                                          reorder,
+                                          (object, child, new_position, other_data),
+                                          FALSE);
+}
+
+void 
+gdl_dock_object_present (GdlDockObject *object,
+                         GdlDockObject *child)
+{
+    GdlDockObject *parent;
+    
+    g_return_if_fail (object != NULL && GDL_IS_DOCK_OBJECT (object));
+
+    parent = gdl_dock_object_get_parent_object (object);
+    if (parent)
+        /* chain the call to our parent */
+        gdl_dock_object_present (parent, object);
+
+    GDL_CALL_VIRTUAL (object, GDL_DOCK_OBJECT_GET_CLASS, present, (object, child));
+}
+
+/**
+ * gdl_dock_object_child_placement:
+ * @object: the dock object we are asking for child placement
+ * @child: the child of the @object we want the placement for
+ * @placement: where to return the placement information
+ *
+ * This function returns information about placement of a child dock
+ * object inside another dock object.  The function returns %TRUE if
+ * @child is effectively a child of @object.  @placement should
+ * normally be initially setup to %GDL_DOCK_NONE.  If it's set to some
+ * other value, this function will not touch the stored value if the
+ * specified placement is "compatible" with the actual placement of
+ * the child.
+ *
+ * @placement can be %NULL, in which case the function simply tells if
+ * @child is attached to @object.
+ *
+ * Returns: %TRUE if @child is a child of @object.
+ */
+gboolean 
+gdl_dock_object_child_placement (GdlDockObject    *object,
+                                 GdlDockObject    *child,
+                                 GdlDockPlacement *placement)
+{
+    g_return_val_if_fail (object != NULL && child != NULL, FALSE);
+
+    /* simple case */
+    if (!gdl_dock_object_is_compound (object))
+        return FALSE;
+    
+    return GDL_CALL_VIRTUAL_WITH_DEFAULT (object, GDL_DOCK_OBJECT_GET_CLASS,
+                                          child_placement,
+                                          (object, child, placement),
+                                          FALSE);
+}
+
+
+/* ----- dock param type functions start here ------ */
+
+static void 
+gdl_dock_param_export_int (const GValue *src,
+                           GValue       *dst)
+{
+    dst->data [0].v_pointer = g_strdup_printf ("%d", src->data [0].v_int);
+}
+
+static void 
+gdl_dock_param_export_uint (const GValue *src,
+                            GValue       *dst)
+{
+    dst->data [0].v_pointer = g_strdup_printf ("%u", src->data [0].v_uint);
+}
+
+static void 
+gdl_dock_param_export_string (const GValue *src,
+                              GValue       *dst)
+{
+    dst->data [0].v_pointer = g_strdup (src->data [0].v_pointer);
+}
+
+static void 
+gdl_dock_param_export_bool (const GValue *src,
+                            GValue       *dst)
+{
+    dst->data [0].v_pointer = g_strdup_printf ("%s", src->data [0].v_int ? "yes" : "no");
+}
+
+static void 
+gdl_dock_param_export_placement (const GValue *src,
+                                 GValue       *dst)
+{
+    switch (src->data [0].v_int) {
+        case GDL_DOCK_NONE:
+            dst->data [0].v_pointer = g_strdup ("");
+            break;
+        case GDL_DOCK_TOP:
+            dst->data [0].v_pointer = g_strdup ("top");
+            break;
+        case GDL_DOCK_BOTTOM:
+            dst->data [0].v_pointer = g_strdup ("bottom");
+            break;
+        case GDL_DOCK_LEFT:
+            dst->data [0].v_pointer = g_strdup ("left");
+            break;
+        case GDL_DOCK_RIGHT:
+            dst->data [0].v_pointer = g_strdup ("right");
+            break;
+        case GDL_DOCK_CENTER:
+            dst->data [0].v_pointer = g_strdup ("center");
+            break;
+        case GDL_DOCK_FLOATING:
+            dst->data [0].v_pointer = g_strdup ("floating");
+            break;
+    }
+}
+
+static void 
+gdl_dock_param_import_int (const GValue *src,
+                           GValue       *dst)
+{
+    dst->data [0].v_int = atoi (src->data [0].v_pointer);
+}
+
+static void 
+gdl_dock_param_import_uint (const GValue *src,
+                            GValue       *dst)
+{
+    dst->data [0].v_uint = (guint) atoi (src->data [0].v_pointer);
+}
+
+static void 
+gdl_dock_param_import_string (const GValue *src,
+                              GValue       *dst)
+{
+    dst->data [0].v_pointer = g_strdup (src->data [0].v_pointer);
+}
+
+static void 
+gdl_dock_param_import_bool (const GValue *src,
+                            GValue       *dst)
+{
+    dst->data [0].v_int = !strcmp (src->data [0].v_pointer, "yes");
+}
+
+static void 
+gdl_dock_param_import_placement (const GValue *src,
+                                 GValue       *dst)
+{
+    if (!strcmp (src->data [0].v_pointer, "top"))
+        dst->data [0].v_int = GDL_DOCK_TOP;
+    else if (!strcmp (src->data [0].v_pointer, "bottom"))
+        dst->data [0].v_int = GDL_DOCK_BOTTOM;
+    else if (!strcmp (src->data [0].v_pointer, "center"))
+        dst->data [0].v_int = GDL_DOCK_CENTER;
+    else if (!strcmp (src->data [0].v_pointer, "left"))
+        dst->data [0].v_int = GDL_DOCK_LEFT;
+    else if (!strcmp (src->data [0].v_pointer, "right"))
+        dst->data [0].v_int = GDL_DOCK_RIGHT;
+    else if (!strcmp (src->data [0].v_pointer, "floating"))
+        dst->data [0].v_int = GDL_DOCK_FLOATING;
+    else
+        dst->data [0].v_int = GDL_DOCK_NONE;
+}
+
+GType
+gdl_dock_param_get_type (void)
+{
+    static GType our_type = 0;
+
+    if (our_type == 0) {
+        GTypeInfo tinfo = { 0, };
+        our_type = g_type_register_static (G_TYPE_STRING, "GdlDockParam", &tinfo, 0);
+
+        /* register known transform functions */
+        /* exporters */
+        g_value_register_transform_func (G_TYPE_INT, our_type, gdl_dock_param_export_int);
+        g_value_register_transform_func (G_TYPE_UINT, our_type, gdl_dock_param_export_uint);
+        g_value_register_transform_func (G_TYPE_STRING, our_type, gdl_dock_param_export_string);
+        g_value_register_transform_func (G_TYPE_BOOLEAN, our_type, gdl_dock_param_export_bool);
+        g_value_register_transform_func (GDL_TYPE_DOCK_PLACEMENT, our_type, gdl_dock_param_export_placement);
+        /* importers */
+        g_value_register_transform_func (our_type, G_TYPE_INT, gdl_dock_param_import_int);
+        g_value_register_transform_func (our_type, G_TYPE_UINT, gdl_dock_param_import_uint);
+        g_value_register_transform_func (our_type, G_TYPE_STRING, gdl_dock_param_import_string);
+        g_value_register_transform_func (our_type, G_TYPE_BOOLEAN, gdl_dock_param_import_bool);
+        g_value_register_transform_func (our_type, GDL_TYPE_DOCK_PLACEMENT, gdl_dock_param_import_placement);
+    }
+
+    return our_type;
+}
+
+/* -------------- nick <-> type conversion functions --------------- */
+
+static GRelation *dock_register = NULL;
+
+enum {
+    INDEX_NICK = 0,
+    INDEX_TYPE
+};
+
+static void
+gdl_dock_object_register_init (void)
+{
+    if (dock_register)
+        return;
+    
+    /* FIXME: i don't know if GRelation is efficient */
+    dock_register = g_relation_new (2);
+    g_relation_index (dock_register, INDEX_NICK, g_str_hash, g_str_equal);
+    g_relation_index (dock_register, INDEX_TYPE, g_direct_hash, g_direct_equal);
+
+    /* add known types */
+    g_relation_insert (dock_register, "dock", (gpointer) GDL_TYPE_DOCK);
+    g_relation_insert (dock_register, "item", (gpointer) GDL_TYPE_DOCK_ITEM);
+    g_relation_insert (dock_register, "paned", (gpointer) GDL_TYPE_DOCK_PANED);
+    g_relation_insert (dock_register, "notebook", (gpointer) GDL_TYPE_DOCK_NOTEBOOK);
+    g_relation_insert (dock_register, "placeholder", (gpointer) GDL_TYPE_DOCK_PLACEHOLDER);
+}
+
+G_CONST_RETURN gchar *
+gdl_dock_object_nick_from_type (GType type)
+{
+    GTuples *tuples;
+    gchar *nick = NULL;
+    
+    if (!dock_register)
+        gdl_dock_object_register_init ();
+
+    if (g_relation_count (dock_register, (gpointer) type, INDEX_TYPE) > 0) {
+        tuples = g_relation_select (dock_register, (gpointer) type, INDEX_TYPE);
+        nick = (gchar *) g_tuples_index (tuples, 0, INDEX_NICK);
+        g_tuples_destroy (tuples);
+    }
+    
+    return nick ? nick : g_type_name (type);
+}
+
+GType
+gdl_dock_object_type_from_nick (const gchar *nick)
+{
+    GTuples *tuples;
+    GType type = G_TYPE_NONE;
+    
+    if (!dock_register)
+        gdl_dock_object_register_init ();
+
+    if (g_relation_count (dock_register, (gpointer) nick, INDEX_NICK) > 0) {
+        tuples = g_relation_select (dock_register, (gpointer) nick, INDEX_NICK);
+        type = (GType) g_tuples_index (tuples, 0, INDEX_TYPE);
+        g_tuples_destroy (tuples);
+    }
+    else {
+        /* try searching in the glib type system */
+        type = g_type_from_name (nick);
+    }
+    
+    return type;
+}
+
+GType
+gdl_dock_object_set_type_for_nick (const gchar *nick,
+                                   GType        type)
+{
+    GType old_type = G_TYPE_NONE;
+    
+    if (!dock_register)
+        gdl_dock_object_register_init ();
+
+    g_return_val_if_fail (g_type_is_a (type, GDL_TYPE_DOCK_OBJECT), G_TYPE_NONE);
+    
+    if (g_relation_count (dock_register, (gpointer) nick, INDEX_NICK) > 0) {
+        old_type = gdl_dock_object_type_from_nick (nick);
+        g_relation_delete (dock_register, (gpointer) nick, INDEX_NICK);
+    }
+    
+    g_relation_insert (dock_register, nick, type);
+
+    return old_type;
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-object.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,224 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-object.h - Abstract base class for all dock related objects
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_OBJECT_H__
+#define __GDL_DOCK_OBJECT_H__
+
+#include <gtk/gtkcontainer.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_OBJECT             (gdl_dock_object_get_type ())
+#define GDL_DOCK_OBJECT(obj)             (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_OBJECT, GdlDockObject))
+#define GDL_DOCK_OBJECT_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_OBJECT, GdlDockObjectClass))
+#define GDL_IS_DOCK_OBJECT(obj)          (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_OBJECT))
+#define GDL_IS_DOCK_OBJECT_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_OBJECT))
+#define GDL_DOCK_OBJECT_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_OBJECT, GdlDockObjectClass))
+
+/* data types & structures */
+typedef enum {
+    /* the parameter is to be exported for later layout rebuilding */
+    GDL_DOCK_PARAM_EXPORT = 1 << G_PARAM_USER_SHIFT,
+    /* the parameter must be set after adding the children objects */
+    GDL_DOCK_PARAM_AFTER  = 1 << (G_PARAM_USER_SHIFT + 1)
+} GdlDockParamFlags;
+
+#define GDL_DOCK_NAME_PROPERTY    "name"
+#define GDL_DOCK_MASTER_PROPERTY  "master"
+
+typedef enum {
+    GDL_DOCK_AUTOMATIC  = 1 << 0,
+    GDL_DOCK_ATTACHED   = 1 << 1,
+    GDL_DOCK_IN_REFLOW  = 1 << 2,
+    GDL_DOCK_IN_DETACH  = 1 << 3
+} GdlDockObjectFlags;
+
+#define GDL_DOCK_OBJECT_FLAGS_SHIFT 8
+
+typedef enum {
+    GDL_DOCK_NONE = 0,
+    GDL_DOCK_TOP,
+    GDL_DOCK_BOTTOM,
+    GDL_DOCK_RIGHT,
+    GDL_DOCK_LEFT,
+    GDL_DOCK_CENTER,
+    GDL_DOCK_FLOATING
+} GdlDockPlacement;
+
+typedef struct _GdlDockObject      GdlDockObject;
+typedef struct _GdlDockObjectClass GdlDockObjectClass;
+typedef struct _GdlDockRequest     GdlDockRequest;
+
+struct _GdlDockRequest {
+    GdlDockObject    *applicant;
+    GdlDockObject    *target;
+    GdlDockPlacement  position;
+    GdkRectangle      rect;
+    GValue            extra;
+};
+
+struct _GdlDockObject {
+    GtkContainer        container;
+
+    GdlDockObjectFlags  flags;
+    gint                freeze_count;
+    
+    GObject            *master;
+    gchar              *name;
+    gchar              *long_name;
+    
+    gboolean            reduce_pending;
+};
+
+struct _GdlDockObjectClass {
+    GtkContainerClass parent_class;
+
+    gboolean          is_compound;
+    
+    void     (* detach)          (GdlDockObject    *object,
+                                  gboolean          recursive);
+    void     (* reduce)          (GdlDockObject    *object);
+
+    gboolean (* dock_request)    (GdlDockObject    *object,
+                                  gint              x,
+                                  gint              y,
+                                  GdlDockRequest   *request);
+
+    void     (* dock)            (GdlDockObject    *object,
+                                  GdlDockObject    *requestor,
+                                  GdlDockPlacement  position,
+                                  GValue           *other_data);
+    
+    gboolean (* reorder)         (GdlDockObject    *object,
+                                  GdlDockObject    *child,
+                                  GdlDockPlacement  new_position,
+                                  GValue           *other_data);
+
+    void     (* present)         (GdlDockObject    *object,
+                                  GdlDockObject    *child);
+
+    gboolean (* child_placement) (GdlDockObject    *object,
+                                  GdlDockObject    *child,
+                                  GdlDockPlacement *placement);
+};
+
+/* additional macros */
+#define GDL_DOCK_OBJECT_FLAGS(obj)  (GDL_DOCK_OBJECT (obj)->flags)
+#define GDL_DOCK_OBJECT_AUTOMATIC(obj) \
+    ((GDL_DOCK_OBJECT_FLAGS (obj) & GDL_DOCK_AUTOMATIC) != 0)
+#define GDL_DOCK_OBJECT_ATTACHED(obj) \
+    ((GDL_DOCK_OBJECT_FLAGS (obj) & GDL_DOCK_ATTACHED) != 0)
+#define GDL_DOCK_OBJECT_IN_REFLOW(obj) \
+    ((GDL_DOCK_OBJECT_FLAGS (obj) & GDL_DOCK_IN_REFLOW) != 0)
+#define GDL_DOCK_OBJECT_IN_DETACH(obj) \
+    ((GDL_DOCK_OBJECT_FLAGS (obj) & GDL_DOCK_IN_DETACH) != 0)
+
+#define GDL_DOCK_OBJECT_SET_FLAGS(obj,flag) \
+    G_STMT_START { (GDL_DOCK_OBJECT_FLAGS (obj) |= (flag)); } G_STMT_END
+#define GDL_DOCK_OBJECT_UNSET_FLAGS(obj,flag) \
+    G_STMT_START { (GDL_DOCK_OBJECT_FLAGS (obj) &= ~(flag)); } G_STMT_END
+ 
+#define GDL_DOCK_OBJECT_FROZEN(obj) (GDL_DOCK_OBJECT (obj)->freeze_count > 0)
+
+
+/* public interface */
+ 
+GType          gdl_dock_object_get_type          (void);
+
+gboolean       gdl_dock_object_is_compound       (GdlDockObject    *object);
+
+void           gdl_dock_object_detach            (GdlDockObject    *object,
+                                                  gboolean          recursive);
+
+GdlDockObject *gdl_dock_object_get_parent_object (GdlDockObject    *object);
+
+void           gdl_dock_object_freeze            (GdlDockObject    *object);
+void           gdl_dock_object_thaw              (GdlDockObject    *object);
+
+void           gdl_dock_object_reduce            (GdlDockObject    *object);
+
+gboolean       gdl_dock_object_dock_request      (GdlDockObject    *object,
+                                                  gint              x,
+                                                  gint              y,
+                                                  GdlDockRequest   *request);
+void           gdl_dock_object_dock              (GdlDockObject    *object,
+                                                  GdlDockObject    *requestor,
+                                                  GdlDockPlacement  position,
+                                                  GValue           *other_data);
+
+void           gdl_dock_object_bind              (GdlDockObject    *object,
+                                                  GObject          *master);
+void           gdl_dock_object_unbind            (GdlDockObject    *object);
+gboolean       gdl_dock_object_is_bound          (GdlDockObject    *object);
+
+gboolean       gdl_dock_object_reorder           (GdlDockObject    *object,
+                                                  GdlDockObject    *child,
+                                                  GdlDockPlacement  new_position,
+                                                  GValue           *other_data);
+
+void           gdl_dock_object_present           (GdlDockObject    *object,
+                                                  GdlDockObject    *child);
+
+gboolean       gdl_dock_object_child_placement   (GdlDockObject    *object,
+                                                  GdlDockObject    *child,
+                                                  GdlDockPlacement *placement);
+
+/* other types */
+
+/* this type derives from G_TYPE_STRING and is meant to be the basic
+   type for serializing object parameters which are exported
+   (i.e. those that are needed for layout rebuilding) */
+#define GDL_TYPE_DOCK_PARAM   (gdl_dock_param_get_type ())
+
+GType gdl_dock_param_get_type (void);
+
+/* functions for setting/retrieving nick names for serializing GdlDockObject types */
+G_CONST_RETURN gchar *gdl_dock_object_nick_from_type    (GType        type);
+GType                 gdl_dock_object_type_from_nick    (const gchar *nick);
+GType                 gdl_dock_object_set_type_for_nick (const gchar *nick,
+                                                         GType        type);
+
+
+/* helper macros */
+#define GDL_TRACE_OBJECT(object, format, args...) \
+    G_STMT_START {                            \
+    g_log (G_LOG_DOMAIN,                      \
+	   G_LOG_LEVEL_DEBUG,                 \
+           "%s:%d (%s) %s [%p %d%s:%d]: "format, \
+	   __FILE__,                          \
+	   __LINE__,                          \
+	   __PRETTY_FUNCTION__,               \
+           G_OBJECT_TYPE_NAME (object), object, \
+           G_OBJECT (object)->ref_count, \
+           (GTK_IS_OBJECT (object) && GTK_OBJECT_FLOATING (object)) ? "(float)" : "", \
+           GDL_IS_DOCK_OBJECT (object) ? GDL_DOCK_OBJECT (object)->freeze_count : -1, \
+	   ##args); } G_STMT_END                   
+    
+
+
+G_END_DECLS
+
+#endif  /* __GDL_DOCK_OBJECT_H__ */
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,663 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * gdl-dock-paned.h
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <string.h>
+#include <gtk/gtkhpaned.h>
+#include <gtk/gtkvpaned.h>
+#include <libgnome/gnome-macros.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock-paned.h"
+
+
+/* Private prototypes */
+
+static void     gdl_dock_paned_class_init     (GdlDockPanedClass *klass);
+static void     gdl_dock_paned_instance_init  (GdlDockPaned      *paned);
+static GObject *gdl_dock_paned_constructor    (GType              type,
+                                               guint              n_construct_properties,
+                                               GObjectConstructParam *construct_param);
+static void     gdl_dock_paned_set_property   (GObject           *object,
+                                               guint              prop_id,
+                                               const GValue      *value,
+                                               GParamSpec        *pspec);
+static void     gdl_dock_paned_get_property   (GObject           *object,
+                                               guint              prop_id,
+                                               GValue            *value,
+                                               GParamSpec        *pspec);
+
+static void     gdl_dock_paned_destroy        (GtkObject         *object);
+
+static void     gdl_dock_paned_add            (GtkContainer      *container,
+                                               GtkWidget         *widget);
+static void     gdl_dock_paned_forall         (GtkContainer      *container,
+                                               gboolean           include_internals,
+                                               GtkCallback        callback,
+                                               gpointer           callback_data);
+static GType    gdl_dock_paned_child_type     (GtkContainer      *container);
+
+static gboolean gdl_dock_paned_dock_request   (GdlDockObject     *object, 
+                                               gint               x,
+                                               gint               y, 
+                                               GdlDockRequest    *request);
+static void     gdl_dock_paned_dock           (GdlDockObject    *object,
+                                               GdlDockObject    *requestor,
+                                               GdlDockPlacement  position,
+                                               GValue           *other_data);
+
+static void     gdl_dock_paned_set_orientation (GdlDockItem    *item,
+                                                GtkOrientation  orientation);
+
+static gboolean gdl_dock_paned_child_placement (GdlDockObject    *object,
+                                                GdlDockObject    *child,
+                                                GdlDockPlacement *placement);
+
+
+/* ----- Class variables and definitions ----- */
+
+#define SPLIT_RATIO  0.3
+
+enum {
+    PROP_0,
+    PROP_POSITION
+};
+
+
+/* ----- Private functions ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockPaned, gdl_dock_paned, GdlDockItem, GDL_TYPE_DOCK_ITEM);
+
+static void
+gdl_dock_paned_class_init (GdlDockPanedClass *klass)
+{
+    GObjectClass       *g_object_class;
+    GtkObjectClass     *gtk_object_class;
+    GtkWidgetClass     *widget_class;
+    GtkContainerClass  *container_class;
+    GdlDockObjectClass *object_class;
+    GdlDockItemClass   *item_class;
+
+    g_object_class = G_OBJECT_CLASS (klass);
+    gtk_object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    object_class = GDL_DOCK_OBJECT_CLASS (klass);
+    item_class = GDL_DOCK_ITEM_CLASS (klass);
+
+    g_object_class->set_property = gdl_dock_paned_set_property;
+    g_object_class->get_property = gdl_dock_paned_get_property;
+    g_object_class->constructor = gdl_dock_paned_constructor;
+    
+    gtk_object_class->destroy = gdl_dock_paned_destroy;
+
+    container_class->add = gdl_dock_paned_add;
+    container_class->forall = gdl_dock_paned_forall;
+    container_class->child_type = gdl_dock_paned_child_type;
+    
+    object_class->is_compound = TRUE;
+    
+    object_class->dock_request = gdl_dock_paned_dock_request;
+    object_class->dock = gdl_dock_paned_dock;
+    object_class->child_placement = gdl_dock_paned_child_placement;
+    
+    item_class->has_grip = FALSE;
+    item_class->set_orientation = gdl_dock_paned_set_orientation;    
+
+    g_object_class_install_property (
+        g_object_class, PROP_POSITION,
+        g_param_spec_uint ("position", _("Position"),
+                           _("Position of the divider in pixels"),
+                           0, G_MAXINT, 0,
+                           G_PARAM_READWRITE |
+                           GDL_DOCK_PARAM_EXPORT | GDL_DOCK_PARAM_AFTER));
+}
+
+static void
+gdl_dock_paned_instance_init (GdlDockPaned *paned)
+{
+    paned->position_changed = FALSE;
+}
+
+static void 
+gdl_dock_paned_notify_cb (GObject    *g_object,
+                          GParamSpec *pspec,
+                          gpointer    user_data) 
+{
+    GdlDockPaned *paned;
+    
+    g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data));
+    
+    /* chain the notification to the GdlDockPaned */
+    g_object_notify (G_OBJECT (user_data), pspec->name);
+    
+    paned = GDL_DOCK_PANED (user_data);
+    
+    if (GDL_DOCK_ITEM_USER_ACTION (user_data) && !strcmp (pspec->name, "position"))
+        paned->position_changed = TRUE;
+}
+
+static gboolean 
+gdl_dock_paned_button_cb (GtkWidget      *widget,
+                          GdkEventButton *event,
+                          gpointer        user_data)
+{
+    GdlDockPaned *paned;
+    
+    g_return_val_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data), FALSE);
+    
+    paned = GDL_DOCK_PANED (user_data);
+    if (event->button == 1) {
+        if (event->type == GDK_BUTTON_PRESS)
+            GDL_DOCK_ITEM_SET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
+        else {
+            GDL_DOCK_ITEM_UNSET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
+            if (paned->position_changed) {
+                /* emit pending layout changed signal to track separator position */
+                if (GDL_DOCK_OBJECT (paned)->master)
+                    g_signal_emit_by_name (GDL_DOCK_OBJECT (paned)->master, "layout_changed");
+                paned->position_changed = FALSE;
+            }
+        }
+    }
+    
+    return FALSE;
+}
+
+static void 
+gdl_dock_paned_create_child (GdlDockPaned   *paned,
+                             GtkOrientation  orientation) 
+{
+    GdlDockItem *item;
+    
+    item = GDL_DOCK_ITEM (paned);
+    
+    if (item->child)
+        gtk_widget_unparent (GTK_WIDGET (item->child));
+    
+    /* create the container paned */
+    if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        item->child = gtk_hpaned_new ();
+    else
+        item->child = gtk_vpaned_new ();
+    
+    /* get notification for propagation */
+    g_signal_connect (item->child, "notify::position",
+                      (GCallback) gdl_dock_paned_notify_cb, (gpointer) item);
+    g_signal_connect (item->child, "button-press-event",
+                      (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
+    g_signal_connect (item->child, "button-release-event",
+                      (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
+    
+    gtk_widget_set_parent (item->child, GTK_WIDGET (item));
+    gtk_widget_show (item->child);
+}
+
+static GObject *
+gdl_dock_paned_constructor (GType                  type,
+                            guint                  n_construct_properties,
+                            GObjectConstructParam *construct_param)
+{
+    GObject *g_object;
+    
+    g_object = GNOME_CALL_PARENT_WITH_DEFAULT (G_OBJECT_CLASS, 
+                                               constructor, 
+                                               (type,
+                                                n_construct_properties,
+                                                construct_param),
+                                               NULL);
+    if (g_object) {
+        GdlDockItem *item = GDL_DOCK_ITEM (g_object);
+        
+        if (!item->child)
+            gdl_dock_paned_create_child (GDL_DOCK_PANED (g_object),
+                                         item->orientation);
+        /* otherwise, the orientation was set as a construction
+           parameter and the child is already created */
+    }
+    
+    return g_object;
+}
+
+static void
+gdl_dock_paned_set_property (GObject        *object,
+                             guint           prop_id,
+                             const GValue   *value,
+                             GParamSpec     *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+      
+    switch (prop_id) {
+        case PROP_POSITION:
+            if (item->child && GTK_IS_PANED (item->child))
+                gtk_paned_set_position (GTK_PANED (item->child),
+                                        g_value_get_uint (value));
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_paned_get_property (GObject        *object,
+                             guint           prop_id,
+                             GValue         *value,
+                             GParamSpec     *pspec)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+      
+    switch (prop_id) {
+        case PROP_POSITION:
+            if (item->child && GTK_IS_PANED (item->child))
+                g_value_set_uint (value,
+                                  gtk_paned_get_position (GTK_PANED (item->child)));
+            else
+                g_value_set_uint (value, 0);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_paned_destroy (GtkObject *object)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (object);
+
+    /* we need to call the virtual first, since in GdlDockDestroy our
+       children dock objects are detached */
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
+
+    /* after that we can remove the GtkNotebook */
+    if (item->child) {
+        gtk_widget_unparent (item->child);
+        item->child = NULL;
+    };
+}
+
+static void
+gdl_dock_paned_add (GtkContainer *container,
+                    GtkWidget    *widget)
+{
+    GdlDockItem     *item;
+    GtkPaned        *paned;
+    GdlDockPlacement pos = GDL_DOCK_NONE;
+    
+    g_return_if_fail (container != NULL && widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_PANED (container));
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    item = GDL_DOCK_ITEM (container);
+    g_return_if_fail (item->child != NULL);
+    paned = GTK_PANED (item->child);
+    g_return_if_fail (!paned->child1 || !paned->child2);
+
+    if (!paned->child1)
+        pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
+            GDL_DOCK_LEFT : GDL_DOCK_TOP;
+    else if (!paned->child2)
+        pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
+            GDL_DOCK_RIGHT : GDL_DOCK_BOTTOM;
+
+    if (pos != GDL_DOCK_NONE)
+        gdl_dock_object_dock (GDL_DOCK_OBJECT (container),
+                              GDL_DOCK_OBJECT (widget),
+                              pos, NULL);
+}
+
+static void
+gdl_dock_paned_forall (GtkContainer *container,
+                       gboolean      include_internals,
+                       GtkCallback   callback,
+                       gpointer      callback_data)
+{
+    GdlDockItem *item;
+
+    g_return_if_fail (container != NULL);
+    g_return_if_fail (GDL_IS_DOCK_PANED (container));
+    g_return_if_fail (callback != NULL);
+
+    if (include_internals) {
+        /* use GdlDockItem's forall */
+        GNOME_CALL_PARENT (GTK_CONTAINER_CLASS, forall, 
+                           (container, include_internals, callback, callback_data));
+    }
+    else {
+        item = GDL_DOCK_ITEM (container);
+        if (item->child)
+            gtk_container_foreach (GTK_CONTAINER (item->child), callback, callback_data);
+    }
+}
+
+static GType
+gdl_dock_paned_child_type (GtkContainer *container)
+{
+    GdlDockItem *item = GDL_DOCK_ITEM (container);
+
+    if (gtk_container_child_type (GTK_CONTAINER (item->child)) == G_TYPE_NONE)
+        return G_TYPE_NONE;
+    else
+        return GDL_TYPE_DOCK_ITEM;
+}
+
+static void
+gdl_dock_paned_request_foreach (GdlDockObject *object,
+                                gpointer       user_data)
+{
+    struct {
+        gint            x, y;
+        GdlDockRequest *request;
+        gboolean        may_dock;
+    } *data = user_data;
+    
+    GdlDockRequest my_request;
+    gboolean       may_dock;
+    
+    my_request = *data->request;
+    may_dock = gdl_dock_object_dock_request (object, data->x, data->y, &my_request);
+    if (may_dock) {
+        data->may_dock = TRUE;
+        *data->request = my_request;
+    }
+}
+
+static gboolean
+gdl_dock_paned_dock_request (GdlDockObject  *object, 
+                             gint            x,
+                             gint            y, 
+                             GdlDockRequest *request)
+{
+    GdlDockItem        *item;
+    guint               bw;
+    gint                rel_x, rel_y;
+    GtkAllocation      *alloc;
+    gboolean            may_dock = FALSE;
+    GdlDockRequest      my_request;
+
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (object), FALSE);
+
+    /* we get (x,y) in our allocation coordinates system */
+    
+    item = GDL_DOCK_ITEM (object);
+    
+    /* Get item's allocation. */
+    alloc = &(GTK_WIDGET (object)->allocation);
+    bw = GTK_CONTAINER (object)->border_width;
+
+    /* Get coordinates relative to our window. */
+    rel_x = x - alloc->x;
+    rel_y = y - alloc->y;
+
+    if (request)
+        my_request = *request;
+        
+    /* Check if coordinates are inside the widget. */
+    if (rel_x > 0 && rel_x < alloc->width &&
+        rel_y > 0 && rel_y < alloc->height) {
+        GtkRequisition my, other;
+        gint divider = -1;
+        
+        gdl_dock_item_preferred_size (GDL_DOCK_ITEM (my_request.applicant), &other);
+        gdl_dock_item_preferred_size (GDL_DOCK_ITEM (object), &my);
+
+        /* It's inside our area. */
+        may_dock = TRUE;
+
+	/* Set docking indicator rectangle to the widget size. */
+        my_request.rect.x = bw;
+        my_request.rect.y = bw;
+        my_request.rect.width = alloc->width - 2*bw;
+        my_request.rect.height = alloc->height - 2*bw;
+
+        my_request.target = object;
+
+        /* See if it's in the border_width band. */
+        if (rel_x < bw) {
+            my_request.position = GDL_DOCK_LEFT;
+            my_request.rect.width *= SPLIT_RATIO;
+            divider = other.width;
+        } else if (rel_x > alloc->width - bw) {
+            my_request.position = GDL_DOCK_RIGHT;
+            my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
+            my_request.rect.width *= SPLIT_RATIO;
+            divider = MAX (0, my.width - other.width);
+        } else if (rel_y < bw) {
+            my_request.position = GDL_DOCK_TOP;
+            my_request.rect.height *= SPLIT_RATIO;
+            divider = other.height;
+        } else if (rel_y > alloc->height - bw) {
+            my_request.position = GDL_DOCK_BOTTOM;
+            my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
+            my_request.rect.height *= SPLIT_RATIO;
+            divider = MAX (0, my.height - other.height);
+            
+        } else { /* Otherwise try our children. */
+            struct {
+                gint            x, y;
+                GdlDockRequest *request;
+                gboolean        may_dock;
+            } data;
+
+            /* give them coordinates in their allocation system... the
+               GtkPaned has no window, so our children allocation
+               coordinates are our window coordinates */
+            data.x = rel_x;
+            data.y = rel_y;
+            data.request = &my_request;
+            data.may_dock = FALSE;
+            
+            gtk_container_foreach (GTK_CONTAINER (object),
+                                   (GtkCallback) gdl_dock_paned_request_foreach,
+                                   &data);
+
+            may_dock = data.may_dock;
+            if (!may_dock) {
+                /* the pointer is on the handle, so snap to top/bottom
+                   or left/right */
+                may_dock = TRUE;
+                if (item->orientation == GTK_ORIENTATION_HORIZONTAL) {
+                    if (rel_y < alloc->height / 2) {
+                        my_request.position = GDL_DOCK_TOP;
+                        my_request.rect.height *= SPLIT_RATIO;
+                        divider = other.height;
+                    } else {
+                        my_request.position = GDL_DOCK_BOTTOM;
+                        my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
+                        my_request.rect.height *= SPLIT_RATIO;
+                        divider = MAX (0, my.height - other.height);
+                    }
+                } else {
+                    if (rel_x < alloc->width / 2) {
+                        my_request.position = GDL_DOCK_LEFT;
+                        my_request.rect.width *= SPLIT_RATIO;
+                        divider = other.width;
+                    } else {
+                        my_request.position = GDL_DOCK_RIGHT;
+                        my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
+                        my_request.rect.width *= SPLIT_RATIO;
+                        divider = MAX (0, my.width - other.width);
+                    }
+                }
+            }
+        }
+
+        if (divider >= 0 && my_request.position != GDL_DOCK_CENTER) {
+            if (G_IS_VALUE (&my_request.extra))
+                g_value_unset (&my_request.extra);
+            g_value_init (&my_request.extra, G_TYPE_UINT);
+            g_value_set_uint (&my_request.extra, (guint) divider);
+        }
+        
+        if (may_dock) {
+            /* adjust returned coordinates so they are relative to
+               our allocation */
+            my_request.rect.x += alloc->x;
+            my_request.rect.y += alloc->y;
+        }
+    }
+
+    if (may_dock && request)
+        *request = my_request;
+    
+    return may_dock;
+}
+
+static void
+gdl_dock_paned_dock (GdlDockObject    *object,
+                     GdlDockObject    *requestor,
+                     GdlDockPlacement  position,
+                     GValue           *other_data)
+{
+    GtkPaned *paned;
+    gboolean  done = FALSE;
+    
+    g_return_if_fail (GDL_IS_DOCK_PANED (object));
+    g_return_if_fail (GDL_DOCK_ITEM (object)->child != NULL);
+
+    paned = GTK_PANED (GDL_DOCK_ITEM (object)->child);
+
+    /* see if we can dock the item in our paned */
+    switch (GDL_DOCK_ITEM (object)->orientation) {
+        case GTK_ORIENTATION_HORIZONTAL:
+            if (!paned->child1 && position == GDL_DOCK_LEFT) {
+                gtk_paned_pack1 (paned, GTK_WIDGET (requestor), FALSE, FALSE);
+                done = TRUE;
+            } else if (!paned->child2 && position == GDL_DOCK_RIGHT) {
+                gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
+                done = TRUE;
+            }
+            break;
+        case GTK_ORIENTATION_VERTICAL:
+            if (!paned->child1 && position == GDL_DOCK_TOP) {
+                gtk_paned_pack1 (paned, GTK_WIDGET (requestor), FALSE, FALSE);
+                done = TRUE;
+            } else if (!paned->child2 && position == GDL_DOCK_BOTTOM) {
+                gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
+                done = TRUE;
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (!done) {
+        /* this will create another paned and reparent us there */
+        GNOME_CALL_PARENT (GDL_DOCK_OBJECT_CLASS, dock, (object, requestor, position,
+                                                         other_data));
+    }
+    else {
+        gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor));
+        GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED);
+    }
+}
+
+static void
+gdl_dock_paned_set_orientation (GdlDockItem    *item,
+                                GtkOrientation  orientation)
+{
+    GtkPaned    *old_paned = NULL, *new_paned;
+    GtkWidget   *child1, *child2;
+    
+    g_return_if_fail (GDL_IS_DOCK_PANED (item));
+
+    if (item->child) {
+        old_paned = GTK_PANED (item->child);
+        g_object_ref (old_paned);
+        gtk_widget_unparent (GTK_WIDGET (old_paned));
+        item->child = NULL;
+    }
+    
+    gdl_dock_paned_create_child (GDL_DOCK_PANED (item), orientation);
+    
+    if (old_paned) {
+        new_paned = GTK_PANED (item->child);
+        child1 = old_paned->child1;
+        child2 = old_paned->child2;
+    
+        if (child1) {
+            g_object_ref (child1);
+            gtk_container_remove (GTK_CONTAINER (old_paned), child1);
+            gtk_paned_pack1 (new_paned, child1, TRUE, FALSE);
+            g_object_unref (child1);
+        }
+        if (child2) {
+            g_object_ref (child2);
+            gtk_container_remove (GTK_CONTAINER (old_paned), child2);
+            gtk_paned_pack1 (new_paned, child2, TRUE, FALSE);
+            g_object_unref (child2);
+        }
+    }
+    
+    GNOME_CALL_PARENT (GDL_DOCK_ITEM_CLASS, set_orientation, (item, orientation));
+}
+
+static gboolean 
+gdl_dock_paned_child_placement (GdlDockObject    *object,
+                                GdlDockObject    *child,
+                                GdlDockPlacement *placement)
+{
+    GdlDockItem      *item = GDL_DOCK_ITEM (object);
+    GtkPaned         *paned;
+    GdlDockPlacement  pos = GDL_DOCK_NONE;
+    
+    if (item->child) {
+        paned = GTK_PANED (item->child);
+        if (GTK_WIDGET (child) == paned->child1)
+            pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
+                GDL_DOCK_LEFT : GDL_DOCK_TOP;
+        else if (GTK_WIDGET (child) == paned->child2)
+            pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
+                GDL_DOCK_RIGHT : GDL_DOCK_BOTTOM;
+    }
+
+    if (pos != GDL_DOCK_NONE) {
+        if (placement)
+            *placement = pos;
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+
+/* ----- Public interface ----- */
+
+GtkWidget *
+gdl_dock_paned_new (GtkOrientation orientation)
+{
+    GdlDockPaned *paned;
+
+    paned = GDL_DOCK_PANED (g_object_new (GDL_TYPE_DOCK_PANED,
+                                          "orientation", orientation, NULL));
+    GDL_DOCK_OBJECT_UNSET_FLAGS (paned, GDL_DOCK_AUTOMATIC);
+    
+    return GTK_WIDGET (paned);
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-paned.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * gdl-dock-paned.h
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_PANED_H__
+#define __GDL_DOCK_PANED_H__
+
+#include <gdl/gdl-dock-item.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_PANED                  (gdl_dock_paned_get_type ())
+#define GDL_DOCK_PANED(obj)                  (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_PANED, GdlDockPaned))
+#define GDL_DOCK_PANED_CLASS(klass)          (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_PANED, GdlDockPanedClass))
+#define GDL_IS_DOCK_PANED(obj)               (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_PANED))
+#define GDL_IS_DOCK_PANED_CLASS(klass)       (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_PANED))
+#define GDL_DOCK_PANED_GET_CLASS(obj)        (GTK_CHECK_GET_CLASS ((obj), GDL_TYE_DOCK_PANED, GdlDockPanedClass))
+
+/* data types & structures */
+typedef struct _GdlDockPaned      GdlDockPaned;
+typedef struct _GdlDockPanedClass GdlDockPanedClass;
+
+struct _GdlDockPaned {
+    GdlDockItem  dock_item;
+
+    gboolean     position_changed;
+};
+
+struct _GdlDockPanedClass {
+    GdlDockItemClass parent_class;
+};
+
+
+/* public interface */
+ 
+GType      gdl_dock_paned_get_type        (void);
+
+GtkWidget *gdl_dock_paned_new             (GtkOrientation orientation);
+
+
+G_END_DECLS
+
+#endif /* __GDL_DOCK_PANED_H__ */
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,618 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-placeholder.c - Placeholders for docking items
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <libgnome/gnome-macros.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock-placeholder.h"
+#include "gdl-dock-item.h"
+#include "libgdltypebuiltins.h"
+
+
+#undef PLACEHOLDER_DEBUG
+
+/* ----- Private prototypes ----- */
+
+static void     gdl_dock_placeholder_class_init     (GdlDockPlaceholderClass *klass);
+static void     gdl_dock_placeholder_instance_init  (GdlDockPlaceholder      *ph);
+
+static void     gdl_dock_placeholder_set_property   (GObject                 *g_object,
+                                                     guint                    prop_id,
+                                                     const GValue            *value,
+                                                     GParamSpec              *pspec);
+static void     gdl_dock_placeholder_get_property   (GObject                 *g_object,
+                                                     guint                    prop_id,
+                                                     GValue                  *value,
+                                                     GParamSpec              *pspec);
+
+static void     gdl_dock_placeholder_destroy        (GtkObject               *object);
+
+static void     gdl_dock_placeholder_add            (GtkContainer            *container,
+                                                     GtkWidget               *widget);
+
+static void     gdl_dock_placeholder_detach         (GdlDockObject           *object,
+                                                     gboolean                 recursive);
+static void     gdl_dock_placeholder_reduce         (GdlDockObject           *object);
+static void     gdl_dock_placeholder_dock           (GdlDockObject           *object,
+                                                     GdlDockObject           *requestor,
+                                                     GdlDockPlacement         position,
+                                                     GValue                  *other_data);
+
+static void     gdl_dock_placeholder_weak_notify    (gpointer                 data,
+                                                     GObject                 *old_object);
+
+static void     disconnect_host                     (GdlDockPlaceholder      *ph);
+static void     connect_host                        (GdlDockPlaceholder      *ph,
+                                                     GdlDockObject           *new_host);
+static void     do_excursion                        (GdlDockPlaceholder      *ph);
+
+static void     gdl_dock_placeholder_present        (GdlDockObject           *object,
+                                                     GdlDockObject           *child);
+
+
+/* ----- Private variables and data structures ----- */
+
+enum {
+    PROP_0,
+    PROP_STICKY,
+    PROP_HOST,
+    PROP_NEXT_PLACEMENT
+};
+
+struct _GdlDockPlaceholderPrivate {
+    /* current object this placeholder is pinned to */
+    GdlDockObject    *host;
+    gboolean          sticky;
+    
+    /* when the placeholder is moved up the hierarchy, this stack
+       keeps track of the necessary dock positions needed to get the
+       placeholder to the original position */
+    GSList           *placement_stack;
+
+    /* connected signal handlers */
+    guint             host_detach_handler;
+    guint             host_dock_handler;
+};
+
+
+/* ----- Private interface ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockPlaceholder, gdl_dock_placeholder,
+			 GdlDockObject, GDL_TYPE_DOCK_OBJECT);
+
+static void 
+gdl_dock_placeholder_class_init (GdlDockPlaceholderClass *klass)
+{
+    GObjectClass       *g_object_class;
+    GtkObjectClass     *gtk_object_class;
+    GtkContainerClass  *container_class;
+    GdlDockObjectClass *object_class;
+    
+    g_object_class = G_OBJECT_CLASS (klass);
+    gtk_object_class = GTK_OBJECT_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    object_class = GDL_DOCK_OBJECT_CLASS (klass);
+
+    g_object_class->get_property = gdl_dock_placeholder_get_property;
+    g_object_class->set_property = gdl_dock_placeholder_set_property;
+    
+    g_object_class_install_property (
+	g_object_class, PROP_STICKY,
+	g_param_spec_boolean ("sticky", _("Sticky"),
+			      _("Whether the placeholder will stick to its host or "
+				"move up the hierarchy when the host is redocked"),
+			      FALSE,
+			      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+    
+    g_object_class_install_property (
+	g_object_class, PROP_HOST,
+	g_param_spec_object ("host", _("Host"),
+			     _("The dock object this placeholder is attached to"),
+			     GDL_TYPE_DOCK_OBJECT,
+			     G_PARAM_READWRITE));
+    
+    /* this will return the top of the placement stack */
+    g_object_class_install_property (
+	g_object_class, PROP_NEXT_PLACEMENT,
+	g_param_spec_enum ("next_placement", _("Next placement"),
+			   _("The position an item will be docked to our host if a "
+			     "request is made to dock to us"),
+			   GDL_TYPE_DOCK_PLACEMENT,
+			   GDL_DOCK_CENTER,
+			   G_PARAM_READWRITE |
+                           GDL_DOCK_PARAM_EXPORT | GDL_DOCK_PARAM_AFTER));
+    
+    gtk_object_class->destroy = gdl_dock_placeholder_destroy;
+    container_class->add = gdl_dock_placeholder_add;
+    
+    object_class->is_compound = FALSE;
+    object_class->detach = gdl_dock_placeholder_detach;
+    object_class->reduce = gdl_dock_placeholder_reduce;
+    object_class->dock = gdl_dock_placeholder_dock;
+    object_class->present = gdl_dock_placeholder_present;
+}
+
+static void 
+gdl_dock_placeholder_instance_init (GdlDockPlaceholder *ph)
+{
+    GTK_WIDGET_SET_FLAGS (ph, GTK_NO_WINDOW);
+    GTK_WIDGET_UNSET_FLAGS (ph, GTK_CAN_FOCUS);
+    
+    ph->_priv = g_new0 (GdlDockPlaceholderPrivate, 1);
+}
+
+static void 
+gdl_dock_placeholder_set_property (GObject      *g_object,
+				   guint         prop_id,
+				   const GValue *value,
+				   GParamSpec   *pspec)
+{
+    GdlDockPlaceholder *ph = GDL_DOCK_PLACEHOLDER (g_object);
+
+    switch (prop_id) {
+	case PROP_STICKY:
+            if (ph->_priv)
+                ph->_priv->sticky = g_value_get_boolean (value);
+	    break;
+	case PROP_HOST:
+            gdl_dock_placeholder_attach (ph, g_value_get_object (value));
+	    break;
+        case PROP_NEXT_PLACEMENT:
+            if (ph->_priv) {
+                ph->_priv->placement_stack =
+                    g_slist_prepend (ph->_priv->placement_stack,
+                                     (gpointer) g_value_get_enum (value));
+            }
+            break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (g_object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void 
+gdl_dock_placeholder_get_property (GObject    *g_object,
+				   guint       prop_id,
+				   GValue     *value,
+				   GParamSpec *pspec)
+{
+    GdlDockPlaceholder *ph = GDL_DOCK_PLACEHOLDER (g_object);
+
+    switch (prop_id) {
+	case PROP_STICKY:
+            if (ph->_priv)
+                g_value_set_boolean (value, ph->_priv->sticky);
+            else
+                g_value_set_boolean (value, FALSE);
+	    break;
+	case PROP_HOST:
+            if (ph->_priv)
+                g_value_set_object (value, ph->_priv->host);
+            else
+                g_value_set_object (value, NULL);
+	    break;
+	case PROP_NEXT_PLACEMENT:
+            if (ph->_priv && ph->_priv->placement_stack)
+                g_value_set_enum (value, (GdlDockPlacement) ph->_priv->placement_stack->data);
+            else
+                g_value_set_enum (value, GDL_DOCK_CENTER);
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (g_object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+gdl_dock_placeholder_destroy (GtkObject *object)
+{
+    GdlDockPlaceholder *ph = GDL_DOCK_PLACEHOLDER (object);
+
+    if (ph->_priv) {
+        if (ph->_priv->host)
+            gdl_dock_placeholder_detach (GDL_DOCK_OBJECT (object), FALSE);
+        g_free (ph->_priv);
+        ph->_priv = NULL;
+    }
+
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
+}
+
+static void 
+gdl_dock_placeholder_add (GtkContainer *container,
+                          GtkWidget    *widget)
+{
+    GdlDockPlaceholder *ph;
+    GdlDockPlacement    pos = GDL_DOCK_CENTER;   /* default position */
+    
+    g_return_if_fail (GDL_IS_DOCK_PLACEHOLDER (container));
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    ph = GDL_DOCK_PLACEHOLDER (container);
+    if (ph->_priv->placement_stack)
+        pos = (GdlDockPlacement) ph->_priv->placement_stack->data;
+        
+    gdl_dock_object_dock (GDL_DOCK_OBJECT (ph), GDL_DOCK_OBJECT (widget),
+                          pos, NULL);
+}
+
+static void
+gdl_dock_placeholder_detach (GdlDockObject *object,
+                             gboolean       recursive)
+{
+    GdlDockPlaceholder *ph = GDL_DOCK_PLACEHOLDER (object);
+
+    /* disconnect handlers */
+    disconnect_host (ph);
+    
+    /* free the placement stack */
+    g_slist_free (ph->_priv->placement_stack);
+    ph->_priv->placement_stack = NULL;
+
+    GDL_DOCK_OBJECT_UNSET_FLAGS (object, GDL_DOCK_ATTACHED);
+}
+
+static void 
+gdl_dock_placeholder_reduce (GdlDockObject *object)
+{
+    /* placeholders are not reduced */
+    return;
+}
+
+static void 
+gdl_dock_placeholder_dock (GdlDockObject    *object,
+			   GdlDockObject    *requestor,
+			   GdlDockPlacement  position,
+			   GValue           *other_data)
+{
+    GdlDockPlaceholder *ph = GDL_DOCK_PLACEHOLDER (object);
+    
+    if (ph->_priv->host) {
+        /* we simply act as a proxy for our host */
+        gdl_dock_object_dock (ph->_priv->host, requestor,
+                              position, other_data);
+    }
+    else {
+        GdlDockObject *toplevel;
+        
+        if (!gdl_dock_object_is_bound (GDL_DOCK_OBJECT (ph))) {
+            g_warning (_("Attempt to dock a dock object to an unbound placeholder"));
+            return;
+        }
+        
+        /* dock the item as a floating of the controller */
+        toplevel = gdl_dock_master_get_controller (GDL_DOCK_OBJECT_GET_MASTER (ph));
+        gdl_dock_object_dock (toplevel, requestor,
+                              GDL_DOCK_FLOATING, NULL);
+    }
+}
+
+#ifdef PLACEHOLDER_DEBUG
+static void
+print_placement_stack (GdlDockPlaceholder *ph)
+{
+    GSList *s = ph->_priv->placement_stack;
+    GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_ref (GDL_TYPE_DOCK_PLACEMENT));
+    GEnumValue *enum_value;
+    gchar *name;
+    GString *message;
+
+    message = g_string_new (NULL);
+    g_string_printf (message, "[%p] host: %p (%s), stack: ",
+                     ph, ph->_priv->host, G_OBJECT_TYPE_NAME (ph->_priv->host));
+    for (; s; s = s->next) {
+        enum_value = g_enum_get_value (enum_class, (GdlDockPlacement) s->data);
+        name = enum_value ? enum_value->value_name : NULL;
+        g_string_append_printf (message, "%s, ", name);
+    }
+    g_message ("%s", message->str);
+    
+    g_string_free (message, TRUE);
+    g_type_class_unref (enum_class);
+}
+#endif
+
+static void 
+gdl_dock_placeholder_present (GdlDockObject *object,
+                              GdlDockObject *child)
+{
+    /* do nothing */
+    return;
+}
+
+/* ----- Public interface ----- */
+
+GtkWidget * 
+gdl_dock_placeholder_new (gchar            *name,
+                          GdlDockObject    *object,
+                          GdlDockPlacement  position,
+                          gboolean          sticky)
+{
+    GdlDockPlaceholder *ph;
+
+    ph = GDL_DOCK_PLACEHOLDER (g_object_new (GDL_TYPE_DOCK_PLACEHOLDER,
+                                             "name", name,
+                                             "sticky", sticky,
+                                             NULL));
+    GDL_DOCK_OBJECT_UNSET_FLAGS (ph, GDL_DOCK_AUTOMATIC);
+
+    if (object) {
+        gdl_dock_placeholder_attach (ph, object);
+        if (position == GDL_DOCK_NONE)
+            position = GDL_DOCK_CENTER;
+        g_object_set (G_OBJECT (ph), "next_placement", position, NULL);
+        if (GDL_IS_DOCK (object)) {
+            /* the top placement will be consumed by the toplevel
+               dock, so add a dummy placement */
+            g_object_set (G_OBJECT (ph), "next_placement", GDL_DOCK_CENTER, NULL);
+        }
+        /* try a recursion */
+        do_excursion (ph);
+    }
+    
+    return GTK_WIDGET (ph);
+}
+
+static void 
+gdl_dock_placeholder_weak_notify (gpointer data,
+                                  GObject *old_object)
+{
+    GdlDockPlaceholder *ph;
+    
+    g_return_if_fail (data != NULL && GDL_IS_DOCK_PLACEHOLDER (data));
+
+    ph = GDL_DOCK_PLACEHOLDER (data);
+
+    /* we shouldn't get here, so perform an emergency detach. instead
+       we should have gotten a detach signal from our host */
+    ph->_priv->host = NULL;
+    /* free the placement stack */
+    g_slist_free (ph->_priv->placement_stack);
+    ph->_priv->placement_stack = NULL;
+
+    GDL_DOCK_OBJECT_UNSET_FLAGS (ph, GDL_DOCK_ATTACHED);
+}
+
+static void
+detach_cb (GdlDockObject *object,
+           gboolean       recursive,
+           gpointer       user_data)
+{
+    GdlDockPlaceholder *ph;
+    GdlDockObject      *new_host, *obj;
+
+    g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PLACEHOLDER (user_data));
+    
+    /* we go up in the hierarchy and we store the hinted placement in
+     * the placement stack so we can rebuild the docking layout later
+     * when we get the host's dock signal.  */
+
+    ph = GDL_DOCK_PLACEHOLDER (user_data);
+    obj = ph->_priv->host;
+    if (obj != object) {
+        g_warning (_("Got a detach signal from an object (%p) who is not "
+                     "our host %p"), object, ph->_priv->host);
+        return;
+    }
+    
+    /* skip sticky objects */
+    if (ph->_priv->sticky)
+        return;
+    
+    /* go up in the hierarchy */
+    new_host = gdl_dock_object_get_parent_object (obj);
+
+    while (new_host) {
+        GdlDockPlacement pos = GDL_DOCK_NONE;
+        
+        /* get placement hint from the new host */
+        if (gdl_dock_object_child_placement (new_host, obj, &pos)) {
+            ph->_priv->placement_stack = g_slist_prepend (
+                ph->_priv->placement_stack, (gpointer) pos);
+        }
+        else {
+            g_warning (_("Something weird happened while getting the child "
+                         "placement for %p from parent %p"), obj, new_host);
+        }
+
+        if (!GDL_DOCK_OBJECT_IN_DETACH (new_host))
+            /* we found a "stable" dock object */
+            break;
+        
+        obj = new_host;
+        new_host = gdl_dock_object_get_parent_object (obj);
+    }
+
+    /* disconnect host */
+    disconnect_host (ph);
+
+    if (!new_host) {
+        /* the toplevel was detached: we attach ourselves to the
+           controller with an initial placement of floating */
+        new_host = gdl_dock_master_get_controller (GDL_DOCK_OBJECT_GET_MASTER (ph));
+        ph->_priv->placement_stack = g_slist_prepend (
+            ph->_priv->placement_stack, (gpointer) GDL_DOCK_FLOATING);
+    }
+    if (new_host)
+        connect_host (ph, new_host);
+
+#ifdef PLACEHOLDER_DEBUG
+    print_placement_stack (ph);
+#endif
+}
+
+/**
+ * do_excursion:
+ * @ph: placeholder object
+ *
+ * Tries to shrink the placement stack by examining the host's
+ * children and see if any of them matches the placement which is at
+ * the top of the stack.  If this is the case, it tries again with the
+ * new host.
+ **/
+static void
+do_excursion (GdlDockPlaceholder *ph)
+{
+    if (ph->_priv->host &&
+        !ph->_priv->sticky &&
+        ph->_priv->placement_stack &&
+        gdl_dock_object_is_compound (ph->_priv->host)) {
+
+        GdlDockPlacement pos, stack_pos =
+            (GdlDockPlacement) ph->_priv->placement_stack->data;
+        GList           *children, *l;
+        GdlDockObject   *host = ph->_priv->host;
+        
+        children = gtk_container_get_children (GTK_CONTAINER (host));
+        for (l = children; l; l = l->next) {
+            pos = stack_pos;
+            gdl_dock_object_child_placement (GDL_DOCK_OBJECT (host),
+                                             GDL_DOCK_OBJECT (l->data),
+                                             &pos);
+            if (pos == stack_pos) {
+                /* remove the stack position */
+                ph->_priv->placement_stack =
+                    g_slist_remove_link (ph->_priv->placement_stack,
+                                         ph->_priv->placement_stack);
+                
+                /* connect to the new host */
+                disconnect_host (ph);
+                connect_host (ph, GDL_DOCK_OBJECT (l->data));
+
+                /* recurse... */
+                if (!GDL_DOCK_OBJECT_IN_REFLOW (l->data))
+                    do_excursion (ph);
+                
+                break;
+            }
+        }
+        g_list_free (children);
+    }
+}
+
+static void 
+dock_cb (GdlDockObject    *object,
+         GdlDockObject    *requestor,
+         GdlDockPlacement  position,
+         GValue           *other_data,
+         gpointer          user_data)
+{
+    GdlDockPlacement    pos = GDL_DOCK_NONE;
+    GdlDockPlaceholder *ph;
+    
+    g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PLACEHOLDER (user_data));
+    ph = GDL_DOCK_PLACEHOLDER (user_data);
+    g_return_if_fail (ph->_priv->host == object);
+    
+    /* see if the given position is compatible for the stack's top
+       element */
+    if (!ph->_priv->sticky && ph->_priv->placement_stack) {
+        pos = (GdlDockPlacement) ph->_priv->placement_stack->data;
+        if (gdl_dock_object_child_placement (object, requestor, &pos)) {
+            if (pos == (GdlDockPlacement) ph->_priv->placement_stack->data) {
+                /* the position is compatible: excurse down */
+                do_excursion (ph);
+            }
+        }
+    }
+#ifdef PLACEHOLDER_DEBUG
+    print_placement_stack (ph);
+#endif
+}
+
+static void
+disconnect_host (GdlDockPlaceholder *ph)
+{
+    if (!ph->_priv->host)
+        return;
+    
+    if (ph->_priv->host_detach_handler)
+        g_signal_handler_disconnect (ph->_priv->host, ph->_priv->host_detach_handler);
+    if (ph->_priv->host_dock_handler)
+        g_signal_handler_disconnect (ph->_priv->host, ph->_priv->host_dock_handler);
+    ph->_priv->host_detach_handler = 0;
+    ph->_priv->host_dock_handler = 0;
+
+    /* remove weak ref to object */
+    g_object_weak_unref (G_OBJECT (ph->_priv->host),
+                         gdl_dock_placeholder_weak_notify, ph);
+    ph->_priv->host = NULL;
+}
+
+static void
+connect_host (GdlDockPlaceholder *ph,
+              GdlDockObject      *new_host)
+{
+    if (ph->_priv->host)
+        disconnect_host (ph);
+    
+    ph->_priv->host = new_host;
+    g_object_weak_ref (G_OBJECT (ph->_priv->host),
+                       gdl_dock_placeholder_weak_notify, ph);
+
+    ph->_priv->host_detach_handler =
+        g_signal_connect (ph->_priv->host,
+                          "detach",
+                          (GCallback) detach_cb,
+                          (gpointer) ph);
+    
+    ph->_priv->host_dock_handler =
+        g_signal_connect (ph->_priv->host,
+                          "dock",
+                          (GCallback) dock_cb,
+                          (gpointer) ph);
+}
+
+void
+gdl_dock_placeholder_attach (GdlDockPlaceholder *ph,
+                             GdlDockObject      *object)
+{
+    g_return_if_fail (ph != NULL && GDL_IS_DOCK_PLACEHOLDER (ph));
+    g_return_if_fail (ph->_priv != NULL);
+    g_return_if_fail (object != NULL);
+    
+    /* object binding */
+    if (!gdl_dock_object_is_bound (GDL_DOCK_OBJECT (ph)))
+        gdl_dock_object_bind (GDL_DOCK_OBJECT (ph), object->master);
+
+    g_return_if_fail (GDL_DOCK_OBJECT (ph)->master == object->master);
+        
+    gdl_dock_object_freeze (GDL_DOCK_OBJECT (ph));
+    
+    /* detach from previous host first */
+    if (ph->_priv->host)
+        gdl_dock_object_detach (GDL_DOCK_OBJECT (ph), FALSE);
+
+    connect_host (ph, object);
+    
+    GDL_DOCK_OBJECT_SET_FLAGS (ph, GDL_DOCK_ATTACHED);
+    
+    gdl_dock_object_thaw (GDL_DOCK_OBJECT (ph));
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-placeholder.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * gdl-dock-placeholder.h - Placeholders for docking items
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_PLACEHOLDER_H__
+#define __GDL_DOCK_PLACEHOLDER_H__
+
+#include <gdl/gdl-dock-object.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_PLACEHOLDER             (gdl_dock_placeholder_get_type ())
+#define GDL_DOCK_PLACEHOLDER(obj)             (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_PLACEHOLDER, GdlDockPlaceholder))
+#define GDL_DOCK_PLACEHOLDER_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_PLACEHOLDER, GdlDockPlaceholderClass))
+#define GDL_IS_DOCK_PLACEHOLDER(obj)          (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_PLACEHOLDER))
+#define GDL_IS_DOCK_PLACEHOLDER_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_PLACEHOLDER))
+#define GDL_DOCK_PLACEHOLDER_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_PLACEHOLDER, GdlDockPlaceholderClass))
+
+/* data types & structures */
+typedef struct _GdlDockPlaceholder        GdlDockPlaceholder;
+typedef struct _GdlDockPlaceholderClass   GdlDockPlaceholderClass;
+typedef struct _GdlDockPlaceholderPrivate GdlDockPlaceholderPrivate;
+
+struct _GdlDockPlaceholder {
+    GdlDockObject              object;
+
+    GdlDockPlaceholderPrivate *_priv;
+};
+
+struct _GdlDockPlaceholderClass {
+    GdlDockObjectClass parent_class;
+};
+
+/* public interface */
+
+GType       gdl_dock_placeholder_get_type (void);
+
+GtkWidget  *gdl_dock_placeholder_new      (gchar              *name,
+                                           GdlDockObject      *object,
+                                           GdlDockPlacement    position,
+                                           gboolean            sticky);
+
+void        gdl_dock_placeholder_attach   (GdlDockPlaceholder *ph,
+                                           GdlDockObject      *object);
+
+
+G_END_DECLS
+
+#endif /* __GDL_DOCK_PLACEHOLDER_H__ */

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,623 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * gdl-dock-tablabel.c
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <libgnome/gnome-macros.h>
+#include <gtk/gtk.h>
+
+#include "gdl-dock-tablabel.h"
+#include "gdl-tools.h"
+#include "gdl-dock-item.h"
+#include "libgdlmarshal.h"
+
+
+/* ----- Private prototypes ----- */
+
+static void  gdl_dock_tablabel_class_init    (GdlDockTablabelClass *klass);
+static void  gdl_dock_tablabel_instance_init (GdlDockTablabel      *tablabel);
+
+static void  gdl_dock_tablabel_set_property  (GObject              *object,
+                                              guint                 prop_id,
+                                              const GValue         *value,
+                                              GParamSpec           *pspec);
+static void  gdl_dock_tablabel_get_property  (GObject              *object,
+                                              guint                 prop_id,
+                                              GValue               *value,
+                                              GParamSpec           *pspec);
+
+static void  gdl_dock_tablabel_item_notify   (GObject            *master,
+                                              GParamSpec         *pspec,
+                                              gpointer            data);
+
+static void  gdl_dock_tablabel_size_request  (GtkWidget          *widget,
+                                              GtkRequisition     *requisition);
+static void  gdl_dock_tablabel_size_allocate (GtkWidget          *widget,
+                                              GtkAllocation      *allocation);
+                                              
+static void  gdl_dock_tablabel_paint         (GtkWidget      *widget,
+                                              GdkEventExpose *event);
+static gint  gdl_dock_tablabel_expose        (GtkWidget      *widget,
+                                              GdkEventExpose *event);
+
+static gboolean gdl_dock_tablabel_button_event  (GtkWidget      *widget,
+                                                 GdkEventButton *event);
+static gboolean gdl_dock_tablabel_motion_event  (GtkWidget      *widget,
+                                                 GdkEventMotion *event);
+
+static void  gdl_dock_tablabel_realize (GtkWidget *widget);
+static void  gdl_dock_tablabel_unrealize (GtkWidget *widget);
+static void  gdl_dock_tablabel_map (GtkWidget *widget);
+static void  gdl_dock_tablabel_unmap (GtkWidget *widget);
+
+/* ----- Private data types and variables ----- */
+
+#define DEFAULT_DRAG_HANDLE_SIZE 10
+#define HANDLE_RATIO 1.0
+
+enum {
+    BUTTON_PRESSED_HANDLE,
+    LAST_SIGNAL
+};
+
+enum {
+    PROP_0,
+    PROP_ITEM
+};
+
+
+static guint dock_tablabel_signals [LAST_SIGNAL] = { 0 };
+
+
+/* ----- Private interface ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDockTablabel, gdl_dock_tablabel,
+                         GtkBin, GTK_TYPE_BIN);
+
+static void
+gdl_dock_tablabel_class_init (GdlDockTablabelClass *klass)
+{
+    GObjectClass      *g_object_class;
+    GtkObjectClass    *object_class;
+    GtkWidgetClass    *widget_class;
+    GtkContainerClass *container_class;
+
+    g_object_class = G_OBJECT_CLASS (klass);
+    object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    
+    g_object_class->set_property = gdl_dock_tablabel_set_property;
+    g_object_class->get_property = gdl_dock_tablabel_get_property;
+
+    widget_class->size_request = gdl_dock_tablabel_size_request;
+    widget_class->size_allocate = gdl_dock_tablabel_size_allocate;
+    widget_class->expose_event = gdl_dock_tablabel_expose;
+    widget_class->button_press_event = gdl_dock_tablabel_button_event;
+    widget_class->button_release_event = gdl_dock_tablabel_button_event;
+    widget_class->motion_notify_event = gdl_dock_tablabel_motion_event;
+    widget_class->realize = gdl_dock_tablabel_realize;
+    widget_class->unrealize = gdl_dock_tablabel_unrealize;
+    widget_class->map = gdl_dock_tablabel_map;
+    widget_class->unmap = gdl_dock_tablabel_unmap;
+
+    g_object_class_install_property (
+        g_object_class, PROP_ITEM,
+        g_param_spec_object ("item", _("Controlling dock item"),
+                             _("Dockitem which 'owns' this tablabel"),
+                             GDL_TYPE_DOCK_ITEM,
+                             G_PARAM_READWRITE));
+
+    dock_tablabel_signals [BUTTON_PRESSED_HANDLE] =
+        g_signal_new ("button_pressed_handle",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (GdlDockTablabelClass, 
+                                       button_pressed_handle),
+                      NULL, NULL,
+                      gdl_marshal_VOID__BOXED,
+                      G_TYPE_NONE,
+                      1,
+                      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+    klass->button_pressed_handle = NULL;
+}
+
+static void
+gdl_dock_tablabel_instance_init (GdlDockTablabel *tablabel)
+{
+    GtkWidget *widget;
+    GtkWidget *label_widget;
+
+    widget = GTK_WIDGET (tablabel);
+
+    tablabel->drag_handle_size = DEFAULT_DRAG_HANDLE_SIZE;
+    tablabel->item = NULL;
+
+    label_widget = gtk_label_new ("Dock item");
+    gtk_container_add (GTK_CONTAINER (tablabel), label_widget);
+    gtk_widget_show (label_widget);
+
+    tablabel->active = FALSE;
+    gtk_widget_set_state (GTK_WIDGET (tablabel), GTK_STATE_ACTIVE);
+}
+
+static void
+gdl_dock_tablabel_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+    GdlDockTablabel *tablabel;
+    GtkBin          *bin;
+
+    tablabel = GDL_DOCK_TABLABEL (object);
+
+    switch (prop_id) {
+        case PROP_ITEM:
+            if (tablabel->item) {
+                g_object_remove_weak_pointer (G_OBJECT (tablabel->item), 
+                                              (gpointer *) &tablabel->item);
+                g_signal_handlers_disconnect_by_func (
+                    tablabel->item, gdl_dock_tablabel_item_notify, tablabel);
+            };
+
+            tablabel->item = g_value_get_object (value);
+            if (tablabel->item) {
+                gboolean locked;
+                gchar   *long_name;
+                
+                g_object_add_weak_pointer (G_OBJECT (tablabel->item), 
+                                           (gpointer *) &tablabel->item);
+
+                g_signal_connect (tablabel->item, "notify::locked",
+                                  G_CALLBACK (gdl_dock_tablabel_item_notify),
+                                  tablabel);
+                g_signal_connect (tablabel->item, "notify::long_name",
+                                  G_CALLBACK (gdl_dock_tablabel_item_notify),
+                                  tablabel);
+                g_signal_connect (tablabel->item, "notify::grip_size",
+                                  G_CALLBACK (gdl_dock_tablabel_item_notify),
+                                  tablabel);
+
+                g_object_get (tablabel->item,
+                              "locked", &locked,
+                              "long_name", &long_name,
+                              "grip_size", &tablabel->drag_handle_size,
+                              NULL);
+
+                if (locked)
+                    tablabel->drag_handle_size = 0;
+                
+                bin = GTK_BIN (tablabel);
+                if (bin->child && g_object_class_find_property (
+                    G_OBJECT_GET_CLASS (bin->child), "label"))
+                    g_object_set (bin->child, "label", long_name, NULL);
+                g_free (long_name);
+            };
+            break;
+            
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_tablabel_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+    GdlDockTablabel *tablabel;
+
+    tablabel = GDL_DOCK_TABLABEL (object);
+
+    switch (prop_id) {
+        case PROP_ITEM:
+            g_value_set_object (value, tablabel->item);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_tablabel_item_notify (GObject    *master,
+                               GParamSpec *pspec,
+                               gpointer    data)
+{
+    GdlDockTablabel *tablabel = GDL_DOCK_TABLABEL (data);
+    gboolean         locked;
+    gchar           *label;
+    GtkBin          *bin;
+    
+    g_object_get (master,
+                  "locked", &locked,
+                  "grip_size", &tablabel->drag_handle_size,
+                  "long_name", &label,
+                  NULL);
+
+    if (locked)
+        tablabel->drag_handle_size = 0;
+
+    bin = GTK_BIN (tablabel);
+    if (bin->child && g_object_class_find_property (
+        G_OBJECT_GET_CLASS (bin->child), "label"))
+        g_object_set (bin->child, "label", label, NULL);
+    g_free (label);
+
+    gtk_widget_queue_resize (GTK_WIDGET (tablabel));
+}
+
+static void
+gdl_dock_tablabel_size_request (GtkWidget      *widget,
+                                GtkRequisition *requisition)
+{
+    GtkBin          *bin;
+    GtkRequisition   child_req;
+    GdlDockTablabel *tablabel;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_TABLABEL (widget));
+    g_return_if_fail (requisition != NULL);
+
+    tablabel = GDL_DOCK_TABLABEL (widget);
+    bin = GTK_BIN (widget);
+
+    requisition->width = tablabel->drag_handle_size;
+    requisition->height = 0;
+
+    if (bin->child)
+        gtk_widget_size_request (bin->child, &child_req);
+    else
+        child_req.width = child_req.height = 0;
+        
+    requisition->width += child_req.width;
+    requisition->height += child_req.height;
+
+    requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+    requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+
+    widget->requisition = *requisition;
+}
+
+static void
+gdl_dock_tablabel_size_allocate (GtkWidget     *widget,
+                                 GtkAllocation *allocation)
+{
+    GtkBin          *bin;
+    GdlDockTablabel *tablabel;
+    gint             border_width;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK_TABLABEL (widget));
+    g_return_if_fail (allocation != NULL);
+  
+    bin = GTK_BIN (widget);
+    tablabel = GDL_DOCK_TABLABEL (widget);
+
+    border_width = GTK_CONTAINER (widget)->border_width;
+  
+    widget->allocation = *allocation;
+
+    if (GTK_WIDGET_REALIZED (widget))
+        gdk_window_move_resize (tablabel->event_window, 
+                                allocation->x, 
+                                allocation->y,
+                                allocation->width, 
+                                allocation->height);
+
+    if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
+        GtkAllocation  child_allocation;
+
+        child_allocation.x = widget->allocation.x + border_width;
+        child_allocation.y = widget->allocation.y + border_width;
+
+        allocation->width = MAX (1, (int) allocation->width - 
+                                 (int) tablabel->drag_handle_size);
+        child_allocation.x += tablabel->drag_handle_size;
+
+        child_allocation.width = 
+            MAX (1, (int) allocation->width - 2 * border_width);
+        child_allocation.height = 
+            MAX (1, (int) allocation->height - 2 * border_width);
+
+        gtk_widget_size_allocate (bin->child, &child_allocation);
+    }
+}
+
+static void
+gdl_dock_tablabel_paint (GtkWidget      *widget,
+                         GdkEventExpose *event)
+{
+    GdkRectangle     dest, rect;
+    GtkBin          *bin;
+    GdlDockTablabel *tablabel;
+    gint             border_width;
+
+    bin = GTK_BIN (widget);
+    tablabel = GDL_DOCK_TABLABEL (widget);
+    border_width = GTK_CONTAINER (widget)->border_width;
+
+    rect.x = widget->allocation.x + border_width;
+    rect.y = widget->allocation.y + border_width;
+    rect.width = tablabel->drag_handle_size * HANDLE_RATIO;
+    rect.height = widget->allocation.height - 2*border_width;
+
+    if (gdk_rectangle_intersect (&event->area, &rect, &dest)) {
+        gtk_paint_handle (widget->style, widget->window, 
+                          tablabel->active ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE, 
+                          GTK_SHADOW_NONE,
+                          &dest, widget, "dock_tablabel",
+                          rect.x, rect.y, rect.width, rect.height,
+                          GTK_ORIENTATION_VERTICAL);
+    };
+}
+
+static gint
+gdl_dock_tablabel_expose (GtkWidget      *widget,
+                          GdkEventExpose *event)
+{
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_TABLABEL (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+
+    if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) {
+        GNOME_CALL_PARENT (GTK_WIDGET_CLASS, expose_event, (widget, event));
+        gdl_dock_tablabel_paint (widget, event);
+    };
+  
+    return FALSE;
+}
+
+static gboolean 
+gdl_dock_tablabel_button_event (GtkWidget      *widget,
+                                GdkEventButton *event)
+{
+    GdlDockTablabel *tablabel;
+    gboolean         event_handled;
+  
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_TABLABEL (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+    
+    tablabel = GDL_DOCK_TABLABEL (widget);
+    
+    event_handled = FALSE;
+
+    if (event->window != tablabel->event_window)
+        return FALSE;
+    
+    switch (event->type) {
+        case GDK_BUTTON_PRESS:
+            if (tablabel->active) {
+                gboolean in_handle;
+                gint     rel_x, rel_y;
+                guint    border_width;
+                GtkBin  *bin;
+
+                bin = GTK_BIN (widget);
+                border_width = GTK_CONTAINER (widget)->border_width;
+
+                rel_x = event->x - border_width;
+                rel_y = event->y - border_width;
+
+                /* Check if user clicked on the drag handle. */      
+                in_handle = (rel_x < tablabel->drag_handle_size * HANDLE_RATIO) &&
+                    (rel_x > 0);
+
+                if (event->button == 1) {
+                    tablabel->pre_drag = TRUE;
+                    tablabel->drag_start_event = *event;
+                }
+                else {
+                    g_signal_emit (widget, 
+                                   dock_tablabel_signals [BUTTON_PRESSED_HANDLE],
+                                   0,
+                                   event);
+                }
+                
+                event_handled = TRUE;
+            }
+            break;
+
+        case GDK_BUTTON_RELEASE:
+            tablabel->pre_drag = FALSE;
+            break;
+
+        default:
+            break;
+    }
+    
+    if (!event_handled) {
+        /* propagate the event to the parent's gdkwindow */
+        GdkEventButton e;
+
+        e = *event;
+        e.window = gtk_widget_get_parent_window (widget);
+        e.x += widget->allocation.x;
+        e.y += widget->allocation.y;
+        
+        gdk_event_put ((GdkEvent *) &e);
+    };
+
+    return event_handled;
+}
+
+static gboolean 
+gdl_dock_tablabel_motion_event (GtkWidget      *widget,
+                                GdkEventMotion *event)
+{
+    GdlDockTablabel *tablabel;
+    gboolean         event_handled;
+  
+    g_return_val_if_fail (widget != NULL, FALSE);
+    g_return_val_if_fail (GDL_IS_DOCK_TABLABEL (widget), FALSE);
+    g_return_val_if_fail (event != NULL, FALSE);
+    
+    tablabel = GDL_DOCK_TABLABEL (widget);
+    
+    event_handled = FALSE;
+
+    if (event->window != tablabel->event_window)
+        return FALSE;
+    
+    if (tablabel->pre_drag) {
+        if (gtk_drag_check_threshold (widget,
+                                      tablabel->drag_start_event.x,
+                                      tablabel->drag_start_event.y,
+                                      event->x,
+                                      event->y)) {
+            tablabel->pre_drag = FALSE;
+            g_signal_emit (widget, 
+                           dock_tablabel_signals [BUTTON_PRESSED_HANDLE],
+                           0,
+                           &tablabel->drag_start_event);
+            event_handled = TRUE;
+        }
+    }
+    
+    if (!event_handled) {
+        /* propagate the event to the parent's gdkwindow */
+        GdkEventMotion e;
+
+        e = *event;
+        e.window = gtk_widget_get_parent_window (widget);
+        e.x += widget->allocation.x;
+        e.y += widget->allocation.y;
+        
+        gdk_event_put ((GdkEvent *) &e);
+    };
+
+    return event_handled;
+}
+
+static void   
+gdl_dock_tablabel_realize (GtkWidget *widget)
+{
+    GdlDockTablabel *tablabel;
+    GdkWindowAttr attributes;
+    int attributes_mask;
+    
+    tablabel = GDL_DOCK_TABLABEL (widget);
+    
+    attributes.window_type = GDK_WINDOW_CHILD;
+    attributes.x = widget->allocation.x;
+    attributes.y = widget->allocation.y;
+    attributes.width = widget->allocation.width;
+    attributes.height = widget->allocation.height;
+    attributes.wclass = GDK_INPUT_ONLY;
+    attributes.event_mask = gtk_widget_get_events (widget);
+    attributes.event_mask |= (GDK_EXPOSURE_MASK | 
+                              GDK_BUTTON_PRESS_MASK |
+                              GDK_BUTTON_RELEASE_MASK | 
+                              GDK_ENTER_NOTIFY_MASK | 
+                              GDK_POINTER_MOTION_MASK | 
+                              GDK_LEAVE_NOTIFY_MASK);
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    
+    widget->window = gtk_widget_get_parent_window (widget);
+    g_object_ref (widget->window);
+    
+    tablabel->event_window = 
+        gdk_window_new (gtk_widget_get_parent_window (widget),
+                        &attributes, attributes_mask);
+    gdk_window_set_user_data (tablabel->event_window, widget);
+    
+    widget->style = gtk_style_attach (widget->style, widget->window);
+    
+    GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+}
+
+static void   
+gdl_dock_tablabel_unrealize (GtkWidget *widget)
+{
+    GdlDockTablabel *tablabel = GDL_DOCK_TABLABEL (widget);
+    
+    if (tablabel->event_window) {
+        gdk_window_set_user_data (tablabel->event_window, NULL);
+        gdk_window_destroy (tablabel->event_window);
+        tablabel->event_window = NULL;
+    }
+    
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, unrealize, (widget));
+}
+
+static void  
+gdl_dock_tablabel_map (GtkWidget *widget)
+{
+    GdlDockTablabel *tablabel = GDL_DOCK_TABLABEL (widget);
+    
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, map, (widget));
+    
+    gdk_window_show (tablabel->event_window);
+}
+
+static void   
+gdl_dock_tablabel_unmap (GtkWidget *widget)
+{
+    GdlDockTablabel *tablabel = GDL_DOCK_TABLABEL (widget);
+
+    gdk_window_hide (tablabel->event_window);
+
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, unmap, (widget));
+}
+
+/* ----- Public interface ----- */
+
+GtkWidget *
+gdl_dock_tablabel_new (GdlDockItem *item)
+{
+    GdlDockTablabel *tablabel;
+
+    tablabel = GDL_DOCK_TABLABEL (g_object_new (GDL_TYPE_DOCK_TABLABEL,
+                                                "item", item,
+                                                NULL));
+    
+    return GTK_WIDGET (tablabel);
+}
+
+void
+gdl_dock_tablabel_activate (GdlDockTablabel *tablabel)
+{
+    g_return_if_fail (tablabel != NULL);
+
+    tablabel->active = TRUE;
+    gtk_widget_set_state (GTK_WIDGET (tablabel), GTK_STATE_NORMAL);
+}
+
+void
+gdl_dock_tablabel_deactivate (GdlDockTablabel *tablabel)
+{
+    g_return_if_fail (tablabel != NULL);
+
+    tablabel->active = FALSE;
+    /* yeah, i know it contradictive */
+    gtk_widget_set_state (GTK_WIDGET (tablabel), GTK_STATE_ACTIVE);
+}

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock-tablabel.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * gdl-dock-tablabel.h
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_TABLABEL_H__
+#define __GDL_DOCK_TABLABEL_H__
+
+#include <gtk/gtk.h>
+#include <gdl/gdl-dock-item.h>
+
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK_TABLABEL            (gdl_dock_tablabel_get_type ())
+#define GDL_DOCK_TABLABEL(obj)            (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK_TABLABEL, GdlDockTablabel))
+#define GDL_DOCK_TABLABEL_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK_TABLABEL, GdlDockTablabelClass))
+#define GDL_IS_DOCK_TABLABEL(obj)         (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK_TABLABEL))
+#define GDL_IS_DOCK_TABLABEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK_TABLABEL))
+#define GDL_DOCK_TABLABEL_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK_TABLABEL, GdlDockTablabelClass))
+
+/* data types & structures */
+typedef struct _GdlDockTablabel      GdlDockTablabel;
+typedef struct _GdlDockTablabelClass GdlDockTablabelClass;
+
+struct _GdlDockTablabel {
+    GtkBin          parent;
+
+    guint           drag_handle_size;
+    GtkWidget      *item;
+    GdkWindow      *event_window;
+    gboolean        active;
+
+    GdkEventButton  drag_start_event;
+    gboolean        pre_drag;
+};
+
+struct _GdlDockTablabelClass {
+    GtkBinClass      parent_class;
+
+    void            (*button_pressed_handle)  (GdlDockTablabel *tablabel,
+                                               GdkEventButton  *event);
+};
+
+/* public interface */
+ 
+GtkWidget     *gdl_dock_tablabel_new           (GdlDockItem *item);
+GType          gdl_dock_tablabel_get_type      (void);
+
+void           gdl_dock_tablabel_activate      (GdlDockTablabel *tablabel);
+void           gdl_dock_tablabel_deactivate    (GdlDockTablabel *tablabel);
+
+G_END_DECLS
+
+#endif

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.c
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.c	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.c	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,1206 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gdl-i18n.h"
+#include <stdlib.h>
+#include <string.h>
+#include <gdk/gdkx.h>
+#include <libgnome/gnome-macros.h>
+
+#include "gdl-tools.h"
+#include "gdl-dock.h"
+#include "gdl-dock-master.h"
+#include "gdl-dock-paned.h"
+#include "gdl-dock-notebook.h"
+#include "gdl-dock-placeholder.h"
+
+#include "libgdlmarshal.h"
+
+
+/* ----- Private prototypes ----- */
+
+static void  gdl_dock_class_init      (GdlDockClass *class);
+static void  gdl_dock_instance_init   (GdlDock *dock);
+
+static GObject *gdl_dock_constructor  (GType                  type,
+                                       guint                  n_construct_properties,
+                                       GObjectConstructParam *construct_param);
+static void  gdl_dock_set_property    (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec);
+static void  gdl_dock_get_property    (GObject      *object,
+                                       guint         prop_id,
+                                       GValue       *value,
+                                       GParamSpec   *pspec);
+static void  gdl_dock_notify_cb       (GObject      *object,
+                                       GParamSpec   *pspec,
+                                       gpointer      user_data);
+
+static void  gdl_dock_set_title       (GdlDock      *dock);
+
+static void  gdl_dock_destroy         (GtkObject    *object);
+
+static void  gdl_dock_size_request    (GtkWidget      *widget,
+                                       GtkRequisition *requisition);
+static void  gdl_dock_size_allocate   (GtkWidget      *widget,
+                                       GtkAllocation  *allocation);
+static void  gdl_dock_map             (GtkWidget      *widget);
+static void  gdl_dock_unmap           (GtkWidget      *widget);
+static void  gdl_dock_show            (GtkWidget      *widget);
+static void  gdl_dock_hide            (GtkWidget      *widget);
+
+static void  gdl_dock_add             (GtkContainer *container,
+                                       GtkWidget    *widget);
+static void  gdl_dock_remove          (GtkContainer *container,
+                                       GtkWidget    *widget);
+static void  gdl_dock_forall          (GtkContainer *container,
+                                       gboolean      include_internals,
+                                       GtkCallback   callback,
+                                       gpointer      callback_data);
+static GtkType  gdl_dock_child_type   (GtkContainer *container);
+
+static void     gdl_dock_detach       (GdlDockObject    *object,
+                                       gboolean          recursive);
+static void     gdl_dock_reduce       (GdlDockObject    *object);
+static gboolean gdl_dock_dock_request (GdlDockObject    *object,
+                                       gint              x,
+                                       gint              y,
+                                       GdlDockRequest   *request);
+static void     gdl_dock_dock         (GdlDockObject    *object,
+                                       GdlDockObject    *requestor,
+                                       GdlDockPlacement  position,
+                                       GValue           *other_data);
+static gboolean gdl_dock_reorder      (GdlDockObject    *object,
+                                       GdlDockObject    *requestor,
+                                       GdlDockPlacement  new_position,
+                                       GValue           *other_data);
+
+static gboolean gdl_dock_floating_window_delete_event_cb (GtkWidget *widget);
+
+static gboolean gdl_dock_child_placement  (GdlDockObject    *object,
+                                           GdlDockObject    *child,
+                                           GdlDockPlacement *placement);
+
+static void     gdl_dock_present          (GdlDockObject    *object,
+                                           GdlDockObject    *child);
+
+
+/* ----- Class variables and definitions ----- */
+
+struct _GdlDockPrivate
+{
+    /* for floating docks */
+    gboolean            floating;
+    GtkWidget          *window;
+    gboolean            auto_title;
+    
+    gint                float_x;
+    gint                float_y;
+    gint                width;
+    gint                height;
+    
+    /* auxiliary fields */
+    GdkGC              *xor_gc;
+};
+
+enum {
+    LAYOUT_CHANGED,
+    LAST_SIGNAL
+};
+
+enum {
+    PROP_0,
+    PROP_FLOATING,
+    PROP_DEFAULT_TITLE,
+    PROP_WIDTH,
+    PROP_HEIGHT,
+    PROP_FLOAT_X,
+    PROP_FLOAT_Y
+};
+
+static guint dock_signals [LAST_SIGNAL] = { 0 };
+
+#define SPLIT_RATIO  0.3
+
+
+/* ----- Private functions ----- */
+
+GNOME_CLASS_BOILERPLATE (GdlDock, gdl_dock, GdlDockObject, GDL_TYPE_DOCK_OBJECT);
+
+static void
+gdl_dock_class_init (GdlDockClass *klass)
+{
+    GObjectClass       *g_object_class;
+    GtkObjectClass     *gtk_object_class;
+    GtkWidgetClass     *widget_class;
+    GtkContainerClass  *container_class;
+    GdlDockObjectClass *object_class;
+    
+    g_object_class = G_OBJECT_CLASS (klass);
+    gtk_object_class = GTK_OBJECT_CLASS (klass);
+    widget_class = GTK_WIDGET_CLASS (klass);
+    container_class = GTK_CONTAINER_CLASS (klass);
+    object_class = GDL_DOCK_OBJECT_CLASS (klass);
+    
+    g_object_class->constructor = gdl_dock_constructor;
+    g_object_class->set_property = gdl_dock_set_property;
+    g_object_class->get_property = gdl_dock_get_property;
+    
+    /* properties */
+
+    g_object_class_install_property (
+        g_object_class, PROP_FLOATING,
+        g_param_spec_boolean ("floating", _("Floating"),
+                              _("Whether the dock is floating in its own window"),
+                              FALSE,
+                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                              GDL_DOCK_PARAM_EXPORT));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_DEFAULT_TITLE,
+        g_param_spec_string ("default_title", _("Default title"),
+                             _("Default title for the newly created floating docks"),
+                             NULL,
+                             G_PARAM_READWRITE));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_WIDTH,
+        g_param_spec_int ("width", _("Width"),
+                          _("Width for the dock when it's of floating type"),
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+                          GDL_DOCK_PARAM_EXPORT));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_HEIGHT,
+        g_param_spec_int ("height", _("Height"),
+                          _("Height for the dock when it's of floating type"),
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+                          GDL_DOCK_PARAM_EXPORT));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_FLOAT_X,
+        g_param_spec_int ("floatx", _("Float X"),
+                          _("X coordinate for a floating dock"),
+                          G_MININT, G_MAXINT, 0,
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+                          GDL_DOCK_PARAM_EXPORT));
+    
+    g_object_class_install_property (
+        g_object_class, PROP_FLOAT_Y,
+        g_param_spec_int ("floaty", _("Float Y"),
+                          _("Y coordinate for a floating dock"),
+                          G_MININT, G_MAXINT, 0,
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+                          GDL_DOCK_PARAM_EXPORT));
+    
+    gtk_object_class->destroy = gdl_dock_destroy;
+
+    widget_class->size_request = gdl_dock_size_request;
+    widget_class->size_allocate = gdl_dock_size_allocate;
+    widget_class->map = gdl_dock_map;
+    widget_class->unmap = gdl_dock_unmap;
+    widget_class->show = gdl_dock_show;
+    widget_class->hide = gdl_dock_hide;
+    
+    container_class->add = gdl_dock_add;
+    container_class->remove = gdl_dock_remove;
+    container_class->forall = gdl_dock_forall;
+    container_class->child_type = gdl_dock_child_type;
+    
+    object_class->is_compound = TRUE;
+    
+    object_class->detach = gdl_dock_detach;
+    object_class->reduce = gdl_dock_reduce;
+    object_class->dock_request = gdl_dock_dock_request;
+    object_class->dock = gdl_dock_dock;
+    object_class->reorder = gdl_dock_reorder;    
+    object_class->child_placement = gdl_dock_child_placement;
+    object_class->present = gdl_dock_present;
+    
+    /* signals */
+
+    dock_signals [LAYOUT_CHANGED] = 
+        g_signal_new ("layout_changed", 
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (GdlDockClass, layout_changed),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__VOID,
+                      G_TYPE_NONE, /* return type */
+                      0);
+
+    klass->layout_changed = NULL;
+}
+
+static void
+gdl_dock_instance_init (GdlDock *dock)
+{
+    GTK_WIDGET_SET_FLAGS (GTK_WIDGET (dock), GTK_NO_WINDOW);
+
+    dock->root = NULL;
+    dock->_priv = g_new0 (GdlDockPrivate, 1);
+    dock->_priv->width = -1;
+    dock->_priv->height = -1;
+}
+
+static gboolean 
+gdl_dock_floating_configure_event_cb (GtkWidget         *widget,
+                                      GdkEventConfigure *event,
+                                      gpointer           user_data)
+{
+    GdlDock *dock;
+    
+    g_return_val_if_fail (user_data != NULL && GDL_IS_DOCK (user_data), TRUE);
+
+    dock = GDL_DOCK (user_data);
+    dock->_priv->float_x = event->x;
+    dock->_priv->float_y = event->y;
+    dock->_priv->width = event->width;
+    dock->_priv->height = event->height;
+
+    return FALSE;
+}
+
+static GObject *
+gdl_dock_constructor (GType                  type,
+                      guint                  n_construct_properties,
+                      GObjectConstructParam *construct_param)
+{
+    GObject *g_object;
+    
+    g_object = GNOME_CALL_PARENT_WITH_DEFAULT (G_OBJECT_CLASS, 
+                                               constructor, 
+                                               (type,
+                                                n_construct_properties,
+                                                construct_param),
+                                               NULL);
+    if (g_object) {
+        GdlDock *dock = GDL_DOCK (g_object);
+        GdlDockMaster *master;
+        
+        /* create a master for the dock if none was provided in the construction */
+        master = GDL_DOCK_OBJECT_GET_MASTER (GDL_DOCK_OBJECT (dock));
+        if (!master) {
+            GDL_DOCK_OBJECT_UNSET_FLAGS (dock, GDL_DOCK_AUTOMATIC);
+            master = g_object_new (GDL_TYPE_DOCK_MASTER, NULL);
+            /* the controller owns the master ref */
+            gdl_dock_object_bind (GDL_DOCK_OBJECT (dock), G_OBJECT (master));
+        }
+
+        if (dock->_priv->floating) {
+            GdlDockObject *controller;
+            
+            /* create floating window for this dock */
+            dock->_priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+            g_object_set_data (G_OBJECT (dock->_priv->window), "dock", dock);
+            
+            /* set position and default size */
+            gtk_window_set_position (GTK_WINDOW (dock->_priv->window),
+                                     GTK_WIN_POS_MOUSE);
+            gtk_window_set_default_size (GTK_WINDOW (dock->_priv->window),
+                                         dock->_priv->width,
+                                         dock->_priv->height);
+            gtk_window_set_type_hint (GTK_WINDOW (dock->_priv->window),
+                                      GDK_WINDOW_TYPE_HINT_NORMAL);
+            
+            /* metacity ignores this */
+            gtk_window_move (GTK_WINDOW (dock->_priv->window),
+                             dock->_priv->float_x,
+                             dock->_priv->float_y);
+            
+            /* connect to the configure event so we can track down window geometry */
+            g_signal_connect (dock->_priv->window, "configure_event",
+                              (GCallback) gdl_dock_floating_configure_event_cb,
+                              dock);
+            
+            /* set the title and connect to the long_name notify queue
+               so we can reset the title when this prop changes */
+            gdl_dock_set_title (dock);
+            g_signal_connect (dock, "notify::long_name",
+                              (GCallback) gdl_dock_notify_cb, NULL);
+            
+            /* set transient for the first dock if that is a non-floating dock */
+            controller = gdl_dock_master_get_controller (master);
+            if (controller && GDL_IS_DOCK (controller)) {
+                gboolean first_is_floating;
+                g_object_get (controller, "floating", &first_is_floating, NULL);
+                if (!first_is_floating) {
+                    GtkWidget *toplevel =
+                        gtk_widget_get_toplevel (GTK_WIDGET (controller));
+
+                    if (GTK_IS_WINDOW (toplevel))
+                        gtk_window_set_transient_for (GTK_WINDOW (dock->_priv->window),
+                                                      GTK_WINDOW (toplevel));
+                }
+            }
+
+            gtk_container_add (GTK_CONTAINER (dock->_priv->window), GTK_WIDGET (dock));
+    
+            g_signal_connect (dock->_priv->window, "delete_event",
+                              G_CALLBACK (gdl_dock_floating_window_delete_event_cb), 
+                              NULL);
+        }
+        GDL_DOCK_OBJECT_SET_FLAGS (dock, GDL_DOCK_ATTACHED);
+    }
+    
+    return g_object;
+}
+
+static void
+gdl_dock_set_property  (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+    GdlDock *dock = GDL_DOCK (object);
+    
+    switch (prop_id) {
+        case PROP_FLOATING:
+            dock->_priv->floating = g_value_get_boolean (value);
+            break;
+        case PROP_DEFAULT_TITLE:
+            if (GDL_DOCK_OBJECT (object)->master)
+                g_object_set (GDL_DOCK_OBJECT (object)->master,
+                              "default_title", g_value_get_string (value),
+                              NULL);
+            break;
+        case PROP_WIDTH:
+            dock->_priv->width = g_value_get_int (value);
+            break;
+        case PROP_HEIGHT:
+            dock->_priv->height = g_value_get_int (value);
+            break;
+        case PROP_FLOAT_X:
+            dock->_priv->float_x = g_value_get_int (value);
+            break;
+        case PROP_FLOAT_Y:
+            dock->_priv->float_y = g_value_get_int (value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+
+    switch (prop_id) {
+        case PROP_WIDTH:
+        case PROP_HEIGHT:
+        case PROP_FLOAT_X:
+        case PROP_FLOAT_Y:
+            if (dock->_priv->floating && dock->_priv->window) {
+                gtk_window_resize (GTK_WINDOW (dock->_priv->window),
+                                   dock->_priv->width,
+                                   dock->_priv->height);
+            }
+            break;
+    }
+}
+
+static void
+gdl_dock_get_property  (GObject      *object,
+                        guint         prop_id,
+                        GValue       *value,
+                        GParamSpec   *pspec)
+{
+    GdlDock *dock = GDL_DOCK (object);
+
+    switch (prop_id) {
+        case PROP_FLOATING:
+            g_value_set_boolean (value, dock->_priv->floating);
+            break;
+        case PROP_DEFAULT_TITLE:
+            if (GDL_DOCK_OBJECT (object)->master) {
+                gchar *default_title;
+                g_object_get (GDL_DOCK_OBJECT (object)->master,
+                              "default_title", &default_title,
+                              NULL);
+                g_value_take_string (value, default_title);
+            }
+            else
+                g_value_set_string (value, NULL);
+            break;
+        case PROP_WIDTH:
+            g_value_set_int (value, dock->_priv->width);
+            break;
+        case PROP_HEIGHT:
+            g_value_set_int (value, dock->_priv->height);
+            break;
+        case PROP_FLOAT_X:
+            g_value_set_int (value, dock->_priv->float_x);
+            break;
+        case PROP_FLOAT_Y:
+            g_value_set_int (value, dock->_priv->float_y);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gdl_dock_set_title (GdlDock *dock)
+{
+    GdlDockObject *object = GDL_DOCK_OBJECT (dock);
+    gchar         *title = NULL;
+    gboolean       free_title = FALSE;
+    
+    if (!dock->_priv->window)
+        return;
+    
+    if (!dock->_priv->auto_title && object->long_name) {
+        title = object->long_name;
+    }
+    else if (object->master) {
+        g_object_get (object->master, "default_title", &title, NULL);
+        free_title = TRUE;
+    }
+
+    if (!title && dock->root) {
+        g_object_get (dock->root, "long_name", &title, NULL);
+        free_title = TRUE;
+    }
+    
+    if (!title) {
+        /* set a default title in the long_name */
+        dock->_priv->auto_title = TRUE;
+        free_title = FALSE;
+        title = object->long_name = g_strdup_printf (
+            _("Dock #%d"), GDL_DOCK_MASTER (object->master)->dock_number++);
+    }
+
+    gtk_window_set_title (GTK_WINDOW (dock->_priv->window), title);
+    if (free_title)
+        g_free (title);
+}
+
+static void
+gdl_dock_notify_cb (GObject    *object,
+                    GParamSpec *pspec,
+                    gpointer    user_data)
+{
+    GdlDock *dock;
+    
+    g_return_if_fail (object != NULL || GDL_IS_DOCK (object));
+    
+    dock = GDL_DOCK (object);
+    dock->_priv->auto_title = FALSE;
+    gdl_dock_set_title (dock);
+}
+
+static void
+gdl_dock_destroy (GtkObject *object)
+{
+    GdlDock *dock = GDL_DOCK (object);
+
+    if (dock->_priv) {
+        GdlDockPrivate *priv = dock->_priv;
+        dock->_priv = NULL;
+
+        if (priv->window) {
+            gtk_widget_destroy (priv->window);
+            priv->floating = FALSE;
+            priv->window = NULL;
+        }
+        
+        /* destroy the xor gc */
+        if (priv->xor_gc) {
+            g_object_unref (priv->xor_gc);
+            priv->xor_gc = NULL;
+        }
+
+        g_free (priv);
+    }
+    
+    GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
+}
+
+static void
+gdl_dock_size_request (GtkWidget      *widget,
+                       GtkRequisition *requisition)
+{
+    GdlDock      *dock;
+    GtkContainer *container;
+    guint         border_width;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+
+    dock = GDL_DOCK (widget);
+    container = GTK_CONTAINER (widget);
+    border_width = container->border_width;
+
+    /* make request to root */
+    if (dock->root && GTK_WIDGET_VISIBLE (dock->root))
+        gtk_widget_size_request (GTK_WIDGET (dock->root), requisition);
+    else {
+        requisition->width = 0;
+        requisition->height = 0;
+    };
+
+    requisition->width += 2 * border_width;
+    requisition->height += 2 * border_width;
+
+    widget->requisition = *requisition;
+}
+
+static void
+gdl_dock_size_allocate (GtkWidget     *widget,
+                        GtkAllocation *allocation)
+{
+    GdlDock      *dock;
+    GtkContainer *container;
+    guint         border_width;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+    
+    dock = GDL_DOCK (widget);
+    container = GTK_CONTAINER (widget);
+    border_width = container->border_width;
+
+    widget->allocation = *allocation;
+
+    /* reduce allocation by border width */
+    allocation->x += border_width;
+    allocation->y += border_width;
+    allocation->width = MAX (1, allocation->width - 2 * border_width);
+    allocation->height = MAX (1, allocation->height - 2 * border_width);
+
+    if (dock->root && GTK_WIDGET_VISIBLE (dock->root))
+        gtk_widget_size_allocate (GTK_WIDGET (dock->root), allocation);
+}
+
+static void
+gdl_dock_map (GtkWidget *widget)
+{
+    GtkWidget *child;
+    GdlDock   *dock;
+
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+
+    dock = GDL_DOCK (widget);
+
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, map, (widget));
+
+    if (dock->root) {
+        child = GTK_WIDGET (dock->root);
+        if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
+            gtk_widget_map (child);
+    }
+}
+
+static void
+gdl_dock_unmap (GtkWidget *widget)
+{
+    GtkWidget *child;
+    GdlDock   *dock;
+    
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+
+    dock = GDL_DOCK (widget);
+
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, unmap, (widget));
+
+    if (dock->root) {
+        child = GTK_WIDGET (dock->root);
+        if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_MAPPED (child))
+            gtk_widget_unmap (child);
+    }
+    
+    if (dock->_priv->window)
+        gtk_widget_unmap (dock->_priv->window);
+}
+
+static void
+gdl_dock_foreach_automatic (GdlDockObject *object,
+                            gpointer       user_data)
+{
+    void (* function) (GtkWidget *) = user_data;
+
+    if (GDL_DOCK_OBJECT_AUTOMATIC (object))
+        (* function) (GTK_WIDGET (object));
+}
+
+static void
+gdl_dock_show (GtkWidget *widget)
+{
+    GdlDock *dock;
+    
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+    
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, show, (widget));
+    
+    dock = GDL_DOCK (widget);
+    if (dock->_priv->floating && dock->_priv->window)
+        gtk_widget_show (dock->_priv->window);
+
+    if (GDL_DOCK_IS_CONTROLLER (dock)) {
+        gdl_dock_master_foreach_toplevel (GDL_DOCK_OBJECT_GET_MASTER (dock),
+                                          FALSE, (GFunc) gdl_dock_foreach_automatic,
+                                          gtk_widget_show);
+    }
+}
+
+static void
+gdl_dock_hide (GtkWidget *widget)
+{
+    GdlDock *dock;
+    
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (GDL_IS_DOCK (widget));
+    
+    GNOME_CALL_PARENT (GTK_WIDGET_CLASS, hide, (widget));
+    
+    dock = GDL_DOCK (widget);
+    if (dock->_priv->floating && dock->_priv->window)
+        gtk_widget_hide (dock->_priv->window);
+
+    if (GDL_DOCK_IS_CONTROLLER (dock)) {
+        gdl_dock_master_foreach_toplevel (GDL_DOCK_OBJECT_GET_MASTER (dock),
+                                          FALSE, (GFunc) gdl_dock_foreach_automatic,
+                                          gtk_widget_hide);
+    }
+}
+
+static void
+gdl_dock_add (GtkContainer *container,
+              GtkWidget    *widget)
+{
+    g_return_if_fail (container != NULL);
+    g_return_if_fail (GDL_IS_DOCK (container));
+    g_return_if_fail (GDL_IS_DOCK_ITEM (widget));
+
+    gdl_dock_add_item (GDL_DOCK (container), 
+                       GDL_DOCK_ITEM (widget), 
+                       GDL_DOCK_TOP);  /* default position */
+}
+
+static void
+gdl_dock_remove (GtkContainer *container,
+                 GtkWidget    *widget)
+{
+    GdlDock  *dock;
+    gboolean  was_visible;
+
+    g_return_if_fail (container != NULL);
+    g_return_if_fail (widget != NULL);
+
+    dock = GDL_DOCK (container);
+    was_visible = GTK_WIDGET_VISIBLE (widget);
+
+    if (GTK_WIDGET (dock->root) == widget) {
+        dock->root = NULL;
+        GDL_DOCK_OBJECT_UNSET_FLAGS (widget, GDL_DOCK_ATTACHED);
+        gtk_widget_unparent (widget);
+
+        if (was_visible && GTK_WIDGET_VISIBLE (GTK_WIDGET (container)))
+            gtk_widget_queue_resize (GTK_WIDGET (dock));
+    }
+}
+
+static void
+gdl_dock_forall (GtkContainer *container,
+                 gboolean      include_internals,
+                 GtkCallback   callback,
+                 gpointer      callback_data)
+{
+    GdlDock *dock;
+
+    g_return_if_fail (container != NULL);
+    g_return_if_fail (GDL_IS_DOCK (container));
+    g_return_if_fail (callback != NULL);
+
+    dock = GDL_DOCK (container);
+
+    if (dock->root)
+        (*callback) (GTK_WIDGET (dock->root), callback_data);
+}
+
+static GtkType
+gdl_dock_child_type (GtkContainer *container)
+{
+    return GDL_TYPE_DOCK_ITEM;
+}
+
+static void
+gdl_dock_detach (GdlDockObject *object,
+                 gboolean       recursive)
+{
+    GdlDock *dock = GDL_DOCK (object);
+    
+    /* detach children */
+    if (recursive && dock->root) {
+        gdl_dock_object_detach (dock->root, recursive);
+    }
+    GDL_DOCK_OBJECT_UNSET_FLAGS (object, GDL_DOCK_ATTACHED);
+}
+
+static void
+gdl_dock_reduce (GdlDockObject *object)
+{
+    GdlDock *dock = GDL_DOCK (object);
+    
+    if (dock->root)
+        return;
+    
+    if (GDL_DOCK_OBJECT_AUTOMATIC (dock)) {
+        gtk_widget_destroy (GTK_WIDGET (dock));
+
+    } else if (!GDL_DOCK_OBJECT_ATTACHED (dock)) {
+        /* if the user explicitly detached the object */
+        if (dock->_priv->floating)
+            gtk_widget_hide (GTK_WIDGET (dock));
+        else {
+            GtkWidget *widget = GTK_WIDGET (object);
+            if (widget->parent) 
+                gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+        }
+    }
+}
+
+static gboolean
+gdl_dock_dock_request (GdlDockObject  *object,
+                       gint            x,
+                       gint            y,
+                       GdlDockRequest *request)
+{
+    GdlDock            *dock;
+    guint               bw;
+    gint                rel_x, rel_y;
+    GtkAllocation      *alloc;
+    gboolean            may_dock = FALSE;
+    GdlDockRequest      my_request;
+
+    g_return_val_if_fail (GDL_IS_DOCK (object), FALSE);
+
+    /* we get (x,y) in our allocation coordinates system */
+    
+    dock = GDL_DOCK (object);
+    
+    /* Get dock size. */
+    alloc = &(GTK_WIDGET (dock)->allocation);
+    bw = GTK_CONTAINER (dock)->border_width;
+
+    /* Get coordinates relative to our allocation area. */
+    rel_x = x - alloc->x;
+    rel_y = y - alloc->y;
+
+    if (request)
+        my_request = *request;
+        
+    /* Check if coordinates are in GdlDock widget. */
+    if (rel_x > 0 && rel_x < alloc->width &&
+        rel_y > 0 && rel_y < alloc->height) {
+
+        /* It's inside our area. */
+        may_dock = TRUE;
+
+	/* Set docking indicator rectangle to the GdlDock size. */
+        my_request.rect.x = alloc->x + bw;
+        my_request.rect.y = alloc->y + bw;
+        my_request.rect.width = alloc->width - 2*bw;
+        my_request.rect.height = alloc->height - 2*bw;
+
+	/* If GdlDock has no root item yet, set the dock itself as 
+	   possible target. */
+        if (!dock->root) {
+            my_request.position = GDL_DOCK_TOP;
+            my_request.target = object;
+        } else {
+            my_request.target = dock->root;
+
+            /* See if it's in the border_width band. */
+            if (rel_x < bw) {
+                my_request.position = GDL_DOCK_LEFT;
+                my_request.rect.width *= SPLIT_RATIO;
+            } else if (rel_x > alloc->width - bw) {
+                my_request.position = GDL_DOCK_RIGHT;
+                my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
+                my_request.rect.width *= SPLIT_RATIO;
+            } else if (rel_y < bw) {
+                my_request.position = GDL_DOCK_TOP;
+                my_request.rect.height *= SPLIT_RATIO;
+            } else if (rel_y > alloc->height - bw) {
+                my_request.position = GDL_DOCK_BOTTOM;
+                my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
+                my_request.rect.height *= SPLIT_RATIO;
+            } else {
+                /* Otherwise try our children. */
+                /* give them allocation coordinates (we are a
+                   GTK_NO_WINDOW) widget */
+                may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock->root), 
+                                                         x, y, &my_request);
+            }
+        }
+    }
+
+    if (may_dock && request)
+        *request = my_request;
+    
+    return may_dock;
+}
+
+static void
+gdl_dock_dock (GdlDockObject    *object,
+               GdlDockObject    *requestor,
+               GdlDockPlacement  position,
+               GValue           *user_data)
+{
+    GdlDock *dock;
+    
+    g_return_if_fail (GDL_IS_DOCK (object));
+    /* only dock items allowed at this time */
+    g_return_if_fail (GDL_IS_DOCK_ITEM (requestor));
+
+    dock = GDL_DOCK (object);
+    
+    if (position == GDL_DOCK_FLOATING) {
+        GdlDockItem *item = GDL_DOCK_ITEM (requestor);
+        gint x, y, width, height;
+
+        if (user_data && G_VALUE_HOLDS (user_data, GDK_TYPE_RECTANGLE)) {
+            GdkRectangle *rect;
+
+            rect = g_value_get_boxed (user_data);
+            x = rect->x;
+            y = rect->y;
+            width = rect->width;
+            height = rect->height;
+        }
+        else {
+            x = y = 0;
+            width = height = -1;
+        }
+        
+        gdl_dock_add_floating_item (dock, item,
+                                    x, y, width, height);
+    }
+    else if (dock->root) {
+        /* This is somewhat a special case since we know which item to
+           pass the request on because we only have on child */
+        gdl_dock_object_dock (dock->root, requestor, position, NULL);
+        gdl_dock_set_title (dock);
+        
+    }
+    else { /* Item about to be added is root item. */
+        GtkWidget *widget = GTK_WIDGET (requestor);
+        
+        dock->root = requestor;
+        GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED);
+        gtk_widget_set_parent (widget, GTK_WIDGET (dock));
+        
+        gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor));
+
+        /* Realize the item (create its corresponding GdkWindow) when 
+           GdlDock has been realized. */
+        if (GTK_WIDGET_REALIZED (dock))
+            gtk_widget_realize (widget);
+        
+        /* Map the widget if it's visible and the parent is visible and has 
+           been mapped. This is done to make sure that the GdkWindow is 
+           visible. */
+        if (GTK_WIDGET_VISIBLE (dock) && 
+            GTK_WIDGET_VISIBLE (widget)) {
+            if (GTK_WIDGET_MAPPED (dock))
+                gtk_widget_map (widget);
+            
+            /* Make the widget resize. */
+            gtk_widget_queue_resize (widget);
+        }
+        gdl_dock_set_title (dock);
+    }
+}
+    
+static gboolean
+gdl_dock_floating_window_delete_event_cb (GtkWidget *widget)
+{
+    GdlDock *dock;
+    
+    g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+    
+    dock = GDL_DOCK (g_object_get_data (G_OBJECT (widget), "dock"));
+    if (dock->root) {
+        /* this will call reduce on ourselves, hiding the window if appropiate */
+        gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock->root));
+    }
+
+    return TRUE;
+}
+
+static void
+_gdl_dock_foreach_build_list (GdlDockObject *object,
+                              gpointer       user_data)
+{
+    GList **l = (GList **) user_data;
+
+    if (GDL_IS_DOCK_ITEM (object))
+        *l = g_list_prepend (*l, object);
+}
+
+static gboolean
+gdl_dock_reorder (GdlDockObject    *object,
+                  GdlDockObject    *requestor,
+                  GdlDockPlacement  new_position,
+                  GValue           *other_data)
+{
+    GdlDock *dock = GDL_DOCK (object);
+    gboolean handled = FALSE;
+    
+    if (dock->_priv->floating &&
+        new_position == GDL_DOCK_FLOATING &&
+        dock->root == requestor) {
+        
+        if (other_data && G_VALUE_HOLDS (other_data, GDK_TYPE_RECTANGLE)) {
+            GdkRectangle *rect;
+
+            rect = g_value_get_boxed (other_data);
+            gtk_window_move (GTK_WINDOW (dock->_priv->window),
+                             rect->x,
+                             rect->y);
+            handled = TRUE;
+        }
+    }
+    
+    return handled;
+}
+
+static gboolean 
+gdl_dock_child_placement (GdlDockObject    *object,
+                          GdlDockObject    *child,
+                          GdlDockPlacement *placement)
+{
+    GdlDock *dock = GDL_DOCK (object);
+    gboolean retval = TRUE;
+    
+    if (dock->root == child) {
+        if (placement) {
+            if (*placement == GDL_DOCK_NONE || *placement == GDL_DOCK_FLOATING)
+                *placement = GDL_DOCK_TOP;
+        }
+    } else 
+        retval = FALSE;
+
+    return retval;
+}
+
+static void 
+gdl_dock_present (GdlDockObject *object,
+                  GdlDockObject *child)
+{
+    GdlDock *dock = GDL_DOCK (object);
+
+    if (dock->_priv->floating)
+        gtk_window_present (GTK_WINDOW (dock->_priv->window));
+}
+
+
+/* ----- Public interface ----- */
+
+GtkWidget *
+gdl_dock_new (void)
+{
+    GObject *dock;
+
+    dock = g_object_new (GDL_TYPE_DOCK, NULL);
+    GDL_DOCK_OBJECT_UNSET_FLAGS (dock, GDL_DOCK_AUTOMATIC);
+    
+    return GTK_WIDGET (dock);
+}
+
+GtkWidget *
+gdl_dock_new_from (GdlDock  *original,
+                   gboolean  floating)
+{
+    GObject *new_dock;
+    
+    g_return_val_if_fail (original != NULL, NULL);
+    
+    new_dock = g_object_new (GDL_TYPE_DOCK, 
+                             "master", GDL_DOCK_OBJECT_GET_MASTER (original), 
+                             "floating", floating,
+                             NULL);
+    GDL_DOCK_OBJECT_UNSET_FLAGS (new_dock, GDL_DOCK_AUTOMATIC);
+    
+    return GTK_WIDGET (new_dock);
+}
+
+void
+gdl_dock_add_item (GdlDock          *dock,
+                   GdlDockItem      *item,
+                   GdlDockPlacement  placement)
+{
+    g_return_if_fail (dock != NULL);
+    g_return_if_fail (item != NULL);
+
+    if (placement == GDL_DOCK_FLOATING)
+        /* Add the item to a new floating dock */
+        gdl_dock_add_floating_item (dock, item, 0, 0, -1, -1);
+
+    else {
+        /* Non-floating item. */
+        gdl_dock_object_dock (GDL_DOCK_OBJECT (dock),
+                              GDL_DOCK_OBJECT (item),
+                              placement, NULL);
+    }
+}
+
+void
+gdl_dock_add_floating_item (GdlDock        *dock,
+                            GdlDockItem    *item,
+                            gint            x,
+                            gint            y,
+                            gint            width,
+                            gint            height)
+{
+    GdlDock *new_dock;
+    
+    g_return_if_fail (dock != NULL);
+    g_return_if_fail (item != NULL);
+    
+    new_dock = GDL_DOCK (g_object_new (GDL_TYPE_DOCK, 
+                                       "master", GDL_DOCK_OBJECT_GET_MASTER (dock), 
+                                       "floating", TRUE,
+                                       "width", width,
+                                       "height", height,
+                                       "floatx", x,
+                                       "floaty", y,
+                                       NULL));
+    
+    if (GTK_WIDGET_VISIBLE (dock)) {
+        gtk_widget_show (GTK_WIDGET (new_dock));
+        if (GTK_WIDGET_MAPPED (dock))
+            gtk_widget_map (GTK_WIDGET (new_dock));
+        
+        /* Make the widget resize. */
+        gtk_widget_queue_resize (GTK_WIDGET (new_dock));
+    }
+
+    gdl_dock_add_item (GDL_DOCK (new_dock), item, GDL_DOCK_TOP);
+}
+
+GdlDockItem *
+gdl_dock_get_item_by_name (GdlDock     *dock,
+                           const gchar *name)
+{
+    GdlDockObject *found;
+    
+    g_return_val_if_fail (dock != NULL && name != NULL, NULL);
+    
+    /* proxy the call to our master */
+    found = gdl_dock_master_get_object (GDL_DOCK_OBJECT_GET_MASTER (dock), name);
+
+    return (found && GDL_IS_DOCK_ITEM (found)) ? GDL_DOCK_ITEM (found) : NULL;
+}
+
+GdlDockPlaceholder *
+gdl_dock_get_placeholder_by_name (GdlDock     *dock,
+                                  const gchar *name)
+{
+    GdlDockObject *found;
+    
+    g_return_val_if_fail (dock != NULL && name != NULL, NULL);
+    
+    /* proxy the call to our master */
+    found = gdl_dock_master_get_object (GDL_DOCK_OBJECT_GET_MASTER (dock), name);
+
+    return (found && GDL_IS_DOCK_PLACEHOLDER (found)) ?
+        GDL_DOCK_PLACEHOLDER (found) : NULL;
+}
+
+GList *
+gdl_dock_get_named_items (GdlDock *dock)
+{
+    GList *list = NULL;
+    
+    g_return_val_if_fail (dock != NULL, NULL);
+
+    gdl_dock_master_foreach (GDL_DOCK_OBJECT_GET_MASTER (dock),
+                             (GFunc) _gdl_dock_foreach_build_list, &list);
+
+    return list;
+}
+
+GdlDock *
+gdl_dock_object_get_toplevel (GdlDockObject *object)
+{
+    GdlDockObject *parent = object;
+    
+    g_return_val_if_fail (object != NULL, NULL);
+
+    while (parent && !GDL_IS_DOCK (parent))
+        parent = gdl_dock_object_get_parent_object (parent);
+
+    return parent ? GDL_DOCK (parent) : NULL;
+}
+
+void
+gdl_dock_xor_rect (GdlDock      *dock,
+                   GdkRectangle *rect)
+{
+    GtkWidget *widget;
+    gint8      dash_list [2];
+
+    widget = GTK_WIDGET (dock);
+
+    if (!dock->_priv->xor_gc) {
+        if (GTK_WIDGET_REALIZED (widget)) {
+            GdkGCValues values;
+
+            values.function = GDK_INVERT;
+            values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+            dock->_priv->xor_gc = gdk_gc_new_with_values 
+                (widget->window, &values, GDK_GC_FUNCTION | GDK_GC_SUBWINDOW);
+        } else 
+            return;
+    };
+
+    gdk_gc_set_line_attributes (dock->_priv->xor_gc, 1,
+                                GDK_LINE_ON_OFF_DASH,
+                                GDK_CAP_NOT_LAST,
+                                GDK_JOIN_BEVEL);
+    
+    dash_list [0] = 1;
+    dash_list [1] = 1;
+    
+    gdk_gc_set_dashes (dock->_priv->xor_gc, 1, dash_list, 2);
+
+    gdk_draw_rectangle (widget->window, dock->_priv->xor_gc, 0, 
+                        rect->x, rect->y,
+                        rect->width, rect->height);
+
+    gdk_gc_set_dashes (dock->_priv->xor_gc, 0, dash_list, 2);
+
+    gdk_draw_rectangle (widget->window, dock->_priv->xor_gc, 0, 
+                        rect->x + 1, rect->y + 1,
+                        rect->width - 2, rect->height - 2);
+}
+

Added: trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.h
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.h	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl/gdl-dock.h	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,100 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This file is part of the GNOME Devtools Libraries.
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __GDL_DOCK_H__
+#define __GDL_DOCK_H__
+
+#include <gtk/gtk.h>
+#include <gdl/gdl-dock-object.h>
+#include <gdl/gdl-dock-item.h>
+#include <gdl/gdl-dock-placeholder.h>
+
+G_BEGIN_DECLS
+
+/* standard macros */
+#define GDL_TYPE_DOCK            (gdl_dock_get_type ())
+#define GDL_DOCK(obj)            (GTK_CHECK_CAST ((obj), GDL_TYPE_DOCK, GdlDock))
+#define GDL_DOCK_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GDL_TYPE_DOCK, GdlDockClass))
+#define GDL_IS_DOCK(obj)         (GTK_CHECK_TYPE ((obj), GDL_TYPE_DOCK))
+#define GDL_IS_DOCK_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GDL_TYPE_DOCK))
+#define GDL_DOCK_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DOCK, GdlDockClass))
+
+/* data types & structures */
+typedef struct _GdlDock        GdlDock;
+typedef struct _GdlDockClass   GdlDockClass;
+typedef struct _GdlDockPrivate GdlDockPrivate;
+
+struct _GdlDock {
+    GdlDockObject    object;
+
+    GdlDockObject   *root;
+
+    GdlDockPrivate  *_priv;
+};
+
+struct _GdlDockClass {
+    GdlDockObjectClass parent_class;
+
+    void  (* layout_changed)  (GdlDock *dock);    /* proxy signal for the master */
+};
+
+/* additional macros */
+#define GDL_DOCK_IS_CONTROLLER(dock)  \
+    (gdl_dock_master_get_controller (GDL_DOCK_OBJECT_GET_MASTER (dock)) == \
+     GDL_DOCK_OBJECT (dock))
+
+/* public interface */
+ 
+GtkWidget     *gdl_dock_new               (void);
+
+GtkWidget     *gdl_dock_new_from          (GdlDock          *original,
+                                           gboolean          floating);
+
+GType          gdl_dock_get_type          (void);
+
+void           gdl_dock_add_item          (GdlDock          *dock,
+                                           GdlDockItem      *item,
+                                           GdlDockPlacement  place);
+
+void           gdl_dock_add_floating_item (GdlDock        *dock,
+                                           GdlDockItem    *item,
+                                           gint            x,
+                                           gint            y,
+                                           gint            width,
+                                           gint            height);
+
+GdlDockItem   *gdl_dock_get_item_by_name  (GdlDock     *dock,
+                                           const gchar *name);
+
+GdlDockPlaceholder *gdl_dock_get_placeholder_by_name (GdlDock     *dock,
+                                                      const gchar *name);
+
+GList         *gdl_dock_get_named_items   (GdlDock    *dock);
+
+GdlDock       *gdl_dock_object_get_toplevel (GdlDockObject *object);
+
+void           gdl_dock_xor_rect            (GdlDock       *dock,
+                                             GdkRectangle  *rect);
+
+G_END_DECLS
+
+#endif

Added: trunk/MonoDevelop/gdldock/sources/gdl-sharp-sources.xml
===================================================================
--- trunk/MonoDevelop/gdldock/sources/gdl-sharp-sources.xml	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/sources/gdl-sharp-sources.xml	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,9 @@
+<gapi-parser-input>
+  <api filename="../gdl/gdl-api.xml">
+    <library name="gdl-1">
+      <namespace name="Gdl">
+        <dir>gdl</dir>
+      </namespace>
+    </library>
+  </api>
+</gapi-parser-input>

Added: trunk/MonoDevelop/gdldock/test/GdlDockTest.cs
===================================================================
--- trunk/MonoDevelop/gdldock/test/GdlDockTest.cs	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/test/GdlDockTest.cs	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,53 @@
+using System;
+using Gtk;
+using GtkSharp;
+using Gnome;
+using GnomeSharp;
+using Gdl;
+using GdlSharp;
+
+class T
+{
+	Program program;
+	
+	static void Main (string[] args)
+	{
+		new T (args);
+	}
+	
+	T (string[] args)
+	{
+		program = new Program ("test", "0.0", Modules.UI, args);
+		App app = new App ("test", "Test for Gdl.Dock widget");
+		app.SetDefaultSize (600, 450);
+		app.DeleteEvent += new DeleteEventHandler (OnAppDelete);
+		
+		Dock dock = new Dock ();
+		DockLayout layout = new DockLayout (dock);
+		
+		DockItem di = new DockItem ("item1", "Item #1", DockItemBehavior.Locked);
+		di.Add (new Label ("test"));
+		dock.AddItem (di, DockPlacement.Right);
+		
+		DockItem di2 = new DockItem ("item2", "Item #2", DockItemBehavior.Locked);
+		di2.Add (new Label ("test2"));
+		dock.AddItem (di2, DockPlacement.Bottom);
+		
+		DockItem di3 = new DockItem ("item3", "Item #3", DockItemBehavior.Locked);
+		di3.Add (new Label ("test3"));
+		dock.AddItem (di3, DockPlacement.Left);
+		
+		DockItem di4 = new DockItem ("item4", "Item #4", DockItemBehavior.Locked);
+		di4.Add (new Label ("test4"));
+		dock.AddItem (di4, DockPlacement.Top);
+		
+		app.Contents = dock;
+		app.ShowAll ();
+		program.Run ();
+	}
+	
+	private void OnAppDelete (object o, DeleteEventArgs args)
+	{
+		program.Quit ();
+	}
+}

Added: trunk/MonoDevelop/gdldock/test/Makefile
===================================================================
--- trunk/MonoDevelop/gdldock/test/Makefile	2004-01-31 18:40:50 UTC (rev 733)
+++ trunk/MonoDevelop/gdldock/test/Makefile	2004-01-31 19:16:43 UTC (rev 734)
@@ -0,0 +1,8 @@
+all:
+	mcs -g GdlDockTest.cs /r:gtk-sharp.dll /r:gdl-sharp.dll /r:gnome-sharp.dll -o GdlDockTest.exe
+
+run:
+	mono --debug GdlDockTest.exe
+
+clean:
+	rm -f GdlDockTest.exe




More information about the Monodevelop-patches-list mailing list