1 // Container.cs - 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 namespace Gtk { 22 23 using System; 24 using System.Collections; 25 using System.Runtime.InteropServices; 26 27 public partial class Container : IEnumerable { 28 29 [DllImport("gtksharpglue-3")] gtksharp_container_child_get_property(IntPtr container, IntPtr child, IntPtr property, ref GLib.Value value)30 static extern void gtksharp_container_child_get_property (IntPtr container, IntPtr child, IntPtr property, ref GLib.Value value); 31 ChildGetProperty(Gtk.Widget child, string property_name)32 public GLib.Value ChildGetProperty (Gtk.Widget child, string property_name) { 33 GLib.Value value = new GLib.Value (); 34 35 IntPtr native = GLib.Marshaller.StringToPtrGStrdup (property_name); 36 gtksharp_container_child_get_property (Handle, child.Handle, native, ref value); 37 GLib.Marshaller.Free (native); 38 return value; 39 } 40 GetEnumerator()41 public IEnumerator GetEnumerator () 42 { 43 return Children.GetEnumerator (); 44 } 45 46 class ChildAccumulator { 47 public ArrayList Children = new ArrayList (); 48 Add(Gtk.Widget widget)49 public void Add (Gtk.Widget widget) 50 { 51 Children.Add (widget); 52 } 53 } 54 55 public IEnumerable AllChildren { 56 get { 57 ChildAccumulator acc = new ChildAccumulator (); 58 Forall (new Gtk.Callback (acc.Add)); 59 return acc.Children; 60 } 61 } 62 63 [DllImport (Global.GtkNativeDll, CallingConvention = CallingConvention.Cdecl)] gtk_container_get_focus_chain(IntPtr raw, out IntPtr list_ptr)64 static extern bool gtk_container_get_focus_chain (IntPtr raw, out IntPtr list_ptr); 65 66 [DllImport (Global.GtkNativeDll, CallingConvention = CallingConvention.Cdecl)] gtk_container_set_focus_chain(IntPtr raw, IntPtr list_ptr)67 static extern void gtk_container_set_focus_chain (IntPtr raw, IntPtr list_ptr); 68 69 public Widget[] FocusChain { 70 get { 71 IntPtr list_ptr; 72 bool success = gtk_container_get_focus_chain (Handle, out list_ptr); 73 if (!success) 74 return new Widget [0]; 75 76 GLib.List list = new GLib.List (list_ptr); 77 Widget[] result = new Widget [list.Count]; 78 for (int i = 0; i < list.Count; i++) 79 result [i] = list [i] as Widget; 80 return result; 81 } 82 set { 83 GLib.List list = new GLib.List (IntPtr.Zero); 84 foreach (Widget val in value) 85 list.Append (val.Handle); 86 gtk_container_set_focus_chain (Handle, list.Handle); 87 } 88 89 } 90 91 [DllImport("gtksharpglue-3")] gtksharp_container_base_forall(IntPtr handle, bool include_internals, IntPtr cb, IntPtr data)92 static extern void gtksharp_container_base_forall (IntPtr handle, bool include_internals, IntPtr cb, IntPtr data); 93 94 [DllImport("gtksharpglue-3")] gtksharp_container_override_forall(IntPtr gtype, ForallDelegate cb)95 static extern void gtksharp_container_override_forall (IntPtr gtype, ForallDelegate cb); 96 97 [DllImport("gtksharpglue-3")] gtksharp_container_invoke_gtk_callback(IntPtr cb, IntPtr handle, IntPtr data)98 static extern void gtksharp_container_invoke_gtk_callback (IntPtr cb, IntPtr handle, IntPtr data); 99 100 [UnmanagedFunctionPointer (CallingConvention.Cdecl)] ForallDelegate(IntPtr container, bool include_internals, IntPtr cb, IntPtr data)101 delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data); 102 103 static ForallDelegate ForallOldCallback; 104 static ForallDelegate ForallCallback; 105 106 public struct CallbackInvoker { 107 IntPtr cb; 108 IntPtr data; 109 CallbackInvokerGtk.Container.CallbackInvoker110 internal CallbackInvoker (IntPtr cb, IntPtr data) 111 { 112 this.cb = cb; 113 this.data = data; 114 } 115 116 internal IntPtr Data { 117 get { 118 return data; 119 } 120 } 121 122 internal IntPtr Callback { 123 get { 124 return cb; 125 } 126 } 127 InvokeGtk.Container.CallbackInvoker128 public void Invoke (Widget w) 129 { 130 gtksharp_container_invoke_gtk_callback (cb, w.Handle, data); 131 } 132 } 133 ForallOld_cb(IntPtr container, bool include_internals, IntPtr cb, IntPtr data)134 static void ForallOld_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data) 135 { 136 try { 137 //GtkContainer's unmanaged dispose calls forall, but by that time the managed object is gone 138 //so it couldn't do anything useful, and resurrecting it would cause a resurrection cycle. 139 //In that case, just chain to the native base in case it can do something. 140 Container obj = (Container) GLib.Object.TryGetObject (container); 141 if (obj != null) { 142 CallbackInvoker invoker = new CallbackInvoker (cb, data); 143 obj.ForAll (include_internals, invoker); 144 } else { 145 gtksharp_container_base_forall (container, include_internals, cb, data); 146 } 147 } catch (Exception e) { 148 GLib.ExceptionManager.RaiseUnhandledException (e, false); 149 } 150 } 151 OverrideForallOld(GLib.GType gtype)152 static void OverrideForallOld (GLib.GType gtype) 153 { 154 if (ForallOldCallback == null) 155 ForallOldCallback = new ForallDelegate (ForallOld_cb); 156 gtksharp_container_override_forall (gtype.Val, ForallOldCallback); 157 } 158 159 [Obsolete ("Override the ForAll(bool,Gtk.Callback) method instead")] 160 [GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForallOld")] ForAll(bool include_internals, CallbackInvoker invoker)161 protected virtual void ForAll (bool include_internals, CallbackInvoker invoker) 162 { 163 gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data); 164 } 165 Forall_cb(IntPtr container, bool include_internals, IntPtr cb, IntPtr data)166 static void Forall_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data) 167 { 168 try { 169 //GtkContainer's unmanaged dispose calls forall, but by that time the managed object is gone 170 //so it couldn't do anything useful, and resurrecting it would cause a resurrection cycle. 171 //In that case, just chain to the native base in case it can do something. 172 Container obj = (Container) GLib.Object.TryGetObject (container); 173 if (obj != null) { 174 CallbackInvoker invoker = new CallbackInvoker (cb, data); 175 obj.ForAll (include_internals, new Gtk.Callback (invoker.Invoke)); 176 } else { 177 gtksharp_container_base_forall (container, include_internals, cb, data); 178 } 179 } catch (Exception e) { 180 GLib.ExceptionManager.RaiseUnhandledException (e, false); 181 } 182 } 183 OverrideForall(GLib.GType gtype)184 static void OverrideForall (GLib.GType gtype) 185 { 186 if (ForallCallback == null) 187 ForallCallback = new ForallDelegate (Forall_cb); 188 gtksharp_container_override_forall (gtype.Val, ForallCallback); 189 } 190 191 [GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForall")] ForAll(bool include_internals, Gtk.Callback callback)192 protected virtual void ForAll (bool include_internals, Gtk.Callback callback) 193 { 194 CallbackInvoker invoker; 195 try { 196 invoker = (CallbackInvoker)callback.Target; 197 } catch { 198 throw new ApplicationException ("ForAll can only be called as \"base.ForAll()\". Use Forall() or Foreach()."); 199 } 200 gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data); 201 } 202 203 // Compatibility code for old ChildType() virtual method ObsoleteChildType_cb(IntPtr raw)204 static IntPtr ObsoleteChildType_cb (IntPtr raw) 205 { 206 try { 207 Container obj = GLib.Object.GetObject (raw, false) as Container; 208 GLib.GType gtype = obj.ChildType (); 209 return gtype.Val; 210 } catch (Exception e) { 211 GLib.ExceptionManager.RaiseUnhandledException (e, false); 212 } 213 214 return GLib.GType.Invalid.Val; 215 } 216 217 static ChildTypeNativeDelegate ObsoleteChildTypeVMCallback; 218 OverrideObsoleteChildType(GLib.GType gtype)219 static void OverrideObsoleteChildType (GLib.GType gtype) 220 { 221 if (ObsoleteChildTypeVMCallback == null) 222 ObsoleteChildTypeVMCallback = new ChildTypeNativeDelegate (ObsoleteChildType_cb); 223 OverrideChildType (gtype, ObsoleteChildTypeVMCallback); // -> autogenerated method 224 } 225 226 [Obsolete ("Replaced by OnChildType for implementations and SupportedChildType for callers.")] 227 [GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideObsoleteChildType")] ChildType()228 public virtual GLib.GType ChildType() { 229 return InternalChildType (); // -> autogenerated method 230 } 231 232 public class ContainerChild { 233 protected Container parent; 234 protected Widget child; 235 ContainerChild(Container parent, Widget child)236 public ContainerChild (Container parent, Widget child) 237 { 238 this.parent = parent; 239 this.child = child; 240 } 241 242 public Container Parent { 243 get { 244 return parent; 245 } 246 } 247 248 public Widget Child { 249 get { 250 return child; 251 } 252 } 253 } 254 255 public virtual ContainerChild this [Widget w] { 256 get { 257 return new ContainerChild (this, w); 258 } 259 } 260 } 261 } 262