OSDN Git Service

a252c81667dff297be2bbfc0c44c5b6d8a801459
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / ShipLabel.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.ComponentModel;\r
17 using System.Drawing;\r
18 using System.Linq;\r
19 using System.Text.RegularExpressions;\r
20 using System.Windows.Forms;\r
21 using KancolleSniffer.Model;\r
22 using static System.Math;\r
23 \r
24 namespace KancolleSniffer.View\r
25 {\r
26     [DesignerCategory("Code")]\r
27     public abstract class ShipLabel : GrowLeftLabel\r
28     {\r
29         protected Color InitialBackColor;\r
30 \r
31         public override Color BackColor\r
32         {\r
33             get => base.BackColor;\r
34             set\r
35             {\r
36                 if (InitialBackColor == Color.Empty)\r
37                     InitialBackColor = value;\r
38                 base.BackColor = value;\r
39             }\r
40         }\r
41 \r
42         protected ShipLabel()\r
43         {\r
44             UseMnemonic = false;\r
45         }\r
46 \r
47         public abstract void Set(ShipStatus status);\r
48 \r
49         public abstract void Reset();\r
50 \r
51         public new sealed class Name : ShipLabel\r
52         {\r
53             private SlotStatus _slotStatus;\r
54             private readonly ShipNameWidth _defaultWidth;\r
55 \r
56             public static Font LatinFont { get; set; }\r
57             public static Font BaseFont { get; set; }\r
58 \r
59             public Name(Point location, ShipNameWidth defaultWidth)\r
60             {\r
61                 _defaultWidth = defaultWidth;\r
62                 Location = location;\r
63                 AutoSize = true;\r
64             }\r
65 \r
66             [Flags]\r
67             private enum SlotStatus\r
68             {\r
69                 Equipped = 0,\r
70                 SemiEquipped = 1,\r
71                 NormalEmpty = 2,\r
72                 ExtraEmpty = 4\r
73             }\r
74 \r
75             public override void Set(ShipStatus status)\r
76             {\r
77                 SetName(status, _defaultWidth);\r
78             }\r
79 \r
80             public override void Reset()\r
81             {\r
82                 SetName("");\r
83             }\r
84 \r
85             public void SetName(ShipStatus status, ShipNameWidth width)\r
86             {\r
87                 var slotStatus = GetSlotStatus(status);\r
88                 var dcName = DameConName(status);\r
89                 var sp = SpecialAttack(status);\r
90                 SetName((status.Escaped ? "[避]" : dcName) + sp, status.Name, slotStatus, width);\r
91             }\r
92 \r
93             private static SlotStatus GetSlotStatus(ShipStatus status)\r
94             {\r
95                 if (status.Empty)\r
96                     return SlotStatus.Equipped;\r
97                 var slots = status.Slot.Take(status.Spec.SlotNum).ToArray();\r
98                 var normal = slots.Any(item => item.Empty)\r
99                     ? slots.All(item => item.Empty) ? SlotStatus.NormalEmpty : SlotStatus.SemiEquipped\r
100                     : SlotStatus.Equipped;\r
101                 var extra = status.SlotEx.Empty ? SlotStatus.ExtraEmpty : SlotStatus.Equipped;\r
102                 return normal | extra;\r
103             }\r
104 \r
105             private string DameConName(ShipStatus status)\r
106             {\r
107                 switch (status.PreparedDamageControl)\r
108                 {\r
109                     case 42:\r
110                         return "[ダ]";\r
111                     case 43:\r
112                         return "[メ]";\r
113                     default:\r
114                         return "";\r
115                 }\r
116             }\r
117 \r
118             private string SpecialAttack(ShipStatus status)\r
119             {\r
120                 switch (status.SpecialAttack)\r
121                 {\r
122                     case ShipStatus.Attack.Fire:\r
123                         return "+";\r
124                     case ShipStatus.Attack.Fired:\r
125                         return "-";\r
126                     default:\r
127                         return "";\r
128                 }\r
129             }\r
130 \r
131             public void SetName(string name)\r
132             {\r
133                 SetName(name, _defaultWidth);\r
134             }\r
135 \r
136             public void SetName(string name, ShipNameWidth width)\r
137             {\r
138                 SetName("", name, SlotStatus.Equipped, width);\r
139             }\r
140 \r
141             private void SetName(string prefix, string name, SlotStatus slotStatus, ShipNameWidth width)\r
142             {\r
143                 _slotStatus = slotStatus;\r
144                 ChangeFont(name);\r
145                 var realWidth = width == ShipNameWidth.Max ? (int)width : Scaler.ScaleWidth((int)width);\r
146                 Text = prefix + StringTruncator.Truncate(name, "", realWidth, Font);\r
147                 Invalidate(); // 必ずOnPaintを実行させるため\r
148             }\r
149 \r
150             private void ChangeFont(string name)\r
151             {\r
152                 var lu = StartWithLetter(name);\r
153                 var shift = Scaler.ScaleHeight(1);\r
154                 if (lu && !Font.Equals(LatinFont))\r
155                 {\r
156                     Location += new Size(0, -shift);\r
157                     Font = LatinFont;\r
158                 }\r
159                 else if (!lu && Font.Equals(LatinFont))\r
160                 {\r
161                     Location += new Size(0, shift);\r
162                     Font = BaseFont;\r
163                 }\r
164             }\r
165 \r
166             public static bool StartWithLetter(string name)\r
167             {\r
168                 return Regex.IsMatch(name, @"^\p{Lu}");\r
169             }\r
170 \r
171             protected override void OnPaint(PaintEventArgs e)\r
172             {\r
173                 base.OnPaint(e);\r
174                 if ((_slotStatus & SlotStatus.NormalEmpty) != 0)\r
175                 {\r
176                     e.Graphics.DrawRectangle(Pens.Black,\r
177                         new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 0), Scaler.Scale(2, 5)));\r
178                 }\r
179                 else if ((_slotStatus & SlotStatus.SemiEquipped) != 0)\r
180                 {\r
181                     e.Graphics.DrawLine(Pens.Black,\r
182                         Scaler.Move(ClientSize.Width, 0, -1, 0),\r
183                         Scaler.Move(ClientSize.Width, 0, -1, 5));\r
184                 }\r
185                 if ((_slotStatus & SlotStatus.ExtraEmpty) != 0)\r
186                 {\r
187                     e.Graphics.DrawRectangle(Pens.Black,\r
188                         new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 8), Scaler.Scale(2, 3)));\r
189                 }\r
190             }\r
191         }\r
192 \r
193         public sealed class Hp : ShipLabel\r
194         {\r
195             private bool _hpPercent;\r
196             private ShipStatus _status;\r
197 \r
198             public Hp()\r
199             {\r
200             }\r
201 \r
202             public Hp(Point location, int height)\r
203             {\r
204                 Location = location;\r
205                 MinimumSize = new Size(0, height);\r
206                 TextAlign = ContentAlignment.MiddleLeft;\r
207                 GrowLeft = true;\r
208                 Cursor = Cursors.Hand;\r
209             }\r
210 \r
211             public override void Reset()\r
212             {\r
213                 _status = null;\r
214                 Text = "";\r
215                 BackColor = InitialBackColor;\r
216             }\r
217 \r
218             public override void Set(ShipStatus status)\r
219             {\r
220                 _status = status;\r
221                 Text = _hpPercent\r
222                     ? $"{(int)Floor(status.NowHp * 100.0 / status.MaxHp):D}%"\r
223                     : $"{status.NowHp:D}/{status.MaxHp:D}";\r
224                 BackColor = DamageColor(status);\r
225             }\r
226 \r
227             public void ToggleHpPercent()\r
228             {\r
229                 _hpPercent = !_hpPercent;\r
230                 if (_status != null)\r
231                     Set(_status);\r
232             }\r
233 \r
234             public void SetHp(int now, int max)\r
235             {\r
236                 Set(new ShipStatus {NowHp = now, MaxHp = max});\r
237             }\r
238 \r
239             public Color DamageColor(ShipStatus status)\r
240             {\r
241                 switch (status.DamageLevel)\r
242                 {\r
243                     case ShipStatus.Damage.Sunk:\r
244                         return Color.CornflowerBlue;\r
245                     case ShipStatus.Damage.Badly:\r
246                         return CUDColors.Red;\r
247                     case ShipStatus.Damage.Half:\r
248                         return CUDColors.Orange;\r
249                     case ShipStatus.Damage.Small:\r
250                         return Color.FromArgb(240, 240, 0);\r
251                     default:\r
252                         return InitialBackColor;\r
253                 }\r
254             }\r
255 \r
256             public void SetColor(ShipStatus status)\r
257             {\r
258                 BackColor = DamageColor(status);\r
259             }\r
260         }\r
261 \r
262         public sealed class Cond : ShipLabel\r
263         {\r
264             public Cond(Point location, int height)\r
265             {\r
266                 Location = location;\r
267                 Size = new Size(24, height);\r
268                 TextAlign = ContentAlignment.MiddleRight;\r
269             }\r
270 \r
271             public override void Reset()\r
272             {\r
273                 Text = "";\r
274                 BackColor = InitialBackColor;\r
275             }\r
276 \r
277             public override void Set(ShipStatus status)\r
278             {\r
279                 var cond = status.Cond;\r
280                 Text = cond.ToString("D");\r
281                 BackColor = cond >= 50\r
282                     ? CUDColors.Yellow\r
283                     : cond >= 30\r
284                         ? InitialBackColor\r
285                         : cond >= 20\r
286                             ? CUDColors.Orange\r
287                             : CUDColors.Red;\r
288             }\r
289         }\r
290 \r
291         public sealed class Level : ShipLabel\r
292         {\r
293             public Level(Point location, int height)\r
294             {\r
295                 Location = location;\r
296                 Size = new Size(24, height);\r
297                 TextAlign = ContentAlignment.MiddleRight;\r
298             }\r
299 \r
300             public override void Reset()\r
301             {\r
302                 Text = "";\r
303             }\r
304 \r
305             public override void Set(ShipStatus status)\r
306             {\r
307                 Text = status.Level.ToString("D");\r
308             }\r
309         }\r
310 \r
311         public sealed class Exp : ShipLabel\r
312         {\r
313             public Exp(Point location, int height)\r
314             {\r
315                 Location = location;\r
316                 Size = new Size(42, height);\r
317                 TextAlign = ContentAlignment.MiddleRight;\r
318             }\r
319 \r
320             public override void Reset()\r
321             {\r
322                 Text = "";\r
323             }\r
324 \r
325             public override void Set(ShipStatus status)\r
326             {\r
327                 Text = status.ExpToNext.ToString("D");\r
328             }\r
329         }\r
330 \r
331         public sealed class Fleet : ShipLabel\r
332         {\r
333             public Fleet(Point location)\r
334             {\r
335                 Location = location;\r
336                 AutoSize = true;\r
337             }\r
338 \r
339             public override void Reset()\r
340             {\r
341                 Text = "";\r
342             }\r
343 \r
344             public override void Set(ShipStatus status)\r
345             {\r
346                 Text = status.Fleet == null ? "" : new[] {"1", "2", "3", "4"}[status.Fleet.Number];\r
347             }\r
348         }\r
349 \r
350         public sealed class RepairTime : ShipLabel\r
351         {\r
352             public RepairTime(Point location)\r
353             {\r
354                 Location = location;\r
355                 AutoSize = true;\r
356             }\r
357 \r
358             public override void Reset()\r
359             {\r
360                 Text = "";\r
361             }\r
362 \r
363             public override void Set(ShipStatus status)\r
364             {\r
365                 SetRepairTime(status.RepairTime);\r
366             }\r
367 \r
368             public void SetRepairTime(TimeSpan span)\r
369             {\r
370                 Text = $@"{(int)span.TotalHours:d2}:{span:mm\:ss}";\r
371             }\r
372         }\r
373     }\r
374 }