OSDN Git Service

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