OSDN Git Service

MainFormの中身をMainWindowに移す
authorKazuhiro Fujieda <fujieda@users.osdn.me>
Mon, 4 May 2020 05:50:23 +0000 (14:50 +0900)
committerKazuhiro Fujieda <fujieda@users.osdn.me>
Sun, 30 Aug 2020 05:58:22 +0000 (14:58 +0900)
KancolleSniffer/KancolleSniffer.csproj
KancolleSniffer/ListForm.cs
KancolleSniffer/ListFormGroup.cs
KancolleSniffer/Main.cs
KancolleSniffer/MainForm.cs
KancolleSniffer/MainWindow.cs [new file with mode: 0644]

index 8710a7a..94117a8 100644 (file)
@@ -62,6 +62,7 @@
     <Compile Include="Log\BattleLogger.cs" />\r
     <Compile Include="Main.cs" />\r
     <Compile Include="ListFormGroup.cs" />\r
+    <Compile Include="MainWindow.cs" />\r
     <Compile Include="Model\AirBattleResult.cs" />\r
     <Compile Include="Model\AirCorpsFighterPower.cs" />\r
     <Compile Include="Model\QuestCounter.cs" />\r
index 0068758..bf3691b 100644 (file)
@@ -27,8 +27,8 @@ namespace KancolleSniffer
     {\r
         private readonly Sniffer _sniffer;\r
         private readonly Config _config;\r
-        private readonly MainForm _main;\r
-        private readonly MainForm.TimeOutChecker _suppressActivate;\r
+        private readonly Form _form;\r
+        private readonly MainWindow.TimeOutChecker _suppressActivate;\r
         private readonly CheckBox[] _shipTypeCheckBoxes;\r
         private bool _isMaster;\r
         private Settings _settings;\r
@@ -94,11 +94,11 @@ namespace KancolleSniffer
             Repair\r
         }\r
 \r
-        public ListForm(MainForm main)\r
+        public ListForm(MainWindow main)\r
         {\r
             InitializeComponent();\r
             IsMaster = false;\r
-            _main = main;\r
+            _form = main.Form;\r
             _sniffer = main.Sniffer;\r
             _config = main.Config;\r
             _suppressActivate = main.SuppressActivate;\r
@@ -290,7 +290,7 @@ namespace KancolleSniffer
             if (config.Location.X == int.MinValue)\r
                 return;\r
             var bounds = new Rectangle(config.Location, config.Size);\r
-            if (MainForm.IsTitleBarOnAnyScreen(bounds.Location))\r
+            if (MainWindow.IsTitleBarOnAnyScreen(bounds.Location))\r
                 Location = bounds.Location;\r
             Height = bounds.Height;\r
         }\r
