OSDN Git Service

装備一覧が正しく更新されないのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / 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.View;\r
21 using KancolleSniffer.View.ShipListPanel;\r
22 using Clipboard = KancolleSniffer.Util.Clipboard;\r
23 \r
24 namespace KancolleSniffer\r
25 {\r
26     public partial class ListForm : Form\r
27     {\r
28         private readonly Sniffer _sniffer;\r
29         private readonly Config _config;\r
30         private readonly MainForm _main;\r
31         private readonly MainForm.TimeOutChecker _suppressActivate;\r
32         private readonly CheckBox[] _shipTypeCheckBoxes;\r
33         public const int PanelWidth = 217;\r
34 \r
35         public enum SortOrder\r
36         {\r
37             None,\r
38             Cond,\r
39             CondAscend = Cond,\r
40             CondDescend,\r
41             ExpToNext,\r
42             ExpToNextAscend = ExpToNext,\r
43             ExpToNextDescend,\r
44             Repair\r
45         }\r
46 \r
47         public ListForm(MainForm main)\r
48         {\r
49             InitializeComponent();\r
50             _main = main;\r
51             _sniffer = main.Sniffer;\r
52             _config = main.Config;\r
53             _suppressActivate = main.SuppressActivate;\r
54             _shipTypeCheckBoxes = new[]\r
55             {\r
56                 checkBoxSTypeBattleShip,\r
57                 checkBoxSTypeAircraftCarrier,\r
58                 checkBoxSTypeHeavyCruiser,\r
59                 checkBoxSTypeLightCruiser,\r
60                 checkBoxSTypeDestroyer,\r
61                 checkBoxSTypeEscort,\r
62                 checkBoxSTypeSubmarine,\r
63                 checkBoxSTypeAuxiliary\r
64             };\r
65             battleResultPanel.HpLabelClick += ToggleHpPercent;\r
66             shipListPanel.HpLabelClick += ToggleHpPercent;\r
67             var swipe = new SwipeScrollify();\r
68             swipe.AddShipListPanel(shipListPanel);\r
69             swipe.AddTreeView(itemTreeView);\r
70             swipe.AddPanel(fleetPanel);\r
71         }\r
72 \r
73         public void UpdateList()\r
74         {\r
75             SetHeaderVisibility();\r
76             SetPanelVisibility();\r
77             if (InItemList)\r
78             {\r
79                 itemTreeView.SetNodes(_sniffer.ItemList);\r
80             }\r
81             else if (InFleetInfo)\r
82             {\r
83                 fleetPanel.Update(_sniffer);\r
84             }\r
85             else if (InAntiAir)\r
86             {\r
87                 antiAirPanel.Update(_sniffer);\r
88             }\r
89             else if (InMiscText)\r
90             {\r
91                 richTextBoxMiscText.Text = _sniffer.MiscText;\r
92             }\r
93             else if (InShipStatus || InGroupConfig || InRepairList)\r
94             {\r
95                 SetHeaderSortOrder();\r
96                 shipListPanel.Update(_sniffer, comboBoxGroup.Text, _config.ShipList);\r
97             }\r
98             if (shipListPanel.GroupUpdated)\r
99             {\r
100                 StoreShipGroupToConfig();\r
101                 _config.Save();\r
102                 shipListPanel.GroupUpdated = false;\r
103             }\r
104         }\r
105 \r
106         private void SetHeaderVisibility()\r
107         {\r
108             static void Set(Control header, bool visible)\r
109             {\r
110                 header.Visible = visible;\r
111                 if (visible)\r
112                     header.BringToFront();\r
113             }\r
114 \r
115             Set(panelItemHeader, InItemList || InAntiAir || InBattleResult || InMiscText);\r
116             Set(panelGroupHeader, InGroupConfig);\r
117             Set(panelRepairHeader, InRepairList);\r
118             Set(panelFleetHeader, InFleetInfo);\r
119         }\r
120 \r
121         private void SetPanelVisibility()\r
122         {\r
123             static void Set(Control panel, bool visible)\r
124             {\r
125                 // SwipeScrollifyが誤作動するのでEnabledも切り替える\r
126                 panel.Visible = panel.Enabled = visible;\r
127             }\r
128 \r
129             Set(shipListPanel, InShipStatus || InGroupConfig || InRepairList);\r
130             Set(itemTreeView, InItemList);\r
131             Set(fleetPanel, InFleetInfo);\r
132             Set(antiAirPanel, InAntiAir);\r
133             Set(airBattleResultPanel, InBattleResult);\r
134             Set(battleResultPanel, InBattleResult);\r
135             Set(richTextBoxMiscText, InMiscText);\r
136         }\r
137 \r
138         public void UpdateAirBattleResult()\r
139         {\r
140             airBattleResultPanel.ShowResultAutomatic = (_config.Spoilers & Spoiler.AirBattleResult) != 0;\r
141             airBattleResultPanel.SetResult(_sniffer);\r
142         }\r
143 \r
144         public void UpdateBattleResult()\r
145         {\r
146             MoveToBattleResult();\r
147             battleResultPanel.Spoilers = _config.Spoilers;\r
148             battleResultPanel.Update(_sniffer);\r
149             BackFromBattleResult();\r
150         }\r
151 \r
152         private int _prevSelectedIndex = -1;\r
153         private const int BattleResultIndex = 10;\r
154 \r
155         private void MoveToBattleResult()\r
156         {\r
157             if (!_config.ShipList.AutoBattleResult || comboBoxGroup.SelectedIndex == BattleResultIndex ||\r
158                 _sniffer.InSortie == -1)\r
159                 return;\r
160             _prevSelectedIndex = comboBoxGroup.SelectedIndex;\r
161             comboBoxGroup.SelectedIndex = BattleResultIndex;\r
162         }\r
163 \r
164         private void BackFromBattleResult()\r
165         {\r
166             if (_sniffer.InSortie != -1 || _prevSelectedIndex == -1)\r
167                 return;\r
168             comboBoxGroup.SelectedIndex = _prevSelectedIndex;\r
169             _prevSelectedIndex = -1;\r
170         }\r
171 \r
172         public void UpdateCellInfo()\r
173         {\r
174             battleResultPanel.Spoilers = _config.Spoilers;\r
175             battleResultPanel.UpdateCellInfo(_sniffer.CellInfo);\r
176         }\r
177 \r
178         private void SetHeaderSortOrder()\r
179         {\r
180             switch (_config.ShipList.SortOrder)\r
181             {\r
182                 case SortOrder.None:\r
183                     labelHeaderCond.Text = "cond";\r
184                     labelHeaderExp.Text = "Exp";\r
185                     break;\r
186                 case SortOrder.CondAscend:\r
187                     labelHeaderCond.Text = "cond▴";\r
188                     labelHeaderExp.Text = "Exp";\r
189                     break;\r
190                 case SortOrder.CondDescend:\r
191                     labelHeaderCond.Text = "cond▾";\r
192                     labelHeaderExp.Text = "Exp";\r
193                     break;\r
194                 case SortOrder.ExpToNextAscend:\r
195                     labelHeaderCond.Text = "cond";\r
196                     labelHeaderExp.Text = "Exp▴";\r
197                     break;\r
198                 case SortOrder.ExpToNextDescend:\r
199                     labelHeaderCond.Text = "cond";\r
200                     labelHeaderExp.Text = "Exp▾";\r
201                     break;\r
202             }\r
203         }\r
204 \r
205         private bool InShipStatus => Array.Exists(new[] {"全艦", "A", "B", "C", "D"}, x => comboBoxGroup.Text == x);\r
206 \r
207         private bool InGroupConfig => comboBoxGroup.Text == "分類";\r
208 \r
209         private bool InRepairList => comboBoxGroup.Text == "修復";\r
210 \r
211         private bool InItemList => comboBoxGroup.Text == "装備";\r
212 \r
213         private bool InFleetInfo => comboBoxGroup.Text == "艦隊";\r
214 \r
215         private bool InAntiAir => comboBoxGroup.Text == "対空";\r
216 \r
217         private bool InBattleResult => comboBoxGroup.Text == "戦況";\r
218 \r
219         private bool InMiscText => comboBoxGroup.Text == "情報";\r
220 \r
221         private void ListForm_Load(object sender, EventArgs e)\r
222         {\r
223             /* DPIではなくズームしたときにパネルは大きくなるがScrollBarはそのままなので隙間ができる。\r
224                そこでScrollBarの幅に合わせて全体の横幅を設定し直す。*/\r
225             Width = Scaler.ScaleWidth(PanelWidth + 12 /* PanelとFrameの内側 */) +\r
226                     SystemInformation.VerticalScrollBarWidth + 2 /* 縁の幅 */ + Width - ClientSize.Width;\r
227             MinimumSize = new Size(Width, 0);\r
228             MaximumSize = new Size(Width, int.MaxValue);\r
229             var config = _config.ShipList;\r
230             if (config.ShowHpInPercent)\r
231             {\r
232                 shipListPanel.ToggleHpPercent();\r
233                 battleResultPanel.ToggleHpPercent();\r
234             }\r
235             LoadShipGroupFromConfig();\r
236             comboBoxGroup.SelectedItem = config.Mode ?? "全艦";\r
237             SetCheckBoxSTypeSate();\r
238             if (config.Location.X == int.MinValue)\r
239                 return;\r
240             var bounds = new Rectangle(config.Location, config.Size);\r
241             if (MainForm.IsTitleBarOnAnyScreen(bounds.Location))\r
242                 Location = bounds.Location;\r
243             Height = bounds.Height;\r
244         }\r
245 \r
246         private void LoadShipGroupFromConfig()\r
247         {\r
248             var group = _config.ShipList.ShipGroup;\r
249             for (var i = 0; i < GroupConfigLabels.GroupCount; i++)\r
250                 shipListPanel.GroupSettings[i] = i < group.Count ? new HashSet<int>(group[i]) : new HashSet<int>();\r
251         }\r
252 \r
253         private void SetCheckBoxSTypeSate()\r
254         {\r
255             for (var type = 0; type < _shipTypeCheckBoxes.Length; type++)\r
256                 _shipTypeCheckBoxes[type].Checked = ((int)_config.ShipList.ShipCategories & (1 << type)) != 0;\r
257             checkBoxSTypeAll.Checked = _config.ShipList.ShipCategories == ShipCategory.All;\r
258             checkBoxSTypeDetails.Checked = _config.ShipList.ShipType;\r
259         }\r
260 \r
261         private void ListForm_FormClosing(object sender, FormClosingEventArgs e)\r
262         {\r
263             e.Cancel = true;\r
264             if (!Visible) // 非表示のときは保存すべき情報がないのでスキップする\r
265                 return;\r
266             var config = _config.ShipList;\r
267             StoreShipGroupToConfig();\r
268             var bounds = WindowState == FormWindowState.Normal ? Bounds : RestoreBounds;\r
269             config.Location = bounds.Location;\r
270             config.Size = bounds.Size;\r
271             config.Mode = (string)comboBoxGroup.SelectedItem;\r
272             Hide();\r
273         }\r
274 \r
275         public void ChangeWindowState(FormWindowState newState)\r
276         {\r
277             if (!Visible)\r
278                 return;\r
279             if (newState == FormWindowState.Minimized)\r
280             {\r
281                 if (WindowState == FormWindowState.Normal)\r
282                     WindowState = FormWindowState.Minimized;\r
283                 if (_config.HideOnMinimized)\r
284                     ShowInTaskbar = false;\r
285             }\r
286             else\r
287             {\r
288                 if (WindowState == FormWindowState.Minimized)\r
289                 {\r
290                     Application.DoEvents();\r
291                     if (_config.HideOnMinimized)\r
292                         ShowInTaskbar = true;\r
293                     WindowState = FormWindowState.Normal;\r
294                 }\r
295             }\r
296         }\r
297 \r
298         private void ListForm_Activated(object sender, EventArgs e)\r
299         {\r
300             if (_suppressActivate.Check())\r
301                 return;\r
302             if (WindowState == FormWindowState.Minimized)\r
303                 return;\r
304             RaiseBothWindows();\r
305         }\r
306 \r
307         private void RaiseBothWindows()\r
308         {\r
309             _main.Owner = null;\r
310             Owner = _main;\r
311             BringToFront();\r
312             Owner = null;\r
313         }\r
314 \r
315         private void StoreShipGroupToConfig()\r
316         {\r
317             var all = _sniffer.ShipList.Select(s => s.Id).ToArray();\r
318             var group = _config.ShipList.ShipGroup;\r
319             group.Clear();\r
320             for (var i = 0; i < GroupConfigLabels.GroupCount; i++)\r
321             {\r
322                 if (all.Length > 0)\r
323                     shipListPanel.GroupSettings[i].IntersectWith(all);\r
324                 group.Add(shipListPanel.GroupSettings[i].ToList());\r
325             }\r
326         }\r
327 \r
328         public void ShowShip(int id)\r
329         {\r
330             if (InShipStatus)\r
331             {\r
332                 shipListPanel.ShowShip(id);\r
333             }\r
334             else if (InFleetInfo)\r
335             {\r
336                 fleetPanel.ShowShip(id);\r
337             }\r
338             else if (InAntiAir)\r
339             {\r
340                 antiAirPanel.ShowShip(id);\r
341             }\r
342         }\r
343 \r
344         private void comboBoxGroup_DropDownClosed(object sender, EventArgs e)\r
345         {\r
346             SetActiveControl();\r
347         }\r
348 \r
349         private void comboBoxGroup_SelectedIndexChanged(object sender, EventArgs e)\r
350         {\r
351             UpdateList();\r
352             SetActiveControl();\r
353             if (!(InShipStatus || InGroupConfig || InRepairList))\r
354                 SetPanelSTypeState(false);\r
355         }\r
356 \r
357         private void ListForm_KeyPress(object sender, KeyPressEventArgs e)\r
358         {\r
359             var g = Array.FindIndex(new[] {'Z', 'A', 'B', 'C', 'D', 'G', 'R', 'W', 'X', 'Y', 'S', 'I'},\r
360                 x => x == char.ToUpper(e.KeyChar));\r
361             if (g == -1)\r
362                 return;\r
363             comboBoxGroup.SelectedIndex = g;\r
364             e.Handled = true;\r
365         }\r
366 \r
367         // マウスホイールでスクロールするためにコントロールにフォーカスを合わせる。\r
368         private void SetActiveControl()\r
369         {\r
370             if (InItemList)\r
371             {\r
372                 ActiveControl = itemTreeView;\r
373             }\r
374             else if (InFleetInfo)\r
375             {\r
376                 ActiveControl = fleetPanel;\r
377             }\r
378             else if (InAntiAir)\r
379             {\r
380                 ActiveControl = antiAirPanel;\r
381             }\r
382             else\r
383             {\r
384                 ActiveControl = shipListPanel;\r
385             }\r
386         }\r
387 \r
388         private void itemCsvToolStripMenuItem_Click(object sender, EventArgs e)\r
389         {\r
390             Clipboard.SetText(TextGenerator.GenerateItemList(_sniffer.ItemList));\r
391         }\r
392 \r
393         private void kantaiBunsekiToolStripMenuItem_Click(object sender, EventArgs e)\r
394         {\r
395             Clipboard.SetText(TextGenerator.GenerateKantaiBunsekiItemList(_sniffer.ItemList));\r
396         }\r
397 \r
398         private void fleetTextToolStripMenuItem_Click(object sender, EventArgs e)\r
399         {\r
400             Clipboard.SetText(TextGenerator.GenerateFleetData(_sniffer));\r
401         }\r
402 \r
403         private void deckBuilderToolStripMenuItem_Click(object sender, EventArgs e)\r
404         {\r
405             Clipboard.SetText(TextGenerator.GenerateDeckBuilderData(_sniffer));\r
406         }\r
407 \r
408         private void labelHeaderCond_Click(object sender, EventArgs e)\r
409         {\r
410             var sl = _config.ShipList;\r
411             switch (sl.SortOrder)\r
412             {\r
413                 case SortOrder.CondAscend:\r
414                     sl.SortOrder = SortOrder.CondDescend;\r
415                     break;\r
416                 case SortOrder.CondDescend:\r
417                     sl.SortOrder = SortOrder.None;\r
418                     break;\r
419                 default:\r
420                     sl.SortOrder = SortOrder.CondAscend;\r
421                     break;\r
422             }\r
423             UpdateList();\r
424         }\r
425 \r
426         private void labelHeaderExp_Click(object sender, EventArgs e)\r
427         {\r
428             var sl = _config.ShipList;\r
429             switch (sl.SortOrder)\r
430             {\r
431                 case SortOrder.ExpToNextAscend:\r
432                     sl.SortOrder = SortOrder.ExpToNextDescend;\r
433                     break;\r
434                 case SortOrder.ExpToNextDescend:\r
435                     sl.SortOrder = SortOrder.None;\r
436                     break;\r
437                 default:\r
438                     sl.SortOrder = SortOrder.ExpToNextAscend;\r
439                     break;\r
440             }\r
441             UpdateList();\r
442         }\r
443 \r
444         private void shipCsvToolStripMenuItem_Click(object sender, EventArgs e)\r
445         {\r
446             Clipboard.SetText(TextGenerator.GenerateShipList(shipListPanel.CurrentShipList));\r
447         }\r
448 \r
449         private void kantaiSarashiToolStripMenuItem_Click(object sender, EventArgs e)\r
450         {\r
451             Clipboard.SetText(TextGenerator.GenerateKantaiSarashiData(shipListPanel.CurrentShipList));\r
452         }\r
453 \r
454         private void labelFleet_Click(object sender, EventArgs e)\r
455         {\r
456             fleetPanel.ShowFleet(((Label)sender).Text);\r
457         }\r
458 \r
459         private void labelHeaderHp_Click(object sender, EventArgs e)\r
460         {\r
461             ToggleHpPercent();\r
462         }\r
463 \r
464         private void ToggleHpPercent()\r
465         {\r
466             _config.ShipList.ShowHpInPercent = !_config.ShipList.ShowHpInPercent;\r
467             shipListPanel.ToggleHpPercent();\r
468             battleResultPanel.ToggleHpPercent();\r
469         }\r
470 \r
471         private void labelSTypeButton_Click(object sender, EventArgs e)\r
472         {\r
473             SetPanelSTypeState(!panelSType.Visible);\r
474         }\r
475 \r
476         private void checkBoxSType_Click(object sender, EventArgs e)\r
477         {\r
478             _config.ShipList.ShipCategories = SelectedShipTypes;\r
479             UpdateList();\r
480             SetActiveControl();\r
481         }\r
482 \r
483         private ShipCategory SelectedShipTypes =>\r
484             (ShipCategory)_shipTypeCheckBoxes.Select((cb, type) => cb.Checked ? 1 << type : 0).Sum();\r
485 \r
486         private void checkBoxSTypeAll_Click(object sender, EventArgs e)\r
487         {\r
488             foreach (var checkBox in _shipTypeCheckBoxes)\r
489                 checkBox.Checked = checkBoxSTypeAll.Checked;\r
490             checkBoxSType_Click(sender, e);\r
491         }\r
492 \r
493         private void panelSType_Click(object sender, EventArgs e)\r
494         {\r
495             SetPanelSTypeState(false);\r
496         }\r
497 \r
498         private void SetPanelSTypeState(bool visible)\r
499         {\r
500             panelSType.Visible = visible;\r
501             if (visible)\r
502                 panelSType.BringToFront();\r
503             labelSTypeButton.BackColor = visible ? CustomColors.ActiveButtonColor : DefaultBackColor;\r
504         }\r
505 \r
506         private void checkBoxSTypeDetails_Click(object sender, EventArgs e)\r
507         {\r
508             _config.ShipList.ShipType = checkBoxSTypeDetails.Checked;\r
509             UpdateList();\r
510             SetActiveControl();\r
511         }\r
512     }\r
513 }