forked from mirrors/NBTExplorer
914 lines
22 KiB
C#
914 lines
22 KiB
C#
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using MonoMac.Foundation;
|
|
using MonoMac.AppKit;
|
|
using NBTExplorer.Mac;
|
|
using System.IO;
|
|
using NBTExplorer.Model;
|
|
using Substrate.Nbt;
|
|
using System.Threading;
|
|
|
|
namespace NBTExplorer
|
|
{
|
|
public partial class MainWindow : MonoMac.AppKit.NSWindow
|
|
{
|
|
#region Constructors
|
|
|
|
// Called when created from unmanaged code
|
|
public MainWindow (IntPtr handle) : base (handle)
|
|
{
|
|
Initialize ();
|
|
}
|
|
|
|
// Called when created directly from a XIB file
|
|
[Export ("initWithCoder:")]
|
|
public MainWindow (NSCoder coder) : base (coder)
|
|
{
|
|
Initialize ();
|
|
}
|
|
|
|
// Shared initialization code
|
|
void Initialize ()
|
|
{
|
|
Delegate = new WindowDelegate(this);
|
|
InitializeIconRegistry();
|
|
FormHandlers.Register();
|
|
NbtClipboardController.Initialize(new NbtClipboardControllerMac());
|
|
}
|
|
|
|
private AppDelegate _appDelegate;
|
|
|
|
private NBTExplorer.Mac.IconRegistry _iconRegistry;
|
|
|
|
private void InitializeIconRegistry ()
|
|
{
|
|
_iconRegistry = new NBTExplorer.Mac.IconRegistry();
|
|
_iconRegistry.DefaultIcon = NSImage.ImageNamed("question-white.png");
|
|
|
|
_iconRegistry.Register(typeof(TagByteDataNode), NSImage.ImageNamed("document-attribute-b.png"));
|
|
_iconRegistry.Register(typeof(TagShortDataNode), NSImage.ImageNamed("document-attribute-s.png"));
|
|
_iconRegistry.Register(typeof(TagIntDataNode), NSImage.ImageNamed("document-attribute-i.png"));
|
|
_iconRegistry.Register(typeof(TagLongDataNode), NSImage.ImageNamed("document-attribute-l.png"));
|
|
_iconRegistry.Register(typeof(TagFloatDataNode), NSImage.ImageNamed("document-attribute-f.png"));
|
|
_iconRegistry.Register(typeof(TagDoubleDataNode), NSImage.ImageNamed("document-attribute-d.png"));
|
|
_iconRegistry.Register(typeof(TagByteArrayDataNode), NSImage.ImageNamed("edit-code.png"));
|
|
_iconRegistry.Register(typeof(TagStringDataNode), NSImage.ImageNamed("edit-small-caps.png"));
|
|
_iconRegistry.Register(typeof(TagListDataNode), NSImage.ImageNamed("edit-list.png"));
|
|
_iconRegistry.Register(typeof(TagCompoundDataNode), NSImage.ImageNamed("box.png"));
|
|
_iconRegistry.Register(typeof(RegionChunkDataNode), NSImage.ImageNamed("wooden-box.png"));
|
|
_iconRegistry.Register(typeof(DirectoryDataNode), NSImage.ImageNamed("folder-open"));
|
|
_iconRegistry.Register(typeof(RegionFileDataNode), NSImage.ImageNamed("block.png"));
|
|
_iconRegistry.Register(typeof(CubicRegionDataNode), NSImage.ImageNamed("block.png"));
|
|
_iconRegistry.Register(typeof(NbtFileDataNode), NSImage.ImageNamed("wooden-box.png"));
|
|
_iconRegistry.Register(typeof(TagIntArrayDataNode), NSImage.ImageNamed("edit-code-i.png"));
|
|
}
|
|
|
|
public AppDelegate AppDelegate
|
|
{
|
|
get { return _appDelegate; }
|
|
set
|
|
{
|
|
_appDelegate = value;
|
|
UpdateUI ();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
private TreeDataSource _dataSource;
|
|
|
|
public override void AwakeFromNib ()
|
|
{
|
|
base.AwakeFromNib ();
|
|
|
|
NSApplication.SharedApplication.MainMenu.AutoEnablesItems = false;
|
|
|
|
_dataSource = new TreeDataSource();
|
|
_mainOutlineView.DataSource = _dataSource;
|
|
_mainOutlineView.Delegate = new MyDelegate(this);
|
|
|
|
string[] args = Environment.GetCommandLineArgs();
|
|
if (args.Length > 2) {
|
|
string[] paths = new string[args.Length - 1];
|
|
Array.Copy(args, 1, paths, 0, paths.Length);
|
|
OpenPaths(paths);
|
|
}
|
|
else {
|
|
OpenMinecraftDirectory();
|
|
}
|
|
}
|
|
|
|
public class WindowDelegate : NSWindowDelegate
|
|
{
|
|
private MainWindow _main;
|
|
|
|
public WindowDelegate (MainWindow main) {
|
|
_main = main;
|
|
}
|
|
|
|
public override bool WindowShouldClose (NSObject sender)
|
|
{
|
|
//Settings.Default.RecentFiles = Settings.Default.RecentFiles;
|
|
//Settings.Default.Save();
|
|
return _main.ConfirmExit();
|
|
}
|
|
}
|
|
|
|
public class MyDelegate : NSOutlineViewDelegate
|
|
{
|
|
private MainWindow _main;
|
|
|
|
public MyDelegate (MainWindow main)
|
|
{
|
|
_main = main;
|
|
}
|
|
|
|
public override void SelectionDidChange (NSNotification notification)
|
|
{
|
|
TreeDataNode node = _main.SelectedNode;
|
|
if (node != null)
|
|
_main.UpdateUI(node.Data);
|
|
}
|
|
|
|
public override void ItemWillExpand (NSNotification notification)
|
|
{
|
|
TreeDataNode node = notification.UserInfo ["NSObject"] as TreeDataNode;
|
|
if (node != null) {
|
|
Console.WriteLine ("Preparing to expand: " + node.Data.NodeDisplay);
|
|
_main.ExpandNode(node);
|
|
}
|
|
}
|
|
|
|
public override void ItemDidExpand (NSNotification notification)
|
|
{
|
|
TreeDataNode node = notification.UserInfo ["NSObject"] as TreeDataNode;
|
|
if (node != null) {
|
|
Console.WriteLine("Finished Expanding: " + node.Data.NodeDisplay);
|
|
}
|
|
}
|
|
|
|
public override void ItemWillCollapse (NSNotification notification)
|
|
{
|
|
TreeDataNode node = notification.UserInfo ["NSObject"] as TreeDataNode;
|
|
if (node != null) {
|
|
if (node.Data.NodeDisplay == "saves") // The root node
|
|
Console.WriteLine ("Uh-oh...");
|
|
Console.WriteLine("Preparing to collapse: " + node.Data.NodeDisplay);
|
|
}
|
|
}
|
|
|
|
public override void ItemDidCollapse (NSNotification notification)
|
|
{
|
|
TreeDataNode node = notification.UserInfo ["NSObject"] as TreeDataNode;
|
|
if (node != null) {
|
|
_main.CollapseNode(node);
|
|
}
|
|
}
|
|
|
|
public override void WillDisplayCell (NSOutlineView outlineView, NSObject cell, NSTableColumn tableColumn, NSObject item)
|
|
{
|
|
ImageAndTextCell c = cell as ImageAndTextCell;
|
|
TreeDataNode node = item as TreeDataNode;
|
|
|
|
c.Title = node.CombinedName;
|
|
c.Image = _main._iconRegistry.Lookup(node.Data.GetType());
|
|
//c.StringValue = node.Name;
|
|
//throw new System.NotImplementedException ();
|
|
}
|
|
}
|
|
|
|
#region Actions
|
|
|
|
partial void ActionOpenFolder (NSObject sender)
|
|
{
|
|
OpenFolder ();
|
|
}
|
|
|
|
partial void ActionSave (NSObject sender)
|
|
{
|
|
ActionSave ();
|
|
}
|
|
|
|
#endregion
|
|
|
|
private string _openFolderPath = null;
|
|
|
|
private void OpenFolder ()
|
|
{
|
|
NSOpenPanel opanel = new NSOpenPanel ();
|
|
opanel.CanChooseDirectories = true;
|
|
opanel.CanChooseFiles = false;
|
|
|
|
if (_openFolderPath != null)
|
|
opanel.DirectoryUrl = new NSUrl (_openFolderPath, true);
|
|
|
|
if (opanel.RunModal () == (int)NSPanelButtonType.Ok) {
|
|
_openFolderPath = opanel.DirectoryUrl.AbsoluteString;
|
|
OpenPaths(new string[] { opanel.DirectoryUrl.Path });
|
|
}
|
|
|
|
UpdateUI();
|
|
}
|
|
|
|
private void OpenFile ()
|
|
{
|
|
NSOpenPanel opanel = new NSOpenPanel ();
|
|
opanel.CanChooseDirectories = false;
|
|
opanel.CanChooseFiles = true;
|
|
//opanel.AllowsMultipleSelection = true;
|
|
|
|
if (opanel.RunModal() == (int)NSPanelButtonType.Ok) {
|
|
List<string> paths = new List<string>();
|
|
foreach (var url in opanel.Urls)
|
|
paths.Add(url.Path);
|
|
OpenPaths(paths);
|
|
}
|
|
|
|
UpdateUI();
|
|
}
|
|
|
|
private void OpenMinecraftDirectory ()
|
|
{
|
|
try {
|
|
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
|
path = Path.Combine(path, "Library", "Application Support");
|
|
path = Path.Combine(path, "minecraft", "saves");
|
|
|
|
if (!Directory.Exists(path)) {
|
|
path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
|
}
|
|
|
|
OpenPaths(new string[] { path });
|
|
}
|
|
catch (Exception e) {
|
|
NSAlert.WithMessage("Operation Failed", "OK", null, null, "Could not open default Minecraft save directory").RunModal();
|
|
Console.WriteLine(e.Message);
|
|
|
|
try {
|
|
OpenPaths(new string[] { Directory.GetCurrentDirectory() });
|
|
}
|
|
catch (Exception) {
|
|
//MessageBox.Show("Could not open current directory, this tool is probably not compatible with your platform.");
|
|
Console.WriteLine(e.Message);
|
|
NSApplication.SharedApplication.Terminate(this);
|
|
}
|
|
}
|
|
|
|
UpdateUI();
|
|
}
|
|
|
|
private void OpenPaths (IEnumerable<string> paths)
|
|
{
|
|
_dataSource.Nodes.Clear ();
|
|
_mainOutlineView.ReloadData ();
|
|
|
|
foreach (string path in paths) {
|
|
if (Directory.Exists (path)) {
|
|
DirectoryDataNode node = new DirectoryDataNode (path);
|
|
_dataSource.Nodes.Add (new TreeDataNode (node));
|
|
|
|
// AddPathToHistory(Settings.Default.RecentDirectories, path);
|
|
} else if (File.Exists (path)) {
|
|
DataNode node = null;
|
|
}
|
|
}
|
|
|
|
if (_dataSource.Nodes.Count > 0) {
|
|
_mainOutlineView.ExpandItem(_dataSource.Nodes[0]);
|
|
}
|
|
|
|
_mainOutlineView.ReloadData();
|
|
|
|
UpdateUI();
|
|
}
|
|
|
|
private void ExpandNode (TreeDataNode node)
|
|
{
|
|
if (node == null || node.IsExpanded)
|
|
return;
|
|
|
|
Console.WriteLine ("Expand Node: " + node.Data.NodeDisplay);
|
|
|
|
node.IsExpanded = true;
|
|
node.Nodes.Clear ();
|
|
|
|
DataNode backNode = node.Data;
|
|
if (!backNode.IsExpanded) {
|
|
backNode.Expand ();
|
|
}
|
|
|
|
foreach (DataNode child in backNode.Nodes) {
|
|
if (child != null) {
|
|
node.AddNode (new TreeDataNode (child));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CollapseNode (TreeDataNode node)
|
|
{
|
|
if (node == null || !node.IsExpanded)
|
|
return;
|
|
|
|
Console.WriteLine("Collapse Node: " + node.Data.NodeDisplay);
|
|
|
|
DataNode backNode = node.Data;
|
|
if (backNode.IsModified)
|
|
return;
|
|
|
|
backNode.Collapse();
|
|
|
|
node.IsExpanded = false;
|
|
node.Nodes.Clear();
|
|
}
|
|
|
|
private void RefreshChildNodes (TreeDataNode node, DataNode dataNode)
|
|
{
|
|
Dictionary<DataNode, TreeDataNode> currentNodes = new Dictionary<DataNode, TreeDataNode>();
|
|
foreach (TreeDataNode child in node.Nodes) {
|
|
currentNodes.Add(child.Data, child);
|
|
}
|
|
|
|
node.Nodes.Clear();
|
|
foreach (DataNode child in dataNode.Nodes) {
|
|
if (!currentNodes.ContainsKey(child))
|
|
node.Nodes.Add(new TreeDataNode(child));
|
|
else
|
|
node.Nodes.Add(currentNodes[child]);
|
|
}
|
|
|
|
//foreach (TreeDataNode child in node.Nodes)
|
|
// child.ContextMenuStrip = BuildNodeContextMenu(child.Tag as DataNode);
|
|
|
|
if (node.Nodes.Count == 0 && dataNode.HasUnexpandedChildren) {
|
|
ExpandNode(node);
|
|
_mainOutlineView.ExpandItem(node);
|
|
//node.Expand();
|
|
}
|
|
|
|
_mainOutlineView.ReloadItem(node, true);
|
|
}
|
|
|
|
private void CreateNode (TreeDataNode node, TagType type)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanCreateTag(type))
|
|
return;
|
|
|
|
if (node.Data.CreateNode(type)) {
|
|
//node.Text = dataNode.NodeDisplay;
|
|
RefreshChildNodes(node, node.Data);
|
|
UpdateUI(node.Data);
|
|
}
|
|
}
|
|
|
|
private TreeDataNode SelectedNode
|
|
{
|
|
get { return _mainOutlineView.ItemAtRow (_mainOutlineView.SelectedRow) as TreeDataNode; }
|
|
}
|
|
|
|
public void ActionOpen ()
|
|
{
|
|
if (ConfirmOpen())
|
|
OpenFile();
|
|
}
|
|
|
|
public void ActionOpenFolder ()
|
|
{
|
|
if (ConfirmOpen ())
|
|
OpenFolder ();
|
|
}
|
|
|
|
public void ActionOpenMinecraft ()
|
|
{
|
|
if (ConfirmOpen ())
|
|
OpenMinecraftDirectory();
|
|
}
|
|
|
|
public void ActionSave ()
|
|
{
|
|
Save ();
|
|
}
|
|
|
|
public void ActionCopy ()
|
|
{
|
|
CopyNode (SelectedNode);
|
|
}
|
|
|
|
public void ActionCut ()
|
|
{
|
|
CutNode (SelectedNode);
|
|
}
|
|
|
|
public void ActionPaste ()
|
|
{
|
|
PasteNode (SelectedNode);
|
|
}
|
|
|
|
public void ActionEditValue ()
|
|
{
|
|
EditNode(SelectedNode);
|
|
}
|
|
|
|
public void ActionRenameValue ()
|
|
{
|
|
RenameNode(SelectedNode);
|
|
}
|
|
|
|
public void ActionDeleteValue ()
|
|
{
|
|
DeleteNode(SelectedNode);
|
|
}
|
|
|
|
public void ActionMoveNodeUp ()
|
|
{
|
|
MoveNodeUp(SelectedNode);
|
|
}
|
|
|
|
public void ActionMoveNodeDown ()
|
|
{
|
|
MoveNodeDown (SelectedNode);
|
|
}
|
|
|
|
public void ActionFind ()
|
|
{
|
|
SearchNode (SelectedNode);
|
|
}
|
|
|
|
public void ActionFindNext ()
|
|
{
|
|
SearchNextNode();
|
|
}
|
|
|
|
public void ActionInsertByteTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_BYTE);
|
|
}
|
|
|
|
public void ActionInsertShortTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_SHORT);
|
|
}
|
|
|
|
public void ActionInsertIntTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_INT);
|
|
}
|
|
|
|
public void ActionInsertLongTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_LONG);
|
|
}
|
|
|
|
public void ActionInsertFloatTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_FLOAT);
|
|
}
|
|
|
|
public void ActionInsertDoubleTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_DOUBLE);
|
|
}
|
|
|
|
public void ActionInsertByteArrayTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_BYTE_ARRAY);
|
|
}
|
|
|
|
public void ActionInsertIntArrayTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_INT_ARRAY);
|
|
}
|
|
|
|
public void ActionInsertStringTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_STRING);
|
|
}
|
|
|
|
public void ActionInsertListTag ()
|
|
{
|
|
CreateNode (SelectedNode, TagType.TAG_LIST);
|
|
}
|
|
|
|
public void ActionInsertCompoundTag ()
|
|
{
|
|
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)
|
|
return;
|
|
|
|
if (!node.Data.CanEditNode)
|
|
return;
|
|
|
|
if (node.Data.EditNode()) {
|
|
//node.Text = node.Data.NodeDisplay;
|
|
UpdateUI(node.Data);
|
|
}
|
|
}
|
|
|
|
private void RenameNode (TreeDataNode node)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanRenameNode)
|
|
return;
|
|
|
|
if (node.Data.RenameNode()) {
|
|
//node.Text = dataNode.NodeDisplay;
|
|
UpdateUI(node.Data);
|
|
}
|
|
}
|
|
|
|
private void DeleteNode (TreeDataNode node)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanDeleteNode)
|
|
return;
|
|
|
|
if (node.Data.DeleteNode()) {
|
|
UpdateUI(node.Parent.Data);
|
|
//UpdateNodeText(node.Parent);
|
|
TreeDataNode parent = node.Parent;
|
|
node.Remove();
|
|
|
|
_mainOutlineView.ReloadItem(parent, true);
|
|
}
|
|
}
|
|
|
|
private void MoveNodeUp (TreeDataNode node)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanMoveNodeUp)
|
|
return;
|
|
|
|
node.Data.ChangeRelativePosition(-1);
|
|
RefreshChildNodes(node.Parent, node.Data.Parent);
|
|
}
|
|
|
|
private void MoveNodeDown (TreeDataNode node)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanMoveNodeDown)
|
|
return;
|
|
|
|
node.Data.ChangeRelativePosition(1);
|
|
RefreshChildNodes(node.Parent, node.Data.Parent);
|
|
}
|
|
|
|
private void Save ()
|
|
{
|
|
foreach (TreeDataNode node in _dataSource.Nodes) {
|
|
if (node.Data != null)
|
|
node.Data.Save();
|
|
}
|
|
|
|
UpdateUI();
|
|
}
|
|
|
|
private static ModalResult RunWindow (NSWindowController controller)
|
|
{
|
|
int response = NSApplication.SharedApplication.RunModalForWindow (controller.Window);
|
|
controller.Window.Close();
|
|
controller.Window.OrderOut(null);
|
|
|
|
if (!Enum.IsDefined(typeof(ModalResult), response))
|
|
response = 0;
|
|
|
|
return (ModalResult)response;
|
|
}
|
|
|
|
private CancelFindWindowController _searchForm;
|
|
private SearchStateMac _searchState;
|
|
|
|
private void SearchNode (TreeDataNode node)
|
|
{
|
|
if (node == null)
|
|
return;
|
|
|
|
if (!node.Data.CanSearchNode)
|
|
return;
|
|
|
|
FindWindowController form = new FindWindowController();
|
|
if (RunWindow (form) != ModalResult.OK)
|
|
return;
|
|
|
|
_searchState = new SearchStateMac(this) {
|
|
RootNode = node.Data,
|
|
SearchName = form.NameToken,
|
|
SearchValue = form.ValueToken,
|
|
DiscoverCallback = SearchDiscoveryCallback,
|
|
CollapseCallback = SearchCollapseCallback,
|
|
EndCallback = SearchEndCallback,
|
|
};
|
|
|
|
SearchNextNode();
|
|
}
|
|
|
|
private void SearchNextNode ()
|
|
{
|
|
if (_searchState == null)
|
|
return;
|
|
|
|
SearchWorker worker = new SearchWorker (_searchState);
|
|
|
|
Thread t = new Thread (new ThreadStart (worker.Run));
|
|
t.IsBackground = true;
|
|
t.Start ();
|
|
|
|
_searchForm = new CancelFindWindowController ();
|
|
if (RunWindow (_searchForm) == ModalResult.Cancel) {
|
|
worker.Cancel();
|
|
_searchState = null;
|
|
}
|
|
|
|
t.Join();
|
|
}
|
|
|
|
private void SearchDiscoveryCallback (DataNode node)
|
|
{
|
|
Console.WriteLine ("Discovery: " + node.NodeDisplay);
|
|
TreeDataNode frontNode = FindFrontNode(node);
|
|
Console.WriteLine (" Front Node: " + frontNode.Data.NodeDisplay);
|
|
_mainOutlineView.SelectRow (_mainOutlineView.RowForItem(frontNode), false);
|
|
_mainOutlineView.ScrollRowToVisible(_mainOutlineView.RowForItem(frontNode));
|
|
//_nodeTree.SelectedNode = FindFrontNode(node);
|
|
|
|
if (_searchForm != null) {
|
|
_searchForm.Accept();
|
|
_searchForm = null;
|
|
}
|
|
}
|
|
|
|
private void SearchCollapseCallback (DataNode node)
|
|
{
|
|
CollapseBelow(node);
|
|
}
|
|
|
|
private void SearchEndCallback (DataNode node)
|
|
{
|
|
_searchForm.Cancel();
|
|
_searchForm = null;
|
|
|
|
NSAlert.WithMessage("End of Results", "OK", null, null, "").RunModal();
|
|
}
|
|
|
|
private TreeDataNode GetRootFromDataNodePath (DataNode node, out Stack<DataNode> hierarchy)
|
|
{
|
|
hierarchy = new Stack<DataNode>();
|
|
while (node != null) {
|
|
hierarchy.Push(node);
|
|
node = node.Parent;
|
|
}
|
|
|
|
DataNode rootDataNode = hierarchy.Pop();
|
|
TreeDataNode frontNode = null;
|
|
foreach (TreeDataNode child in _dataSource.Nodes) {
|
|
if (child.Data == rootDataNode)
|
|
frontNode = child;
|
|
}
|
|
|
|
return frontNode;
|
|
}
|
|
|
|
private TreeDataNode FindFrontNode (DataNode node)
|
|
{
|
|
Stack<DataNode> hierarchy;
|
|
TreeDataNode frontNode = GetRootFromDataNodePath(node, out hierarchy);
|
|
|
|
if (frontNode == null)
|
|
return null;
|
|
|
|
while (hierarchy.Count > 0) {
|
|
if (!frontNode.IsExpanded) {
|
|
_mainOutlineView.ExpandItem(frontNode);
|
|
_mainOutlineView.ReloadItem(frontNode);
|
|
}
|
|
|
|
DataNode childData = hierarchy.Pop();
|
|
foreach (TreeDataNode childFront in frontNode.Nodes) {
|
|
if (childFront.Data == childData) {
|
|
frontNode = childFront;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return frontNode;
|
|
}
|
|
|
|
private void CollapseBelow (DataNode node)
|
|
{
|
|
Stack<DataNode> hierarchy;
|
|
TreeDataNode frontNode = GetRootFromDataNodePath (node, out hierarchy);
|
|
|
|
if (frontNode == null)
|
|
return;
|
|
|
|
while (hierarchy.Count > 0) {
|
|
if (!frontNode.IsExpanded)
|
|
return;
|
|
|
|
DataNode childData = hierarchy.Pop ();
|
|
foreach (TreeDataNode childFront in frontNode.Nodes) {
|
|
if (childFront.Data == childData) {
|
|
frontNode = childFront;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (frontNode.IsExpanded) {
|
|
_mainOutlineView.CollapseItem (frontNode);
|
|
frontNode.IsExpanded = false;
|
|
}
|
|
}
|
|
|
|
private bool ConfirmExit ()
|
|
{
|
|
if (CheckModifications()) {
|
|
int id = NSAlert.WithMessage("Unsaved Changes", "OK", "Cancel", "", "You currently have unsaved changes. Close anyway?").RunModal();
|
|
if (id != 1)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool ConfirmOpen ()
|
|
{
|
|
if (CheckModifications()) {
|
|
int id = NSAlert.WithMessage("Unsaved Changes", "OK", "Cancel", "", "You currently have unsaved changes. Open new location anyway?").RunModal();
|
|
if (id != 1)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool CheckModifications ()
|
|
{
|
|
foreach (TreeDataNode node in _dataSource.Nodes) {
|
|
if (node.Data != null && node.Data.IsModified)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void UpdateUI ()
|
|
{
|
|
if (_appDelegate == null)
|
|
return;
|
|
|
|
TreeDataNode selected = _mainOutlineView.ItemAtRow(_mainOutlineView.SelectedRow) as TreeDataNode;
|
|
if (selected != null) {
|
|
UpdateUI(selected.Data);
|
|
}
|
|
else {
|
|
UpdateUI(new DataNode());
|
|
|
|
_appDelegate.MenuSave.Enabled = CheckModifications();
|
|
_appDelegate.MenuFind.Enabled = false;
|
|
_appDelegate.MenuFindNext.Enabled = _searchState != null;
|
|
|
|
_toolbarSave.Enabled = _appDelegate.MenuSave.Enabled;
|
|
}
|
|
}
|
|
|
|
private void UpdateUI (DataNode node)
|
|
{
|
|
if (_appDelegate == null || node == null)
|
|
return;
|
|
|
|
_appDelegate.MenuInsertByte.Enabled = node.CanCreateTag(TagType.TAG_BYTE);
|
|
_appDelegate.MenuInsertShort.Enabled = node.CanCreateTag(TagType.TAG_SHORT);
|
|
_appDelegate.MenuInsertInt.Enabled = node.CanCreateTag(TagType.TAG_INT);
|
|
_appDelegate.MenuInsertLong.Enabled = node.CanCreateTag(TagType.TAG_LONG);
|
|
_appDelegate.MenuInsertFloat.Enabled = node.CanCreateTag(TagType.TAG_FLOAT);
|
|
_appDelegate.MenuInsertDouble.Enabled = node.CanCreateTag(TagType.TAG_DOUBLE);
|
|
_appDelegate.MenuInsertByteArray.Enabled = node.CanCreateTag(TagType.TAG_BYTE_ARRAY);
|
|
_appDelegate.MenuInsertIntArray.Enabled = node.CanCreateTag(TagType.TAG_INT_ARRAY);
|
|
_appDelegate.MenuInsertString.Enabled = node.CanCreateTag(TagType.TAG_STRING);
|
|
_appDelegate.MenuInsertList.Enabled = node.CanCreateTag(TagType.TAG_LIST);
|
|
_appDelegate.MenuInsertCompound.Enabled = node.CanCreateTag(TagType.TAG_COMPOUND);
|
|
|
|
_appDelegate.MenuSave.Enabled = CheckModifications();
|
|
_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;
|
|
_appDelegate.MenuMoveUp.Enabled = node.CanMoveNodeUp;
|
|
_appDelegate.MenuMoveDown.Enabled = node.CanMoveNodeDown;
|
|
_appDelegate.MenuFind.Enabled = node.CanSearchNode;
|
|
_appDelegate.MenuFindNext.Enabled = _searchState != null;
|
|
|
|
_toolbarSave.Enabled = _appDelegate.MenuSave.Enabled;
|
|
}
|
|
|
|
/*private void UpdateOpenMenu ()
|
|
{
|
|
try {
|
|
if (Settings.Default.RecentDirectories == null)
|
|
Settings.Default.RecentDirectories = new StringCollection();
|
|
if (Settings.Default.RecentFiles == null)
|
|
Settings.Default.RecentFiles = new StringCollection();
|
|
}
|
|
catch {
|
|
return;
|
|
}
|
|
|
|
_menuItemRecentFolders.DropDown = BuildRecentEntriesDropDown(Settings.Default.RecentDirectories);
|
|
_menuItemRecentFiles.DropDown = BuildRecentEntriesDropDown(Settings.Default.RecentFiles);
|
|
}
|
|
|
|
private ToolStripDropDown BuildRecentEntriesDropDown (StringCollection list)
|
|
{
|
|
if (list == null || list.Count == 0)
|
|
return new ToolStripDropDown();
|
|
|
|
ToolStripDropDown menu = new ToolStripDropDown();
|
|
foreach (string entry in list) {
|
|
ToolStripMenuItem item = new ToolStripMenuItem("&" + (menu.Items.Count + 1) + " " + entry);
|
|
item.Tag = entry;
|
|
item.Click += _menuItemRecentPaths_Click;
|
|
|
|
menu.Items.Add(item);
|
|
}
|
|
|
|
return menu;
|
|
}
|
|
|
|
private void AddPathToHistory (StringCollection list, string entry)
|
|
{
|
|
foreach (string item in list) {
|
|
if (item == entry) {
|
|
list.Remove(item);
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (list.Count >= 5)
|
|
list.RemoveAt(list.Count - 1);
|
|
|
|
list.Insert(0, entry);
|
|
}*/
|
|
}
|
|
}
|
|
|