Working clipboard support, albeit by hacks.

This commit is contained in:
Justin Aquadro 2012-11-10 02:45:36 -05:00
parent 45dac1389d
commit e11c0c4d9d
7 changed files with 261 additions and 9 deletions

View file

@ -4,10 +4,8 @@
<dict>
<key>CFBundleDocumentTypes</key>
<array/>
<key>CFBundleIconFiles</key>
<array>
<string>dead_bush.icns</string>
</array>
<key>CFBundleIconFile</key>
<string>nbte.icns</string>
<key>CFBundleIdentifier</key>
<string>jaquadro.NBTExplorer</string>
<key>CFBundleName</key>

View file

@ -156,6 +156,21 @@ namespace NBTExplorer
get { return _menuInsertCompound; }
}
partial void ActionCut (MonoMac.Foundation.NSObject sender)
{
mainWindowController.Window.ActionCut();
}
partial void ActionCopy (MonoMac.Foundation.NSObject sender)
{
mainWindowController.Window.ActionCopy();
}
partial void ActionPaste (MonoMac.Foundation.NSObject sender)
{
mainWindowController.Window.ActionPaste();
}
partial void ActionRename (NSObject sender)
{
mainWindowController.Window.ActionRenameValue();

View file

@ -33,6 +33,7 @@ namespace NBTExplorer
{
InitializeIconRegistry();
FormHandlers.Register();
NbtClipboardController.Initialize(new NbtClipboardControllerMac());
}
private AppDelegate _appDelegate;
@ -360,6 +361,21 @@ namespace NBTExplorer
get { return _mainOutlineView.ItemAtRow (_mainOutlineView.SelectedRow) as TreeDataNode; }
}
public void ActionCopy ()
{
CopyNode (SelectedNode);
}
public void ActionCut ()
{
CutNode (SelectedNode);
}
public void ActionPaste ()
{
PasteNode (SelectedNode);
}
public void ActionEditValue ()
{
EditNode(SelectedNode);
@ -440,6 +456,48 @@ namespace NBTExplorer
CreateNode (SelectedNode, TagType.TAG_COMPOUND);
}
private void CopyNode (TreeDataNode node)
{
if (node == null)
return;
if (!node.Data.CanCopyNode)
return;
node.Data.CopyNode();
}
private void CutNode (TreeDataNode node)
{
if (node == null)
return;
if (!node.Data.CanCutNode)
return;
if (node.Data.CutNode()) {
TreeDataNode parent = node.Parent;
UpdateUI(parent.Data);
node.Remove();
_mainOutlineView.ReloadItem(parent, true);
}
}
private void PasteNode (TreeDataNode node)
{
if (node == null)
return;
if (!node.Data.CanPasteIntoNode)
return;
if (node.Data.PasteNode()) {
//node.Text = dataNode.NodeDisplay;
RefreshChildNodes(node, node.Data);
UpdateUI(node.Data);
}
}
private void EditNode (TreeDataNode node)
{
if (node == null)
@ -622,9 +680,9 @@ namespace NBTExplorer
_appDelegate.MenuInsertCompound.Enabled = node.CanCreateTag(TagType.TAG_COMPOUND);
_appDelegate.MenuSave.Enabled = CheckModifications();
_appDelegate.MenuCopy.Enabled = node.CanCopyNode;
_appDelegate.MenuCut.Enabled = node.CanCutNode;
_appDelegate.MenuPaste.Enabled = node.CanPasteIntoNode;
_appDelegate.MenuCopy.Enabled = node.CanCopyNode && NbtClipboardController.IsInitialized;
_appDelegate.MenuCut.Enabled = node.CanCutNode && NbtClipboardController.IsInitialized;
_appDelegate.MenuPaste.Enabled = node.CanPasteIntoNode && NbtClipboardController.IsInitialized;
_appDelegate.MenuDelete.Enabled = node.CanDeleteNode;
_appDelegate.MenuEditValue.Enabled = node.CanEditNode;
_appDelegate.MenuRename.Enabled = node.CanRenameNode;

View file

@ -0,0 +1,175 @@
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;
}
// 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;
}
}
}

View file

@ -69,8 +69,8 @@
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Data" />
<Reference Include="MonoMac, Version=0.0.0.0, Culture=neutral">
<Private>False</Private>
<Reference Include="MonoMac">
<HintPath>..\monomac\src\MonoMac.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@ -183,6 +183,8 @@
<Compile Include="Mac\EditValueWindow.designer.cs">
<DependentUpon>EditValueWindow.cs</DependentUpon>
</Compile>
<Compile Include="NbtClipboardController.cs" />
<Compile Include="Mac\NbtClipboardControllerMac.cs" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="Resources\Dead_Bush.png" />
@ -244,4 +246,8 @@
<InterfaceDefinition Include="Mac\CreateNodeWindow.xib" />
<InterfaceDefinition Include="Mac\EditValueWindow.xib" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Dead_Bush_256.icns" />
<Content Include="nbte.icns" />
</ItemGroup>
</Project>

Binary file not shown.

BIN
nbte.icns Normal file

Binary file not shown.