mirror of
https://gitee.com/csharpui/CPF.git
synced 2025-04-05 17:37:51 +08:00
1598 lines
48 KiB
C#
1598 lines
48 KiB
C#
using CPF.Mac.CoreGraphics;
|
|
using CPF.Mac.ObjCRuntime;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace CPF.Mac.Foundation
|
|
{
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
[Register("NSObject", true)]
|
|
public class NSObject : INativeObject, IDisposable
|
|
{
|
|
private struct objc_super
|
|
{
|
|
public IntPtr receiver;
|
|
|
|
public IntPtr super;
|
|
}
|
|
|
|
[Register("__NSObject_Disposer")]
|
|
[Preserve(AllMembers = true)]
|
|
internal class NSObject_Disposer : NSObject
|
|
{
|
|
private static readonly List<NSObject> drainList1 = new List<NSObject>();
|
|
|
|
private static readonly List<NSObject> drainList2 = new List<NSObject>();
|
|
|
|
private static List<NSObject> handles = drainList1;
|
|
|
|
private new static readonly IntPtr class_ptr = Class.GetHandle("__NSObject_Disposer");
|
|
|
|
private static readonly IntPtr drainHandle = Selector.GetHandle("drain:");
|
|
|
|
private new static readonly object lock_obj = new object();
|
|
|
|
private NSObject_Disposer()
|
|
{
|
|
}
|
|
|
|
internal static void Add(NSObject handle)
|
|
{
|
|
bool flag;
|
|
lock (lock_obj)
|
|
{
|
|
handles.Add(handle);
|
|
flag = (handles.Count == 1);
|
|
}
|
|
if (flag)
|
|
{
|
|
Messaging.void_objc_msgSend_intptr_intptr_bool(class_ptr, Selector.PerformSelectorOnMainThreadWithObjectWaitUntilDoneHandle, drainHandle, IntPtr.Zero, arg3: false);
|
|
}
|
|
}
|
|
|
|
[Export("drain:")]
|
|
private static void Drain(NSObject ctx)
|
|
{
|
|
List<NSObject> list;
|
|
lock (lock_obj)
|
|
{
|
|
list = handles;
|
|
if (handles == drainList1)
|
|
{
|
|
handles = drainList2;
|
|
}
|
|
else
|
|
{
|
|
handles = drainList1;
|
|
}
|
|
}
|
|
foreach (NSObject item in list)
|
|
{
|
|
item.ReleaseManagedRef();
|
|
}
|
|
list.Clear();
|
|
}
|
|
}
|
|
|
|
private delegate IntPtr RetainTrampolineDelegate(IntPtr @this, IntPtr sel);
|
|
|
|
private delegate void ReleaseTrampolineDelegate(IntPtr @this, IntPtr sel);
|
|
|
|
private const string selConformsToProtocol = "conformsToProtocol:";
|
|
|
|
private const string selEncodeWithCoder = "encodeWithCoder:";
|
|
|
|
private const string selAwakeFromNib = "awakeFromNib";
|
|
|
|
private const string selRespondsToSelector = "respondsToSelector:";
|
|
|
|
private static IntPtr selConformsToProtocolHandle = Selector.GetHandle("conformsToProtocol:");
|
|
|
|
private static IntPtr selEncodeWithCoderHandle = Selector.GetHandle("encodeWithCoder:");
|
|
|
|
private static IntPtr selAwakeFromNibHandle = Selector.GetHandle("awakeFromNib");
|
|
|
|
private static IntPtr selRespondsToSelectorHandle = Selector.GetHandle("respondsToSelector:");
|
|
|
|
private IntPtr handle;
|
|
|
|
private IntPtr super;
|
|
|
|
private bool disposed;
|
|
|
|
protected bool IsDirectBinding;
|
|
|
|
public static readonly Assembly MonoMacAssembly = typeof(NSObject).Assembly;
|
|
|
|
private IntPtr gchandle;
|
|
|
|
private bool has_managed_ref;
|
|
|
|
private static object lock_obj = new object();
|
|
|
|
private static IntPtr RetainTrampolineFunctionPointer;
|
|
|
|
private static IntPtr ReleaseTrampolineFunctionPointer;
|
|
|
|
private static RetainTrampolineDelegate retainTrampoline;
|
|
|
|
private static ReleaseTrampolineDelegate releaseTrampoline;
|
|
|
|
private static readonly IntPtr selDescriptionHandle = Selector.GetHandle("description");
|
|
|
|
private static readonly IntPtr selDebugDescriptionHandle = Selector.GetHandle("debugDescription");
|
|
|
|
private static readonly IntPtr selObserveValueForKeyPathOfObjectChangeContext_Handle = Selector.GetHandle("observeValueForKeyPath:ofObject:change:context:");
|
|
|
|
private static readonly IntPtr selAddObserverForKeyPathOptionsContext_Handle = Selector.GetHandle("addObserver:forKeyPath:options:context:");
|
|
|
|
private static readonly IntPtr selRemoveObserverForKeyPath_Handle = Selector.GetHandle("removeObserver:forKeyPath:");
|
|
|
|
private static readonly IntPtr selWillChangeValueForKey_Handle = Selector.GetHandle("willChangeValueForKey:");
|
|
|
|
private static readonly IntPtr selDidChangeValueForKey_Handle = Selector.GetHandle("didChangeValueForKey:");
|
|
|
|
private static readonly IntPtr selWillChangeValuesAtIndexesForKey_Handle = Selector.GetHandle("willChange:valuesAtIndexes:forKey:");
|
|
|
|
private static readonly IntPtr selDidChangeValuesAtIndexesForKey_Handle = Selector.GetHandle("didChange:valuesAtIndexes:forKey:");
|
|
|
|
private static readonly IntPtr selWillChangeValueForKeyWithSetMutationUsingObjects_Handle = Selector.GetHandle("willChangeValueForKey:withSetMutation:usingObjects:");
|
|
|
|
private static readonly IntPtr selDidChangeValueForKeyWithSetMutationUsingObjects_Handle = Selector.GetHandle("didChangeValueForKey:withSetMutation:usingObjects:");
|
|
|
|
private static readonly IntPtr selKeyPathsForValuesAffectingValueForKey_Handle = Selector.GetHandle("keyPathsForValuesAffectingValueForKey:");
|
|
|
|
private static readonly IntPtr selAutomaticallyNotifiesObserversForKey_Handle = Selector.GetHandle("automaticallyNotifiesObserversForKey:");
|
|
|
|
private static readonly IntPtr selValueForKey_Handle = Selector.GetHandle("valueForKey:");
|
|
|
|
private static readonly IntPtr selSetValueForKey_Handle = Selector.GetHandle("setValue:forKey:");
|
|
|
|
private static readonly IntPtr selValueForKeyPath_Handle = Selector.GetHandle("valueForKeyPath:");
|
|
|
|
private static readonly IntPtr selSetValueForKeyPath_Handle = Selector.GetHandle("setValue:forKeyPath:");
|
|
|
|
private static readonly IntPtr selValueForUndefinedKey_Handle = Selector.GetHandle("valueForUndefinedKey:");
|
|
|
|
private static readonly IntPtr selSetValueForUndefinedKey_Handle = Selector.GetHandle("setValue:forUndefinedKey:");
|
|
|
|
private static readonly IntPtr selSetNilValueForKey_Handle = Selector.GetHandle("setNilValueForKey:");
|
|
|
|
private static readonly IntPtr selDictionaryWithValuesForKeys_Handle = Selector.GetHandle("dictionaryWithValuesForKeys:");
|
|
|
|
private static readonly IntPtr selSetValuesForKeysWithDictionary_Handle = Selector.GetHandle("setValuesForKeysWithDictionary:");
|
|
|
|
private static readonly IntPtr selExposedBindingsHandle = Selector.GetHandle("exposedBindings");
|
|
|
|
private static readonly IntPtr selValueClassForBinding_Handle = Selector.GetHandle("valueClassForBinding:");
|
|
|
|
private static readonly IntPtr selBindToObjectWithKeyPathOptions_Handle = Selector.GetHandle("bind:toObject:withKeyPath:options:");
|
|
|
|
private static readonly IntPtr selUnbind_Handle = Selector.GetHandle("unbind:");
|
|
|
|
private static readonly IntPtr selInfoForBinding_Handle = Selector.GetHandle("infoForBinding:");
|
|
|
|
private static readonly IntPtr selOptionDescriptionsForBinding_Handle = Selector.GetHandle("optionDescriptionsForBinding:");
|
|
|
|
private static readonly IntPtr selDefaultPlaceholderForMarkerWithBinding_Handle = Selector.GetHandle("defaultPlaceholderForMarker:withBinding:");
|
|
|
|
private static readonly IntPtr selSetDefaultPlaceholderForMarkerWithBinding_Handle = Selector.GetHandle("setDefaultPlaceholder:forMarker:withBinding:");
|
|
|
|
private static readonly IntPtr selObjectDidEndEditing_Handle = Selector.GetHandle("objectDidEndEditing:");
|
|
|
|
private static readonly IntPtr selCommitEditingHandle = Selector.GetHandle("commitEditing");
|
|
|
|
private static readonly IntPtr selCommitEditingWithDelegateDidCommitSelectorContextInfo_Handle = Selector.GetHandle("commitEditingWithDelegate:didCommitSelector:contextInfo:");
|
|
|
|
private static readonly IntPtr selCopyHandle = Selector.GetHandle("copy");
|
|
|
|
private static readonly IntPtr selMutableCopyHandle = Selector.GetHandle("mutableCopy");
|
|
|
|
private static readonly IntPtr selPerformSelectorWithObjectAfterDelayInModes_Handle = Selector.GetHandle("performSelector:withObject:afterDelay:inModes:");
|
|
|
|
private static readonly IntPtr selPerformSelectorOnThreadWithObjectWaitUntilDone_Handle = Selector.GetHandle("performSelector:onThread:withObject:waitUntilDone:");
|
|
|
|
private static readonly IntPtr selPerformSelectorOnThreadWithObjectWaitUntilDoneModes_Handle = Selector.GetHandle("performSelector:onThread:withObject:waitUntilDone:modes:");
|
|
|
|
private static readonly IntPtr selCancelPreviousPerformRequestsWithTarget_Handle = Selector.GetHandle("cancelPreviousPerformRequestsWithTarget:");
|
|
|
|
private static readonly IntPtr selCancelPreviousPerformRequestsWithTargetSelectorObject_Handle = Selector.GetHandle("cancelPreviousPerformRequestsWithTarget:selector:object:");
|
|
|
|
private static readonly IntPtr class_ptr = Class.GetHandle("NSObject");
|
|
|
|
private static NSString _ChangeKindKey;
|
|
|
|
private static NSString _ChangeNewKey;
|
|
|
|
private static NSString _ChangeOldKey;
|
|
|
|
private static NSString _ChangeIndexesKey;
|
|
|
|
private static NSString _ChangeNotificationIsPriorKey;
|
|
|
|
private static IntPtr fl = Dlfcn.dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", 1);
|
|
|
|
private static IntPtr al = Dlfcn.dlopen("/System/Library/Frameworks/AppKit.framework/AppKit", 1);
|
|
|
|
private static IntPtr ab = Dlfcn.dlopen("/System/Library/Frameworks/AddressBook.framework/AddressBook", 1);
|
|
|
|
private static IntPtr ct = Dlfcn.dlopen("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText", 1);
|
|
|
|
private static IntPtr wl = Dlfcn.dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", 1);
|
|
|
|
private static IntPtr zl = Dlfcn.dlopen("/System/Library/Frameworks/QuartzCore.framework/QuartzCore", 1);
|
|
|
|
private static IntPtr ql = Dlfcn.dlopen("/System/Library/Frameworks/QTKit.framework/QTKit", 1);
|
|
|
|
private static IntPtr cl = Dlfcn.dlopen("/System/Library/Frameworks/CoreLocation.framework/CoreLocation", 1);
|
|
|
|
private static IntPtr ll = Dlfcn.dlopen("/System/Library/Frameworks/Security.framework/Security", 1);
|
|
|
|
private static IntPtr zc = Dlfcn.dlopen("/System/Library/Frameworks/Quartz.framework/Frameworks/QuartzComposer.framework/QuartzComposer", 1);
|
|
|
|
private static IntPtr cw = Dlfcn.dlopen("/System/Library/Frameworks/CoreWLAN.framework/CoreWLAN", 1);
|
|
|
|
private static IntPtr pk = Dlfcn.dlopen("/System/Library/Frameworks/Quartz.framework/Frameworks/PDFKit.framework/PDFKit", 1);
|
|
|
|
private static IntPtr ik = Dlfcn.dlopen("/System/Library/Frameworks/Quartz.framework/Frameworks/ImageKit.framework/ImageKit", 1);
|
|
|
|
private static IntPtr sb = Dlfcn.dlopen("/System/Library/Frameworks/ScriptingBridge.framework/ScriptingBridge", 1);
|
|
|
|
private static IntPtr av = Dlfcn.dlopen("/System/Library/Frameworks/AVFoundation.framework/AVFoundation", 1);
|
|
|
|
public unsafe IntPtr SuperHandle
|
|
{
|
|
get
|
|
{
|
|
if (super == IntPtr.Zero)
|
|
{
|
|
super = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(objc_super)));
|
|
objc_super* ptr = (objc_super*)(void*)super;
|
|
ptr->receiver = handle;
|
|
ptr->super = ClassHandle;
|
|
}
|
|
return super;
|
|
}
|
|
}
|
|
|
|
public IntPtr Handle
|
|
{
|
|
get
|
|
{
|
|
return handle;
|
|
}
|
|
set
|
|
{
|
|
if (!(handle == value))
|
|
{
|
|
if (handle != IntPtr.Zero)
|
|
{
|
|
Runtime.UnregisterNSObject(handle);
|
|
}
|
|
handle = value;
|
|
if (handle != IntPtr.Zero)
|
|
{
|
|
Runtime.RegisterNSObject(this, handle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Export("retainCount")]
|
|
public virtual int RetainCount
|
|
{
|
|
get
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.int_objc_msgSend(Handle, Selector.RetainCount);
|
|
}
|
|
return Messaging.int_objc_msgSendSuper(SuperHandle, Selector.RetainCount);
|
|
}
|
|
}
|
|
|
|
public virtual IntPtr ClassHandle => class_ptr;
|
|
|
|
public virtual string Description
|
|
{
|
|
[Export("description")]
|
|
get
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return NSString.FromHandle(Messaging.IntPtr_objc_msgSend(Handle, selDescriptionHandle));
|
|
}
|
|
return NSString.FromHandle(Messaging.IntPtr_objc_msgSendSuper(SuperHandle, selDescriptionHandle));
|
|
}
|
|
}
|
|
|
|
public virtual string DebugDescription
|
|
{
|
|
[Export("debugDescription")]
|
|
get
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return NSString.FromHandle(Messaging.IntPtr_objc_msgSend(Handle, selDebugDescriptionHandle));
|
|
}
|
|
return NSString.FromHandle(Messaging.IntPtr_objc_msgSendSuper(SuperHandle, selDebugDescriptionHandle));
|
|
}
|
|
}
|
|
|
|
[Field("NSKeyValueChangeKindKey", "Foundation")]
|
|
public static NSString ChangeKindKey
|
|
{
|
|
get
|
|
{
|
|
if (_ChangeKindKey == null)
|
|
{
|
|
_ChangeKindKey = Dlfcn.GetStringConstant(Libraries.Foundation.Handle, "NSKeyValueChangeKindKey");
|
|
}
|
|
return _ChangeKindKey;
|
|
}
|
|
}
|
|
|
|
[Field("NSKeyValueChangeNewKey", "Foundation")]
|
|
public static NSString ChangeNewKey
|
|
{
|
|
get
|
|
{
|
|
if (_ChangeNewKey == null)
|
|
{
|
|
_ChangeNewKey = Dlfcn.GetStringConstant(Libraries.Foundation.Handle, "NSKeyValueChangeNewKey");
|
|
}
|
|
return _ChangeNewKey;
|
|
}
|
|
}
|
|
|
|
[Field("NSKeyValueChangeOldKey", "Foundation")]
|
|
public static NSString ChangeOldKey
|
|
{
|
|
get
|
|
{
|
|
if (_ChangeOldKey == null)
|
|
{
|
|
_ChangeOldKey = Dlfcn.GetStringConstant(Libraries.Foundation.Handle, "NSKeyValueChangeOldKey");
|
|
}
|
|
return _ChangeOldKey;
|
|
}
|
|
}
|
|
|
|
[Field("NSKeyValueChangeIndexesKey", "Foundation")]
|
|
public static NSString ChangeIndexesKey
|
|
{
|
|
get
|
|
{
|
|
if (_ChangeIndexesKey == null)
|
|
{
|
|
_ChangeIndexesKey = Dlfcn.GetStringConstant(Libraries.Foundation.Handle, "NSKeyValueChangeIndexesKey");
|
|
}
|
|
return _ChangeIndexesKey;
|
|
}
|
|
}
|
|
|
|
[Field("NSKeyValueChangeNotificationIsPriorKey", "Foundation")]
|
|
public static NSString ChangeNotificationIsPriorKey
|
|
{
|
|
get
|
|
{
|
|
if (_ChangeNotificationIsPriorKey == null)
|
|
{
|
|
_ChangeNotificationIsPriorKey = Dlfcn.GetStringConstant(Libraries.Foundation.Handle, "NSKeyValueChangeNotificationIsPriorKey");
|
|
}
|
|
return _ChangeNotificationIsPriorKey;
|
|
}
|
|
}
|
|
|
|
[Export("init")]
|
|
public NSObject()
|
|
{
|
|
bool alloced = AllocIfNeeded();
|
|
InitializeObject(alloced);
|
|
}
|
|
|
|
public NSObject(NSObjectFlag x)
|
|
{
|
|
bool alloced = AllocIfNeeded();
|
|
InitializeObject(alloced);
|
|
}
|
|
|
|
public NSObject(IntPtr handle)
|
|
: this(handle, alloced: false)
|
|
{
|
|
}
|
|
|
|
public NSObject(IntPtr handle, bool alloced)
|
|
{
|
|
this.handle = handle;
|
|
InitializeObject(alloced);
|
|
}
|
|
|
|
~NSObject()
|
|
{
|
|
Dispose(disposing: false);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
[Export("encodeWithCoder:")]
|
|
public virtual void EncodeTo(NSCoder coder)
|
|
{
|
|
if (coder == null)
|
|
{
|
|
throw new ArgumentNullException("coder");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_intptr(Handle, selEncodeWithCoderHandle, coder.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_intptr(SuperHandle, selEncodeWithCoderHandle, coder.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("conformsToProtocol:")]
|
|
[Preserve]
|
|
public virtual bool ConformsToProtocol(IntPtr protocol)
|
|
{
|
|
if ((!IsDirectBinding) ? Messaging.bool_objc_msgSendSuper_intptr(SuperHandle, selConformsToProtocolHandle, protocol) : Messaging.bool_objc_msgSend_intptr(Handle, selConformsToProtocolHandle, protocol))
|
|
{
|
|
return true;
|
|
}
|
|
object[] customAttributes = GetType().GetCustomAttributes(typeof(AdoptsAttribute), inherit: true);
|
|
for (int i = 0; i < customAttributes.Length; i++)
|
|
{
|
|
if (((AdoptsAttribute)customAttributes[i]).ProtocolHandle == protocol)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
[Export("respondsToSelector:")]
|
|
public virtual bool RespondsToSelector(Selector sel)
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.bool_objc_msgSend_intptr(Handle, selRespondsToSelectorHandle, sel.Handle);
|
|
}
|
|
return Messaging.bool_objc_msgSendSuper_intptr(SuperHandle, selRespondsToSelectorHandle, sel.Handle);
|
|
}
|
|
|
|
[Export("doesNotRecognizeSelector:")]
|
|
public virtual void DoesNotRecognizeSelector(Selector sel)
|
|
{
|
|
Messaging.void_objc_msgSendSuper_intptr(SuperHandle, Selector.DoesNotRecognizeSelectorHandle, sel.Handle);
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
Messaging.void_objc_msgSend(handle, Selector.ReleaseHandle);
|
|
}
|
|
|
|
public NSObject Retain()
|
|
{
|
|
Messaging.void_objc_msgSend(handle, Selector.RetainHandle);
|
|
return this;
|
|
}
|
|
|
|
public NSObject Autorelease()
|
|
{
|
|
Messaging.void_objc_msgSend(handle, Selector.AutoreleaseHandle);
|
|
return this;
|
|
}
|
|
|
|
private bool AllocIfNeeded()
|
|
{
|
|
if (handle == IntPtr.Zero)
|
|
{
|
|
handle = Messaging.intptr_objc_msgSend(Class.GetHandle(GetType()), Selector.AllocHandle);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private IntPtr GetObjCIvar(string name)
|
|
{
|
|
object_getInstanceVariable(handle, name, out IntPtr val);
|
|
return val;
|
|
}
|
|
|
|
public NSObject GetNativeField(string name)
|
|
{
|
|
IntPtr objCIvar = GetObjCIvar(name);
|
|
if (objCIvar == IntPtr.Zero)
|
|
{
|
|
return null;
|
|
}
|
|
return Runtime.GetNSObject(objCIvar);
|
|
}
|
|
|
|
private void SetObjCIvar(string name, IntPtr value)
|
|
{
|
|
object_setInstanceVariable(handle, name, value);
|
|
}
|
|
|
|
public void SetNativeField(string name, NSObject value)
|
|
{
|
|
if (value == null)
|
|
{
|
|
SetObjCIvar(name, IntPtr.Zero);
|
|
}
|
|
else
|
|
{
|
|
SetObjCIvar(name, value.Handle);
|
|
}
|
|
}
|
|
|
|
[DllImport("/usr/lib/libobjc.dylib")]
|
|
private static extern void object_getInstanceVariable(IntPtr obj, string name, out IntPtr val);
|
|
|
|
[DllImport("/usr/lib/libobjc.dylib")]
|
|
private static extern void object_setInstanceVariable(IntPtr obj, string name, IntPtr val);
|
|
|
|
[Export("performSelector:withObject:afterDelay:")]
|
|
public virtual void PerformSelector(Selector sel, NSObject obj, double delay)
|
|
{
|
|
if (sel == null)
|
|
{
|
|
throw new ArgumentNullException("sel");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_intptr_intptr_double(Handle, Selector.PerformSelectorWithObjectAfterDelayHandle, sel.Handle, obj?.Handle ?? IntPtr.Zero, delay);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_intptr_intptr_double(SuperHandle, Selector.PerformSelectorWithObjectAfterDelayHandle, sel.Handle, obj?.Handle ?? IntPtr.Zero, delay);
|
|
}
|
|
}
|
|
|
|
[Export("awakeFromNib")]
|
|
public virtual void AwakeFromNib()
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend(Handle, selAwakeFromNibHandle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper(SuperHandle, selAwakeFromNibHandle);
|
|
}
|
|
}
|
|
|
|
private void InvokeOnMainThread(Selector sel, NSObject obj, bool wait)
|
|
{
|
|
Messaging.void_objc_msgSend_intptr_intptr_bool(Handle, Selector.PerformSelectorOnMainThreadWithObjectWaitUntilDoneHandle, sel.Handle, obj?.Handle ?? IntPtr.Zero, wait);
|
|
}
|
|
|
|
public void BeginInvokeOnMainThread(Selector sel, NSObject obj)
|
|
{
|
|
InvokeOnMainThread(sel, obj, wait: false);
|
|
}
|
|
|
|
public void InvokeOnMainThread(Selector sel, NSObject obj)
|
|
{
|
|
InvokeOnMainThread(sel, obj, wait: true);
|
|
}
|
|
|
|
public void BeginInvokeOnMainThread(NSAction action)
|
|
{
|
|
NSAsyncActionDispatcher nSAsyncActionDispatcher = new NSAsyncActionDispatcher(action);
|
|
Messaging.void_objc_msgSend_intptr_intptr_bool(nSAsyncActionDispatcher.Handle, Selector.PerformSelectorOnMainThreadWithObjectWaitUntilDoneHandle, NSActionDispatcher.Selector.Handle, nSAsyncActionDispatcher.Handle, arg3: false);
|
|
}
|
|
|
|
public void InvokeOnMainThread(NSAction action)
|
|
{
|
|
using (NSActionDispatcher nSActionDispatcher = new NSActionDispatcher(action))
|
|
{
|
|
Messaging.void_objc_msgSend_intptr_intptr_bool(nSActionDispatcher.Handle, Selector.PerformSelectorOnMainThreadWithObjectWaitUntilDoneHandle, NSActionDispatcher.Selector.Handle, nSActionDispatcher.Handle, arg3: true);
|
|
}
|
|
}
|
|
|
|
public static NSObject FromObject(object obj)
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return NSNull.Null;
|
|
}
|
|
Type type = obj.GetType();
|
|
if (type == typeof(NSObject) || type.IsSubclassOf(typeof(NSObject)))
|
|
{
|
|
return (NSObject)obj;
|
|
}
|
|
switch (Type.GetTypeCode(type))
|
|
{
|
|
case TypeCode.Boolean:
|
|
return new NSNumber((bool)obj);
|
|
case TypeCode.Char:
|
|
return new NSNumber((char)obj);
|
|
case TypeCode.SByte:
|
|
return new NSNumber((sbyte)obj);
|
|
case TypeCode.Byte:
|
|
return new NSNumber((byte)obj);
|
|
case TypeCode.Int16:
|
|
return new NSNumber((short)obj);
|
|
case TypeCode.UInt16:
|
|
return new NSNumber((ushort)obj);
|
|
case TypeCode.Int32:
|
|
return new NSNumber((int)obj);
|
|
case TypeCode.UInt32:
|
|
return new NSNumber((uint)obj);
|
|
case TypeCode.Int64:
|
|
return new NSNumber((long)obj);
|
|
case TypeCode.UInt64:
|
|
return new NSNumber((ulong)obj);
|
|
case TypeCode.Single:
|
|
return new NSNumber((float)obj);
|
|
case TypeCode.Double:
|
|
return new NSNumber((double)obj);
|
|
case TypeCode.String:
|
|
return new NSString((string)obj);
|
|
default:
|
|
{
|
|
if (type == typeof(IntPtr))
|
|
{
|
|
return NSValue.ValueFromPointer((IntPtr)obj);
|
|
}
|
|
if (type == typeof(CGSize))
|
|
{
|
|
return NSValue.FromSize((CGSize)obj);
|
|
}
|
|
if (type == typeof(CGRect))
|
|
{
|
|
return NSValue.FromRectangle((CGRect)obj);
|
|
}
|
|
if (type == typeof(CGPoint))
|
|
{
|
|
return NSValue.FromPoint((CGPoint)obj);
|
|
}
|
|
INativeObject nativeObject = obj as INativeObject;
|
|
if (nativeObject != null)
|
|
{
|
|
return Runtime.GetNSObject(nativeObject.Handle);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetValueForKeyPath(IntPtr handle, NSString keyPath)
|
|
{
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr(Handle, selSetValueForKeyPath_Handle, handle, keyPath.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr(SuperHandle, selSetValueForKeyPath_Handle, handle, keyPath.Handle);
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Description ?? base.ToString();
|
|
}
|
|
|
|
public virtual void Invoke(NSAction action, double delay)
|
|
{
|
|
NSAsyncActionDispatcher obj = new NSAsyncActionDispatcher(action);
|
|
PerformSelector(NSActionDispatcher.Selector, obj, delay);
|
|
}
|
|
|
|
public virtual void Invoke(NSAction action, TimeSpan delay)
|
|
{
|
|
NSAsyncActionDispatcher obj = new NSAsyncActionDispatcher(action);
|
|
PerformSelector(NSActionDispatcher.Selector, obj, delay.TotalSeconds);
|
|
}
|
|
|
|
internal void ClearHandle()
|
|
{
|
|
handle = IntPtr.Zero;
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposed)
|
|
{
|
|
return;
|
|
}
|
|
disposed = true;
|
|
if (handle != IntPtr.Zero)
|
|
{
|
|
if (disposing)
|
|
{
|
|
ReleaseManagedRef();
|
|
}
|
|
else
|
|
{
|
|
NSObject_Disposer.Add(this);
|
|
}
|
|
}
|
|
if (super != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(super);
|
|
super = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
private void InitializeObject(bool alloced)
|
|
{
|
|
if (alloced && handle == IntPtr.Zero && Class.ThrowOnInitFailure)
|
|
{
|
|
if (ClassHandle == IntPtr.Zero)
|
|
{
|
|
throw new Exception($"Could not create an native instance of the type '{GetType().FullName}': the native class hasn't been loaded.\nIt is possible to ignore this condition by setting CPF.Mac.ObjCRuntime.Class.ThrowOnInitFailure to false.");
|
|
}
|
|
throw new Exception($"Failed to create a instance of the native type '{new Class(ClassHandle).Name}'.\nIt is possible to ignore this condition by setting CPF.Mac.ObjCRuntime.Class.ThrowOnInitFailure to false.");
|
|
}
|
|
IsDirectBinding = (GetType().Assembly == MonoMacAssembly);
|
|
if (IsDirectBinding)
|
|
{
|
|
IsDirectBinding = !(this is NotMonoMac);
|
|
}
|
|
Runtime.RegisterNSObject(this, handle);
|
|
CreateManagedRef(!alloced);
|
|
}
|
|
|
|
private static int GetRetainCount(IntPtr @this)
|
|
{
|
|
return Messaging.int_objc_msgSend(@this, Selector.RetainCount);
|
|
}
|
|
|
|
private void UnregisterObject()
|
|
{
|
|
Runtime.NativeObjectHasDied(handle);
|
|
}
|
|
|
|
private void FreeGCHandle()
|
|
{
|
|
if (gchandle != IntPtr.Zero)
|
|
{
|
|
GCHandle.FromIntPtr(gchandle).Free();
|
|
gchandle = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
private void SwitchGCHandle(bool to_weak)
|
|
{
|
|
if (gchandle != IntPtr.Zero)
|
|
{
|
|
GCHandle.FromIntPtr(gchandle).Free();
|
|
}
|
|
if (to_weak)
|
|
{
|
|
gchandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection));
|
|
}
|
|
else
|
|
{
|
|
gchandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Normal));
|
|
}
|
|
}
|
|
|
|
internal static void OverrideRetainAndRelease(IntPtr @class)
|
|
{
|
|
lock (lock_obj)
|
|
{
|
|
if (ReleaseTrampolineFunctionPointer == IntPtr.Zero)
|
|
{
|
|
retainTrampoline = RetainTrampoline;
|
|
releaseTrampoline = ReleaseTrampoline;
|
|
RetainTrampolineFunctionPointer = Marshal.GetFunctionPointerForDelegate(retainTrampoline);
|
|
ReleaseTrampolineFunctionPointer = Marshal.GetFunctionPointerForDelegate(releaseTrampoline);
|
|
}
|
|
}
|
|
Class.class_addMethod(@class, Selector.RetainHandle, RetainTrampolineFunctionPointer, "@@:");
|
|
Class.class_addMethod(@class, Selector.ReleaseHandle, ReleaseTrampolineFunctionPointer, "v@:");
|
|
}
|
|
|
|
private static bool IsUserType(IntPtr @this)
|
|
{
|
|
IntPtr intPtr = object_getClass(@this);
|
|
if (Class.class_getMethodImplementation(intPtr, Selector.RetainHandle) == RetainTrampolineFunctionPointer)
|
|
{
|
|
return true;
|
|
}
|
|
Type type = Class.Lookup(intPtr, throw_on_error: false);
|
|
if (type != null)
|
|
{
|
|
return Class.IsCustomType(type);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void CreateGCHandle(bool force_weak)
|
|
{
|
|
bool num = force_weak || GetRetainCount(handle) == 1;
|
|
has_managed_ref = true;
|
|
if (num)
|
|
{
|
|
gchandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection));
|
|
}
|
|
else
|
|
{
|
|
gchandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Normal));
|
|
}
|
|
}
|
|
|
|
private void CreateManagedRef(bool retain)
|
|
{
|
|
if (IsUserType(handle) && gchandle == IntPtr.Zero)
|
|
{
|
|
CreateGCHandle(!retain);
|
|
}
|
|
if (retain)
|
|
{
|
|
Messaging.void_objc_msgSend(handle, Selector.RetainHandle);
|
|
}
|
|
}
|
|
|
|
private void ReleaseManagedRef()
|
|
{
|
|
IntPtr intPtr = handle;
|
|
if (IsUserType(intPtr))
|
|
{
|
|
has_managed_ref = false;
|
|
}
|
|
else
|
|
{
|
|
UnregisterObject();
|
|
}
|
|
Messaging.void_objc_msgSend(intPtr, Selector.ReleaseHandle);
|
|
}
|
|
|
|
[DllImport("/usr/lib/libobjc.dylib")]
|
|
private static extern IntPtr object_getClass(IntPtr @this);
|
|
|
|
[DllImport("/usr/lib/libobjc.dylib")]
|
|
private static extern IntPtr objc_msgSendSuper(ref objc_super super, IntPtr selector);
|
|
|
|
private static IntPtr InvokeObjCMethodImplementation(IntPtr @this, IntPtr sel)
|
|
{
|
|
IntPtr cls = object_getClass(@this);
|
|
IntPtr cls2 = Class.class_getSuperclass(cls);
|
|
IntPtr value = Class.class_getMethodImplementation(cls, sel);
|
|
IntPtr value2 = Class.class_getMethodImplementation(cls2, sel);
|
|
while (value == value2)
|
|
{
|
|
cls2 = Class.class_getSuperclass(cls2);
|
|
value2 = Class.class_getMethodImplementation(cls2, sel);
|
|
}
|
|
objc_super objc_super = default(objc_super);
|
|
objc_super.receiver = @this;
|
|
objc_super.super = cls2;
|
|
return objc_msgSendSuper(ref objc_super, sel);
|
|
}
|
|
|
|
private static void ReleaseTrampoline(IntPtr @this, IntPtr sel)
|
|
{
|
|
int num = Messaging.int_objc_msgSend(@this, Selector.RetainCount);
|
|
NSObject nSObject = null;
|
|
if (num == 1)
|
|
{
|
|
nSObject = Runtime.TryGetNSObject(@this);
|
|
if (nSObject != null)
|
|
{
|
|
nSObject.UnregisterObject();
|
|
nSObject.FreeGCHandle();
|
|
}
|
|
}
|
|
if (num == 2)
|
|
{
|
|
nSObject = Runtime.TryGetNSObject(@this);
|
|
if (nSObject != null && nSObject.has_managed_ref)
|
|
{
|
|
nSObject.SwitchGCHandle(to_weak: true);
|
|
}
|
|
}
|
|
InvokeObjCMethodImplementation(@this, sel);
|
|
}
|
|
|
|
private static IntPtr RetainTrampoline(IntPtr @this, IntPtr sel)
|
|
{
|
|
int num = Messaging.int_objc_msgSend(@this, Selector.RetainCount);
|
|
NSObject nSObject = null;
|
|
if (num == 1)
|
|
{
|
|
nSObject = Runtime.TryGetNSObject(@this);
|
|
if (nSObject != null && nSObject.has_managed_ref)
|
|
{
|
|
nSObject.SwitchGCHandle(to_weak: false);
|
|
}
|
|
}
|
|
@this = InvokeObjCMethodImplementation(@this, sel);
|
|
return @this;
|
|
}
|
|
|
|
internal void SetAsProxy()
|
|
{
|
|
IsDirectBinding = true;
|
|
}
|
|
|
|
[Export("observeValueForKeyPath:ofObject:change:context:")]
|
|
public virtual void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
|
|
{
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (ofObject == null)
|
|
{
|
|
throw new ArgumentNullException("ofObject");
|
|
}
|
|
if (change == null)
|
|
{
|
|
throw new ArgumentNullException("change");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_IntPtr(Handle, selObserveValueForKeyPathOfObjectChangeContext_Handle, keyPath.Handle, ofObject.Handle, change.Handle, context);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_IntPtr_IntPtr(SuperHandle, selObserveValueForKeyPathOfObjectChangeContext_Handle, keyPath.Handle, ofObject.Handle, change.Handle, context);
|
|
}
|
|
}
|
|
|
|
[Export("addObserver:forKeyPath:options:context:")]
|
|
public virtual void AddObserver(NSObject observer, NSString keyPath, NSKeyValueObservingOptions options, IntPtr context)
|
|
{
|
|
if (observer == null)
|
|
{
|
|
throw new ArgumentNullException("observer");
|
|
}
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_UInt64_IntPtr(Handle, selAddObserverForKeyPathOptionsContext_Handle, observer.Handle, keyPath.Handle, (ulong)options, context);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_UInt64_IntPtr(SuperHandle, selAddObserverForKeyPathOptionsContext_Handle, observer.Handle, keyPath.Handle, (ulong)options, context);
|
|
}
|
|
}
|
|
|
|
[Export("removeObserver:forKeyPath:")]
|
|
public virtual void RemoveObserver(NSObject observer, NSString keyPath)
|
|
{
|
|
if (observer == null)
|
|
{
|
|
throw new ArgumentNullException("observer");
|
|
}
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr(Handle, selRemoveObserverForKeyPath_Handle, observer.Handle, keyPath.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr(SuperHandle, selRemoveObserverForKeyPath_Handle, observer.Handle, keyPath.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("willChangeValueForKey:")]
|
|
public virtual void WillChangeValue(string forKey)
|
|
{
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(forKey);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selWillChangeValueForKey_Handle, arg);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selWillChangeValueForKey_Handle, arg);
|
|
}
|
|
NSString.ReleaseNative(arg);
|
|
}
|
|
|
|
[Export("didChangeValueForKey:")]
|
|
public virtual void DidChangeValue(string forKey)
|
|
{
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(forKey);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selDidChangeValueForKey_Handle, arg);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selDidChangeValueForKey_Handle, arg);
|
|
}
|
|
NSString.ReleaseNative(arg);
|
|
}
|
|
|
|
[Export("willChange:valuesAtIndexes:forKey:")]
|
|
public virtual void WillChange(NSKeyValueChange changeKind, NSIndexSet indexes, NSString forKey)
|
|
{
|
|
if (indexes == null)
|
|
{
|
|
throw new ArgumentNullException("indexes");
|
|
}
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_UInt64_IntPtr_IntPtr(Handle, selWillChangeValuesAtIndexesForKey_Handle, (ulong)changeKind, indexes.Handle, forKey.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_UInt64_IntPtr_IntPtr(SuperHandle, selWillChangeValuesAtIndexesForKey_Handle, (ulong)changeKind, indexes.Handle, forKey.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("didChange:valuesAtIndexes:forKey:")]
|
|
public virtual void DidChange(NSKeyValueChange changeKind, NSIndexSet indexes, NSString forKey)
|
|
{
|
|
if (indexes == null)
|
|
{
|
|
throw new ArgumentNullException("indexes");
|
|
}
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_UInt64_IntPtr_IntPtr(Handle, selDidChangeValuesAtIndexesForKey_Handle, (ulong)changeKind, indexes.Handle, forKey.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_UInt64_IntPtr_IntPtr(SuperHandle, selDidChangeValuesAtIndexesForKey_Handle, (ulong)changeKind, indexes.Handle, forKey.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("willChangeValueForKey:withSetMutation:usingObjects:")]
|
|
public virtual void WillChange(NSString forKey, NSKeyValueSetMutationKind mutationKind, NSSet objects)
|
|
{
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
if (objects == null)
|
|
{
|
|
throw new ArgumentNullException("objects");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_UInt64_IntPtr(Handle, selWillChangeValueForKeyWithSetMutationUsingObjects_Handle, forKey.Handle, (ulong)mutationKind, objects.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_UInt64_IntPtr(SuperHandle, selWillChangeValueForKeyWithSetMutationUsingObjects_Handle, forKey.Handle, (ulong)mutationKind, objects.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("didChangeValueForKey:withSetMutation:usingObjects:")]
|
|
public virtual void DidChange(NSString forKey, NSKeyValueSetMutationKind mutationKind, NSSet objects)
|
|
{
|
|
if (forKey == null)
|
|
{
|
|
throw new ArgumentNullException("forKey");
|
|
}
|
|
if (objects == null)
|
|
{
|
|
throw new ArgumentNullException("objects");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_UInt64_IntPtr(Handle, selDidChangeValueForKeyWithSetMutationUsingObjects_Handle, forKey.Handle, (ulong)mutationKind, objects.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_UInt64_IntPtr(SuperHandle, selDidChangeValueForKeyWithSetMutationUsingObjects_Handle, forKey.Handle, (ulong)mutationKind, objects.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("keyPathsForValuesAffectingValueForKey:")]
|
|
public static NSSet GetKeyPathsForValuesAffecting(NSString key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
return (NSSet)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(class_ptr, selKeyPathsForValuesAffectingValueForKey_Handle, key.Handle));
|
|
}
|
|
|
|
[Export("automaticallyNotifiesObserversForKey:")]
|
|
public static bool AutomaticallyNotifiesObserversForKey(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(key);
|
|
bool result = Messaging.bool_objc_msgSend_IntPtr(class_ptr, selAutomaticallyNotifiesObserversForKey_Handle, arg);
|
|
NSString.ReleaseNative(arg);
|
|
return result;
|
|
}
|
|
|
|
[Export("valueForKey:")]
|
|
public virtual NSObject ValueForKey(NSString key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selValueForKey_Handle, key.Handle));
|
|
}
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selValueForKey_Handle, key.Handle));
|
|
}
|
|
|
|
[Export("setValue:forKey:")]
|
|
public virtual void SetValueForKey(NSObject value, NSString key)
|
|
{
|
|
if (value == null)
|
|
{
|
|
throw new ArgumentNullException("value");
|
|
}
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr(Handle, selSetValueForKey_Handle, value.Handle, key.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr(SuperHandle, selSetValueForKey_Handle, value.Handle, key.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("valueForKeyPath:")]
|
|
public virtual NSObject ValueForKeyPath(NSString keyPath)
|
|
{
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selValueForKeyPath_Handle, keyPath.Handle));
|
|
}
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selValueForKeyPath_Handle, keyPath.Handle));
|
|
}
|
|
|
|
[Export("setValue:forKeyPath:")]
|
|
public virtual void SetValueForKeyPath(NSObject value, NSString keyPath)
|
|
{
|
|
if (value == null)
|
|
{
|
|
throw new ArgumentNullException("value");
|
|
}
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr(Handle, selSetValueForKeyPath_Handle, value.Handle, keyPath.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr(SuperHandle, selSetValueForKeyPath_Handle, value.Handle, keyPath.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("valueForUndefinedKey:")]
|
|
public virtual NSObject ValueForUndefinedKey(NSString key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selValueForUndefinedKey_Handle, key.Handle));
|
|
}
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selValueForUndefinedKey_Handle, key.Handle));
|
|
}
|
|
|
|
[Export("setValue:forUndefinedKey:")]
|
|
public virtual void SetValueForUndefinedKey(NSObject value, NSString undefinedKey)
|
|
{
|
|
if (value == null)
|
|
{
|
|
throw new ArgumentNullException("value");
|
|
}
|
|
if (undefinedKey == null)
|
|
{
|
|
throw new ArgumentNullException("undefinedKey");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr(Handle, selSetValueForUndefinedKey_Handle, value.Handle, undefinedKey.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr(SuperHandle, selSetValueForUndefinedKey_Handle, value.Handle, undefinedKey.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("setNilValueForKey:")]
|
|
public virtual void SetNilValueForKey(NSString key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selSetNilValueForKey_Handle, key.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selSetNilValueForKey_Handle, key.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("dictionaryWithValuesForKeys:")]
|
|
public virtual NSDictionary GetDictionaryOfValuesFromKeys(NSString[] keys)
|
|
{
|
|
if (keys == null)
|
|
{
|
|
throw new ArgumentNullException("keys");
|
|
}
|
|
NSArray nSArray = NSArray.FromNSObjects(keys);
|
|
NSDictionary result = (!IsDirectBinding) ? ((NSDictionary)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selDictionaryWithValuesForKeys_Handle, nSArray.Handle))) : ((NSDictionary)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selDictionaryWithValuesForKeys_Handle, nSArray.Handle)));
|
|
nSArray.Dispose();
|
|
return result;
|
|
}
|
|
|
|
[Export("setValuesForKeysWithDictionary:")]
|
|
public virtual void SetValuesForKeysWithDictionary(NSDictionary keyedValues)
|
|
{
|
|
if (keyedValues == null)
|
|
{
|
|
throw new ArgumentNullException("keyedValues");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selSetValuesForKeysWithDictionary_Handle, keyedValues.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selSetValuesForKeysWithDictionary_Handle, keyedValues.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("exposedBindings")]
|
|
public virtual NSString[] ExposedBindings()
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return NSArray.ArrayFromHandle<NSString>(Messaging.IntPtr_objc_msgSend(Handle, selExposedBindingsHandle));
|
|
}
|
|
return NSArray.ArrayFromHandle<NSString>(Messaging.IntPtr_objc_msgSendSuper(SuperHandle, selExposedBindingsHandle));
|
|
}
|
|
|
|
[Export("valueClassForBinding:")]
|
|
public virtual Class BindingValueClass(string binding)
|
|
{
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
Class result = (!IsDirectBinding) ? new Class(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selValueClassForBinding_Handle, arg)) : new Class(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selValueClassForBinding_Handle, arg));
|
|
NSString.ReleaseNative(arg);
|
|
return result;
|
|
}
|
|
|
|
[Export("bind:toObject:withKeyPath:options:")]
|
|
public virtual void Bind(string binding, NSObject observable, string keyPath, NSDictionary options)
|
|
{
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
if (observable == null)
|
|
{
|
|
throw new ArgumentNullException("observable");
|
|
}
|
|
if (keyPath == null)
|
|
{
|
|
throw new ArgumentNullException("keyPath");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
IntPtr arg2 = NSString.CreateNative(keyPath);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_IntPtr(Handle, selBindToObjectWithKeyPathOptions_Handle, arg, observable.Handle, arg2, options?.Handle ?? IntPtr.Zero);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_IntPtr_IntPtr(SuperHandle, selBindToObjectWithKeyPathOptions_Handle, arg, observable.Handle, arg2, options?.Handle ?? IntPtr.Zero);
|
|
}
|
|
NSString.ReleaseNative(arg);
|
|
NSString.ReleaseNative(arg2);
|
|
}
|
|
|
|
[Export("unbind:")]
|
|
public virtual void Unbind(string binding)
|
|
{
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selUnbind_Handle, arg);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selUnbind_Handle, arg);
|
|
}
|
|
NSString.ReleaseNative(arg);
|
|
}
|
|
|
|
[Export("infoForBinding:")]
|
|
public virtual NSDictionary BindingInfo(string binding)
|
|
{
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
NSDictionary result = (!IsDirectBinding) ? ((NSDictionary)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selInfoForBinding_Handle, arg))) : ((NSDictionary)Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selInfoForBinding_Handle, arg)));
|
|
NSString.ReleaseNative(arg);
|
|
return result;
|
|
}
|
|
|
|
[Export("optionDescriptionsForBinding:")]
|
|
public virtual NSObject[] BindingOptionDescriptions(string aBinding)
|
|
{
|
|
if (aBinding == null)
|
|
{
|
|
throw new ArgumentNullException("aBinding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(aBinding);
|
|
NSObject[] result = (!IsDirectBinding) ? NSArray.ArrayFromHandle<NSObject>(Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selOptionDescriptionsForBinding_Handle, arg)) : NSArray.ArrayFromHandle<NSObject>(Messaging.IntPtr_objc_msgSend_IntPtr(Handle, selOptionDescriptionsForBinding_Handle, arg));
|
|
NSString.ReleaseNative(arg);
|
|
return result;
|
|
}
|
|
|
|
[Export("defaultPlaceholderForMarker:withBinding:")]
|
|
public static NSObject GetDefaultPlaceholder(NSObject marker, string binding)
|
|
{
|
|
if (marker == null)
|
|
{
|
|
throw new ArgumentNullException("marker");
|
|
}
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
NSObject nSObject = Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr(class_ptr, selDefaultPlaceholderForMarkerWithBinding_Handle, marker.Handle, arg));
|
|
NSString.ReleaseNative(arg);
|
|
return nSObject;
|
|
}
|
|
|
|
[Export("setDefaultPlaceholder:forMarker:withBinding:")]
|
|
public static void SetDefaultPlaceholder(NSObject placeholder, NSObject marker, string binding)
|
|
{
|
|
if (placeholder == null)
|
|
{
|
|
throw new ArgumentNullException("placeholder");
|
|
}
|
|
if (marker == null)
|
|
{
|
|
throw new ArgumentNullException("marker");
|
|
}
|
|
if (binding == null)
|
|
{
|
|
throw new ArgumentNullException("binding");
|
|
}
|
|
IntPtr arg = NSString.CreateNative(binding);
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr(class_ptr, selSetDefaultPlaceholderForMarkerWithBinding_Handle, placeholder.Handle, marker.Handle, arg);
|
|
NSString.ReleaseNative(arg);
|
|
}
|
|
|
|
[Export("objectDidEndEditing:")]
|
|
public virtual void ObjectDidEndEditing(NSObject editor)
|
|
{
|
|
if (editor == null)
|
|
{
|
|
throw new ArgumentNullException("editor");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr(Handle, selObjectDidEndEditing_Handle, editor.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr(SuperHandle, selObjectDidEndEditing_Handle, editor.Handle);
|
|
}
|
|
}
|
|
|
|
[Export("commitEditing")]
|
|
public virtual bool CommitEditing()
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Messaging.bool_objc_msgSend(Handle, selCommitEditingHandle);
|
|
}
|
|
return Messaging.bool_objc_msgSendSuper(SuperHandle, selCommitEditingHandle);
|
|
}
|
|
|
|
[Export("commitEditingWithDelegate:didCommitSelector:contextInfo:")]
|
|
public virtual void CommitEditing(NSObject objDelegate, Selector didCommitSelector, IntPtr contextInfo)
|
|
{
|
|
if (objDelegate == null)
|
|
{
|
|
throw new ArgumentNullException("objDelegate");
|
|
}
|
|
if (didCommitSelector == null)
|
|
{
|
|
throw new ArgumentNullException("didCommitSelector");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr(Handle, selCommitEditingWithDelegateDidCommitSelectorContextInfo_Handle, objDelegate.Handle, didCommitSelector.Handle, contextInfo);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_IntPtr(SuperHandle, selCommitEditingWithDelegateDidCommitSelectorContextInfo_Handle, objDelegate.Handle, didCommitSelector.Handle, contextInfo);
|
|
}
|
|
}
|
|
|
|
[Export("copy")]
|
|
public virtual NSObject Copy()
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend(Handle, selCopyHandle));
|
|
}
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper(SuperHandle, selCopyHandle));
|
|
}
|
|
|
|
[Export("mutableCopy")]
|
|
public virtual NSObject MutableCopy()
|
|
{
|
|
if (IsDirectBinding)
|
|
{
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend(Handle, selMutableCopyHandle));
|
|
}
|
|
return Runtime.GetNSObject(Messaging.IntPtr_objc_msgSendSuper(SuperHandle, selMutableCopyHandle));
|
|
}
|
|
|
|
[Export("performSelector:withObject:afterDelay:inModes:")]
|
|
public virtual void PerformSelector(Selector selector, NSObject withObject, double afterDelay, NSString[] nsRunLoopModes)
|
|
{
|
|
if (selector == null)
|
|
{
|
|
throw new ArgumentNullException("selector");
|
|
}
|
|
if (withObject == null)
|
|
{
|
|
throw new ArgumentNullException("withObject");
|
|
}
|
|
if (nsRunLoopModes == null)
|
|
{
|
|
throw new ArgumentNullException("nsRunLoopModes");
|
|
}
|
|
NSArray nSArray = NSArray.FromNSObjects(nsRunLoopModes);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_Double_IntPtr(Handle, selPerformSelectorWithObjectAfterDelayInModes_Handle, selector.Handle, withObject.Handle, afterDelay, nSArray.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_Double_IntPtr(SuperHandle, selPerformSelectorWithObjectAfterDelayInModes_Handle, selector.Handle, withObject.Handle, afterDelay, nSArray.Handle);
|
|
}
|
|
nSArray.Dispose();
|
|
}
|
|
|
|
[Export("performSelector:onThread:withObject:waitUntilDone:")]
|
|
public virtual void PerformSelector(Selector selector, NSThread onThread, NSObject withObject, bool waitUntilDone)
|
|
{
|
|
if (selector == null)
|
|
{
|
|
throw new ArgumentNullException("selector");
|
|
}
|
|
if (onThread == null)
|
|
{
|
|
throw new ArgumentNullException("onThread");
|
|
}
|
|
if (withObject == null)
|
|
{
|
|
throw new ArgumentNullException("withObject");
|
|
}
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_bool(Handle, selPerformSelectorOnThreadWithObjectWaitUntilDone_Handle, selector.Handle, onThread.Handle, withObject.Handle, waitUntilDone);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_IntPtr_bool(SuperHandle, selPerformSelectorOnThreadWithObjectWaitUntilDone_Handle, selector.Handle, onThread.Handle, withObject.Handle, waitUntilDone);
|
|
}
|
|
}
|
|
|
|
[Export("performSelector:onThread:withObject:waitUntilDone:modes:")]
|
|
public virtual void PerformSelector(Selector selector, NSThread onThread, NSObject withObject, bool waitUntilDone, NSString[] nsRunLoopModes)
|
|
{
|
|
if (selector == null)
|
|
{
|
|
throw new ArgumentNullException("selector");
|
|
}
|
|
if (onThread == null)
|
|
{
|
|
throw new ArgumentNullException("onThread");
|
|
}
|
|
if (withObject == null)
|
|
{
|
|
throw new ArgumentNullException("withObject");
|
|
}
|
|
if (nsRunLoopModes == null)
|
|
{
|
|
throw new ArgumentNullException("nsRunLoopModes");
|
|
}
|
|
NSArray nSArray = NSArray.FromNSObjects(nsRunLoopModes);
|
|
if (IsDirectBinding)
|
|
{
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_bool_IntPtr(Handle, selPerformSelectorOnThreadWithObjectWaitUntilDoneModes_Handle, selector.Handle, onThread.Handle, withObject.Handle, waitUntilDone, nSArray.Handle);
|
|
}
|
|
else
|
|
{
|
|
Messaging.void_objc_msgSendSuper_IntPtr_IntPtr_IntPtr_bool_IntPtr(SuperHandle, selPerformSelectorOnThreadWithObjectWaitUntilDoneModes_Handle, selector.Handle, onThread.Handle, withObject.Handle, waitUntilDone, nSArray.Handle);
|
|
}
|
|
nSArray.Dispose();
|
|
}
|
|
|
|
[Export("cancelPreviousPerformRequestsWithTarget:")]
|
|
public static void CancelPreviousPerformRequest(NSObject aTarget)
|
|
{
|
|
if (aTarget == null)
|
|
{
|
|
throw new ArgumentNullException("aTarget");
|
|
}
|
|
Messaging.void_objc_msgSend_IntPtr(class_ptr, selCancelPreviousPerformRequestsWithTarget_Handle, aTarget.Handle);
|
|
}
|
|
|
|
[Export("cancelPreviousPerformRequestsWithTarget:selector:object:")]
|
|
public static void CancelPreviousPerformRequest(NSObject aTarget, Selector selector, NSObject argument)
|
|
{
|
|
if (aTarget == null)
|
|
{
|
|
throw new ArgumentNullException("aTarget");
|
|
}
|
|
if (selector == null)
|
|
{
|
|
throw new ArgumentNullException("selector");
|
|
}
|
|
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr(class_ptr, selCancelPreviousPerformRequestsWithTargetSelectorObject_Handle, aTarget.Handle, selector.Handle, argument?.Handle ?? IntPtr.Zero);
|
|
}
|
|
}
|
|
}
|