Feature parity

This commit is contained in:
Justin Aquadro 2012-09-01 19:27:50 -04:00
parent 2250139349
commit 3e7e05bda9
11 changed files with 755 additions and 80 deletions

76
MainForm.Designer.cs generated
View file

@ -31,11 +31,11 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openMinecraftSaveFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemOpen = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemOpenFolder = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemOpenMinecraftSaveFolder = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemSave = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this._menuItemExit = new System.Windows.Forms.ToolStripMenuItem();
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -48,7 +48,7 @@
this._menuItemDelete = new System.Windows.Forms.ToolStripMenuItem();
this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemFind = new System.Windows.Forms.ToolStripMenuItem();
this.findNextToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemFindNext = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._menuItemAbout = new System.Windows.Forms.ToolStripMenuItem();
this._nodeTree = new System.Windows.Forms.TreeView();
@ -107,11 +107,11 @@
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openToolStripMenuItem,
this.openFolderToolStripMenuItem,
this.openMinecraftSaveFolderToolStripMenuItem,
this._menuItemOpen,
this._menuItemOpenFolder,
this._menuItemOpenMinecraftSaveFolder,
this.toolStripSeparator3,
this.saveToolStripMenuItem,
this._menuItemSave,
this.toolStripSeparator4,
this._menuItemExit});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
@ -120,26 +120,26 @@
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
this.openToolStripMenuItem.Size = new System.Drawing.Size(223, 22);
this.openToolStripMenuItem.Text = "&Open...";
this._menuItemOpen.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
this._menuItemOpen.Name = "openToolStripMenuItem";
this._menuItemOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
this._menuItemOpen.Size = new System.Drawing.Size(223, 22);
this._menuItemOpen.Text = "&Open...";
//
// openFolderToolStripMenuItem
//
this.openFolderToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openFolderToolStripMenuItem.Image")));
this.openFolderToolStripMenuItem.Name = "openFolderToolStripMenuItem";
this.openFolderToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
this._menuItemOpenFolder.Image = ((System.Drawing.Image)(resources.GetObject("openFolderToolStripMenuItem.Image")));
this._menuItemOpenFolder.Name = "openFolderToolStripMenuItem";
this._menuItemOpenFolder.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
| System.Windows.Forms.Keys.O)));
this.openFolderToolStripMenuItem.Size = new System.Drawing.Size(223, 22);
this.openFolderToolStripMenuItem.Text = "Open &Folder...";
this._menuItemOpenFolder.Size = new System.Drawing.Size(223, 22);
this._menuItemOpenFolder.Text = "Open &Folder...";
//
// openMinecraftSaveFolderToolStripMenuItem
//
this.openMinecraftSaveFolderToolStripMenuItem.Name = "openMinecraftSaveFolderToolStripMenuItem";
this.openMinecraftSaveFolderToolStripMenuItem.Size = new System.Drawing.Size(223, 22);
this.openMinecraftSaveFolderToolStripMenuItem.Text = "Open &Minecraft Save Folder";
this._menuItemOpenMinecraftSaveFolder.Name = "openMinecraftSaveFolderToolStripMenuItem";
this._menuItemOpenMinecraftSaveFolder.Size = new System.Drawing.Size(223, 22);
this._menuItemOpenMinecraftSaveFolder.Text = "Open &Minecraft Save Folder";
//
// toolStripSeparator3
//
@ -148,11 +148,11 @@
//
// saveToolStripMenuItem
//
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
this.saveToolStripMenuItem.Size = new System.Drawing.Size(223, 22);
this.saveToolStripMenuItem.Text = "&Save";
this._menuItemSave.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
this._menuItemSave.Name = "saveToolStripMenuItem";
this._menuItemSave.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
this._menuItemSave.Size = new System.Drawing.Size(223, 22);
this._menuItemSave.Text = "&Save";
//
// toolStripSeparator4
//
@ -238,7 +238,7 @@
//
this.searchToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._menuItemFind,
this.findNextToolStripMenuItem});
this._menuItemFindNext});
this.searchToolStripMenuItem.Name = "searchToolStripMenuItem";
this.searchToolStripMenuItem.Size = new System.Drawing.Size(54, 20);
this.searchToolStripMenuItem.Text = "&Search";
@ -253,11 +253,11 @@
//
// findNextToolStripMenuItem
//
this.findNextToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("findNextToolStripMenuItem.Image")));
this.findNextToolStripMenuItem.Name = "findNextToolStripMenuItem";
this.findNextToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F3;
this.findNextToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.findNextToolStripMenuItem.Text = "Find Next";
this._menuItemFindNext.Image = ((System.Drawing.Image)(resources.GetObject("findNextToolStripMenuItem.Image")));
this._menuItemFindNext.Name = "findNextToolStripMenuItem";
this._menuItemFindNext.ShortcutKeys = System.Windows.Forms.Keys.F3;
this._menuItemFindNext.Size = new System.Drawing.Size(146, 22);
this._menuItemFindNext.Text = "Find Next";
//
// helpToolStripMenuItem
//
@ -661,18 +661,18 @@
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.ToolStripButton _buttonAddTagString;
private System.Windows.Forms.ToolStripMenuItem _menuItemAbout;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openFolderToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem _menuItemOpen;
private System.Windows.Forms.ToolStripMenuItem _menuItemOpenFolder;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem _menuItemSave;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
private System.Windows.Forms.ToolStripMenuItem _menuItemExit;
private System.Windows.Forms.ToolStripMenuItem _menuItemFind;
private System.Windows.Forms.ToolStripMenuItem findNextToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem _menuItemFindNext;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
private System.Windows.Forms.ToolStripButton _buttonFindNext;
private System.Windows.Forms.ToolStripButton _buttonOpenFolder;
private System.Windows.Forms.ToolStripMenuItem openMinecraftSaveFolderToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem _menuItemOpenMinecraftSaveFolder;
private System.Windows.Forms.ToolStripPanel BottomToolStripPanel;
private System.Windows.Forms.ToolStripPanel TopToolStripPanel;
private System.Windows.Forms.ToolStripPanel RightToolStripPanel;

