OSDN Git Service

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