Mercurial > projects > dstep
view dstep/objc/bridge/ClassInitializer.d @ 19:ae08a08f44d3
Added IBOutlet
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sun, 17 Jan 2010 16:25:24 +0100 |
parents | 19885b43130e |
children |
line wrap: on
line source
/** * Copyright: Copyright (c) 2009 Jacob Carlborg. * Authors: Jacob Carlborg * Version: Initial created: Apr 7, 2009 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module dstep.objc.bridge.ClassInitializer; version (Tango) import tango.math.Math; else import std.math; import dstep.internal.String; import dstep.internal.Traits; import bindings = dstep.objc.bindings; import dstep.objc.bridge.Bridge; import dstep.objc.bridge.TypeEncoding; import dstep.objc.objc; import dstep.objc.runtime; /** * Objective-C subclass initializer template. * * Param: * subclassName = the name of the subclass to create * superClassName = the name of the Objective-C superclass */ package template ObjcSubclassInitializer (string subclassName, string superclassName) { /** * Return a pointer to the created class data structure. If this class hasn't been added * to the Objective-C runtime, it'll be added. * * Returns: a pointer to the created class data structure */ static dstep.objc.objc.Class objcClass () { if (__objcClass) return __objcClass; dstep.objc.objc.Class superClass = objcSuperClass; auto methods = __collectObjcInstanceMethods(); auto classMethods = __collectObjcClassMethods(); static if (dstep.internal.Traits.hasClassMethod!(typeof(super), objcClass.stringof)) typeof(super).objcClass; return __objcClass = dstep.objc.bridge.ClassInitializer.subclassInit!(subclassName)(superClass, methods, classMethods); } /** * Return a pointer to the superclass data structure. If the superclass hasn't been added * to the Objective-C runtime, it'll be added. * * Returns: a pointer to the superclass data structure */ static dstep.objc.objc.Class objcSuperClass () { if (__objcSuperClass) return __objcSuperClass; if (is(typeof(super) == dstep.objc.bridge.Wrapper.ObjcWrapper)) // root class return __objcSuperClass = dstep.objc.bridge.Capsule.capsuleClass; __objcSuperClass = cast(dstep.objc.objc.Class) dstep.objc.objc.objc.getClass!(subclassName); while (!__objcSuperClass && !is(typeof(super) == dstep.objc.bridge.Wrapper.ObjcWrapper)) __objcSuperClass = super.objcClass; if (!__objcSuperClass) __objcSuperClass = dstep.objc.bridge.Capsule.capsuleClass; return __objcSuperClass; } /** * Collects all binded methods in the class this template is mixed into. * * Returns: an array of methods */ private static dstep.objc.runtime.Method[] __collectObjcInstanceMethods () { dstep.objc.runtime.Method[] methods; mixin("alias " ~ subclassName ~ " Type;"); static if (Type.tupleof.length > 0) { foreach (i, f ; typeof(Type.tupleof)) { const len = Type.stringof.length; const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; static if (fieldName == dstep.objc.bridge.Bridge.Bridge.objcMethodDeclarationVar) { typeof(Type.tupleof[i]) field; dstep.objc.runtime.Method m = new dstep.objc.objc.objc_method; m.method_name = dstep.objc.objc.sel.registerName!(field.methodName); m.method_types = dstep.objc.bridge.TypeEncoding.encode!(field.returnType, dstep.objc.objc.id, dstep.objc.objc.SEL, field.argsType).ptr; m.method_imp = cast(dstep.objc.objc.IMP) field.methodImp; methods ~= m; } } } return methods; } /** * Collects all binded class methods in the class this template is mixed into. * * Returns: */ private static dstep.objc.runtime.Method[] __collectObjcClassMethods () { dstep.objc.runtime.Method[] methods; mixin("alias " ~ subclassName ~ " Type;"); static if (Type.tupleof.length > 0) { foreach (i, f ; typeof(Type.tupleof)) { const len = Type.stringof.length; const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; static if (fieldName == dstep.objc.bridge.Bridge.Bridge.objcClassMethodDeclarationVar) { typeof(Type.tupleof[i]) field; dstep.objc.runtime.Method m = new dstep.objc.objc.objc_method; m.method_name = dstep.objc.objc.sel.registerName!(field.methodName); m.method_types = dstep.objc.bridge.TypeEncoding.encode!(field.returnType, field.argsType).ptr; m.method_imp = cast(dstep.objc.objc.IMP) field.methodImp; methods ~= m; } } } return methods; } /** * Invoke on the receiver the instance method with the given name, return type * and arguments. * * Params: * R = the return type * name = the name (selector) of the method to invoke * ARGS = the type of the arguments * args = the arguments to the method * * Returns: whatever the method returns */ private R invokeObjcSelf (R, dstep.internal.String.string name, ARGS...) (ARGS args) { return dstep.objc.bridge.Bridge.Bridge.invokeObjcMethod!(R, name, ARGS)(this.objcObject, args); } /** * Invoke on the receiver's super part the instance method with the given name, * return type and arguments. * * Params: * R = the return type * name = the name (selector) of the method to invoke * ARGS = the type of the arguments * args = the arguments to the method * * Returns: whatever the method returns */ private R invokeObjcSuper (R, dstep.internal.String.string name, ARGS...) (ARGS args) { return dstep.objc.bridge.Bridge.Bridge.invokeObjcSuperMethod!(R, name, ARGS)(this.objcSuper, args); } /** * Invoke class method with given name, return type and arguments, * on the receiver's superclass. * * Params: * R = the return type * name = the name (selector) of the method to invoke * ARGS = the type of the arguments * args = the arguments to the method * * Returns: whatever the method returns */ private static R invokeObjcSelfClass (R, dstep.internal.String.string name, ARGS...) (ARGS args) { return dstep.objc.bridge.Bridge.Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass, args); } /** * Invoke class method with given name, return type and arguments, * on the receiver's superclass. * * Params: * R = the return type * name = the name (selector) of the method to invoke * ARGS = the type of the arguments * args = the arguments to the method * * Returns: whatever the method returns */ private static R invokeObjcSuperClass (R, dstep.internal.String.string name, ARGS...) (ARGS args) { return dstep.objc.bridge.Bridge.Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcSuperClass, args); } } /** * Creates a new Objective-C subclass, initializes its data and register it with the * Objective-C runtime. * * Params: * className = the name of the subclass * superClass = the subclass' superclass * instanceMethods = the instance methods that should be added to the subclass * classMethods = the class methods that should be added to the subclass * * Returns: the newly created subclass */ Class subclassInit (string className) (Class superClass, Method[] instanceMethods = null, Method[] classMethods = null) { Class cls; if (objc.getClass!(className)) cls = objc.allocateClassPair!("D_" ~ className)(superClass, 0); else cls = objc.allocateClassPair!(className)(superClass, 0); Class metaClass = (cast(id) cls).getClass; ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof); cls.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment); foreach (method ; instanceMethods) bindings.class_addMethod(cls, method.method_name, method.method_imp, method.method_types); foreach (method ; classMethods) bindings.class_addMethod(metaClass, method.method_name, method.method_imp, method.method_types); objc.registerClassPair(cls); return cls; }