OSDN Git Service

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