PKHeX/PKHeX.WinForms/Subforms/PKM Editors/Text.cs
2018-05-12 08:41:29 -07:00

220 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
namespace PKHeX.WinForms
{
public partial class TrashEditor : Form
{
private readonly SaveFile SAV;
public TrashEditor(TextBoxBase TB_NN, byte[] raw, SaveFile sav)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
SAV = sav;
bigendian = new[] { GameVersion.COLO, GameVersion.XD, GameVersion.BATREV, }.Contains(SAV.Version);
FinalString = TB_NN.Text;
Raw = FinalBytes = raw;
editing = true;
if (raw != null)
AddTrashEditing(raw.Length);
AddCharEditing();
TB_Text.MaxLength = TB_NN.MaxLength;
TB_Text.Text = TB_NN.Text;
TB_Text.Font = pkxFont;
if (FLP_Characters.Controls.Count == 0)
{
FLP_Characters.Visible = false;
FLP_Hex.Height *= 2;
}
else if (FLP_Hex.Controls.Count == 0)
{
FLP_Characters.Location = FLP_Hex.Location;
FLP_Characters.Height *= 2;
}
editing = false;
CenterToParent();
}
private readonly List<NumericUpDown> Bytes = new List<NumericUpDown>();
private readonly Font pkxFont = FontUtil.GetPKXFont(12F);
public string FinalString;
public byte[] FinalBytes { get; private set; }
private readonly byte[] Raw;
private bool editing;
private readonly bool bigendian;
private void B_Cancel_Click(object sender, EventArgs e) => Close();
private void B_Save_Click(object sender, EventArgs e)
{
FinalString = TB_Text.Text;
if (FinalBytes != null)
FinalBytes = Raw;
Close();
}
private void AddCharEditing()
{
ushort[] chars = GetChars(SAV.Generation);
if (chars.Length == 0)
return;
FLP_Characters.Visible = true;
foreach (ushort c in chars)
{
var l = GetLabel((char)c+"");
l.Font = pkxFont;
l.AutoSize = false;
l.Size = new Size(20, 20);
l.Click += (s, e) => { if (TB_Text.Text.Length < TB_Text.MaxLength) TB_Text.AppendText(l.Text); };
FLP_Characters.Controls.Add(l);
}
}
private void AddTrashEditing(int count)
{
FLP_Hex.Visible = true;
GB_Trash.Visible = true;
NUD_Generation.Value = SAV.Generation;
Font courier = new Font("Courier New", 8);
for (int i = 0; i < count; i++)
{
var l = GetLabel($"${i:X2}");
l.Font = courier;
var n = GetNUD(hex: true, min: 0, max: 255);
n.Click += (s, e) =>
{
switch (ModifierKeys)
{
case Keys.Shift: n.Value = n.Maximum; break;
case Keys.Alt: n.Value = n.Minimum; break;
}
};
n.Value = Raw[i];
n.ValueChanged += UpdateNUD;
FLP_Hex.Controls.Add(l);
FLP_Hex.Controls.Add(n);
Bytes.Add(n);
}
TB_Text.TextChanged += UpdateString;
CB_Species.DisplayMember = "Text";
CB_Species.ValueMember = "Value";
CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource, null);
CB_Language.DisplayMember = "Text";
CB_Language.ValueMember = "Value";
var languages = Util.GetUnsortedCBList("languages");
if (SAV.Generation < 7)
languages = languages.Where(l => l.Value <= 8).ToList(); // Korean
CB_Language.DataSource = languages;
}
private void UpdateNUD(object sender, EventArgs e)
{
if (editing)
return;
editing = true;
// build bytes
var nud = sender as NumericUpDown;
int index = Bytes.IndexOf(nud);
Raw[index] = (byte)nud.Value;
string str = GetString();
TB_Text.Text = str;
editing = false;
}
private void UpdateString(object sender, EventArgs e)
{
if (editing)
return;
editing = true;
// build bytes
byte[] data = SetString(TB_Text.Text);
Array.Copy(data, Raw, Math.Min(data.Length, Raw.Length));
for (int i = 0; i < Raw.Length; i++)
Bytes[i].Value = Raw[i];
editing = false;
}
private void B_ApplyTrash_Click(object sender, EventArgs e)
{
string species = PKX.GetSpeciesNameGeneration(WinFormsUtil.GetIndex(CB_Species),
WinFormsUtil.GetIndex(CB_Language), (int) NUD_Generation.Value);
if (species == "") // no result
species = CB_Species.Text;
byte[] current = SetString(TB_Text.Text);
byte[] data = SetString(species);
if (data.Length <= current.Length)
{
WinFormsUtil.Alert("Trash byte layer is hidden by current text.",
$"Current Bytes: {current.Length}" + Environment.NewLine + $"Layer Bytes: {data.Length}");
return;
}
if (data.Length > Bytes.Count)
{
WinFormsUtil.Alert("Trash byte layer is too long to apply.");
return;
}
for (int i = current.Length; i < data.Length; i++)
Bytes[i].Value = data[i];
}
private void B_ClearTrash_Click(object sender, EventArgs e)
{
byte[] current = SetString(TB_Text.Text);
for (int i = current.Length; i < Bytes.Count; i++)
Bytes[i].Value = 0;
}
private byte[] SetString(string text)
{
return SAV is SAV2 s && s.Korean
? StringConverter.SetString2KOR(text, Raw.Length)
: StringConverter.SetString(text, SAV.Generation, SAV.Japanese, bigendian, Raw.Length, SAV.Language);
}
private string GetString()
{
return SAV is SAV2 s && s.Korean
? StringConverter.GetString2KOR(Raw, 0, Raw.Length)
: StringConverter.GetString(Raw, SAV.Generation, SAV.Japanese, bigendian, Raw.Length);
}
// Helpers
private static Label GetLabel(string str) => new Label {Text = str, AutoSize = true};
private static NumericUpDown GetNUD(int min, int max, bool hex) => new NumericUpDown
{
Maximum = max,
Minimum = min,
Hexadecimal = hex,
Width = 36,
Padding = new Padding(0),
Margin = new Padding(0),
};
private static ushort[] GetChars(int generation)
{
switch (generation)
{
case 6:
case 7:
return chars67;
default: return new ushort[0];
}
}
private static readonly ushort[] chars67 =
{
0xE081, 0xE082, 0xE083, 0xE084, 0xE085, 0xE086, 0xE087, 0xE08D,
0xE08E, 0xE08F, 0xE090, 0xE091, 0xE092, 0xE093, 0xE094, 0xE095,
0xE096, 0xE097, 0xE098, 0xE099, 0xE09A, 0xE09B, 0xE09C, 0xE09D,
0xE09E, 0xE09F, 0xE0A0, 0xE0A1, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5,
};
}
}