@@ -384,7 +384,7 @@ namespace KancolleSniffer
             {\r
                 if (WindowState == FormWindowState.Minimized)\r
                 {\r
-                    System.Windows.Forms.Application.DoEvents();\r
+                    Application.DoEvents();\r
                     if (_config.HideOnMinimized)\r
                         ShowInTaskbar = true;\r
                     WindowState = FormWindowState.Normal;\r
@@ -405,8 +405,8 @@ namespace KancolleSniffer
 \r
         private void RaiseBothWindows()\r
         {\r
-            _main.Owner = null;\r
-            Owner = _main;\r
+            _form.Owner = null;\r
+            Owner = _form;\r
             BringToFront();\r
             Owner = null;\r
         }\r
index 0d7a619..8046ce4 100644 (file)
@@ -22,17 +22,17 @@ namespace KancolleSniffer
 {\r
     public class ListFormGroup\r
     {\r
-        private readonly MainForm _mainForm;\r
+        private readonly MainWindow _mainWindow;\r
         private readonly List<ListForm> _listForms = new List<ListForm>();\r
 \r
         public ListForm Main => _listForms[0];\r
 \r
-        public ListFormGroup(MainForm mainForm)\r
+        public ListFormGroup(MainWindow main)\r
         {\r
-            _mainForm = mainForm;\r
-            _listForms.Add(new ListForm(mainForm) {IsMaster = true});\r
-            for (var i = 0; i < mainForm.Config.ListFormGroup.Count; i++)\r
-                _listForms.Add(new ListForm(mainForm) {Owner = Main});\r
+            _mainWindow = main;\r
+            _listForms.Add(new ListForm(main) {IsMaster = true});\r
+            for (var i = 0; i < main.Config.ListFormGroup.Count; i++)\r
+                _listForms.Add(new ListForm(main) {Owner = Main});\r
         }\r
 \r
         public void ShowOrCreate()\r
@@ -50,7 +50,7 @@ namespace KancolleSniffer
                     return;\r
                 }\r
             }\r
-            var newForm = new ListForm(_mainForm) {Owner = Main, TopMost = Main.TopMost, Font = Main.Font};\r
+            var newForm = new ListForm(_mainWindow) {Owner = Main, TopMost = Main.TopMost, Font = Main.Font};\r
             newForm.Show();\r
             newForm.UpdateList();\r
             _listForms.Add(newForm);\r
index 7b7d89c..47afbf6 100644 (file)
@@ -11,27 +11,16 @@ using System.Windows.Forms;
 using DynaJson;\r
 using KancolleSniffer.Log;\r
 using KancolleSniffer.Net;\r
-using KancolleSniffer.Notification;\r
 using KancolleSniffer.Util;\r
 using Microsoft.CSharp.RuntimeBinder;\r
 \r
 namespace KancolleSniffer\r
 {\r
-    public interface IMainForm\r
-    {\r
-        Label PlayLogSign { get; }\r
-        Notifier Notifier { get; }\r
-        void UpdateTimers();\r
-        void UpdateItemInfo();\r
-        void UpdateInfo(Sniffer.Update update);\r
-        void ApplyConfig();\r
-    }\r
-\r
     public class Main\r
     {\r
         private ProxyManager _proxyManager;\r
         private Form _form;\r
-        private IMainForm _mainForm;\r
+        private MainWindow _mainBehavior;\r
         private readonly ErrorDialog _errorDialog = new ErrorDialog();\r
         private ConfigDialog _configDialog;\r
         private ErrorLog _errorLog;\r
@@ -54,13 +43,13 @@ namespace KancolleSniffer
         {\r
             Config.Load();\r
             _configDialog = new ConfigDialog(this);\r
-            var form = new MainForm(this);\r
+            var form = new MainForm();\r
             _form = form;\r
-            _mainForm = form;\r
+            _mainBehavior = new MainWindow(this, form);\r
             _proxyManager = new ProxyManager(_form, Config);\r
             _proxyManager.UpdatePacFile();\r
             _errorLog = new ErrorLog(Sniffer);\r
-            Sniffer.RepeatingTimerController = _mainForm.Notifier;\r
+            Sniffer.RepeatingTimerController = _mainBehavior.Notifier;\r
             LoadData();\r
             ApplyConfig();\r
             ApplySettings();\r
@@ -160,7 +149,7 @@ namespace KancolleSniffer
             try\r
             {\r
                 var update = (Sniffer.Update)Sniffer.Sniff(s.Url, s.Request, JsonObject.Parse(s.Response));\r
-                _mainForm.UpdateInfo(update);\r
+                _mainBehavior.UpdateInfo(update);\r
                 if (!Sniffer.Started)\r
                     return;\r
                 Step.SetNowIfNeeded();\r
@@ -283,8 +272,8 @@ namespace KancolleSniffer
                 try\r
                 {\r
                     Step.SetNow();\r
-                    _mainForm.UpdateTimers();\r
-                    _mainForm.Notifier.NotifyTimers();\r
+                    _mainBehavior.UpdateTimers();\r
+                    _mainBehavior.Notifier.NotifyTimers();\r
                     Step.SetPrev();\r
                 }\r
                 catch (Exception ex)\r
@@ -295,7 +284,7 @@ namespace KancolleSniffer
             }\r
             if (_playLog == null || _configDialog.Visible)\r
             {\r
-                _mainForm.PlayLogSign.Visible = false;\r
+                _mainBehavior.PlayLogSign.Visible = false;\r
                 return;\r
             }\r
             PlayLog();\r
@@ -304,13 +293,13 @@ namespace KancolleSniffer
         public void ResetAchievement()\r
         {\r
             Sniffer.Achievement.Reset();\r
-            _mainForm.UpdateItemInfo();\r
+            _mainBehavior.UpdateItemInfo();\r
         }\r
 \r
         private void PlayLog()\r
         {\r
             var lines = new List<string>();\r
-            var sign = _mainForm.PlayLogSign;\r
+            var sign = _mainBehavior.PlayLogSign;\r
             foreach (var s in new[] {"url: ", "request: ", "response: "})\r
             {\r
                 do\r
@@ -333,7 +322,7 @@ namespace KancolleSniffer
             {\r
                 Config.Save();\r
                 ApplyConfig();\r
-                _mainForm.Notifier.StopRepeatingTimer(_configDialog.RepeatSettingsChanged);\r
+                _mainBehavior.Notifier.StopRepeatingTimer(_configDialog.RepeatSettingsChanged);\r
             }\r
         }\r
 \r
@@ -341,10 +330,10 @@ namespace KancolleSniffer
         {\r
             Sniffer.ShipCounter.Margin = Config.MarginShips;\r
             Sniffer.ItemCounter.Margin = Config.MarginEquips;\r
-            _mainForm.Notifier.NotifyShipItemCount();\r
+            _mainBehavior.Notifier.NotifyShipItemCount();\r
             Sniffer.Achievement.ResetHours = Config.ResetHours;\r
             Sniffer.WarnBadDamageWithDameCon = Config.WarnBadDamageWithDameCon;\r
-            _mainForm.ApplyConfig();\r
+            _mainBehavior.ApplyConfig();\r
         }\r
 \r
         public IEnumerable<Control> Controls =>\r
index 6656865..f68310c 100644 (file)
 // See the License for the specific language governing permissions and\r
 // limitations under the License.\r
 \r
-using System;\r
-using System.Collections.Generic;\r
-using System.Drawing;\r
-using System.Linq;\r
 using System.Windows.Forms;\r
-using KancolleSniffer.Notification;\r
 using KancolleSniffer.Util;\r
-using KancolleSniffer.View;\r
 \r
 namespace KancolleSniffer\r
 {\r
-    public partial class MainForm : Form, IMainForm\r
+    public partial class MainForm : Form\r
     {\r
-        private readonly ResizableToolTip _toolTip = new ResizableToolTip();\r
-        private readonly ResizableToolTip _tooltipCopy = new ResizableToolTip {ShowAlways = false, AutomaticDelay = 0};\r
-        private readonly ListFormGroup _listFormGroup;\r
-        private readonly ContextMenuMain _contextMenuMain = new ContextMenuMain();\r
-        private readonly ContextMenuNotifyIcon _contextMenuNotifyIcon = new ContextMenuNotifyIcon();\r
-\r
-        private IEnumerable<IUpdateContext> _updateable;\r
-        private IEnumerable<IUpdateTimers> _timers;\r
-        private Main _main;\r
-\r
-        public Sniffer Sniffer { get; private set; }\r
-        public Config Config { get; private set; }\r
-        public Label PlayLogSign => hqPanel.PlayLog;\r
-        public Notifier Notifier { get; }\r
-\r
-        public MainForm(Main main)\r
+        public MainForm()\r
         {\r
             InitializeComponent();\r
-            notifyIconMain.ContextMenuStrip = _contextMenuNotifyIcon;\r
-            // ReSharper disable once VirtualMemberCallInConstructor\r
-            ContextMenuStrip = _contextMenuMain;\r
-            SetupMain(main);\r
-            _listFormGroup = new ListFormGroup(this);\r
-            Notifier = new Notifier(FlashWindow, ShowTaster, PlaySound);\r
-            SetupView();\r
-        }\r
-\r
-        private void SetupMain(Main main)\r
-        {\r
-            _main = main;\r
-            Config = main.Config;\r
-            Sniffer = main.Sniffer;\r
-        }\r
-\r
-        private void SetupView()\r
-        {\r
-            SetScaleFactorOfDpiScaling();\r
-            SetupQuestPanel();\r
-            SetEventHandlers();\r
-            mainFleetPanel.AkashiRepairTimer = labelAkashiRepairTimer;\r
-            mainFleetPanel.ShowShipOnList = ShowShipOnShipList;\r
-            panelRepairList.CreateLabels(panelRepairList_Click);\r
-            ndockPanel.SetClickHandler(labelNDockCaption);\r
-            missionPanel.SetClickHandler(labelMissionCaption);\r
-            materialHistoryPanel.SetClickHandler(labelMaterialCaption, dropDownButtonMaterialHistory);\r
-            SetupUpdateable();\r
-            PerformZoom();\r
-        }\r
-\r
-        private void SetEventHandlers()\r
-        {\r
-            SetMainFormEventHandler();\r
-            SetContextMenuMainEventHandler();\r
-            SetContextMenuNotifyIconEventHandler();\r
-            SetNotifyIconEventHandler();\r
-            SetRepairListEventHandler();\r
-        }\r
-\r
-        private void SetMainFormEventHandler()\r
-        {\r
-            Load += MainForm_Load;\r
-            FormClosing += MainForm_FormClosing;\r
-            Resize += MainForm_Resize;\r
-            Activated += MainForm_Activated;\r
-        }\r
-\r
-        private void SetContextMenuMainEventHandler()\r
-        {\r
-            _contextMenuMain.SetClickHandlers(\r
-                _listFormGroup.ShowOrCreate,\r
-                _main.ShowReport,\r
-                _main.StartCapture,\r
-                _main.ShowConfigDialog,\r
-                Close);\r
-        }\r
-\r
-        private void SetContextMenuNotifyIconEventHandler()\r
-        {\r
-            _contextMenuNotifyIcon.SetEventHandlers(RevertFromIcon, Close);\r
-        }\r
-\r
-        private void SetNotifyIconEventHandler()\r
-        {\r
-            notifyIconMain.MouseDoubleClick += notifyIconMain_MouseDoubleClick;\r
-        }\r
-\r
-        private void SetRepairListEventHandler()\r
-        {\r
-            labelRepairListCaption.Click += labelRepairListButton_Click;\r
-            dropDownButtonRepairList.Click += labelRepairListButton_Click;\r
-            panelRepairList.Click += panelRepairList_Click;\r
-        }\r
-\r
-        private void SetupUpdateable()\r
-        {\r
-            _updateable = new IUpdateContext[]\r
-            {\r
-                hqPanel, missionPanel, kdockPanel, ndockPanel, materialHistoryPanel, mainFleetPanel, Notifier\r
-            };\r
-            var context = new UpdateContext(Sniffer, Config, () => _main.Step);\r
-            foreach (var updateable in _updateable)\r
-                updateable.Context = context;\r
-            _timers = new IUpdateTimers[] {missionPanel, kdockPanel, ndockPanel, mainFleetPanel};\r
-        }\r
-\r
-        private void SetScaleFactorOfDpiScaling()\r
-        {\r
-            var autoScaleDimensions = new SizeF(6f, 12f); // AutoScaleDimensionの初期値\r
-            Scaler.Factor = new SizeF(CurrentAutoScaleDimensions.Width / autoScaleDimensions.Width,\r
-                CurrentAutoScaleDimensions.Height / autoScaleDimensions.Height);\r
-        }\r
-\r
-        private void SetupQuestPanel()\r
-        {\r
-            int prevHeight = questPanel.Height;\r
-            questPanel.CreateLabels(Config.QuestLines);\r
-            Height += questPanel.Height - prevHeight;\r
-        }\r
-\r
-        public void UpdateInfo(Sniffer.Update update)\r
-        {\r
-            if (update == Sniffer.Update.Start)\r
-            {\r
-                hqPanel.Login.Visible = false;\r
-                mainFleetPanel.Start();\r
-                Notifier.StopAllRepeat();\r
-                return;\r
-            }\r
-            if (!Sniffer.Started)\r
-                return;\r
-            if ((update & Sniffer.Update.Item) != 0)\r
-                UpdateItemInfo();\r
-            if ((update & Sniffer.Update.Timer) != 0)\r
-                UpdateTimers();\r
-            if ((update & Sniffer.Update.NDock) != 0)\r
-                UpdateNDocLabels();\r
-            if ((update & Sniffer.Update.Mission) != 0)\r
-                UpdateMissionLabels();\r
-            if ((update & Sniffer.Update.QuestList) != 0)\r
-                UpdateQuestList();\r
-            if ((update & Sniffer.Update.Ship) != 0)\r
-                UpdateShipInfo();\r
-            if ((update & Sniffer.Update.Battle) != 0)\r
-                UpdateBattleInfo();\r
-            if ((update & Sniffer.Update.Cell) != 0)\r
-                UpdateCellInfo();\r
-        }\r
-\r
-        private void MainForm_Load(object sender, EventArgs e)\r
-        {\r
-            SuppressActivate.Start();\r
-            RestoreLocation();\r
-            if (Config.HideOnMinimized && WindowState == FormWindowState.Minimized)\r
-                ShowInTaskbar = false;\r
-            if (Config.ShowHpInPercent)\r
-                mainFleetPanel.ToggleHpPercent();\r
-            if (Config.ShipList.Visible)\r
-                _listFormGroup.Show();\r
-            _main.CheckVersionUpMain(mainFleetPanel.Guide);\r
-        }\r
-\r
-        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
-        {\r
-            if (!Config.ExitSilently)\r
-            {\r
-                using var dialog = new ConfirmDialog();\r
-                if (dialog.ShowDialog(this) != DialogResult.Yes)\r
-                {\r
-                    e.Cancel = true;\r
-                    return;\r
-                }\r
-            }\r
-            _listFormGroup.Close();\r
-            Config.Location = (WindowState == FormWindowState.Normal ? Bounds : RestoreBounds).Location;\r
-            Config.ShowHpInPercent = mainFleetPanel.ShowHpInPercent;\r
-        }\r
-\r
-        private void MainForm_Resize(object sender, EventArgs e)\r
-        {\r
-            if (_listFormGroup == null) // DPIが100%でないときにInitializeComponentから呼ばれるので\r
-                return;\r
-            SuppressActivate.Start();\r
-            if (WindowState == FormWindowState.Minimized)\r
-            {\r
-                if (Config.HideOnMinimized)\r
-                    ShowInTaskbar = false;\r
-            }\r
-            _listFormGroup.Main.ChangeWindowState(WindowState);\r
-        }\r
-\r
-        public readonly TimeOutChecker SuppressActivate = new TimeOutChecker();\r
-\r
-        private void MainForm_Activated(object sender, EventArgs e)\r
-        {\r
-            if (SuppressActivate.Check())\r
-                return;\r
-            if (NeedRaise)\r
-                RaiseBothWindows();\r
-        }\r
-\r
-        private bool NeedRaise => _listFormGroup.Visible && WindowState != FormWindowState.Minimized;\r
-\r
-        private void RaiseBothWindows()\r
-        {\r
-            _listFormGroup.Main.Owner = null;\r
-            Owner = _listFormGroup.Main;\r
-            BringToFront();\r
-            Owner = null;\r
-        }\r
-\r
-        public class TimeOutChecker\r
-        {\r
-            private DateTime _lastCheck;\r
-            private readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(500);\r
-\r
-            public void Start()\r
-            {\r
-                _lastCheck = DateTime.Now;\r
-            }\r
-\r
-            public bool Check()\r
-            {\r
-                var now = DateTime.Now;\r
-                var last = _lastCheck;\r
-                _lastCheck = now;\r
-                return now - last < _timeout;\r
-            }\r
-        }\r
-\r
-        private void RevertFromIcon()\r
-        {\r
-            ShowInTaskbar = true;\r
-            WindowState = FormWindowState.Normal;\r
-            TopMost = _listFormGroup.TopMost = Config.TopMost; // 最前面に表示されなくなることがあるのを回避する\r
-        }\r
-\r
-        private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
-        {\r
-            RevertFromIcon();\r
-        }\r
-\r
-        private void PerformZoom()\r
-        {\r
-            if (Config.Zoom == 100)\r
-            {\r
-                ShipLabel.Name.BaseFont = Font;\r
-                ShipLabel.Name.LatinFont = LatinFont();\r
-                return;\r
-            }\r
-            var prev = CurrentAutoScaleDimensions;\r
-            foreach (var control in new Control[]\r
-            {\r
-                this, mainFleetPanel.Guide, hqPanel.Login,\r
-                _contextMenuMain\r
-            }.Concat(_main.Controls))\r
-            {\r
-                control.Font = ZoomFont(control.Font);\r
-            }\r
-            _listFormGroup.Font = ZoomFont(_listFormGroup.Font);\r
-            foreach (var toolTip in new[] {_toolTip, _tooltipCopy})\r
-            {\r
-                toolTip.Font = ZoomFont(toolTip.Font);\r
-            }\r
-            ShipLabel.Name.BaseFont = Font;\r
-            ShipLabel.Name.LatinFont = LatinFont();\r
-            var cur = CurrentAutoScaleDimensions;\r
-            Scaler.Factor = Scaler.Scale(cur.Width / prev.Width, cur.Height / prev.Height);\r
-        }\r
-\r
-        private Font ZoomFont(Font font)\r
-        {\r
-            return new Font(font.FontFamily, font.Size * Config.Zoom / 100);\r
-        }\r
-\r
-        private Font LatinFont()\r
-        {\r
-            return new Font("Tahoma", 8f * Config.Zoom / 100);\r
-        }\r
-\r
-        private void RestoreLocation()\r
-        {\r
-            if (Config.Location.X == int.MinValue)\r
-                return;\r
-            if (IsTitleBarOnAnyScreen(Config.Location))\r
-                Location = Config.Location;\r
-        }\r
-\r
-        public void ApplyConfig()\r
-        {\r
-            if (TopMost != Config.TopMost)\r
-                TopMost = _listFormGroup.TopMost = Config.TopMost;\r
-            hqPanel.Update();\r
-            labelAkashiRepair.Visible = labelAkashiRepairTimer.Visible = Config.UsePresetAkashi;\r
-        }\r
-\r
-        public static bool IsTitleBarOnAnyScreen(Point location)\r
-        {\r
-            var rect = new Rectangle(\r
-                new Point(location.X + SystemInformation.IconSize.Width + SystemInformation.HorizontalFocusThickness,\r
-                    location.Y + SystemInformation.CaptionHeight), new Size(60, 1));\r
-            return Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect));\r
-        }\r
-\r
-        private void ShowShipOnShipList(int id)\r
-        {\r
-            if (!_listFormGroup.Visible)\r
-                return;\r
-            _listFormGroup.ShowShip(id);\r
-        }\r
-\r
-        public void UpdateItemInfo()\r
-        {\r
-            hqPanel.Update();\r
-            Notifier.NotifyShipItemCount();\r
-            materialHistoryPanel.Update();\r
-            if (_listFormGroup.Visible)\r
-                _listFormGroup.UpdateList();\r
-        }\r
-\r
-        private void UpdateShipInfo()\r
-        {\r
-            mainFleetPanel.Update();\r
-            Notifier.NotifyDamagedShip();\r
-            UpdateChargeInfo();\r
-            UpdateRepairList();\r
-            UpdateMissionLabels();\r
-            if (_listFormGroup.Visible)\r
-                _listFormGroup.UpdateList();\r
-        }\r
-\r
-        private void UpdateBattleInfo()\r
-        {\r
-            _listFormGroup.UpdateBattleResult();\r
-            _listFormGroup.UpdateAirBattleResult();\r
-            mainFleetPanel.UpdateBattleInfo();\r
-        }\r
-\r
-        private void UpdateCellInfo()\r
-        {\r
-            _listFormGroup.UpdateCellInfo();\r
-        }\r
-\r
-        private void UpdateChargeInfo()\r
-        {\r
-            mainFleetPanel.UpdateChargeInfo();\r
-        }\r
-\r
-        private void UpdateNDocLabels()\r
-        {\r
-            ndockPanel.Update();\r
-        }\r
-\r
-        private void UpdateMissionLabels()\r
-        {\r
-            missionPanel.Update();\r
-        }\r
-\r
-        public void UpdateTimers()\r
-        {\r
-            foreach (var timer in _timers)\r
-                timer.UpdateTimers();\r
-        }\r
-\r
-        private void UpdateRepairList()\r
-        {\r
-            panelRepairList.SetRepairList(Sniffer.RepairList);\r
-            _toolTip.SetToolTip(labelRepairListCaption, new RepairShipCount(Sniffer.RepairList).ToString());\r
-        }\r
-\r
-        private void UpdateQuestList()\r
-        {\r
-            questPanel.Update(Sniffer.Quests);\r
-            labelQuestCount.Text = Sniffer.Quests.Length.ToString();\r
-            Notifier.NotifyQuestComplete();\r
-        }\r
-\r
-        private void FlashWindow()\r
-        {\r
-            Win32API.FlashWindow(Handle);\r
-        }\r
-\r
-        private void ShowTaster(string title, string message)\r
-        {\r
-            notifyIconMain.ShowBalloonTip(20000, title, message, ToolTipIcon.Info);\r
-        }\r
-\r
-        private void PlaySound(string file, int volume)\r
-        {\r
-            SoundPlayer.PlaySound(Handle, file, volume);\r
         }\r
 \r
         protected override void WndProc(ref Message m)\r
@@ -421,26 +29,5 @@ namespace KancolleSniffer
             SoundPlayer.CloseSound(m);\r
             base.WndProc(ref m);\r
         }\r
-\r
-        private void labelRepairListButton_Click(object sender, EventArgs e)\r
-        {\r
-            if (panelRepairList.Visible)\r
-            {\r
-                panelRepairList.Visible = false;\r
-                dropDownButtonRepairList.BackColor = DefaultBackColor;\r
-            }\r
-            else\r
-            {\r
-                panelRepairList.Visible = true;\r
-                panelRepairList.BringToFront();\r
-                dropDownButtonRepairList.BackColor = CustomColors.ActiveButtonColor;\r
-            }\r
-        }\r
-\r
-        private void panelRepairList_Click(object sender, EventArgs e)\r
-        {\r
-            panelRepairList.Visible = false;\r
-            dropDownButtonRepairList.BackColor = DefaultBackColor;\r
-        }\r
     }\r
 }
\ No newline at end of file
diff --git a/KancolleSniffer/MainWindow.cs b/KancolleSniffer/MainWindow.cs
new file mode 100644 (file)
index 0000000..b858c40
--- /dev/null
@@ -0,0 +1,468 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Drawing;\r
+using System.Linq;\r
+using System.Reflection;\r
+using System.Windows.Forms;\r
+using KancolleSniffer.Notification;\r
+using KancolleSniffer.Util;\r
+using KancolleSniffer.View;\r
+\r
+namespace KancolleSniffer\r
+{\r
+    public class MainWindow\r
+    {\r
+        private readonly ResizableToolTip _toolTip = new ResizableToolTip();\r
+        private readonly ResizableToolTip _tooltipCopy = new ResizableToolTip {ShowAlways = false, AutomaticDelay = 0};\r
+        private readonly ListFormGroup _listFormGroup;\r
+        private readonly ContextMenuMain _contextMenuMain = new ContextMenuMain();\r
+        private readonly ContextMenuNotifyIcon _contextMenuNotifyIcon = new ContextMenuNotifyIcon();\r
+        private readonly Components _c;\r
+\r
+        private IEnumerable<IUpdateContext> _updateable;\r
+        private IEnumerable<IUpdateTimers> _timers;\r
+        private Main _main;\r
+\r
+        public Sniffer Sniffer { get; private set; }\r
+        public Config Config { get; private set; }\r
+        public Label PlayLogSign => _c.hqPanel.PlayLog;\r
+        public Notifier Notifier { get; }\r
+        public Form Form { get; }\r
+\r
+        private class Components\r
+        {\r
+            // ReSharper disable InconsistentNaming\r
+            // ReSharper disable UnusedAutoPropertyAccessor.Local\r
+            public NotifyIcon notifyIconMain { get; set; }\r
+            public HqPanel hqPanel { get; set; }\r
+            public MainFleetPanel mainFleetPanel { get; set; }\r
+            public Label labelNDockCaption { get; set; }\r
+            public NDockPanel ndockPanel { get; set; }\r
+            public KDockPanel kdockPanel { get; set; }\r
+            public Label labelMissionCaption { get; set; }\r
+            public MissionPanel missionPanel { get; set; }\r
+            public Label labelMaterialCaption { get; set; }\r
+            public DropDownButton dropDownButtonMaterialHistory { get; set; }\r
+            public MaterialHistoryPanel materialHistoryPanel { get; set; }\r
+            public Label labelQuestCount { get; set; }\r
+            public QuestPanel questPanel { get; set; }\r
+            public Label labelAkashiRepair { get; set; }\r
+            public Label labelAkashiRepairTimer { get; set; }\r
+            public Label labelRepairListCaption { get; set; }\r
+            public Label dropDownButtonRepairList { get; set; }\r
+            public RepairListForMain panelRepairList { get; set; }\r
+            // ReSharper restore InconsistentNaming\r
+            // ReSharper restore UnusedAutoPropertyAccessor.Local\r
+        }\r
+\r
+        public MainWindow(Main main, Form form)\r
+        {\r
+            _c = GetComponents(form);\r
+            Form = form;\r
+            _c.notifyIconMain.ContextMenuStrip = _contextMenuNotifyIcon;\r
+            Form.ContextMenuStrip = _contextMenuMain;\r
+            Form.ContextMenuStrip = _contextMenuMain;\r
+            SetupMain(main);\r
+            _listFormGroup = new ListFormGroup(this);\r
+            Notifier = new Notifier(FlashWindow, ShowTaster, PlaySound);\r
+            SetupView();\r
+        }\r
+\r
+        private Components GetComponents(Form form)\r
+        {\r
+            var r = new Components();\r
+            foreach (var prop in typeof(Components).GetProperties())\r
+            {\r
+                // ReSharper disable once PossibleNullReferenceException\r
+                prop.SetValue(r,\r
+                    form.GetType().GetField(prop.Name, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(form));\r
+            }\r
+            return r;\r
+        }\r
+\r
+        private void SetupMain(Main main)\r
+        {\r
+            _main = main;\r
+            Config = main.Config;\r
+            Sniffer = main.Sniffer;\r
+        }\r
+\r
+        private void SetupView()\r
+        {\r
+            SetScaleFactorOfDpiScaling();\r
+            SetupQuestPanel();\r
+            SetEventHandlers();\r
+            _c.mainFleetPanel.AkashiRepairTimer = _c.labelAkashiRepairTimer;\r
+            _c.mainFleetPanel.ShowShipOnList = ShowShipOnShipList;\r
+            _c.panelRepairList.CreateLabels(panelRepairList_Click);\r
+            _c.ndockPanel.SetClickHandler(_c.labelNDockCaption);\r
+            _c.missionPanel.SetClickHandler(_c.labelMissionCaption);\r
+            _c.materialHistoryPanel.SetClickHandler(_c.labelMaterialCaption, _c.dropDownButtonMaterialHistory);\r
+            SetupUpdateable();\r
+            PerformZoom();\r
+        }\r
+\r
+        private void SetEventHandlers()\r
+        {\r
+            SetMainFormEventHandler();\r
+            SetContextMenuMainEventHandler();\r
+            SetContextMenuNotifyIconEventHandler();\r
+            SetNotifyIconEventHandler();\r
+            SetRepairListEventHandler();\r
+        }\r
+\r
+        private void SetMainFormEventHandler()\r
+        {\r
+            Form.Load += MainForm_Load;\r
+            Form.FormClosing += MainForm_FormClosing;\r
+            Form.Resize += MainForm_Resize;\r
+            Form.Activated += MainForm_Activated;\r
+        }\r
+\r
+        private void SetContextMenuMainEventHandler()\r
+        {\r
+            _contextMenuMain.SetClickHandlers(\r
+                _listFormGroup.ShowOrCreate,\r
+                _main.ShowReport,\r
+                _main.StartCapture,\r
+                _main.ShowConfigDialog,\r
+                Form.Close);\r
+        }\r
+\r
+        private void SetContextMenuNotifyIconEventHandler()\r
+        {\r
+            _contextMenuNotifyIcon.SetEventHandlers(RevertFromIcon, Form.Close);\r
+        }\r
+\r
+        private void SetNotifyIconEventHandler()\r
+        {\r
+            _c.notifyIconMain.MouseDoubleClick += notifyIconMain_MouseDoubleClick;\r
+        }\r
+\r
+        private void SetRepairListEventHandler()\r
+        {\r
+            _c.labelRepairListCaption.Click += labelRepairListButton_Click;\r
+            _c.dropDownButtonRepairList.Click += labelRepairListButton_Click;\r
+        }\r
+\r
+        private void SetupUpdateable()\r
+        {\r
+            _updateable = new IUpdateContext[]\r
+            {\r
+                _c.hqPanel, _c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.materialHistoryPanel, _c.mainFleetPanel,\r
+                Notifier\r
+            };\r
+            var context = new UpdateContext(Sniffer, Config, () => _main.Step);\r
+            foreach (var updateable in _updateable)\r
+                updateable.Context = context;\r
+            _timers = new IUpdateTimers[] {_c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.mainFleetPanel};\r
+        }\r
+\r
+        private void SetScaleFactorOfDpiScaling()\r
+        {\r
+            var autoScaleDimensions = new SizeF(6f, 12f); // AutoScaleDimensionの初期値\r
+            Scaler.Factor = new SizeF(Form.CurrentAutoScaleDimensions.Width / autoScaleDimensions.Width,\r
+                Form.CurrentAutoScaleDimensions.Height / autoScaleDimensions.Height);\r
+        }\r
+\r
+        private void SetupQuestPanel()\r
+        {\r
+            int prevHeight = _c.questPanel.Height;\r
+            _c.questPanel.CreateLabels(Config.QuestLines);\r
+            Form.Height += _c.questPanel.Height - prevHeight;\r
+        }\r
+\r
+        public void UpdateInfo(Sniffer.Update update)\r
+        {\r
+            if (update == Sniffer.Update.Start)\r
+            {\r
+                _c.hqPanel.Login.Visible = false;\r
+                _c.mainFleetPanel.Start();\r
+                Notifier.StopAllRepeat();\r
+                return;\r
+            }\r
+            if (!Sniffer.Started)\r
+                return;\r
+            if ((update & Sniffer.Update.Item) != 0)\r
+                UpdateItemInfo();\r
+            if ((update & Sniffer.Update.Timer) != 0)\r
+                UpdateTimers();\r
+            if ((update & Sniffer.Update.NDock) != 0)\r
+                UpdateNDocLabels();\r
+            if ((update & Sniffer.Update.Mission) != 0)\r
+                UpdateMissionLabels();\r
+            if ((update & Sniffer.Update.QuestList) != 0)\r
+                UpdateQuestList();\r
+            if ((update & Sniffer.Update.Ship) != 0)\r
+                UpdateShipInfo();\r
+            if ((update & Sniffer.Update.Battle) != 0)\r
+                UpdateBattleInfo();\r
+            if ((update & Sniffer.Update.Cell) != 0)\r
+                UpdateCellInfo();\r
+        }\r
+\r
+        private void MainForm_Load(object sender, EventArgs e)\r
+        {\r
+            SuppressActivate.Start();\r
+            RestoreLocation();\r
+            if (Config.HideOnMinimized && Form.WindowState == FormWindowState.Minimized)\r
+                Form.ShowInTaskbar = false;\r
+            if (Config.ShowHpInPercent)\r
+                _c.mainFleetPanel.ToggleHpPercent();\r
+            if (Config.ShipList.Visible)\r
+                _listFormGroup.Show();\r
+            _main.CheckVersionUpMain(_c.mainFleetPanel.Guide);\r
+        }\r
+\r
+        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
+        {\r
+            if (!Config.ExitSilently)\r
+            {\r
+                using var dialog = new ConfirmDialog();\r
+                if (dialog.ShowDialog(Form) != DialogResult.Yes)\r
+                {\r
+                    e.Cancel = true;\r
+                    return;\r
+                }\r
+            }\r
+            _listFormGroup.Close();\r
+            Config.Location = (Form.WindowState == FormWindowState.Normal ? Form.Bounds : Form.RestoreBounds).Location;\r
+            Config.ShowHpInPercent = _c.mainFleetPanel.ShowHpInPercent;\r
+        }\r
+\r
+        private void MainForm_Resize(object sender, EventArgs e)\r
+        {\r
+            if (_listFormGroup == null) // DPIが100%でないときにInitializeComponentから呼ばれるので\r
+                return;\r
+            SuppressActivate.Start();\r
+            if (Form.WindowState == FormWindowState.Minimized)\r
+            {\r
+                if (Config.HideOnMinimized)\r
+                    Form.ShowInTaskbar = false;\r
+            }\r
+            _listFormGroup.Main.ChangeWindowState(Form.WindowState);\r
+        }\r
+\r
+        public readonly TimeOutChecker SuppressActivate = new TimeOutChecker();\r
+\r
+        private void MainForm_Activated(object sender, EventArgs e)\r
+        {\r
+            if (SuppressActivate.Check())\r
+                return;\r
+            if (NeedRaise)\r
+                RaiseBothWindows();\r
+        }\r
+\r
+        private bool NeedRaise => _listFormGroup.Visible && Form.WindowState != FormWindowState.Minimized;\r
+\r
+        private void RaiseBothWindows()\r
+        {\r
+            _listFormGroup.Main.Owner = null;\r
+            Form.Owner = _listFormGroup.Main;\r
+            Form.BringToFront();\r
+            Form.Owner = null;\r
+        }\r
+\r
+        public class TimeOutChecker\r
+        {\r
+            private DateTime _lastCheck;\r
+            private readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(500);\r
+\r
+            public void Start()\r
+            {\r
+                _lastCheck = DateTime.Now;\r
+            }\r
+\r
+            public bool Check()\r
+            {\r
+                var now = DateTime.Now;\r
+                var last = _lastCheck;\r
+                _lastCheck = now;\r
+                return now - last < _timeout;\r
+            }\r
+        }\r
+\r
+        private void RevertFromIcon()\r
+        {\r
+            Form.ShowInTaskbar = true;\r
+            Form.WindowState = FormWindowState.Normal;\r
+            Form.TopMost = _listFormGroup.TopMost = Config.TopMost; // 最前面に表示されなくなることがあるのを回避する\r
+        }\r
+\r
+        private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
+        {\r
+            RevertFromIcon();\r
+        }\r
+\r
+        private void PerformZoom()\r
+        {\r
+            if (Config.Zoom == 100)\r
+            {\r
+                ShipLabel.Name.BaseFont = Form.Font;\r
+                ShipLabel.Name.LatinFont = LatinFont();\r
+                return;\r
+            }\r
+            var prev = Form.CurrentAutoScaleDimensions;\r
+            foreach (var control in new Control[]\r
+            {\r
+                Form, _c.mainFleetPanel.Guide, _c.hqPanel.Login,\r
+                _contextMenuMain\r
+            }.Concat(_main.Controls))\r
+            {\r
+                control.Font = ZoomFont(control.Font);\r
+            }\r
+            _listFormGroup.Font = ZoomFont(_listFormGroup.Font);\r
+            foreach (var toolTip in new[] {_toolTip, _tooltipCopy})\r
+            {\r
+                toolTip.Font = ZoomFont(toolTip.Font);\r
+            }\r
+            ShipLabel.Name.BaseFont = Form.Font;\r
+            ShipLabel.Name.LatinFont = LatinFont();\r
+            var cur = Form.CurrentAutoScaleDimensions;\r
+            Scaler.Factor = Scaler.Scale(cur.Width / prev.Width, cur.Height / prev.Height);\r
+        }\r
+\r
+        private Font ZoomFont(Font font)\r
+        {\r
+            return new Font(font.FontFamily, font.Size * Config.Zoom / 100);\r
+        }\r
+\r
+        private Font LatinFont()\r
+        {\r
+            return new Font("Tahoma", 8f * Config.Zoom / 100);\r
+        }\r
+\r
+        private void RestoreLocation()\r
+        {\r
+            if (Config.Location.X == int.MinValue)\r
+                return;\r
+            if (IsTitleBarOnAnyScreen(Config.Location))\r
+                Form.Location = Config.Location;\r
+        }\r
+\r
+        public void ApplyConfig()\r
+        {\r
+            if (Form.TopMost != Config.TopMost)\r
+                Form.TopMost = _listFormGroup.TopMost = Config.TopMost;\r
+            _c.hqPanel.Update();\r
+            _c.labelAkashiRepair.Visible = _c.labelAkashiRepairTimer.Visible = Config.UsePresetAkashi;\r
+        }\r
+\r
+        public static bool IsTitleBarOnAnyScreen(Point location)\r
+        {\r
+            var rect = new Rectangle(\r
+                new Point(location.X + SystemInformation.IconSize.Width + SystemInformation.HorizontalFocusThickness,\r
+                    location.Y + SystemInformation.CaptionHeight), new Size(60, 1));\r
+            return Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect));\r
+        }\r
+\r
+        private void ShowShipOnShipList(int id)\r
+        {\r
+            if (!_listFormGroup.Visible)\r
+                return;\r
+            _listFormGroup.ShowShip(id);\r
+        }\r
+\r
+        public void UpdateItemInfo()\r
+        {\r
+            _c.hqPanel.Update();\r
+            Notifier.NotifyShipItemCount();\r
+            _c.materialHistoryPanel.Update();\r
+            if (_listFormGroup.Visible)\r
+                _listFormGroup.UpdateList();\r
+        }\r
+\r
+        private void UpdateShipInfo()\r
+        {\r
+            _c.mainFleetPanel.Update();\r
+            Notifier.NotifyDamagedShip();\r
+            UpdateChargeInfo();\r
+            UpdateRepairList();\r
+            UpdateMissionLabels();\r
+            if (_listFormGroup.Visible)\r
+                _listFormGroup.UpdateList();\r
+        }\r
+\r
+        private void UpdateBattleInfo()\r
+        {\r
+            _listFormGroup.UpdateBattleResult();\r
+            _listFormGroup.UpdateAirBattleResult();\r
+            _c.mainFleetPanel.UpdateBattleInfo();\r
+        }\r
+\r
+        private void UpdateCellInfo()\r
+        {\r
+            _listFormGroup.UpdateCellInfo();\r
+        }\r
+\r
+        private void UpdateChargeInfo()\r
+        {\r
+            _c.mainFleetPanel.UpdateChargeInfo();\r
+        }\r
+\r
+        private void UpdateNDocLabels()\r
+        {\r
+            _c.ndockPanel.Update();\r
+        }\r
+\r
+        private void UpdateMissionLabels()\r
+        {\r
+            _c.missionPanel.Update();\r
+        }\r
+\r
+        public void UpdateTimers()\r
+        {\r
+            foreach (var timer in _timers)\r
+                timer.UpdateTimers();\r
+        }\r
+\r
+        private void UpdateRepairList()\r
+        {\r
+            _c.panelRepairList.SetRepairList(Sniffer.RepairList);\r
+            _toolTip.SetToolTip(_c.labelRepairListCaption, new RepairShipCount(Sniffer.RepairList).ToString());\r
+        }\r
+\r
+        private void UpdateQuestList()\r
+        {\r
+            _c.questPanel.Update(Sniffer.Quests);\r
+            _c.labelQuestCount.Text = Sniffer.Quests.Length.ToString();\r
+            Notifier.NotifyQuestComplete();\r
+        }\r
+\r
+        private void FlashWindow()\r
+        {\r
+            Win32API.FlashWindow(Form.Handle);\r
+        }\r
+\r
+        private void ShowTaster(string title, string message)\r
+        {\r
+            _c.notifyIconMain.ShowBalloonTip(20000, title, message, ToolTipIcon.Info);\r
+        }\r
+\r
+        private void PlaySound(string file, int volume)\r
+        {\r
+            SoundPlayer.PlaySound(Form.Handle, file, volume);\r
+        }\r
+\r
+        private void labelRepairListButton_Click(object sender, EventArgs e)\r
+        {\r
+            if (_c.panelRepairList.Visible)\r
+            {\r
+                _c.panelRepairList.Visible = false;\r
+                _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;\r
+            }\r
+            else\r
+            {\r
+                _c.panelRepairList.Visible = true;\r
+                _c.panelRepairList.BringToFront();\r
+                _c.dropDownButtonRepairList.BackColor = CustomColors.ActiveButtonColor;\r
+            }\r
+        }\r
+\r
+        private void panelRepairList_Click(object sender, EventArgs e)\r
+        {\r
+            _c.panelRepairList.Visible = false;\r
+            _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;\r
+        }\r
+    }\r
+}
\ No newline at end of file