view FrmMain.cs @ 137:ce63500e0ec1

Re #260: New panels don't work perfectly in Linux through Mono * Debug ToolStrip width and button widths
author IBBoard <dev@ibboard.co.uk>
date Sat, 03 Apr 2010 20:06:33 +0000
parents c095c57a56f9
children 60c795eca8de
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.1b8pre";
        const string DefaultDataDir = "data";

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

		private CommandStack commandStack;

		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.OpenFileDialog openArmyDialog;
		private System.Windows.Forms.SaveFileDialog saveArmyDialog;
		private System.Windows.Forms.MainMenu mainMenu;
		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 MenuStrip menuStrip;
		private IBBToolStripMenuItem menuFile;
		private IBBToolStripMenuItem miNewArmy;
		private IBBToolStripMenuItem miOpenArmy;
		private IBBToolStripMenuItem miSaveArmy;
		private IBBToolStripMenuItem miSaveArmyAs;
		private IBBToolStripMenuItem miExportArmyAs;
		private IBBToolStripMenuItem miExportArmyAsBasicHTML;
		private IBBToolStripMenuItem miCloseArmy;
		private ToolStripSeparator toolStripSeparator1;
		private IBBToolStripMenuItem miReloadFiles;
		private ToolStripSeparator toolStripSeparator2;
		private IBBToolStripMenuItem miExit;
		private IBBToolStripMenuItem menuEdit;
		private IBBToolStripMenuItem miUndo;
		private IBBToolStripMenuItem miRedo;
		private IBBToolStripMenuItem menuHelp;
		private ToolStrip mainToolStrip;
		private IBBToolStripButton bttnNewArmy;
		private IBBToolStripButton bttnOpenArmy;
		private IBBToolStripButton bttnSaveArmy;
		private ToolStripSeparator toolStripSeparator3;
		private IBBToolStripSplitButton bttnUndo;
		private IBBToolStripSplitButton bttnRedo;
		private ToolStrip catToolStrip;
		private ToolStripPanel toolStripPanel;
		private IBBToolStripMenuItem miAbout;

		/// <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();
			toolStripPanel.Join(mainToolStrip, 0, 0);
			toolStripPanel.Join(catToolStrip, mainToolStrip.Right, 0);

			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);
			}

			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 Environment.GetFolderPath(Environment.SpecialFolder.Personal); }
		}

		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.undoMenu = new System.Windows.Forms.ContextMenu();
			this.redoMenu = new System.Windows.Forms.ContextMenu();
			this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
			this.openArmyDialog = new System.Windows.Forms.OpenFileDialog();
			this.saveArmyDialog = new System.Windows.Forms.SaveFileDialog();
			this.statusBarTimer = new System.Windows.Forms.Timer(this.components);
			this.menuStrip = new System.Windows.Forms.MenuStrip();
			this.menuFile = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miNewArmy = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miOpenArmy = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miSaveArmy = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miSaveArmyAs = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miExportArmyAs = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miExportArmyAsBasicHTML = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miCloseArmy = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
			this.miReloadFiles = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
			this.miExit = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.menuEdit = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miUndo = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miRedo = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.menuHelp = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.miAbout = new IBBoard.Windows.Forms.IBBToolStripMenuItem();
			this.mainToolStrip = new System.Windows.Forms.ToolStrip();
			this.bttnNewArmy = new IBBoard.Windows.Forms.IBBToolStripButton();
			this.bttnOpenArmy = new IBBoard.Windows.Forms.IBBToolStripButton();
			this.bttnSaveArmy = new IBBoard.Windows.Forms.IBBToolStripButton();
			this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
			this.bttnUndo = new IBBoard.Windows.Forms.IBBToolStripSplitButton();
			this.bttnRedo = new IBBoard.Windows.Forms.IBBToolStripSplitButton();
			this.catToolStrip = new System.Windows.Forms.ToolStrip();
			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.toolStripPanel = new System.Windows.Forms.ToolStripPanel();
			this.menuStrip.SuspendLayout();
			this.mainToolStrip.SuspendLayout();
			((System.ComponentModel.ISupportInitialize) (this.sbMainPanel)).BeginInit();
			((System.ComponentModel.ISupportInitialize) (this.sbErrorPanel)).BeginInit();
			((System.ComponentModel.ISupportInitialize) (this.sbPointsPanel)).BeginInit();
			this.SuspendLayout();
			// 
			// saveArmyDialog
			// 
			this.saveArmyDialog.Title = "Translatable:saveArmyDialog";
			// 
			// statusBarTimer
			// 
			this.statusBarTimer.Interval = 5000;
			this.statusBarTimer.Tick += new System.EventHandler(this.statusBarTimer_Tick);
			// 
			// menuStrip
			// 
			this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.menuFile,
            this.menuEdit,
            this.menuHelp});
			this.menuStrip.Location = new System.Drawing.Point(0, 0);
			this.menuStrip.Name = "menuStrip";
			this.menuStrip.Size = new System.Drawing.Size(790, 24);
			this.menuStrip.TabIndex = 6;
			this.menuStrip.Text = "menuStrip1";
			// 
			// menuFile
			// 
			this.menuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miNewArmy,
            this.miOpenArmy,
            this.miSaveArmy,
            this.miSaveArmyAs,
            this.miExportArmyAs,
            this.miCloseArmy,
            this.toolStripSeparator1,
            this.miReloadFiles,
            this.toolStripSeparator2,
            this.miExit});
			this.menuFile.Name = "menuFile";
			this.menuFile.Size = new System.Drawing.Size(33, 20);
			this.menuFile.Text = "&file";
			// 
			// miNewArmy
			// 
			this.miNewArmy.Name = "miNewArmy";
			this.miNewArmy.Size = new System.Drawing.Size(164, 22);
			this.miNewArmy.Text = "&new army";
			this.miNewArmy.Click += new System.EventHandler(this.miNewArmy_Click);
			// 
			// miOpenArmy
			// 
			this.miOpenArmy.Name = "miOpenArmy";
			this.miOpenArmy.Size = new System.Drawing.Size(164, 22);
			this.miOpenArmy.Text = "&open army";
			this.miOpenArmy.Click += new System.EventHandler(this.miOpenArmy_Click);
			// 
			// miSaveArmy
			// 
			this.miSaveArmy.Enabled = false;
			this.miSaveArmy.Name = "miSaveArmy";
			this.miSaveArmy.Size = new System.Drawing.Size(164, 22);
			this.miSaveArmy.Text = "&save army";
			this.miSaveArmy.Click += new System.EventHandler(this.miSaveArmy_Click);
			// 
			// miSaveArmyAs
			// 
			this.miSaveArmyAs.Enabled = false;
			this.miSaveArmyAs.Name = "miSaveArmyAs";
			this.miSaveArmyAs.Size = new System.Drawing.Size(164, 22);
			this.miSaveArmyAs.Text = "save army &as...";
			this.miSaveArmyAs.Click += new System.EventHandler(this.miSaveArmyAs_Click);
			// 
			// miExportArmyAs
			// 
			this.miExportArmyAs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miExportArmyAsBasicHTML});
			this.miExportArmyAs.Enabled = false;
			this.miExportArmyAs.Name = "miExportArmyAs";
			this.miExportArmyAs.Size = new System.Drawing.Size(164, 22);
			this.miExportArmyAs.Text = "export army as...";
			// 
			// miExportArmyAsBasicHTML
			// 
			this.miExportArmyAsBasicHTML.Name = "miExportArmyAsBasicHTML";
			this.miExportArmyAsBasicHTML.Size = new System.Drawing.Size(130, 22);
			this.miExportArmyAsBasicHTML.Text = "&basic html";
			this.miExportArmyAsBasicHTML.Click += new System.EventHandler(this.miExportArmyAsBasicHTML_Click);
			// 
			// miCloseArmy
			// 
			this.miCloseArmy.Enabled = false;
			this.miCloseArmy.Name = "miCloseArmy";
			this.miCloseArmy.Size = new System.Drawing.Size(164, 22);
			this.miCloseArmy.Text = "&close army";
			this.miCloseArmy.Click += new System.EventHandler(this.miCloseArmy_Click);
			// 
			// toolStripSeparator1
			// 
			this.toolStripSeparator1.Name = "toolStripSeparator1";
			this.toolStripSeparator1.Size = new System.Drawing.Size(161, 6);
			// 
			// miReloadFiles
			// 
			this.miReloadFiles.Name = "miReloadFiles";
			this.miReloadFiles.Size = new System.Drawing.Size(164, 22);
			this.miReloadFiles.Text = "&reload files";
			this.miReloadFiles.Click += new System.EventHandler(this.miReloadFiles_Click);
			// 
			// toolStripSeparator2
			// 
			this.toolStripSeparator2.Name = "toolStripSeparator2";
			this.toolStripSeparator2.Size = new System.Drawing.Size(161, 6);
			// 
			// miExit
			// 
			this.miExit.Name = "miExit";
			this.miExit.Size = new System.Drawing.Size(164, 22);
			this.miExit.Text = "e&xit";
			this.miExit.Click += new System.EventHandler(this.miExit_Click);
			// 
			// menuEdit
			// 
			this.menuEdit.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miUndo,
            this.miRedo});
			this.menuEdit.Name = "menuEdit";
			this.menuEdit.Size = new System.Drawing.Size(36, 20);
			this.menuEdit.Text = "&edit";
			// 
			// miUndo
			// 
			this.miUndo.Enabled = false;
			this.miUndo.Name = "miUndo";
			this.miUndo.Size = new System.Drawing.Size(106, 22);
			this.miUndo.Text = "&undo";
			this.miUndo.Click += new System.EventHandler(this.miUndo_Click);
			// 
			// miRedo
			// 
			this.miRedo.Enabled = false;
			this.miRedo.Name = "miRedo";
			this.miRedo.Size = new System.Drawing.Size(106, 22);
			this.miRedo.Text = "&redo";
			this.miRedo.Click += new System.EventHandler(this.miRedo_Click);
			// 
			// menuHelp
			// 
			this.menuHelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miAbout});
			this.menuHelp.Name = "menuHelp";
			this.menuHelp.Size = new System.Drawing.Size(39, 20);
			this.menuHelp.Text = "&help";
			// 
			// miAbout
			// 
			this.miAbout.Name = "miAbout";
			this.miAbout.Size = new System.Drawing.Size(109, 22);
			this.miAbout.Text = "&about";
			this.miAbout.Click += new System.EventHandler(this.miAbout_Click);
			// 
			// mainToolStrip
			// 
			this.mainToolStrip.Dock = System.Windows.Forms.DockStyle.None;
			this.mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.bttnNewArmy,
            this.bttnOpenArmy,
            this.bttnSaveArmy,
            this.toolStripSeparator3,
            this.bttnUndo,
            this.bttnRedo});
			this.mainToolStrip.Location = new System.Drawing.Point(0, 24);
			this.mainToolStrip.Name = "mainToolStrip";
			this.mainToolStrip.Size = new System.Drawing.Size(151, 25);
			this.mainToolStrip.TabIndex = 8;
			// 
			// bttnNewArmy
			// 
			this.bttnNewArmy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
			this.bttnNewArmy.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.document_new;
			this.bttnNewArmy.ImageTransparentColor = System.Drawing.Color.Magenta;
			this.bttnNewArmy.Name = "bttnNewArmy";
			this.bttnNewArmy.Size = new System.Drawing.Size(23, 22);
			this.bttnNewArmy.Text = "new army";
			this.bttnNewArmy.Click += new System.EventHandler(this.miNewArmy_Click);
			// 
			// bttnOpenArmy
			// 
			this.bttnOpenArmy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
			this.bttnOpenArmy.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.document_open;
			this.bttnOpenArmy.ImageTransparentColor = System.Drawing.Color.Magenta;
			this.bttnOpenArmy.Name = "bttnOpenArmy";
			this.bttnOpenArmy.Size = new System.Drawing.Size(23, 22);
			this.bttnOpenArmy.Text = "open army";
			this.bttnOpenArmy.Click += new System.EventHandler(this.miOpenArmy_Click);
			// 
			// bttnSaveArmy
			// 
			this.bttnSaveArmy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
			this.bttnSaveArmy.Enabled = false;
			this.bttnSaveArmy.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.document_save;
			this.bttnSaveArmy.ImageTransparentColor = System.Drawing.Color.Magenta;
			this.bttnSaveArmy.Name = "bttnSaveArmy";
			this.bttnSaveArmy.Size = new System.Drawing.Size(23, 22);
			this.bttnSaveArmy.Text = "save army";
			this.bttnSaveArmy.Click += new System.EventHandler(this.miSaveArmy_Click);
			// 
			// toolStripSeparator3
			// 
			this.toolStripSeparator3.Name = "toolStripSeparator3";
			this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25);
			// 
			// bttnUndo
			// 
			this.bttnUndo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
			this.bttnUndo.Enabled = false;
			this.bttnUndo.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.edit_undo;
			this.bttnUndo.ImageTransparentColor = System.Drawing.Color.Magenta;
			this.bttnUndo.Name = "bttnUndo";
			this.bttnUndo.Size = new System.Drawing.Size(32, 22);
			this.bttnUndo.Text = "undo";
			this.bttnUndo.ButtonClick += new System.EventHandler(this.miUndo_Click);
			// 
			// bttnRedo
			// 
			this.bttnRedo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
			this.bttnRedo.Enabled = false;
			this.bttnRedo.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.edit_redo;
			this.bttnRedo.ImageTransparentColor = System.Drawing.Color.Magenta;
			this.bttnRedo.Name = "bttnRedo";
			this.bttnRedo.Size = new System.Drawing.Size(32, 22);
			this.bttnRedo.Text = "redo";
			this.bttnRedo.ButtonClick += new System.EventHandler(this.miRedo_Click);
			// 
			// catToolStrip
			// 
			this.catToolStrip.Dock = System.Windows.Forms.DockStyle.None;
			this.catToolStrip.Location = new System.Drawing.Point(161, 24);
			this.catToolStrip.Name = "catToolStrip";
			this.catToolStrip.Size = new System.Drawing.Size(111, 25);
			this.catToolStrip.TabIndex = 9;
			this.catToolStrip.Visible = false;
			// 
			// statusBar
			// 
			this.statusBar.Location = new System.Drawing.Point(0, 586);
			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;
			// 
			// toolStripPanel
			// 
			this.toolStripPanel.Dock = System.Windows.Forms.DockStyle.Top;
			this.toolStripPanel.Location = new System.Drawing.Point(0, 24);
			this.toolStripPanel.Name = "toolStripPanel";
			this.toolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal;
			this.toolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0);
			this.toolStripPanel.Size = new System.Drawing.Size(790, 0);
			// 
			// FrmMain
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(790, 608);
			this.Controls.Add(this.mainToolStrip);
			this.Controls.Add(this.toolStripPanel);
			this.Controls.Add(this.statusBar);
			this.Controls.Add(this.catToolStrip);
			this.Controls.Add(this.menuStrip);
			this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
			this.IsMdiContainer = true;
			this.MainMenuStrip = this.menuStrip;
			this.Menu = this.mainMenu;
			this.Name = "FrmMain";
			this.Text = "WarFoundry";
			this.Load += new System.EventHandler(this.FrmMain_Load);
			this.menuStrip.ResumeLayout(false);
			this.menuStrip.PerformLayout();
			this.mainToolStrip.ResumeLayout(false);
			this.mainToolStrip.PerformLayout();
			((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;
			}
		}

		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();
		}

		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
			{
				WarFoundryCore.CurrentGameSystem = newArmy.GameSystem;
				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)
		{
			SetCategoryButtons(newArmy.Race.Categories);
			EnableCategoryButtons();
			miSaveArmyAs.Enabled = true;
			miCloseArmy.Enabled = true;
			miExportArmyAs.Enabled = true;
			armyTree.Show();
		}

		private void SetCategoryButtons(Category[] cats)
		{
			if (CategoryButtonsHaveChanged(cats))
			{
				RemoveCategoryButtons();
				AddCategoryButtons(cats);
			}
		}

		private bool CategoryButtonsHaveChanged(Category[] cats)
		{
			int catCount = cats.Length;
			ToolStripItemCollection items = catToolStrip.Items;
			bool haveChanged = (!catToolStrip.Visible || catCount != items.Count);

			if (!haveChanged)
			{
				for (int i = 0; i < catCount; i++)
				{
					if (cats[i].Equals(items[i+1].Tag))
					{
						haveChanged = true;
						break;
					}
				}
			}

			return haveChanged;
		}

		private void RemoveCategoryButtons()
		{
			this.Invoke(new MethodInvoker(catToolStrip.Items.Clear));
		}

		private void AddCategoryButtons(Category[] cats)
		{
			int catCount = cats.Length;
			Category cat;
			IBBToolStripButton[] categoryButtons = new IBBToolStripButton[catCount];
			int buttonWidths = 0;

			for (int i = 0; i < catCount; i++)
			{
				cat = cats[i];
				IBBToolStripButton button = new IBBToolStripButton();
				button.Text = cat.Name;
				button.Tag = cat;
				button.Image = global::IBBoard.WarFoundry.GUI.WinForms.Properties.Resources.list_add;
				button.Enabled = false;
				button.Click += new EventHandler(CreateUnitForCategoryButtonClick);
				categoryButtons[i] = button;
				buttonWidths += button.Width;
			}

			log.Debug("Toolstrip width: " + catToolStrip.Width);
			log.Debug("Button widths: " + buttonWidths);

			this.Invoke(new ArrayMethodInvoker<IBBToolStripButton>(catToolStrip.Items.AddRange), new object[]{ categoryButtons });
		}

		private void CreateUnitForCategoryButtonClick(object sender, EventArgs e)
		{
			if (sender is IBBToolStripButton)
			{
				IBBToolStripButton button = (IBBToolStripButton)sender;
				object tag = button.Tag;

				if (tag is Category)
				{
					AddUnitFromCategory((Category)tag);
				}
			}
		}

		private void EnableCategoryButtons()
		{
			catToolStrip.Visible = true;
			SetCategoryButtonState(true);
		}

		private void DisableCategoryButtons()
		{
			catToolStrip.Visible = false;
			SetCategoryButtonState(false);
		}

		private void SetCategoryButtonState(bool state)
		{
			foreach (IBBToolStripButton button in catToolStrip.Items)
			{
				button.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;

			PopulateRedoMenu();
			PopulateUndoMenu();

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

		private void PopulateRedoMenu()
		{
			int redoLength = commandStack.RedoLength;
			int maxRedo = Math.Min(10, redoLength);
			ToolStripItemCollection dropDownItems = bttnRedo.DropDownItems;
			dropDownItems.Clear();

			for (int i = 1; i <= maxRedo; i++)
			{
				Command cmd = commandStack.PeekRedoCommand(i);

				if (cmd == null)
				{
					break;
				}

				dropDownItems.Add(cmd.Description, null, redoMenu_Click);
			}

			if (redoLength > 0)
			{
				bttnRedo.Text = commandStack.PeekRedoCommand(1).Description;
			}
			else
			{
				bttnRedo.Text = Translation.GetTranslation("bttnRedo");
			}
		}

		private void PopulateUndoMenu()
		{
			int undoLength = commandStack.UndoLength;
			int maxUndo = Math.Min(10, undoLength);
			ToolStripItemCollection dropDownItems = bttnUndo.DropDownItems;
			dropDownItems.Clear();

			for (int i = 1; i <= maxUndo; i++)
			{
				Command cmd = commandStack.PeekUndoCommand(i);

				if (cmd == null)
				{
					break;
				}

				dropDownItems.Add(cmd.UndoDescription, null, undoMenu_Click);
			}

			if (undoLength > 0)
			{
				bttnUndo.Text = commandStack.PeekUndoCommand(1).UndoDescription;
			}
			else
			{
				bttnUndo.Text = Translation.GetTranslation("bttnUndo");
			}
		}

		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;
			}
		}*/

		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 ToolStripDropDownItem)
			{
				ToolStripDropDownItem item = (ToolStripDropDownItem)sender;
					//we know it's an redo menu item so find it's index and redo everything					
				int max = bttnRedo.DropDownItems.IndexOf(item);

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

		private void undoMenu_Click(object sender, EventArgs e)
		{
			if (sender is ToolStripDropDownItem)
			{
				ToolStripDropDownItem item = (ToolStripDropDownItem)sender;
				//we know it's an redo menu item so find it's index and redo everything					
				int max = bttnUndo.DropDownItems.IndexOf(item);

				if (max >= 0)
				{
					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);
		}
	}
}