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;
\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 Invalidate(); // 必ずOnPaintを実行させるため
\r
150 private void ChangeFont(string name)
\r
152 var lu = StartWithLetter(name);
\r
153 var shift = Scaler.ScaleHeight(1);
\r
154 if (lu && !Font.Equals(LatinFont))
\r
156 Location += new Size(0, -shift);
\r
159 else if (!lu && Font.Equals(LatinFont))
\r
161 Location += new Size(0, shift);
\r
166 public static bool StartWithLetter(string name)
\r
168 return Regex.IsMatch(name, @"^\p{Lu}");
\r
171 protected override void OnPaint(PaintEventArgs e)
\r
174 if ((_slotStatus & SlotStatus.NormalEmpty) != 0)
\r
176 e.Graphics.DrawRectangle(Pens.Black,
\r
177 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 0), Scaler.Scale(2, 5)));
\r
179 else if ((_slotStatus & SlotStatus.SemiEquipped) != 0)
\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
185 if ((_slotStatus & SlotStatus.ExtraEmpty) != 0)
\r
187 e.Graphics.DrawRectangle(Pens.Black,
\r
188 new Rectangle(Scaler.Move(ClientSize.Width, 0, -3, 8), Scaler.Scale(2, 3)));
\r
193 public sealed class Hp : ShipLabel
\r
195 private bool _hpPercent;
\r
196 private ShipStatus _status;
\r
202 public Hp(Point location, int height)
\r
204 Location = location;
\r
205 MinimumSize = new Size(0, height);
\r
206 TextAlign = ContentAlignment.MiddleLeft;
\r
208 Cursor = Cursors.Hand;
\r
211 public override void Reset()
\r
215 BackColor = InitialBackColor;
\r
218 public override void Set(ShipStatus status)
\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
227 public void ToggleHpPercent()
\r
229 _hpPercent = !_hpPercent;
\r
230 if (_status != null)
\r
234 public void SetHp(int now, int max)
\r
236 Set(new ShipStatus {NowHp = now, MaxHp = max});
\r
239 public Color DamageColor(ShipStatus status)
\r
241 switch (status.DamageLevel)
\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
252 return InitialBackColor;
\r
256 public void SetColor(ShipStatus status)
\r
258 BackColor = DamageColor(status);
\r
262 public sealed class Cond : ShipLabel
\r
264 public Cond(Point location, int height)
\r
266 Location = location;
\r
267 Size = new Size(24, height);
\r
268 TextAlign = ContentAlignment.MiddleRight;
\r
271 public override void Reset()
\r
274 BackColor = InitialBackColor;
\r
277 public override void Set(ShipStatus status)
\r
279 var cond = status.Cond;
\r
280 Text = cond.ToString("D");
\r
281 BackColor = cond >= 50
\r
291 public sealed class Level : ShipLabel
\r
293 public Level(Point location, int height)
\r
295 Location = location;
\r
296 Size = new Size(24, height);
\r
297 TextAlign = ContentAlignment.MiddleRight;
\r
300 public override void Reset()
\r
305 public override void Set(ShipStatus status)
\r
307 Text = status.Level.ToString("D");
\r
311 public sealed class Exp : ShipLabel
\r
313 public Exp(Point location, int height)
\r
315 Location = location;
\r
316 Size = new Size(42, height);
\r
317 TextAlign = ContentAlignment.MiddleRight;
\r
320 public override void Reset()
\r
325 public override void Set(ShipStatus status)
\r
327 Text = status.ExpToNext.ToString("D");
\r
331 public sealed class Fleet : ShipLabel
\r
333 public Fleet(Point location)
\r
335 Location = location;
\r
339 public override void Reset()
\r
344 public override void Set(ShipStatus status)
\r
346 Text = status.Fleet == null ? "" : new[] {"1", "2", "3", "4"}[status.Fleet.Number];
\r
350 public sealed class RepairTime : ShipLabel
\r
352 public RepairTime(Point location)
\r
354 Location = location;
\r
358 public override void Reset()
\r
363 public override void Set(ShipStatus status)
\r
365 SetRepairTime(status.RepairTime);
\r
368 public void SetRepairTime(TimeSpan span)
\r
370 Text = $@"{(int)span.TotalHours:d2}:{span:mm\:ss}";
\r