1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gobject.DClosure; 26 27 private import core.memory; 28 private import glib.Str; 29 private import glib.Variant; 30 private import gobject.Closure; 31 private import gobject.ObjectG; 32 private import gobject.ParamSpec; 33 private import gobject.c.functions; 34 public import gobject.c.types; 35 public import gtkc.gobjecttypes; 36 private import std.algorithm; 37 private import std.conv; 38 private import std.traits; 39 private import std.typecons; 40 41 42 /** */ 43 struct DGClosure(T) 44 { 45 GClosure closure; 46 47 static if ( isDelegate!T ) 48 { 49 DGClosureWrapDelegate!(T)* wrap; 50 alias wrap this; 51 } 52 else 53 { 54 T callback; 55 } 56 } 57 58 struct DGClosureWrapDelegate(T) 59 { 60 T callback; 61 } 62 63 /** 64 * DClosure is a wrapper around the gobject library's GClosure with special handling for marshalling D delegates and function pointers as callbacks. 65 * 66 * Closures are central to the concept of asynchronous signal delivery which is widely used throughout GTK+ and GNOME applications. 67 * A closure is an abstraction, a generic representation of a callback. 68 */ 69 class DClosure : Closure 70 { 71 /** Get the main Gtk struct */ 72 public GClosure* getDClosureStruct(bool transferOwnership = false) 73 { 74 if (transferOwnership) 75 ownedRef = false; 76 return gClosure; 77 } 78 79 /** 80 * Sets our main struct and passes it to the parent class. 81 */ 82 public this (GClosure* gClosure, bool ownedRef = false) 83 { 84 super(gClosure, ownedRef); 85 } 86 87 /** 88 * Create a new Closure that will call `callback` when it's invoked. 89 * 90 * Params: 91 * callback = a delegate or function to call when the DClosure is invoked. 92 * swap = Should the first and last parameter passed to the callback be swapped. 93 * This is usefull when using the closure for a Signal, where the instance is 94 * the first parameter, but when using delegates it usually isn't used. 95 */ 96 this(T)(T callback, bool swap = false) 97 if ( isCallable!T ) 98 { 99 GClosure* gClosure = g_closure_new_simple(DGClosure!(T).sizeof, null); 100 g_closure_ref(gClosure); 101 g_closure_sink(gClosure); 102 g_closure_set_marshal(gClosure, &d_closure_marshal!T); 103 if ( swap ) gClosure.derivativeFlag = true; 104 105 auto dClosure = cast(DGClosure!(T)*)gClosure; 106 107 static if ( isDelegate!T ) 108 { 109 dClosure.wrap = new DGClosureWrapDelegate!T; 110 GC.addRoot(dClosure.wrap); 111 g_closure_add_finalize_notifier(gClosure, null, &d_finalize_nofify); 112 } 113 114 dClosure.callback = callback; 115 super(gClosure, true); 116 } 117 118 extern(C) static void d_finalize_nofify(void* data, GClosure* dClosure) 119 { 120 GC.removeRoot((cast(DGClosure!(void delegate())*)dClosure).wrap); 121 } 122 123 extern(C) static void d_closure_marshal(T)(GClosure* closure, GValue* return_value, uint n_param_values, /*const*/ GValue* param_values, void* invocation_hint, void* marshal_data) 124 { 125 DGClosure!(T)* cl = cast(DGClosure!(T)*)closure; 126 127 if ( Parameters!(T).length > n_param_values ) 128 assert(false, "DClosure doesn't have enough parameters."); 129 130 if ( closure.derivativeFlag ) 131 { 132 GValue[] swapped = new GValue[n_param_values]; 133 swapped[0..n_param_values-1] = param_values[1..n_param_values]; 134 swapped[n_param_values-1] = param_values[0]; 135 param_values = swapped.ptr; 136 } 137 138 mixin(getCallbackCall!T()); 139 } 140 141 private static string getCallbackCall(T)() 142 { 143 if (!__ctfe) assert(false); 144 145 string call; 146 147 alias Params = Parameters!T; 148 foreach ( param; Params ) 149 { 150 static if ( __traits(compiles, TemplateOf!param) && __traits(isSame, TemplateOf!param, glib.c.types.Scoped) ) 151 call ~= "import "~moduleName!(TemplateArgsOf!(param)[0])~";\n"; 152 else static if ( is(param == class) || is(param == interface) || is(param == struct) || is(param == enum) ) 153 call ~= "import "~moduleName!param~";\n"; 154 else static if ( isPointer!param && ( is(PointerTarget!param == struct) || is(PointerTarget!param == enum)) ) 155 //The moduleName template gives an forward reference error here. 156 call ~= "import "~fullyQualifiedName!param.findSplitAfter(".c.types")[0]~";\n"; 157 } 158 alias Ret = ReturnType!T; 159 static if ( is(Ret == class) || is(Ret == interface) || is(Ret == struct) || is(Ret == enum) ) 160 call ~= "import "~moduleName!Ret~";\n"; 161 else static if ( isPointer!Ret && ( is(PointerTarget!Ret == struct) || is(PointerTarget!Ret == enum)) ) 162 call ~= "import "~fullyQualifiedName!Ret.findSplitAfter(".c.types")[0]~";\n"; 163 164 static if ( !is(Ret == void) ) 165 call ~= "auto ret = "; 166 call ~= "cl.callback("; 167 168 foreach ( i, param; Params ) 169 { 170 if ( i > 0 ) 171 call ~= ", "; 172 call ~= getValue!param(i); 173 } 174 call ~= ");\n"; 175 176 static if ( is(Ret == bool) ) 177 call ~= "g_value_set_boolean(return_value, ret);"; 178 else static if ( is(Ret == byte) ) 179 call ~= "g_value_set_schar(return_value, ret);"; 180 else static if ( is(Ret == ubyte) ) 181 call ~= "g_value_set_uchar(return_value, ret);"; 182 else static if ( is(Ret == int) ) 183 call ~= "g_value_set_int(return_value, ret);"; 184 else static if ( is(Ret == uint) ) 185 call ~= "g_value_set_uint(return_value, ret);"; 186 else static if ( is(Ret == long) ) 187 call ~= "g_value_set_int64(return_value, ret);"; 188 else static if ( is(Ret == ulong) ) 189 call ~= "g_value_set_uint64(return_value, ret);"; 190 else static if ( is(Ret == float) ) 191 call ~= "g_value_set_float(return_value, ret);"; 192 else static if ( is(Ret == double) ) 193 call ~= "g_value_set_double(return_value, ret);"; 194 else static if ( is(Ret == string) ) 195 call ~= "g_value_set_string(return_value, Str.toStringz(ret));"; 196 else static if ( is(Ret == string[]) ) 197 call ~= "g_value_set_pointer(return_value, Str.toStringzArray(ret));"; 198 else static if ( is(Ret == enum) ) 199 call ~= "g_type_is_a(return_value.gType, GType.ENUM) ? g_value_set_enum(return_value, ret) : g_value_set_flags(return_value, ret);"; 200 else static if ( isPointer!Ret ) 201 call ~= "g_type_is_a(return_value.gType, GType.POINTER) ? g_value_set_pointer(return_value, ret) : (g_type_is_a(return_value.gType, GType.BOXED) ? g_value_set_boxed(return_value, ret) : g_value_set_object(return_value, ret));"; 202 else static if ( is(Ret == interface) ) 203 call ~= "g_value_set_object(return_value, (cast(ObjectG)ret).getObjectGStruct());"; 204 else static if ( is(Ret == class) ) 205 { 206 static if ( is(Ret == Variant) ) 207 call ~= "g_value_set_variant(return_value, ret.getVariantStruct());"; 208 else static if ( is(Ret == ParamSpec) ) 209 call ~= "g_value_set_param(return_value, ret.getParamSpecStruct());"; 210 else static if ( is(Ret : ObjectG) ) 211 call ~= "g_value_set_object(return_value, ret.getObjectGStruct());"; 212 else 213 call ~= "g_type_is_a(return_value.gType, GType.POINTER) ? g_value_set_pointer(return_value, ret.get"~Ret.stringof~"Struct()) : (g_type_is_a(return_value.gType, GType.BOXED) ? g_value_set_boxed(return_value, ret.get"~Ret.stringof~"Struct()) : g_value_set_object(return_value, ret.get"~Ret.stringof~"Struct()));"; 214 } 215 216 return call; 217 } 218 219 private static string getValue(Param)(int index) 220 { 221 if (!__ctfe) assert(false); 222 223 static if ( is(Param == bool) ) 224 return "g_value_get_boolean(¶m_values["~to!string(index)~"]) != 0"; 225 else static if ( is(Param == byte) ) 226 return "g_value_get_schar(¶m_values["~to!string(index)~"])"; 227 else static if ( is(Param == ubyte) ) 228 return "g_value_get_uchar(¶m_values["~to!string(index)~"])"; 229 else static if ( is(Param == int) ) 230 return "g_value_get_int(¶m_values["~to!string(index)~"])"; 231 else static if ( is(Param == uint) ) 232 return "g_value_get_uint(¶m_values["~to!string(index)~"])"; 233 else static if ( is(Param == long) ) 234 return "g_value_get_int64(¶m_values["~to!string(index)~"])"; 235 else static if ( is(Param == ulong) ) 236 return "g_value_get_uint64(¶m_values["~to!string(index)~"])"; 237 else static if ( is(Param == float) ) 238 return "g_value_get_float(¶m_values["~to!string(index)~"])"; 239 else static if ( is(Param == double) ) 240 return "g_value_get_double(¶m_values["~to!string(index)~"])"; 241 else static if ( is(Param == string) ) 242 return "Str.toString(g_value_get_string(¶m_values["~to!string(index)~"]))"; 243 else static if ( is(Param == string[]) ) 244 return "Str.toStringArray(cast(const(char*)*)g_value_get_pointer(¶m_values["~to!string(index)~"]))"; 245 else static if ( is(Param == enum) ) 246 return "cast("~fullyQualifiedName!Param~")(g_type_is_a(param_values["~to!string(index)~"].gType, GType.ENUM) ? g_value_get_enum(¶m_values["~to!string(index)~"]) : g_value_get_flags(¶m_values["~to!string(index)~"]))"; 247 else static if ( isPointer!Param ) 248 return "cast("~fullyQualifiedName!Param~")(g_type_is_a(param_values["~to!string(index)~"].gType, GType.POINTER) ? g_value_get_pointer(¶m_values["~to!string(index)~"]) : (g_type_is_a(param_values["~to!string(index)~"].gType, GType.BOXED) ? g_value_get_boxed(¶m_values["~to!string(index)~"]) : g_value_get_object(¶m_values["~to!string(index)~"])))"; 249 else static if ( __traits(compiles, TemplateOf!Param) && __traits(isSame, TemplateOf!Param, glib.c.types.Scoped) ) 250 return "getScopedGobject!("~fullyQualifiedName!(TemplateArgsOf!(Param)[0])~")(cast(typeof("~fullyQualifiedName!(TemplateArgsOf!(Param)[0])~".tupleof[0]))(g_type_is_a(param_values["~to!string(index)~"].gType, GType.POINTER) ? g_value_get_pointer(¶m_values["~to!string(index)~"]) : (g_type_is_a(param_values["~to!string(index)~"].gType, GType.BOXED) ? g_value_get_boxed(¶m_values["~to!string(index)~"]) : g_value_get_object(¶m_values["~to!string(index)~"]))))"; 251 else static if ( is(Param == interface) ) 252 return "ObjectG.getDObject!("~fullyQualifiedName!Param~")(cast(GObject*)g_value_get_object(¶m_values["~to!string(index)~"]))"; 253 else static if ( is(Param == class) ) 254 { 255 static if ( is(Param == Variant) ) 256 return "new Variant(g_value_get_variant(¶m_values["~to!string(index)~"]))"; 257 else static if ( is(Param== ParamSpec) ) 258 return "new ParamSpec(g_value_get_param(¶m_values["~to!string(index)~"]))"; 259 else static if ( is(Param : ObjectG) ) 260 return "ObjectG.getDObject!("~fullyQualifiedName!Param~")(cast(typeof("~fullyQualifiedName!Param~".tupleof[0]))g_value_get_object(¶m_values["~to!string(index)~"]))"; 261 else 262 return "ObjectG.getDObject!("~fullyQualifiedName!Param~")(cast(typeof("~fullyQualifiedName!Param~".tupleof[0]))(g_type_is_a(param_values["~to!string(index)~"].gType, GType.POINTER) ? g_value_get_pointer(¶m_values["~to!string(index)~"]) : (g_type_is_a(param_values["~to!string(index)~"].gType, GType.BOXED) ? g_value_get_boxed(¶m_values["~to!string(index)~"]) : g_value_get_object(¶m_values["~to!string(index)~"]))))"; 263 } 264 } 265 } 266 267 /** 268 */