root/IBBoard.WarFoundry.GUI.GTK/trunk/FrmMainWindow.cs @ 145

Revision 145, 25.2 KB (checked in by ibboard, 15 months ago)
  • Fix line terminators

no-open-ticket

Line 
1// This file (FrmMainWindow.cs) is a part of the IBBoard.WarFoundry.GTK project and is copyright 2009 IBBoard.
2//
3// The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license.
4
5using System;
6using System.IO;
7using System.Collections.Generic;
8using System.Configuration;
9using Gtk;
10using IBBoard;
11using IBBoard.Commands;
12using IBBoard.GtkSharp;
13using IBBoard.IO;
14using IBBoard.Lang;
15using IBBoard.Logging;
16using IBBoard.CustomMath;
17using IBBoard.Log4Net;
18using IBBoard.WarFoundry.API;
19using IBBoard.WarFoundry.API.Factories;
20using IBBoard.WarFoundry.API.Factories.Xml;
21using IBBoard.WarFoundry.API.Objects;
22using IBBoard.WarFoundry.API.Commands;
23using IBBoard.WarFoundry.API.Savers;
24using IBBoard.WarFoundry.API.Requirements;
25using IBBoard.WarFoundry.GTK.Widgets;
26using IBBoard.WarFoundry.Plugin.Rollcall;
27using IBBoard.Xml;
28using log4net;
29
30namespace IBBoard.WarFoundry.GTK
31{   
32    public partial class FrmMainWindow: Gtk.Window
33    {
34        private static readonly string AppTitle = "WarFoundry";
35        private const int CATEGORY_BUTTON_SEPARATOR_INDEX = 6;
36
37        private Preferences preferences;
38        private ILog logger = LogManager.GetLogger(typeof(FrmMainWindow));
39
40        private CommandStack commandStack;
41        private Dictionary<ToolButton, Category> categoryMap = new Dictionary<ToolButton, Category>();
42        private Dictionary<IBBoard.WarFoundry.API.Objects.Unit, UnitDisplayWidget> unitToWidgetMap = new Dictionary<IBBoard.WarFoundry.API.Objects.Unit,UnitDisplayWidget>();
43
44        private ObjectAddDelegate UnitAddedMethod;
45        private ObjectRemoveDelegate UnitRemovedMethod;
46        private DoubleValChangedDelegate PointsValueChangedMethod;
47        private FailedUnitRequirementDelegate FailedUnitRequirementMethod;
48        private StringValChangedDelegate UnitNameChangedMethod;
49       
50        private GameSystem system;
51        private string loadedArmyPath;
52       
53        private MenuToolButton undoMenuButton, redoMenuButton;
54       
55        public static void Main (string[] args)
56        {           
57            try
58            {
59                Application.Init();
60                FrmMainWindow win = new FrmMainWindow(args);
61                win.Show();
62                Application.Run();
63                LogManager.GetLogger(typeof(FrmMainWindow)).Debug("Application ended");
64            }
65            catch(Exception ex)
66            {
67                LogManager.GetLogger(typeof(FrmMainWindow)).Fatal("("+ex.GetType().Name+") "+ex.Message + Environment.NewLine + ex.StackTrace);
68            }
69        }
70       
71        public FrmMainWindow() : this(new string[0])
72        {
73            //Do nothing extra
74        }
75           
76        public FrmMainWindow (string[] args): base (Gtk.WindowType.Toplevel)
77        {
78            logger.Info("Opening FrmMainWindow");
79            LogNotifierHandler.RegisterNotifierHandler();
80            Build ();
81            //Replace the undo/redo buttons with menu versions, which Monodevelop's GUI editor doesn't currently support
82            redoMenuButton = new MenuToolButton("gtk-redo");
83            redoMenuButton.Label = "Redo";
84            redoMenuButton.TooltipText = "Redo";
85            redoMenuButton.Clicked+= redoTBButtonActivated;
86            toolbar.Insert(redoMenuButton, CATEGORY_BUTTON_SEPARATOR_INDEX);
87            undoMenuButton = new MenuToolButton("gtk-undo");
88            undoMenuButton.Label = "Undo";
89            undoMenuButton.TooltipText = "Undo";
90            undoMenuButton.Clicked+= undoTBButtonActivated;
91            toolbar.Insert(undoMenuButton, CATEGORY_BUTTON_SEPARATOR_INDEX);
92            toolbar.Remove(toolbar.Children[CATEGORY_BUTTON_SEPARATOR_INDEX-1]);
93            toolbar.Remove(toolbar.Children[CATEGORY_BUTTON_SEPARATOR_INDEX-2]);
94            toolbar.ShowAll();
95           
96            Title = AppTitle;
97            TreeViewColumn mainColumn = new TreeViewColumn ();
98            mainColumn.Title = "Army Categories";
99            CellRendererText mainCell = new CellRendererText ();
100            mainColumn.PackStart (mainCell, true);
101            treeUnits.AppendColumn(mainColumn);
102            mainColumn.SetCellDataFunc(mainCell, new TreeCellDataFunc(RenderCategoryTreeObjectName));
103            treeUnits.Model = new TreeStore(typeof(WarFoundryObject));
104            logger.Debug("Loading preferences");
105            Preferences = new Preferences("WarFoundryGTK");
106            logger.Debug("Loading translations");
107           
108            try
109            {
110                Translation.InitialiseTranslations(Constants.ExecutablePath, Preferences["language"].ToString());
111            }
112            catch (TranslationLoadException ex)
113            {
114                logger.Error(ex);
115                MessageDialog dialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, ex.Message);
116                dialog.Title = "Translation loading failed";
117                dialog.Run();
118                dialog.Destroy();
119            }
120           
121            logger.Debug("Initialising");
122            commandStack = new CommandStack();
123            commandStack.CommandStackUpdated+=new MethodInvoker(commandStack_CommandStackUpdated);
124            WarFoundryCore.GameSystemChanged+= new GameSystemChangedDelegate(OnGameSystemChanged);
125            WarFoundryCore.ArmyChanged+= new ArmyChangedDelegate(OnArmyChanged);
126            Destroyed+= new EventHandler(OnWindowDestroyed);
127            //TODO: Translate and subscribe to other events
128            UnitAddedMethod = new ObjectAddDelegate(OnUnitAdded);
129            UnitRemovedMethod = new ObjectRemoveDelegate(OnUnitRemoved);
130            PointsValueChangedMethod = new DoubleValChangedDelegate(OnPointsValueChanged);
131            FailedUnitRequirementMethod = new FailedUnitRequirementDelegate(OnFailedUnitRequirement);
132            UnitNameChangedMethod = new StringValChangedDelegate(OnUnitNameChanged);
133            logger.Debug("Initialising complete - trying to load default army or system");
134           
135            //FIXME: Temporary hack to add paths and factories
136            WarFoundryLoader.GetDefault().AddLoadDirectory(new DirectoryInfo(Constants.ExecutablePath + Constants.DirectoryString + "data"));
137            IWarFoundryFactory factory = WarFoundryFactoryFactory.GetFactoryFactory().GetFactory(typeof(WarFoundryXmlFactory));
138           
139            if (factory!=null && factory is WarFoundryXmlFactory)
140            {
141                WarFoundryLoader.GetDefault().RegisterFactory((WarFoundryXmlFactory)factory);
142            }
143           
144            factory = WarFoundryFactoryFactory.GetFactoryFactory().GetFactory(typeof(RollcallFactory));
145           
146            if (factory!=null && factory is RollcallFactory)
147            {
148                WarFoundryLoader.GetDefault().RegisterNonNativeFactory((INonNativeWarFoundryFactory)factory);
149            }
150                               
151            if (args.Length == 1)
152            {
153                logger.Debug("Attempting to load from file");               
154                FileInfo file = new FileInfo(args[0]);
155               
156                try
157                {
158                    ICollection<IWarFoundryObject> objects = WarFoundryLoader.GetDefault().LoadFile(file);
159
160                    if (objects.Count == 1)
161                    {
162                        List<IWarFoundryObject> objectList = new List<IWarFoundryObject>();
163                        objectList.AddRange(objects);
164                        IWarFoundryObject loadedObject = objectList[0];
165                       
166                        if (loadedObject is Army)
167                        {
168                            WarFoundryCore.CurrentArmy = (Army)loadedObject;
169                            logger.InfoFormat("Loaded army from {0}", file.FullName);
170                        }
171                        else if (loadedObject is GameSystem)
172                        {
173                            WarFoundryCore.CurrentGameSystem = (GameSystem)loadedObject;
174                            logger.InfoFormat("Loaded game system from {0}", file.FullName);
175                        }
176                    }
177                }
178                catch (InvalidFileException ex)
179                {
180                    //TODO: show error dialog
181                    logger.Error(ex);
182                }
183            }
184            else
185            {
186                string gameSystemID = Preferences.GetStringProperty("currSystem");
187
188                if (gameSystemID!=null && !"".Equals(gameSystemID))
189                {
190                    logger.Debug("Attempting to load current game system from properties");
191                    GameSystem sys = WarFoundryLoader.GetDefault().GetGameSystem(gameSystemID);
192                   
193                    if (sys!=null)
194                    {
195                        WarFoundryCore.CurrentGameSystem = sys;
196                        logger.InfoFormat("Loaded game system {0} from properties", gameSystemID);
197                    }
198                }
199            }
200        }
201       
202        private void RenderCategoryTreeObjectName(TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
203        {
204            object o = model.GetValue(iter, 0);
205           
206            if (o is ArmyCategory)
207            {
208                ArmyCategory c = (ArmyCategory)o;
209                string name = "";
210               
211                if (Preferences.GetBooleanProperty("ShowCatPercentage"))
212                {
213                    name = Translation.GetTranslation("categoryTreeCatName", "{0} - {1}pts", c.Name, c.PointsTotal);
214                }
215                else
216                {
217                    name = Translation.GetTranslation("categoryTreeCatNamePercentage", "{0} - {1}pts ({2}%)", c.Name, c.PointsTotal, (c.ParentArmy.PointsTotal > 0 ? Math.Round((c.PointsTotal / c.ParentArmy.PointsTotal) * 100) : 0));
218                }
219               
220                (cell as CellRendererText).Text = name;
221            }
222            else if (o is IBBoard.WarFoundry.API.Objects.Unit)
223            {
224                IBBoard.WarFoundry.API.Objects.Unit u = (IBBoard.WarFoundry.API.Objects.Unit)o;
225                string name = Translation.GetTranslation("categoryTreeCatName", "{0} - {1}pts", u.Name, u.PointsValue);
226                (cell as CellRendererText).Text = name;
227            }
228        }
229       
230        private void OnWindowDestroyed(object source, EventArgs args)
231        {
232            logger.Info("Exiting");
233            Application.Quit();
234        }
235       
236        private void OnUnitNameChanged(WarFoundryObject val, string oldValue, string newValue)
237        {
238            IBBoard.WarFoundry.API.Objects.Unit unit = (IBBoard.WarFoundry.API.Objects.Unit)val;
239            UnitDisplayWidget widget;
240            unitToWidgetMap.TryGetValue(unit, out widget);
241           
242            if (widget!=null)
243            {
244                unitsNotebook.SetTabLabelText(widget, newValue);
245            }
246        }
247       
248        private void OnUnitAdded(WarFoundryObject val)
249        {
250            IBBoard.WarFoundry.API.Objects.Unit unit = (IBBoard.WarFoundry.API.Objects.Unit)val;
251            unit.NameChanged+= UnitNameChangedMethod;
252            AddUnitToTree(unit);
253        }
254       
255        private void AddUnitToTree(IBBoard.WarFoundry.API.Objects.Unit unit)
256        {
257            TreeStore model = (TreeStore)treeUnits.Model;
258            TreeIter iter;
259            model.GetIterFirst(out iter);
260           
261            do
262            {
263                object obj = model.GetValue(iter, 0);
264               
265                if (obj is ArmyCategory)
266                {
267                    ArmyCategory cat = (ArmyCategory)obj;
268                   
269                    if (cat.Equals(unit.Category))
270                    {
271                        model.AppendValues(iter, unit);
272                        TreePath path = model.GetPath(iter);
273                        treeUnits.ExpandToPath(path);
274                    }
275                }
276            }
277            while (model.IterNext(ref iter));
278        }
279       
280        private void OnUnitRemoved(WarFoundryObject obj)
281        {
282            IBBoard.WarFoundry.API.Objects.Unit unit = (IBBoard.WarFoundry.API.Objects.Unit)obj;
283            unit.NameChanged-= UnitNameChangedMethod;
284            RemoveUnitFromTree(unit);
285           
286            //See if unit has a tab open and close it if it does
287        }
288       
289        private void RemoveUnitFromTree(IBBoard.WarFoundry.API.Objects.Unit unit)
290        {
291            TreeStore model = (TreeStore)treeUnits.Model;
292            TreeIter iter;
293            model.GetIterFirst(out iter);
294            bool removed = false;
295           
296            do
297            {
298                object obj = model.GetValue(iter, 0);
299               
300                if (obj is ArmyCategory)
301                {
302                    ArmyCategory cat = (ArmyCategory)obj;
303                   
304                    if (unit.Category == null || cat.Equals(unit.Category))
305                    {
306                        TreeIter innerIter;
307                        model.IterChildren(out innerIter, iter);
308                       
309                        do
310                        {
311                            object innerObj = model.GetValue(innerIter, 0);
312                           
313                            if (unit.Equals(innerObj))
314                            {
315                                model.Remove(ref innerIter);
316                                removed = true;
317                                break;
318                            }
319                        }
320                        while (model.IterNext(ref innerIter));
321                       
322                        if (removed)
323                        {
324                            break;
325                        }
326                    }
327                }
328            }
329            while (model.IterNext(ref iter));
330        }
331       
332        private void OnPointsValueChanged(WarFoundryObject obj, double before, double after)
333        {
334            //Set points in panel
335        }
336       
337        private void OnFailedUnitRequirement(List<FailedUnitRequirement> failedRequirement)
338        {
339            //Show error message in panel
340        }
341       
342        public Preferences Preferences
343        {
344            get { return preferences; }
345            set { preferences = value; }       
346        }
347       
348        /*public AbstractNativeWarFoundryFactory Factory
349        {
350            get { return WarFoundryFactoryFactory.GetFactoryFactory().GetFactory(Constants.ExecutablePath, factoryType); }
351        }*/
352       
353        protected void OnDeleteEvent (object sender, DeleteEventArgs a)
354        {
355            Application.Quit ();
356            a.RetVal = true;
357        }
358
359        protected virtual void OnExitActivated(object sender, System.EventArgs e)
360        {
361            Application.Quit();
362        }
363
364        protected virtual void OnChangeGameSystemActivated(object sender, System.EventArgs e)
365        {
366            ChangeCurrentGameSystem();
367        }
368
369        protected virtual void OnCreateArmyActivated(object sender, System.EventArgs e)
370        {
371            CreateNewArmy();
372        }
373
374        protected virtual void OnReloadFilesActivated(object sender, System.EventArgs e)
375        {
376        }
377
378        protected virtual void OnSaveArmyAsActivated(object sender, System.EventArgs e)
379        {
380            SaveCurrentArmyAs();
381        }
382
383        protected virtual void OnCloseArmyActivated(object sender, System.EventArgs e)
384        {
385            CloseCurrentArmy();
386        }
387
388        protected virtual void OnOpenArmyActivated(object sender, System.EventArgs e)
389        {
390            OpenArmy();
391        }
392
393        protected virtual void OnSaveArmyActivated(object sender, System.EventArgs e)
394        {
395            SaveCurrentArmy();
396        }
397       
398        protected virtual void OnAddUnitActivated(object sender, System.EventArgs e)
399        {
400            if (sender is ToolButton)
401            {
402                Category cat = null;
403                categoryMap.TryGetValue((ToolButton)sender, out cat);
404               
405                if (cat!=null)
406                {
407                    logger.DebugFormat("Show FrmNewUnit for {0}", cat.Name);
408                    FrmNewUnit newUnit = new FrmNewUnit(WarFoundryCore.CurrentArmy.Race, cat, WarFoundryCore.CurrentArmy);
409                    ResponseType response = (ResponseType)newUnit.Run();
410                    newUnit.Hide();
411                   
412                    if (response==ResponseType.Ok)
413                    {
414                        CreateAndAddUnitCommand cmd = new CreateAndAddUnitCommand(newUnit.SelectedUnit, WarFoundryCore.CurrentArmy);
415                        commandStack.Execute(cmd);
416                    }
417                   
418                    newUnit.Dispose();
419                }
420            }
421        }
422       
423        public CommandStack CommandStack
424        {
425            get { return commandStack; }
426        }
427       
428        private void SetAppTitle()
429        {
430            if (WarFoundryCore.CurrentArmy!=null)
431            {
432                Title = AppTitle + " - " + WarFoundryCore.CurrentGameSystem.Name + " - " + WarFoundryCore.CurrentArmy.Name;
433            }
434            else if (WarFoundryCore.CurrentGameSystem!=null)
435            {
436                Title = AppTitle + " - " + WarFoundryCore.CurrentGameSystem.Name;
437            }
438            else
439            {
440                Title = AppTitle;
441            }
442        }
443       
444        private void OnGameSystemChanged(GameSystem oldSys, GameSystem newSys)
445        {
446            system = newSys;
447            SetAppTitle();
448            miCreateArmy.Sensitive = system!=null;
449            newArmyButton.Sensitive = system!=null;
450            RemoveCategoryButtons();
451           
452            if (system!=null)
453            {
454                AddCategoryButtons(system.Categories);
455            }
456        }
457       
458        private void OnArmyChanged(Army oldArmy, Army newArmy)
459        {
460            loadedArmyPath = null;
461            SetAppTitle();
462            SetArmyTree(newArmy);
463                       
464            if (oldArmy!=null)
465            {
466                oldArmy.UnitAdded-= UnitAddedMethod;
467                oldArmy.UnitRemoved-= UnitRemovedMethod;
468                oldArmy.PointsValueChanged-= PointsValueChangedMethod;
469                oldArmy.FailedRequirement-=FailedUnitRequirementMethod;             
470            }
471           
472            unitToWidgetMap.Clear();
473           
474            while (unitsNotebook.NPages > 0)
475            {
476                unitsNotebook.RemovePage(0);
477            }
478           
479            if (newArmy==null)
480            {
481                DisableCategoryButtons();
482            }
483            else
484            {
485                newArmy.UnitAdded+= UnitAddedMethod;
486                newArmy.UnitRemoved+= UnitRemovedMethod;
487                newArmy.PointsValueChanged+= PointsValueChangedMethod;
488                newArmy.FailedRequirement+=FailedUnitRequirementMethod;
489                //TODO: Clear all buttons
490                EnableCategoryButtons();
491
492                if (newArmy.Race.HasCategoryOverrides())
493                {
494                    RemoveCategoryButtons();
495                    AddCategoryButtons(newArmy.Race.Categories);
496                }
497            }
498           
499            miCloseArmy.Sensitive = newArmy!=null;
500            miSaveArmyAs.Sensitive = newArmy!=null;
501            //New army has no changes, so we can't save it
502            miSaveArmy.Sensitive = false;
503            saveArmyButton.Sensitive = false;
504
505            CommandStack.Reset();
506            SetPointsPanelText();
507        }
508       
509        private void SetArmyTree(Army army)
510        {
511            logger.Debug("Resetting tree");
512            TreeStore store = (TreeStore)treeUnits.Model;
513            store.Clear();
514            TreeIter iter;
515           
516            if (army!=null)
517            {
518                logger.Debug("Loading in categories to tree");
519                               
520                foreach (ArmyCategory cat in army.Categories)
521                {
522                    logger.DebugFormat("Append category {0}", cat.Name);
523                    iter = store.AppendValues(cat);
524                   
525                    foreach (IBBoard.WarFoundry.API.Objects.Unit unit in cat.GetUnits())
526                    {
527                        store.AppendValues(iter, unit);
528                    }
529                }
530               
531                logger.Debug("Finished loading tree categories");
532            }
533        }
534       
535        private void DisableCategoryButtons()
536        {
537            SetCategoryButtonsSensitive(false);
538        }
539       
540        private void EnableCategoryButtons()
541        {
542            SetCategoryButtonsSensitive(true);
543        }
544       
545        private void SetCategoryButtonsSensitive(bool state)
546        {
547            int toolbarButtonCount = toolbar.Children.Length - 1;
548            logger.Debug("Last button index: "+toolbarButtonCount);
549           
550            for (int i = toolbarButtonCount; i > CATEGORY_BUTTON_SEPARATOR_INDEX; i--)
551            {
552                logger.DebugFormat("Setting button {0} state to {1}", i, state);
553                toolbar.Children[i].Sensitive = state;
554            }
555        }
556       
557        private void RemoveCategoryButtons()
558        {
559            int toolbarButtonCount = toolbar.Children.Length - 1;
560           
561            for (int i = toolbarButtonCount; i > CATEGORY_BUTTON_SEPARATOR_INDEX; i--)
562            {
563                toolbar.Remove(toolbar.Children[i]);
564            }
565           
566            categoryMap.Clear();
567        }
568       
569        private void AddCategoryButtons(Category[] cats)
570        {
571            if (cats!=null && cats.Length > 0)
572            {
573                logger.DebugFormat("Toolbar button count: {0}. Adding {1} categories.", toolbar.Children.Length, cats.Length);
574               
575                foreach (Category cat in cats)
576                {
577                    ToolButton button = new ToolButton("gtk-add");
578                    button.Label = cat.Name;
579                    button.TooltipText = "Add unit from "+cat.Name;
580                    //TODO: See if we can associate data in some way, the same as we can with SWF. For now we just use the map.
581                    categoryMap.Add(button, cat);
582                    button.Clicked+= new System.EventHandler(OnAddUnitActivated);
583                    toolbar.Insert(button, -1);
584                }
585            }
586           
587            toolbar.Children[CATEGORY_BUTTON_SEPARATOR_INDEX].Visible = cats!=null && cats.Length>0;
588           
589            toolbar.ShowAll();
590        }
591       
592        private void SetPointsPanelText()
593        {
594            //TODO: Set the points value in the status bar
595        }
596       
597        private void commandStack_CommandStackUpdated()
598        {
599            undoMenuButton.Sensitive = commandStack.CanUndo();
600            miUndo.Sensitive = undoMenuButton.Sensitive;
601            redoMenuButton.Sensitive = commandStack.CanRedo();
602            miRedo.Sensitive = redoMenuButton.Sensitive;
603            int redoLength = commandStack.RedoLength;
604            //TODO: Build menus for undo/redo and find way of adding tooltips
605            /*int maxRedo = Math.Min(10, redoLength);
606            MenuItem[] menuItems = null;
607       
608            if (redoLength > 0)
609            {
610                menuItems = new MenuItem[maxRedo];
611                Command com;
612                MenuItem mi;
613
614                for (int i = 0; i < maxRedo; i++)
615                {
616                    com = commandStack.PeekRedoCommand(i+1);
617
618                    if (com == null)
619                    {
620                        break;
621                    }
622
623                    mi = new MenuItem(com.Description);
624                    mi.Click+=new EventHandler(redoMenu_Click);
625                    menuItems[i] = mi;
626                }
627            }
628
629            redoMenu.MenuItems.Clear();
630
631            if (menuItems!=null && menuItems[0]!=null)
632            {
633                bttnRedo.ToolTipText = menuItems[0].Text;
634                redoMenu.MenuItems.AddRange(menuItems);
635            }*/
636            //TODO: Put above code back when we have a dropdown version of the redo button
637            if (redoLength > 0)
638            {
639                //redoMenuButton.Tooltip = CommandStack.PeekRedoCommand().Description;
640            }
641
642            int undoLength = commandStack.UndoLength;
643            /*int maxUndo = Math.Min(10, undoLength);
644            MenuItem[] menuItemsUndo = null;
645           
646            if (undoLength > 0)
647            {
648                menuItemsUndo = new MenuItem[maxUndo];
649                Command com;
650                MenuItem mi;
651
652                for (int i = 0; i < maxUndo; i++)
653                {
654                    com = commandStack.PeekUndoCommand(i+1);
655
656                    if (com == null)
657                    {
658                        break;
659                    }
660
661                    mi = new MenuItem(com.UndoDescription);
662                    mi.Click+=new EventHandler(undoMenu_Click);
663                    menuItemsUndo[i] = mi;
664                }
665            }
666
667            undoMenu.MenuItems.Clear();
668
669            if (menuItemsUndo!=null && menuItemsUndo[0]!=null)
670            {
671                bttnUndo.ToolTipText = menuItemsUndo[0].Text;
672                undoMenu.MenuItems.AddRange(menuItemsUndo);
673            }*/         
674            //TODO: Put above code back when we have a dropdown version of the undo button
675            if (undoLength > 0)
676            {
677                //undoMenuButton.Tooltip = CommandStack.PeekUndoCommand().UndoDescription;
678            }
679           
680            saveArmyButton.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy!=null && CanSave();
681            miSaveArmy.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy!=null && CanSave();
682        }   
683       
684        private bool CanSave()
685        {
686            return loadedArmyPath!=null && WarFoundryCore.CurrentArmy!=null && WarFoundrySaver.GetSaver()!=null;
687        }
688
689        private bool SaveCurrentArmyOrSaveAs()
690        {
691            if (CanSave())
692            {
693                return SaveCurrentArmy();
694            }
695            else
696            {
697                return SaveCurrentArmyAs();
698            }
699        }
700       
701        private bool OpenArmy()
702        {
703            //TODO: Open dialog for file selection then open army
704            bool success = false;
705            loadedArmyPath = null;//TODO: Set loaded file path
706            return success;
707        }
708
709        private bool SaveCurrentArmy()
710        {
711            bool success = false;
712           
713            if (CanSave())
714            {
715                try
716                {
717                    if (WarFoundrySaver.GetSaver().Save(WarFoundryCore.CurrentArmy, loadedArmyPath))
718                    {
719                        saveArmyButton.Sensitive = false;
720                        miSaveArmy.Sensitive = false;
721                        CommandStack.setCleanMark();
722                        success = true;
723                    }
724                }
725                catch (IOException ex)
726                {
727                    logger.Error("Saving army failed", ex);
728                    MessageDialog md = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "An error occured while saving the army. Please check the logs for details on what failed");
729                    md.Show();
730                }
731            }
732           
733            return success;
734        }
735
736        private bool SaveCurrentArmyAs()
737        {
738            /*if (saveArmyDialog.Filter == "")
739            {
740                string savePath = UserDataPath+Constants.DirectoryString+"armies"+Constants.DirectoryString;
741               
742                if (!Directory.Exists(savePath))
743                {
744                    Directory.CreateDirectory(savePath);
745                }
746
747                saveArmyDialog.InitialDirectory = savePath;
748                saveArmyDialog.Filter = Translation.GetTranslation("armyFileFilter")+"|*.army";
749                saveArmyDialog.Title = Translation.GetTranslation("saveArmyDialog");
750            }
751
752            DialogResult dr = saveArmyDialog.ShowDialog(this);
753
754            if (dr == DialogResult.OK)
755            {
756                if (WarFoundrySaver.GetSaver().Save(WarFoundryCore.CurrentArmy, saveArmyDialog.FileName))
757                {
758                    miSaveArmy.Enabled = false;
759                    bttnSaveArmy.Enabled = false;
760                    CommandStack.setCleanMark();
761                    loadedArmyPath = saveArmyDialog.FileName;
762                    return true;
763                }
764                else
765                {
766                    MessageBox.Show(this, Translation.GetTranslation("SaveFailed"), Translation.GetTranslation("SaveFailedTitle"), MessageBoxButtons.OK, MessageBoxIcon.Error);
767                    return false;
768                }
769            }
770            else
771            {
772                return false;
773            }*/
774            return false;
775        }
776       
777        private bool CloseCurrentArmy()
778        {
779            if (WarFoundryCore.CurrentArmy!=null)
780            {
781                bool canClose = false;
782
783                if (CommandStack.IsDirty())
784                {
785                    MessageDialog dia  = new MessageDialog(this, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.YesNo | ButtonsType.Cancel, "The army \""+WarFoundryCore.CurrentArmy.Name+"\" has been modified.\r\nSave changes before closing army?");   
786                    ResponseType dr = (ResponseType)dia.Run();
787
788                    if (dr == ResponseType.Yes)
789                    {
790                        //They want to save so try to save it or prompt for save as
791                        //If they cancel the save as then assume they don't want to close
792                        canClose = SaveCurrentArmyOrSaveAs();
793                    }
794                    else if (dr == ResponseType.No)
795                    {
796                        //They don't care about their changes
797                        canClose = true;
798                    }
799                    else
800                    {
801                        //Assume cancel or close with the X button
802                        canClose = false;
803                    }
804                   
805                    dia.Dispose();
806                }
807                else
808                {
809                    //Nothing has changed so we can safely close
810                    canClose = true;
811                }
812
813                if (canClose)
814                {
815                    //do close
816                    WarFoundryCore.CurrentArmy = null;
817                    return true;
818                }
819                else
820                {
821                    return false;
822                }
823            }
824            else
825            {
826                //pretend we succeeded
827                return true;
828            }
829        }
830
831        private void CreateNewArmy()
832        {
833            logger.Debug("Create new army");
834            FrmNewArmy newArmy = new FrmNewArmy(WarFoundryCore.CurrentGameSystem);
835            ResponseType type = (ResponseType)newArmy.Run();
836            newArmy.Hide();
837       
838            if (type == ResponseType.Ok)
839            {
840                if (CloseCurrentArmy())
841                {
842                    WarFoundryCore.CurrentArmy = new Army(newArmy.SelectedRace, newArmy.ArmyName, newArmy.ArmySize);
843                }
844            }
845            else
846            {
847                logger.Debug("Create new army cancelled");
848            }
849           
850            newArmy.Destroy();
851        }
852       
853        private void ChangeCurrentGameSystem()
854        {               
855            logger.Debug("Changing game system");
856            FrmChangeGameSystem dialog = new FrmChangeGameSystem(this);
857            ResponseType type = (ResponseType)dialog.Run();
858            dialog.Hide();
859           
860            if (type == ResponseType.Ok)
861            {
862                WarFoundryCore.CurrentGameSystem = dialog.SelectedSystem;
863            }
864            else
865            {
866                logger.Debug("Game system change cancelled");
867            }
868           
869            dialog.Destroy();
870        }
871
872        protected virtual void undoTBButtonActivated (object sender, System.EventArgs e)
873        {
874            CommandStack.Undo();
875        }
876
877        protected virtual void redoTBButtonActivated (object sender, System.EventArgs e)
878        {
879            CommandStack.Redo();
880        }
881
882        protected virtual void saveTBButtonActivated (object sender, System.EventArgs e)
883        {
884            SaveCurrentArmy();
885        }
886
887        protected virtual void openTBButtonActivated (object sender, System.EventArgs e)
888        {
889            OpenArmy();
890        }
891
892        protected virtual void newTBButtonActivated (object sender, System.EventArgs e)
893        {
894            CreateNewArmy();
895        }
896
897        protected virtual void ArmyRowActivated (object o, Gtk.RowActivatedArgs args)
898        {
899            TreeModel model = treeUnits.Model;
900            TreeIter iter;
901            model.GetIter(out iter, args.Path);
902            object obj = model.GetValue(iter, 0);
903           
904            if (obj is IBBoard.WarFoundry.API.Objects.Unit)
905            {
906                IBBoard.WarFoundry.API.Objects.Unit unit = (IBBoard.WarFoundry.API.Objects.Unit)obj;
907               
908                UnitDisplayWidget widget;
909                unitToWidgetMap.TryGetValue(unit, out widget);
910               
911                if (widget!=null)
912                {
913                    logger.DebugFormat("Selecting existing page for "+unit.Name);
914                    unitsNotebook.Page = unitsNotebook.PageNum(widget);
915                }
916                else
917                {
918                    widget = new UnitDisplayWidget(unit, CommandStack);
919                    logger.Debug("Adding page for "+unit.Name);
920                    unitToWidgetMap[unit] = widget;
921                    int pageNum = NotebookUtil.AddPageToNotebookWithCloseButton(unitsNotebook, widget, unit.Name);
922                    logger.Debug("Page added at index "+pageNum);
923                    unitsNotebook.ShowAll();
924                    unitsNotebook.Page = pageNum;
925                }
926            }
927        }
928    }
929}
Note: See TracBrowser for help on using the browser.