FreeTrainの進化系を目指す
ビュー周りの整備(途上) 終了確認
| @@ -4,6 +4,7 @@ | ||
| 4 | 4 | using nft.core.schedule; |
| 5 | 5 | using nft.core; |
| 6 | 6 | using nft.framework; |
| 7 | +using nft.util; | |
| 7 | 8 | |
| 8 | 9 | namespace nft.impl.game |
| 9 | 10 | { |
| @@ -20,8 +21,12 @@ | ||
| 20 | 21 | protected TerrainMapImpl terrains; |
| 21 | 22 | protected IPointerHandler activeHandler; |
| 22 | 23 | protected ViewCollection views; |
| 24 | + protected bool modified; | |
| 25 | + protected bool closed; | |
| 23 | 26 | |
| 24 | 27 | public GameImpl(string name, ITerrainMap map, Calendar cal) { |
| 28 | + this.closed = false; | |
| 29 | + this.modified = true; | |
| 25 | 30 | if (cal == null) cal = Calendar.ActiveCalendar; |
| 26 | 31 | this.name = name; |
| 27 | 32 | this.calender = cal; |
| @@ -53,17 +58,42 @@ | ||
| 53 | 58 | } |
| 54 | 59 | } |
| 55 | 60 | |
| 56 | - public void Close() | |
| 61 | + public virtual void Close() | |
| 57 | 62 | { |
| 58 | - // TODO: GameImpl.Close 実装を追加します。 | |
| 63 | + closed = true; | |
| 64 | + calender = null; | |
| 65 | + clock = null; | |
| 66 | + if (terrains != null) { | |
| 67 | + terrains.Dispose(); | |
| 68 | + terrains = null; | |
| 69 | + } | |
| 70 | + if (views != null) { | |
| 71 | + views.CloseAll(); | |
| 72 | + views = null; | |
| 73 | + } | |
| 59 | 74 | } |
| 60 | 75 | |
| 76 | + public bool ConfirmClose() { | |
| 77 | + if (Closed) { | |
| 78 | + return true; | |
| 79 | + } else if(modified){ | |
| 80 | + string text = I18n.T("GameManager", "Unsaved game data will be lost. Are you sure?"); | |
| 81 | + modified = !UIUtil.ConfirmMessage(text, UIMessageType.warning, UIInformLevel.normal); | |
| 82 | + } | |
| 83 | + return !modified; | |
| 84 | + } | |
| 85 | + | |
| 86 | + public bool Closed { | |
| 87 | + get { | |
| 88 | + return closed; | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 61 | 92 | public bool Modified |
| 62 | 93 | { |
| 63 | 94 | get |
| 64 | 95 | { |
| 65 | - // TODO: GameImpl.Modified getter 実装を追加します。 | |
| 66 | - return false; | |
| 96 | + return modified; | |
| 67 | 97 | } |
| 68 | 98 | } |
| 69 | 99 |
| @@ -49,8 +49,12 @@ | ||
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | public void Close() { |
| 52 | + if (OnClose != null) OnClose(new ViewEventArgs(this)); | |
| 52 | 53 | this.Dispose(); |
| 53 | 54 | } |
| 55 | + | |
| 56 | + public event ViewEventHandler OnClose; | |
| 57 | + public event ViewQueryEventHandler QueryClose; | |
| 54 | 58 | #endregion |
| 55 | 59 | |
| 56 | 60 | void OnTouchPanelScroll(object sender, ScrollEventArgs e) { |
| @@ -70,9 +74,33 @@ | ||
| 70 | 74 | Size szc = builder.ContentSize; |
| 71 | 75 | InitScroll(szc, szu); |
| 72 | 76 | renderPanel.EventTarget.MouseMove += new MouseEventHandler(EventTarget_MouseMove); |
| 77 | + SetupCloseConfirmation(); | |
| 73 | 78 | this.ResumeLayout(false); |
| 74 | 79 | } |
| 75 | 80 | |
| 81 | + protected virtual void SetupCloseConfirmation() { | |
| 82 | + Control c = this; | |
| 83 | + Form f = null; | |
| 84 | + while (null == (f = c as Form)) { | |
| 85 | + c = c.Parent; | |
| 86 | + if (c == null) return; // 予期せぬ状況 | |
| 87 | + } | |
| 88 | + f.FormClosing += new FormClosingEventHandler(OnClosing); | |
| 89 | + } | |
| 90 | + | |
| 91 | + protected void OnClosing(object sender, FormClosingEventArgs e) { | |
| 92 | + if (QueryClose != null) { | |
| 93 | + ViewQueryEventArgs arg = new ViewQueryEventArgs(this); | |
| 94 | + QueryClose(arg); | |
| 95 | + e.Cancel = arg.Cancel; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + | |
| 99 | + protected override void Dispose(bool disposing) { | |
| 100 | + base.Dispose(disposing); | |
| 101 | + if (OnClose != null) OnClose(new ViewEventArgs(this)); | |
| 102 | + } | |
| 103 | + | |
| 76 | 104 | #region Designer generated |
| 77 | 105 | private TouchPanel touchPanel; |
| 78 | 106 | private RenderViewPanel renderPanel; |
| @@ -6,6 +6,7 @@ | ||
| 6 | 6 | using nft.ui.mainframe; |
| 7 | 7 | using nft.impl.game; |
| 8 | 8 | using nft.core.geometry; |
| 9 | +using System.Windows.Forms; | |
| 9 | 10 | |
| 10 | 11 | namespace nft.impl.view { |
| 11 | 12 | public class GameViewFactory : IGameViewFactory { |
| @@ -11,6 +11,7 @@ | ||
| 11 | 11 | using System.Drawing; |
| 12 | 12 | |
| 13 | 13 | namespace nft.impl.view { |
| 14 | + [Obsolete] | |
| 14 | 15 | public class ViewController { |
| 15 | 16 | |
| 16 | 17 | public static ICommandEntity_Old GetRotateRightCommand(String id){ |
| @@ -14,8 +14,9 @@ | ||
| 14 | 14 | namespace nft.debug |
| 15 | 15 | { |
| 16 | 16 | /// <summary> |
| 17 | - /// TestGame の概要の説明です。 | |
| 17 | + /// 使われてません | |
| 18 | 18 | /// </summary> |
| 19 | + [Obsolete] | |
| 19 | 20 | public class TestGame : ICommandEntity_Old |
| 20 | 21 | { |
| 21 | 22 | static TestGame theInstance; |
| @@ -40,15 +40,21 @@ | ||
| 40 | 40 | protected GameManager(MainFrame mainFrame) |
| 41 | 41 | { |
| 42 | 42 | this.theFrame = mainFrame; |
| 43 | - theFrame.Closing+=new System.ComponentModel.CancelEventHandler(theFrame_Closing); | |
| 44 | 43 | theFrame.ActiveViewChanged += new EventHandler<EventArgs>(theFrame_ActiveViewChanged); |
| 45 | 44 | } |
| 46 | 45 | |
| 47 | 46 | public IGameMode CurrentMode { get{ return _curMode; } } |
| 48 | 47 | public IGame CurrentGame { get{ return _curGame; } } |
| 49 | - public void SetGame(IGame newgame, IGameMode mode, bool prompt) | |
| 48 | + [Obsolete] | |
| 49 | + public void SetGame(IGame newgame, IGameMode mode, bool prompt){} | |
| 50 | + | |
| 51 | + public void NewGameFromMap(ITerrainMap map, IGameMode mode, bool prompt) { | |
| 52 | + NewGameFromMap(null, map, Calendar.ActiveCalendar, mode, prompt); | |
| 53 | + } | |
| 54 | + | |
| 55 | + public virtual void NewGameFromMap(string name, ITerrainMap map, Calendar cal, IGameMode mode, bool prompt) | |
| 50 | 56 | { |
| 51 | - if( _curGame==newgame ) return; | |
| 57 | + IGame newgame = CreateGame(name, map, cal); | |
| 52 | 58 | if(_curGame != null) |
| 53 | 59 | { |
| 54 | 60 | if( prompt ) |
| @@ -63,33 +69,26 @@ | ||
| 63 | 69 | _curGame.Start(); |
| 64 | 70 | } |
| 65 | 71 | |
| 72 | + protected virtual IGame CreateGame(string name, ITerrainMap map, Calendar cal) { | |
| 73 | + if(name==null || name.Length == 0) name = I18n.T("GameManager", "NewGame"); | |
| 74 | + return new GameImpl(name, map, cal); | |
| 75 | + } | |
| 76 | + | |
| 66 | 77 | public event EventHandler ActiveViewChanged; |
| 67 | 78 | |
| 79 | + /// 使われてない. | |
| 80 | + [Obsolete] | |
| 68 | 81 | public GameViewPanel ActiveView { |
| 69 | 82 | get { |
| 70 | - GameViewPanel gvp = theFrame.ActiveView as GameViewPanel; | |
| 71 | - if (gvp != null) { | |
| 72 | - //MapViewDrawer drawer = dp.ViewDrawer as MapViewDrawer; | |
| 73 | - return gvp; | |
| 83 | + if (CurrentGame != null) { | |
| 84 | + return CurrentGame.Views.ActiveView as GameViewPanel; | |
| 74 | 85 | } else { |
| 75 | 86 | return null; |
| 76 | 87 | } |
| 77 | - throw new NotImplementedException(); | |
| 78 | 88 | } |
| 79 | 89 | } |
| 80 | 90 | |
| 81 | - public void NewGameFromMap(ITerrainMap map, IGameMode mode, bool prompt) { | |
| 82 | - if (_curGame != null) { | |
| 83 | - if (prompt) | |
| 84 | - if (!ConfirmCloseGame()) return; | |
| 85 | - else | |
| 86 | - _curGame.Close(); | |
| 87 | - } | |
| 88 | - _curGame = null; | |
| 89 | - SetGame(new GameImpl(map, Calendar.ActiveCalendar), mode, false); | |
| 90 | - } | |
| 91 | - | |
| 92 | - /// <summary> | |
| 91 | + /// <summary> | |
| 93 | 92 | /// Starts a new game |
| 94 | 93 | /// </summary> |
| 95 | 94 | protected void newGame() |
| @@ -124,13 +123,7 @@ | ||
| 124 | 123 | bool b = true; |
| 125 | 124 | if(_curGame!=null && _curGame.Modified) |
| 126 | 125 | { |
| 127 | - string text = I18n.T("Unsaved game data will be lost. Are you sure?"); | |
| 128 | - b = UIUtil.ConfirmMessage(text,UIMessageType.warning,UIInformLevel.normal); | |
| 129 | - if( b ) | |
| 130 | - { | |
| 131 | - _curGame.Close(); | |
| 132 | - _curGame=null; | |
| 133 | - } | |
| 126 | + b = _curGame.ConfirmClose(); | |
| 134 | 127 | } |
| 135 | 128 | return b; |
| 136 | 129 | } |
| @@ -261,10 +254,5 @@ | ||
| 261 | 254 | } |
| 262 | 255 | } |
| 263 | 256 | |
| 264 | - private void theFrame_Closing(object sender, System.ComponentModel.CancelEventArgs e) | |
| 265 | - { | |
| 266 | - e.Cancel = !ConfirmCloseGame(); | |
| 267 | - } | |
| 268 | - | |
| 269 | 257 | } |
| 270 | 258 | } |
| @@ -4,6 +4,7 @@ | ||
| 4 | 4 | using nft.core.view; |
| 5 | 5 | using nft.core.geometry; |
| 6 | 6 | using nft.framework; |
| 7 | +using System.Windows.Forms; | |
| 7 | 8 | |
| 8 | 9 | namespace nft.core.game { |
| 9 | 10 | public class ViewCollection : IEnumerable<IView>{ |
| @@ -15,6 +16,8 @@ | ||
| 15 | 16 | |
| 16 | 17 | protected List<IView> views; |
| 17 | 18 | protected IGame game; |
| 19 | + protected IView current; | |
| 20 | + | |
| 18 | 21 | public ViewCollection(IGame _game) { |
| 19 | 22 | game = _game; |
| 20 | 23 | views = new List<IView>(); |
| @@ -28,7 +31,7 @@ | ||
| 28 | 31 | |
| 29 | 32 | public virtual IView ActiveView { |
| 30 | 33 | get { |
| 31 | - return views.Count > 0 ? views[0] : null; | |
| 34 | + return current; | |
| 32 | 35 | } |
| 33 | 36 | set { |
| 34 | 37 | if (value != null) { |
| @@ -37,9 +40,21 @@ | ||
| 37 | 40 | } |
| 38 | 41 | } |
| 39 | 42 | |
| 43 | + public virtual IView PrimaryView { | |
| 44 | + get { | |
| 45 | + return views.Count>0 ? views[0] : null; | |
| 46 | + } | |
| 47 | + /* | |
| 48 | + set { | |
| 49 | + throw new NotImplementedException(); | |
| 50 | + } | |
| 51 | + */ | |
| 52 | + } | |
| 53 | + | |
| 40 | 54 | public IView OpenNew() { |
| 41 | 55 | IView v = CreateView(); |
| 42 | 56 | if (Add(v)) { |
| 57 | + SetActive(v); | |
| 43 | 58 | return v; |
| 44 | 59 | }else{ |
| 45 | 60 | v.Close(); |
| @@ -56,7 +71,7 @@ | ||
| 56 | 71 | |
| 57 | 72 | #region protected methods for override |
| 58 | 73 | protected virtual bool Add(IView v) { |
| 59 | - SetActive(v); | |
| 74 | + views.Add(v); | |
| 60 | 75 | return true; |
| 61 | 76 | } |
| 62 | 77 |
| @@ -66,14 +81,35 @@ | ||
| 66 | 81 | |
| 67 | 82 | protected virtual void SetActive(IView v) { |
| 68 | 83 | if (views.Contains(v)) { |
| 69 | - views.Remove(v); | |
| 84 | + current = v; | |
| 85 | + } else { | |
| 86 | + throw new InvalidOperationException("The view is not a member of collection."); | |
| 70 | 87 | } |
| 71 | - views.Insert(0, v); | |
| 72 | 88 | } |
| 73 | 89 | |
| 74 | 90 | protected virtual IView CreateView() { |
| 75 | - return ViewFactory.Create(game, Location.UNPLACED); | |
| 91 | + IView v = ViewFactory.Create(game, Location.UNPLACED); | |
| 92 | + v.OnClose += new ViewEventHandler(OnViewClose); | |
| 93 | + v.QueryClose += new ViewQueryEventHandler(QueryViewClose); | |
| 94 | + return v; | |
| 76 | 95 | } |
| 96 | + | |
| 97 | + protected virtual void OnViewClose(ViewEventArgs ea) { | |
| 98 | + IView v = ea.View; | |
| 99 | + v.OnClose -= new ViewEventHandler(OnViewClose); | |
| 100 | + v.QueryClose -= new ViewQueryEventHandler(OnViewClose); | |
| 101 | + if (PrimaryView == v && !game.Closed) { | |
| 102 | + game.Close(); | |
| 103 | + } | |
| 104 | + Remove(v); | |
| 105 | + } | |
| 106 | + | |
| 107 | + protected virtual void QueryViewClose(ViewQueryEventArgs ea) { | |
| 108 | + IView v = ea.View; | |
| 109 | + if (PrimaryView == v) { | |
| 110 | + ea.Cancel = !game.ConfirmClose(); | |
| 111 | + } | |
| 112 | + } | |
| 77 | 113 | #endregion |
| 78 | 114 | |
| 79 | 115 | #region IEnumerable implementation |
| @@ -14,6 +14,7 @@ | ||
| 14 | 14 | { |
| 15 | 15 | void Start(); |
| 16 | 16 | void Close(); |
| 17 | + bool Closed {get;} | |
| 17 | 18 | // if false, no need to save the game. |
| 18 | 19 | bool Modified {get;} |
| 19 | 20 | Clock Clock {get;} |
| @@ -22,5 +23,7 @@ | ||
| 22 | 23 | IPointerHandler ActiveController {get; set;} |
| 23 | 24 | //World world {get;} |
| 24 | 25 | ViewCollection Views {get;} |
| 25 | - } | |
| 26 | + //Return if prepare for close the game. | |
| 27 | + bool ConfirmClose(); | |
| 28 | + } | |
| 26 | 29 | } |
| @@ -5,7 +5,12 @@ | ||
| 5 | 5 | using nft.core.geometry; |
| 6 | 6 | |
| 7 | 7 | namespace nft.core.view { |
| 8 | + public delegate void ViewEventHandler(ViewEventArgs ea); | |
| 9 | + public delegate void ViewQueryEventHandler(ViewQueryEventArgs ea); | |
| 8 | 10 | public interface IView { |
| 11 | + event ViewEventHandler OnClose; | |
| 12 | + event ViewQueryEventHandler QueryClose; | |
| 13 | + | |
| 9 | 14 | SceneBuilder SceneBuilder { |
| 10 | 15 | get; |
| 11 | 16 | } |
| @@ -17,4 +22,18 @@ | ||
| 17 | 22 | |
| 18 | 23 | void Close(); |
| 19 | 24 | } |
| 25 | + | |
| 26 | + public class ViewEventArgs : EventArgs { | |
| 27 | + public readonly IView View; | |
| 28 | + public ViewEventArgs(IView v) { | |
| 29 | + View = v; | |
| 30 | + } | |
| 31 | + } | |
| 32 | + | |
| 33 | + public class ViewQueryEventArgs : ViewEventArgs { | |
| 34 | + public bool Cancel; | |
| 35 | + public ViewQueryEventArgs(IView v): base(v) { | |
| 36 | + Cancel = false; | |
| 37 | + } | |
| 38 | + } | |
| 20 | 39 | } |