OSDN Git Service

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