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