[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 << 0" />
+ <member cname="GDL_DOCK_ITEM_BEH_NEVER_VERTICAL" name="NeverVertical" value="1 << 1" />
+ <member cname="GDL_DOCK_ITEM_BEH_NEVER_HORIZONTAL" name="NeverHorizontal" value="1 << 2" />
+ <member cname="GDL_DOCK_ITEM_BEH_LOCKED" name="Locked" value="1 << 3" />
+ <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_TOP" name="CantDockTop" value="1 << 4" />
+ <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_BOTTOM" name="CantDockBottom" value="1 << 5" />
+ <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_LEFT" name="CantDockLeft" value="1 << 6" />
+ <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_RIGHT" name="CantDockRight" value="1 << 7" />
+ <member cname="GDL_DOCK_ITEM_BEH_CANT_DOCK_CENTER" name="CantDockCenter" value="1 << 8" />
+ </enum>
+ <enum name="DockItemFlags" cname="GdlDockItemFlags" type="enum" hidden="1">
+ <member cname="GDL_DOCK_IN_DRAG" name="InDrag" value="1 << GDL_DOCK_OBJECT_FLAGS_SHIFT" />
+ <member cname="GDL_DOCK_IN_PREDRAG" name="InPredrag" value="1 << (GDL_DOCK_OBJECT_FLAGS_SHIFT + 1)" />
+ <member cname="GDL_DOCK_USER_ACTION" name="UserAction" value="1 << (GDL_DOCK_OBJECT_FLAGS_SHIFT + 2)" />
+ </enum>
+ <enum name="DockObjectFlags" cname="GdlDockObjectFlags" type="flags">
+ <member cname="GDL_DOCK_AUTOMATIC" name="Automatic" value="1 << 0" />
+ <member cname="GDL_DOCK_ATTACHED" name="Attached" value="1 << 1" />
+ <member cname="GDL_DOCK_IN_REFLOW" name="InReflow" value="1 << 2" />
+ <member cname="GDL_DOCK_IN_DETACH" name="InDetach" value="1 << 3" />
+ </enum>
+ <enum name="DockParamFlags" cname="GdlDockParamFlags" type="enum" hidden="1">
+ <member cname="GDL_DOCK_PARAM_EXPORT" name="Export" value="1 << G_PARAM_USER_SHIFT" />
+ <member cname="GDL_DOCK_PARAM_AFTER" name="After" value="1 << (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 (¶ms [n_params].value, GDL_TYPE_DOCK_MASTER);
+ g_value_set_object (¶ms [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,
+ ¶ms [i].value);
+ }
+
+ /* free the parameters (names are static/const strings) */
+ for (i = 0; i < n_params; i++)
+ g_value_unset (¶ms [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