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 private 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 ShipStatus _status;
\r
56 public static Font LatinFont { get; set; }
\r
57 public static Font BaseFont { get; set; }
\r
58 private readonly ShipNameWidth _defaultWidth;
\r
59 private int _nameWidth;
\r
61 public void AdjustWidth(int adjust, bool update = false)
\r
63 _nameWidth = (int)_defaultWidth + Max(-24, adjust);
\r
64 if (update && _status != null)
\r
68 public Name(Point location, ShipNameWidth nameWidth)
\r
70 _defaultWidth = nameWidth;
\r
71 _nameWidth = (int)nameWidth;
\r
72 Location = location;
\r
77 private enum SlotStatus
\r
85 public override void Set(ShipStatus status)
\r
87 SetName(status, _nameWidth);
\r
90 public override void Reset()
\r
95 public void SetName(ShipStatus status, ShipNameWidth width)
\r
97 SetName(status, (int)width);
\r
100 private void SetName(ShipStatus status, int width)
\r
103 var slotStatus = GetSlotStatus(status);
\r
104 var dcName = DameConName(status);
\r
105 var sp = SpecialAttack(status);
\r
106 SetName((status.Escaped ? "[避]" : dcName) + sp, status.Name, slotStatus, width);
\r
109 private static SlotStatus GetSlotStatus(ShipStatus status)
\r
112 return SlotStatus.Equipped;
\r
113 var slots = status.Slot.Take(status.Spec.SlotNum).ToArray();
\r
114 var normal = slots.Any(item => item.Empty)
\r
115 ? slots.All(item => item.Empty) ? SlotStatus.NormalEmpty : SlotStatus.SemiEquipped
\r
116 : SlotStatus.Equipped;
\r
117 var extra = status.SlotEx.Empty ? SlotStatus.ExtraEmpty : SlotStatus.Equipped;
\r
118 return normal | extra;
\r
121 private string DameConName(ShipStatus status)
\r
123 switch (status.PreparedDamageControl)
\r
134 private string SpecialAttack(ShipStatus status)
\r
136 switch (status.SpecialAttack)
\r
138 case ShipStatus.Attack.Fire:
\r
140 case ShipStatus.Attack.Fired:
\r
147 public void SetName(string name)
\r
149 Set(new ShipStatus{Spec = new ShipSpec{Name = name}});
\r
152 private void SetName(string prefix, string name, SlotStatus slotStatus, int width)
\r
154 _slotStatus = slotStatus;
\r
156 var realWidth = width == int.MaxValue ? width : Scaler.ScaleWidth(width);
\r
157 Text = prefix + StringTruncator.Truncate(name, "", realWidth, Font);
\r
158 if (_prevSlotStatus != _slotStatus)
\r
159 Invalidate(); // OnPaintを実行させるため
\r
160 _prevSlotStatus = _slotStatus;
\r
163 private void ChangeFont(string name)
\r
165 var lu = StartWithLetter(name);
\r
166 var shift = Scaler.ScaleHeight(1);
\r
167 if (lu && !Font.Equals(LatinFont))
\r
169 Location += new Size(0, -shift);
\r
172 else if (!lu && Font.Equals(LatinFont))
\r
174 Location += new Size(0, shift);
\r
179 public static bool StartWithLetter(string name)
\r
181 return Regex.IsMatch(name, @"^\p{Lu}");
\r
184 protected override void OnPaint(PaintEventArgs e)
\r
187 if ((_slotStatus & SlotStatus.NormalEmpty) != 0)
\r
189 e.Graphics.DrawRectangle(Pens.Black,
\r
190 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 0), Scaler.Scale(2, 5)));
\r
192 else if ((_slotStatus & SlotStatus.SemiEquipped) != 0)
\r
194 e.Graphics.DrawLine(Pens.Black,
\r
195 Scaler.Move(ClientSize.Width, 0, -1, 0),
\r
196 Scaler.Move(ClientSize.Width, 0, -1, 5));
\r
198 if ((_slotStatus & SlotStatus.ExtraEmpty) != 0)
\r
200 e.Graphics.DrawRectangle(Pens.Black,
\r
201 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 8), Scaler.Scale(2, 3)));
\r
206 public sealed class Hp : ShipLabel
\r
208 private bool _hpPercent;
\r
209 private ShipStatus _status;
\r
215 public Hp(Point location, int height)
\r
217 Location = location;
\r
218 MinimumSize = new Size(0, height);
\r
219 TextAlign = ContentAlignment.MiddleLeft;
\r
221 Cursor = Cursors.Hand;
\r
224 public override void Reset()
\r
228 BackColor = _initialBackColor;
\r
231 public override void Set(ShipStatus status)
\r
235 ? $"{(int)Floor(status.NowHp * 100.0 / status.MaxHp):D}%"
\r
236 : $"{status.NowHp:D}/{status.MaxHp:D}";
\r
237 BackColor = DamageColor(status);
\r
240 public void ToggleHpPercent()
\r
242 _hpPercent = !_hpPercent;
\r
243 if (_status != null)
\r
247 public void SetHp(int now, int max)
\r
249 Set(new ShipStatus {NowHp = now, MaxHp = max});
\r
252 private Color DamageColor(ShipStatus status)
\r
254 return status.DamageLevel switch
\r
256 ShipStatus.Damage.Sunk => Color.CornflowerBlue,
\r
257 ShipStatus.Damage.Badly => status.Escaped ? CUDColors.LightGray : CUDColors.Red,
\r
258 ShipStatus.Damage.Half => CUDColors.Orange,
\r
259 ShipStatus.Damage.Small => Color.FromArgb(240, 240, 0),
\r
260 _ => _initialBackColor
\r
264 public void SetColor(ShipStatus status)
\r
266 BackColor = DamageColor(status);
\r
270 public sealed class Cond : ShipLabel
\r
272 public Cond(Point location, int height)
\r
274 Location = location;
\r
275 Size = new Size(24, height);
\r
276 TextAlign = ContentAlignment.MiddleRight;
\r
279 public override void Reset()
\r
282 BackColor = _initialBackColor;
\r
285 public override void Set(ShipStatus status)
\r
287 var cond = status.Cond;
\r
288 Text = cond.ToString("D");
\r
289 BackColor = cond >= 50
\r
292 ? _initialBackColor
\r
299 public sealed class Level : ShipLabel
\r
301 public Level(Point location, int height)
\r
303 Location = location;
\r
304 Size = new Size(24, height);
\r
305 TextAlign = ContentAlignment.MiddleRight;
\r
308 public override void Reset()
\r
313 public override void Set(ShipStatus status)
\r
315 Text = status.Level.ToString("D");
\r
319 public sealed class Exp : ShipLabel
\r
321 public Exp(Point location, int height)
\r
323 Location = location;
\r
324 Size = new Size(42, height);
\r
325 TextAlign = ContentAlignment.MiddleRight;
\r
328 public override void Reset()
\r
333 public override void Set(ShipStatus status)
\r
335 Text = status.ExpToNext.ToString("D");
\r
339 public sealed class Fleet : ShipLabel
\r
341 public Fleet(Point location)
\r
343 Location = location;
\r
347 public override void Reset()
\r
352 public override void Set(ShipStatus status)
\r
354 Text = status.Fleet == null ? "" : new[] {"1", "2", "3", "4"}[status.Fleet.Number];
\r
358 public sealed class RepairTime : ShipLabel
\r
360 public RepairTime(Point location)
\r
362 Location = location;
\r
366 public override void Reset()
\r
371 public override void Set(ShipStatus status)
\r
373 SetRepairTime(status.RepairTime);
\r
376 private void SetRepairTime(TimeSpan span)
\r
378 Text = $@"{(int)span.TotalHours:d2}:{span:mm\:ss}";
\r