OSDN Git Service

明石タイマーが原因で大破時の文字色が黒になるのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / MainFormLabels.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.Windows.Forms;\r
19 using KancolleSniffer.Model;\r
20 using static System.Math;\r
21 \r
22 namespace KancolleSniffer.View\r
23 {\r
24     /// <summary>\r
25     /// 艦娘名の横幅\r
26     /// 艦娘名のラベルのZ-orderは最下なので名前が長すぎると右隣のラベルの下に隠れるが、\r
27     /// 空装備マークはラベルの右端に表示するので右端が見えるように縮める必要がある。\r
28     /// </summary>\r
29     public enum ShipNameWidth\r
30     {\r
31         MainPanel = 92, // 左端2 HP右端129幅35 129-2-35=92\r
32         AkashiTimer = 53, // 左端2 タイマー左端55 55-2=53 漢字4文字\r
33         NDock = 65, // 左端29 終了時刻右端138幅47 138-47-29=62 空装備マークなし漢字5文字65\r
34         RepairList = 65, // 左端9 時間左端75 75-9=66 漢字5文字65\r
35         RepairListFull = 73, // 左端10 HP右端118幅35 118-10-35=73\r
36         ShipList = 81, // 左端10 HP右端126幅35 126-10-35=81\r
37         GroupConfig = 80, // 左端10 レベル左端90 90-10=80\r
38         Combined = 53, // 左端2 HP右端88幅35 88-2-35=51 空装備マーク犠牲 漢字4文字53\r
39         BattleResult = 65, // 左端2 HP右端101幅35 101-1-35=65\r
40         CiShipName = 65, // 左端168幅236 236-168=68 漢字5文字65\r
41         Max = int.MaxValue\r
42     }\r
43 \r
44     public class MainFormPanels\r
45     {\r
46         public Control PanelShipInfo { get; set; }\r
47         public Control Panel7Ships { get; set; }\r
48         public Control PanelCombinedFleet { get; set; }\r
49         public Control PanelNDock { get; set; }\r
50     }\r
51 \r
52     public class MainFormLabels\r
53     {\r
54         private readonly ShipLabel[][] _shipLabels = new ShipLabel[ShipInfo.MemberCount][];\r
55         private readonly ShipLabel[][] _shipLabels7 = new ShipLabel[7][];\r
56         private readonly ShipLabel[][] _combinedLabels = new ShipLabel[ShipInfo.MemberCount * 2][];\r
57         private readonly ShipLabel[] _akashiTimers = new ShipLabel[ShipInfo.MemberCount];\r
58         private readonly ShipLabel[] _akashiTimers7 = new ShipLabel[ShipInfo.MemberCount];\r
59         private readonly ShipLabel[][] _ndockLabels = new ShipLabel[DockInfo.DockCount][];\r
60         private readonly List<ShipLabel> _hpLabels = new List<ShipLabel>();\r
61         private readonly MainFormPanels _panels;\r
62         public bool ShowHpInPercent { get; private set; }\r
63 \r
64         public MainFormLabels(MainFormPanels panels)\r
65         {\r
66             _panels = panels;\r
67         }\r
68 \r
69         public void CreateAllShipLabels(EventHandler onClick)\r
70         {\r
71             CreateAkashiTimers(_panels.PanelShipInfo);\r
72             CreateShipLabels(_panels.PanelShipInfo, onClick);\r
73             CreateAkashiTimers7(_panels.Panel7Ships);\r
74             CreateShipLabels7(_panels.Panel7Ships, onClick);\r
75             CreateCombinedShipLabels(_panels.PanelCombinedFleet, onClick);\r
76         }\r
77 \r
78         public void CreateNDockLabels(EventHandler onClick)\r
79         {\r
80             CreateNDockLabels(_panels.PanelNDock, onClick);\r
81         }\r
82 \r
83         private void CreateShipLabels(Control parent, EventHandler onClick)\r
84         {\r
85             CreateShipLabels(parent, onClick, _shipLabels, 16);\r
86         }\r
87 \r
88         private void CreateShipLabels7(Control parent, EventHandler onClick)\r
89         {\r
90             CreateShipLabels(parent, onClick, _shipLabels7, 14);\r
91         }\r
92 \r
93         private void CreateShipLabels(Control parent, EventHandler onClick, ShipLabel[][] shipLabels, int lineHeight)\r
94         {\r
95             parent.SuspendLayout();\r
96             const int top = 1, height = 12;\r
97             ShipLabel[] headings;\r
98             parent.Controls.AddRange(headings = new[]\r
99             {\r
100                 new ShipLabel {Location = new Point(109, top), Text = "HP", AutoSize = true},\r
101                 new ShipLabel {Location = new Point(128, top), Text = "cond", AutoSize = true},\r
102                 new ShipLabel {Location = new Point(162, top), Text = "Lv", AutoSize = true},\r
103                 new ShipLabel {Location = new Point(194, top), Text = "Exp", AutoSize = true},\r
104                 new ShipLabel {Location = new Point(0, 1), Size = new Size(parent.Width, lineHeight - 1)}\r
105             });\r
106             foreach (var label in headings)\r
107             {\r
108                 label.Scale();\r
109                 label.BackColor = ShipLabel.ColumnColors[1];\r
110             }\r
111             for (var i = 0; i < shipLabels.Length; i++)\r
112             {\r
113                 var y = top + lineHeight * (i + 1);\r
114                 parent.Controls.AddRange(shipLabels[i] = new[]\r
115                 {\r
116                     new ShipLabel\r
117                     {\r
118                         Location = new Point(129, y),\r
119                         AutoSize = true,\r
120                         AnchorRight = true,\r
121                         MinimumSize = new Size(0, lineHeight),\r
122                         TextAlign = ContentAlignment.MiddleLeft,\r
123                         Cursor = Cursors.Hand\r
124                     },\r
125                     new ShipLabel\r
126                     {\r
127                         Location = new Point(131, y),\r
128                         Size = new Size(24, lineHeight),\r
129                         TextAlign = ContentAlignment.MiddleRight\r
130                     },\r
131                     new ShipLabel\r
132                     {\r
133                         Location = new Point(155, y + 2),\r
134                         Size = new Size(24, height),\r
135                         TextAlign = ContentAlignment.MiddleRight\r
136                     },\r
137                     new ShipLabel\r
138                     {\r
139                         Location = new Point(176, y + 2),\r
140                         Size = new Size(42, height),\r
141                         TextAlign = ContentAlignment.MiddleRight\r
142                     },\r
143                     new ShipLabel {Location = new Point(2, y + 2), AutoSize = true}, // 名前のZ-orderを下に\r
144                     new ShipLabel {Location = new Point(0, y), Size = new Size(parent.Width, lineHeight)}\r
145                 });\r
146                 foreach (var label in shipLabels[i])\r
147                 {\r
148                     label.Scale();\r
149                     label.PresetColor = label.BackColor = ShipLabel.ColumnColors[i % 2];\r
150                     label.Tag = i;\r
151                     label.Click += onClick;\r
152                 }\r
153                 var hpLabel = shipLabels[i][0];\r
154                 _hpLabels.Add(hpLabel);\r
155                 hpLabel.DoubleClick += HpLabelClickHandler;\r
156             }\r
157             headings[0].Cursor = Cursors.Hand;\r
158             headings[0].Click += HpLabelClickHandler;\r
159             parent.ResumeLayout();\r
160         }\r
161 \r
162         private void HpLabelClickHandler(object sender, EventArgs ev)\r
163         {\r
164             ToggleHpPercent();\r
165         }\r
166 \r
167         public void ToggleHpPercent()\r
168         {\r
169             ShowHpInPercent = !ShowHpInPercent;\r
170             foreach (var label in _hpLabels)\r
171                 label.ToggleHpPercent();\r
172         }\r
173 \r
174         public void SetShipLabels(IReadOnlyList<ShipStatus> ships)\r
175         {\r
176             SetShipLabels(ships, ships.Count == 7 ? _shipLabels7 : _shipLabels);\r
177         }\r
178 \r
179         public void SetShipLabels(IReadOnlyList<ShipStatus> ships, ShipLabel[][] shipLabels)\r
180         {\r
181             for (var i = 0; i < shipLabels.Length; i++)\r
182             {\r
183                 var labels = shipLabels[i];\r
184                 var ship = i < ships.Count ? ships[i] : null;\r
185                 labels[0].SetHp(ship);\r
186                 labels[1].SetCond(ship);\r
187                 labels[2].SetLevel(ship);\r
188                 labels[3].SetExpToNext(ship);\r
189                 labels[4].SetName(ship, ShipNameWidth.MainPanel);\r
190             }\r
191         }\r
192 \r
193         public void CreateCombinedShipLabels(Control parent, EventHandler onClick)\r
194         {\r
195             parent.SuspendLayout();\r
196             const int top = 1, lh = 16;\r
197             const int parentWidth = 220; // parent.Widthを使うとDPIスケーリング時に計算がくるうので\r
198             ShipLabel[] headings;\r
199             parent.Controls.AddRange(headings = new[]\r
200             {\r
201                 new ShipLabel {Location = new Point(68, top), Text = "HP", AutoSize = true},\r
202                 new ShipLabel {Location = new Point(86, top), Text = "cnd", AutoSize = true},\r
203                 new ShipLabel {Location = new Point(177, top), Text = "HP", AutoSize = true},\r
204                 new ShipLabel {Location = new Point(195, top), Text = "cnd", AutoSize = true},\r
205                 new ShipLabel {Location = new Point(0, 1), Size = new Size(parentWidth, lh - 1)}\r
206             });\r
207             foreach (var label in headings)\r
208             {\r
209                 label.Scale();\r
210                 label.BackColor = ShipLabel.ColumnColors[1];\r
211             }\r
212             for (var i = 0; i < _combinedLabels.Length; i++)\r
213             {\r
214                 var x = parentWidth / 2 * (i / ShipInfo.MemberCount);\r
215                 var y = top + lh * (i % ShipInfo.MemberCount + 1);\r
216                 parent.Controls.AddRange(_combinedLabels[i] = new[]\r
217                 {\r
218                     new ShipLabel\r
219                     {\r
220                         Location = new Point(x + 88, y),\r
221                         AutoSize = true,\r
222                         AnchorRight = true,\r
223                         MinimumSize = new Size(0, lh),\r
224                         TextAlign = ContentAlignment.MiddleLeft,\r
225                         Cursor = Cursors.Hand\r
226                     },\r
227                     new ShipLabel\r
228                     {\r
229                         Location = new Point(x + 85, y),\r
230                         Size = new Size(24, lh),\r
231                         TextAlign = ContentAlignment.MiddleRight\r
232                     },\r
233                     new ShipLabel {Location = new Point(x + 2, y + 2), AutoSize = true}, // 名前のZ-orderを下に\r
234                     new ShipLabel {Location = new Point(x, y), Size = new Size(parentWidth / 2, lh)}\r
235                 });\r
236                 foreach (var label in _combinedLabels[i])\r
237                 {\r
238                     label.Scale();\r
239                     label.PresetColor = label.BackColor = ShipLabel.ColumnColors[i % 2];\r
240                     label.Tag = i;\r
241                     label.Click += onClick;\r
242                 }\r
243                 var hpLabel = _combinedLabels[i][0];\r
244                 _hpLabels.Add(hpLabel);\r
245                 hpLabel.DoubleClick += HpLabelClickHandler;\r
246             }\r
247             headings[0].Cursor = headings[2].Cursor = Cursors.Hand;\r
248             headings[0].Click += HpLabelClickHandler;\r
249             headings[2].Click += HpLabelClickHandler;\r
250             parent.ResumeLayout();\r
251         }\r
252 \r
253         public void SetCombinedShipLabels(IReadOnlyList<ShipStatus> first, IReadOnlyList<ShipStatus> second)\r
254         {\r
255             for (var i = 0; i < _combinedLabels.Length; i++)\r
256             {\r
257                 var idx = i % ShipInfo.MemberCount;\r
258                 var ships = i < ShipInfo.MemberCount ? first : second;\r
259                 var labels = _combinedLabels[i];\r
260                 var s = idx < ships.Count ? ships[idx] : null;\r
261                 labels[0].SetHp(s);\r
262                 labels[1].SetCond(s);\r
263                 labels[2].SetName(s, ShipNameWidth.Combined);\r
264             }\r
265         }\r
266 \r
267         public void CreateAkashiTimers(Control parent)\r
268         {\r
269             CreateAkashiTimers(parent, _akashiTimers, 16);\r
270         }\r
271 \r
272         public void CreateAkashiTimers7(Control parent)\r
273         {\r
274             CreateAkashiTimers(parent, _akashiTimers7, 14);\r
275         }\r
276 \r
277         public void CreateAkashiTimers(Control parent, ShipLabel[] timerLabels, int lineHeight)\r
278         {\r
279             parent.SuspendLayout();\r
280             for (var i = 0; i < timerLabels.Length; i++)\r
281             {\r
282                 const int x = 55;\r
283                 var y = 3 + lineHeight * (i + 1);\r
284                 ShipLabel label;\r
285                 parent.Controls.Add(\r
286                     label = timerLabels[i] =\r
287                         new ShipLabel\r
288                         {\r
289                             Location = new Point(x, y),\r
290                             Size = new Size(31, 12),\r
291                             TextAlign = ContentAlignment.TopRight\r
292                         });\r
293                 label.BackColor = ShipLabel.ColumnColors[i % 2];\r
294             }\r
295             foreach (var label in timerLabels)\r
296                 label.Scale();\r
297             parent.ResumeLayout();\r
298         }\r
299 \r
300         public void AdjustAkashiTimers()\r
301         {\r
302             AdjustAkashiTimers(_akashiTimers, 16);\r
303             AdjustAkashiTimers(_akashiTimers7, 14);\r
304         }\r
305 \r
306         public void AdjustAkashiTimers(ShipLabel[] timers, int lineHeight)\r
307         {\r
308             var scale = ShipLabel.ScaleFactor;\r
309             if (scale.Height < 1.2)\r
310                 return;\r
311             for (var i = 0; i < timers.Length; i++)\r
312             {\r
313                 const int x = 55;\r
314                 var y = 3 + lineHeight * (i + 1);\r
315                 timers[i].Location = new Point((int)Round(x * scale.Width) - 3, (int)Round(y * scale.Height));\r
316                 timers[i].Size = new Size((int)Round(31 * scale.Width) + 1, (int)Round(12 * scale.Height));\r
317             }\r
318         }\r
319 \r
320         public void SetAkashiTimer(IReadOnlyList<ShipStatus> ships, AkashiTimer.RepairSpan[] timers)\r
321         {\r
322             if (ships.Count == 7)\r
323             {\r
324                 SetAkashiTimer(ships, timers, _akashiTimers7, _shipLabels7);\r
325             }\r
326             else\r
327             {\r
328                 SetAkashiTimer(ships, timers, _akashiTimers, _shipLabels);\r
329             }\r
330         }\r
331 \r
332         public void SetAkashiTimer(IReadOnlyList<ShipStatus> ships, AkashiTimer.RepairSpan[] timers,\r
333             ShipLabel[] timerLabels, ShipLabel[][] shipLabels)\r
334         {\r
335             var shortest = -1;\r
336             for (var i = 0; i < timers.Length; i++)\r
337             {\r
338                 if (timers[i].Span <= TimeSpan.Zero)\r
339                     continue;\r
340                 if (shortest == -1 || timers[i].Span < timers[shortest].Span)\r
341                     shortest = i;\r
342             }\r
343             for (var i = 0; i < timerLabels.Length; i++)\r
344             {\r
345                 var label = timerLabels[i];\r
346                 var labelHp = shipLabels[i][0];\r
347                 var labelName = shipLabels[i][4];\r
348                 if (i >= timers.Length || timers[i].Span == TimeSpan.MinValue)\r
349                 {\r
350                     label.Visible = false;\r
351                     continue;\r
352                 }\r
353                 var timer = timers[i];\r
354                 var stat = ships[i];\r
355                 label.Visible = true;\r
356                 label.Text = timer.Span.ToString(@"mm\:ss");\r
357                 label.ForeColor = Control.DefaultForeColor;\r
358                 labelName.SetName(stat, ShipNameWidth.AkashiTimer);\r
359                 if (timer.Diff == 0)\r
360                     continue;\r
361                 if (i == shortest)\r
362                     label.ForeColor = CUDColors.Red;\r
363                 labelHp.SetHp(stat.NowHp + timer.Diff, stat.MaxHp);\r
364                 labelHp.ForeColor = Color.DimGray;\r
365             }\r
366         }\r
367 \r
368         public void CreateNDockLabels(Control parent, EventHandler onClick)\r
369         {\r
370             const int lh = 15;\r
371             for (var i = 0; i < _ndockLabels.Length; i++)\r
372             {\r
373                 var y = i * lh;\r
374                 parent.Controls.AddRange(\r
375                     _ndockLabels[i] = new[]\r
376                     {\r
377                         new ShipLabel\r
378                         {\r
379                             Location = new Point(138, y + 2),\r
380                             AutoSize = true,\r
381                             AnchorRight = true,\r
382                             MinimumSize = new Size(0, lh),\r
383                             TextAlign = ContentAlignment.MiddleLeft,\r
384                             Cursor = Cursors.Hand\r
385                         },\r
386                         new ShipLabel {Location = new Point(29, y + 3), AutoSize = true} // 名前のZ-orderを下に\r
387                     });\r
388                 foreach (var label in _ndockLabels[i])\r
389                 {\r
390                     label.Scale();\r
391                     label.Click += onClick;\r
392                 }\r
393             }\r
394         }\r
395 \r
396         public void SetNDockLabels(NameAndTimer[] ndock)\r
397         {\r
398             for (var i = 0; i < _ndockLabels.Length; i++)\r
399                 _ndockLabels[i][1].SetName(ndock[i].Name, ShipNameWidth.NDock);\r
400         }\r
401 \r
402         public void SetNDockTimer(int dock, AlarmTimer timer, DateTime now, bool finishTime)\r
403         {\r
404             var label = _ndockLabels[dock][0];\r
405             label.ForeColor = timer.IsFinished(now) ? CUDColors.Red : Color.Black;\r
406             label.Text = timer.ToString(now, finishTime);\r
407         }\r
408     }\r
409 }