PKHeX/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.cs
Kurt cce4707604
Enable nullable for winforms csproj (#3037)
Handle all warnings
obviously the usage of null! could potentially be avoided if the object init wasn't such garbage, but here we are with years of old junk and lack of abstraction in the GUI project
2020-10-18 11:02:39 -07:00

261 lines
9.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using PKHeX.Core;
using PKHeX.Drawing;
using static PKHeX.Core.MessageStrings;
namespace PKHeX.WinForms.Controls
{
public partial class BoxEditor : UserControl, ISlotViewer<PictureBox>
{
public IList<PictureBox> SlotPictureBoxes { get; private set; } = Array.Empty<PictureBox>();
public SaveFile SAV => M?.SE.SAV ?? throw new ArgumentNullException(nameof(SAV));
public int BoxSlotCount { get; private set; }
public SlotChangeManager? M { get; set; }
public bool FlagIllegal { get; set; }
public bool CanSetCurrentBox { get; set; }
public BoxEdit Editor { get; set; } = null!;
public BoxEditor()
{
InitializeComponent();
}
internal bool InitializeGrid()
{
var count = SAV.BoxSlotCount;
var width = count / 5;
var height = count / width;
if (!BoxPokeGrid.InitializeGrid(width, height, SpriteUtil.Spriter))
return false;
RecenterControls();
InitializeSlots();
return true;
}
public void RecenterControls()
{
if (Width < BoxPokeGrid.Width)
Width = BoxPokeGrid.Width;
BoxPokeGrid.HorizontallyCenter(this);
int p1 = CB_BoxSelect.Location.X;
CB_BoxSelect.HorizontallyCenter(this);
int p2 = CB_BoxSelect.Location.X;
if (p1 == p2)
return;
B_BoxLeft.Location = new Point(B_BoxLeft.Location.X + p2 - p1, B_BoxLeft.Location.Y);
B_BoxRight.Location = new Point(B_BoxRight.Location.X + p2 - p1, B_BoxRight.Location.Y);
}
private void InitializeSlots()
{
SlotPictureBoxes = BoxPokeGrid.Entries;
BoxSlotCount = SlotPictureBoxes.Count;
foreach (var pb in SlotPictureBoxes)
{
pb.MouseEnter += (o, args) => BoxSlot_MouseEnter(pb, args);
pb.MouseLeave += (o, args) => BoxSlot_MouseLeave(pb, args);
pb.MouseClick += BoxSlot_MouseClick;
pb.MouseMove += BoxSlot_MouseMove;
pb.MouseDown += BoxSlot_MouseDown;
pb.MouseUp += BoxSlot_MouseUp;
pb.DragEnter += BoxSlot_DragEnter;
pb.DragDrop += BoxSlot_DragDrop;
pb.QueryContinueDrag += BoxSlot_QueryContinueDrag;
pb.GiveFeedback += (sender, e) => e.UseDefaultCursors = false;
pb.AllowDrop = true;
}
}
public void NotifySlotOld(ISlotInfo previous)
{
if (!(previous is SlotInfoBox b) || b.Box != CurrentBox)
return;
var pb = SlotPictureBoxes[previous.Slot];
pb.BackgroundImage = null;
}
public void NotifySlotChanged(ISlotInfo slot, SlotTouchType type, PKM pkm)
{
int index = GetViewIndex(slot);
if (index < 0)
return;
var pb = SlotPictureBoxes[index];
SlotUtil.UpdateSlot(pb, slot, pkm, SAV, FlagIllegal, type);
}
public int GetViewIndex(ISlotInfo slot)
{
if (!(slot is SlotInfoBox b) || b.Box != CurrentBox)
return -1;
return slot.Slot;
}
public ISlotInfo GetSlotData(PictureBox view)
{
int slot = GetSlot(view);
return new SlotInfoBox(ViewIndex, slot);
}
private int GetSlot(PictureBox sender) => SlotPictureBoxes.IndexOf(sender);
public int ViewIndex => CurrentBox;
public bool ControlsVisible
{
get => CB_BoxSelect.Enabled;
set => CB_BoxSelect.Enabled = CB_BoxSelect.Visible = B_BoxLeft.Visible = B_BoxRight.Visible = value;
}
public bool ControlsEnabled
{
get => CB_BoxSelect.Enabled;
set => CB_BoxSelect.Enabled = B_BoxLeft.Enabled = B_BoxRight.Enabled = value;
}
public int CurrentBox
{
get => CB_BoxSelect.SelectedIndex;
set
{
CB_BoxSelect.SelectedIndex = value;
if (value < 0)
return;
Editor.LoadBox(value);
}
}
public string CurrentBoxName => CB_BoxSelect.Text;
public void Setup(SlotChangeManager m)
{
M = m;
M.Boxes.Add(this);
FlagIllegal = M.SE.FlagIllegal;
}
public void ResetBoxNames(int box = -1)
{
if (!SAV.HasBox)
return;
CB_BoxSelect.Items.Clear();
CB_BoxSelect.Items.AddRange(BoxUtil.GetBoxNames(SAV));
if (box < 0 && (uint)SAV.CurrentBox < CB_BoxSelect.Items.Count)
CurrentBox = SAV.CurrentBox; // restore selected box
else
CurrentBox = box;
}
public void ResetSlots()
{
Editor.Reload();
int box = CurrentBox;
BoxPokeGrid.SetBackground(SAV.WallpaperImage(box));
M?.Hover.Stop();
int index = box * SAV.BoxSlotCount;
for (int i = 0; i < BoxSlotCount; i++)
{
var pb = SlotPictureBoxes[i];
if (i >= SAV.BoxSlotCount || index + i >= SAV.SlotCount)
{
pb.Visible = false;
continue;
}
pb.Visible = true;
SlotUtil.UpdateSlot(pb, (SlotInfoBox) GetSlotData(pb), Editor[i], SAV, FlagIllegal);
}
if (M?.Env.Slots.Publisher.Previous is SlotInfoBox b && b.Box == CurrentBox)
SlotPictureBoxes[b.Slot].BackgroundImage = SlotUtil.GetTouchTypeBackground(M.Env.Slots.Publisher.PreviousType);
}
public bool SaveBoxBinary()
{
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel,
MsgSaveBoxExportYes + Environment.NewLine +
string.Format(MsgSaveBoxExportNo, CurrentBoxName, CurrentBox + 1) + Environment.NewLine +
MsgSaveBoxExportCancel);
if (dr == DialogResult.Yes)
{
using var sfd = new SaveFileDialog { Filter = "Box Data|*.bin", FileName = "pcdata.bin" };
if (sfd.ShowDialog() != DialogResult.OK)
return false;
File.WriteAllBytes(sfd.FileName, SAV.GetPCBinary());
return true;
}
if (dr == DialogResult.No)
{
using var sfd = new SaveFileDialog { Filter = "Box Data|*.bin", FileName = $"boxdata {CurrentBoxName}.bin" };
if (sfd.ShowDialog() != DialogResult.OK)
return false;
File.WriteAllBytes(sfd.FileName, SAV.GetBoxBinary(CurrentBox));
return true;
}
return false;
}
public void ClearEvents()
{
#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate.
B_BoxRight.Click -= ClickBoxRight;
B_BoxLeft.Click -= ClickBoxLeft;
CB_BoxSelect.SelectedIndexChanged -= GetBox;
#pragma warning restore CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate.
}
public void Reset()
{
ResetBoxNames();
ResetSlots();
}
private void GetBox(object sender, EventArgs e)
{
CurrentBox = CB_BoxSelect.SelectedIndex;
if (SAV.CurrentBox != CurrentBox && CanSetCurrentBox)
SAV.CurrentBox = CurrentBox;
ResetSlots();
M?.Hover.Stop();
}
private void ClickBoxLeft(object sender, EventArgs e) => CurrentBox = Editor.MoveLeft(ModifierKeys == Keys.Control);
private void ClickBoxRight(object sender, EventArgs e) => CurrentBox = Editor.MoveRight(ModifierKeys == Keys.Control);
// Drag & Drop Handling
private void BoxSlot_MouseEnter(object sender, EventArgs e) => M?.MouseEnter(sender, e);
private void BoxSlot_MouseLeave(object sender, EventArgs e) => M?.MouseLeave(sender, e);
private void BoxSlot_MouseClick(object sender, MouseEventArgs e) => M?.MouseClick(sender, e);
private void BoxSlot_MouseUp(object sender, MouseEventArgs e) => M?.MouseUp(sender, e);
private void BoxSlot_MouseDown(object sender, MouseEventArgs e) => M?.MouseDown(sender, e);
private void BoxSlot_MouseMove(object sender, MouseEventArgs e) => M?.MouseMove(sender, e);
private void BoxSlot_DragEnter(object sender, DragEventArgs e) => M?.DragEnter(sender, e);
private void BoxSlot_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) => M?.QueryContinueDrag(sender, e);
private void BoxSlot_DragDrop(object sender, DragEventArgs e) => M?.DragDrop(sender, e);
public bool InitializeFromSAV(SaveFile sav)
{
Editor = new BoxEdit(sav);
bool result = InitializeGrid();
int box = sav.CurrentBox;
if ((uint)box >= sav.BoxCount)
box = 0;
Editor.LoadBox(box);
ResetBoxNames(); // Display the Box Names
return result;
}
}
}