NBTExplorer/Mac/NbtClipboardControllerMac.cs
2012-11-10 23:21:09 -05:00

184 lines
4.8 KiB
C#

using System;
using MonoMac.AppKit;
using MonoMac.Foundation;
using MonoMac.ObjCRuntime;
using Substrate.Nbt;
using System.Runtime.InteropServices;
namespace NBTExplorer.Mac
{
public class NbtClipboardControllerMac : INbtClipboardController
{
public void CopyToClipboard (NbtClipboardData data)
{
NbtClipboardDataMac dataItem = new NbtClipboardDataMac(data);
NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
pasteboard.ClearContents();
pasteboard.WriteObjects(new NSPasteboardReading[] { dataItem });
}
public NbtClipboardData CopyFromClipboard ()
{
NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
NSObject[] items = pasteboard.ReadObjectsForClasses (new NSPasteboardReading[] { NbtClipboardDataMac.Type }, new NSDictionary());
foreach (NbtClipboardDataMac item in items) {
if (item == null)
continue;
TagNode node = item.Node;
if (node == null)
continue;
return new NbtClipboardData(item.Name, node);
}
return null;
}
public bool ContainsData
{
get {
NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
NSObject[] items = pasteboard.ReadObjectsForClasses (new NSPasteboardReading[] { NbtClipboardDataMac.Type }, new NSDictionary());
return items != null && items.Length > 0;
}
}
}
[Adopts("NSCoding")]
[Adopts("NSPasteboardReading")]
[Adopts("NSPasteboardWriting")]
[Register("NbtClipboardDataMac")]
public class NbtClipboardDataMac : NSPasteboardReading
{
static AdoptsAttribute _writingProtocol = new AdoptsAttribute ("NSPasteboardWriting");
static AdoptsAttribute _readingProtocol = new AdoptsAttribute ("NSPasteboardReading");
static AdoptsAttribute _codingProtocol = new AdoptsAttribute("NSCoding");
private static string _pasteboardItemName = "jaquadro.nbtexplorer.nbtClipboardDataMac";
public static NbtClipboardDataMac Type
{
get {
NbtClipboardDataMac inst = new NbtClipboardDataMac ();
return inst;
}
}
private string _name;
private byte[] _data;
private bool _bypassProtocolCheck = true;
private NbtClipboardDataMac ()
{
_name = "";
_data = new byte[0];
}
public NbtClipboardDataMac (NbtClipboardData data)
{
Name = data.Name;
Node = data.Node;
}
public override bool ConformsToProtocol (IntPtr protocol)
{
// XXX: This is a hack! There seems to be a bug in MonoMac resulting in different handle addresses
// for two protocols of (seemingly) the same name, so we have no way to make objc accept that we
// implement a given protocol. objc runtime method protocol_getName should be able to help us, but it
// crashes the runtime.
if (_bypassProtocolCheck)
return true;
if (protocol == _readingProtocol.ProtocolHandle)
return true;
if (protocol == _writingProtocol.ProtocolHandle)
return true;
if (protocol == _codingProtocol.ProtocolHandle)
return true;
return base.ConformsToProtocol (protocol);
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public TagNode Node
{
get { return NbtClipboardData.DeserializeNode(_data); }
set { _data = NbtClipboardData.SerializeNode(value); }
}
[Export ("initWithCoder:")]
public NbtClipboardDataMac (NSCoder coder)
: base(NSObjectFlag.Empty)
{
_name = (NSString)coder.DecodeObject("name");
_data = coder.DecodeBytes("data");
}
[Export ("encodeWithCoder:")]
public void Encode (NSCoder coder)
{
coder.Encode ((NSString)_name, "name");
coder.Encode (_data, "data");
}
[Export("writableTypesForPasteboard:")]
public string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard)
{
return new string[] { _pasteboardItemName };
}
[Export("pasteboardPropertyListForType:")]
public NSObject GetPasteboardPropertyListForType (string type)
{
if (type == _pasteboardItemName)
return NSKeyedArchiver.ArchivedDataWithRootObject(this);
else
return null;
}
[Export ("writingOptionsForType:pasteboard:")]
public NSPasteboardWritingOptions GetWritingOptionsForType (string type, NSPasteboard pasteboard)
{
return 0;
}
public override string[] GetReadableTypesForPasteboard (NSPasteboard pasteboard)
{
return new string[] { _pasteboardItemName };
}
public override NSPasteboardReadingOptions GetReadingOptionsForType (string type, NSPasteboard pasteboard)
{
if (type == _pasteboardItemName)
return NSPasteboardReadingOptions.AsKeyedArchive;
else
return 0;
}
public override NSObject InitWithPasteboardPropertyList (NSObject propertyList, string type)
{
if (type == _pasteboardItemName) {
return null;
}
else
return null;
}
// XXX: This is a hack. Not sure how to properly implement, but it's required either by pasteboard reading,
// or is a side-effect of our protocol conformance hack.
[Export("isSubclassOfClass:")]
public bool IsSubclassOf (NSObject cl)
{
return false;
}
}
}