OSDN Git Service

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