view FrmArmyTree.cs @ 246:b57a7cf844f8

Fixes #426: Changing unit size doesn't trigger all validation * Hook validation in to army composition changed event * Make sure we're ignoring old armies and listening to the new one
author IBBoard <dev@ibboard.co.uk>
date Sat, 01 Sep 2012 16:12:48 +0100
parents d0454aae0241
children
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IBBoard.Commands;
using IBBoard.WarFoundry.API.Objects;
using IBBoard.WarFoundry.API;
using IBBoard.Lang;
using IBBoard.Windows.Forms.I18N;
using IBBoard.WarFoundry.API.Commands;
using IBBoard.Windows.Forms;

namespace IBBoard.WarFoundry.GUI.WinForms
{
	public partial class FrmArmyTree : IBBoard.Windows.Forms.IBBForm
	{
		private Dictionary<string, TreeNode> nodes;
		private ObjectAddDelegate UnitAddedMethod;
		private ObjectRemoveDelegate UnitRemovedMethod;
		private StringValChangedDelegate UnitNameChangedMethod, ArmyNameChangedMethod, TreeNameChangedMethod;
		private CommandStack commandStack;
		public GameSystem CurrentGameSystem
		{
			get { return WarFoundryCore.CurrentGameSystem; }
			set { WarFoundryCore.CurrentGameSystem = value; }
		}

		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";
			miDeleteUnit.Name = "miDeleteUnit";
			miEditUnit.Name = "miEditUnit";
			miEditArmy.Name = "miEditArmy";
			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 (IBBToolStripMenuItem mi in contextMenuStrip.Items)
			{
				ControlTranslator.TranslateComponent(mi);
			}

