OSDN Git Service

一覧の自動戦況切り替えをマス情報の更新時にする
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Forms / ListForm.cs
1 // Copyright (C) 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\r
3 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Collections.Generic;\r
17 using System.Drawing;\r
18 using System.Linq;\r
19 using System.Windows.Forms;\r
20 using KancolleSniffer.Model;\r
21 using KancolleSniffer.View;\r
22 using KancolleSniffer.View.ListWindow;\r
23 using KancolleSniffer.View.ShipListPanel;\r
24 using Clipboard = KancolleSniffer.Util.Clipboard;\r
25 \r
26 namespace KancolleSniffer.Forms\r
27 {\r
28     public partial class ListForm : Form\r
29     {\r
30         private readonly Sniffer _sniffer;\r
31         private readonly Config _config;\r
32         private readonly Form _form;\r
33         private readonly MainWindow.TimeOutChecker _suppressActivate;\r
34         private readonly CheckBox[] _shipTypeCheckBoxes;\r
35         private bool _isMaster;\r
36         private Settings _settings;\r
37         public const int PanelWidth = 215;\r
38 \r
39         public class Settings\r
40         {\r
41             public string Mode { get; set; }\r
42             public ShipCategory ShipCategories { get; set; }\r
43             public bool ShipType { get; set; }\r
44             public bool ShowHpInPercent { get; set; }\r
45             public SortOrder SortOrder { get; set; }\r
46 \r
47             public static Settings FromShipListConfig(ShipListConfig config)\r
48             {\r
49                 return new Settings\r
50                 {\r
51                     Mode = config.Mode ?? "全艦",\r
52                     ShipCategories = config.ShipCategories,\r
53                     ShipType = config.ShipType,\r
54                     ShowHpInPercent = config.ShowHpInPercent,\r
55                     SortOrder = config.SortOrder\r
56                 };\r
57             }\r
58 \r
59             public void SetToShipListConfig(ShipListConfig config)\r
60             {\r
61                 config.Mode = Mode;\r
62                 config.ShipCategories = ShipCategories;\r
63                 config.ShipType = ShipType;\r
64                 config.ShowHpInPercent = ShowHpInPercent;\r
65                 config.SortOrder = SortOrder;\r
66             }\r
67         }\r
68 \r
69         private object[] PanelNames => new object[] {"全艦", "A", "B", "C", "D", "分類", "修復", "装備", "艦隊", "対空", "戦況", "情報"}\r
70             .Where(n => IsMaster || (string)n != "分類").ToArray();\r
71 \r
72         private char[] PanelKeys => new[] {'Z', 'A', 'B', 'C', 'D', 'G', 'R', 'W', 'X', 'Y', 'S', 'I'}\r
73             .Where(key => IsMaster || key != 'G').ToArray();\r
74 \r
75         public bool IsMaster\r
76         {\r
77             get => _isMaster;\r
78             set\r
79             {\r
80                 _isMaster = value;\r
81                 Text = _isMaster ? "一覧 プライマリ" : "一覧";\r
82                 comboBoxGroup.Items.Clear();\r
83                 comboBoxGroup.Items.AddRange(PanelNames);\r
84             }\r
85         }\r
86 \r
87         public enum SortOrder\r
88         {\r
89             None,\r
90             Cond,\r
91             CondAscend = Cond,\r
92             CondDescend,\r
93             ExpToNext,\r
94             ExpToNextAscend = ExpToNext,\r
95             ExpToNextDescend,\r
96             Repair\r
97         }\r
98 \r
99         public ListForm(MainWindow main)\r
100         {\r
101             InitializeComponent();\r
102             IsMaster = false;\r
103             _form = main.Form;\r
104             _sniffer = main.Sniffer;\r
105             _config = main.Config;\r
106             _suppressActivate = main.SuppressActivate;\r
107             _shipTypeCheckBoxes = new[]\r
108             {\r
109                 checkBoxSTypeBattleShip,\r
110                 checkBoxSTypeAircraftCarrier,\r
111                 checkBoxSTypeHeavyCruiser,\r
112                 checkBoxSTypeLightCruiser,\r
113                 checkBoxSTypeDestroyer,\r
114                 checkBoxSTypeEscort,\r
115                 checkBoxSTypeSubmarine,\r
116                 checkBoxSTypeAuxiliary\r
117             };\r
118             battleResultPanel.HpLabelClick += ToggleHpPercent;\r
119             shipListPanel.HpLabelClick += ToggleHpPercent;\r
120             var swipe = new SwipeScrollify();\r
121             swipe.AddShipListPanel(shipListPanel);\r
122             swipe.AddTreeView(itemTreeView);\r
123             swipe.AddPanel(fleetPanel);\r
124         }\r
125 \r
126         public void UpdateList()\r
127         {\r
128             SetHeaderVisibility();\r
129             SetPanelVisibility();\r
130             if (InItemList)\r
131             {\r
132                 itemTreeView.SetNodes(_sniffer.ItemList);\r
133             }\r
134             else if (InFleetInfo)\r
135             {\r
136                 fleetPanel.Update(_sniffer);\r
137             }\r
138             else if (InAntiAir)\r
139             {\r
140                 antiAirPanel.Update(_sniffer);\r
141             }\r
142             else if (InMiscText)\r
143             {\r
144                 richTextBoxMiscText.Text = _sniffer.MiscText;\r
145             }\r
146             else if (InShipStatus || InGroupConfig || InRepairList)\r
147             {\r
148                 SetHeaderSortOrder();\r
149                 shipListPanel.Update(_sniffer, comboBoxGroup.Text, _settings);\r
150             }\r
151             if (shipListPanel.GroupUpdated)\r
152             {\r
153                 StoreShipGroupToConfig();\r
154                 _config.Save();\r
155                 shipListPanel.GroupUpdated = false;\r
156             }\r
157         }\r
158 \r
159         private void SetHeaderVisibility()\r
160         {\r
161             static void Set(Control header, bool visible)\r
162             {\r
163                 header.Visible = visible;\r
164                 if (visible)\r
165                     header.BringToFront();\r
166             }\r
167 \r
168             Set(panelShipHeader, InShipStatus);\r
169             Set(panelEmptyHeader, InItemList || InAntiAir || InBattleResult || InMiscText);\r
170             Set(panelGroupHeader, InGroupConfig);\r
171             Set(panelRepairHeader, InRepairList);\r
172             Set(panelFleetHeader, InFleetInfo);\r
173         }\r
174 \r
175         private void SetPanelVisibility()\r
176         {\r
177             static void Set(Control panel, bool visible)\r
178             {\r
179                 // SwipeScrollifyが誤作動するのでEnabledも切り替える\r
180                 panel.Visible = panel.Enabled = visible;\r
181             }\r
182 \r
183             Set(shipListPanel, InShipStatus || InGroupConfig || InRepairList);\r
184             Set(itemTreeView, InItemList);\r
185             Set(fleetPanel, InFleetInfo);\r
186             Set(antiAirPanel, InAntiAir);\r
187             Set(airBattleResultPanel, InBattleResult);\r
188             Set(battleResultPanel, InBattleResult);\r
189             Set(richTextBoxMiscText, InMiscText);\r
190         }\r
191 \r
192         public void UpdateAirBattleResult()\r
193         {\r
194             airBattleResultPanel.ShowResultAutomatic = (_config.Spoilers & Spoiler.AirBattleResult) != 0;\r
195             airBattleResultPanel.SetResult(_sniffer);\r
196         }\r
197 \r
198         public void UpdateBattleResult()\r
199         {\r
200             MoveToBattleResult();\r
201             battleResultPanel.Spoilers = _config.Spoilers;\r
202             battleResultPanel.Update(_sniffer);\r
203             BackFromBattleResult();\r
204         }\r
205 \r
206         private int _prevSelectedIndex = -1;\r
207         private const int BattleResultIndex = 10;\r
208 \r
209         private void MoveToBattleResult()\r
210         {\r
211             if (!_isMaster || !_config.ShipList.AutoBattleResult || comboBoxGroup.SelectedIndex == BattleResultIndex ||\r
212                 _sniffer.InSortie == -1)\r
213                 return;\r
214             _prevSelectedIndex = comboBoxGroup.SelectedIndex;\r
215             comboBoxGroup.SelectedIndex = BattleResultIndex;\r
216         }\r
217 \r
218         private void BackFromBattleResult()\r
219         {\r
220             if (_sniffer.InSortie != -1 || _prevSelectedIndex == -1)\r
221                 return;\r
222             comboBoxGroup.SelectedIndex = _prevSelectedIndex;\r
223             _prevSelectedIndex = -1;\r
224         }\r
225 \r
226         public void UpdateCellInfo()\r
227         {\r
228             MoveToBattleResult();\r
229             battleResultPanel.Spoilers = _config.Spoilers;\r
230             battleResultPanel.UpdateCellInfo(_sniffer.CellInfo);\r
231         }\r
232 \r
233         private void SetHeaderSortOrder()\r
234         {\r
235             switch (_settings.SortOrder)\r
236             {\r
237                 case SortOrder.None:\r
238                     labelHeaderCond.Text = "cond";\r
239                     labelHeaderExp.Text = "Exp";\r
240                     break;\r
241                 case SortOrder.CondAscend:\r
242                     labelHeaderCond.Text = "cond▴";\r
243                     labelHeaderExp.Text = "Exp";\r
244                     break;\r
245                 case SortOrder.CondDescend:\r
246                     labelHeaderCond.Text = "cond▾";\r
247                     labelHeaderExp.Text = "Exp";\r
248                     break;\r
249                 case SortOrder.ExpToNextAscend:\r
250                     labelHeaderCond.Text = "cond";\r
251                     labelHeaderExp.Text = "Exp▴";\r
252                     break;\r
253                 case SortOrder.ExpToNextDescend:\r
254                     labelHeaderCond.Text = "cond";\r
255                     labelHeaderExp.Text = "Exp▾";\r
256                     break;\r
257             }\r
258         }\r
259 \r
260         private bool InShipStatus => Array.Exists(new[] {"全艦", "A", "B", "C", "D"}, x => _settings.Mode == x);\r
261 \r
262         private bool InGroupConfig => _settings.Mode == "分類";\r
263 \r
264         private bool InRepairList => _settings.Mode == "修復";\r
265 \r
266         private bool InItemList => _settings.Mode == "装備";\r
267 \r
268         private bool InFleetInfo => _settings.Mode == "艦隊";\r
269 \r
270         private bool InAntiAir => _settings.Mode == "対空";\r
271 \r
272         private bool InBattleResult => _settings.Mode == "戦況";\r
273 \r
274         private bool InMiscText => _settings.Mode == "情報";\r
275 \r
276         private void ListForm_Load(object sender, EventArgs e)\r
277         {\r
278             AdjustHeader();\r
279             SetMinimumSize();\r
280             var config = GetConfig();\r
281             _settings = Settings.FromShipListConfig(config);\r
282             if (_settings.ShowHpInPercent)\r
283             {\r
284                 shipListPanel.ToggleHpPercent();\r
285                 battleResultPanel.ToggleHpPercent();\r
286             }\r
287             LoadShipGroupFromConfig();\r
288             comboBoxGroup.SelectedItem = _settings.Mode;\r
289             SetCheckBoxSTypeState();\r
290             if (config.Location.X == int.MinValue)\r
291                 return;\r
292             var bounds = new Rectangle(config.Location, config.Size);\r
293             if (MainWindow.IsTitleBarOnAnyScreen(bounds.Location))\r
294                 Location = bounds.Location;\r
295             Size = bounds.Size;\r
296         }\r
297 \r
298         private void AdjustHeader()\r
299         {\r
300             if (_config.Zoom == 100)\r
301                 return;\r
302             foreach (var header in new[]\r
303             {\r
304                 panelShipHeader, panelGroupHeader, panelRepairHeader\r
305             })\r
306             {\r
307                 header.Left += SystemInformation.VerticalScrollBarWidth * (_config.Zoom - 100) / 100;\r
308             }\r
309         }\r
310 \r
311         private void SetMinimumSize()\r
312         {\r
313             MinimumSize = new Size(Width - Scaler.ScaleWidth(24) - SystemInformation.VerticalScrollBarWidth * (_config.Zoom - 100) / 100, 0);\r
314         }\r
315 \r
316         private ShipListConfig GetConfig()\r
317         {\r
318             if (_isMaster || _config.ListFormGroup.Count == 0)\r
319                 return _config.ShipList;\r
320             var config = _config.ListFormGroup[0];\r
321             _config.ListFormGroup.RemoveAt(0);\r
322             if (config.Mode == "分類")\r
323                 config.Mode = "全艦";\r
324             return config;\r
325         }\r
326 \r
327         private void LoadShipGroupFromConfig()\r
328         {\r
329             var group = _config.ShipList.ShipGroup;\r
330             for (var i = 0; i < GroupConfigLabels.GroupCount; i++)\r
331                 shipListPanel.GroupSettings[i] = i < group.Count ? new HashSet<int>(group[i]) : new HashSet<int>();\r
332         }\r
333 \r
334         private void SetCheckBoxSTypeState()\r
335         {\r
336             for (var type = 0; type < _shipTypeCheckBoxes.Length; type++)\r
337                 _shipTypeCheckBoxes[type].Checked = ((int)_settings.ShipCategories & (1 << type)) != 0;\r
338             checkBoxSTypeAll.Checked = _settings.ShipCategories == ShipCategory.All;\r
339             checkBoxSTypeDetails.Checked = _settings.ShipType;\r
340         }\r
341 \r
342         private void ListForm_FormClosing(object sender, FormClosingEventArgs e)\r
343         {\r
344             e.Cancel = true;\r
345             Hide();\r
346         }\r
347 \r
348         public void SaveConfig()\r
349         {\r
350             if (_isMaster)\r
351             {\r
352                 SaveMasterState();\r
353             }\r
354             else\r
355             {\r
356                 SaveSlaveState();\r
357             }\r
358         }\r
359 \r
360         private void SaveMasterState()\r
361         {\r
362             StoreShipGroupToConfig();\r
363             var config = _config.ShipList;\r
364             config.Visible = Visible && WindowState == FormWindowState.Normal;\r
365             _settings.SetToShipListConfig(config);\r
366             if (!Visible)\r
367                 return;\r
368             SaveBounds(config); // 最小化時は以前のサイズを記録する\r
369         }\r
370 \r
371         private void SaveSlaveState()\r
372         {\r
373             if (!Visible)\r
374                 return;\r
375             if (WindowState != FormWindowState.Normal) // 最小化時は次回復旧しない\r
376                 return;\r
377             var config = new ShipListConfig {Visible = true};\r
378             _settings.SetToShipListConfig(config);\r
379             _config.ListFormGroup.Add(config);\r
380             SaveBounds(config);\r
381         }\r
382 \r
383         private void SaveBounds(ShipListConfig config)\r
384         {\r
385             var bounds = WindowState == FormWindowState.Normal ? Bounds : RestoreBounds;\r
386             config.Location = bounds.Location;\r
387             config.Size = bounds.Size;\r
388         }\r
389 \r
390         public void ChangeWindowState(FormWindowState newState)\r
391         {\r
392             if (!Visible)\r
393                 return;\r
394             if (newState == FormWindowState.Minimized)\r
395             {\r
396                 if (WindowState == FormWindowState.Normal)\r
397                     WindowState = FormWindowState.Minimized;\r
398                 if (_config.HideOnMinimized)\r
399                     ShowInTaskbar = false;\r
400             }\r
401             else\r
402             {\r
403                 if (WindowState == FormWindowState.Minimized)\r
404                 {\r
405                     Application.DoEvents();\r
406                     if (_config.HideOnMinimized)\r
407                         ShowInTaskbar = true;\r
408                     WindowState = FormWindowState.Normal;\r
409                 }\r
410             }\r
411         }\r
412 \r
413         private void ListForm_Activated(object sender, EventArgs e)\r
414         {\r
415             if (!_isMaster)\r
416                 return;\r
417             if (_suppressActivate.Check())\r
418                 return;\r
419             if (WindowState == FormWindowState.Minimized)\r
420                 return;\r
421             RaiseBothWindows();\r
422         }\r
423 \r
424         private void RaiseBothWindows()\r
425         {\r
426             _form.Owner = null;\r
427             Owner = _form;\r
428             BringToFront();\r
429             Owner = null;\r
430         }\r
431 \r
432         private void StoreShipGroupToConfig()\r
433         {\r
434             var all = _sniffer.ShipList.Select(s => s.Id).ToArray();\r
435             var group = _config.ShipList.ShipGroup;\r
436             group.Clear();\r
437             for (var i = 0; i < GroupConfigLabels.GroupCount; i++)\r
438             {\r
439                 if (all.Length > 0)\r
440                     shipListPanel.GroupSettings[i].IntersectWith(all);\r
441                 group.Add(shipListPanel.GroupSettings[i].ToList());\r
442             }\r
443         }\r
444 \r
445         public void ShowShip(int id)\r
446         {\r
447             if (InShipStatus)\r
448             {\r
449                 shipListPanel.ShowShip(id);\r
450             }\r
451             else if (InFleetInfo)\r
452             {\r
453                 fleetPanel.ShowShip(id);\r
454             }\r
455             else if (InAntiAir)\r
456             {\r
457                 antiAirPanel.ShowShip(id);\r
458             }\r
459         }\r
460 \r
461         private void comboBoxGroup_DropDownClosed(object sender, EventArgs e)\r
462         {\r
463             SetActiveControl();\r
464         }\r
465 \r
466         private void comboBoxGroup_SelectedIndexChanged(object sender, EventArgs e)\r
467         {\r
468             _settings.Mode = comboBoxGroup.Text;\r
469             UpdateList();\r
470             SetActiveControl();\r
471             if (!(InShipStatus || InGroupConfig || InRepairList))\r
472                 SetPanelSTypeState(false);\r
473         }\r
474 \r
475         private void ListForm_KeyPress(object sender, KeyPressEventArgs e)\r
476         {\r
477             var g = Array.FindIndex(PanelKeys, x => x == char.ToUpper(e.KeyChar));\r
478             if (g == -1)\r
479                 return;\r
480             comboBoxGroup.SelectedIndex = g;\r
481             e.Handled = true;\r
482         }\r
483 \r
484         // マウスホイールでスクロールするためにコントロールにフォーカスを合わせる。\r
485         private void SetActiveControl()\r
486         {\r
487             if (InItemList)\r
488             {\r
489                 ActiveControl = itemTreeView;\r
490             }\r
491             else if (InFleetInfo)\r
492             {\r
493                 ActiveControl = fleetPanel;\r
494             }\r
495             else if (InAntiAir)\r
496             {\r
497                 ActiveControl = antiAirPanel;\r
498             }\r
499             else\r
500             {\r
501                 ActiveControl = shipListPanel;\r
502             }\r
503         }\r
504 \r
505         private void itemCsvToolStripMenuItem_Click(object sender, EventArgs e)\r
506         {\r
507             Clipboard.SetText(TextGenerator.GenerateItemList(_sniffer.ItemList));\r
508         }\r
509 \r
510         private void kantaiBunsekiToolStripMenuItem_Click(object sender, EventArgs e)\r
511         {\r
512             Clipboard.SetText(TextGenerator.GenerateKantaiBunsekiItemList(_sniffer.ItemList));\r
513         }\r
514 \r
515         private void fleetTextToolStripMenuItem_Click(object sender, EventArgs e)\r
516         {\r
517             Clipboard.SetText(TextGenerator.GenerateFleetData(_sniffer));\r
518         }\r
519 \r
520         private void deckBuilderToolStripMenuItem_Click(object sender, EventArgs e)\r
521         {\r
522             Clipboard.SetText(TextGenerator.GenerateDeckBuilderData(_sniffer));\r
523         }\r
524 \r
525         private void labelHeaderCond_Click(object sender, EventArgs e)\r
526         {\r
527             switch (_settings.SortOrder)\r
528             {\r
529                 case SortOrder.CondAscend:\r
530                     _settings.SortOrder = SortOrder.CondDescend;\r
531                     break;\r
532                 case SortOrder.CondDescend:\r
533                     _settings.SortOrder = SortOrder.None;\r
534                     break;\r
535                 default:\r
536                     _settings.SortOrder = SortOrder.CondAscend;\r
537                     break;\r
538             }\r
539             UpdateList();\r
540         }\r
541 \r
542         private void labelHeaderExp_Click(object sender, EventArgs e)\r
543         {\r
544             switch (_settings.SortOrder)\r
545             {\r
546                 case SortOrder.ExpToNextAscend:\r
547                     _settings.SortOrder = SortOrder.ExpToNextDescend;\r
548                     break;\r
549                 case SortOrder.ExpToNextDescend:\r
550                     _settings.SortOrder = SortOrder.None;\r
551                     break;\r
552                 default:\r
553                     _settings.SortOrder = SortOrder.ExpToNextAscend;\r
554                     break;\r
555             }\r
556             UpdateList();\r
557         }\r
558 \r
559         private void shipCsvToolStripMenuItem_Click(object sender, EventArgs e)\r
560         {\r
561             Clipboard.SetText(TextGenerator.GenerateShipList(shipListPanel.CurrentShipList));\r
562         }\r
563 \r
564         private void kantaiSarashiToolStripMenuItem_Click(object sender, EventArgs e)\r
565         {\r
566             Clipboard.SetText(TextGenerator.GenerateKantaiSarashiData(shipListPanel.CurrentShipList));\r
567         }\r
568 \r
569         private void labelFleet_Click(object sender, EventArgs e)\r
570         {\r
571             fleetPanel.ShowFleet(((Label)sender).Text);\r
572         }\r
573 \r
574         private void labelHeaderHp_Click(object sender, EventArgs e)\r
575         {\r
576             ToggleHpPercent();\r
577         }\r
578 \r
579         private void ToggleHpPercent()\r
580         {\r
581             _settings.ShowHpInPercent = !_settings.ShowHpInPercent;\r
582             shipListPanel.ToggleHpPercent();\r
583             battleResultPanel.ToggleHpPercent();\r
584         }\r
585 \r
586         private void labelSTypeButton_Click(object sender, EventArgs e)\r
587         {\r
588             SetPanelSTypeState(!panelSType.Visible);\r
589         }\r
590 \r
591         private void checkBoxSType_Click(object sender, EventArgs e)\r
592         {\r
593             _settings.ShipCategories = SelectedShipTypes;\r
594             UpdateList();\r
595             SetActiveControl();\r
596         }\r
597 \r
598         private ShipCategory SelectedShipTypes =>\r
599             (ShipCategory)_shipTypeCheckBoxes.Select((cb, type) => cb.Checked ? 1 << type : 0).Sum();\r
600 \r
601         private void checkBoxSTypeAll_Click(object sender, EventArgs e)\r
602         {\r
603             foreach (var checkBox in _shipTypeCheckBoxes)\r
604                 checkBox.Checked = checkBoxSTypeAll.Checked;\r
605             checkBoxSType_Click(sender, e);\r
606         }\r
607 \r
608         private void panelSType_Click(object sender, EventArgs e)\r
609         {\r
610             SetPanelSTypeState(false);\r
611         }\r
612 \r
613         private void SetPanelSTypeState(bool visible)\r
614         {\r
615             panelSType.Visible = visible;\r
616             if (visible)\r
617                 panelSType.BringToFront();\r
618             dropDownButtonSType.BackColor = visible ? CustomColors.ActiveButtonColor : DefaultBackColor;\r
619         }\r
620 \r
621         private void checkBoxSTypeDetails_Click(object sender, EventArgs e)\r
622         {\r
623             _settings.ShipType = checkBoxSTypeDetails.Checked;\r
624             UpdateList();\r
625             SetActiveControl();\r
626         }\r
627 \r
628         private void ListForm_ResizeEnd(object sender, EventArgs e)\r
629         {\r
630             foreach (var panel in new IPanelResize[] {shipListPanel, antiAirPanel, airBattleResultPanel, battleResultPanel, fleetPanel})\r
631             {\r
632                 if (panel.Visible)\r
633                     panel.ApplyResize();\r
634             }\r
635         }\r
636     }\r
637 }