Skip to content

Commit 86a6991

Browse files
authored
Merge pull request #2307 from Nexus-Mods/loadorder-v2-TreeDataGrid-backend
Loadorder v2 tree data grid backend part 5
2 parents 861d178 + 95cb39f commit 86a6991

File tree

4 files changed

+75
-22
lines changed

4 files changed

+75
-22
lines changed

src/Games/NexusMods.Games.RedEngine/Cyberpunk2077/SortOrder/RedMod/RedModSortableItemProvider.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ private async Task PersistSortableEntries(List<RedModSortableItem> orderList)
378378

379379
private static bool RedModIsEnabled(RedModLoadoutGroup.ReadOnly grp)
380380
{
381-
return !grp.AsLoadoutItemGroup().AsLoadoutItem().GetThisAndParents().Any(f => f.Contains(LoadoutItem.Disabled));
381+
return grp.AsLoadoutItemGroup().AsLoadoutItem().IsEnabled();
382382
}
383383

384384
private static RelativePath RedModFolder(RedModLoadoutGroup.ReadOnly group)

src/NexusMods.App.UI/Pages/Sorting/LoadOrder/ILoadOrderItemModel.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Reactive;
2-
using NexusMods.Abstractions.Games;
32
using NexusMods.App.UI.Controls;
43
using ReactiveUI;
54

src/NexusMods.App.UI/Pages/Sorting/LoadOrder/LoadOrderItemModel.cs

+31-5
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
using System.Reactive;
2+
using System.Reactive.Disposables;
23
using NexusMods.Abstractions.Games;
34
using NexusMods.App.UI.Controls;
45
using ReactiveUI;
6+
using ReactiveUI.Fody.Helpers;
57

68
namespace NexusMods.App.UI.Pages.Sorting;
79

810
public class LoadOrderItemModel : TreeDataGridItemModel<ILoadOrderItemModel, Guid>, ILoadOrderItemModel
911
{
12+
private CompositeDisposable _disposables = new();
1013
public ISortableItem InnerItem { get; }
1114

1215
public ReactiveCommand<Unit, Unit> MoveUp { get; }
1316
public ReactiveCommand<Unit, Unit> MoveDown { get; }
1417
public int SortIndex { get; }
1518
public string DisplayName { get; }
1619

17-
// TODO: Populate these properly
18-
public string ModName { get; } = string.Empty;
19-
public bool IsActive { get; } = true;
20+
[Reactive] public string ModName { get; private set; }
21+
[Reactive] public bool IsActive { get; private set; }
2022

2123
public LoadOrderItemModel(ISortableItem sortableItem)
2224
{
2325
InnerItem = sortableItem;
2426
SortIndex = sortableItem.SortIndex;
2527
DisplayName = sortableItem.DisplayName;
2628

29+
IsActive = sortableItem.IsActive;
30+
ModName = sortableItem.ModName;
31+
2732
MoveUp = ReactiveCommand.CreateFromTask(async () =>
2833
{
2934
await sortableItem.SortableItemProvider.SetRelativePosition(InnerItem, delta: 1);
@@ -37,9 +42,30 @@ public LoadOrderItemModel(ISortableItem sortableItem)
3742
return Unit.Default;
3843
}
3944
);
40-
45+
46+
this.WhenAnyValue(vm => vm.InnerItem.IsActive)
47+
.Subscribe(value => IsActive = value)
48+
.DisposeWith(_disposables);
49+
50+
this.WhenAnyValue(vm => vm.InnerItem.ModName)
51+
.Subscribe(value => ModName = value)
52+
.DisposeWith(_disposables);
4153
}
4254

4355

44-
56+
private bool _isDisposed;
57+
protected override void Dispose(bool disposing)
58+
{
59+
if (!_isDisposed)
60+
{
61+
if (disposing)
62+
{
63+
_disposables.Dispose();
64+
}
65+
66+
_isDisposed = true;
67+
}
68+
69+
base.Dispose(disposing);
70+
}
4571
}

src/NexusMods.App.UI/Pages/Sorting/LoadOrder/LoadOrderViewModel.cs

+43-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.ComponentModel;
22
using System.Reactive;
33
using System.Reactive.Disposables;
4+
using System.Reactive.Linq;
45
using Avalonia.Controls.Models.TreeDataGrid;
56
using DynamicData;
67
using DynamicData.Binding;
@@ -23,7 +24,7 @@ public class LoadOrderViewModel : AViewModel<ILoadOrderViewModel>, ILoadOrderVie
2324
public ReactiveCommand<Unit, Unit> InfoAlertCommand { get; } = ReactiveCommand.Create(() => { });
2425
public string TrophyToolTip { get; }
2526
[Reactive] public ListSortDirection SortDirectionCurrent { get; set; }
26-
[Reactive] public bool IsWinnerTop { get; set; }
27+
[Reactive] public bool IsWinnerTop { get; private set; }
2728
public string EmptyStateMessageTitle { get; }
2829
public string EmptyStateMessageContents { get; }
2930

