PKHeX/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs
Kurt 88830e0d00
Update from .NET Framework 4.6 to .NET 7 (#3729)
Updates from net46->net7, dropping support for mono in favor of using the latest runtime (along with the performance/API improvements). Releases will be posted as 64bit only for now.

Refactors a good amount of internal API methods to be more performant and more customizable for future updates & fixes.

Adds functionality for Batch Editor commands to `>`, `<` and <=/>=

TID/SID properties renamed to TID16/SID16 for clarity; other properties exposed for Gen7 / display variants.

Main window has a new layout to account for DPI scaling (8 point grid)

Fixed: Tatsugiri and Paldean Tauros now output Showdown form names as Showdown expects
Changed: Gen9 species now interact based on the confirmed National Dex IDs (closes #3724)
Fixed: Pokedex set all no longer clears species with unavailable non-base forms (closes #3720)
Changed: Hyper Training suggestions now apply for level 50 in SV. (closes #3714)
Fixed: B2/W2 hatched egg met locations exclusive to specific versions are now explicitly checked (closes #3691)
Added: Properties for ribbon/mark count (closes #3659)
Fixed: Traded SV eggs are now checked correctly (closes #3692)
2023-01-21 20:02:33 -08:00

326 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
using static PKHeX.Core.MessageStrings;
namespace PKHeX.WinForms;
public sealed partial class SAV_EventFlags : Form
{
private readonly EventWorkspace<IEventFlag37, ushort> Editor;
private readonly Dictionary<int, NumericUpDown> WorkDict = new();
private readonly Dictionary<int, int> FlagDict = new();
private bool editing;
public SAV_EventFlags(IEventFlag37 sav)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
var editor = Editor = new EventWorkspace<IEventFlag37, ushort>(sav);
DragEnter += Main_DragEnter;
DragDrop += Main_DragDrop;
editing = true;
CB_Stats.Items.Clear();
for (int i = 0; i < editor.Values.Length; i++)
CB_Stats.Items.Add(i.ToString());
dgv.SuspendLayout();
TLP_Const.SuspendLayout();
TLP_Const.Scroll += WinFormsUtil.PanelScroll;
TLP_Const.Controls.Clear();
AddFlagList(editor.Labels, editor.Flags);
AddConstList(editor.Labels, editor.Values);
dgv.ResumeLayout();
TLP_Const.ResumeLayout();
Text = $"{Text} ({((IVersion)sav).Version})";
if (CB_Stats.Items.Count > 0)
{
CB_Stats.SelectedIndex = 0;
}
else
{
L_Stats.Visible = CB_Stats.Visible = MT_Stat.Visible = false;
tabControl1.TabPages.Remove(GB_Constants);
}
NUD_Flag.Maximum = editor.Flags.Length - 1;
NUD_Flag.Value = 0;
c_CustomFlag.Checked = editor.Flags[0];
editing = false;
}
private void B_Cancel_Click(object sender, EventArgs e)
{
Close();
}
private void B_Save_Click(object sender, EventArgs e)
{
Editor.Save();
Close();
}
private void AddFlagList(EventLabelCollection list, bool[] values)
{
var labels = list.Flag;
if (labels.Count == 0)
{
dgv.Visible = false;
var research = new Label { Text = MsgResearchRequired, Name = "TLP_Flags_Research", ForeColor = Color.Red, AutoSize = true, Location = new Point(20, 20) };
GB_Flags.Controls.Add(research);
return;
}
var cFlag = new DataGridViewCheckBoxColumn
{
DisplayIndex = 0,
Width = 20,
SortMode = DataGridViewColumnSortMode.NotSortable,
};
var cLabel = new DataGridViewTextBoxColumn
{
DisplayIndex = 1,
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.NotSortable,
};
cFlag.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
cLabel.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
dgv.Columns.Add(cFlag);
dgv.Columns.Add(cLabel);
var hideBelow = Main.Settings.Advanced.HideEventTypeBelow;
labels = labels.Where(z => z.Type >= hideBelow).OrderByDescending(z => z.Type).ToList();
dgv.Rows.Add(labels.Count);
for (int i = 0; i < labels.Count; i++)
FlagDict[labels[i].Index] = i;
for (int i = 0; i < labels.Count; i++)
{
var (name, index, _) = labels[i];
var cells = dgv.Rows[i].Cells;
cells[0].Value = values[index];
cells[1].Value = name;
}
dgv.CellValueChanged += (s, e) =>
{
if (e.ColumnIndex != 0 || e.RowIndex == -1)
return;
bool chk = (bool)dgv.Rows[e.RowIndex].Cells[0].Value;
var index = labels[e.RowIndex].Index;
values[index] = chk;
if (NUD_Flag.Value == index)
c_CustomFlag.Checked = chk;
};
dgv.CellMouseUp += (s, e) =>
{
if (e.RowIndex == -1)
return;
if (e.ColumnIndex == 0)
{
dgv.EndEdit();
return;
}
if (e.ColumnIndex != 1)
return;
bool chk = (bool)dgv.Rows[e.RowIndex].Cells[0].Value;
dgv.Rows[e.RowIndex].Cells[0].Value = !chk;
var index = labels[e.RowIndex].Index;
values[index] = !chk;
if (NUD_Flag.Value == index)
c_CustomFlag.Checked = !chk;
};
}
private void AddConstList(EventLabelCollection list, ushort[] values)
{
var labels = list.Work;
if (labels.Count == 0)
{
TLP_Const.Controls.Add(new Label { Text = MsgResearchRequired, Name = "TLP_Const_Research", ForeColor = Color.Red, AutoSize = true }, 0, 0);
return;
}
var hide = Main.Settings.Advanced.HideEventTypeBelow;
labels = labels.OrderByDescending(z => z.Type).ToList();
for (var i = 0; i < labels.Count; i++)
{
var entry = labels[i];
if (entry.Type < hide)
break;
var lbl = new Label { Text = entry.Name, Margin = Padding.Empty, AutoSize = true };
var mtb = new NumericUpDown
{
Maximum = ushort.MaxValue,
Minimum = ushort.MinValue,
Margin = Padding.Empty,
Width = 50,
};
var map = entry.PredefinedValues.Select(z => new ComboItem(z.Name, z.Value)).ToList();
var cb = new ComboBox
{
Margin = Padding.Empty,
Width = 150,
DropDownStyle = ComboBoxStyle.DropDownList,
BindingContext = BindingContext,
};
var font = cb.Font;
cb.DropDownWidth = entry.PredefinedValues.Max(z => TextRenderer.MeasureText(z.Name, font).Width);
cb.InitializeBinding();
cb.DataSource = map;
lbl.Click += (sender, e) => mtb.Value = 0;
bool updating = false;
mtb.ValueChanged += ChangeConstValue;
void ChangeConstValue(object? sender, EventArgs e)
{
if (updating)
return;
updating = true;
var value = (ushort) mtb.Value;
var (_, valueID) = map.Find(z => z.Value == value) ?? map[0];
if (WinFormsUtil.GetIndex(cb) != valueID)
cb.SelectedValue = valueID;
Editor.Values[entry.Index] = value;
if (CB_Stats.SelectedIndex == entry.Index)
MT_Stat.Text = ((int)mtb.Value).ToString();
updating = false;
}
cb.SelectedValueChanged += (o, args) =>
{
if (editing || updating)
return;
var value = WinFormsUtil.GetIndex(cb);
mtb.Value = value == NamedEventConst.CustomMagicValue ? 0 : value;
};
mtb.Value = values[entry.Index];
if (mtb.Value == 0)
ChangeConstValue(this, EventArgs.Empty);
TLP_Const.Controls.Add(lbl, 0, i);
TLP_Const.Controls.Add(cb, 1, i);
TLP_Const.Controls.Add(mtb, 2, i);
WorkDict.Add(entry.Index, mtb);
}
}
private void ChangeCustomBool(object sender, EventArgs e)
{
if (editing)
return;
editing = true;
var index = (int) NUD_Flag.Value;
Editor.Flags[index] = c_CustomFlag.Checked;
if (FlagDict.TryGetValue(index, out var rowIndex))
dgv.Rows[rowIndex].Cells[0].Value = c_CustomFlag.Checked;
editing = false;
}
private void ChangeCustomFlag(object sender, EventArgs e)
{
int flag = (int)NUD_Flag.Value;
c_CustomFlag.Checked = Editor.Flags[flag];
}
private void ChangeCustomFlag(object sender, KeyEventArgs e) => ChangeCustomFlag(sender, (EventArgs)e);
private void ChangeConstantIndex(object sender, EventArgs e)
{
var constants = Editor.Values;
var index = CB_Stats.SelectedIndex;
MT_Stat.Text = constants[index].ToString();
}
private void ChangeCustomConst(object sender, EventArgs e)
{
if (editing)
return;
editing = true;
var index = CB_Stats.SelectedIndex;
var parse = ushort.TryParse(MT_Stat.Text, out var value) ? value : (ushort)0;
Editor.Values[index] = parse;
if (WorkDict.TryGetValue(index, out var mtb))
mtb.Value = parse;
editing = false;
}
private void ChangeSAV(object sender, EventArgs e)
{
if (TB_NewSAV.Text.Length > 0 && TB_OldSAV.Text.Length > 0)
DiffSaves();
}
private void OpenSAV(object sender, EventArgs e)
{
using var ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
LoadSAV(sender, ofd.FileName);
}
private void LoadSAV(object sender, string path)
{
var dest = sender == B_LoadOld ? TB_OldSAV : TB_NewSAV;
dest.Text = path;
}
private void DiffSaves()
{
var diff = new EventBlockDiff<IEventFlag37, ushort>(TB_OldSAV.Text, TB_NewSAV.Text);
if (diff.Message != EventWorkDiffCompatibility.Valid)
{
WinFormsUtil.Alert(diff.Message.GetMessage());
return;
}
TB_IsSet.Text = string.Join(", ", diff.SetFlags.Select(z => $"{z:0000}"));
TB_UnSet.Text = string.Join(", ", diff.ClearedFlags.Select(z => $"{z:0000}"));
if (diff.WorkDiff.Count == 0)
{
WinFormsUtil.Alert("No Event Constant diff found.");
return;
}
var promptCopy = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Copy Event Constant diff to clipboard?");
if (promptCopy == DialogResult.Yes)
WinFormsUtil.SetClipboardText(string.Join(Environment.NewLine, diff.WorkDiff));
}
private static void Main_DragEnter(object? sender, DragEventArgs? e)
{
if (e?.Data is null)
return;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
private void Main_DragDrop(object? sender, DragEventArgs? e)
{
if (e?.Data?.GetData(DataFormats.FileDrop) is not string[] { Length: not 0 } files)
return;
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, Name, "Yes: Old Save" + Environment.NewLine + "No: New Save");
var button = dr == DialogResult.Yes ? B_LoadOld : B_LoadNew;
LoadSAV(button, files[0]);
}
}