view FrmMain.cs @ 66:68d4f7499212

Re #176: Bug when saving recently edited army * Make save button available whether army has previously been saved or not (partly for usability and partly to try to trigger bug) Bug seems to occur when opening an army as the first action, adding a unit and saving it, but not when creating a new army as the first action, then loading an old army as the second action, then adding a unit and saving it
author IBBoard <dev@ibboard.co.uk>
date Sat, 26 Sep 2009 09:51:53 +0000
parents c4181adba7df
children 75cf9b6608f5
line wrap: on
line source

// This file (FrmMain.cs) is a part of the IBBoard.WarFoundry.GUI.WinForms project and is copyright 2007, 2008, 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.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Threading;
using log4net;
using IBBoard;
using IBBoard.CustomMath;
using IBBoard.Commands;
using IBBoard.IO;
using IBBoard.Lang;
using IBBoard.Windows.Forms;
using IBBoard.Windows.Forms.I18N;
using IBBoard.Xml;
using IBBoard.WarFoundry.API;
using IBBoard.WarFoundry.API.Commands;
using IBBoard.WarFoundry.API.Exporters;
using IBBoard.WarFoundry.API.Objects;
using IBBoard.WarFoundry.API.Savers;
using IBBoard.WarFoundry.API.Factories;
using IBBoard.WarFoundry.API.Factories.Xml;

