OSDN Git Service

開幕夜戦で前の航空戦の結果がクリアされないのを直す
[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 class ShipLabel : Label\r
28     {\r
29         public static Color[] ColumnColors = {SystemColors.Control, Color.FromArgb(255, 250, 250, 250)};\r
30         public static SizeF ScaleFactor { get; set; }\r
31         public static Font LatinFont { get; set; } = new Font("Tahoma", 8f);\r
32         public Color PresetColor { get; set; }\r
33         public bool AnchorRight { get; set; }\r
34         private int _right = Int32.MinValue;\r
35         private int _left;\r
36         private SlotStatus _slotStatus;\r
37         private ShipStatus _status;\r
38         private bool _hpPercent;\r
39 \r
40         public override Color BackColor\r
41         {\r
42             get => base.BackColor;\r
43             set => base.BackColor = value == DefaultBackColor ? PresetColor : value;\r
44         }\r
45 \r
46         [Flags]\r
47         private enum SlotStatus\r
48         {\r
49             Equipped = 0,\r
50             NormalEmpty = 1,\r
51             ExtraEmpty = 2\r
52         }\r
53 \r
54         public ShipLabel()\r
55         {\r
56             UseMnemonic = false;\r
57         }\r
58 \r
59         public void SetName(ShipStatus status, ShipNameWidth width = ShipNameWidth.Max)\r
60         {\r
61             if (status == null)\r
62             {\r
63                 SetName("");\r
64                 return;\r
65             }\r
66             var empty = SlotStatus.Equipped;\r
67             if (!status.Empty)\r
68             {\r
69                 if (status.Slot.All(item => item.Empty))\r
70                     empty |= SlotStatus.NormalEmpty;\r
71                 if (status.SlotEx.Empty)\r
72                     empty |= SlotStatus.ExtraEmpty;\r
73             }\r
74             var dc = status.PreparedDamageControl;\r
75             var dcName = dc == 42 ? "[ダ]" :\r
76                 dc == 43 ? "[メ]" : "";\r
77             SetName(status.Escaped ? "[避]" : dcName, status.Name, empty, width);\r
78         }\r
79 \r
80         public void SetName(string name)\r
81         {\r
82             SetName("", name, SlotStatus.Equipped);\r
83         }\r
84 \r
85         public void SetName(string name, ShipNameWidth width)\r
86         {\r
87             SetName("", name, SlotStatus.Equipped, width);\r
88         }\r
89 \r
90         private void SetName(string prefix, string name, SlotStatus slotStatus, ShipNameWidth width = ShipNameWidth.Max)\r
91         {\r
92             if (name == null)\r
93                 name = "";\r
94             _slotStatus = slotStatus;\r
95             var lu = new Regex(@"^\p{Lu}").IsMatch(name);\r
96             var shift = (int)Round(ScaleFactor.Height);\r
97             if (lu && Font.Equals(Parent.Font))\r
98             {\r
99                 Location += new Size(0, -shift);\r
100                 Font = LatinFont;\r
101             }\r
102             else if (!lu && !Font.Equals(Parent.Font))\r
103             {\r
104                 Location += new Size(0, shift);\r
105                 Font = Parent.Font;\r
106             }\r
107             var result = prefix + name;\r
108             var measured = TextRenderer.MeasureText(result, Font).Width;\r
109             if (measured <= (int)width)\r
110             {\r
111                 Text = result;\r
112                 Invalidate(); // 必ずOnPaintを実行させるため\r
113                 return;\r
114             }\r
115             var truncated = "";\r
116             foreach (var ch in name)\r
117             {\r
118                 var tmp = truncated + ch;\r
119                 if (TextRenderer.MeasureText(tmp, Font).Width > (int)width * ScaleFactor.Width)\r
120                     break;\r
121                 truncated = tmp;\r
122             }\r
123             Text = prefix + truncated.TrimEnd(' ');\r
124             Invalidate();\r
125         }\r
126 \r
127         public void SetHp(ShipStatus status)\r
128         {\r
129             _status = status;\r
130             if (status == null)\r
131             {\r
132                 Text = "";\r
133                 BackColor = PresetColor;\r
134                 return;\r
135             }\r
136             Text = _hpPercent\r
137                 ? $"{(int)Floor(status.NowHp * 100.0 / status.MaxHp):D}%"\r
138                 : $"{status.NowHp:D}/{status.MaxHp:D}";\r
139             BackColor = DamageColor(status, PresetColor);\r
140         }\r
141 \r
142         public void ToggleHpPercent()\r
143         {\r
144             _hpPercent = !_hpPercent;\r
145             SetHp(_status);\r
146         }\r
147 \r
148         public void SetHp(int now, int max)\r
149         {\r
150             SetHp(new ShipStatus {NowHp = now, MaxHp = max});\r
151         }\r
152 \r
153         public static Color DamageColor(ShipStatus status, Color backColor)\r
154         {\r
155             switch (status.DamageLevel)\r
156             {\r
157                 case ShipStatus.Damage.Sunk:\r
158                     return Color.CornflowerBlue;\r
159                 case ShipStatus.Damage.Badly:\r
160                     return CUDColors.Red;\r
161                 case ShipStatus.Damage.Half:\r
162                     return CUDColors.Orange;\r
163                 case ShipStatus.Damage.Small:\r
164                     return Color.FromArgb(240, 240, 0);\r
165                 default:\r
166                     return backColor;\r
167             }\r
168         }\r
169 \r
170         public void SetCond(ShipStatus status)\r
171         {\r
172             if (status == null)\r
173             {\r
174                 Text = "";\r
175                 BackColor = PresetColor;\r
176                 return;\r
177             }\r
178             var cond = status.Cond;\r
179             Text = cond.ToString("D");\r
180             BackColor = cond >= 50\r
181                 ? CUDColors.Yellow\r
182                 : cond >= 30\r
183                     ? PresetColor\r
184                     : cond >= 20\r
185                         ? CUDColors.Orange\r
186                         : CUDColors.Red;\r
187         }\r
188 \r
189         public void SetLevel(ShipStatus status)\r
190         {\r
191             Text = status?.Level.ToString("D");\r
192         }\r
193 \r
194         public void SetExpToNext(ShipStatus status)\r
195         {\r
196             Text = status?.ExpToNext.ToString("D");\r
197         }\r
198 \r
199         public void SetRepairTime(ShipStatus status)\r
200         {\r
201             if (status == null)\r
202             {\r
203                 Text = "";\r
204                 return;\r
205             }\r
206             SetRepairTime(status.RepairTime);\r
207         }\r
208 \r
209         public void SetRepairTime(TimeSpan span)\r
210         {\r
211             Text = $@"{(int)span.TotalHours:d2}:{span:mm\:ss}";\r
212         }\r
213 \r
214         public void SetFleet(ShipStatus status)\r
215         {\r
216             Text = status?.Fleet == null ? "" : new[] {"1", "2", "3", "4"}[status.Fleet.Number];\r
217         }\r
218 \r
219         protected override void OnLayout(LayoutEventArgs args)\r
220         {\r
221             base.OnLayout(args);\r
222             if (!AnchorRight)\r
223                 return;\r
224             if (_right == int.MinValue || _left != Left)\r
225             {\r
226                 _right = Right;\r
227                 _left = Left;\r
228                 return;\r
229             }\r
230             if (_right == Right)\r
231                 return;\r
232             _left -= Right - _right;\r
233             Location = new Point(_left, Top);\r
234         }\r
235 \r
236         protected override void OnPaint(PaintEventArgs e)\r
237         {\r
238             base.OnPaint(e);\r
239             if ((_slotStatus & SlotStatus.NormalEmpty) != 0)\r
240             {\r
241                 e.Graphics.DrawRectangle(\r
242                     Pens.Black,\r
243                     ClientSize.Width - 3 * ScaleFactor.Width, 1 * ScaleFactor.Height,\r
244                     2 * ScaleFactor.Width, 4 * ScaleFactor.Height);\r
245             }\r
246             if ((_slotStatus & SlotStatus.ExtraEmpty) != 0)\r
247             {\r
248                 e.Graphics.DrawRectangle(\r
249                     Pens.Black,\r
250                     ClientSize.Width - 3 * ScaleFactor.Width, 7 * ScaleFactor.Height,\r
251                     2 * ScaleFactor.Width, 3 * ScaleFactor.Height);\r
252             }\r
253         }\r
254 \r
255         public void Scale()\r
256         {\r
257             Scale(ScaleFactor);\r
258         }\r
259     }\r
260 }