From 38d61f7b3d9aad89313ac33602f4a2503eb32284 Mon Sep 17 00:00:00 2001 From: Bartosz Korczynski Date: Tue, 30 Apr 2024 19:04:07 +0100 Subject: [PATCH] [Solutions] Async solution name generation --- .../DatabaseTableSolutionItemNameProvider.cs | 32 +++++++++++++++++-- .../DatabaseEntitiesGroupViewModel.cs | 15 +++++++-- .../MultiRowDbTableEditorViewModel.cs | 2 +- .../ViewModels/RowPickerViewModel.cs | 1 + .../ViewModels/ViewModelBase.cs | 18 +++++++++-- .../Manager/SolutionItemNameRegistry.cs | 29 ++++++++++++++++- .../Solution/ISolutionItemNameRegistry.cs | 4 ++- .../Solution/ISolutionNameProvider.cs | 14 +++++++- 8 files changed, 104 insertions(+), 11 deletions(-) diff --git a/WDE.DatabaseEditors/Solution/DatabaseTableSolutionItemNameProvider.cs b/WDE.DatabaseEditors/Solution/DatabaseTableSolutionItemNameProvider.cs index 8384f9624..f86c9f8d3 100644 --- a/WDE.DatabaseEditors/Solution/DatabaseTableSolutionItemNameProvider.cs +++ b/WDE.DatabaseEditors/Solution/DatabaseTableSolutionItemNameProvider.cs @@ -1,4 +1,5 @@ -using WDE.Common.Database; +using System.Threading.Tasks; +using WDE.Common.Database; using WDE.Common.Parameters; using WDE.Common.Solution; using WDE.DatabaseEditors.Data.Interfaces; @@ -7,7 +8,8 @@ namespace WDE.DatabaseEditors.Solution { [AutoRegister] - public class DatabaseTableSolutionItemNameProvider : ISolutionNameProvider + public class DatabaseTableSolutionItemNameProvider : ISolutionNameProvider, + ISolutionNameProviderAsync { private readonly IParameterFactory parameterFactory; private readonly ITableDefinitionProvider tableDefinitionProvider; @@ -38,5 +40,31 @@ public string GetName(DatabaseTableSolutionItem item) return definition.MultiSolutionName; } + + public async Task GetNameAsync(DatabaseTableSolutionItem item) + { + var definition = tableDefinitionProvider.GetDefinition(item.TableName); + if (definition == null) + return $"Unknown item (" + item.TableName + ")"; + + var parameter = parameterFactory.Factory(definition.Picker); + + if (item.Entries.Count == 1) + { + string name; + if (parameter is IAsyncParameter asyncParameter) + { + name = await asyncParameter.ToStringAsync(item.Entries[0].Key[0], default); + } + else + { + name = parameter.ToString(item.Entries[0].Key[0]); + } + + return definition.SingleSolutionName.Replace("{name}", name).Replace("{key}", item.Entries[0].Key.ToString()); + } + + return definition.MultiSolutionName; + } } } \ No newline at end of file diff --git a/WDE.DatabaseEditors/ViewModels/MultiRow/DatabaseEntitiesGroupViewModel.cs b/WDE.DatabaseEditors/ViewModels/MultiRow/DatabaseEntitiesGroupViewModel.cs index c2e96e7cf..3b6823e99 100644 --- a/WDE.DatabaseEditors/ViewModels/MultiRow/DatabaseEntitiesGroupViewModel.cs +++ b/WDE.DatabaseEditors/ViewModels/MultiRow/DatabaseEntitiesGroupViewModel.cs @@ -2,8 +2,11 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using System.Threading.Tasks; using AvaloniaStyles.Controls.FastTableView; +using PropertyChanged.SourceGenerator; using WDE.Common.Services; +using WDE.Common.Utils; using WDE.DatabaseEditors.Models; namespace WDE.DatabaseEditors.ViewModels.MultiRow @@ -12,7 +15,7 @@ public partial class DatabaseEntitiesGroupViewModel : CustomObservableCollection { private bool isExpanded = true; public DatabaseKey Key { get; } - public string Name { get; } + [Notify] private string name; public bool IsExpanded { @@ -25,10 +28,16 @@ public bool IsExpanded } } - public DatabaseEntitiesGroupViewModel(DatabaseKey key, string name) + public DatabaseEntitiesGroupViewModel(DatabaseKey key, string name, Func> nameLazyGetter) { Key = key; - Name = name; + this.name = name; + async Task SetName() + { + Name = await nameLazyGetter(); + } + + SetName().ListenErrors(); } public override void OrderByIndices(List indices) diff --git a/WDE.DatabaseEditors/ViewModels/MultiRow/MultiRowDbTableEditorViewModel.cs b/WDE.DatabaseEditors/ViewModels/MultiRow/MultiRowDbTableEditorViewModel.cs index 9b7d83bf9..fde690f2f 100644 --- a/WDE.DatabaseEditors/ViewModels/MultiRow/MultiRowDbTableEditorViewModel.cs +++ b/WDE.DatabaseEditors/ViewModels/MultiRow/MultiRowDbTableEditorViewModel.cs @@ -789,7 +789,7 @@ private void EnsureKey(DatabaseKey entity) { if (keys.Add(entity)) { - byEntryGroups[entity] = new DatabaseEntitiesGroupViewModel(entity, GenerateName(entity[0])); + byEntryGroups[entity] = new DatabaseEntitiesGroupViewModel(entity, GenerateName(entity[0]), () => GenerateNameAsync(entity[0])); Rows.Add(byEntryGroups[entity]); entities.Add(new CustomObservableCollection()); } diff --git a/WDE.DatabaseEditors/ViewModels/RowPickerViewModel.cs b/WDE.DatabaseEditors/ViewModels/RowPickerViewModel.cs index 14b7b0762..6ad2867ce 100644 --- a/WDE.DatabaseEditors/ViewModels/RowPickerViewModel.cs +++ b/WDE.DatabaseEditors/ViewModels/RowPickerViewModel.cs @@ -54,6 +54,7 @@ public RowPickerViewModel(ViewModelBase baseViewModel, this.messageBoxService = messageBoxService; this.noSaveMode = noSaveMode; Watch(baseViewModel, o => o.IsModified, nameof(Title)); + Watch(baseViewModel, o => o.Title, nameof(Title)); ExecuteChangedCommand = noSaveMode ? AlwaysDisabledAsyncCommand.Command : new AsyncAutoCommand(async () => { await baseViewModel.Save.ExecuteAsync(); diff --git a/WDE.DatabaseEditors/ViewModels/ViewModelBase.cs b/WDE.DatabaseEditors/ViewModels/ViewModelBase.cs index 46625eb2f..0ab51051e 100644 --- a/WDE.DatabaseEditors/ViewModels/ViewModelBase.cs +++ b/WDE.DatabaseEditors/ViewModels/ViewModelBase.cs @@ -98,6 +98,11 @@ protected ViewModelBase(IHistoryManager history, redoCommand = new DelegateCommand(History.Redo, CanRedo); Save = new AsyncAutoCommand(SaveSolutionItem); title = solutionItemName.GetName(solutionItem); + async Task GetTitleAsync() + { + Title = await solutionItemName.GetNameAsync(solutionItem); + } + GetTitleAsync().ListenErrors(); Icon = iconRegistry.GetIcon(solutionItem); nameGeneratorParameter = parameterFactory.Factory("Parameter"); @@ -210,7 +215,7 @@ await messageBoxService.ShowDialog(new MessageBoxFactory() } progress.ReportFinished(); }); - Title = solutionItemName.GetName(SolutionItem); + Title = await solutionItemName.GetNameAsync(SolutionItem); } protected virtual Task AfterSave() => Task.CompletedTask; @@ -220,7 +225,7 @@ await messageBoxService.ShowDialog(new MessageBoxFactory() protected virtual async Task LoadData() { - return await databaseTableDataProvider.Load(solutionItem.TableName, null, null, null, solutionItem.Entries.Select(e => e.Key).ToArray()) as DatabaseTableData; ; + return await databaseTableDataProvider.Load(solutionItem.TableName, null, null, null, solutionItem.Entries.Select(e => e.Key).ToArray()) as DatabaseTableData; } protected async Task InternalLoadData() @@ -321,6 +326,15 @@ protected string GenerateName(long entity) { return nameGeneratorParameter.ToString(entity); } + + protected async Task GenerateNameAsync(long entity) + { + if (nameGeneratorParameter is IAsyncParameter lp) + { + return await lp.ToStringAsync(entity, default); + } + return nameGeneratorParameter.ToString(entity); + } protected DatabaseTableDefinitionJson tableDefinition = null!; public DatabaseTableDefinitionJson TableDefinition => tableDefinition; diff --git a/WDE.Solutions/Manager/SolutionItemNameRegistry.cs b/WDE.Solutions/Manager/SolutionItemNameRegistry.cs index 0bfca6228..6905b3cdb 100644 --- a/WDE.Solutions/Manager/SolutionItemNameRegistry.cs +++ b/WDE.Solutions/Manager/SolutionItemNameRegistry.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using WDE.Common; using WDE.Common.Solution; using WDE.Module.Attributes; @@ -10,12 +11,17 @@ namespace WDE.Solutions.Manager public class SolutionItemNameRegistry : ISolutionItemNameRegistry { private readonly Dictionary nameProviders = new(); + private readonly Dictionary asyncNameProviders = new(); - public SolutionItemNameRegistry(IEnumerable providers) + public SolutionItemNameRegistry(IEnumerable providers, + IEnumerable asyncProviders) { // handy trick with (dynamic) cast, thanks to this proper Generic method will be called! foreach (ISolutionNameProvider provider in providers) Register((dynamic) provider); + + foreach (ISolutionNameProviderAsync provider in asyncProviders) + RegisterAsync((dynamic)provider); } public string GetName(ISolutionItem item) @@ -23,11 +29,21 @@ public string GetName(ISolutionItem item) return GetName((dynamic) item); } + public Task GetNameAsync(ISolutionItem item) + { + return GetNameAsync((dynamic) item); + } + private void Register(ISolutionNameProvider provider) where T : ISolutionItem { nameProviders.Add(typeof(T), provider); } + private void RegisterAsync(ISolutionNameProviderAsync provider) where T : ISolutionItem + { + asyncNameProviders.Add(typeof(T), provider); + } + private string GetName(T item) where T : ISolutionItem { if (nameProviders.TryGetValue(item.GetType(), out var nameProvider)) @@ -41,5 +57,16 @@ private string GetName(T item) where T : ISolutionItem return item.GetType().Name; #endif } + + private async Task GetNameAsync(T item) where T : ISolutionItem + { + if (asyncNameProviders.TryGetValue(item.GetType(), out var nameProvider)) + { + var x = (ISolutionNameProviderAsync)nameProvider; + return await x.GetNameAsync(item); + } + + return GetName(item); + } } } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionItemNameRegistry.cs b/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionItemNameRegistry.cs index d0e19402b..768cb7e1a 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionItemNameRegistry.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionItemNameRegistry.cs @@ -1,4 +1,5 @@ -using WDE.Module.Attributes; +using System.Threading.Tasks; +using WDE.Module.Attributes; namespace WDE.Common.Solution { @@ -6,5 +7,6 @@ namespace WDE.Common.Solution public interface ISolutionItemNameRegistry { string GetName(ISolutionItem item); + Task GetNameAsync(ISolutionItem item); } } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionNameProvider.cs b/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionNameProvider.cs index 826c3ac8e..10778cf2f 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionNameProvider.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Solution/ISolutionNameProvider.cs @@ -1,4 +1,5 @@ -using WDE.Module.Attributes; +using System.Threading.Tasks; +using WDE.Module.Attributes; namespace WDE.Common.Solution { @@ -12,4 +13,15 @@ public interface ISolutionNameProvider : ISolutionNameProvider where T : ISol { string GetName(T item); } + + [NonUniqueProvider] + public interface ISolutionNameProviderAsync + { + } + + [NonUniqueProvider] + public interface ISolutionNameProviderAsync : ISolutionNameProviderAsync where T : ISolutionItem + { + Task GetNameAsync(T item); + } } \ No newline at end of file