changeset 159:964f946d3cac

Fixes #288: WarFoundry WinForms assumes that army tree will be open * Add a getter method that returns a new army tree if the old one was disposed or non exists * Unhook the army tree from the army changed events on dispose
author IBBoard <dev@ibboard.co.uk>
date Fri, 04 Jun 2010 19:31:02 +0000
parents 0ae6aff8c862
children cd35c56d8153
files FrmArmyTree.cs FrmMain.cs
diffstat 2 files changed, 482 insertions(+), 468 deletions(-) [+]
line wrap: on
line diff
--- a/FrmArmyTree.cs	Mon May 31 20:09:12 2010 +0000
+++ b/FrmArmyTree.cs	Fri Jun 04 19:31:02 2010 +0000
@@ -1,461 +1,462 @@
-// This file (FrmArmyTree.cs) is a part of the IBBoard.WarFoundry.GUI.WinForms project and is copyright 2009 IBBoard.
-//
-// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
-
-using System;
-using System.Drawing;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Windows.Forms;
-using IBBoard.Commands;
-using IBBoard.Lang;
-using IBBoard.Windows.Forms.I18N;
-using IBBoard.Windows.Forms;
-using IBBoard.WarFoundry.API;
-using IBBoard.WarFoundry.API.Commands;
-using IBBoard.WarFoundry.API.Objects;
-
-namespace IBBoard.WarFoundry.GUI.WinForms
-{
-	/// <summary>
-	/// Summary description for FrmArmyTree.
-	/// </summary>
-	public class FrmArmyTree : IBBoard.Windows.Forms.IBBForm
-	{
-		private System.Windows.Forms.TreeView treeView;
-		private IContainer components;
-		private Dictionary<string, TreeNode> nodes;
-		private System.Windows.Forms.ContextMenu contextMenu;
-		private IBBMenuItem miDeleteUnit;
-		private IBBMenuItem miEditUnit;
-		
-		private ObjectAddDelegate UnitAddedMethod;
-		private ObjectRemoveDelegate UnitRemovedMethod;
-		private StringValChangedDelegate UnitNameChangedMethod, ArmyNameChangedMethod, TreeNameChangedMethod;
-		private ToolBar toolBar;
-		private IBBToolBarButton bttnEdit;
-		private IBBToolBarButton bttnDelete;
-		private ImageList imageList;
-		private CommandStack commandStack;
-
-		public FrmArmyTree(CommandStack cmdStack)
-		{
-			commandStack = cmdStack;
-			InitializeComponent();
-			UnitAddedMethod = new ObjectAddDelegate(UnitAdded);
-			UnitRemovedMethod = new ObjectRemoveDelegate(UnitRemoved);
-			UnitNameChangedMethod = new StringValChangedDelegate(UpdateUnitName);
-			ArmyNameChangedMethod = new StringValChangedDelegate(UpdateArmyName);
-			TreeNameChangedMethod = new StringValChangedDelegate(FrmArmyTree_TreeNameChanged);
-			nodes = new Dictionary<string, TreeNode>();
-			this.Name = "ArmyTree";			
-			WarFoundryCore.ArmyChanged+= new ArmyChangedDelegate(FrmArmyTree_ArmyChanged);
-			TranslateForm();
-			Translation.TranslationChanged += new MethodInvoker(TranslateForm);
-		}
-
-		private void TranslateForm()
-		{
-			ControlTranslator.TranslateControl(this);
-
-			foreach (Component comp in components.Components)
-			{
-				ControlTranslator.TranslateComponent(comp);
-			}
-
-			foreach (IBBMenuItem mi in contextMenu.MenuItems)
-			{
-				ControlTranslator.TranslateComponent(mi);
-			}
-		}
-
-		/// <summary>
-		/// Clean up any resources being used.
-		/// </summary>
-		protected override void Dispose( bool disposing )
-		{
-			if( disposing )
-			{
-				if(components != null)
-				{
-					components.Dispose();
-				}
-			}
-			base.Dispose( disposing );
-			Translation.TranslationChanged -= new MethodInvoker(TranslateForm);
-		}
-
-		#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.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmArmyTree));
-			this.contextMenu = new System.Windows.Forms.ContextMenu();
-			this.miEditUnit = new IBBoard.Windows.Forms.IBBMenuItem();
-			this.miDeleteUnit = new IBBoard.Windows.Forms.IBBMenuItem();
-			this.imageList = new System.Windows.Forms.ImageList(this.components);
-			this.toolBar = new System.Windows.Forms.ToolBar();
-			this.bttnEdit = new IBBoard.Windows.Forms.IBBToolBarButton();
-			this.bttnDelete = new IBBoard.Windows.Forms.IBBToolBarButton();
-			this.treeView = new System.Windows.Forms.TreeView();
-			this.SuspendLayout();
-			// 
-			// contextMenu
-			// 
-			this.contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
-            this.miEditUnit,
-            this.miDeleteUnit});
-			this.contextMenu.Popup += new System.EventHandler(this.contextMenu_Popup);
-			// 
-			// miEdit
-			// 
-			this.miEditUnit.Index = 0;
-			this.miEditUnit.Text = "&edit unit";
-			this.miEditUnit.Click += new System.EventHandler(this.miEdit_Click);
-			this.miEditUnit.Name = "miEditUnit";
-			// 
-			// miDelete
-			// 
-			this.miDeleteUnit.Index = 1;
-			this.miDeleteUnit.Text = "&delete unit";
-			this.miDeleteUnit.Click += new System.EventHandler(this.miDelete_Click);
-			this.miDeleteUnit.Name = "miDeleteUnit";
-			// 
-			// imageList
-			// 
-			this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer) (resources.GetObject("imageList.ImageStream")));
-			this.imageList.TransparentColor = System.Drawing.Color.Transparent;
-			this.imageList.Images.SetKeyName(0, "gtk-edit.png");
-			this.imageList.Images.SetKeyName(1, "edit-delete.png");
-			// 
-			// toolBar
-			// 
-			this.toolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
-            this.bttnEdit,
-            this.bttnDelete});
-			this.toolBar.ButtonSize = new System.Drawing.Size(16, 16);
-			this.toolBar.DropDownArrows = true;
-			this.toolBar.ImageList = this.imageList;
-			this.toolBar.Location = new System.Drawing.Point(0, 0);
-			this.toolBar.Name = "toolBar";
-			this.toolBar.ShowToolTips = true;
-			this.toolBar.Size = new System.Drawing.Size(240, 28);
-			this.toolBar.TabIndex = 3;
-			this.toolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBar_ButtonClick);
-			// 
-			// bttnEdit
-			// 
-			this.bttnEdit.Enabled = false;
-			this.bttnEdit.ImageIndex = 0;
-			this.bttnEdit.Name = "bttnEdit";
-			// 
-			// bttnDelete
-			// 
-			this.bttnDelete.Enabled = false;
-			this.bttnDelete.ImageIndex = 1;
-			this.bttnDelete.Name = "bttnDelete";
-			// 
-			// treeView
-			// 
-			this.treeView.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.treeView.ContextMenu = this.contextMenu;
-			this.treeView.FullRowSelect = true;
-			this.treeView.Location = new System.Drawing.Point(0, 28);
-			this.treeView.Name = "treeView";
-			this.treeView.Size = new System.Drawing.Size(240, 250);
-			this.treeView.TabIndex = 0;
-			this.treeView.DoubleClick += new System.EventHandler(this.treeView_DoubleClick);
-			this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
-			this.treeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeView_MouseDown);
-			// 
-			// FrmArmyTree
-			// 
-			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
-			this.ClientSize = new System.Drawing.Size(240, 277);
-			this.ControlBox = false;
-			this.Controls.Add(this.toolBar);
-			this.Controls.Add(this.treeView);
-			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
-			this.MaximizeBox = false;
-			this.MinimizeBox = false;
-			this.Name = "FrmArmyTree";
-			this.Text = "FrmArmyTree";
-			this.ResumeLayout(false);
-			this.PerformLayout();
-
-		}
-		#endregion
-
-		private void ClearArmy()
-		{
-			nodes.Clear();
-			treeView.Nodes.Clear();
-		}
-
-		private void SetArmy(Army army)
-		{
-			ClearArmy();
-
-			if (army != null)
-			{
-				ArmyCategory[] cats = army.Categories;
-				TreeNode[] catNodes = new TreeNode[cats.Length];
-				Unit[] units;
-
-				for (int i = 0; i < cats.Length; i++)
-				{
-					ArmyCategory cat = cats[i];
-					units = army.GetUnits(cat);
-					cat.NameChanged += TreeNameChangedMethod;
-					cat.PointsValueChanged += NodePointsValueChanged;
-					TreeNode[] unitNodes = new TreeNode[units.Length];
-					TreeNode temp;
-
-					for (int j = 0; j < units.Length; j++)
-					{
-						unitNodes[j] = CreateTreeNode(units[j]);
-					}
-
-					temp = new TreeNode(CreateNodeName(cat), unitNodes);
-					temp.Tag = cat;
-					catNodes[i] = temp;
-					nodes[cat.ID] = temp;
-				}
-
-				TreeNode root = new TreeNode(CreateNodeName(army), catNodes);
-				root.Tag = army;
-				army.PointsValueChanged += NodePointsValueChanged;
-				nodes[army.ID] = root;
-				treeView.Nodes.Add(root);
-				root.ExpandAll();
-			}
-		}
-		
-		private string CreateNodeName(ICostedWarFoundryObject obj)
-		{
-			return Translation.GetTranslation("treeNodeText", "{0} ({1}pts)", obj.Name, obj.Points);
-		}
-
-		private void NodePointsValueChanged(WarFoundryObject obj, double oldValue, double newValue)
-		{
-			if (obj is ICostedWarFoundryObject)
-			{
-				SetNodeName(obj);
-			}
-		}
-
-		private void SetNodeName(WarFoundryObject obj)
-		{
-			TreeNode node = nodes[obj.ID];
-
-			if (node != null)
-			{
-				node.Text = CreateNodeName((ICostedWarFoundryObject)obj);
-			}
-		}
-
-		private TreeNode CreateTreeNode(Unit unit)
-		{
-			TreeNode temp = new TreeNode(CreateNodeName(unit));
-			temp.Tag = unit;
-			unit.NameChanged+= UnitNameChangedMethod;
-			unit.PointsValueChanged += NodePointsValueChanged;
-			nodes[unit.ID] = temp;
-			return temp;
-		}
-
-		public void FrmArmyTree_ArmyChanged(Army oldArmy, Army newArmy)
-		{
-			if (oldArmy != null)
-			{
-				oldArmy.UnitAdded -= UnitAddedMethod;
-				oldArmy.UnitRemoved -= UnitRemovedMethod;
-				oldArmy.PointsValueChanged -= NodePointsValueChanged;
-			}
-
-			if (newArmy != null)
-			{
-				newArmy.UnitAdded += UnitAddedMethod;
-				newArmy.UnitRemoved += UnitRemovedMethod;
-				newArmy.PointsValueChanged += NodePointsValueChanged;
-			}
-
-			SetArmy(newArmy);
-		}
-
-		private void UnitAdded(WarFoundryObject obj)
-		{
-			if (obj is Unit)
-			{
-				Unit unit = (Unit)obj;
-				ArmyCategory cat = unit.Category;
-				TreeNode parent = nodes[cat.ID];
-				TreeNode unitNode = CreateTreeNode(unit);
-				parent.Nodes.Add(unitNode);
-				parent.Expand(); //make sure it's expanded
-			}
-		}
-
-		public new FrmMain MdiParent
-		{
-			get { return (FrmMain) base.MdiParent; }
-			set { base.MdiParent = value; }
-		}
-
-		private void UnitRemoved(WarFoundryObject obj)
-		{
-			if (obj is Unit)
-			{
-				Unit unit = (Unit)obj;
-				RemoveUnitFromTree(unit);
-			}
-		}
-
-		private void RemoveUnitFromTree(Unit unit)
-		{
-			TreeNode unitNode = nodes[unit.ID];
-			unit.NameChanged-= UnitNameChangedMethod;
-
-			if (unitNode!=null)
-			{
-				unitNode.Remove();
-				nodes.Remove(unit.ID);
-			}
-		}
-
-
-		private void contextMenu_Popup(object sender, System.EventArgs e)
-		{
-			TreeNode node = treeView.SelectedNode;
-
-			if (node!=null && node.Tag is Unit)
-			{
-				foreach(MenuItem item in contextMenu.MenuItems)
-				{
-					item.Visible = true;
-				}
-			}
-			else
-			{
-				foreach(MenuItem item in contextMenu.MenuItems)
-				{
-					item.Visible = false;
-				}
-			}
-		}
-
-		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 miDelete_Click(object sender, System.EventArgs e)
-		{
-			DeleteUnit();
-		}
-
-		private void DeleteUnit()
-		{
-
-			TreeNode selected = treeView.SelectedNode;
-
-			if (selected.Tag != null && selected.Tag is Unit)
-			{
-				Unit unit = (Unit) selected.Tag;
-				commandStack.Execute(new RemoveUnitCommand(unit));
-			}
-		}
-
-		private void miEdit_Click(object sender, System.EventArgs e)
-		{	
-			EditUnit();
-		}
-
-		private void treeView_DoubleClick(object sender, System.EventArgs e)
-		{
-			EditUnit();			
-		}
-
-		private void EditUnit()
-		{
-			TreeNode selected = treeView.SelectedNode;
-			object tagData = selected.Tag;
-
-			if (tagData is Unit)
-			{
-				Unit unit = (Unit) tagData;
-				MdiParent.OpenUnitDialog(unit);
-			}
-		}
-
-		private void UpdateUnitName(WarFoundryObject obj, string oldValue, string newValue)
-		{
-			if (obj is ICostedWarFoundryObject)
-			{
-				SetNodeName(obj);
-			}
-		}
-
-		private void UpdateArmyName(WarFoundryObject obj, string oldValue, string newValue)
-		{
-			if (obj is Army)
-			{
-				Army army = (Army)obj;
-				TreeNode node = treeView.Nodes[0];
-				
-				if (node!=null)
-				{
-					node.Text = army.Name;
-				}
-			}
-		}
-
-		private void FrmArmyTree_TreeNameChanged(WarFoundryObject obj, string oldValue, string newValue)
-		{
-			TreeNode node = nodes[obj.ID];
-
-			if (node!=null)
-			{
-				node.Text = obj.Name;
-			}
-		}
-
-		private void toolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
-		{
-			if (e.Button == bttnDelete)
-			{
-				DeleteUnit();
-			}
-			else if (e.Button == bttnEdit)
-			{
-				EditUnit();
-			}
-		}
-
-		private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
-		{
-			TreeNode node = treeView.SelectedNode;
-
-			bttnDelete.Enabled = (node != null && node.Tag is Unit);
-			bttnEdit.Enabled = bttnDelete.Enabled;
-		}
-	}
-}
+// This file (FrmArmyTree.cs) is a part of the IBBoard.WarFoundry.GUI.WinForms project and is copyright 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Forms;
+using IBBoard.Commands;
+using IBBoard.Lang;
+using IBBoard.Windows.Forms.I18N;
+using IBBoard.Windows.Forms;
+using IBBoard.WarFoundry.API;
+using IBBoard.WarFoundry.API.Commands;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.GUI.WinForms
+{
+	/// <summary>
+	/// Summary description for FrmArmyTree.
+	/// </summary>
+	public class FrmArmyTree : IBBoard.Windows.Forms.IBBForm
+	{
+		private System.Windows.Forms.TreeView treeView;
+		private IContainer components;
+		private Dictionary<string, TreeNode> nodes;
+		private System.Windows.Forms.ContextMenu contextMenu;
+		private IBBMenuItem miDeleteUnit;
+		private IBBMenuItem miEditUnit;
+		
+		private ObjectAddDelegate UnitAddedMethod;
+		private ObjectRemoveDelegate UnitRemovedMethod;
+		private StringValChangedDelegate UnitNameChangedMethod, ArmyNameChangedMethod, TreeNameChangedMethod;
+		private ToolBar toolBar;
+		private IBBToolBarButton bttnEdit;
+		private IBBToolBarButton bttnDelete;
+		private ImageList imageList;
+		private CommandStack commandStack;
+
+		public FrmArmyTree(CommandStack cmdStack)
+		{
+			commandStack = cmdStack;
+			InitializeComponent();
+			UnitAddedMethod = new ObjectAddDelegate(UnitAdded);
+			UnitRemovedMethod = new ObjectRemoveDelegate(UnitRemoved);
+			UnitNameChangedMethod = new StringValChangedDelegate(UpdateUnitName);
+			ArmyNameChangedMethod = new StringValChangedDelegate(UpdateArmyName);
+			TreeNameChangedMethod = new StringValChangedDelegate(FrmArmyTree_TreeNameChanged);
+			nodes = new Dictionary<string, TreeNode>();
+			this.Name = "ArmyTree";			
+			WarFoundryCore.ArmyChanged+= new ArmyChangedDelegate(FrmArmyTree_ArmyChanged);
+			TranslateForm();
+			Translation.TranslationChanged += new MethodInvoker(TranslateForm);
+		}
+
+		private void TranslateForm()
+		{
+			ControlTranslator.TranslateControl(this);
+
+			foreach (Component comp in components.Components)
+			{
+				ControlTranslator.TranslateComponent(comp);
+			}
+
+			foreach (IBBMenuItem mi in contextMenu.MenuItems)
+			{
+				ControlTranslator.TranslateComponent(mi);
+			}
+		}
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		protected override void Dispose( bool disposing )
+		{
+			if( disposing )
+			{
+				if(components != null)
+				{
+					components.Dispose();
+				}
+			}
+			base.Dispose( disposing );
+			Translation.TranslationChanged -= new MethodInvoker(TranslateForm);
+			WarFoundryCore.ArmyChanged -= new ArmyChangedDelegate(FrmArmyTree_ArmyChanged);
+		}
+
+		#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.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmArmyTree));
+			this.contextMenu = new System.Windows.Forms.ContextMenu();
+			this.miEditUnit = new IBBoard.Windows.Forms.IBBMenuItem();
+			this.miDeleteUnit = new IBBoard.Windows.Forms.IBBMenuItem();
+			this.imageList = new System.Windows.Forms.ImageList(this.components);
+			this.toolBar = new System.Windows.Forms.ToolBar();
+			this.bttnEdit = new IBBoard.Windows.Forms.IBBToolBarButton();
+			this.bttnDelete = new IBBoard.Windows.Forms.IBBToolBarButton();
+			this.treeView = new System.Windows.Forms.TreeView();
+			this.SuspendLayout();
+			// 
+			// contextMenu
+			// 
+			this.contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+            this.miEditUnit,
+            this.miDeleteUnit});
+			this.contextMenu.Popup += new System.EventHandler(this.contextMenu_Popup);
+			// 
+			// miEditUnit
+			// 
+			this.miEditUnit.Index = 0;
+			this.miEditUnit.Text = "&edit unit";
+			this.miEditUnit.Click += new System.EventHandler(this.miEdit_Click);
+			this.miEditUnit.Name = "miEditUnit";
+			// 
+			// miDeleteUnit
+			// 
+			this.miDeleteUnit.Index = 1;
+			this.miDeleteUnit.Text = "&delete unit";
+			this.miDeleteUnit.Click += new System.EventHandler(this.miDelete_Click);
+			this.miDeleteUnit.Name = "miDeleteUnit";
+			// 
+			// imageList
+			// 
+			this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer) (resources.GetObject("imageList.ImageStream")));
+			this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+			this.imageList.Images.SetKeyName(0, "gtk-edit.png");
+			this.imageList.Images.SetKeyName(1, "edit-delete.png");
+			// 
+			// toolBar
+			// 
+			this.toolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
+            this.bttnEdit,
+            this.bttnDelete});
+			this.toolBar.ButtonSize = new System.Drawing.Size(16, 16);
+			this.toolBar.DropDownArrows = true;
+			this.toolBar.ImageList = this.imageList;
+			this.toolBar.Location = new System.Drawing.Point(0, 0);
+			this.toolBar.Name = "toolBar";
+			this.toolBar.ShowToolTips = true;
+			this.toolBar.Size = new System.Drawing.Size(240, 28);
+			this.toolBar.TabIndex = 3;
+			this.toolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBar_ButtonClick);
+			// 
+			// bttnEdit
+			// 
+			this.bttnEdit.Enabled = false;
+			this.bttnEdit.ImageIndex = 0;
+			this.bttnEdit.Name = "bttnEdit";
+			// 
+			// bttnDelete
+			// 
+			this.bttnDelete.Enabled = false;
+			this.bttnDelete.ImageIndex = 1;
+			this.bttnDelete.Name = "bttnDelete";
+			// 
+			// treeView
+			// 
+			this.treeView.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.treeView.ContextMenu = this.contextMenu;
+			this.treeView.FullRowSelect = true;
+			this.treeView.Location = new System.Drawing.Point(0, 28);
+			this.treeView.Name = "treeView";
+			this.treeView.Size = new System.Drawing.Size(240, 250);
+			this.treeView.TabIndex = 0;
+			this.treeView.DoubleClick += new System.EventHandler(this.treeView_DoubleClick);
+			this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
+			this.treeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeView_MouseDown);
+			// 
+			// FrmArmyTree
+			// 
+			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+			this.ClientSize = new System.Drawing.Size(240, 277);
+			this.ControlBox = false;
+			this.Controls.Add(this.toolBar);
+			this.Controls.Add(this.treeView);
+			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "FrmArmyTree";
+			this.Text = "FrmArmyTree";
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+		#endregion
+
+		private void ClearArmy()
+		{
+			nodes.Clear();
+			treeView.Nodes.Clear();
+		}
+
+		private void SetArmy(Army army)
+		{
+			ClearArmy();
+
+			if (army != null)
+			{
+				ArmyCategory[] cats = army.Categories;
+				TreeNode[] catNodes = new TreeNode[cats.Length];
+				Unit[] units;
+
+				for (int i = 0; i < cats.Length; i++)
+				{
+					ArmyCategory cat = cats[i];
+					units = army.GetUnits(cat);
+					cat.NameChanged += TreeNameChangedMethod;
+					cat.PointsValueChanged += NodePointsValueChanged;
+					TreeNode[] unitNodes = new TreeNode[units.Length];
+					TreeNode temp;
+
+					for (int j = 0; j < units.Length; j++)
+					{
+						unitNodes[j] = CreateTreeNode(units[j]);
+					}
+
+					temp = new TreeNode(CreateNodeName(cat), unitNodes);
+					temp.Tag = cat;
+					catNodes[i] = temp;
+					nodes[cat.ID] = temp;
+				}
+
+				TreeNode root = new TreeNode(CreateNodeName(army), catNodes);
+				root.Tag = army;
+				army.PointsValueChanged += NodePointsValueChanged;
+				nodes[army.ID] = root;
+				treeView.Nodes.Add(root);
+				root.ExpandAll();
+			}
+		}
+		
+		private string CreateNodeName(ICostedWarFoundryObject obj)
+		{
+			return Translation.GetTranslation("treeNodeText", "{0} ({1}pts)", obj.Name, obj.Points);
+		}
+
+		private void NodePointsValueChanged(WarFoundryObject obj, double oldValue, double newValue)
+		{
+			if (obj is ICostedWarFoundryObject)
+			{
+				SetNodeName(obj);
+			}
+		}
+
+		private void SetNodeName(WarFoundryObject obj)
+		{
+			TreeNode node = nodes[obj.ID];
+
+			if (node != null)
+			{
+				node.Text = CreateNodeName((ICostedWarFoundryObject)obj);
+			}
+		}
+
+		private TreeNode CreateTreeNode(Unit unit)
+		{
+			TreeNode temp = new TreeNode(CreateNodeName(unit));
+			temp.Tag = unit;
+			unit.NameChanged+= UnitNameChangedMethod;
+			unit.PointsValueChanged += NodePointsValueChanged;
+			nodes[unit.ID] = temp;
+			return temp;
+		}
+
+		public void FrmArmyTree_ArmyChanged(Army oldArmy, Army newArmy)
+		{
+			if (oldArmy != null)
+			{
+				oldArmy.UnitAdded -= UnitAddedMethod;
+				oldArmy.UnitRemoved -= UnitRemovedMethod;
+				oldArmy.PointsValueChanged -= NodePointsValueChanged;
+			}
+
+			if (newArmy != null)
+			{
+				newArmy.UnitAdded += UnitAddedMethod;
+				newArmy.UnitRemoved += UnitRemovedMethod;
+				newArmy.PointsValueChanged += NodePointsValueChanged;
+			}
+
+			SetArmy(newArmy);
+		}
+
+		private void UnitAdded(WarFoundryObject obj)
+		{
+			if (obj is Unit)
+			{
+				Unit unit = (Unit)obj;
+				ArmyCategory cat = unit.Category;
+				TreeNode parent = nodes[cat.ID];
+				TreeNode unitNode = CreateTreeNode(unit);
+				parent.Nodes.Add(unitNode);
+				parent.Expand(); //make sure it's expanded
+			}
+		}
+
+		public new FrmMain MdiParent
+		{
+			get { return (FrmMain) base.MdiParent; }
+			set { base.MdiParent = value; }
+		}
+
+		private void UnitRemoved(WarFoundryObject obj)
+		{
+			if (obj is Unit)
+			{
+				Unit unit = (Unit)obj;
+				RemoveUnitFromTree(unit);
+			}
+		}
+
+		private void RemoveUnitFromTree(Unit unit)
+		{
+			TreeNode unitNode = nodes[unit.ID];
+			unit.NameChanged-= UnitNameChangedMethod;
+
+			if (unitNode!=null)
+			{
+				unitNode.Remove();
+				nodes.Remove(unit.ID);
+			}
+		}
+
+
+		private void contextMenu_Popup(object sender, System.EventArgs e)
+		{
+			TreeNode node = treeView.SelectedNode;
+
+			if (node!=null && node.Tag is Unit)
+			{
+				foreach(MenuItem item in contextMenu.MenuItems)
+				{
+					item.Visible = true;
+				}
+			}
+			else
+			{
+				foreach(MenuItem item in contextMenu.MenuItems)
+				{
+					item.Visible = false;
+				}
+			}
+		}
+
+		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 miDelete_Click(object sender, System.EventArgs e)
+		{
+			DeleteUnit();
+		}
+
+		private void DeleteUnit()
+		{
+
+			TreeNode selected = treeView.SelectedNode;
+
+			if (selected.Tag != null && selected.Tag is Unit)
+			{
+				Unit unit = (Unit) selected.Tag;
+				commandStack.Execute(new RemoveUnitCommand(unit));
+			}
+		}
+
+		private void miEdit_Click(object sender, System.EventArgs e)
+		{	
+			EditUnit();
+		}
+
+		private void treeView_DoubleClick(object sender, System.EventArgs e)
+		{
+			EditUnit();			
+		}
+
+		private void EditUnit()
+		{
+			TreeNode selected = treeView.SelectedNode;
+			object tagData = selected.Tag;
+
+			if (tagData is Unit)
+			{
+				Unit unit = (Unit) tagData;
+				MdiParent.OpenUnitDialog(unit);
+			}
+		}
+
+		private void UpdateUnitName(WarFoundryObject obj, string oldValue, string newValue)
+		{
+			if (obj is ICostedWarFoundryObject)
+			{
+				SetNodeName(obj);
+			}
+		}
+
+		private void UpdateArmyName(WarFoundryObject obj, string oldValue, string newValue)
+		{
+			if (obj is Army)
+			{
+				Army army = (Army)obj;
+				TreeNode node = treeView.Nodes[0];
+				
+				if (node!=null)
+				{
+					node.Text = army.Name;
+				}
+			}
+		}
+
+		private void FrmArmyTree_TreeNameChanged(WarFoundryObject obj, string oldValue, string newValue)
+		{
+			TreeNode node = nodes[obj.ID];
+
+			if (node!=null)
+			{
+				node.Text = obj.Name;
+			}
+		}
+
+		private void toolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
+		{
+			if (e.Button == bttnDelete)
+			{
+				DeleteUnit();
+			}
+			else if (e.Button == bttnEdit)
+			{
+				EditUnit();
+			}
+		}
+
+		private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
+		{
+			TreeNode node = treeView.SelectedNode;
+
+			bttnDelete.Enabled = (node != null && node.Tag is Unit);
+			bttnEdit.Enabled = bttnDelete.Enabled;
+		}
+	}
+}
--- a/FrmMain.cs	Mon May 31 20:09:12 2010 +0000
+++ b/FrmMain.cs	Fri Jun 04 19:31:02 2010 +0000
@@ -149,11 +149,6 @@
 			sbErrorPanel.Color = Color.Red;
 			sbPointsPanel.ToolTipText = Translation.GetTranslation("statusPanelPointsToolTip", "total points value");
 
