1 // Copyright (C) 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>
\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
7 // http://www.apache.org/licenses/LICENSE-2.0
\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
16 using System.ComponentModel;
\r
17 using System.Drawing;
\r
19 using System.Text.RegularExpressions;
\r
20 using System.Windows.Forms;
\r
21 using KancolleSniffer.Model;
\r
22 using static System.Math;
\r
24 namespace KancolleSniffer.View
\r
26 [DesignerCategory("Code")]
\r
27 public abstract class ShipLabel : GrowLeftLabel
\r
29 protected Color InitialBackColor;
\r
31 public override Color BackColor
\r
33 get => base.BackColor;
\r
36 if (InitialBackColor == Color.Empty)
\r
37 InitialBackColor = value;
\r
38 base.BackColor = value;
\r
42 protected ShipLabel()
\r
44 UseMnemonic = false;
\r
47 public abstract void Set(ShipStatus status);
\r
49 public abstract void Reset();
\r
51 public new sealed class Name : ShipLabel
\r
53 private SlotStatus _slotStatus, _prevSlotStatus;
\r
54 private readonly ShipNameWidth _defaultWidth;
\r
56 public static Font LatinFont { get; set; }
\r
57 public static Font BaseFont { get; set; }
\r
59 public Name(Point location, ShipNameWidth defaultWidth)
\r
61 _defaultWidth = defaultWidth;
\r
62 Location = location;
\r
67 private enum SlotStatus
\r
75 public override void Set(ShipStatus status)
\r
77 SetName(status, _defaultWidth);
\r
80 public override void Reset()
\r
85 public void SetName(ShipStatus status, ShipNameWidth width)
\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
93 private static SlotStatus GetSlotStatus(ShipStatus status)
\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
105 private string DameConName(ShipStatus status)
\r
107 switch (status.PreparedDamageControl)
\r
118 private string SpecialAttack(ShipStatus status)
\r
120 switch (status.SpecialAttack)
\r
122 case ShipStatus.Attack.Fire:
\r
124 case ShipStatus.Attack.Fired:
\r
131 public void SetName(string name)
\r
133 SetName(name, _defaultWidth);
\r
136 public void SetName(string name, ShipNameWidth width)
\r
138 SetName("", name, SlotStatus.Equipped, width);
\r
141 private void SetName(string prefix, string name, SlotStatus slotStatus, ShipNameWidth width)
\r
143 _slotStatus = slotStatus;
\r
145 var realWidth = width == ShipNameWidth.Max ? (int)width : Scaler.ScaleWidth((int)width);
\r
146 Text = prefix + StringTruncator.Truncate(name, "", realWidth, Font);
\r
147 if (_prevSlotStatus != _slotStatus)
\r
148 Invalidate(); // OnPaintを実行させるため
\r
149 _prevSlotStatus = _slotStatus;
\r
152 private void ChangeFont(string name)
\r
154 var lu = StartWithLetter(name);
\r
155 var shift = Scaler.ScaleHeight(1);
\r
156 if (lu && !Font.Equals(LatinFont))
\r
158 Location += new Size(0, -shift);
\r
161 else if (!lu && Font.Equals(LatinFont))
\r
163 Location += new Size(0, shift);
\r
168 public static bool StartWithLetter(string name)
\r
170 return Regex.IsMatch(name, @"^\p{Lu}");
\r
173 protected override void OnPaint(PaintEventArgs e)
\r
176 if ((_slotStatus & SlotStatus.NormalEmpty) != 0)
\r
178 e.Graphics.DrawRectangle(Pens.Black,
\r
179 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 0), Scaler.Scale(2, 5)));
\r
181 else if ((_slotStatus & SlotStatus.SemiEquipped) != 0)
\r
183 e.Graphics.DrawLine(Pens.Black,
\r
184 Scaler.Move(ClientSize.Width, 0, -1, 0),
\r
185 Scaler.Move(ClientSize.Width, 0, -1, 5));
\r
187 if ((_slotStatus & SlotStatus.ExtraEmpty) != 0)
\r
189 e.Graphics.DrawRectangle(Pens.Black,
\r
190 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 8), Scaler.Scale(2, 3)));
\r
195 public sealed class Hp : ShipLabel
\r
197 private bool _hpPercent;
\r
198 private ShipStatus _status;
\r
204 public Hp(Point location, int height)
\r
206 Location = location;
\r
207 MinimumSize = new Size(0, height);
\r
208 TextAlign = ContentAlignment.MiddleLeft;
\r
210 Cursor = Cursors.Hand;
\r
213 public override void Reset()
\r
217 BackColor = InitialBackColor;
\r
220 public override void Set(ShipStatus status)
\r
224 ? $"{(int)Floor(status.NowHp * 100.0 / status.MaxHp):D}%"
\r
225 : $"{status.NowHp:D}/{status.MaxHp:D}";
\r
226 BackColor = DamageColor(status);
\r
229 public void ToggleHpPercent()
\r
231 _hpPercent = !_hpPercent;
\r
232 if (_status != null)
\r
236 public void SetHp(int now, int max)
\r
238 Set(new ShipStatus {NowHp = now, MaxHp = max});
\r
241 private Color DamageColor(ShipStatus status)
\r
243 return status.DamageLevel switch
\r
245 ShipStatus.Damage.Sunk => Color.CornflowerBlue,
\r
246 ShipStatus.Damage.Badly => status.Escaped ? CUDColors.LightGray : CUDColors.Red,
\r
247 ShipStatus.Damage.Half => CUDColors.Orange,
\r
248 ShipStatus.Damage.Small => Color.FromArgb(240, 240, 0),
\r
249 _ => InitialBackColor
\r
253 public void SetColor(ShipStatus status)
\r
255 BackColor = DamageColor(status);
\r
259 public sealed class Cond : ShipLabel
\r
261 public Cond(Point location, int height)
\r
263 Location = location;
\r
264 Size = new Size(24, height);
\r
265 TextAlign = ContentAlignment.MiddleRight;
\r
268 public override void Reset()
\r
271 BackColor = InitialBackColor;
\r
274 public override void Set(ShipStatus status)
\r
276 var cond = status.Cond;
\r
277 Text = cond.ToString("D");
\r
278 BackColor = cond >= 50
\r
288 public sealed class Level : ShipLabel
\r
290 public Level(Point location, int height)
\r
292 Location = location;
\r
293 Size = new Size(24, height);
\r
294 TextAlign = ContentAlignment.MiddleRight;
\r
297 public override void Reset()
\r
302 public override void Set(ShipStatus status)
\r
304 Text = status.Level.ToString("D");
\r
308 public sealed class Exp : ShipLabel
\r
310 public Exp(Point location, int height)
\r
312 Location = location;
\r
313 Size = new Size(42, height);
\r
314 TextAlign = ContentAlignment.MiddleRight;
\r
317 public override void Reset()
\r
322 public override void Set(ShipStatus status)
\r
324 Text = status.ExpToNext.ToString("D");
\r
328 public sealed class Fleet : ShipLabel
\r
330 public Fleet(Point location)
\r
332 Location = location;
\r
336 public override void Reset()
\r
341 public override void Set(ShipStatus status)
\r
343 Text = status.Fleet == null ? "" : new[] {"1", "2", "3", "4"}[status.Fleet.Number];
\r
347 public sealed class RepairTime : ShipLabel
\r
349 public RepairTime(Point location)
\r
351 Location = location;
\r
355 public override void Reset()
\r
360 public override void Set(ShipStatus status)
\r
362 SetRepairTime(status.RepairTime);
\r
365 public void SetRepairTime(TimeSpan span)
\r
367 Text = $@"{(int)span.TotalHours:d2}:{span:mm\:ss}";
\r