View file

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Substrate;
using Substrate.Core;
using Substrate.Nbt;
using NBTExplorer.Forms;
using NBTExplorer.Model;
using Substrate.Nbt;
namespace NBTExplorer
{
@ -15,6 +16,8 @@ namespace NBTExplorer
private IconRegistry _iconRegistry;
private string _openFolderPath = null;
static MainForm ()
{
_tagIconIndex = new Dictionary<TagType, int>();
@ -36,10 +39,18 @@ namespace NBTExplorer
InitializeComponent();
InitializeIconRegistry();
FormClosing += MainForm_Closing;
_nodeTree.BeforeExpand += _nodeTree_BeforeExpand;
_nodeTree.AfterCollapse += _nodeTree_AfterCollapse;
_nodeTree.AfterSelect += _nodeTree_AfterSelect;
_nodeTree.NodeMouseDoubleClick += _nodeTree_NodeMouseDoubleClick;
_nodeTree.DragEnter += _nodeTree_DragEnter;
_nodeTree.DragDrop += _nodeTree_DragDrop;
_buttonOpen.Click += _buttonOpen_Click;
_buttonOpenFolder.Click += _buttonOpenFolder_Click;
_buttonSave.Click += _buttonSave_Click;
_buttonEdit.Click += _buttonEdit_Click;
_buttonRename.Click += _buttonRename_Click;
_buttonDelete.Click += _buttonDelete_Click;
@ -57,7 +68,12 @@ namespace NBTExplorer
_buttonAddTagLong.Click += _buttonAddTagLong_Click;
_buttonAddTagShort.Click += _buttonAddTagShort_Click;
_buttonAddTagString.Click += _buttonAddTagString_Click;
_buttonFindNext.Click += _buttonFindNext_Click;
_menuItemOpen.Click += _menuItemOpen_Click;
_menuItemOpenFolder.Click += _menuItemOpenFolder_Click;
_menuItemOpenMinecraftSaveFolder.Click += _menuItemOpenMinecraftSaveFolder_Click;
_menuItemSave.Click += _menuItemSave_Click;
_menuItemExit.Click += _menuItemExit_Click;
_menuItemEditValue.Click += _menuItemEditValue_Click;
_menuItemRename.Click += _menuItemRename_Click;
@ -65,27 +81,15 @@ namespace NBTExplorer
_menuItemCopy.Click += _menuItemCopy_Click;
_menuItemCut.Click += _menuItemCut_Click;
_menuItemPaste.Click += _menuItemPaste_Click;
_menuItemFind.Click += _menuItemFind_Click;
_menuItemFindNext.Click += _menuItemFindNext_Click;
_menuItemAbout.Click += _menuItemAbout_Click;
/*_nodeTree.BeforeExpand += NodeExpand;
_nodeTree.AfterCollapse += NodeCollapse;
_nodeTree.AfterSelect += NodeSelected;
_nodeTree.NodeMouseClick += NodeClicked;
_nodeTree.NodeMouseDoubleClick += NodeDoubleClicked;
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1) {
OpenFile(args[1]);
}
else {
OpenMinecraftDir();
}*/
//OpenDirectory(@"F:\Minecraft\tps");
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1) {
OpenFile(args[1]);
string[] paths = new string[args.Length - 1];
Array.Copy(args, 1, paths, 0, paths.Length);
OpenPaths(paths);
}
else {
OpenMinecraftDirectory();
@ -114,26 +118,47 @@ namespace NBTExplorer
_iconRegistry.Register(typeof(TagIntArrayDataNode), 14);
}
private void OpenFile (string path)
public void OpenFile ()
{
_nodeTree.Nodes.Clear();
OpenFileDialog ofd = new OpenFileDialog();
ofd.RestoreDirectory = true;
ofd.Multiselect = true;
NbtFileDataNode node = NbtFileDataNode.TryCreateFrom(path);
_nodeTree.Nodes.Add(CreateUnexpandedNode(node));
if (ofd.ShowDialog() == DialogResult.OK) {
OpenPaths(ofd.FileNames);
}
}
private void OpenDirectory (string path)
private void OpenFolder ()
{
FolderBrowserDialog ofd = new FolderBrowserDialog();
if (_openFolderPath != null)
ofd.SelectedPath = _openFolderPath;
if (ofd.ShowDialog() == DialogResult.OK) {
_openFolderPath = ofd.SelectedPath;
OpenPaths(new string[] { ofd.SelectedPath });
}
}
public void OpenPaths (string[] paths)
{
_nodeTree.Nodes.Clear();
DirectoryDataNode node = new DirectoryDataNode(path);
foreach (string path in paths) {
if (Directory.Exists(path)) {
DirectoryDataNode node = new DirectoryDataNode(path);
_nodeTree.Nodes.Add(CreateUnexpandedNode(node));
}
else if (File.Exists(path)) {
NbtFileDataNode node = NbtFileDataNode.TryCreateFrom(path);
_nodeTree.Nodes.Add(CreateUnexpandedNode(node));
}
}
TreeNode frontNode = CreateUnexpandedNode(node);
_nodeTree.Nodes.Add(frontNode);
ExpandNode(frontNode);
frontNode.Expand();
if (_nodeTree.Nodes.Count > 0) {
_nodeTree.Nodes[0].Expand();
}
}
private void OpenMinecraftDirectory ()
@ -147,12 +172,12 @@ namespace NBTExplorer
path = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
}
OpenDirectory(path);
OpenPaths(new string[] { path });
}
catch (Exception) {
MessageBox.Show("Could not open default Minecraft save directory");
try {
OpenDirectory(Directory.GetCurrentDirectory());
OpenPaths(new string[] { Directory.GetCurrentDirectory() });
}
catch (Exception) {
MessageBox.Show("Could not open current directory, this tool is probably not compatible with your platform.");
@ -179,12 +204,12 @@ namespace NBTExplorer
if (node == null || !(node.Tag is DataNode))
return;
DataNode backNode = node.Tag as DataNode;
if (!backNode.HasUnexpandedChildren)
if (node.IsExpanded)
return;
node.Nodes.Clear();
DataNode backNode = node.Tag as DataNode;
if (!backNode.IsExpanded)
backNode.Expand();
@ -192,6 +217,22 @@ namespace NBTExplorer
node.Nodes.Add(CreateUnexpandedNode(child));
}
private void CollapseNode (TreeNode node)
{
if (node == null || !(node.Tag is DataNode))
return;
DataNode backNode = node.Tag as DataNode;
if (backNode.IsModified)
return;
backNode.Collapse();
node.Nodes.Clear();
if (backNode.HasUnexpandedChildren)
node.Nodes.Add(new TreeNode());
}
private void CreateNode (TreeNode node, TagType type)
{
if (node == null || !(node.Tag is DataNode))
@ -244,6 +285,7 @@ namespace NBTExplorer
if (dataNode.EditNode()) {
node.Text = dataNode.NodeDisplay;
UpdateUI(dataNode);
}
}
@ -321,6 +363,167 @@ namespace NBTExplorer
}
}
private void Save ()
{
foreach (TreeNode node in _nodeTree.Nodes) {
DataNode dataNode = node.Tag as DataNode;
if (dataNode != null)
dataNode.Save();
}
UpdateUI();
}
private bool ConfirmExit ()
{
if (CheckModifications()) {
if (MessageBox.Show("You currently have unsaved changes. Close anyway?", "Unsaved Changes", MessageBoxButtons.OKCancel) != DialogResult.OK)
return false;
}
return true;
}
private CancelSearchForm _searchForm;
private SearchState _searchState;
private void SearchNode (TreeNode node)
{
if (node == null || !(node.Tag is DataNode))
return;
DataNode dataNode = node.Tag as DataNode;
if (!dataNode.CanSearchNode)
return;
Find form = new Find();
if (form.ShowDialog() != DialogResult.OK)
return;
_searchState = new SearchState() {
RootNode = dataNode,
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, this);
Thread t = new Thread(new ThreadStart(worker.Run));
t.IsBackground = true;
t.Start();
_searchForm = new CancelSearchForm();
if (_searchForm.ShowDialog(this) == DialogResult.Cancel) {
worker.Cancel();
_searchState = null;
}
t.Join();
}
private void SearchDiscoveryCallback (DataNode node)
{
_nodeTree.SelectedNode = FindFrontNode(node);
if (_searchForm != null) {
_searchForm.DialogResult = DialogResult.OK;
_searchForm = null;
}
}
private void SearchCollapseCallback (DataNode node)
{
CollapseBelow(node);
}
private void SearchEndCallback ()
{
_searchForm.DialogResult = DialogResult.OK;
_searchForm = null;
MessageBox.Show("End of results");
}
private TreeNode GetRootFromDataNodePath (DataNode node, out Stack<DataNode> hierarchy)
{
hierarchy = new Stack<DataNode>();
while (node != null) {
hierarchy.Push(node);
node = node.Parent;
}
DataNode rootDataNode = hierarchy.Pop();
TreeNode frontNode = null;
foreach (TreeNode child in _nodeTree.Nodes) {
if (child.Tag == rootDataNode)
frontNode = child;
}
return frontNode;
}
private TreeNode FindFrontNode (DataNode node)
{
Stack<DataNode> hierarchy;
TreeNode frontNode = GetRootFromDataNodePath(node, out hierarchy);
if (frontNode == null)
return null;
while (hierarchy.Count > 0) {
if (!frontNode.IsExpanded) {
frontNode.Nodes.Add(new TreeNode());
frontNode.Expand();
}
DataNode childData = hierarchy.Pop();
foreach (TreeNode childFront in frontNode.Nodes) {
if (childFront.Tag == childData) {
frontNode = childFront;
break;
}
}
}
return frontNode;
}
private void CollapseBelow (DataNode node)
{
Stack<DataNode> hierarchy;
TreeNode frontNode = GetRootFromDataNodePath(node, out hierarchy);
if (frontNode == null)
return;
while (hierarchy.Count > 0) {
if (!frontNode.IsExpanded)
return;
DataNode childData = hierarchy.Pop();
foreach (TreeNode childFront in frontNode.Nodes) {
if (childFront.Tag == childData) {
frontNode = childFront;
break;
}
}
}
if (frontNode.IsExpanded)
frontNode.Collapse();
}
private void UpdateNodeText (TreeNode node)
{
if (node == null || !(node.Tag is DataNode))
@ -330,6 +533,33 @@ namespace NBTExplorer
node.Text = dataNode.NodeDisplay;
}
private bool CheckModifications ()
{
foreach (TreeNode node in _nodeTree.Nodes) {
DataNode dataNode = node.Tag as DataNode;
if (dataNode != null && dataNode.IsModified)
return true;
}
return false;
}
private void UpdateUI ()
{
TreeNode selected = _nodeTree.SelectedNode;
if (selected != null && selected.Tag is DataNode) {
UpdateUI(selected.Tag as DataNode);
}
else {
_buttonSave.Enabled = CheckModifications();
_buttonFindNext.Enabled = false;
_menuItemSave.Enabled = _buttonSave.Enabled;
_menuItemFind.Enabled = false;
_menuItemFindNext.Enabled = _searchState != null;
}
}
private void UpdateUI (DataNode node)
{
if (node == null)
@ -347,25 +577,35 @@ namespace NBTExplorer
_buttonAddTagShort.Enabled = node.CanCreateTag(TagType.TAG_SHORT);
_buttonAddTagString.Enabled = node.CanCreateTag(TagType.TAG_STRING);
_buttonSave.Enabled = CheckModifications();
_buttonCopy.Enabled = node.CanCopyNode;
_buttonCut.Enabled = node.CanCutNode;
_buttonDelete.Enabled = node.CanDeleteNode;
_buttonEdit.Enabled = node.CanEditNode;
_buttonFindNext.Enabled = node.CanSearchNode; // Not entirely
_buttonPaste.Enabled = node.CanPasteIntoNode; // Not entirely
_buttonFindNext.Enabled = node.CanSearchNode || _searchState != null;
_buttonPaste.Enabled = node.CanPasteIntoNode;
_buttonRename.Enabled = node.CanRenameNode;
_menuItemSave.Enabled = _buttonSave.Enabled;
_menuItemCopy.Enabled = node.CanCopyNode;
_menuItemCut.Enabled = node.CanCutNode;
_menuItemDelete.Enabled = node.CanDeleteNode;
_menuItemEditValue.Enabled = node.CanEditNode;
_menuItemFind.Enabled = node.CanSearchNode;
_menuItemPaste.Enabled = node.CanPasteIntoNode; // Not entirely
_menuItemPaste.Enabled = node.CanPasteIntoNode;
_menuItemRename.Enabled = node.CanRenameNode;
_menuItemFind.Enabled = node.CanSearchNode;
_menuItemFindNext.Enabled = _searchState != null;
}
#region Event Handlers
private void MainForm_Closing (object sender, CancelEventArgs e)
{
if (!ConfirmExit())
e.Cancel = true;
}
#region TreeView Event Handlers
private void _nodeTree_BeforeExpand (object sender, TreeViewCancelEventArgs e)
@ -373,9 +613,15 @@ namespace NBTExplorer
ExpandNode(e.Node);
}
private void _nodeTree_AfterCollapse (object sender, TreeViewEventArgs e)
{
CollapseNode(e.Node);
}
private void _nodeTree_AfterSelect (object sender, TreeViewEventArgs e)
{
UpdateUI(e.Node.Tag as DataNode);
if (e.Node != null)
UpdateUI(e.Node.Tag as DataNode);
}
private void _nodeTree_NodeMouseDoubleClick (object sender, TreeNodeMouseClickEventArgs e)
@ -383,10 +629,36 @@ namespace NBTExplorer
EditNode(e.Node);
}
private void _nodeTree_DragDrop (object sender, DragEventArgs e)
{
OpenPaths((string[])e.Data.GetData(DataFormats.FileDrop));
}
private void _nodeTree_DragEnter (object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
#endregion
#region Toolstrip Event Handlers
private void _buttonOpen_Click (object sender, EventArgs e)
{
OpenFile();
}
private void _buttonOpenFolder_Click (object sender, EventArgs e)
{
OpenFolder();
}
private void _buttonSave_Click (object sender, EventArgs e)
{
Save();
}
private void _buttonEdit_Click (object sender, EventArgs e)
{
EditNode(_nodeTree.SelectedNode);
@ -472,10 +744,38 @@ namespace NBTExplorer
CreateNode(_nodeTree.SelectedNode, TagType.TAG_STRING);
}
private void _buttonFindNext_Click (object sender, EventArgs e)
{
if (_searchState != null)
SearchNextNode();
else
SearchNode(_nodeTree.SelectedNode);
}
#endregion
#region Menu Event Handlers
private void _menuItemOpen_Click (object sender, EventArgs e)
{
OpenFile();
}
private void _menuItemOpenFolder_Click (object sender, EventArgs e)
{
OpenFolder();
}
private void _menuItemOpenMinecraftSaveFolder_Click (object sender, EventArgs e)
{
OpenMinecraftDirectory();
}
private void _menuItemSave_Click (object sender, EventArgs e)
{
Save();
}
private void _menuItemExit_Click (object sender, EventArgs e)
{
Close();
@ -508,7 +808,17 @@ namespace NBTExplorer
private void _menuItemPaste_Click (object sender, EventArgs e)
{
PasteNode(_nodeTree.SelectedNode);
PasteNode(_nodeTree.SelectedNode);
}
private void _menuItemFind_Click (object sender, EventArgs e)
{
SearchNode(_nodeTree.SelectedNode);
}
private void _menuItemFindNext_Click (object sender, EventArgs e)
{
SearchNextNode();
}
private void _menuItemAbout_Click (object sender, EventArgs e)
@ -520,4 +830,118 @@ namespace NBTExplorer
#endregion
}
internal class SearchState
{
public DataNode RootNode { get; set; }
public string SearchName { get; set; }
public string SearchValue { get; set; }
public IEnumerator<DataNode> State { get; set; }
public Action<DataNode> DiscoverCallback { get; set; }
public Action<DataNode> ProgressCallback { get; set; }
public Action<DataNode> CollapseCallback { get; set; }
public Action EndCallback { get; set; }
}
internal class SearchWorker
{
private ContainerControl _sender;
private SearchState _state;
private bool _cancel;
private object _lock;
public SearchWorker (SearchState state, ContainerControl sender)
{
_state = state;
_sender = sender;
_lock = new object();
}
public void Cancel ()
{
lock (_lock) {
_cancel = true;
}
}
public void Run ()
{
if (_state.State == null)
_state.State = FindNode(_state.RootNode).GetEnumerator();
if (!_state.State.MoveNext())
InvokeEndCallback();
}
private IEnumerable<DataNode> FindNode (DataNode node)
{
lock (_lock) {
if (_cancel)
yield break;
}
if (node == null)
yield break;
bool searchExpanded = false;
if (!node.IsExpanded) {
node.Expand();
searchExpanded = true;
}
TagDataNode tagNode = node as TagDataNode;
if (tagNode != null) {
bool mName = _state.SearchName == null;
bool mValue = _state.SearchValue == null;
if (_state.SearchName != null) {
string tagName = node.NodeName;
if (tagName != null)
mName = tagName.Contains(_state.SearchName);
}
if (_state.SearchValue != null) {
string tagValue = node.NodeDisplay;
if (tagValue != null)
mValue = tagValue.Contains(_state.SearchValue);
}
if (mName && mValue) {
InvokeDiscoverCallback(node);
yield return node;
}
}
foreach (DataNode sub in node.Nodes) {
foreach (DataNode s in FindNode(sub))
yield return s;
}
if (searchExpanded) {
if (!node.IsModified) {
node.Collapse();
InvokeCollapseCallback(node);
}
}
}
private void InvokeDiscoverCallback (DataNode node)
{
if (_sender != null && _state.DiscoverCallback != null)
_sender.BeginInvoke(_state.DiscoverCallback, new object[] { node });
}
private void InvokeCollapseCallback (DataNode node)
{
if (_sender != null && _state.CollapseCallback != null)
_sender.BeginInvoke(_state.CollapseCallback, new object[] { node });
}
private void InvokeEndCallback ()
{
if (_sender != null && _state.EndCallback != null)
_sender.BeginInvoke(_state.EndCallback);
}
}
}