@@ -32,30 +33,40 @@ public class LoadOrderViewModel : AViewModel<ILoadOrderViewModel>, ILoadOrderVie
3233
public LoadOrderViewModel(LoadoutId loadoutId, ISortableItemProviderFactory itemProviderFactory)
3334
{
3435
var provider = itemProviderFactory.GetLoadoutSortableItemProvider(loadoutId);
35-
36+
3637
SortOrderName = itemProviderFactory.SortOrderName;
3738
InfoAlertTitle = itemProviderFactory.OverrideInfoTitle;
3839
InfoAlertHeading = itemProviderFactory.OverrideInfoHeading;
3940
InfoAlertMessage = itemProviderFactory.OverrideInfoMessage;
4041
TrophyToolTip = itemProviderFactory.WinnerIndexToolTip;
4142
EmptyStateMessageTitle = itemProviderFactory.EmptyStateMessageTitle;
4243
EmptyStateMessageContents = itemProviderFactory.EmptyStateMessageContents;
43-
44+
4445
// TODO: load these from settings
4546
SortDirectionCurrent = itemProviderFactory.SortDirectionDefault;
46-
IsWinnerTop = itemProviderFactory.IndexOverrideBehavior == IndexOverrideBehavior.SmallerIndexWins &&
47-
SortDirectionCurrent == ListSortDirection.Ascending;
4847
InfoAlertIsVisible = true;
4948

50-
51-
Adapter = new LoadOrderTreeDataGridAdapter(provider);
49+
IsWinnerTop = SortDirectionCurrent == ListSortDirection.Ascending &&
50+
itemProviderFactory.IndexOverrideBehavior == IndexOverrideBehavior.SmallerIndexWins;
51+
52+
var sortDirectionObservable = this.WhenAnyValue(vm => vm.SortDirectionCurrent);
53+
Adapter = new LoadOrderTreeDataGridAdapter(provider, sortDirectionObservable);
5254
Adapter.ViewHierarchical.Value = true;
5355

5456
this.WhenActivated(d =>
5557
{
5658
Adapter.Activate();
5759
Disposable.Create(() => Adapter.Deactivate())
5860
.DisposeWith(d);
61+
62+
sortDirectionObservable.Subscribe(sortDirection =>
63+
{
64+
var isAscending = sortDirection == ListSortDirection.Ascending;
65+
IsWinnerTop = isAscending &&
66+
itemProviderFactory.IndexOverrideBehavior == IndexOverrideBehavior.SmallerIndexWins;
67+
}
68+
)
69+
.DisposeWith(d);
5970
}
6071
);
6172
}
@@ -64,17 +75,34 @@ public LoadOrderViewModel(LoadoutId loadoutId, ISortableItemProviderFactory item
6475
public class LoadOrderTreeDataGridAdapter : TreeDataGridAdapter<ILoadOrderItemModel, Guid>
6576
{
6677
private ILoadoutSortableItemProvider _sortableItemsProvider;
78+
private IObservable<ListSortDirection> _sortDirectionObservable;
6779

68-
public LoadOrderTreeDataGridAdapter(ILoadoutSortableItemProvider sortableItemsProvider)
80+
public LoadOrderTreeDataGridAdapter(ILoadoutSortableItemProvider sortableItemsProvider, IObservable<ListSortDirection> sortDirectionObservable)
6981
{
7082
_sortableItemsProvider = sortableItemsProvider;
83+
_sortDirectionObservable = sortDirectionObservable;
7184
}
7285

7386
protected override IObservable<IChangeSet<ILoadOrderItemModel, Guid>> GetRootsObservable(bool viewHierarchical)
7487
{
75-
return _sortableItemsProvider.SortableItems
76-
.ToObservableChangeSet(item => item.ItemId)
77-
.Transform(item => (ILoadOrderItemModel)new LoadOrderItemModel(item));
88+
var sortableItems = _sortableItemsProvider.SortableItems
89+
.ToObservableChangeSet(item => item.ItemId);
90+
91+
var ascendingSortableItems = sortableItems
92+
.ToSortedCollection(item => item.SortIndex, SortDirection.Ascending)
93+
.ToObservableChangeSet(item => item.ItemId);
94+
95+
var descendingSortableItems = sortableItems
96+
.ToSortedCollection(item => item.SortIndex, SortDirection.Descending)
97+
.ToObservableChangeSet(item => item.ItemId);
98+
99+
// Sort the items based on SortDirection
100+
var sortedItems = _sortDirectionObservable
101+
.Select(direction => direction == ListSortDirection.Ascending ? ascendingSortableItems : descendingSortableItems)
102+
.Switch()
103+
.Transform(ILoadOrderItemModel (item) => new LoadOrderItemModel(item));
104+
105+
return sortedItems;
78106
}
79107

80108
protected override IColumn<ILoadOrderItemModel>[] CreateColumns(bool viewHierarchical)
@@ -83,10 +111,10 @@ protected override IColumn<ILoadOrderItemModel>[] CreateColumns(bool viewHierarc
83111
[
84112
// TODO: Use <see cref="ColumnCreator"/> to create the columns using interfaces
85113
new HierarchicalExpanderColumn<ILoadOrderItemModel>(
86-
inner: CreateIndexColumn(_sortableItemsProvider.ParentFactory.IndexColumnHeader),
87-
childSelector: static model => model.Children,
88-
hasChildrenSelector: static model => model.HasChildren.Value,
89-
isExpandedSelector: static model => model.IsExpanded
114+
inner: CreateIndexColumn(_sortableItemsProvider.ParentFactory.IndexColumnHeader),
115+
childSelector: static model => model.Children,
116+
hasChildrenSelector: static model => model.HasChildren.Value,
117+
isExpandedSelector: static model => model.IsExpanded
90118
)
91119
{
92120
Tag = "expander",

0 commit comments

Comments
 (0)