view FrmMain.cs @ 114:727c1b0e49a6

Fixes #115: Typing number for equipment amount doesn't update Okay button * Remove KeyDown capture code (AcceptButton functionality captures the key press first) * Add ProcessDialogKey method that uses ValueChanged helper class to determine whether the control changes when we force an update New functionality is that the values can be typed and changed by pressing Enter, then a second Enter will accept the changes and close the dialog. If no changes were made then pressing Enter once accepts changes and closes the dialog.
author IBBoard <dev@ibboard.co.uk>
date Thu, 24 Dec 2009 12:04:32 +0000
parents 39b93ca5fb9c
children 9c5f7c5b0f1c
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";
		internal static readonly string VERSION = "0.1b6pre";
        const string DefaultDataDir = "data";

		private Preferences preferences;
		private readonly ILog log = 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 IBBoard.Windows.Forms.IBBMenuItem miExportArmyAs;
		private IBBoard.Windows.Forms.IBBMenuItem miExportArmyAsBasicHTML;
		private System.Windows.Forms.Panel pnlRight;

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			try
			{
				LogManager.GetLogger(typeof(FrmMain)).Info("Starting WarFoundry WinForms");
				Application.EnableVisualStyles();
				Application.Run(new FrmMain(args));
				LogManager.GetLogger(typeof(FrmMain)).Info("Closing WarFoundry WinForms");
			}
			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)
			{
				log.Error("Translation loading failed for language " + Preferences["language"].ToString(), 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;

			ControlTranslator.TranslateControls(Controls);
			ControlTranslator.TranslateComponents(components.Components);
			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;
			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);
            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 IBBoard.Windows.Forms.IBBMenuItem();
			this.miExportArmyAsBasicHTML = new IBBoard.Windows.Forms.IBBMenuItem();
			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 = 473;
			// 
			// 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";
			this.menuFile.Name = "menuFile";
			// 
			// miNewArmy
			// 
			this.miNewArmy.Index = 0;
			this.miNewArmy.Text = "&new army";
			this.miNewArmy.Click += new System.EventHandler(this.miNewArmy_Click);
			this.miNewArmy.Name = "miNewArmy";
			// 
			// miOpenArmy
			// 
			this.miOpenArmy.Index = 1;
			this.miOpenArmy.Text = "&open army";
			this.miOpenArmy.Click += new System.EventHandler(this.miOpenArmy_Click);
			this.miOpenArmy.Name = "miOpenArmy";
			// 
			// miSaveArmy
			// 
			this.miSaveArmy.Enabled = false;
			this.miSaveArmy.Index = 2;
			this.miSaveArmy.Text = "&save army";
			this.miSaveArmy.Click += new System.EventHandler(this.miSaveArmy_Click);
			this.miSaveArmy.Name = "miSaveArmy";
			// 
			// miSaveArmyAs
			// 
			this.miSaveArmyAs.Enabled = false;
			this.miSaveArmyAs.Index = 3;
			this.miSaveArmyAs.Text = "save army &as...";
			this.miSaveArmyAs.Click += new System.EventHandler(this.miSaveArmyAs_Click);
			this.miSaveArmyAs.Name = "miSaveArmyAs";
			// 
			// 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...";
			this.miExportArmyAs.Name = "miExportArmyAs";
			// 
			// miExportArmyAsBasicHTML
			// 
			this.miExportArmyAsBasicHTML.Index = 0;
			this.miExportArmyAsBasicHTML.Text = "basic html";
			this.miExportArmyAsBasicHTML.Click += new System.EventHandler(this.miExportArmyAsBasicHTML_Click);
			this.miExportArmyAsBasicHTML.Name = "miExportArmyAsBasicHTML";
			// 
			// miCloseArmy
			// 
			this.miCloseArmy.Enabled = false;
			this.miCloseArmy.Index = 5;
			this.miCloseArmy.Text = "&close army";
			this.miCloseArmy.Click += new System.EventHandler(this.miCloseArmy_Click);
			this.miCloseArmy.Name = "miCloseArmy";
			// 
			// 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);
			this.miReloadFiles.Name = "miReloadFiles";
			// 
			// 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);
			this.miExit.Name = "miExit";
			// 
			// menuEdit
			// 
			this.menuEdit.Index = 1;
			this.menuEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miUndo,
            this.miRedo});
			this.menuEdit.Text = "&edit";
			this.menuEdit.Name = "menuEdit";
			// 
			// miUndo
			// 
			this.miUndo.Enabled = false;
			this.miUndo.Index = 0;
			this.miUndo.Text = "&undo";
			this.miUndo.Click += new System.EventHandler(this.miUndo_Click);
			this.miUndo.Name = "miUndo";
			// 
			// miRedo
			// 
			this.miRedo.Enabled = false;
			this.miRedo.Index = 1;
			this.miRedo.Text = "&redo";
			this.miRedo.Click += new System.EventHandler(this.miRedo_Click);
			this.miRedo.Name = "miRedo";
			// 
			// menuHelp
			// 
			this.menuHelp.Index = 2;
			this.menuHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miAbout});
			this.menuHelp.Text = "&help";
			this.menuHelp.Name = "menuHelp";
			// 
			// miAbout
			// 
			this.miAbout.Index = 0;
			this.miAbout.Text = "&about";
			this.miAbout.Name = "miAbout";
			this.miAbout.Click += new System.EventHandler(this.miAbout_Click);
			// 
			// 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";
			this.Load += new System.EventHandler(this.FrmMain_Load);
			((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)
			{
				log.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)
				{
					try
					{
						CurrentArmy = new Army(newArmy.SelectedRace, newArmy.ArmyName, newArmy.ArmySize);
					}
					catch (RequiredDataMissingException ex)
					{
						log.Error("Required data missing from race file", ex);
						MessageBox.Show(this, ex.Message, Translation.GetTranslation("InvalidRaceFileBoxTitle", "invalid race file"), MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
					catch (InvalidFileException ex)
					{
						log.Error("Race file was invalid", ex);
						MessageBox.Show(this, ex.Message, Translation.GetTranslation("InvalidRaceFileBoxTitle", "invalid race file"), MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
		}

		private bool OpenArmy()
		{
			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)
			{
				if (CloseCurrentArmy())
				{
					try
					{
						string newFilePath = openArmyDialog.FileName;
						CurrentArmy = WarFoundryLoader.GetDefault().LoadArmy(new FileInfo(newFilePath));
						loadedFilePath = newFilePath;
						return true;
					}
					catch (RequiredDataMissingException ex)
					{
						log.Error(ex);
						MessageBox.Show(this, ex.Message, Translation.GetTranslation("InvalidArmyFileBoxTitle", "invalid army file"), MessageBoxButtons.OK, MessageBoxIcon.Error);
						return false;
					}
					catch (InvalidFileException ex)
					{
						log.Error(ex);
						MessageBox.Show(this, ex.Message, Translation.GetTranslation("InvalidArmyFileBoxTitle", "invalid army 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())
				{
					string saveChanges = Translation.GetTranslation("SaveChangesQuestion", "the army \"{0}\" has been modified\r\nsave changes before closing army?", CurrentArmy.Name);
					string saveChangesTitle = Translation.GetTranslation("SaveChangesTitle", "unsaved changes");
					DialogResult dr = MessageBox.Show(this, saveChanges, saveChangesTitle, 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", "file save failed - check log for details"), Translation.GetTranslation("SaveFailedTitle", "file save failed"), 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 GameSystem CurrentGameSystem
		{
			get { return WarFoundryCore.CurrentGameSystem; }
			set { WarFoundryCore.CurrentGameSystem = value; }
		}

		public Army CurrentArmy
		{
			get { return WarFoundryCore.CurrentArmy; }
			set { SetArmy(value); }
		}

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

		private void FrmMain_ArmyChanged(Army oldArmy, Army newArmy)
		{
			CommandStack.Reset();
			loadedFilePath = null;
			miSaveArmy.Enabled = false;
			bttnSaveArmy.Enabled = false;
			SetPointsPanelText();
			SetAppTitle();
		}

		private void SetArmy(Army newArmy)
		{
			IgnoreArmy(CurrentArmy);
			CloseAllUnitWindows();

			if (newArmy == null)
			{
				SetNullArmyState();
			}
			else
			{
				ListenToArmy(newArmy);
				SetNonNullArmyState(newArmy);
			}
			
			WarFoundryCore.CurrentArmy = newArmy;
		}

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

		private void CloseAllUnitWindows()
		{
			FrmUnit[] unitForms = DictionaryUtils.ToArray(unitWindows);

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

			unitWindows.Clear();
		}

		private void ListenToArmy(Army newArmy)
		{
			if (newArmy != null)
			{
				newArmy.UnitAdded += UnitAddedMethod;
				newArmy.UnitRemoved += UnitRemovedMethod;
				newArmy.PointsValueChanged += PointsValueChangedMethod;
			}
		}

		private void SetNullArmyState()
		{
			miSaveArmyAs.Enabled = false;
			miCloseArmy.Enabled = false;
			miExportArmyAs.Enabled = false;
			DisableCategoryButtons();
			armyTree.Hide();
		}

		private void SetNonNullArmyState(Army newArmy)
		{
			if (newArmy.Race.HasCategoryOverrides())
			{
				RemoveCategoryButtons();
				AddCategoryButtons(newArmy.Race.Categories);
			}

			EnableCategoryButtons();
			miSaveArmyAs.Enabled = true;
			miCloseArmy.Enabled = true;
			miExportArmyAs.Enabled = true;
			armyTree.Show();
		}

		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;
				log.DebugFormat("Exporting {0} to {1} as basic HTML", army.Name, filePath);
				WarFoundryHtmlExporter.GetDefault().ExportArmy(army, filePath);
			}
		}

		private void FrmMain_Load(object sender, EventArgs e)
		{
			string gameSystemID = Preferences.GetStringProperty("currSystem");

			if (gameSystemID != null && !"".Equals(gameSystemID))
			{
				log.Debug("Attempting to load current game system from properties");
				GameSystem sys = WarFoundryLoader.GetDefault().GetGameSystem(gameSystemID);

				if (sys != null)
				{
					WarFoundryCore.CurrentGameSystem = sys;
					log.InfoFormat("Loaded game system {0} from properties", gameSystemID);
				}
			}
		}

		private void miAbout_Click(object sender, EventArgs e)
		{
			FrmAbout about = new FrmAbout();
			about.ShowDialog(this);
		}
	}
}