Ava UI: Fix crash when clicking on a cheat's name (#5860)
* Fix crash * Remove nullable * Hide BuildId for child nodes * Fix warning * Fix charset
This commit is contained in:
parent
feec5ef7b3
commit
19a949d0bf
5 changed files with 70 additions and 116 deletions
|
@ -1,40 +0,0 @@
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models
|
|
||||||
{
|
|
||||||
public class CheatModel : BaseModel
|
|
||||||
{
|
|
||||||
private bool _isEnabled;
|
|
||||||
|
|
||||||
public event EventHandler<bool> EnableToggled;
|
|
||||||
|
|
||||||
public CheatModel(string name, string buildId, bool isEnabled)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
BuildId = buildId;
|
|
||||||
IsEnabled = isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEnabled
|
|
||||||
{
|
|
||||||
get => _isEnabled;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isEnabled = value;
|
|
||||||
|
|
||||||
EnableToggled?.Invoke(this, _isEnabled);
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string BuildId { get; }
|
|
||||||
|
|
||||||
public string BuildIdKey => $"{BuildId}-{Name}";
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
public string CleanName => Name[1..^7];
|
|
||||||
}
|
|
||||||
}
|
|
57
src/Ryujinx.Ava/UI/Models/CheatNode.cs
Normal file
57
src/Ryujinx.Ava/UI/Models/CheatNode.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Models
|
||||||
|
{
|
||||||
|
public class CheatNode : BaseModel
|
||||||
|
{
|
||||||
|
private bool _isEnabled = false;
|
||||||
|
public ObservableCollection<CheatNode> SubNodes { get; } = new();
|
||||||
|
public string CleanName => Name[1..^7];
|
||||||
|
public string BuildIdKey => $"{BuildId}-{Name}";
|
||||||
|
public bool IsRootNode { get; }
|
||||||
|
public string Name { get; }
|
||||||
|
public string BuildId { get; }
|
||||||
|
public string Path { get; }
|
||||||
|
public bool IsEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (SubNodes.Count > 0)
|
||||||
|
{
|
||||||
|
return SubNodes.ToList().TrueForAll(x => x.IsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _isEnabled;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
foreach (var cheat in SubNodes)
|
||||||
|
{
|
||||||
|
cheat.IsEnabled = value;
|
||||||
|
cheat.OnPropertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
_isEnabled = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheatNode(string name, string buildId, string path, bool isRootNode, bool isEnabled = false)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
BuildId = buildId;
|
||||||
|
Path = path;
|
||||||
|
IsEnabled = isEnabled;
|
||||||
|
IsRootNode = isRootNode;
|
||||||
|
|
||||||
|
SubNodes.CollectionChanged += CheatsList_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
OnPropertyChanged(nameof(IsEnabled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models
|
|
||||||
{
|
|
||||||
public class CheatsList : ObservableCollection<CheatModel>
|
|
||||||
{
|
|
||||||
public CheatsList(string buildId, string path)
|
|
||||||
{
|
|
||||||
BuildId = buildId;
|
|
||||||
Path = path;
|
|
||||||
|
|
||||||
CollectionChanged += CheatsList_CollectionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string BuildId { get; }
|
|
||||||
public string Path { get; }
|
|
||||||
|
|
||||||
public bool IsEnabled
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.ToList().TrueForAll(x => x.IsEnabled);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
foreach (var cheat in this)
|
|
||||||
{
|
|
||||||
cheat.IsEnabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
|
||||||
{
|
|
||||||
(e.NewItems[0] as CheatModel).EnableToggled += Item_EnableToggled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Item_EnableToggled(object sender, bool e)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -86,28 +86,16 @@
|
||||||
</Style>
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
</TreeView.Styles>
|
</TreeView.Styles>
|
||||||
<TreeView.DataTemplates>
|
<TreeView.ItemTemplate>
|
||||||
<TreeDataTemplate DataType="model:CheatsList" ItemsSource="{Binding}">
|
<TreeDataTemplate ItemsSource="{Binding SubNodes}">
|
||||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||||
<CheckBox MinWidth="20" IsChecked="{Binding IsEnabled}" />
|
<CheckBox MinWidth="20" IsChecked="{Binding IsEnabled}" />
|
||||||
<TextBlock Width="150" Text="{Binding BuildId}" />
|
<TextBlock Width="150" Text="{Binding CleanName}" IsVisible="{Binding !IsRootNode}" />
|
||||||
<TextBlock Text="{Binding Path}" />
|
<TextBlock Width="150" Text="{Binding BuildId}" IsVisible="{Binding IsRootNode}" />
|
||||||
|
<TextBlock Text="{Binding Path}" IsVisible="{Binding IsRootNode}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
<DataTemplate x:DataType="model:CheatModel">
|
</TreeView.ItemTemplate>
|
||||||
<StackPanel
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Orientation="Horizontal">
|
|
||||||
<CheckBox
|
|
||||||
MinWidth="20"
|
|
||||||
Margin="5,0"
|
|
||||||
Padding="0"
|
|
||||||
IsChecked="{Binding IsEnabled}" />
|
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding CleanName}" />
|
|
||||||
</StackPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
</TreeView.DataTemplates>
|
|
||||||
</TreeView>
|
</TreeView>
|
||||||
</Border>
|
</Border>
|
||||||
<DockPanel
|
<DockPanel
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||||
private readonly string _enabledCheatsPath;
|
private readonly string _enabledCheatsPath;
|
||||||
public bool NoCheatsFound { get; }
|
public bool NoCheatsFound { get; }
|
||||||
|
|
||||||
public AvaloniaList<CheatsList> LoadedCheats { get; }
|
public AvaloniaList<CheatNode> LoadedCheats { get; }
|
||||||
|
|
||||||
public string Heading { get; }
|
public string Heading { get; }
|
||||||
public string BuildId { get; }
|
public string BuildId { get; }
|
||||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||||
|
|
||||||
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
||||||
{
|
{
|
||||||
LoadedCheats = new AvaloniaList<CheatsList>();
|
LoadedCheats = new AvaloniaList<CheatNode>();
|
||||||
|
|
||||||
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
|
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
|
||||||
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
|
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
|
||||||
|
@ -62,7 +62,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||||
string currentCheatFile = string.Empty;
|
string currentCheatFile = string.Empty;
|
||||||
string buildId = string.Empty;
|
string buildId = string.Empty;
|
||||||
|
|
||||||
CheatsList currentGroup = null;
|
CheatNode currentGroup = null;
|
||||||
|
|
||||||
foreach (var cheat in mods.Cheats)
|
foreach (var cheat in mods.Cheats)
|
||||||
{
|
{
|
||||||
|
@ -72,13 +72,13 @@ namespace Ryujinx.Ava.UI.Windows
|
||||||
string parentPath = currentCheatFile.Replace(titleModsPath, "");
|
string parentPath = currentCheatFile.Replace(titleModsPath, "");
|
||||||
|
|
||||||
buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
|
buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
|
||||||
currentGroup = new CheatsList(buildId, parentPath);
|
currentGroup = new CheatNode("", buildId, parentPath, true);
|
||||||
|
|
||||||
LoadedCheats.Add(currentGroup);
|
LoadedCheats.Add(currentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
var model = new CheatModel(cheat.Name, buildId, enabled.Contains($"{buildId}-{cheat.Name}"));
|
var model = new CheatNode(cheat.Name, buildId, "", false, enabled.Contains($"{buildId}-{cheat.Name}"));
|
||||||
currentGroup?.Add(model);
|
currentGroup?.SubNodes.Add(model);
|
||||||
|
|
||||||
cheatAdded++;
|
cheatAdded++;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||||
|
|
||||||
foreach (var cheats in LoadedCheats)
|
foreach (var cheats in LoadedCheats)
|
||||||
{
|
{
|
||||||
foreach (var cheat in cheats)
|
foreach (var cheat in cheats.SubNodes)
|
||||||
{
|
{
|
||||||
if (cheat.IsEnabled)
|
if (cheat.IsEnabled)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue