OSDN Git Service

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