comparison FrmMainWindow.cs @ 0:1bb28f84d567

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