OSDN Git Service

AkashiTimer.GetTimersがnullを返さないようにする
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ShipInfoLabels.cs
1 // Copyright (C) 2014 Kazuhiro Fujieda <fujieda@users.sourceforge.jp>\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 ShipInfoLabels\r
26     {\r
27         private readonly ShipLabel[][] _labels = new ShipLabel[ShipInfo.MemberCount][];\r
28         private readonly Label[] _akashiTimers = new Label[ShipInfo.MemberCount];\r
29         private readonly ShipLabel[][] _damagedShipList = new ShipLabel[14][];\r
30         private Control _panelDamagedShipList;\r
31         public static Color[] ColumnColors = {SystemColors.Control, Color.FromArgb(255, 250, 250, 250)};\r
32 \r
33         public void CreateLabels(Control parent, EventHandler onClick)\r
34         {\r
35             parent.SuspendLayout();\r
36             const int top = 3, height = 12, lh = 16;\r
37             Control[] headings =\r
38             {\r
39                 new Label {Location = new Point(109, top), Text = "HP", AutoSize = true},\r
40                 new Label {Location = new Point(128, top), Text = "cond", AutoSize = true},\r
41                 new Label {Location = new Point(163, top), Text = "Lv", AutoSize = true},\r
42                 new Label {Location = new Point(194, top), Text = "Exp", AutoSize = true},\r
43                 new Label {Location = new Point(0, 1), Size = new Size(parent.Width, lh - 1)}\r
44             };\r
45             foreach (var label in headings)\r
46             {\r
47                 label.Scale(ShipLabel.ScaleFactor);\r
48                 label.BackColor = ColumnColors[1];\r
49             }\r
50             parent.Controls.AddRange(headings);\r
51             for (var i = 0; i < _labels.Length; i++)\r
52             {\r
53                 var y = top + lh * (i + 1);\r
54                 parent.Controls.AddRange(_labels[i] = new[]\r
55                 {\r
56                     new ShipLabel {Location = new Point(129, y), AutoSize = true, AnchorRight = true},\r
57                     new ShipLabel\r
58                     {\r
59                         Location = new Point(132, y),\r
60                         Size = new Size(23, height),\r
61                         TextAlign = ContentAlignment.MiddleRight\r
62                     },\r
63                     new ShipLabel\r
64                     {\r
65                         Location = new Point(157, y),\r
66                         Size = new Size(23, height),\r
67                         TextAlign = ContentAlignment.MiddleRight\r
68                     },\r
69                     new ShipLabel\r
70                     {\r
71                         Location = new Point(177, y),\r
72                         Size = new Size(41, height),\r
73                         TextAlign = ContentAlignment.MiddleRight\r
74                     },\r
75                     new ShipLabel {Location = new Point(2, y), AutoSize = true}, // 名前のZ-orderを下に\r
76                     new ShipLabel {Location = new Point(0, y - 2), Size = new Size(parent.Width, lh - 1)}\r
77                 });\r
78                 foreach (var label in _labels[i])\r
79                 {\r
80                     label.Scale(ShipLabel.ScaleFactor);\r
81                     label.PresetColor = label.BackColor = ColumnColors[i % 2];\r
82                     label.Tag = i;\r
83                     label.Click += onClick;\r
84                 }\r
85             }\r
86             parent.ResumeLayout();\r
87         }\r
88 \r
89         public void SetShipInfo(ShipStatus[] statuses)\r
90         {\r
91             var empty = new ShipStatus();\r
92             for (var i = 0; i < _labels.Length; i++)\r
93             {\r
94                 var labels = _labels[i];\r
95                 var s = i < statuses.Length ? statuses[i] : empty;\r
96                 labels[0].SetHp(s);\r
97                 labels[1].SetCond(s);\r
98                 labels[2].SetLevel(s);\r
99                 labels[3].SetExpToNext(s);\r
100                 labels[4].SetName(s);\r
101             }\r
102         }\r
103 \r
104         public void CreateAkashiTimers(Control parent)\r
105         {\r
106             parent.SuspendLayout();\r
107             for (var i = 0; i < _akashiTimers.Length; i++)\r
108             {\r
109                 const int x = 54;\r
110                 var y = 20 + 16 * i;\r
111                 Label label;\r
112                 parent.Controls.Add(\r
113                     label = _akashiTimers[i] = new Label {Location = new Point(x, y), AutoSize = true});\r
114                 label.BackColor = ColumnColors[i % 2];\r
115             }\r
116             foreach (var label in _akashiTimers)\r
117                 label.Scale(ShipLabel.ScaleFactor);\r
118             parent.ResumeLayout();\r
119         }\r
120 \r
121         public void SetAkashiTimer(ShipStatus[] statuses, AkashiTimer.RepairSpan[] timers)\r
122         {\r
123             for (var i = 0; i < _akashiTimers.Length; i++)\r
124             {\r
125                 var label = _akashiTimers[i];\r
126                 var labelHp = _labels[i][0];\r
127                 if (i >= timers.Length || timers[i].Span == TimeSpan.MinValue)\r
128                 {\r
129                     label.Visible = false;\r
130                     labelHp.ForeColor = Control.DefaultForeColor;\r
131                     continue;\r
132                 }\r
133                 var timer = timers[i];\r
134                 var stat = statuses[i];\r
135                 label.Visible = true;\r
136                 label.Text = timer.Span.ToString(@"mm\:ss");\r
137                 if (timer.Diff == 0)\r
138                 {\r
139                     labelHp.ForeColor = Control.DefaultForeColor;\r
140                     continue;\r
141                 }\r
142                 labelHp.ForeColor = Color.DimGray;\r
143                 labelHp.SetHp(stat.NowHp + timer.Diff, stat.MaxHp);\r
144             }\r
145         }\r
146 \r
147         public void CreateDamagedShipList(Control parent)\r
148         {\r
149             parent.SuspendLayout();\r
150             for (var i = 0; i < _damagedShipList.Length; i++)\r
151             {\r
152                 var y = 3 + i * 16;\r
153                 const int height = 12;\r
154                 parent.Controls.AddRange(_damagedShipList[i] = new[]\r
155                 {\r
156                     new ShipLabel {Location = new Point(1, y), Size = new Size(11, height)},\r
157                     new ShipLabel {Location = new Point(79, y), AutoSize = true},\r
158                     new ShipLabel {Location = new Point(123, y), Size = new Size(5, height - 1)},\r
159                     new ShipLabel {Location = new Point(10, y), AutoSize = true},\r
160                     new ShipLabel {Location = new Point(0, y - 2), Size = new Size(parent.Width, height + 3)}\r
161                 });\r
162                 foreach (var label in _damagedShipList[i])\r
163                 {\r
164                     label.Scale(ShipLabel.ScaleFactor);\r
165                     label.PresetColor = label.BackColor = ColumnColors[(i + 1) % 2];\r
166                 }\r
167             }\r
168             _panelDamagedShipList = parent;\r
169             parent.ResumeLayout();\r
170         }\r
171 \r
172         public void SetDamagedShipList(ShipStatus[] list)\r
173         {\r
174             const int fleet = 0, name = 3, time = 1, damage = 2;\r
175             var parent = _panelDamagedShipList;\r
176             var num = Math.Min(list.Length, _damagedShipList.Length);\r
177             if (num == 0)\r
178             {\r
179                 parent.Size = new Size(parent.Width, (int)Math.Round(ShipLabel.ScaleFactor.Height * 19));\r
180                 var labels = _damagedShipList[0];\r
181                 labels[fleet].Text = "";\r
182                 labels[name].SetName("なし");\r
183                 labels[time].Text = "";\r
184                 labels[damage].BackColor = labels[damage].PresetColor;\r
185                 return;\r
186             }\r
187             parent.Size = new Size(parent.Width, (int)Math.Round(ShipLabel.ScaleFactor.Height * (num * 16 + 3)));\r
188             var colors = new[] { Color.FromArgb(255, 225, 225, 21), Color.Orange, Color.Red };\r
189             for (var i = 0; i < num; i++)\r
190             {\r
191                 var s = list[i];\r
192                 var labels = _damagedShipList[i];\r
193                 labels[fleet].SetFleet(s);\r
194                 labels[name].SetName(s);\r
195                 labels[time].SetRepairTime(s);\r
196                 labels[damage].BackColor = (int)s.DamageLevel == 0\r
197                     ? labels[damage].PresetColor\r
198                     : colors[(int)s.DamageLevel - 1];\r
199             }\r
200         }\r
201     }\r
202 \r
203     [System.ComponentModel.DesignerCategory("Code")]\r
204     public class ShipLabel : Label\r
205     {\r
206         public static SizeF ScaleFactor { get; set; }\r
207         public Color PresetColor { get; set; }\r
208         public bool AnchorRight { get; set; }\r
209         private int _right = int.MinValue;\r
210         private int _left;\r
211 \r
212         public void SetName(ShipStatus status)\r
213         {\r
214             SetName(status.Name);\r
215         }\r
216 \r
217         public void SetName(string name)\r
218         {\r
219             var lu = name != null && new Regex(@"^\p{Lu}").IsMatch(name);\r
220             var shift = (int)Math.Round(ScaleFactor.Height);\r
221             if (lu && Font.Equals(Parent.Font))\r
222             {\r
223                 Location += new Size(0, -shift);\r
224                 Font = new Font("Tahoma", 8f);\r
225             }\r
226             else if (!lu && !Font.Equals(Parent.Font))\r
227             {\r
228                 Location += new Size(0, shift);\r
229                 Font = Parent.Font;\r
230             }\r
231             Text = name;\r
232         }\r
233 \r
234         public void SetHp(ShipStatus status)\r
235         {\r
236             SetHp(status.NowHp, status.MaxHp);\r
237         }\r
238 \r
239         public void SetHp(int now, int max)\r
240         {\r
241             var colors = new[] {PresetColor, Color.FromArgb(255, 240, 240, 100), Color.Orange, Color.Red};\r
242             Text = string.Format("{0:D}/{1:D}", now, max);\r
243             BackColor = colors[(int)ShipStatus.CalcDamage(now, max)];\r
244         }\r
245 \r
246         public void SetCond(ShipStatus status)\r
247         {\r
248             if (status.Level == 0)\r
249             {\r
250                 Text = "0";\r
251                 BackColor = PresetColor;\r
252                 return;\r
253             }\r
254             var cond = status.Cond;\r
255             Text = cond.ToString("D");\r
256             BackColor = cond >= 50\r
257                 ? Color.Yellow\r
258                 : cond >= 30\r
259                     ? PresetColor\r
260                     : cond >= 20 ? Color.Orange : Color.Red;\r
261         }\r
262 \r
263         public void SetLevel(ShipStatus status)\r
264         {\r
265             Text = status.Level.ToString("D");\r
266         }\r
267 \r
268         public void SetExpToNext(ShipStatus status)\r
269         {\r
270             Text = status.ExpToNext.ToString("D");\r
271         }\r
272 \r
273         public void SetRepairTime(ShipStatus status)\r
274         {\r
275             var t = status.RepairTime;\r
276             Text = string.Format(@"{0:d2}:{1:mm\:ss}", (int)t.TotalHours, t);\r
277         }\r
278 \r
279         public void SetFleet(ShipStatus status)\r
280         {\r
281             Text = new[] {"", "1", "2", "3", "4"}[status.Fleet + 1];\r
282         }\r
283 \r
284         protected override void OnLayout(LayoutEventArgs levent)\r
285         {\r
286             base.OnLayout(levent);\r
287             if (!AnchorRight)\r
288                 return;\r
289             if (_right == int.MinValue || _left != Left)\r
290             {\r
291                 _right = Right;\r
292                 _left = Left;\r
293                 return;\r
294             }\r
295             if (_right == Right)\r
296                 return;\r
297             _left -= Right - _right;\r
298             Location = new Point(_left, Top);\r
299         }\r
300     }\r
301 }