			foreach (TreeNode node in nodes.Values)
			{
				node.Text = CreateNodeName((ICostedWarFoundryObject)node.Tag);
			}
		}
		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];

				for (int i = 0; i < cats.Length; i++)
				{
					ArmyCategory cat = cats[i];
					cat.NameChanged += TreeNameChangedMethod;
					cat.PointsValueChanged += NodePointsValueChanged;
					TreeNode[] unitNodes = CreateChildNodes(army.GetMainUnits(cat));
					TreeNode 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, CurrentGameSystem.GetPointsAbbrev(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[] unitNodes = CreateChildNodes(unit.ContainedUnits);
			TreeNode temp = new TreeNode(CreateNodeName(unit), unitNodes);
			temp.Tag = unit;
			unit.NameChanged += UnitNameChangedMethod;
			unit.PointsValueChanged += NodePointsValueChanged;
			nodes[unit.ID] = temp;
			return temp;
		}

		private TreeNode[] CreateChildNodes(Unit[] containedUnits)
		{
			TreeNode[] unitNodes;

			if (containedUnits.Length > 0)
			{
				unitNodes = new TreeNode[containedUnits.Length];

				for (int j = 0; j < containedUnits.Length; j++)
				{
					unitNodes[j] = CreateTreeNode(containedUnits[j]);
				}
			}
			else
			{
				unitNodes = new TreeNode[0];
			}

			return unitNodes;
		}

		public void FrmArmyTree_ArmyChanged(Army oldArmy, Army newArmy)
		{
			if (oldArmy != null)
			{
				oldArmy.NameChanged -= ArmyNameChangedMethod;
				oldArmy.UnitAdded -= UnitAddedMethod;
				oldArmy.UnitRemoved -= UnitRemovedMethod;
				oldArmy.PointsValueChanged -= NodePointsValueChanged;
			}

			if (newArmy != null)
			{
				newArmy.NameChanged += ArmyNameChangedMethod;
				newArmy.UnitAdded += UnitAddedMethod;
				newArmy.UnitRemoved += UnitRemovedMethod;
				newArmy.PointsValueChanged += NodePointsValueChanged;
			}

			SetArmy(newArmy);
		}

		private void UnitAdded(WarFoundryObject obj)
		{
			if (obj is Unit)
			{
				Unit unit = (Unit)obj;
				TreeNode parent;

				if (unit.ParentUnit == null)
				{
					ArmyCategory cat = unit.Category;
					parent = nodes[cat.ID];
				}
				else
				{
					parent = nodes[unit.ParentUnit.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 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)
		{
			EditTreeItem();
		}

		private void treeView_DoubleClick(object sender, System.EventArgs e)
		{
			EditTreeItem();
		}

		private void EditTreeItem()
		{
			TreeNode selected = treeView.SelectedNode;
			object tagData = selected.Tag;

			if (tagData is Unit)
			{
				Unit unit = (Unit)tagData;
				MdiParent.OpenUnitDialog(unit);
			}
			else if (tagData is Army)
			{
				EditArmy((Army)tagData);
			}
			else if (tagData is ArmyCategory)
			{
				AddUnitFromCategory((ArmyCategory)tagData);
			}
		}
		
		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)
			{
				SetNodeName((Army)obj);
			}
		}

		private void FrmArmyTree_TreeNameChanged(WarFoundryObject obj, string oldValue, string newValue)
		{
			TreeNode node = nodes[obj.ID];

			if (node != null)
			{
				node.Text = obj.Name;
			}
		}

		private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
		{
			TreeNode node = treeView.SelectedNode;
			Object tag = (node != null) ? node.Tag : null;
			bool tagIsUnit = (tag is Unit);
			bool tagIsUnitWithContained;

			if (tagIsUnit)
			{
				tagIsUnitWithContained = ((Unit)tag).UnitType.ContainedUnitTypes.Length > 0;
			}
			else
			{
				tagIsUnitWithContained = false;
			}

			bool tagIsArmy = (tag is Army);
			bool tagIsCategory = (tag is ArmyCategory);
			bttnAdd.Enabled = tagIsCategory || tagIsUnitWithContained;
			bttnDelete.Enabled = tagIsUnit;
			bttnEdit.Enabled = tagIsArmy || tagIsUnit;
		}

		private void miEditArmy_Click(object sender, EventArgs e)
		{
			Army army = treeView.SelectedNode.Tag as Army;
			EditArmy(army);
		}

		private void EditArmy(Army army)
		{
			FrmEditArmy editForm = new FrmEditArmy(commandStack, army);
			editForm.ShowDialog(this.ParentForm);
		}

		private void bttnEdit_Click(object sender, EventArgs e)
		{
			EditTreeItem();
		}

		private void bttnDelete_Click(object sender, EventArgs e)
		{
			DeleteUnit();
		}

		private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
		{
			TreeNode node = treeView.SelectedNode;
			Object tag = (node != null) ? node.Tag : null;
			bool tagIsUnit = (tag is Unit);
			bool tagIsUnitWithContained;

			if (tagIsUnit)
			{
				tagIsUnitWithContained = ((Unit)tag).UnitType.ContainedUnitTypes.Length > 0;
			}
			else
			{
				tagIsUnitWithContained = false;
			}

			bool tagIsArmy = (tag is Army);
			bool tagIsCategory = (tag is ArmyCategory);

			if (!tagIsUnit && !tagIsArmy && !tagIsCategory)
			{
				e.Cancel = true;
			}
			else
			{
				miDeleteUnit.Visible = tagIsUnit;
				miEditUnit.Visible = tagIsUnit;
				miEditArmy.Visible = tagIsArmy;
				miAddUnit.Visible = tagIsCategory || tagIsUnitWithContained;
			}
		}

		private void miAddUnit_Click(object sender, EventArgs e)
		{
			AddUnit();
		}

		private void AddUnit()
		{
			object tag = treeView.SelectedNode.Tag;

			if (tag is Unit)
			{
				Unit unit = (Unit)tag;
				UnitType[] unitTypes = unit.UnitType.ContainedUnitTypes;
				FrmNewUnit newUnitFrm = new FrmNewUnit(WarFoundryCore.CurrentArmy, unitTypes);
				DialogResult dr = newUnitFrm.ShowDialog(this);

				if (dr == DialogResult.OK)
				{
					UnitType newUnit = newUnitFrm.SelectedUnit;
					CreateAndAddUnitCommand cmd = new CreateAndAddUnitCommand(newUnitFrm.SelectedUnit, WarFoundryCore.CurrentArmy.GetCategory(newUnit.MainCategory), unit);
					commandStack.Execute(cmd);
					MdiParent.OpenUnitDialog(cmd.Unit);
				}
			}
			else
			{
				ArmyCategory tagData = tag as ArmyCategory;
				AddUnitFromCategory(tagData);
			}
		}

		private void AddUnitFromCategory(ArmyCategory tagData)
		{
			MdiParent.AddUnitFromCategory(tagData.Category);
		}

		private void bttnAdd_Click(object sender, EventArgs e)
		{
			AddUnit();
		}
	}
}