namespace IBBoard.WarFoundry.GUI.WinForms
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class FrmMain : System.Windows.Forms.Form
	{
		private static readonly string AppTitle = "WarFoundry";
        const string DefaultDataDir = "data";

		private Preferences preferences;
		protected readonly ILog logger = LogManager.GetLogger(typeof(FrmMain));

		private CommandStack commandStack;
		private ToolBarButton[] categoryButtons;

		public ObjectAddDelegate UnitAddedMethod;
		public ObjectRemoveDelegate UnitRemovedMethod;
		public DoubleValChangedDelegate PointsValueChangedMethod;
		//public FailedUnitRequirementDelegate FailedUnitRequirementMethod;

		private FrmArmyTree armyTree;
		private string loadedFilePath;
		private Dictionary<string, FrmUnit> unitWindows;

		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.ToolBar toolBar;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnNewArmy;
		private System.Windows.Forms.ImageList buttonIcons;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnSaveArmy;
		private System.Windows.Forms.OpenFileDialog openArmyDialog;
		private System.Windows.Forms.SaveFileDialog saveArmyDialog;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnOpenArmy;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnSep1;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnUndo;
		private IBBoard.Windows.Forms.IBBToolBarButton bttnRedo;
		private System.Windows.Forms.MainMenu mainMenu;
		private IBBoard.Windows.Forms.IBBMenuItem menuFile;
		private IBBoard.Windows.Forms.IBBMenuItem miNewArmy;
		private IBBoard.Windows.Forms.IBBMenuItem miOpenArmy;
		private IBBoard.Windows.Forms.IBBMenuItem miCloseArmy;
		private IBBoard.Windows.Forms.IBBMenuItem miSaveArmy;
		private IBBoard.Windows.Forms.IBBMenuItem miSaveArmyAs;
		private System.Windows.Forms.MenuItem miSep2;
		private IBBoard.Windows.Forms.IBBMenuItem miReloadFiles;
		private System.Windows.Forms.MenuItem miSep3;
		private IBBoard.Windows.Forms.IBBMenuItem miExit;
		private IBBoard.Windows.Forms.IBBMenuItem menuEdit;
		private IBBoard.Windows.Forms.IBBMenuItem miUndo;
		private IBBoard.Windows.Forms.IBBMenuItem miRedo;
		private IBBoard.Windows.Forms.IBBMenuItem menuHelp;
		private IBBoard.Windows.Forms.IBBMenuItem miAbout;
		private IBBoard.Windows.Forms.ColorableStatusBarPanel sbMainPanel;
		private IBBoard.Windows.Forms.ColorableStatusBarPanel sbErrorPanel;
		private IBBoard.Windows.Forms.ColorableStatusBarPanel sbPointsPanel;
		private System.Windows.Forms.ContextMenu undoMenu;
		private System.Windows.Forms.ContextMenu redoMenu;
		private IBBoard.Windows.Forms.ColorableStatusBar statusBar;
		private System.Windows.Forms.Timer statusBarTimer;
		private MenuItem miExportArmyAs;
		private MenuItem miExportArmyAsBasicHTML;
		private System.Windows.Forms.Panel pnlRight;

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			try
			{
				Application.EnableVisualStyles();
				Application.Run(new FrmMain(args));
			}
			catch (Exception ex)
			{
				LogManager.GetLogger(typeof(FrmMain)).Fatal(ex);
				MessageBox.Show(null, "A major, unexpected and fatal error ocurred while starting the application: \r\n\r\n" + ex.Message + "\r\n\r\n" + ex.StackTrace, "Fatal error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		public FrmMain(string[] args)
		{
			this.Closing+=new CancelEventHandler(FrmMain_Closing);
			CommandStack.CommandStackUpdated += new MethodInvoker(commandStack_CommandStackUpdated);

			InitializeComponent();

			Preferences = new Preferences("WarFoundry");
			try
			{
				Translation.InitialiseTranslations(Constants.ExecutablePath, Preferences["language"].ToString());
			}
			catch (TranslationLoadException ex)
			{
				logger.Error(ex);
				MessageBox.Show(this, "Translation loading failed for language " + Preferences["language"].ToString(), "Translation failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

			//pnlRight.Left = ClientSize.Width - pnlRight.Width - 2;
			//pnlRight.Top = toolBar.Height + 5;
			//pnlRight.Height = ClientRectangle.Bottom - statusBar.Height - pnlRight.Top - 3;

			foreach (Control ctrl in Controls)
			{
				ControlTranslator.TranslateControl(ctrl);
			}

			foreach(Component comp in components.Components)
			{
				ControlTranslator.TranslateComponent(comp);
			}

			foreach (IBBMenuItem mi in Menu.MenuItems)
			{
				ControlTranslator.TranslateComponent(mi);
			}

			ControlTranslator.TranslateComponent(openArmyDialog);
			ControlTranslator.TranslateComponent(saveArmyDialog);
			unitWindows = new Dictionary<string, FrmUnit>();

			WarFoundryCore.GameSystemChanged+= new GameSystemChangedDelegate(FrmMain_GameSystemChanged);
			WarFoundryCore.ArmyChanged += new ArmyChangedDelegate(FrmMain_ArmyChanged);
			UnitAddedMethod = new ObjectAddDelegate(FrmMain_UnitAddedMethod);
			UnitRemovedMethod = new ObjectRemoveDelegate(FrmMain_UnitRemovedMethod);
			PointsValueChangedMethod = new DoubleValChangedDelegate(FrmMain_PointsValueChangedMethod);
			//FailedUnitRequirementMethod = new FailedUnitRequirementDelegate(FrmMain_FailedUnitRequirement);

			sbErrorPanel.Color = Color.Red;

			armyTree = new FrmArmyTree(CommandStack);
			armyTree.MdiParent = this;
			armyTree.StartPosition = FormStartPosition.Manual;
			armyTree.Location = new Point(this.DisplayRectangle.Width - armyTree.Width - 10, 10);
            ControlTranslator.TranslateControl(armyTree);

            // hack to load default files
            WarFoundryLoader.GetDefault().AddLoadDirectory(new DirectoryInfo(Constants.ExecutablePath + Constants.DirectoryString + DefaultDataDir));
            WarFoundryLoader.GetDefault().RegisterFactory(WarFoundryXmlFactory.GetFactory());
			WarFoundryLoader.GetDefault().FileLoadingFinished += FileLoadingFinished;
			WarFoundrySaver.SetFileSaver(new WarFoundryXmlSaver());
		}

		public static string DataPath
		{
			get { return Constants.ExecutablePath+Constants.DirectoryChar+"data"; }
		}

		public static String ArmiesPath
		{
			get { return Constants.UserDataPath+Constants.DirectoryChar+"armies"; }
		}

		public Preferences Preferences
		{
			get { return preferences; }
			set { preferences = value; }
		}

		public CommandStack CommandStack
		{
			get 
			{
				if (commandStack == null)
				{					
					commandStack = new CommandStack();
				}

				return commandStack; 
			}
		}

		/// <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.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain));
			this.statusBar = new IBBoard.Windows.Forms.ColorableStatusBar();
			this.sbMainPanel = new IBBoard.Windows.Forms.ColorableStatusBarPanel();
			this.sbErrorPanel = new IBBoard.Windows.Forms.ColorableStatusBarPanel();
			this.sbPointsPanel = new IBBoard.Windows.Forms.ColorableStatusBarPanel();
			this.toolBar = new System.Windows.Forms.ToolBar();
			this.bttnNewArmy = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.bttnOpenArmy = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.bttnSaveArmy = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.bttnSep1 = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.bttnUndo = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.undoMenu = new System.Windows.Forms.ContextMenu();
			this.bttnRedo = new IBBoard.Windows.Forms.IBBToolBarButton();
			this.redoMenu = new System.Windows.Forms.ContextMenu();
			this.buttonIcons = new System.Windows.Forms.ImageList(this.components);
			this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
			this.menuFile = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miNewArmy = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miOpenArmy = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miSaveArmy = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miSaveArmyAs = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miExportArmyAs = new System.Windows.Forms.MenuItem();
			this.miExportArmyAsBasicHTML = new System.Windows.Forms.MenuItem();
			this.miCloseArmy = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miSep2 = new System.Windows.Forms.MenuItem();
			this.miReloadFiles = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miSep3 = new System.Windows.Forms.MenuItem();
			this.miExit = new IBBoard.Windows.Forms.IBBMenuItem();
			this.menuEdit = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miUndo = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miRedo = new IBBoard.Windows.Forms.IBBMenuItem();
			this.menuHelp = new IBBoard.Windows.Forms.IBBMenuItem();
			this.miAbout = new IBBoard.Windows.Forms.IBBMenuItem();
			this.openArmyDialog = new System.Windows.Forms.OpenFileDialog();
			this.saveArmyDialog = new System.Windows.Forms.SaveFileDialog();
			this.pnlRight = new System.Windows.Forms.Panel();
			this.statusBarTimer = new System.Windows.Forms.Timer(this.components);
			((System.ComponentModel.ISupportInitialize) (this.sbMainPanel)).BeginInit();
			((System.ComponentModel.ISupportInitialize) (this.sbErrorPanel)).BeginInit();
			((System.ComponentModel.ISupportInitialize) (this.sbPointsPanel)).BeginInit();
			this.SuspendLayout();
			// 
			// statusBar
			// 
			this.statusBar.Location = new System.Drawing.Point(0, 546);
			this.statusBar.Name = "statusBar";
			this.statusBar.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
            this.sbMainPanel,
            this.sbErrorPanel,
            this.sbPointsPanel});
			this.statusBar.ShowPanels = true;
			this.statusBar.Size = new System.Drawing.Size(790, 22);
			this.statusBar.TabIndex = 1;
			this.statusBar.PanelClick += new System.Windows.Forms.StatusBarPanelClickEventHandler(this.statusBar_PanelClick);
			this.statusBar.DrawItem += new System.Windows.Forms.StatusBarDrawItemEventHandler(this.statusBar_DrawItem);
			// 
			// sbMainPanel
			// 
			this.sbMainPanel.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;
			this.sbMainPanel.Color = System.Drawing.SystemColors.WindowText;
			this.sbMainPanel.Name = "sbMainPanel";
			this.sbMainPanel.Style = System.Windows.Forms.StatusBarPanelStyle.OwnerDraw;
			this.sbMainPanel.Width = 475;
			// 
			// sbErrorPanel
			// 
			this.sbErrorPanel.Color = System.Drawing.SystemColors.WindowText;
			this.sbErrorPanel.Name = "sbErrorPanel";
			this.sbErrorPanel.Style = System.Windows.Forms.StatusBarPanelStyle.OwnerDraw;
			this.sbErrorPanel.Width = 150;
			// 
			// sbPointsPanel
			// 
			this.sbPointsPanel.Color = System.Drawing.SystemColors.WindowText;
			this.sbPointsPanel.Name = "sbPointsPanel";
			this.sbPointsPanel.Style = System.Windows.Forms.StatusBarPanelStyle.OwnerDraw;
			this.sbPointsPanel.ToolTipText = "Current Points Total";
			this.sbPointsPanel.Width = 150;
			// 
			// toolBar
			// 
			this.toolBar.Appearance = System.Windows.Forms.ToolBarAppearance.Flat;
			this.toolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
            this.bttnNewArmy,
            this.bttnOpenArmy,
            this.bttnSaveArmy,
            this.bttnSep1,
            this.bttnUndo,
            this.bttnRedo});
			this.toolBar.ButtonSize = new System.Drawing.Size(16, 16);
			this.toolBar.DropDownArrows = true;
			this.toolBar.ImageList = this.buttonIcons;
			this.toolBar.Location = new System.Drawing.Point(0, 0);
			this.toolBar.Name = "toolBar";
			this.toolBar.ShowToolTips = true;
			this.toolBar.Size = new System.Drawing.Size(790, 28);
			this.toolBar.TabIndex = 2;
			this.toolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBar_ButtonClick);
			// 
			// bttnNewArmy
			// 
			this.bttnNewArmy.ImageIndex = 0;
			this.bttnNewArmy.Name = "bttnNewArmy";
			// 
			// bttnOpenArmy
			// 
			this.bttnOpenArmy.ImageIndex = 2;
			this.bttnOpenArmy.Name = "bttnOpenArmy";
			// 
			// bttnSaveArmy
			// 
			this.bttnSaveArmy.Enabled = false;
			this.bttnSaveArmy.ImageIndex = 1;
			this.bttnSaveArmy.Name = "bttnSaveArmy";
			// 
			// bttnSep1
			// 
			this.bttnSep1.Name = "";
			this.bttnSep1.Style = System.Windows.Forms.ToolBarButtonStyle.Separator;
			// 
			// bttnUndo
			// 
			this.bttnUndo.DropDownMenu = this.undoMenu;
			this.bttnUndo.Enabled = false;
			this.bttnUndo.ImageIndex = 3;
			this.bttnUndo.Name = "bttnUndo";
			this.bttnUndo.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton;
			// 
			// bttnRedo
			// 
			this.bttnRedo.DropDownMenu = this.redoMenu;
			this.bttnRedo.Enabled = false;
			this.bttnRedo.ImageIndex = 4;
			this.bttnRedo.Name = "bttnRedo";
			this.bttnRedo.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton;
			// 
			// buttonIcons
			// 
			this.buttonIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer) (resources.GetObject("buttonIcons.ImageStream")));
			this.buttonIcons.TransparentColor = System.Drawing.Color.Transparent;
			this.buttonIcons.Images.SetKeyName(0, "");
			this.buttonIcons.Images.SetKeyName(1, "");
			this.buttonIcons.Images.SetKeyName(2, "");
			this.buttonIcons.Images.SetKeyName(3, "");
			this.buttonIcons.Images.SetKeyName(4, "");
			this.buttonIcons.Images.SetKeyName(5, "");
			this.buttonIcons.Images.SetKeyName(6, "");
			// 
			// mainMenu
			// 
			this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuFile,
            this.menuEdit,
            this.menuHelp});
			// 
			// menuFile
			// 
			this.menuFile.Index = 0;
			this.menuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miNewArmy,
            this.miOpenArmy,
            this.miSaveArmy,
            this.miSaveArmyAs,
            this.miExportArmyAs,
            this.miCloseArmy,
            this.miSep2,
            this.miReloadFiles,
            this.miSep3,
            this.miExit});
			this.menuFile.Text = "&file";
			// 
			// miNewArmy
			// 
			this.miNewArmy.Index = 0;
			this.miNewArmy.Text = "&new army";
			this.miNewArmy.Click += new System.EventHandler(this.miNewArmy_Click);
			// 
			// miOpenArmy
			// 
			this.miOpenArmy.Index = 1;
			this.miOpenArmy.Text = "&open army";
			this.miOpenArmy.Click += new System.EventHandler(this.miOpenArmy_Click);
			// 
			// miSaveArmy
			// 
			this.miSaveArmy.Enabled = false;
			this.miSaveArmy.Index = 2;
			this.miSaveArmy.Text = "&save army";
			this.miSaveArmy.Click += new System.EventHandler(this.miSaveArmy_Click);
			// 
			// miSaveArmyAs
			// 
			this.miSaveArmyAs.Enabled = false;
			this.miSaveArmyAs.Index = 3;
			this.miSaveArmyAs.Text = "save army &as...";
			this.miSaveArmyAs.Click += new System.EventHandler(this.miSaveArmyAs_Click);
			// 
			// miExportArmyAs
			// 
			this.miExportArmyAs.Enabled = false;
			this.miExportArmyAs.Index = 4;
			this.miExportArmyAs.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miExportArmyAsBasicHTML});
			this.miExportArmyAs.Text = "export army as...";
			// 
			// miExportArmyAsBasicHTML
			// 
			this.miExportArmyAsBasicHTML.Index = 0;
			this.miExportArmyAsBasicHTML.Text = "Basic HTML";
			this.miExportArmyAsBasicHTML.Click += new System.EventHandler(this.miExportArmyAsBasicHTML_Click);
			// 
			// miCloseArmy
			// 
			this.miCloseArmy.Enabled = false;
			this.miCloseArmy.Index = 5;
			this.miCloseArmy.Text = "&close army";
			this.miCloseArmy.Click += new System.EventHandler(this.miCloseArmy_Click);
			// 
			// miSep2
			// 
			this.miSep2.Index = 6;
			this.miSep2.Text = "-";
			// 
			// miReloadFiles
			// 
			this.miReloadFiles.Index = 7;
			this.miReloadFiles.Text = "&reload files";
			this.miReloadFiles.Click += new System.EventHandler(this.miReloadFiles_Click);
			// 
			// miSep3
			// 
			this.miSep3.Index = 8;
			this.miSep3.Text = "-";
			// 
			// miExit
			// 
			this.miExit.Index = 9;
			this.miExit.Text = "e&xit";
			this.miExit.Click += new System.EventHandler(this.miExit_Click);
			// 
			// menuEdit
			// 
			this.menuEdit.Index = 1;
			this.menuEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miUndo,
            this.miRedo});
			this.menuEdit.Text = "&edit";
			// 
			// miUndo
			// 
			this.miUndo.Enabled = false;
			this.miUndo.Index = 0;
			this.miUndo.Text = "&undo";
			this.miUndo.Click += new System.EventHandler(this.miUndo_Click);
			// 
			// miRedo
			// 
			this.miRedo.Enabled = false;
			this.miRedo.Index = 1;
			this.miRedo.Text = "&redo";
			this.miRedo.Click += new System.EventHandler(this.miRedo_Click);
			// 
			// menuHelp
			// 
			this.menuHelp.Index = 2;
			this.menuHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miAbout});
			this.menuHelp.Text = "&help";
			// 
			// miAbout
			// 
			this.miAbout.Enabled = false;
			this.miAbout.Index = 0;
			this.miAbout.Text = "&about";
			// 
			// saveArmyDialog
			// 
			this.saveArmyDialog.Title = "Translatable:saveArmyDialog";
			// 
			// pnlRight
			// 
			this.pnlRight.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.pnlRight.BackColor = System.Drawing.SystemColors.AppWorkspace;
			this.pnlRight.Location = new System.Drawing.Point(724, 30);
			this.pnlRight.Name = "pnlRight";
			this.pnlRight.Size = new System.Drawing.Size(64, 514);
			this.pnlRight.TabIndex = 4;
			this.pnlRight.Visible = false;
			this.pnlRight.Paint += new System.Windows.Forms.PaintEventHandler(this.pnlRight_Paint);
			// 
			// statusBarTimer
			// 
			this.statusBarTimer.Interval = 5000;
			this.statusBarTimer.Tick += new System.EventHandler(this.statusBarTimer_Tick);
			// 
			// FrmMain
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(790, 568);
			this.Controls.Add(this.pnlRight);
			this.Controls.Add(this.toolBar);
			this.Controls.Add(this.statusBar);
			this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
			this.IsMdiContainer = true;
			this.Menu = this.mainMenu;
			this.Name = "FrmMain";
			this.Text = "WarFoundry";
			((System.ComponentModel.ISupportInitialize) (this.sbMainPanel)).EndInit();
			((System.ComponentModel.ISupportInitialize) (this.sbErrorPanel)).EndInit();
			((System.ComponentModel.ISupportInitialize) (this.sbPointsPanel)).EndInit();
			this.ResumeLayout(false);
			this.PerformLayout();

		}
		#endregion

		private void FileLoadingFinished(List<FileLoadFailure> failures)
		{
			foreach (FileLoadFailure failure in failures)
			{
				logger.Warn("Failed to load " + failure.FailedFile.FullName + ": " + failure.Message);
			}
		}

		private void miExit_Click(object sender, System.EventArgs e)
		{
			Application.Exit();
		}

		private void miNewArmy_Click(object sender, System.EventArgs e)
		{
			CreateNewArmy();
		}

		private void CreateNewArmy()
		{
			if (CloseCurrentArmy())
			{
				FrmNewArmy newArmy = new FrmNewArmy(CurrentGameSystem);
				DialogResult dr = newArmy.ShowDialog();

				if (dr == DialogResult.OK)
				{
					CurrentArmy = new Army(newArmy.SelectedRace, newArmy.ArmyName, newArmy.ArmySize);
				}
			}
		}

		private bool OpenArmy()
		{
			if (CloseCurrentArmy())
			{
				if (openArmyDialog.Filter=="")
				{
					string savePath = ArmiesPath;
				
					if (!Directory.Exists(savePath))
					{
						Directory.CreateDirectory(savePath);
					}

					openArmyDialog.InitialDirectory = savePath;
					openArmyDialog.Filter = Translation.GetTranslation("armyFileFilter")+"|*.army";
					openArmyDialog.Title = Translation.GetTranslation("openArmyDialog");

				}

				DialogResult dr = openArmyDialog.ShowDialog(this);

				if (dr == DialogResult.OK)
				{
					try
					{
						string newFilePath = openArmyDialog.FileName;
						CurrentArmy = WarFoundryLoader.GetDefault().LoadArmy(new FileInfo(newFilePath));
						loadedFilePath = newFilePath;
						return true;					
					}
					catch (InvalidFileException ex)
					{
						logger.Error(ex);
						MessageBox.Show(this, ex.Message, Translation.GetTranslation("InvalidFileBoxTitle", "Invalid data file"), MessageBoxButtons.OK, MessageBoxIcon.Error);
						return false;
					}
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}

		private bool CloseCurrentArmy()
		{
			if (CurrentArmy!=null)
			{
				bool canClose = false;

				if (CommandStack.IsDirty())
				{
					DialogResult dr = MessageBox.Show(this, "The army \""+CurrentArmy.Name+"\" has been modified.\r\nSave changes before closing army?", "Unsaved changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button3);

					if (dr == DialogResult.Yes)
					{
						canClose = SaveCurrentArmy();
					}
					else if (dr == DialogResult.No)
					{
						canClose = true;
					}
					//else they said cancel and we default to "canClose = false" so do nothing
				}
				else
				{
					canClose = true;
				}

				if (canClose)
				{
					//do close
					DisableCategoryButtons();
					CurrentArmy = null;
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				DisableCategoryButtons();
				//pretend we succeeded
				return true;
			}
		}

		private void UndoLastAction()
		{
			if (commandStack.CanUndo())
			{
				commandStack.Undo();
			}
		}

		private void RedoAction()
		{
			if (commandStack.CanRedo())
			{
				commandStack.Redo();
			}
		}

		private bool SaveCurrentArmy()
		{
			bool saved = false;

			string filePath = loadedFilePath;

			if (filePath == null)
			{
				filePath = PromptForArmyFilePath();
			}

			if (filePath != null)
			{
				saved = SaveCurrentArmyToFile(filePath);
			}

			return saved;
		}

		private bool SaveCurrentArmyAs()
		{
			bool saved = false;
			string filePath = PromptForArmyFilePath();

			if (filePath != null)
			{
				saved = SaveCurrentArmyToFile(filePath);
			}
			
			return saved;
		}

		private bool SaveCurrentArmyToFile(string filePath)
		{
			if (WarFoundrySaver.GetSaver().Save(CurrentArmy, filePath))
			{
				loadedFilePath = filePath;
				miSaveArmy.Enabled = false;
				bttnSaveArmy.Enabled = false;
				CommandStack.setCleanMark();
				return true;
			}
			else
			{
				MessageBox.Show(this, Translation.GetTranslation("SaveFailed"), Translation.GetTranslation("SaveFailedTitle"), MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
		}

		private string PromptForArmyFilePath()
		{
			if (saveArmyDialog.Filter == "")
			{
				string savePath = ArmiesPath;
				
				if (!Directory.Exists(savePath))
				{
					Directory.CreateDirectory(savePath);
				}

				saveArmyDialog.InitialDirectory = savePath;
				saveArmyDialog.Filter = Translation.GetTranslation("armyFileFilter")+"|*.army";
				saveArmyDialog.Title = Translation.GetTranslation("saveArmyDialog");
			}

			DialogResult dr = saveArmyDialog.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				return saveArmyDialog.FileName;
			}
			else
			{
				return null;
			}
		}

		private void toolBar_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)
		{
			if (e.Button == bttnUndo)
			{
				UndoLastAction();
			}
			else if (e.Button == bttnRedo)
			{
				RedoAction();
			}
			else if (e.Button == bttnNewArmy)
			{
				CreateNewArmy();
			}
			else if (e.Button == bttnOpenArmy)
			{
				OpenArmy();
			}
			else if (e.Button == bttnSaveArmy)
			{
				SaveCurrentArmy();
			}
			else
			{
				//it must be one of our extra buttons for the categories
				AddUnitFromCategory((Category)e.Button.Tag);
			}
		}

		public static GameSystem CurrentGameSystem
		{
			get { return WarFoundryCore.CurrentGameSystem; }
			set { WarFoundryCore.CurrentGameSystem = value; }
		}

		public static Army CurrentArmy
		{
			get { return WarFoundryCore.CurrentArmy; }
			set { WarFoundryCore.CurrentArmy = value; }
		}

		private void FrmMain_GameSystemChanged(GameSystem oldSystem, GameSystem newSystem)
		{
			SetAppTitle();
			RemoveCategoryButtons();
			AddCategoryButtons();
		}

		private void FrmMain_ArmyChanged(Army oldArmy, Army newArmy)
		{		
			SetAppTitle();

			if (oldArmy != null)
			{
				oldArmy.UnitAdded -= UnitAddedMethod;
				oldArmy.UnitRemoved -= UnitRemovedMethod;
				oldArmy.PointsValueChanged -= PointsValueChangedMethod;
			}

			FrmUnit[] unitForms = DictionaryUtils.ToArray(unitWindows);

			foreach (FrmUnit window in unitForms)
			{
				window.Close();
			}

			unitWindows.Clear();

			if (CurrentArmy==null)
			{
				miSaveArmyAs.Enabled = false;
				miCloseArmy.Enabled = false;
				miExportArmyAs.Enabled = false;
				DisableCategoryButtons();
				armyTree.Hide();
			}
			else
			{
				newArmy.UnitAdded += UnitAddedMethod;
				newArmy.UnitRemoved += UnitRemovedMethod;
				newArmy.PointsValueChanged += PointsValueChangedMethod;
				//TODO: Clear all buttons
				miSaveArmyAs.Enabled = true;
				miCloseArmy.Enabled = true;
				miExportArmyAs.Enabled = true;
				EnableCategoryButtons();
				armyTree.Show();

				if (newArmy.Race.HasCategoryOverrides())
				{
					RemoveCategoryButtons();
					AddCategoryButtons(newArmy.Race.Categories);
				}
			}

			CommandStack.Reset();

			loadedFilePath = null;
			miSaveArmy.Enabled = false;
			bttnSaveArmy.Enabled = false;

			SetPointsPanelText();
		}

		private void AddCategoryButtons()
		{
			if (CurrentGameSystem!=null)
			{
				AddCategoryButtons(CurrentGameSystem.Categories);
			}
		}

		private void AddCategoryButtons(Category[] cats)
		{
			int catCount = cats.Length;
			Category cat;
			categoryButtons = new ToolBarButton[catCount+1];

			ToolBarButton sep = new ToolBarButton();
			sep.Style = ToolBarButtonStyle.Separator;
			categoryButtons[0] = sep;

			IBBToolBarButton button;

			for (int i = 0; i<catCount; i++)
			{
				cat = cats[i];
				button = new IBBToolBarButton();
				///button.Name = "bttnAddCategory" + cat.Name[0].ToString();
				button.Text = cat.Name.ToString();//String.Format(Translation.GetTranslation("bttnAddCategory"), cat.Name);
				button.Tag = cat;
				button.ImageIndex = 6;
				button.Enabled = false;
				categoryButtons[i+1] = button;
			}

			this.Invoke(new ToolBarButtonRangeDelegate(toolBar.Buttons.AddRange), new object[]{categoryButtons});
		}

		private void RemoveCategoryButtons()
		{
			if (categoryButtons!=null)
			{
				for (int i = 0; i<categoryButtons.Length; i++)
				{
					this.Invoke(new ToolBarButtonDelegate(toolBar.Buttons.Remove), new object[]{categoryButtons[i]});
				}
			}
		}

		private void EnableCategoryButtons()
		{
			SetCategoryButtonState(true);
		}

		private void DisableCategoryButtons()
		{
			SetCategoryButtonState(false);
		}

		private void SetCategoryButtonState(bool state)
		{
			if (categoryButtons!=null)
			{
				for (int i = 0; i<categoryButtons.Length; i++)
				{
					categoryButtons[i].Enabled = state;
				}
			}
		}

		private void miSaveArmyAs_Click(object sender, System.EventArgs e)
		{
			SaveCurrentArmyAs();
		}

		private void commandStack_CommandStackUpdated()
		{
			bttnUndo.Enabled = commandStack.CanUndo();
			miUndo.Enabled = bttnUndo.Enabled;
			bttnRedo.Enabled = commandStack.CanRedo();
			miRedo.Enabled = bttnRedo.Enabled;
			MenuItem[] menuItems = null;
			int redoLength = commandStack.RedoLength;
			int maxRedo = Math.Min(10, redoLength);
			
			if (redoLength > 0)
			{
				menuItems = new MenuItem[maxRedo];
				Command com;
				MenuItem mi;

				for (int i = 0; i < maxRedo; i++)
				{
					com = commandStack.PeekRedoCommand(i+1);

					if (com == null)
					{
						break; 
					}

					mi = new MenuItem(com.Description);
					mi.Click+=new EventHandler(redoMenu_Click);
					menuItems[i] = mi;
				}
			}

			redoMenu.MenuItems.Clear();

			if (menuItems!=null && menuItems[0]!=null)
			{
				bttnRedo.ToolTipText = menuItems[0].Text;
				redoMenu.MenuItems.AddRange(menuItems);
			}

			int undoLength = commandStack.UndoLength;
			int maxUndo = Math.Min(10, undoLength);
			MenuItem[] menuItemsUndo = null;
			
			if (undoLength > 0)
			{
				menuItemsUndo = new MenuItem[maxUndo];
				Command com;
				MenuItem mi;

				for (int i = 0; i < maxUndo; i++)
				{
					com = commandStack.PeekUndoCommand(i+1);

					if (com == null)
					{
						break; 
					}

					mi = new MenuItem(com.UndoDescription);
					mi.Click+=new EventHandler(undoMenu_Click);
					menuItemsUndo[i] = mi;
				}
			}

			undoMenu.MenuItems.Clear();

			if (menuItemsUndo!=null && menuItemsUndo[0]!=null)
			{
				bttnUndo.ToolTipText = menuItemsUndo[0].Text;
				undoMenu.MenuItems.AddRange(menuItemsUndo);
			}

			bttnSaveArmy.Enabled = commandStack.IsDirty() && CurrentArmy!=null;
			miSaveArmy.Enabled = commandStack.IsDirty() && CurrentArmy!=null;
		}

		private void miSaveArmy_Click(object sender, System.EventArgs e)
		{
			SaveCurrentArmy();
		}

		private void SetAppTitle()
		{
			string str = AppTitle;

			if (CurrentGameSystem!=null)
			{
				str+= " - "+CurrentGameSystem.Name;
			}

			if (CurrentArmy!=null)
			{
				str+= " - "+CurrentArmy.Name;
			}

			this.Text = str;
		}

		private void AddUnitFromCategory(Category cat)
		{
			FrmNewUnit newUnit = new FrmNewUnit(CurrentArmy.Race, cat, CurrentArmy);
			DialogResult dr = newUnit.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				CreateAndAddUnitCommand cmd = new CreateAndAddUnitCommand(newUnit.SelectedUnit, CurrentArmy.GetCategory(cat));
				commandStack.Execute(cmd);
				OpenUnitDialog(cmd.Unit);
			}
		}

		internal void OpenUnitDialog(Unit unit)
		{
			string unitID = unit.ID;

			if (unitWindows.ContainsKey(unitID))
			{
				unitWindows[unitID].Focus();
			}
			else
			{
				FrmUnit unitForm = new FrmUnit(unit, commandStack);
				unitWindows.Add(unitID, unitForm);
				unitForm.MdiParent = this;
				unitForm.Closing += new CancelEventHandler(unitForm_Closing);
				unitForm.Show();
			}
		}

		private void unitForm_Closing(object sender, CancelEventArgs e)
		{
			if (sender is FrmUnit)
			{
				FrmUnit unitForm = (FrmUnit) sender;
				unitWindows.Remove(unitForm.Unit.ID);
			}
		}

		private void FrmMain_UnitAddedMethod(object unitObj)
		{
			if (unitObj is Unit)
			{
				Unit unit = (Unit)unitObj;
				sbErrorPanel.Text = "";
			}
		}

		private void FrmMain_UnitRemovedMethod(object unitObj)
		{
			if (unitObj is Unit)
			{
				Unit unit = (Unit)unitObj;
				sbErrorPanel.Text = "";

				//check if window is open, and close it if it is
				foreach (Form frm in this.MdiChildren)
				{
					if (frm is FrmUnit)
					{
						if (((FrmUnit)frm).Unit == unit)
						{
							frm.Close();
							break;
						}
					}
				}
			}
		}

		/*private void FrmMain_FailedUnitRequirement(FailedUnitRequirement failedRequirement)
		{
			sbErrorPanel.Text = Translation.GetTranslation("UnitRequirementFailed", "Unit Requirement Failed");
			sbErrorPanel.Tag = failedRequirement.Description;
		}*/

		/*public void MdiChildMoved()
		{
			Point mouseAt = PointToClient(ActiveMdiChild.Location);

			if (Comparisons.ValueWithinAmount(pnlRight.Right, ActiveMdiChild.Right, 10))
			{
				pnlRight.Visible = true;
				//pnlRight.Container.Add(ActiveMdiChild);
			}
			else
			{
				pnlRight.Visible = false;
			}
		}*/

		public void pnlRight_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			HatchBrush dockCueBrush = new HatchBrush(HatchStyle.LightDownwardDiagonal, Color.White, Color.Gray);
			Pen dockCuePen = new Pen(dockCueBrush, 10);
			e.Graphics.DrawRectangle(dockCuePen, new Rectangle(pnlRight.Left, pnlRight.Top, pnlRight.Width, pnlRight.Height));
		}

		private void miUndo_Click(object sender, System.EventArgs e)
		{
			UndoLastAction();
		}

		private void miRedo_Click(object sender, System.EventArgs e)
		{
			RedoAction();
		}

		private void miCloseArmy_Click(object sender, EventArgs e)
		{
			CloseCurrentArmy();
		}

		private void miOpenArmy_Click(object sender, EventArgs e)
		{
			OpenArmy();
		}

		private void FrmMain_PointsValueChangedMethod(WarFoundryObject obj, double oldVal, double newVal)
		{
			if (obj is Army)
			{
				SetPointsPanelText();
			}
		}

		private void SetPointsPanelText()
		{	
			if (CurrentArmy==null)
			{
				sbPointsPanel.Text = "";
				sbPointsPanel.ResetColor();
			}
			else 
			{
				sbPointsPanel.Text = String.Format(Translation.GetTranslation("statusPanelPoints"), CurrentArmy.Points, CurrentArmy.MaxPoints);

				if (CurrentArmy.Points>CurrentArmy.MaxPoints)
				{
					sbPointsPanel.Color = Color.Red;
				}
				else
				{
					sbPointsPanel.ResetColor();
				}
			}
		}

		private void redoMenu_Click(object sender, EventArgs e)
		{
			if (sender is MenuItem)
			{
				MenuItem mi = (MenuItem)sender;

				if (mi.Parent == redoMenu)
				{
					//we know it's an redo menu item so find it's index and redo everything					
					int max = mi.Index;

					for (int i = 0; i <= max; i++)
					{
						commandStack.Redo();
					}
				}
			}
		}

		private void undoMenu_Click(object sender, EventArgs e)
		{
			if (sender is MenuItem)
			{
				MenuItem mi = (MenuItem)sender;

				if (mi.Parent == undoMenu)
				{
					//we know it's an undo menu item so find it's index and undo everything
					int max = mi.Index;
					for (int i = 0; i <= max; i++)
					{
						commandStack.Undo();
					}
				}
			}
		}

		private void statusBar_DrawItem(object sender, System.Windows.Forms.StatusBarDrawItemEventArgs sbdevent)
		{
			statusBar.ColorableStatusBarDrawItem(sender, sbdevent);
		}

		private void FrmMain_Closing(object sender, CancelEventArgs e)
		{
			if (!CloseCurrentArmy())
			{
				e.Cancel = true;
			}
		}

		private void miReloadFiles_Click(object sender, System.EventArgs e)
		{
			WarFoundryLoader.GetDefault().LoadFiles();
			sbMainPanel.Text = Translation.GetTranslation("GameSystemFilesReloaded", "Game system and race files reloaded");
			statusBarTimer.Enabled = true;
		}

		private void statusBarTimer_Tick(object sender, System.EventArgs e)
		{
			sbMainPanel.Text = "";
			statusBarTimer.Enabled = false;
		}

		private void statusBar_PanelClick(object sender, StatusBarPanelClickEventArgs e)
		{
			if (e.StatusBarPanel == sbErrorPanel && sbErrorPanel.Text!="")
			{
				MessageBox.Show(this, sbErrorPanel.TagString, Translation.GetTranslation("FailedRequirementMessage"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
			}
		}

		private void miExportArmyAsBasicHTML_Click(object sender, EventArgs e)
		{
			SaveFileDialog dialog = new SaveFileDialog();
			dialog.Filter = Translation.GetTranslation("armyExportBasicHtmlFilter", "HTML pages") + "|*.html";
			dialog.Title = Translation.GetTranslation("exportArmyDialog", "Export army");

			DialogResult dr = dialog.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				Army army = CurrentArmy;
				string filePath = dialog.FileName;
				logger.DebugFormat("Exporting {0} to {1} as basic HTML", army.Name, filePath);
				WarFoundryHtmlExporter.GetDefault().ExportArmy(army, filePath);
			}
		}
	}
}