View file

@ -75,6 +75,20 @@ namespace NBTExplorer.Model
Nodes.Clear();
}
public void Save ()
{
foreach (DataNode node in Nodes)
if (node.IsModified)
node.Save();
SaveCore();
IsModified = false;
}
protected virtual void SaveCore ()
{
}
public virtual string NodeName
{
get { return ""; }

View file

@ -91,6 +91,14 @@ namespace NBTExplorer.Model
Nodes.Clear();
}
protected override void SaveCore ()
{
NBTFile file = new NBTFile(_path);
using (Stream str = file.GetDataOutputStream(_compressionType)) {
_tree.WriteTo(str);
}
}
public bool IsNamedContainer
{
get { return true; }

View file

@ -1,5 +1,6 @@
using Substrate.Core;
using Substrate.Nbt;
using System.IO;
namespace NBTExplorer.Model
{
@ -63,6 +64,13 @@ namespace NBTExplorer.Model
Nodes.Clear();
}
protected override void SaveCore ()
{
using (Stream str = _regionFile.GetChunkDataOutputStream(_x, _z)) {
_tree.WriteTo(str);
}
}
public bool IsNamedContainer
{
get { return true; }

View file

@ -304,10 +304,20 @@ namespace NBTExplorer.Model
: base(tag)
{ }
protected new TagNodeByte Tag
{
get { return base.Tag as TagNodeByte; }
}
public override bool EditNode ()
{
return EditScalarValue(Tag);
}
public override string NodeDisplay
{
get { return NodeDisplayPrefix + unchecked((sbyte)Tag.Data).ToString(); }
}
}
public class TagShortDataNode : TagDataNode

View file

@ -48,6 +48,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Forms\CancelSearchForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\CancelSearchForm.Designer.cs">
<DependentUpon>CancelSearchForm.cs</DependentUpon>
</Compile>
<Compile Include="IconRegistry.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
@ -141,6 +147,9 @@
<Compile Include="Vendor\Be.Windows.Forms.HexBox\MemoryDataBlock.cs" />
<Compile Include="Vendor\Be.Windows.Forms.HexBox\NativeMethods.cs" />
<Compile Include="Vendor\Be.Windows.Forms.HexBox\Util.cs" />
<EmbeddedResource Include="Forms\CancelSearchForm.resx">
<DependentUpon>CancelSearchForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>

63
forms/CancelSearchForm.Designer.cs generated Normal file
View file

@ -0,0 +1,63 @@
namespace NBTExplorer.Forms
{
partial class CancelSearchForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
this._buttonCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// _buttonCancel
//
this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this._buttonCancel.Location = new System.Drawing.Point(124, 57);
this._buttonCancel.Name = "_buttonCancel";
this._buttonCancel.Size = new System.Drawing.Size(75, 23);
this._buttonCancel.TabIndex = 0;
this._buttonCancel.Text = "Cancel";
this._buttonCancel.UseVisualStyleBackColor = true;
//
// CancelSearchForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this._buttonCancel;
this.ClientSize = new System.Drawing.Size(322, 92);
this.Controls.Add(this._buttonCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CancelSearchForm";
this.Text = "Searching...";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button _buttonCancel;
}
}

19
forms/CancelSearchForm.cs Normal file
View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NBTExplorer.Forms
{
public partial class CancelSearchForm : Form
{
public CancelSearchForm ()
{
InitializeComponent();
}
}
}

120
forms/CancelSearchForm.resx Normal file
View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -50,7 +50,7 @@ namespace NBTExplorer
try {
switch (_tag.GetTagType()) {
case TagType.TAG_BYTE:
_tag.ToTagByte().Data = byte.Parse(textBox1.Text);
_tag.ToTagByte().Data = unchecked((byte)sbyte.Parse(textBox1.Text));
break;
case TagType.TAG_SHORT: