using System; using System.Collections.Generic; using System.Windows.Forms; using PKHeX.Core; using PKHeX.Drawing.PokeSprite; namespace PKHeX.WinForms.Controls; public partial class SlotList : UserControl, ISlotViewer { private static readonly string[] names = Enum.GetNames(typeof(StorageSlotType)); private readonly LabelType[] Labels = new LabelType[names.Length]; private readonly List slots = new(); private List SlotOffsets = new(); public int SlotCount { get; private set; } public SaveFile SAV { get; set; } = null!; public bool FlagIllegal { get; set; } public SlotList() { InitializeComponent(); AddLabels(); } /// /// Initializes the extra slot viewers with a list of offsets and sets up event handling. /// /// Extra slots to show /// Events to set up /// Uses an object pool for viewers (only generates as needed) public void Initialize(List list, Action enableDragDropContext) { SlotOffsets = list; LoadSlots(list.Count, enableDragDropContext); } /// /// Hides all slots from the . /// public void HideAllSlots() => LoadSlots(0, _ => { }); public void NotifySlotOld(ISlotInfo previous) { if (previous is not SlotInfoMisc m) return; var index = SlotOffsets.FindIndex(z => m.Equals(z)); if (index < 0) return; var pb = slots[index]; pb.BackgroundImage = null; } public void NotifySlotChanged(ISlotInfo slot, SlotTouchType type, PKM pk) { if (slot is not SlotInfoMisc m) return; var index = GetViewIndex(m); if (index < 0) return; var pb = slots[index]; SlotUtil.UpdateSlot(pb, slot, pk, SAV, FlagIllegal, type); } public int GetViewIndex(ISlotInfo info) => SlotOffsets.FindIndex(info.Equals); public ISlotInfo GetSlotData(PictureBox view) { int slot = GetSlot(view); return GetSlotData(slot); } public ISlotInfo GetSlotData(int slot) => SlotOffsets[slot]; public IList SlotPictureBoxes => slots; public int GetSlot(PictureBox sender) { var view = WinFormsUtil.GetUnderlyingControl(sender); if (view == null) return -1; return slots.IndexOf(view); } public int GetSlotOffset(int slot) => SlotOffsets[slot].Offset; public int ViewIndex { get; set; } = -1; private IEnumerable LoadSlots(int after, Action enableDragDropContext) { var generated = new List(); int before = SlotCount; SlotCount = after; int diff = after - before; if (diff > 0) { AddSlots(diff); for (int i = before; i < after; i++) { var slot = slots[i]; enableDragDropContext(slot); FLP_Slots.Controls.Add(slot); FLP_Slots.SetFlowBreak(slot, true); generated.Add(slot); } } else { for (int i = before - 1; i >= after; i--) FLP_Slots.Controls.Remove(slots[i]); } SetLabelVisibility(); return generated; } private void AddSlots(int count) { for (int i = 0; i < count; i++) slots.Add(GetPictureBox(i, SpriteUtil.Spriter)); } private const int PadPixels = 2; private static PictureBox GetPictureBox(int index, SpriteBuilder s) => new() { BorderStyle = BorderStyle.FixedSingle, Width = s.Width + 2, Height = s.Height + 2, AllowDrop = true, Margin = new Padding(PadPixels), SizeMode = PictureBoxSizeMode.CenterImage, Name = $"bpkm{index}", }; private sealed class LabelType : Label { public StorageSlotType Type; } private void AddLabels() { for (var i = 0; i < names.Length; i++) { var name = names[i]; bool result = Enum.TryParse(name, out var value); if (!result) continue; var label = new LabelType { Name = $"L_{name}", Text = name, Type = value, AutoSize = true, Visible = false, }; Labels[i] = label; FLP_Slots.Controls.Add(label); FLP_Slots.SetFlowBreak(label, true); } } private void SetLabelVisibility() { foreach (var l in Labels) { int index = SlotOffsets.FindIndex(z => z.Type == l.Type); if (index < 0) { l.Visible = false; continue; } int pos = FLP_Slots.Controls.IndexOf(slots[index]); if (pos > FLP_Slots.Controls.IndexOf(l)) pos--; FLP_Slots.Controls.SetChildIndex(l, pos); l.Visible = true; } } }