view Form1.cs @ 0:8439bec53421

Initial commit under the GPLv3
author IBBoard <dev@ibboard.co.uk>
date Sat, 06 Oct 2018 20:00:56 +0100
parents
children
line wrap: on
line source

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using IBBoard;
using IBBoard.Relic.RelicTools;
using IBBoard.Relic.RelicTools.Exceptions;
using System.Threading;
using System.IO;

namespace IBBoard.Relic.IChunkyViewer
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.MainMenu mainMenu;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem miFile_Open;
		private System.Windows.Forms.OpenFileDialog openFileDialog;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.TreeView treeView;
		private System.Windows.Forms.TextBox txtDetails;
		private System.Windows.Forms.ImageList imageList;
		private System.Windows.Forms.ContextMenu contextMenu;
		private System.Windows.Forms.MenuItem miSaveChunk;
		private System.Windows.Forms.SaveFileDialog saveFileDialog;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem4;

		private RelicChunkyFile chunkyFile;
		private string chunkyFilePath = "";
		private string chunkyFileNewPath = "";
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog;
		private System.Windows.Forms.StatusBar statusBar;
		private System.Windows.Forms.Timer timer;

		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.MenuItem menuItem8;
		private System.Windows.Forms.MenuItem miExportChunk;
		private System.Windows.Forms.MenuItem miImportChunk;
		private System.Windows.Forms.SaveFileDialog exportFileDialog;
		private System.Windows.Forms.OpenFileDialog importFileDialog;
		private System.Windows.Forms.MenuItem miImportSiblingChunk;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem miSave;
		private System.Windows.Forms.MenuItem menuItem11;
		private System.Windows.Forms.MenuItem menuItem10;
		private System.Windows.Forms.MenuItem miDeleteChunk;
		private System.Windows.Forms.MenuItem miOptions;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem miShowValidationString;
		private System.Windows.Forms.MenuItem menuItem16;
		private System.Windows.Forms.MenuItem miRefreshValidations;

		private ChunkyValidator[] chunkyValidators;
		private System.Windows.Forms.MenuItem miValidateAs;
		private System.Windows.Forms.MenuItem miNoValidators;
		private Preferences preferences;

		private Progress progress = null;

		private Form1()
		{			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			preferences = new Preferences("IChunkyViewer");

			openFileDialog.InitialDirectory = preferences["DoWPath"].ToString();
        }

		public Form1(string path): this()
		{
			if (path!=null && path.Trim()!="")
			{
				chunkyFileNewPath = path;
				Thread thr = new Thread(new ThreadStart(openChunkyFile));
				thr.Start();
			}
		}

		private void Form1_Load(object sender, System.EventArgs e)
		{
			readInValidators();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (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.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
			this.treeView = new System.Windows.Forms.TreeView();
			this.contextMenu = new System.Windows.Forms.ContextMenu();
			this.miSaveChunk = new System.Windows.Forms.MenuItem();
			this.miExportChunk = new System.Windows.Forms.MenuItem();
			this.menuItem8 = new System.Windows.Forms.MenuItem();
			this.miImportChunk = new System.Windows.Forms.MenuItem();
			this.miImportSiblingChunk = new System.Windows.Forms.MenuItem();
			this.menuItem10 = new System.Windows.Forms.MenuItem();
			this.miDeleteChunk = new System.Windows.Forms.MenuItem();
			this.imageList = new System.Windows.Forms.ImageList(this.components);
			this.mainMenu = new System.Windows.Forms.MainMenu();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.miFile_Open = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.miSave = new System.Windows.Forms.MenuItem();
			this.menuItem11 = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem6 = new System.Windows.Forms.MenuItem();
			this.miOptions = new System.Windows.Forms.MenuItem();
			this.menuItem7 = new System.Windows.Forms.MenuItem();
			this.miShowValidationString = new System.Windows.Forms.MenuItem();
			this.miValidateAs = new System.Windows.Forms.MenuItem();
			this.miNoValidators = new System.Windows.Forms.MenuItem();
			this.menuItem16 = new System.Windows.Forms.MenuItem();
			this.miRefreshValidations = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.txtDetails = new System.Windows.Forms.TextBox();
			this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
			this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
			this.statusBar = new System.Windows.Forms.StatusBar();
			this.timer = new System.Windows.Forms.Timer(this.components);
			this.exportFileDialog = new System.Windows.Forms.SaveFileDialog();
			this.importFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.SuspendLayout();
			// 
			// treeView
			// 
			this.treeView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left)));
			this.treeView.ContextMenu = this.contextMenu;
			this.treeView.ImageList = this.imageList;
			this.treeView.Location = new System.Drawing.Point(0, 0);
			this.treeView.Name = "treeView";
			this.treeView.SelectedImageIndex = 1;
			this.treeView.Size = new System.Drawing.Size(344, 520);
			this.treeView.TabIndex = 0;
			this.treeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeView_MouseDown);
			this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
			// 
			// contextMenu
			// 
			this.contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						this.miSaveChunk,
																						this.miExportChunk,
																						this.menuItem8,
																						this.miImportChunk,
																						this.miImportSiblingChunk,
																						this.menuItem10,
																						this.miDeleteChunk});
			this.contextMenu.Popup += new System.EventHandler(this.contextMenu_Popup);
			// 
			// miSaveChunk
			// 
			this.miSaveChunk.Index = 0;
			this.miSaveChunk.Text = "&Save chunk to location";
			this.miSaveChunk.Click += new System.EventHandler(this.miSaveChunk_Click);
			// 
			// miExportChunk
			// 
			this.miExportChunk.Index = 1;
			this.miExportChunk.Text = "&Export chunk";
			this.miExportChunk.Click += new System.EventHandler(this.miExportChunk_Click);
			// 
			// menuItem8
			// 
			this.menuItem8.Index = 2;
			this.menuItem8.Text = "-";
			// 
			// miImportChunk
			// 
			this.miImportChunk.Index = 3;
			this.miImportChunk.Text = "&Import child chunk";
			this.miImportChunk.Click += new System.EventHandler(this.miImportChunk_Click);
			// 
			// miImportSiblingChunk
			// 
			this.miImportSiblingChunk.Index = 4;
			this.miImportSiblingChunk.Text = "I&mport sibling chunk";
			this.miImportSiblingChunk.Click += new System.EventHandler(this.miImportSiblingChunk_Click);
			// 
			// menuItem10
			// 
			this.menuItem10.Index = 5;
			this.menuItem10.Text = "-";
			// 
			// miDeleteChunk
			// 
			this.miDeleteChunk.Index = 6;
			this.miDeleteChunk.Text = "&Delete chunk";
			this.miDeleteChunk.Click += new System.EventHandler(this.miDeleteChunk_Click);
			// 
			// imageList
			// 
			this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
			this.imageList.ImageSize = new System.Drawing.Size(16, 16);
			this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
			this.imageList.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// mainMenu
			// 
			this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					 this.menuItem1,
																					 this.menuItem6,
																					 this.menuItem7,
																					 this.menuItem2});
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 0;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.miFile_Open,
																					  this.menuItem5,
																					  this.menuItem9,
																					  this.miSave,
																					  this.menuItem11,
																					  this.menuItem4});
			this.menuItem1.Text = "&File";
			// 
			// miFile_Open
			// 
			this.miFile_Open.Index = 0;
			this.miFile_Open.Text = "&Open";
			this.miFile_Open.Click += new System.EventHandler(this.miFile_Open_Click);
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 1;
			this.menuItem5.Text = "O&pen in new window";
			this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 2;
			this.menuItem9.Text = "-";
			// 
			// miSave
			// 
			this.miSave.Enabled = false;
			this.miSave.Index = 3;
			this.miSave.Text = "&Save";
			this.miSave.Click += new System.EventHandler(this.miSave_Click);
			// 
			// menuItem11
			// 
			this.menuItem11.Index = 4;
			this.menuItem11.Text = "-";
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 5;
			this.menuItem4.Text = "&Exit";
			this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
			// 
			// menuItem6
			// 
			this.menuItem6.Index = 1;
			this.menuItem6.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.miOptions});
			this.menuItem6.Text = "&Edit";
			// 
			// miOptions
			// 
			this.miOptions.Index = 0;
			this.miOptions.Text = "&Options";
			this.miOptions.Click += new System.EventHandler(this.miOptions_Click);
			// 
			// menuItem7
			// 
			this.menuItem7.Index = 2;
			this.menuItem7.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.miShowValidationString,
																					  this.miValidateAs});
			this.menuItem7.Text = "&Tools";
			// 
			// miShowValidationString
			// 
			this.miShowValidationString.Enabled = false;
			this.miShowValidationString.Index = 0;
			this.miShowValidationString.Text = "Vali&dation string";
			this.miShowValidationString.Click += new System.EventHandler(this.miShowValidationString_Click);
			// 
			// miValidateAs
			// 
			this.miValidateAs.Enabled = false;
			this.miValidateAs.Index = 1;
			this.miValidateAs.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.miNoValidators,
																						 this.menuItem16,
																						 this.miRefreshValidations});
			this.miValidateAs.Text = "&Validate as...";
			// 
			// miNoValidators
			// 
			this.miNoValidators.Enabled = false;
			this.miNoValidators.Index = 0;
			this.miNoValidators.Text = "No validators";
			// 
			// menuItem16
			// 
			this.menuItem16.Index = 1;
			this.menuItem16.Text = "-";
			// 
			// miRefreshValidations
			// 
			this.miRefreshValidations.Index = 2;
			this.miRefreshValidations.Text = "Refresh list";
			this.miRefreshValidations.Click += new System.EventHandler(this.miRefreshValidations_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 3;
			this.menuItem2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem3});
			this.menuItem2.Text = "&Help";
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 0;
			this.menuItem3.Text = "&About";
			this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
			// 
			// txtDetails
			// 
			this.txtDetails.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.txtDetails.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.txtDetails.Location = new System.Drawing.Point(344, 0);
			this.txtDetails.Multiline = true;
			this.txtDetails.Name = "txtDetails";
			this.txtDetails.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
			this.txtDetails.Size = new System.Drawing.Size(392, 520);
			this.txtDetails.TabIndex = 1;
			this.txtDetails.Text = "";
			// 
			// statusBar
			// 
			this.statusBar.Location = new System.Drawing.Point(0, 519);
			this.statusBar.Name = "statusBar";
			this.statusBar.Size = new System.Drawing.Size(736, 22);
			this.statusBar.TabIndex = 2;
			// 
			// timer
			// 
			this.timer.Interval = 2000;
			this.timer.Tick += new System.EventHandler(this.timer_Tick);
			// 
			// exportFileDialog
			// 
			this.exportFileDialog.DefaultExt = "chunk";
			this.exportFileDialog.Filter = "Relic Chunky Chunks (*.chunk)|*.chunk";
			// 
			// importFileDialog
			// 
			this.importFileDialog.Filter = "Relic Chunky Chunks (*.chunk)|*.chunk";
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(736, 541);
			this.Controls.Add(this.statusBar);
			this.Controls.Add(this.txtDetails);
			this.Controls.Add(this.treeView);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Menu = this.mainMenu;
			this.Name = "Form1";
			this.Text = "IChunky Viewer";
			this.Load += new System.EventHandler(this.Form1_Load);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args) 
		{
			if (args.Length==0)
			{
				Application.EnableVisualStyles();
				Application.DoEvents();
				Application.Run(new Form1(""));
			}
			else if (args.Length==1 && File.Exists(args[0]))
			{
				Application.EnableVisualStyles();
				Application.DoEvents();
				Application.Run(new Form1(args[0]));
			}
			else
			{
				MessageBox.Show(null, "The file path specified was invalid. Please try again with a correct path.", "Invalid path", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private delegate void NoParamDelegate();
		private delegate int TreeNodeAddDelegate(TreeNode node);
		private delegate void TreeNodeAddRangeDelegate(TreeNode[] nodes);

		private void openChunkyFile()
		{		
			if (chunkyFileNewPath=="")
			{
				return;
			}

			Thread progressThread = null;

			//if (new FileInfo(chunkyFileNewPath).Length>102400)
			//{
			//	progressThread = new Thread(new ThreadStart(showProgress));
			//	progressThread.Start();
			//}

			Thread.Sleep(100);

			try{
				RelicChunkyFile newChunkyFile = RelicChunkyReader.ReadChunkyFile(chunkyFileNewPath);
				chunkyFile = newChunkyFile; // make sure we don't trash the old value if it fails
			}
			catch(InvalidFileException)
			{
				if (OnChunkyOpenFailed!=null)
				{
					OnChunkyOpenFailed();
				}

				MessageBox.Show(this, "The file '"+chunkyFileNewPath+"' was not a valid Relic Chunky file", "Invalid Chunky File", MessageBoxButtons.OK, MessageBoxIcon.Error);
				
				if (!(progressThread.ThreadState==ThreadState.Aborted || progressThread.ThreadState==ThreadState.AbortRequested
					|| progressThread.ThreadState==ThreadState.Stopped || progressThread.ThreadState==ThreadState.StopRequested))
				{
					try
					{
						progressThread.Abort();
					}
					catch{}
				}

				return;
			}
			catch(InvalidChunkException)
			{
				if (OnChunkyOpenFailed!=null)
				{
					OnChunkyOpenFailed();
				}

				MessageBox.Show(this, "The file '"+chunkyFileNewPath+"' was not a valid Relic Chunky file", "Invalid Chunky Chunk in file", MessageBoxButtons.OK, MessageBoxIcon.Error);
				
				if (!(progressThread.ThreadState==ThreadState.Aborted || progressThread.ThreadState==ThreadState.AbortRequested
					|| progressThread.ThreadState==ThreadState.Stopped || progressThread.ThreadState==ThreadState.StopRequested))
				{
					try
					{
						progressThread.Abort();
					}
					catch{}
				}

				return;
			}

			chunkyFilePath = chunkyFileNewPath;
			chunkyFileNewPath = "";

			if (OnChunkyOpened!=null)
			{
				OnChunkyOpened(chunkyFilePath);
			}

			treeView.Invoke(new NoParamDelegate(treeView.Nodes.Clear));
			txtDetails.Invoke(new NoParamDelegate(txtDetails.Clear));

			foreach (RelicChunkyStructure strct in chunkyFile.ChunkyStructures)
			{
				int count = strct.RootChunks.Count;
				TreeNode node = null;
				ChunkyFolder fold;
				TreeNode[] nodes = new TreeNode[count];

				int children = strct.RootChunks.Count;

				for(int i = 0; i<count; i++)
				{
					if (strct.RootChunks[i] is ChunkyData)
					{
						children+=1;
					}
					else if (strct.RootChunks[i] is ChunkyFolder)
					{
						children += ((ChunkyFolder)strct.RootChunks[i]).Children.Count;
					}
				}

				if (OnChunkyNodesCounted!=null)
				{
					OnChunkyNodesCounted(children);
				}

				for(int i = 0; i<count; i++)
				{
					node = new TreeNode();
					setNodeName(node, strct.RootChunks[i]);
					node.Tag = strct.RootChunks[i];

					if (strct.RootChunks[i] is ChunkyFolder)
					{
						fold = (ChunkyFolder)strct.RootChunks[i];

						foreach(ChunkyChunk chunk in fold.Children)
						{
							addTreeNode(chunk, node);
						}
					}
					else
					{
						node.ImageIndex = 2;
						node.SelectedImageIndex = 2;
					}

					nodes[i] = node;

					if (OnChunkyNodeAdded!=null)
					{
						OnChunkyNodeAdded(strct.RootChunks[i]);
					}
				}

				if (OnChunkyNodesAdded!=null)
				{
					OnChunkyNodesAdded(false);
				}

				treeView.Invoke(new TreeNodeAddRangeDelegate(treeView.Nodes.AddRange), new object[]{nodes});
			
				if (OnChunkyNodesAdded!=null)
				{
					OnChunkyNodesAdded(true);
				}
			}

			this.Invoke(new SetStringDelegate(SetTitle), new object[]{"IChunky Viewer - "+chunkyFile.Name});

			System.Console.Write(chunkyFilePath.Substring(0, chunkyFilePath.LastIndexOf(Constants.DirectoryChar)));
			folderBrowserDialog.SelectedPath = chunkyFilePath.Substring(0, chunkyFilePath.LastIndexOf(Constants.DirectoryChar));
			openFileDialog.InitialDirectory = chunkyFilePath.Substring(0, chunkyFilePath.LastIndexOf(Constants.DirectoryChar));
			miSave.Enabled = true;
			miShowValidationString.Enabled = true;
			miValidateAs.Enabled = true;
		}

        private delegate void SetStringDelegate(string val);

        private void SetTitle(string title)
        {
            this.Text = title;
        }

		private void addTreeNode(ChunkyChunk chunk, TreeNode parent)
		{
			if (chunk is ChunkyData)
			{
				addTreeNode((ChunkyData)chunk, parent);
			}
			else
			{
				addTreeNode((ChunkyFolder)chunk, parent);
			}
		}

		private void addTreeNode(ChunkyData chunk, TreeNode parent)
		{	
			TreeNode temp = new TreeNode("", 2, 2);
			setNodeName(temp, chunk);
			temp.Tag = chunk;
			parent.Nodes.Add(temp);
			
			if (OnChunkyNodeAdded!=null)
			{
				OnChunkyNodeAdded(chunk);
			}
		}

		private void addTreeNode(ChunkyFolder fld, TreeNode parent)
		{
			TreeNode node = new TreeNode("", 0, 1);
			setNodeName(node, fld);
			node.Tag = fld;

			foreach(ChunkyChunk chunk in fld.Children)
			{
				addTreeNode(chunk, node);
			}		
	
			parent.Nodes.Add(node);
			
			if (OnChunkyNodeAdded!=null)
			{
				OnChunkyNodeAdded(fld);
			}
		}

		private void miFile_Open_Click(object sender, System.EventArgs e)
		{
			DialogResult dr = openFileDialog.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				chunkyFileNewPath = openFileDialog.FileName;
				Thread thr = new Thread(new ThreadStart(openChunkyFile));
				thr.Start();
			}
		}

		private void treeView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			txtDetails.Text = ((ChunkyChunk)e.Node.Tag).GetDisplayDetails();
		}

		private void miSaveChunk_Click(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null)
			{
				DialogResult dr = folderBrowserDialog.ShowDialog();

				if (dr == DialogResult.OK)
				{
					statusBar.Text = "Saving chunk...";

					if(treeView.SelectedNode.Tag is ChunkyData)
					{
						if (((ChunkyData)treeView.SelectedNode.Tag).Save(folderBrowserDialog.SelectedPath))
						{
							statusBar.Text+= "Saved";
							timer.Enabled = true;
						}
					}
					else
					{
						int saves = ((ChunkyFolder)treeView.SelectedNode.Tag).Save(folderBrowserDialog.SelectedPath);

						if (saves != 1)
						{
							statusBar.Text+= saves+" items saved";
						}
						else
						{
							statusBar.Text+= "1 item saved";
						}

						timer.Enabled = true;
					}
				}
			}
		}

		private void treeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Right)
			{
				TreeNode tn = treeView.GetNodeAt(e.X, e.Y);

				if (tn!=null)
				{
					treeView.SelectedNode = tn;
				}
				else
				{
					treeView.SelectedNode = null;
				}
			}
		}

		private void contextMenu_Popup(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null)
			{
				foreach(MenuItem item in contextMenu.MenuItems)
				{
					item.Visible = true;
				}

				ChunkyChunk chunk = ((ChunkyChunk)treeView.SelectedNode.Tag);
				miSaveChunk.Enabled = chunk.Savable;

				miDeleteChunk.Enabled = (treeView.SelectedNode!=treeView.Nodes[0] || treeView.Nodes.Count>1);
			}
			else
			{
				foreach(MenuItem item in contextMenu.MenuItems)
				{
					item.Visible = false;
				}
			}		
		}

		private void menuItem3_Click(object sender, System.EventArgs e)
		{			
			AboutChunkyViewer frm = new AboutChunkyViewer();
			frm.ShowDialog(this);
			frm.Dispose();
		}

		private void menuItem4_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}

		private void showProgress()
		{
			try
			{
				progress = new Progress(this);
				progress.ShowDialog(this);
			}
			catch{}
		}

		private void menuItem5_Click(object sender, System.EventArgs e)
		{
			DialogResult dr = openFileDialog.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				System.Diagnostics.Process proc = new System.Diagnostics.Process();
				proc.EnableRaisingEvents = false;
				proc.StartInfo.FileName = Application.ExecutablePath;
				proc.StartInfo.Arguments = "\""+openFileDialog.FileName+"\"";
				proc.Start(); 
			}		
		}

		private void timer_Tick(object sender, System.EventArgs e)
		{
			statusBar.Text = "";
			timer.Enabled = false;
		}

		private void miExportChunk_Click(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null)
			{
				DialogResult dr = exportFileDialog.ShowDialog(this);

				if (dr == DialogResult.OK)
				{
					statusBar.Text = "Exporting...";
					if (((ChunkyChunk)treeView.SelectedNode.Tag).Export(exportFileDialog.FileName))
					{
						statusBar.Text+= "Exported";
						timer.Enabled = true;
					}
					else
					{
						statusBar.Text = "Export failed";
					}
				}
			}
		}

		private void miImportChunk_Click(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null && treeView.SelectedNode.Tag is ChunkyFolder)
			{
				DialogResult dr = importFileDialog.ShowDialog(this);

				if (dr == DialogResult.OK)
				{
					FileStream str = new FileStream(importFileDialog.FileName, FileMode.Open);
					byte[] bytes = new byte[str.Length];
					str.Read(bytes, 0, (int)str.Length);
					str.Close();
					ChunkyChunk chunk = RelicChunkReader.ReadChunkyChunk(bytes);
					ChunkyFolder folder = (ChunkyFolder)treeView.SelectedNode.Tag;
					folder.Children.Add(chunk);
					addTreeNode(chunk, treeView.SelectedNode);
					cascadeRefreshUp(treeView.SelectedNode);
					txtDetails.Text = ((ChunkyChunk)treeView.SelectedNode.Tag).GetDisplayDetails();
				}
			}		
		}

		private void cascadeRefreshUp(TreeNode node)
		{
			setNodeName(node, (ChunkyChunk)node.Tag);

			if (node.Parent!=null)
			{
				cascadeRefreshUp(node.Parent);
			}
		}

		private void cascadeRefreshDown(TreeNode node)
		{
			setNodeName(node, (ChunkyChunk)node.Tag);

			foreach (TreeNode childNode in node.Nodes)
			{
				cascadeRefreshDown(childNode);
			}
		}

		private void setNodeName(TreeNode node, ChunkyChunk chunk)
		{
            int showSizes = (int)preferences["ShowChunkSizes"]; 

			if (showSizes == 1)
			{
				node.Text = chunk.ID+" ("+chunk.DataLength+")";
			}
			else if (showSizes == 2)
			{
				node.Text = chunk.ID+" ("+chunk.Length+")";
			}
			else
			{
				node.Text = chunk.ID;
			}
		}

		private void miImportSiblingChunk_Click(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null)
			{
				DialogResult dr = importFileDialog.ShowDialog(this);

				if (dr == DialogResult.OK)
				{
					FileStream str = new FileStream(importFileDialog.FileName, FileMode.Open);
					byte[] bytes = new byte[str.Length];
					str.Read(bytes, 0, (int)str.Length);
					str.Close();
					ChunkyChunk chunk = RelicChunkReader.ReadChunkyChunk(bytes);

					if (treeView.SelectedNode.Parent!=null)
					{
						ChunkyFolder folder = (ChunkyFolder)((ChunkyChunk)treeView.SelectedNode.Tag).Parent;
						folder.Children.Add(chunk);
						addTreeNode(chunk, treeView.SelectedNode.Parent);
						cascadeRefreshUp(treeView.SelectedNode.Parent);
					}
					else
					{
						RelicChunkyFile file = ((ChunkyChunk)treeView.SelectedNode.Tag).ParentFile;
						file.ChunkyStructures[0].RootChunks.Add(chunk);
						TreeNode node = new TreeNode();
						setNodeName(node, chunk);
						node.Tag = chunk;

						if (chunk is ChunkyFolder)
						{
							ChunkyFolder fold = (ChunkyFolder)chunk;

							foreach(ChunkyChunk childChunk in fold.Children)
							{
								addTreeNode(childChunk, node);
							}
						}
						else
						{
							node.ImageIndex = 2;
							node.SelectedImageIndex = 2;
						}

						treeView.Nodes.Add(node);

						if (OnChunkyNodeAdded!=null)
						{
							OnChunkyNodeAdded(chunk);
						}
					}
				}
			}			
		}

		private void miSave_Click(object sender, System.EventArgs e)
		{
			if (chunkyFile!=null)
			{
				statusBar.Text = "Saving...";
				chunkyFile.Save(new DirectoryInfo(chunkyFilePath.Substring(0, chunkyFilePath.LastIndexOf(Constants.DirectoryChar))));
				statusBar.Text+= "Saved";
				timer.Enabled = true;
			}
		}

		private void miDeleteChunk_Click(object sender, System.EventArgs e)
		{
			if (treeView.SelectedNode!=null)
			{
				TreeNode node = treeView.SelectedNode;
				ChunkyChunk chunk = (ChunkyChunk)node.Tag;
				
				if (chunk.Parent!=null)
				{
					chunk.Parent.Children.Remove(chunk);
					TreeNode parent = node.Parent;
					node.Parent.Nodes.Remove(node);
					cascadeRefreshUp(parent);
				}
				else
				{
					chunk.ParentFile.ChunkyStructures[0].RootChunks.Remove(chunk);
					treeView.Nodes.Remove(node);
				}
			}
		}

		private void miOptions_Click(object sender, System.EventArgs e)
		{
			FrmConfig frm = new FrmConfig(preferences);
			DialogResult dr = frm.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				foreach (TreeNode node in treeView.Nodes)
				{
					cascadeRefreshDown(node);
				}
			}
		}

		private void miShowValidationString_Click(object sender, System.EventArgs e)
		{
			if (chunkyFile!=null)
			{
				FrmValidationString val = new FrmValidationString(chunkyFile);
				val.ShowDialog(this);
			}
		}

		private void readInValidators()
		{
			statusBar.Text = "Reading validators...";
            DirectoryInfo dir = new DirectoryInfo(preferences["DoWPath"].ToString() + Constants.DirectoryString + "IChunkyValidators");

			miValidateAs.MenuItems.Clear();

			if (dir.Exists)
			{
				FileInfo[] validators = dir.GetFiles("*.validator");

				if (validators.Length>0)
				{
					//chunkyValidators = new ChunkyValidator[validators.Length];
					//MenuItem[] items = new MenuItem[validators.Length];
					ArrayList chunkyValidatorsTemp = new ArrayList();
					ArrayList menuitems = new ArrayList();
					EventHandler handler = new EventHandler(miValidate_Click);
					ChunkyValidator validator;

					for (int i = 0; i<validators.Length; i++)
					{
						try
						{
							validator = new ChunkyValidator(validators[i]);
							chunkyValidatorsTemp.Add(validator);
							menuitems.Add(new MenuItem(validator.FileType, handler));
						}
						catch (InvalidOperationException){}//invalid validator file
					}
					
					chunkyValidators = (ChunkyValidator[])chunkyValidatorsTemp.ToArray(typeof(ChunkyValidator));
					miValidateAs.MenuItems.AddRange((MenuItem[])menuitems.ToArray(typeof(MenuItem)));
					miValidateAs.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {this.menuItem16,
																							this.miRefreshValidations});
					
					statusBar.Text = "Refreshed";
					timer.Enabled = true;
				}
				else
				{
					statusBar.Text = "No validators found";
					timer.Enabled = true;
					miValidateAs.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {this.miNoValidators,
																							this.menuItem16,
																							this.miRefreshValidations});
				}
			}
			else
			{
				statusBar.Text = "ERROR: Could not find validators";
				timer.Enabled = true;
				MessageBox.Show(this, "IChunkyViewer could not find a folder of Chunky file validators at "+dir.FullName, "Could not find validators", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				
				miValidateAs.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {this.miNoValidators,
																						this.menuItem16,
																						this.miRefreshValidations});
			}
		}

		private void miValidate_Click(object sender, System.EventArgs e)
		{
			if (sender is MenuItem && chunkyFile!=null)
			{
				ChunkyValidator validator = chunkyValidators[((MenuItem)sender).Index];
				if (validator.Validate(chunkyFile.GetValidationString()))
				{
					MessageBox.Show(this, chunkyFile.Name+" is a valid "+validator.FileType+" file", "Validation successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
				else
				{
					MessageBox.Show(this, chunkyFile.Name+" is not a valid "+validator.FileType+" file", "Validation failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				}
			}
		}

		private void miRefreshValidations_Click(object sender, System.EventArgs e)
		{
			readInValidators();
		}

		public delegate void ChunkyOpenedDelegate(string path);
		public event ChunkyOpenedDelegate OnChunkyOpened;
		public delegate void ChunkyNodesCountedDelegate(int nodes);
		public event ChunkyNodesCountedDelegate OnChunkyNodesCounted;
		public delegate void ChunkyNodeAddedDelegate(ChunkyChunk chunk);
		public event ChunkyNodeAddedDelegate OnChunkyNodeAdded;
		public delegate void ChunkyNodesAddedDelegate(bool rendered);
		public event ChunkyNodesAddedDelegate OnChunkyNodesAdded;
		public delegate void ChunkyOpenFailedDelegate();
		public event ChunkyOpenFailedDelegate OnChunkyOpenFailed;
	}
}