OSDN Git Service

RepairListForMainをRepairListPanelに変える
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / MainWindow.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Drawing;\r
4 using System.Linq;\r
5 using System.Reflection;\r
6 using System.Windows.Forms;\r
7 using KancolleSniffer.Forms;\r
8 using KancolleSniffer.Notification;\r
9 using KancolleSniffer.Util;\r
10 using KancolleSniffer.View;\r
11 using KancolleSniffer.View.MainWindow;\r
12 \r
13 namespace KancolleSniffer\r
14 {\r
15     public class MainWindow\r
16     {\r
17         private readonly ResizableToolTip _toolTip = new ResizableToolTip();\r
18         private readonly ResizableToolTip _tooltipCopy = new ResizableToolTip {ShowAlways = false, AutomaticDelay = 0};\r
19         private readonly ListFormGroup _listFormGroup;\r
20         private readonly ContextMenuMain _contextMenuMain = new ContextMenuMain();\r
21         private readonly ContextMenuNotifyIcon _contextMenuNotifyIcon = new ContextMenuNotifyIcon();\r
22         private readonly Components _c;\r
23 \r
24         private IEnumerable<IUpdateContext> _updateable;\r
25         private IEnumerable<IUpdateTimers> _timers;\r
26         private Main _main;\r
27 \r
28         public Sniffer Sniffer { get; private set; }\r
29         public Config Config { get; private set; }\r
30         public Label PlayLogSign => _c.hqPanel.PlayLog;\r
31         public Notifier Notifier { get; }\r
32         public Form Form { get; }\r
33 \r
34         private class Components\r
35         {\r
36             // ReSharper disable InconsistentNaming\r
37             // ReSharper disable UnusedAutoPropertyAccessor.Local\r
38             public NotifyIcon notifyIconMain { get; set; }\r
39             public HqPanel hqPanel { get; set; }\r
40             public MainFleetPanel mainFleetPanel { get; set; }\r
41             public Label labelNDockCaption { get; set; }\r
42             public NDockPanel ndockPanel { get; set; }\r
43             public KDockPanel kdockPanel { get; set; }\r
44             public Label labelMissionCaption { get; set; }\r
45             public MissionPanel missionPanel { get; set; }\r
46             public Label labelMaterialCaption { get; set; }\r
47             public DropDownButton dropDownButtonMaterialHistory { get; set; }\r
48             public MaterialHistoryPanel materialHistoryPanel { get; set; }\r
49             public Label labelQuestCount { get; set; }\r
50             public QuestPanel questPanel { get; set; }\r
51             public Label labelAkashiRepair { get; set; }\r
52             public Label labelAkashiRepairTimer { get; set; }\r
53             public Label labelRepairListCaption { get; set; }\r
54             public Label dropDownButtonRepairList { get; set; }\r
55             public RepairListPanel panelRepairList { get; set; }\r
56             // ReSharper restore InconsistentNaming\r
57             // ReSharper restore UnusedAutoPropertyAccessor.Local\r
58         }\r
59 \r
60         public MainWindow(Main main, Form form)\r
61         {\r
62             _c = GetComponents(form);\r
63             Form = form;\r
64             _c.notifyIconMain.ContextMenuStrip = _contextMenuNotifyIcon;\r
65             Form.ContextMenuStrip = _contextMenuMain;\r
66             Form.ContextMenuStrip = _contextMenuMain;\r
67             SetupMain(main);\r
68             _listFormGroup = new ListFormGroup(this);\r
69             Notifier = new Notifier(FlashWindow, ShowTaster, PlaySound);\r
70             SetupView();\r
71         }\r
72 \r
73         private Components GetComponents(Form form)\r
74         {\r
75             var r = new Components();\r
76             foreach (var prop in typeof(Components).GetProperties())\r
77             {\r
78                 // ReSharper disable once PossibleNullReferenceException\r
79                 prop.SetValue(r,\r
80                     form.GetType().GetField(prop.Name, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(form));\r
81             }\r
82             return r;\r
83         }\r
84 \r
85         private void SetupMain(Main main)\r
86         {\r
87             _main = main;\r
88             Config = main.Config;\r
89             Sniffer = main.Sniffer;\r
90         }\r
91 \r
92         private void SetupView()\r
93         {\r
94             SetScaleFactorOfDpiScaling();\r
95             SetupQuestPanel();\r
96             SetEventHandlers();\r
97             _c.mainFleetPanel.AkashiRepairTimer = _c.labelAkashiRepairTimer;\r
98             _c.mainFleetPanel.ShowShipOnList = ShowShipOnShipList;\r
99             _c.panelRepairList.CreateLabels(panelRepairList_Click);\r
100             _c.ndockPanel.SetClickHandler(_c.labelNDockCaption);\r
101             _c.missionPanel.SetClickHandler(_c.labelMissionCaption);\r
102             _c.materialHistoryPanel.SetClickHandler(_c.labelMaterialCaption, _c.dropDownButtonMaterialHistory);\r
103             SetupUpdateable();\r
104             PerformZoom();\r
105         }\r
106 \r
107         private void SetEventHandlers()\r
108         {\r
109             SetMainFormEventHandler();\r
110             SetContextMenuMainEventHandler();\r
111             SetContextMenuNotifyIconEventHandler();\r
112             SetNotifyIconEventHandler();\r
113             SetRepairListEventHandler();\r
114         }\r
115 \r
116         private void SetMainFormEventHandler()\r
117         {\r
118             Form.Load += MainForm_Load;\r
119             Form.FormClosing += MainForm_FormClosing;\r
120             Form.Resize += MainForm_Resize;\r
121             Form.Activated += MainForm_Activated;\r
122         }\r
123 \r
124         private void SetContextMenuMainEventHandler()\r
125         {\r
126             _contextMenuMain.SetClickHandlers(\r
127                 _listFormGroup.ShowOrCreate,\r
128                 _main.ShowReport,\r
129                 _main.StartCapture,\r
130                 _main.ShowConfigDialog,\r
131                 Form.Close);\r
132         }\r
133 \r
134         private void SetContextMenuNotifyIconEventHandler()\r
135         {\r
136             _contextMenuNotifyIcon.SetEventHandlers(RevertFromIcon, Form.Close);\r
137         }\r
138 \r
139         private void SetNotifyIconEventHandler()\r
140         {\r
141             _c.notifyIconMain.MouseDoubleClick += notifyIconMain_MouseDoubleClick;\r
142         }\r
143 \r
144         private void SetRepairListEventHandler()\r
145         {\r
146             _c.labelRepairListCaption.Click += labelRepairListButton_Click;\r
147             _c.dropDownButtonRepairList.Click += labelRepairListButton_Click;\r
148         }\r
149 \r
150         private void SetupUpdateable()\r
151         {\r
152             _updateable = new IUpdateContext[]\r
153             {\r
154                 _c.hqPanel, _c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.materialHistoryPanel, _c.mainFleetPanel,\r
155                 Notifier\r
156             };\r
157             var context = new UpdateContext(Sniffer, Config, () => _main.Step);\r
158             foreach (var updateable in _updateable)\r
159                 updateable.Context = context;\r
160             _timers = new IUpdateTimers[] {_c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.mainFleetPanel};\r
161         }\r
162 \r
163         private void SetScaleFactorOfDpiScaling()\r
164         {\r
165             var autoScaleDimensions = new SizeF(6f, 12f); // AutoScaleDimensionの初期値\r
166             Scaler.Factor = new SizeF(Form.CurrentAutoScaleDimensions.Width / autoScaleDimensions.Width,\r
167                 Form.CurrentAutoScaleDimensions.Height / autoScaleDimensions.Height);\r
168         }\r
169 \r
170         private void SetupQuestPanel()\r
171         {\r
172             var prevHeight = _c.questPanel.Height;\r
173             _c.questPanel.CreateLabels(Config.QuestLines);\r
174             Form.Height += _c.questPanel.Height - prevHeight;\r
175         }\r
176 \r
177         public void UpdateInfo(Sniffer.Update update)\r
178         {\r
179             if (update == Sniffer.Update.Start)\r
180             {\r
181                 _c.hqPanel.Login.Visible = false;\r
182                 _c.mainFleetPanel.Start();\r
183                 Notifier.StopAllRepeat();\r
184                 return;\r
185             }\r
186             if (!Sniffer.Started)\r
187                 return;\r
188             if ((update & Sniffer.Update.Item) != 0)\r
189                 UpdateItemInfo();\r
190             if ((update & Sniffer.Update.Timer) != 0)\r
191                 UpdateTimers();\r
192             if ((update & Sniffer.Update.NDock) != 0)\r
193                 UpdateNDocLabels();\r
194             if ((update & Sniffer.Update.Mission) != 0)\r
195                 UpdateMissionLabels();\r
196             if ((update & Sniffer.Update.QuestList) != 0)\r
197                 UpdateQuestList();\r
198             if ((update & Sniffer.Update.Ship) != 0)\r
199                 UpdateShipInfo();\r
200             if ((update & Sniffer.Update.Battle) != 0)\r
201                 UpdateBattleInfo();\r
202             if ((update & Sniffer.Update.Cell) != 0)\r
203                 UpdateCellInfo();\r
204         }\r
205 \r
206         private void MainForm_Load(object sender, EventArgs e)\r
207         {\r
208             SuppressActivate.Start();\r
209             RestoreLocation();\r
210             if (Config.HideOnMinimized && Form.WindowState == FormWindowState.Minimized)\r
211                 Form.ShowInTaskbar = false;\r
212             if (Config.ShowHpInPercent)\r
213                 _c.mainFleetPanel.ToggleHpPercent();\r
214             if (Config.ShipList.Visible)\r
215                 _listFormGroup.Show();\r
216             _main.CheckVersionUpMain(_c.mainFleetPanel.Guide);\r
217         }\r
218 \r
219         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
220         {\r
221             if (!Config.ExitSilently)\r
222             {\r
223                 using var dialog = new ConfirmDialog();\r
224                 if (dialog.ShowDialog(Form) != DialogResult.Yes)\r
225                 {\r
226                     e.Cancel = true;\r
227                     return;\r
228                 }\r
229             }\r
230             _listFormGroup.Close();\r
231             Config.Location = (Form.WindowState == FormWindowState.Normal ? Form.Bounds : Form.RestoreBounds).Location;\r
232             Config.ShowHpInPercent = _c.mainFleetPanel.ShowHpInPercent;\r
233         }\r
234 \r
235         private void MainForm_Resize(object sender, EventArgs e)\r
236         {\r
237             if (_listFormGroup == null) // DPIが100%でないときにInitializeComponentから呼ばれるので\r
238                 return;\r
239             SuppressActivate.Start();\r
240             if (Form.WindowState == FormWindowState.Minimized)\r
241             {\r
242                 if (Config.HideOnMinimized)\r
243                     Form.ShowInTaskbar = false;\r
244             }\r
245             _listFormGroup.Main.ChangeWindowState(Form.WindowState);\r
246         }\r
247 \r
248         public readonly TimeOutChecker SuppressActivate = new TimeOutChecker();\r
249 \r
250         private void MainForm_Activated(object sender, EventArgs e)\r
251         {\r
252             if (SuppressActivate.Check())\r
253                 return;\r
254             if (NeedRaise)\r
255                 RaiseBothWindows();\r
256         }\r
257 \r
258         private bool NeedRaise => _listFormGroup.Visible && Form.WindowState != FormWindowState.Minimized;\r
259 \r
260         private void RaiseBothWindows()\r
261         {\r
262             _listFormGroup.Main.Owner = null;\r
263             Form.Owner = _listFormGroup.Main;\r
264             Form.BringToFront();\r
265             Form.Owner = null;\r
266         }\r
267 \r
268         public class TimeOutChecker\r
269         {\r
270             private DateTime _lastCheck;\r
271             private readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(500);\r
272 \r
273             public void Start()\r
274             {\r
275                 _lastCheck = DateTime.Now;\r
276             }\r
277 \r
278             public bool Check()\r
279             {\r
280                 var now = DateTime.Now;\r
281                 var last = _lastCheck;\r
282                 _lastCheck = now;\r
283                 return now - last < _timeout;\r
284             }\r
285         }\r
286 \r
287         private void RevertFromIcon()\r
288         {\r
289             Form.ShowInTaskbar = true;\r
290             Form.WindowState = FormWindowState.Normal;\r
291             Form.TopMost = _listFormGroup.TopMost = Config.TopMost; // 最前面に表示されなくなることがあるのを回避する\r
292         }\r
293 \r
294         private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
295         {\r
296             RevertFromIcon();\r
297         }\r
298 \r
299         private void PerformZoom()\r
300         {\r
301             if (Config.Zoom == 100)\r
302             {\r
303                 ShipLabel.Name.BaseFont = Form.Font;\r
304                 ShipLabel.Name.LatinFont = LatinFont();\r
305                 return;\r
306             }\r
307             var prev = Form.CurrentAutoScaleDimensions;\r
308             foreach (var control in new Control[]\r
309             {\r
310                 Form, _c.mainFleetPanel.Guide, _c.hqPanel.Login,\r
311                 _contextMenuMain\r
312             }.Concat(_main.Controls))\r
313             {\r
314                 control.Font = ZoomFont(control.Font);\r
315             }\r
316             _listFormGroup.Font = ZoomFont(_listFormGroup.Font);\r
317             foreach (var toolTip in new[] {_toolTip, _tooltipCopy})\r
318             {\r
319                 toolTip.Font = ZoomFont(toolTip.Font);\r
320             }\r
321             ShipLabel.Name.BaseFont = Form.Font;\r
322             ShipLabel.Name.LatinFont = LatinFont();\r
323             var cur = Form.CurrentAutoScaleDimensions;\r
324             Scaler.Factor = Scaler.Scale(cur.Width / prev.Width, cur.Height / prev.Height);\r
325         }\r
326 \r
327         private Font ZoomFont(Font font)\r
328         {\r
329             return new Font(font.FontFamily, font.Size * Config.Zoom / 100);\r
330         }\r
331 \r
332         private Font LatinFont()\r
333         {\r
334             return new Font("Tahoma", 8f * Config.Zoom / 100);\r
335         }\r
336 \r
337         private void RestoreLocation()\r
338         {\r
339             if (Config.Location.X == int.MinValue)\r
340                 return;\r
341             if (IsTitleBarOnAnyScreen(Config.Location))\r
342                 Form.Location = Config.Location;\r
343         }\r
344 \r
345         public void ApplyConfig()\r
346         {\r
347             if (Form.TopMost != Config.TopMost)\r
348                 Form.TopMost = _listFormGroup.TopMost = Config.TopMost;\r
349             _c.hqPanel.Update();\r
350             _c.labelAkashiRepair.Visible = _c.labelAkashiRepairTimer.Visible = Config.UsePresetAkashi;\r
351         }\r
352 \r
353         public static bool IsTitleBarOnAnyScreen(Point location)\r
354         {\r
355             var rect = new Rectangle(\r
356                 new Point(location.X + SystemInformation.IconSize.Width + SystemInformation.HorizontalFocusThickness,\r
357                     location.Y + SystemInformation.CaptionHeight), new Size(60, 1));\r
358             return Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect));\r
359         }\r
360 \r
361         private void ShowShipOnShipList(int id)\r
362         {\r
363             if (!_listFormGroup.Visible)\r
364                 return;\r
365             _listFormGroup.ShowShip(id);\r
366         }\r
367 \r
368         public void UpdateItemInfo()\r
369         {\r
370             _c.hqPanel.Update();\r
371             Notifier.NotifyShipItemCount();\r
372             _c.materialHistoryPanel.Update();\r
373             if (_listFormGroup.Visible)\r
374                 _listFormGroup.UpdateList();\r
375         }\r
376 \r
377         private void UpdateShipInfo()\r
378         {\r
379             _c.mainFleetPanel.Update();\r
380             Notifier.NotifyDamagedShip();\r
381             UpdateChargeInfo();\r
382             UpdateRepairList();\r
383             UpdateMissionLabels();\r
384             if (_listFormGroup.Visible)\r
385                 _listFormGroup.UpdateList();\r
386         }\r
387 \r
388         private void UpdateBattleInfo()\r
389         {\r
390             _listFormGroup.UpdateBattleResult();\r
391             _listFormGroup.UpdateAirBattleResult();\r
392             _c.mainFleetPanel.UpdateBattleInfo();\r
393         }\r
394 \r
395         private void UpdateCellInfo()\r
396         {\r
397             _listFormGroup.UpdateCellInfo();\r
398         }\r
399 \r
400         private void UpdateChargeInfo()\r
401         {\r
402             _c.mainFleetPanel.UpdateChargeInfo();\r
403         }\r
404 \r
405         private void UpdateNDocLabels()\r
406         {\r
407             _c.ndockPanel.Update();\r
408         }\r
409 \r
410         private void UpdateMissionLabels()\r
411         {\r
412             _c.missionPanel.Update();\r
413         }\r
414 \r
415         public void UpdateTimers()\r
416         {\r
417             foreach (var timer in _timers)\r
418                 timer.UpdateTimers();\r
419         }\r
420 \r
421         private void UpdateRepairList()\r
422         {\r
423             _c.panelRepairList.SetRepairList(Sniffer.RepairList);\r
424             _toolTip.SetToolTip(_c.labelRepairListCaption, new RepairShipCount(Sniffer.RepairList).ToString());\r
425         }\r
426 \r
427         private void UpdateQuestList()\r
428         {\r
429             _c.questPanel.Update(Sniffer.Quests);\r
430             _c.labelQuestCount.Text = Sniffer.Quests.Length.ToString();\r
431             Notifier.NotifyQuestComplete();\r
432         }\r
433 \r
434         private void FlashWindow()\r
435         {\r
436             Win32API.FlashWindow(Form.Handle);\r
437         }\r
438 \r
439         private void ShowTaster(string title, string message)\r
440         {\r
441             _c.notifyIconMain.ShowBalloonTip(20000, title, message, ToolTipIcon.Info);\r
442         }\r
443 \r
444         private void PlaySound(string file, int volume)\r
445         {\r
446             SoundPlayer.PlaySound(Form.Handle, file, volume);\r
447         }\r
448 \r
449         private void labelRepairListButton_Click(object sender, EventArgs e)\r
450         {\r
451             if (_c.panelRepairList.Visible)\r
452             {\r
453                 _c.panelRepairList.Visible = false;\r
454                 _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;\r
455             }\r
456             else\r
457             {\r
458                 _c.panelRepairList.Visible = true;\r
459                 _c.panelRepairList.BringToFront();\r
460                 _c.dropDownButtonRepairList.BackColor = CustomColors.ActiveButtonColor;\r
461             }\r
462         }\r
463 \r
464         private void panelRepairList_Click(object sender, EventArgs e)\r
465         {\r
466             _c.panelRepairList.Visible = false;\r
467             _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;\r
468         }\r
469     }\r
470 }