mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-04-21 06:28:56 -05:00
All subform ViewModels now use transactional cancel semantics matching WinForms: edits happen on a clone, Cancel discards them, Save copies the clone back to the origin via CopyChangesFrom. Gen 1-2: SAVEventReset1, SAVHallOfFame1, SAVMisc2, SAVRTC2 Gen 3: SAVRoamer3, SAVSecretBase3, SAVHallOfFame3, SAVRTC3, SAVMisc3, PokeBlock3CaseEditor, SimplePokedex Gen 4: PokeGear4, Trainer4BR, BattlePass4, Gear4, Apricorn4, HoneyTree4, Underground4, Geonet4, PoffinCase4, Pokedex4 Gen 5: Pokedex5, UnityTower5, DLC5 Gen 6: SAVPokepuff6 Gen 7: SAVHallOfFame7 Gen 8 BDSP: Poffin8b, SealStickers8b, Underground8b Cross-gen: EventFlags, EventFlags2, EventWork, Inventory, MailBox, Wondercard, BoxLayout, TrainerStat
104 lines
2.9 KiB
C#
104 lines
2.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using PKHeX.Core;
|
|
|
|
namespace PKHeX.Avalonia.ViewModels.Subforms;
|
|
|
|
/// <summary>
|
|
/// Model for a single trainer stat record.
|
|
/// </summary>
|
|
public partial class TrainerStatModel : ObservableObject
|
|
{
|
|
public int Index { get; }
|
|
public string Label { get; }
|
|
public string OffsetText { get; }
|
|
public int MaxValue { get; }
|
|
|
|
[ObservableProperty]
|
|
private int _value;
|
|
|
|
public TrainerStatModel(int index, string label, int value, int offset, int max)
|
|
{
|
|
Index = index;
|
|
Label = label;
|
|
_value = value;
|
|
OffsetText = $"0x{offset:X3}";
|
|
MaxValue = max;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// ViewModel for the Trainer Stat Records subform.
|
|
/// Displays and edits trainer statistics/records.
|
|
/// </summary>
|
|
public partial class TrainerStatViewModel : SaveEditorViewModelBase
|
|
{
|
|
private readonly SaveFile _origin;
|
|
private readonly SaveFile _clone;
|
|
private readonly ITrainerStatRecord _record;
|
|
|
|
[ObservableProperty]
|
|
private string _searchText = string.Empty;
|
|
|
|
public ObservableCollection<TrainerStatModel> AllRecords { get; } = [];
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<TrainerStatModel> _filteredRecords = [];
|
|
|
|
public string WindowTitle { get; }
|
|
|
|
public TrainerStatViewModel(SaveFile sav, ITrainerStatRecord record, Dictionary<int, string> recordNames) : base(sav)
|
|
{
|
|
_origin = sav;
|
|
_clone = sav.Clone();
|
|
_record = (ITrainerStatRecord)_clone;
|
|
WindowTitle = $"Trainer Stats ({sav.Version})";
|
|
|
|
for (int i = 0; i < record.RecordCount; i++)
|
|
{
|
|
if (!recordNames.TryGetValue(i, out var name))
|
|
name = $"{i:D3}";
|
|
|
|
var value = record.GetRecord(i);
|
|
var offset = record.GetRecordOffset(i);
|
|
var max = record.GetRecordMax(i);
|
|
AllRecords.Add(new TrainerStatModel(i, name, value, offset, max));
|
|
}
|
|
|
|
FilteredRecords = new ObservableCollection<TrainerStatModel>(AllRecords);
|
|
}
|
|
|
|
partial void OnSearchTextChanged(string value)
|
|
{
|
|
ApplyFilter();
|
|
}
|
|
|
|
private void ApplyFilter()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(SearchText))
|
|
{
|
|
FilteredRecords = new ObservableCollection<TrainerStatModel>(AllRecords);
|
|
return;
|
|
}
|
|
|
|
FilteredRecords = new ObservableCollection<TrainerStatModel>(
|
|
AllRecords.Where(r => r.Label.Contains(SearchText, System.StringComparison.OrdinalIgnoreCase)));
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void Save()
|
|
{
|
|
foreach (var rec in AllRecords)
|
|
{
|
|
var clamped = System.Math.Clamp(rec.Value, 0, rec.MaxValue);
|
|
_record.SetRecord(rec.Index, clamped);
|
|
}
|
|
|
|
_origin.CopyChangesFrom(_clone);
|
|
Modified = true;
|
|
}
|
|
}
|