2 using System.Collections.Generic;
\r
3 using System.Drawing;
\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
13 namespace KancolleSniffer
\r
15 public class MainWindow
\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
24 private IEnumerable<IUpdateContext> _updateable;
\r
25 private IEnumerable<IUpdateTimers> _timers;
\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
34 private class Components
\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 FleetPanel fleetPanel { get; set; }
\r
41 public Label labelNDockCaption { get; set; }
\r
42 public NDockPanel ndockPanel { get; set; }
\r
43 public Label labelKDockCaption { get; set; }
\r
44 public KDockPanel kdockPanel { get; set; }
\r
45 public Label labelMissionCaption { get; set; }
\r
46 public MissionPanel missionPanel { get; set; }
\r
47 public Label labelMaterialCaption { get; set; }
\r
48 public DropDownButton dropDownButtonMaterialHistory { get; set; }
\r
49 public MaterialHistoryPanel materialHistoryPanel { get; set; }
\r
50 public Label labelQuestCaption { get; set; }
\r
51 public Label labelQuestCount { get; set; }
\r
52 public QuestPanel questPanel { get; set; }
\r
53 public Label labelAkashiRepair { get; set; }
\r
54 public Label labelAkashiRepairTimer { get; set; }
\r
55 public Label labelRepairListCaption { get; set; }
\r
56 public Label dropDownButtonRepairList { get; set; }
\r
57 public RepairListPanel panelRepairList { get; set; }
\r
58 // ReSharper restore InconsistentNaming
\r
59 // ReSharper restore UnusedAutoPropertyAccessor.Local
\r
62 public MainWindow(Main main, Form form)
\r
64 _c = GetComponents(form);
\r
66 _c.notifyIconMain.ContextMenuStrip = _contextMenuNotifyIcon;
\r
67 Form.ContextMenuStrip = _contextMenuMain;
\r
68 Form.ContextMenuStrip = _contextMenuMain;
\r
70 _listFormGroup = new ListFormGroup(this);
\r
71 Notifier = new Notifier(FlashWindow, ShowTaster, PlaySound);
\r
75 private Components GetComponents(Form form)
\r
77 var r = new Components();
\r
78 foreach (var prop in typeof(Components).GetProperties())
\r
80 // ReSharper disable once PossibleNullReferenceException
\r
82 form.GetType().GetField(prop.Name, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(form));
\r
87 private void SetupMain(Main main)
\r
90 Config = main.Config;
\r
91 Sniffer = main.Sniffer;
\r
94 private void SetupView()
\r
96 SetScaleFactorOfDpiScaling();
\r
97 if (Config.Shape == "横長2")
\r
98 ChangeHorizontalLayout();
\r
100 SetEventHandlers();
\r
101 _c.fleetPanel.AkashiRepairTimer = _c.labelAkashiRepairTimer;
\r
102 _c.fleetPanel.ShowShipOnList = ShowShipOnShipList;
\r
103 _c.panelRepairList.CreateLabels(panelRepairList_Click);
\r
104 _c.ndockPanel.SetClickHandler(_c.labelNDockCaption);
\r
105 _c.missionPanel.SetClickHandler(_c.labelMissionCaption);
\r
106 _c.materialHistoryPanel.SetClickHandler(_c.labelMaterialCaption, _c.dropDownButtonMaterialHistory);
\r
111 private void ChangeHorizontalLayout()
\r
113 var diff = _c.missionPanel.Left - _c.hqPanel.Left;
\r
114 foreach (var control in new Control[]
\r
116 _c.hqPanel, _c.questPanel, _c.labelQuestCaption, _c.labelQuestCount, _c.materialHistoryPanel,
\r
117 _c.dropDownButtonMaterialHistory, _c.labelMaterialCaption
\r
120 control.Left += diff;
\r
122 foreach (var control in new Control[]
\r
124 _c.missionPanel, _c.labelMissionCaption, _c.labelRepairListCaption, _c.panelRepairList,
\r
125 _c.dropDownButtonRepairList, _c.labelAkashiRepair, _c.labelAkashiRepairTimer,
\r
126 _c.ndockPanel, _c.labelNDockCaption, _c.kdockPanel, _c.labelKDockCaption
\r
129 control.Left -= diff;
\r
133 private void SetEventHandlers()
\r
135 SetMainFormEventHandler();
\r
136 SetContextMenuMainEventHandler();
\r
137 SetContextMenuNotifyIconEventHandler();
\r
138 SetNotifyIconEventHandler();
\r
139 SetRepairListEventHandler();
\r
142 private void SetMainFormEventHandler()
\r
144 Form.Load += MainForm_Load;
\r
145 Form.FormClosing += MainForm_FormClosing;
\r
146 Form.Resize += MainForm_Resize;
\r
147 Form.Activated += MainForm_Activated;
\r
150 private void SetContextMenuMainEventHandler()
\r
152 _contextMenuMain.SetClickHandlers(
\r
153 _listFormGroup.ShowOrCreate,
\r
155 _main.StartCapture,
\r
156 _main.ShowConfigDialog,
\r
160 private void SetContextMenuNotifyIconEventHandler()
\r
162 _contextMenuNotifyIcon.SetEventHandlers(RevertFromIcon, Form.Close);
\r
165 private void SetNotifyIconEventHandler()
\r
167 _c.notifyIconMain.MouseDoubleClick += notifyIconMain_MouseDoubleClick;
\r
170 private void SetRepairListEventHandler()
\r
172 _c.labelRepairListCaption.Click += labelRepairListButton_Click;
\r
173 _c.dropDownButtonRepairList.Click += labelRepairListButton_Click;
\r
176 private void SetupUpdateable()
\r
178 _updateable = new IUpdateContext[]
\r
180 _c.hqPanel, _c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.materialHistoryPanel, _c.fleetPanel,
\r
183 var context = new UpdateContext(Sniffer, Config, () => _main.Step);
\r
184 foreach (var updateable in _updateable)
\r
185 updateable.Context = context;
\r
186 _timers = new IUpdateTimers[] {_c.missionPanel, _c.kdockPanel, _c.ndockPanel, _c.fleetPanel};
\r
189 private void SetScaleFactorOfDpiScaling()
\r
191 var autoScaleDimensions = new SizeF(6f, 12f); // AutoScaleDimensionの初期値
\r
192 Scaler.Factor = new SizeF(Form.CurrentAutoScaleDimensions.Width / autoScaleDimensions.Width,
\r
193 Form.CurrentAutoScaleDimensions.Height / autoScaleDimensions.Height);
\r
196 private void SetupQuestPanel()
\r
198 var prevHeight = _c.questPanel.Height;
\r
199 _c.questPanel.CreateLabels(Config.QuestLines);
\r
200 Form.Height += _c.questPanel.Height - prevHeight;
\r
203 public void UpdateInfo(Sniffer.Update update)
\r
205 if (update == Sniffer.Update.Start)
\r
207 _c.hqPanel.Login.Visible = false;
\r
208 _c.fleetPanel.Start();
\r
209 Notifier.StopAllRepeat();
\r
212 if (!Sniffer.Started)
\r
214 if ((update & Sniffer.Update.Item) != 0)
\r
216 if ((update & Sniffer.Update.Timer) != 0)
\r
218 if ((update & Sniffer.Update.NDock) != 0)
\r
219 UpdateNDocLabels();
\r
220 if ((update & Sniffer.Update.Mission) != 0)
\r
221 UpdateMissionLabels();
\r
222 if ((update & Sniffer.Update.QuestList) != 0)
\r
224 if ((update & Sniffer.Update.Ship) != 0)
\r
226 if ((update & Sniffer.Update.Battle) != 0)
\r
227 UpdateBattleInfo();
\r
228 if ((update & Sniffer.Update.Cell) != 0)
\r
232 private void MainForm_Load(object sender, EventArgs e)
\r
234 SuppressActivate.Start();
\r
236 if (Config.HideOnMinimized && Form.WindowState == FormWindowState.Minimized)
\r
237 Form.ShowInTaskbar = false;
\r
238 if (Config.ShowHpInPercent)
\r
239 _c.fleetPanel.ToggleHpPercent();
\r
240 if (Config.ShipList.Visible)
\r
241 _listFormGroup.Show();
\r
242 _main.CheckVersionUpMain(_c.fleetPanel.Guide);
\r
245 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
\r
247 if (!Config.ExitSilently)
\r
249 using var dialog = new ConfirmDialog();
\r
250 if (dialog.ShowDialog(Form) != DialogResult.Yes)
\r
256 _listFormGroup.Close();
\r
257 Config.Location = (Form.WindowState == FormWindowState.Normal ? Form.Bounds : Form.RestoreBounds).Location;
\r
258 Config.ShowHpInPercent = _c.fleetPanel.ShowHpInPercent;
\r
261 private void MainForm_Resize(object sender, EventArgs e)
\r
263 if (_listFormGroup == null) // DPIが100%でないときにInitializeComponentから呼ばれるので
\r
265 SuppressActivate.Start();
\r
266 if (Form.WindowState == FormWindowState.Minimized)
\r
268 if (Config.HideOnMinimized)
\r
269 Form.ShowInTaskbar = false;
\r
271 _listFormGroup.Main.ChangeWindowState(Form.WindowState);
\r
274 public readonly TimeOutChecker SuppressActivate = new TimeOutChecker();
\r
276 private void MainForm_Activated(object sender, EventArgs e)
\r
278 if (SuppressActivate.Check())
\r
281 RaiseBothWindows();
\r
284 private bool NeedRaise => _listFormGroup.Visible && Form.WindowState != FormWindowState.Minimized;
\r
286 private void RaiseBothWindows()
\r
288 _listFormGroup.Main.Owner = null;
\r
289 Form.Owner = _listFormGroup.Main;
\r
290 Form.BringToFront();
\r
294 public class TimeOutChecker
\r
296 private DateTime _lastCheck;
\r
297 private readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(500);
\r
299 public void Start()
\r
301 _lastCheck = DateTime.Now;
\r
304 public bool Check()
\r
306 var now = DateTime.Now;
\r
307 var last = _lastCheck;
\r
309 return now - last < _timeout;
\r
313 private void RevertFromIcon()
\r
315 Form.ShowInTaskbar = true;
\r
316 Form.WindowState = FormWindowState.Normal;
\r
317 Form.TopMost = _listFormGroup.TopMost = Config.TopMost; // 最前面に表示されなくなることがあるのを回避する
\r
320 private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)
\r
325 private void PerformZoom()
\r
327 if (Config.Zoom == 100)
\r
329 ShipLabel.Name.BaseFont = Form.Font;
\r
330 ShipLabel.Name.LatinFont = LatinFont();
\r
333 var prev = Form.CurrentAutoScaleDimensions;
\r
334 foreach (var control in new Control[]
\r
336 Form, _c.fleetPanel.Guide, _c.hqPanel.Login,
\r
338 }.Concat(_main.Controls))
\r
340 control.Font = ZoomFont(control.Font);
\r
342 _listFormGroup.Font = ZoomFont(_listFormGroup.Font);
\r
343 foreach (var toolTip in new[] {_toolTip, _tooltipCopy})
\r
345 toolTip.Font = ZoomFont(toolTip.Font);
\r
347 ShipLabel.Name.BaseFont = Form.Font;
\r
348 ShipLabel.Name.LatinFont = LatinFont();
\r
349 var cur = Form.CurrentAutoScaleDimensions;
\r
350 Scaler.Factor = Scaler.Scale(cur.Width / prev.Width, cur.Height / prev.Height);
\r
353 private Font ZoomFont(Font font)
\r
355 return new Font(font.FontFamily, font.Size * Config.Zoom / 100);
\r
358 private Font LatinFont()
\r
360 return new Font("Tahoma", 8f * Config.Zoom / 100);
\r
363 private void RestoreLocation()
\r
365 if (Config.Location.X == int.MinValue)
\r
367 if (IsTitleBarOnAnyScreen(Config.Location))
\r
368 Form.Location = Config.Location;
\r
371 public void ApplyConfig()
\r
373 if (Form.TopMost != Config.TopMost)
\r
374 Form.TopMost = _listFormGroup.TopMost = Config.TopMost;
\r
375 _c.hqPanel.Update();
\r
376 _c.labelAkashiRepair.Visible = _c.labelAkashiRepairTimer.Visible = Config.UsePresetAkashi;
\r
379 public static bool IsTitleBarOnAnyScreen(Point location)
\r
381 var rect = new Rectangle(
\r
382 new Point(location.X + SystemInformation.IconSize.Width + SystemInformation.HorizontalFocusThickness,
\r
383 location.Y + SystemInformation.CaptionHeight), new Size(60, 1));
\r
384 return Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect));
\r
387 private void ShowShipOnShipList(int id)
\r
389 if (!_listFormGroup.Visible)
\r
391 _listFormGroup.ShowShip(id);
\r
394 public void UpdateItemInfo()
\r
396 _c.hqPanel.Update();
\r
397 Notifier.NotifyShipItemCount();
\r
398 _c.materialHistoryPanel.Update();
\r
399 if (_listFormGroup.Visible)
\r
400 _listFormGroup.UpdateList();
\r
403 private void UpdateShipInfo()
\r
405 _c.fleetPanel.Update();
\r
406 Notifier.NotifyDamagedShip();
\r
407 UpdateChargeInfo();
\r
408 UpdateRepairList();
\r
409 UpdateMissionLabels();
\r
410 if (_listFormGroup.Visible)
\r
411 _listFormGroup.UpdateList();
\r
414 private void UpdateBattleInfo()
\r
416 _listFormGroup.UpdateBattleResult();
\r
417 _listFormGroup.UpdateAirBattleResult();
\r
418 _c.fleetPanel.UpdateBattleInfo();
\r
421 private void UpdateCellInfo()
\r
423 _listFormGroup.UpdateCellInfo();
\r
426 private void UpdateChargeInfo()
\r
428 _c.fleetPanel.UpdateChargeInfo();
\r
431 private void UpdateNDocLabels()
\r
433 _c.ndockPanel.Update();
\r
436 private void UpdateMissionLabels()
\r
438 _c.missionPanel.Update();
\r
441 public void UpdateTimers()
\r
443 foreach (var timer in _timers)
\r
444 timer.UpdateTimers();
\r
447 private void UpdateRepairList()
\r
449 _c.panelRepairList.SetRepairList(Sniffer.RepairList);
\r
450 _toolTip.SetToolTip(_c.labelRepairListCaption, new RepairShipCount(Sniffer.RepairList).ToString());
\r
453 private void UpdateQuestList()
\r
455 _c.questPanel.Update(Sniffer.Quests);
\r
456 _c.labelQuestCount.Text = Sniffer.Quests.Length.ToString();
\r
457 Notifier.NotifyQuestComplete();
\r
460 private void FlashWindow()
\r
462 Win32API.FlashWindow(Form.Handle);
\r
465 private void ShowTaster(string title, string message)
\r
467 _c.notifyIconMain.ShowBalloonTip(20000, title, message, ToolTipIcon.Info);
\r
470 private void PlaySound(string file, int volume)
\r
472 SoundPlayer.PlaySound(Form.Handle, file, volume);
\r
475 private void labelRepairListButton_Click(object sender, EventArgs e)
\r
477 if (_c.panelRepairList.Visible)
\r
479 _c.panelRepairList.Visible = false;
\r
480 _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;
\r
484 _c.panelRepairList.Visible = true;
\r
485 _c.panelRepairList.BringToFront();
\r
486 _c.dropDownButtonRepairList.BackColor = CustomColors.ActiveButtonColor;
\r
490 private void panelRepairList_Click(object sender, EventArgs e)
\r
492 _c.panelRepairList.Visible = false;
\r
493 _c.dropDownButtonRepairList.BackColor = Control.DefaultBackColor;
\r