PKHeX/PKHeX.WinForms/Controls/Slots/SlotList.cs
Kurt 82309cf99d Use Memory<byte> for Gen4 saves
Instead of allocating a buffer for Storage/General, just point within the raw Data, as a Memory<byte> reference. Most of the uses were already using it as span.
2023-03-26 15:16:12 -07:00

166 lines
4.7 KiB
C#

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<PictureBox>
{
private static readonly string[] names = Enum.GetNames(typeof(StorageSlotType));
private readonly Label[] Labels = new Label[names.Length];
private readonly List<PictureBox> slots = new();
private List<SlotInfoMisc> SlotOffsets = new();
public int SlotCount { get; private set; }
public SaveFile SAV { get; set; } = null!;
public bool FlagIllegal { get; set; }
public SlotList()
{
InitializeComponent();
AddLabels();
}
/// <summary>
/// Initializes the extra slot viewers with a list of offsets and sets up event handling.
/// </summary>
/// <param name="list">Extra slots to show</param>
/// <param name="enableDragDropContext">Events to set up</param>
/// <remarks>Uses an object pool for viewers (only generates as needed)</remarks>
public void Initialize(List<SlotInfoMisc> list, Action<Control> enableDragDropContext)
{
SlotOffsets = list;
LoadSlots(list.Count, enableDragDropContext);
}
/// <summary>
/// Hides all slots from the <see cref="SlotList"/>.
/// </summary>
public void HideAllSlots() => LoadSlots(0, _ => { });
public void NotifySlotOld(ISlotInfo previous)
{
if (previous is not SlotInfoMisc m)
return;
var index = SlotOffsets.FindIndex(m.Equals);
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<PictureBox> SlotPictureBoxes => slots;
public int GetSlot(PictureBox sender)
{
var view = WinFormsUtil.GetUnderlyingControl<PictureBox>(sender);
if (view == null)
return -1;
return slots.IndexOf(view);
}
public int ViewIndex { get; set; } = -1;
private void LoadSlots(int count, Action<Control> enableDragDropContext)
{
var controls = FLP_Slots.Controls;
controls.Clear();
if (count == 0)
{
SlotCount = 0;
return;
}
AddSlots(count, enableDragDropContext);
AddControls(count);
SlotCount = count;
}
private void AddControls(int countTotal)
{
var type = (StorageSlotType)(-1);
int added = -1;
for (int i = 0; i < countTotal; i++)
{
var info = SlotOffsets[i];
if (type != info.Type)
{
added++;
type = info.Type;
var label = Labels[(int)type];
FLP_Slots.Controls.Add(label, 0, added++);
}
var slot = slots[i];
FLP_Slots.Controls.Add(slot, 0, added);
}
}
private void AddSlots(int after, Action<Control> enableDragDropContext)
{
int before = SlotCount;
int diff = after - before;
if (diff <= 0)
return;
for (int i = 0; i < diff; i++)
{
var name = $"bpkm{before + i}";
var slot = GetPictureBox(SpriteUtil.Spriter, name);
enableDragDropContext(slot);
slots.Add(slot);
}
}
private const int PadPixels = 2;
private static SelectablePictureBox GetPictureBox(SpriteBuilder s, string name) => new()
{
BorderStyle = BorderStyle.FixedSingle,
Width = s.Width + 2,
Height = s.Height + 2,
AllowDrop = true,
Margin = new Padding(PadPixels),
Padding = Padding.Empty,
SizeMode = PictureBoxSizeMode.CenterImage,
Name = name,
AccessibleName = name,
AccessibleRole = AccessibleRole.Graphic,
};
private void AddLabels()
{
for (var i = 0; i < names.Length; i++)
{
var name = names[i];
Labels[i] = new Label
{
Name = $"L_{name}",
Text = name,
AutoSize = true,
Margin = Padding.Empty,
Padding = Padding.Empty,
};
}
}
}