-			armyTree = new FrmArmyTree(CommandStack);
-			armyTree.MdiParent = this;
-			armyTree.StartPosition = FormStartPosition.Manual;
-			armyTree.Location = new Point(this.DisplayRectangle.Width - armyTree.Width - 10, 10);
-
 			// hack to load default files
 			WarFoundryLoader.GetDefault().AddLoadDirectory(new DirectoryInfo(Constants.ExecutablePath + Constants.DirectoryString + DefaultDataDir));
 			WarFoundryLoader.GetDefault().RegisterFactory(WarFoundryXmlFactory.GetFactory());
@@ -161,6 +156,24 @@
 			WarFoundrySaver.SetFileSaver(new WarFoundryXmlSaver());
 		}
 
+		private FrmArmyTree GetArmyTree()
+		{
+			if (armyTree == null || armyTree.IsDisposed)
+			{
+				CreateArmyTree();
+			}
+
+			return armyTree;
+		}
+
+		private void CreateArmyTree()
+		{
+			armyTree = new FrmArmyTree(CommandStack);
+			armyTree.MdiParent = this;
+			armyTree.StartPosition = FormStartPosition.Manual;
+			armyTree.Location = new Point(this.DisplayRectangle.Width - armyTree.Width - 10, 10);
+		}
+
 		private void TranslateControls()
 		{
 			ControlTranslator.TranslateControls(Controls);
@@ -924,7 +937,7 @@
 			miCloseArmy.Enabled = false;
 			miExportArmyAs.Enabled = false;
 			DisableCategoryButtons();
-			armyTree.Hide();
+			GetArmyTree().Hide();
 		}
 
 		private void SetNonNullArmyState(Army newArmy)
@@ -934,7 +947,7 @@
 			miSaveArmyAs.Enabled = true;
 			miCloseArmy.Enabled = true;
 			miExportArmyAs.Enabled = true;
-			armyTree.Show();
+			GetArmyTree().Show();
 		}
 
 		private void SetCategoryButtons(Category[] cats)