1// Container.custom - customizations to Gtk.Container 2// 3// Authors: Mike Kestner <mkestner@ximian.com> 4// 5// Copyright (c) 2004 Novell, Inc. 6// 7// This program is free software; you can redistribute it and/or 8// modify it under the terms of version 2 of the Lesser GNU General 9// Public License as published by the Free Software Foundation. 10// 11// This program is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14// Lesser General Public License for more details. 15// 16// You should have received a copy of the GNU Lesser General Public 17// License along with this program; if not, write to the 18// Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19// Boston, MA 02111-1307, USA. 20 21 22[DllImport("gtksharpglue-2", CallingConvention=CallingConvention.Cdecl)] 23static extern void gtksharp_container_child_get_property (IntPtr container, IntPtr child, IntPtr property, ref GLib.Value value); 24 25public GLib.Value ChildGetProperty (Gtk.Widget child, string property_name) { 26 GLib.Value value = new GLib.Value (); 27 28 IntPtr native = GLib.Marshaller.StringToPtrGStrdup (property_name); 29 gtksharp_container_child_get_property (Handle, child.Handle, native, ref value); 30 GLib.Marshaller.Free (native); 31 return value; 32} 33 34public IEnumerator GetEnumerator () 35{ 36 return Children.GetEnumerator (); 37} 38 39class ChildAccumulator { 40 public ArrayList Children = new ArrayList (); 41 42 public void Add (Gtk.Widget widget) 43 { 44 Children.Add (widget); 45 } 46} 47 48public IEnumerable AllChildren { 49 get { 50 ChildAccumulator acc = new ChildAccumulator (); 51 Forall (new Gtk.Callback (acc.Add)); 52 return acc.Children; 53 } 54} 55 56[DllImport("libgtk-win32-2.0-0.dll", CallingConvention=CallingConvention.Cdecl)] 57static extern bool gtk_container_get_focus_chain (IntPtr raw, out IntPtr list_ptr); 58 59[DllImport("libgtk-win32-2.0-0.dll", CallingConvention=CallingConvention.Cdecl)] 60static extern void gtk_container_set_focus_chain (IntPtr raw, IntPtr list_ptr); 61 62public Widget[] FocusChain { 63 get { 64 IntPtr list_ptr; 65 bool success = gtk_container_get_focus_chain (Handle, out list_ptr); 66 if (!success) 67 return new Widget [0]; 68 69 return GLib.Marshaller.ListPtrToArray<Widget> (list_ptr, typeof(GLib.List), true, false); 70 } 71 set { 72 GLib.List list = new GLib.List (IntPtr.Zero, typeof(Widget), true, false); 73 foreach (Widget val in value) 74 list.Append (val.Handle); 75 gtk_container_set_focus_chain (Handle, list.Handle); 76 } 77 78} 79 80[DllImport("gtksharpglue-2", CallingConvention=CallingConvention.Cdecl)] 81static extern void gtksharp_container_base_forall (IntPtr handle, bool include_internals, IntPtr cb, IntPtr data); 82 83[DllImport("gtksharpglue-2", CallingConvention=CallingConvention.Cdecl)] 84static extern void gtksharp_container_override_forall (IntPtr gtype, ForallDelegate cb); 85 86[DllImport("gtksharpglue-2", CallingConvention=CallingConvention.Cdecl)] 87static extern void gtksharp_container_invoke_gtk_callback (IntPtr cb, IntPtr handle, IntPtr data); 88 89[UnmanagedFunctionPointer (CallingConvention.Cdecl)] 90delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data); 91 92static ForallDelegate ForallOldCallback; 93static ForallDelegate ForallCallback; 94 95public struct CallbackInvoker { 96 IntPtr cb; 97 IntPtr data; 98 99 internal CallbackInvoker (IntPtr cb, IntPtr data) 100 { 101 this.cb = cb; 102 this.data = data; 103 } 104 105 internal IntPtr Data { 106 get { 107 return data; 108 } 109 } 110 111 internal IntPtr Callback { 112 get { 113 return cb; 114 } 115 } 116 117 public void Invoke (Widget w) 118 { 119 gtksharp_container_invoke_gtk_callback (cb, w.Handle, data); 120 } 121} 122 123static void ForallOld_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data) 124{ 125 try { 126 //GtkContainer's unmanaged dispose calls forall, but by that time the managed object is gone 127 //so it couldn't do anything useful, and resurrecting it would cause a resurrection cycle. 128 //In that case, just chain to the native base in case it can do something. 129 Container obj = (Container) GLib.Object.TryGetObject (container); 130 if (obj != null) { 131 CallbackInvoker invoker = new CallbackInvoker (cb, data); 132 obj.ForAll (include_internals, invoker); 133 } else { 134 gtksharp_container_base_forall (container, include_internals, cb, data); 135 } 136 } catch (Exception e) { 137 GLib.ExceptionManager.RaiseUnhandledException (e, false); 138 } 139} 140 141static void OverrideForallOld (GLib.GType gtype) 142{ 143 if (ForallOldCallback == null) 144 ForallOldCallback = new ForallDelegate (ForallOld_cb); 145 gtksharp_container_override_forall (gtype.Val, ForallOldCallback); 146} 147 148[Obsolete ("Override the ForAll(bool,Gtk.Callback) method instead")] 149[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForallOld")] 150protected virtual void ForAll (bool include_internals, CallbackInvoker invoker) 151{ 152 gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data); 153} 154 155static void Forall_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data) 156{ 157 try { 158 //GtkContainer's unmanaged dispose calls forall, but by that time the managed object is gone 159 //so it couldn't do anything useful, and resurrecting it would cause a resurrection cycle. 160 //In that case, just chain to the native base in case it can do something. 161 Container obj = (Container) GLib.Object.TryGetObject (container); 162 if (obj != null) { 163 CallbackInvoker invoker = new CallbackInvoker (cb, data); 164 obj.ForAll (include_internals, new Gtk.Callback (invoker.Invoke)); 165 } else { 166 gtksharp_container_base_forall (container, include_internals, cb, data); 167 } 168 } catch (Exception e) { 169 GLib.ExceptionManager.RaiseUnhandledException (e, false); 170 } 171} 172 173static void OverrideForall (GLib.GType gtype) 174{ 175 if (ForallCallback == null) 176 ForallCallback = new ForallDelegate (Forall_cb); 177 gtksharp_container_override_forall (gtype.Val, ForallCallback); 178} 179 180[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForall")] 181protected virtual void ForAll (bool include_internals, Gtk.Callback callback) 182{ 183 CallbackInvoker invoker; 184 try { 185 invoker = (CallbackInvoker)callback.Target; 186 } catch { 187 throw new ApplicationException ("ForAll can only be called as \"base.ForAll()\". Use Forall() or Foreach()."); 188 } 189 gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data); 190} 191 192[DllImport("libgtk-win32-2.0-0.dll", CallingConvention=CallingConvention.Cdecl)] 193static extern IntPtr gtk_container_child_type(IntPtr raw); 194 195[DllImport("gtksharpglue-2", CallingConvention=CallingConvention.Cdecl)] 196static extern void gtksharp_container_override_child_type (IntPtr type, ChildTypeDelegate cb); 197 198[UnmanagedFunctionPointer (CallingConvention.Cdecl)] 199delegate IntPtr ChildTypeDelegate (IntPtr raw); 200 201static ChildTypeDelegate ChildTypeCallback; 202 203static IntPtr ChildType_cb (IntPtr raw) 204{ 205 try { 206 Container obj = GLib.Object.GetObject (raw, false) as Container; 207 GLib.GType gtype = obj.ChildType (); 208 return gtype.Val; 209 } catch (Exception e) { 210 GLib.ExceptionManager.RaiseUnhandledException (e, false); 211 } 212 213 return GLib.GType.Invalid.Val; 214} 215 216static void OverrideChildType (GLib.GType gtype) 217{ 218 if (ChildTypeCallback == null) 219 ChildTypeCallback = new ChildTypeDelegate (ChildType_cb); 220 gtksharp_container_override_child_type (gtype.Val, ChildTypeCallback); 221} 222 223[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideChildType")] 224public virtual GLib.GType ChildType() { 225 IntPtr raw_ret = gtk_container_child_type(Handle); 226 GLib.GType ret = new GLib.GType(raw_ret); 227 return ret; 228} 229 230public class ContainerChild { 231 protected Container parent; 232 protected Widget child; 233 234 public ContainerChild (Container parent, Widget child) 235 { 236 this.parent = parent; 237 this.child = child; 238 } 239 240 public Container Parent { 241 get { 242 return parent; 243 } 244 } 245 246 public Widget Child { 247 get { 248 return child; 249 } 250 } 251} 252 253public virtual ContainerChild this [Widget w] { 254 get { 255 return new ContainerChild (this, w); 256 } 257} 258