OSDN Git Service

sourceforge.jpからosdn.jpへの変更に対応する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ShipLabels.cs
1 // Copyright (C) 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 // \r
3 // This program is part of KancolleSniffer.\r
4 //\r
5 // KancolleSniffer is free software: you can redistribute it and/or modify\r
6 // it under the terms of the GNU General Public License as published by\r
7 // the Free Software Foundation, either version 3 of the License, or\r
8 // (at your option) any later version.\r
9 //\r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 //\r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 using System;\r
19 using System.Drawing;\r
20 using System.Text.RegularExpressions;\r
21 using System.Windows.Forms;\r
22 \r
23 namespace KancolleSniffer\r
24 {\r
25     public class ShipLabels\r
26     {\r
27         private readonly ShipLabel[][] _labels = new ShipLabel[ShipInfo.MemberCount][];\r
28         private readonly ShipLabel[] _akashiTimers = new ShipLabel[ShipInfo.MemberCount];\r
29         private readonly ShipLabel[][] _damagedShipList = new ShipLabel[16][];\r
30         private Control _panelDamagedShipList;\r
31         private readonly ShipLabel[][] _ndockLabels = new ShipLabel[DockInfo.DockCount][];\r
32         public static Color[] ColumnColors = {SystemColors.Control, Color.FromArgb(255, 250, 250, 250)};\r
33 \r
34         public void CreateLabels(Control parent, EventHandler onClick)\r
35         {\r
36             parent.SuspendLayout();\r
37             const int top = 3, height = 12, lh = 16;\r
38             ShipLabel[] headings;\r
39             parent.Controls.AddRange(headings = new[]\r
40             {\r
41                 new ShipLabel {Location = new Point(109, top), Text = "HP", AutoSize = true},\r
42                 new ShipLabel {Location = new Point(128, top), Text = "cond", AutoSize = true},\r
43                 new ShipLabel {Location = new Point(163, top), Text = "Lv", AutoSize = true},\r
44                 new ShipLabel {Location = new Point(194, top), Text = "Exp", AutoSize = true},\r
45                 new ShipLabel {Location = new Point(0, 1), Size = new Size(parent.Width, lh - 1)}\r
46             });\r
47             foreach (var label in headings)\r
48             {\r
49                 label.Scale();\r
50                 label.BackColor = ColumnColors[1];\r
51             }\r
52             for (var i = 0; i < _labels.Length; i++)\r
53             {\r
54                 var y = top + lh * (i + 1);\r
55                 parent.Controls.AddRange(_labels[i] = new[]\r
56                 {\r
57                     new ShipLabel {Location = new Point(129, y), AutoSize = true, AnchorRight = true},\r
58                     new ShipLabel\r
59                     {\r
60                         Location = new Point(132, y),\r
61                         Size = new Size(23, height),\r
62                         TextAlign = ContentAlignment.MiddleRight\r
63                     },\r
64                     new ShipLabel\r
65                     {\r
66                         Location = new Point(157, y),\r
67                         Size = new Size(23, height),\r
68                         TextAlign = ContentAlignment.MiddleRight\r
69                     },\r
70                     new ShipLabel\r
71                     {\r
72                         Location = new Point(177, y),\r
73                         Size = new Size(41, height),\r
74                         TextAlign = ContentAlignment.MiddleRight\r
75                     },\r
76                     new ShipLabel {Location = new Point(2, y), AutoSize = true}, // 名前のZ-orderを下に\r
77                     new ShipLabel {Location = new Point(0, y - 2), Size = new Size(parent.Width, lh - 1)}\r
78                 });\r
79                 foreach (var label in _labels[i])\r
80                 {\r
81                     label.Scale();\r
82                     label.PresetColor = label.BackColor = ColumnColors[i % 2];\r
83                     label.Tag = i;\r
84                     label.Click += onClick;\r
85                 }\r
86             }\r
87             parent.ResumeLayout();\r
88         }\r
89 \r
90         public void SetShipInfo(ShipStatus[] statuses)\r
91         {\r
92             var empty = new ShipStatus();\r
93             for (var i = 0; i < _labels.Length; i++)\r
94             {\r
95                 var labels = _labels[i];\r
96                 var s = i < statuses.Length ? statuses[i] : empty;\r
97                 labels[0].SetHp(s);\r
98                 labels[1].SetCond(s);\r
99                 labels[2].SetLevel(s);\r
100                 labels[3].SetExpToNext(s);\r
101                 labels[4].SetName(s);\r
102             }\r
103         }\r
104 \r
105         public void CreateAkashiTimers(Control parent)\r
106         {\r
107             parent.SuspendLayout();\r
108             for (var i = 0; i < _akashiTimers.Length; i++)\r
109             {\r
110                 const int x = 54;\r
111                 var y = 20 + 16 * i;\r
112                 ShipLabel label;\r
113                 parent.Controls.Add(\r
114                     label = _akashiTimers[i] = new ShipLabel {Location = new Point(x, y), AutoSize = true});\r
115                 label.BackColor = ColumnColors[i % 2];\r
116             }\r
117             foreach (var label in _akashiTimers)\r
118                 label.Scale();\r
119             parent.ResumeLayout();\r
120         }\r
121 \r
122         public void SetAkashiTimer(ShipStatus[] statuses, AkashiTimer.RepairSpan[] timers)\r
123         {\r
124             var shortest = -1;\r
125             for (var i = 0; i < timers.Length; i++)\r
126             {\r
127                 if (timers[i].Span <= TimeSpan.Zero)\r
128                     continue;\r
129                 if (shortest == -1 || timers[i].Span < timers[shortest].Span)\r
130                     shortest = i;\r
131             }\r
132             for (var i = 0; i < _akashiTimers.Length; i++)\r
133             {\r
134                 var label = _akashiTimers[i];\r
135                 var labelHp = _labels[i][0];\r
136                 if (i >= timers.Length || timers[i].Span == TimeSpan.MinValue)\r
137                 {\r
138                     label.Visible = false;\r
139                     labelHp.ForeColor = Control.DefaultForeColor;\r
140                     continue;\r
141                 }\r
142                 var timer = timers[i];\r
143                 var stat = statuses[i];\r
144                 label.Visible = true;\r
145                 label.Text = timer.Span.ToString(@"mm\:ss");\r
146                 label.ForeColor = Control.DefaultForeColor;\r
147                 if (timer.Diff == 0)\r
148                 {\r
149                     labelHp.ForeColor = Control.DefaultForeColor;\r
150                     continue;\r
151                 }\r
152                 if (i == shortest)\r
153                     label.ForeColor = Color.Red;\r
154                 labelHp.ForeColor = Color.DimGray;\r
155                 labelHp.SetHp(stat.NowHp + timer.Diff, stat.MaxHp);\r
156             }\r
157         }\r
158 \r
159         public void CreateDamagedShipList(Control parent)\r
160         {\r
161             parent.SuspendLayout();\r
162             for (var i = 0; i < _damagedShipList.Length; i++)\r
163             {\r
164                 var y = 3 + i * 16;\r
165                 const int height = 12;\r
166                 parent.Controls.AddRange(_damagedShipList[i] = new[]\r
167                 {\r
168                     new ShipLabel {Location = new Point(1, y), Size = new Size(11, height)},\r
169                     new ShipLabel {Location = new Point(79, y), AutoSize = true},\r
170                     new ShipLabel {Location = new Point(123, y), Size = new Size(5, height - 1)},\r
171                     new ShipLabel {Location = new Point(10, y), AutoSize = true},\r
172                     new ShipLabel {Location = new Point(0, y - 2), Size = new Size(parent.Width, height + 3)}\r
173                 });\r
174                 foreach (var label in _damagedShipList[i])\r
175                 {\r
176                     label.Scale();\r
177                     label.PresetColor = label.BackColor = ColumnColors[(i + 1) % 2];\r
178                 }\r
179             }\r
180             _panelDamagedShipList = parent;\r
181             parent.ResumeLayout();\r
182         }\r
183 \r
184         public void SetDamagedShipList(ShipStatus[] list)\r
185         {\r
186             const int fleet = 0, name = 3, time = 1, damage = 2;\r
187             var parent = _panelDamagedShipList;\r
188             var num = Math.Min(list.Length, _damagedShipList.Length);\r
189             if (num == 0)\r
190             {\r
191                 parent.Size = new Size(parent.Width, (int)Math.Round(ShipLabel.ScaleFactor.Height * 19));\r
192                 var labels = _damagedShipList[0];\r
193                 labels[fleet].Text = "";\r
194                 labels[name].SetName("なし");\r
195                 labels[time].Text = "";\r
196                 labels[damage].BackColor = labels[damage].PresetColor;\r
197                 return;\r
198             }\r
199             parent.Size = new Size(parent.Width, (int)Math.Round(ShipLabel.ScaleFactor.Height * (num * 16 + 3)));\r
200             var colors = new[] { Color.FromArgb(255, 225, 225, 21), Color.Orange, Color.Red };\r
201             for (var i = 0; i < num; i++)\r
202             {\r
203                 var s = list[i];\r
204                 var labels = _damagedShipList[i];\r
205                 labels[fleet].SetFleet(s);\r
206                 labels[name].SetName(s);\r
207                 labels[time].SetRepairTime(s);\r
208                 labels[damage].BackColor = (int)s.DamageLevel == 0\r
209                     ? labels[damage].PresetColor\r
210                     : colors[(int)s.DamageLevel - 1];\r
211             }\r
212         }\r
213 \r
214         public void CreateNDockLabels(Control parent)\r
215         {\r
216             for (var i = 0; i < _ndockLabels.Length; i++)\r
217             {\r
218                 var y = 3 + i * 15;\r
219                 parent.Controls.AddRange(\r
220                     _ndockLabels[i] = new[]\r
221                     {\r
222                         new ShipLabel {Location = new Point(93, y), AutoSize = true, Text = "00:00:00"},\r
223                         new ShipLabel {Location = new Point(29, y), AutoSize = true} // 名前のZ-orderを下に\r
224                     });\r
225                 foreach (var label in _ndockLabels[i])\r
226                     label.Scale();\r
227             }\r
228         }\r
229 \r
230         public void SetNDockLabels(NameAndTimer[] ndock)\r
231         {\r
232             for (var i = 0; i < _ndockLabels.Length; i++)\r
233                 _ndockLabels[i][1].SetName(ndock[i].Name);\r
234         }\r
235 \r
236         public void SetNDockTimer(int dock, RingTimer timer)\r
237         {\r
238             var label = _ndockLabels[dock][0];\r
239             label.ForeColor = timer.IsFinished ? Color.Red : Color.Black;\r
240             label.SetRepairTime(timer.Rest);\r
241         }\r
242     }\r
243 \r
244     [System.ComponentModel.DesignerCategory("Code")]\r
245     public class ShipLabel : Label\r
246     {\r
247         public static SizeF ScaleFactor { get; set; }\r
248         public Color PresetColor { get; set; }\r
249         public bool AnchorRight { get; set; }\r
250         private int _right = int.MinValue;\r
251         private int _left;\r
252 \r
253         public void SetName(ShipStatus status)\r
254         {\r
255             SetName((status.Escaped ? "[避]" : "") + status.Name);\r
256         }\r
257 \r
258         public void SetName(string name)\r
259         {\r
260             var lu = name != null && new Regex(@"^\p{Lu}").IsMatch(name);\r
261             var shift = (int)Math.Round(ScaleFactor.Height);\r
262             if (lu && Font.Equals(Parent.Font))\r
263             {\r
264                 Location += new Size(0, -shift);\r
265                 Font = new Font("Tahoma", 8f);\r
266             }\r
267             else if (!lu && !Font.Equals(Parent.Font))\r
268             {\r
269                 Location += new Size(0, shift);\r
270                 Font = Parent.Font;\r
271             }\r
272             Text = name;\r
273         }\r
274 \r
275         public void SetHp(ShipStatus status)\r
276         {\r
277             SetHp(status.NowHp, status.MaxHp);\r
278         }\r
279 \r
280         public void SetHp(int now, int max)\r
281         {\r
282             var colors = new[] {PresetColor, Color.FromArgb(255, 240, 240, 100), Color.Orange, Color.Red};\r
283             Text = string.Format("{0:D}/{1:D}", now, max);\r
284             BackColor = colors[(int)ShipStatus.CalcDamage(now, max)];\r
285         }\r
286 \r
287         public void SetCond(ShipStatus status)\r
288         {\r
289             if (status.Level == 0)\r
290             {\r
291                 Text = "0";\r
292                 BackColor = PresetColor;\r
293                 return;\r
294             }\r
295             var cond = status.Cond;\r
296             Text = cond.ToString("D");\r
297             BackColor = cond >= 50\r
298                 ? Color.Yellow\r
299                 : cond >= 30\r
300                     ? PresetColor\r
301                     : cond >= 20 ? Color.Orange : Color.Red;\r
302         }\r
303 \r
304         public void SetLevel(ShipStatus status)\r
305         {\r
306             Text = status.Level.ToString("D");\r
307         }\r
308 \r
309         public void SetExpToNext(ShipStatus status)\r
310         {\r
311             Text = status.ExpToNext.ToString("D");\r
312         }\r
313 \r
314         public void SetRepairTime(ShipStatus status)\r
315         {\r
316             SetRepairTime(status.RepairTime);\r
317         }\r
318 \r
319         public void SetRepairTime(TimeSpan span)\r
320         {\r
321             Text = string.Format(@"{0:d2}:{1:mm\:ss}", (int)span.TotalHours, span);\r
322         }\r
323 \r
324         public void SetFleet(ShipStatus status)\r
325         {\r
326             Text = new[] {"", "1", "2", "3", "4"}[status.Fleet + 1];\r
327         }\r
328 \r
329         protected override void OnLayout(LayoutEventArgs levent)\r
330         {\r
331             base.OnLayout(levent);\r
332             if (!AnchorRight)\r
333                 return;\r
334             if (_right == int.MinValue || _left != Left)\r
335             {\r
336                 _right = Right;\r
337                 _left = Left;\r
338                 return;\r
339             }\r
340             if (_right == Right)\r
341                 return;\r
342             _left -= Right - _right;\r
343             Location = new Point(_left, Top);\r
344         }\r
345 \r
346         public void Scale()\r
347         {\r
348             Scale(ScaleFactor);\r
349         }\r
350     }\r
351 }