mirror of
https://github.com/4sval/FModel.git
synced 2026-09-25 02:29:21 -05:00
Optimize asset tree construction
This commit is contained in:
Submodule CUE4Parse updated: 396ede2a1d...cd9fa6d9c7
@@ -2,11 +2,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public sealed class RangeObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
private static readonly PropertyChangedEventArgs CountChanged = new(nameof(Count));
|
||||
private static readonly PropertyChangedEventArgs IndexerChanged = new("Item[]");
|
||||
private bool _suppressNotification;
|
||||
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
@@ -20,15 +23,26 @@ public sealed class RangeObservableCollection<T> : ObservableCollection<T>
|
||||
if (list == null)
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
|
||||
_suppressNotification = true;
|
||||
|
||||
var changed = false;
|
||||
foreach (var item in list)
|
||||
Add(item);
|
||||
{
|
||||
Items.Add(item);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
_suppressNotification = false;
|
||||
if (!changed || _suppressNotification)
|
||||
return;
|
||||
|
||||
OnPropertyChanged(CountChanged);
|
||||
OnPropertyChanged(IndexerChanged);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an item while constructing a collection that has not been published to a binding yet.
|
||||
/// </summary>
|
||||
public void AddWithoutNotification(T item) => Items.Add(item);
|
||||
|
||||
public void SetSuppressionState(bool state)
|
||||
{
|
||||
_suppressNotification = state;
|
||||
@@ -38,4 +52,4 @@ public sealed class RangeObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(changedAction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@
|
||||
<MultiBinding StringFormat="{}'{0}' has {1} folders and {2} packages">
|
||||
<Binding Path="SelectedItem.Header" ElementName="AssetsFolderName" FallbackValue="None" />
|
||||
<Binding Path="SelectedItem.FoldersView.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
<Binding Path="SelectedItem.AssetsList.Assets.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
<Binding Path="SelectedItem.AssetsList.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
@@ -371,7 +371,7 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.AssetsList.Assets.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.AssetsList.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Packages Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.FoldersView.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="Folders Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
@@ -386,7 +386,7 @@
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}"
|
||||
Header="{Binding SelectedItem.AssetsList.Assets.Count, FallbackValue=0, ElementName=AssetsFolderName}"
|
||||
Header="{Binding SelectedItem.AssetsList.Count, FallbackValue=0, ElementName=AssetsFolderName}"
|
||||
HeaderStringFormat="{}{0} Packages">
|
||||
<DockPanel>
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
var childFolder = folder;
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Assets.Count == 0)
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Count == 0)
|
||||
{
|
||||
childFolder.IsExpanded = true;
|
||||
childFolder = childFolder.Folders[0];
|
||||
@@ -360,14 +360,14 @@ public partial class MainWindow
|
||||
if (e.Key != Key.Enter || sender is not TreeView treeView || treeView.SelectedItem is not TreeItem folder)
|
||||
return;
|
||||
|
||||
if ((folder.IsExpanded || folder.Folders.Count == 0) && folder.AssetsList.Assets.Count > 0)
|
||||
if ((folder.IsExpanded || folder.Folders.Count == 0) && folder.AssetsList.Count > 0)
|
||||
{
|
||||
_applicationView.SelectedLeftTabIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
var childFolder = folder;
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Assets.Count == 0)
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Count == 0)
|
||||
{
|
||||
childFolder.IsExpanded = true;
|
||||
childFolder = childFolder.Folders[0];
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
@@ -16,14 +15,9 @@ using FModel.Services;
|
||||
|
||||
namespace FModel.ViewModels;
|
||||
|
||||
public class TreeItem : ViewModel
|
||||
public sealed class TreeItem : ViewModel
|
||||
{
|
||||
private readonly string _header;
|
||||
public string Header
|
||||
{
|
||||
get => _header;
|
||||
private init => SetProperty(ref _header, value);
|
||||
}
|
||||
public string Header { get; }
|
||||
|
||||
private bool _isExpanded;
|
||||
public bool IsExpanded
|
||||
@@ -39,26 +33,9 @@ public class TreeItem : ViewModel
|
||||
set => SetProperty(ref _isSelected, value);
|
||||
}
|
||||
|
||||
private string _archive;
|
||||
public string Archive
|
||||
{
|
||||
get => _archive;
|
||||
private set => SetProperty(ref _archive, value);
|
||||
}
|
||||
|
||||
private string _mountPoint;
|
||||
public string MountPoint
|
||||
{
|
||||
get => _mountPoint;
|
||||
private set => SetProperty(ref _mountPoint, value);
|
||||
}
|
||||
|
||||
private FPackageFileVersion _version;
|
||||
public FPackageFileVersion Version
|
||||
{
|
||||
get => _version;
|
||||
private set => SetProperty(ref _version, value);
|
||||
}
|
||||
public string Archive { get; }
|
||||
public string MountPoint { get; }
|
||||
public FPackageFileVersion Version { get; }
|
||||
|
||||
private string _searchText = string.Empty;
|
||||
public string SearchText
|
||||
@@ -157,12 +134,12 @@ public class TreeItem : ViewModel
|
||||
}
|
||||
PathAtThisPoint = pathHere;
|
||||
|
||||
AssetsList.AssetsView.Filter = o => ItemFilter(o, SearchText.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries));
|
||||
AssetsList.SetFilter(o => ItemFilter(o, SearchText.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries)));
|
||||
}
|
||||
|
||||
private void RefreshFilters()
|
||||
{
|
||||
AssetsList.AssetsView.Refresh();
|
||||
AssetsList.RefreshView();
|
||||
FilteredFoldersView?.Refresh();
|
||||
}
|
||||
|
||||
@@ -195,7 +172,7 @@ public class TreeItem : ViewModel
|
||||
RefreshFilters();
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Header} | {Folders.Count} Folders | {AssetsList.Assets.Count} Files";
|
||||
public override string ToString() => $"{Header} | {Folders.Count} Folders | {AssetsList.Count} Files";
|
||||
}
|
||||
|
||||
public class AssetsFolderViewModel
|
||||
@@ -214,80 +191,98 @@ public class AssetsFolderViewModel
|
||||
if (entries == null || entries.Count == 0)
|
||||
return;
|
||||
|
||||
var treeItems = new List<TreeItem>();
|
||||
var foldersByPath = new Dictionary<string, TreeItem>(StringComparer.Ordinal);
|
||||
var folderLookup = foldersByPath.GetAlternateLookup<ReadOnlySpan<char>>();
|
||||
TreeItem previousFolder = null;
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
|
||||
.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
var path = entry.Path.AsSpan();
|
||||
if (path.StartsWith(localAppData.AsSpan(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
path = path[localAppData.Length..];
|
||||
while (!path.IsEmpty &&
|
||||
(path[0] == Path.DirectorySeparatorChar || path[0] == Path.AltDirectorySeparatorChar))
|
||||
path = path[1..];
|
||||
}
|
||||
|
||||
var pathEnd = path.Length;
|
||||
while (pathEnd > 0 && path[pathEnd - 1] == Path.AltDirectorySeparatorChar)
|
||||
pathEnd--;
|
||||
|
||||
var lastSeparator = path[..pathEnd].LastIndexOf(Path.AltDirectorySeparatorChar);
|
||||
if (lastSeparator < 0)
|
||||
{
|
||||
previousFolder = GetOrAddContentFolder(foldersByPath, entry, treeItems);
|
||||
previousFolder.AssetsList.Add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
var directories = path[..lastSeparator];
|
||||
if (previousFolder != null && directories.SequenceEqual(previousFolder.PathAtThisPoint.AsSpan()))
|
||||
{
|
||||
previousFolder.AssetsList.Add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (folderLookup.TryGetValue(directories, out var leafFolder))
|
||||
{
|
||||
leafFolder.AssetsList.Add(entry);
|
||||
previousFolder = leafFolder;
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeItem parentNode = null;
|
||||
var segmentStart = 0;
|
||||
|
||||
while (segmentStart < directories.Length)
|
||||
{
|
||||
while (segmentStart < directories.Length && directories[segmentStart] == Path.AltDirectorySeparatorChar)
|
||||
segmentStart++;
|
||||
if (segmentStart == directories.Length)
|
||||
break;
|
||||
|
||||
var segmentEnd = directories[segmentStart..].IndexOf(Path.AltDirectorySeparatorChar);
|
||||
if (segmentEnd < 0)
|
||||
segmentEnd = directories.Length;
|
||||
else
|
||||
segmentEnd += segmentStart;
|
||||
|
||||
var folderPath = directories[..segmentEnd];
|
||||
if (!folderLookup.TryGetValue(folderPath, out var node))
|
||||
{
|
||||
var header = directories[segmentStart..segmentEnd].ToString();
|
||||
var normalizedPath = parentNode == null
|
||||
? header
|
||||
: string.Concat(parentNode.PathAtThisPoint, "/", header);
|
||||
if (!foldersByPath.TryGetValue(normalizedPath, out node))
|
||||
{
|
||||
node = new TreeItem(header, entry, normalizedPath) { Parent = parentNode };
|
||||
foldersByPath.Add(normalizedPath, node);
|
||||
|
||||
if (parentNode == null)
|
||||
treeItems.Add(node);
|
||||
else
|
||||
parentNode.Folders.AddWithoutNotification(node);
|
||||
}
|
||||
}
|
||||
|
||||
parentNode = node;
|
||||
segmentStart = segmentEnd + 1;
|
||||
}
|
||||
|
||||
if (parentNode == null)
|
||||
parentNode = GetOrAddContentFolder(foldersByPath, entry, treeItems);
|
||||
|
||||
parentNode.AssetsList.Add(entry);
|
||||
previousFolder = parentNode;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var treeItems = new RangeObservableCollection<TreeItem>();
|
||||
treeItems.SetSuppressionState(true);
|
||||
|
||||
static TreeItem FindByHeaderOrNull(IReadOnlyList<TreeItem> list, string header)
|
||||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].Header == header)
|
||||
return list[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
TreeItem lastNode = null;
|
||||
TreeItem parentItem = null;
|
||||
|
||||
var path = entry.Path;
|
||||
if (path.StartsWith(localAppData, StringComparison.OrdinalIgnoreCase))
|
||||
path = path[localAppData.Length..].TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
|
||||
var folders = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
var builder = new StringBuilder(64);
|
||||
var parentNode = treeItems;
|
||||
|
||||
if (folders.Length <= 1)
|
||||
{
|
||||
var rootNode = FindByHeaderOrNull(treeItems, "Content");
|
||||
if (rootNode == null)
|
||||
{
|
||||
rootNode = new TreeItem("Content", entry, "Content")
|
||||
{
|
||||
Parent = null
|
||||
};
|
||||
|
||||
rootNode.Folders.SetSuppressionState(true);
|
||||
rootNode.AssetsList.Assets.SetSuppressionState(true);
|
||||
treeItems.Add(rootNode);
|
||||
}
|
||||
|
||||
rootNode.AssetsList.Add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < folders.Length - 1; i++)
|
||||
{
|
||||
var folder = folders[i];
|
||||
builder.Append(folder).Append('/');
|
||||
lastNode = FindByHeaderOrNull(parentNode, folder);
|
||||
|
||||
if (lastNode == null)
|
||||
{
|
||||
var nodePath = builder.ToString();
|
||||
lastNode = new TreeItem(folder, entry, nodePath[..^1])
|
||||
{
|
||||
Parent = parentItem
|
||||
};
|
||||
lastNode.Folders.SetSuppressionState(true);
|
||||
lastNode.AssetsList.Assets.SetSuppressionState(true);
|
||||
parentNode.Add(lastNode);
|
||||
}
|
||||
|
||||
parentItem = lastNode;
|
||||
parentNode = lastNode.Folders;
|
||||
}
|
||||
|
||||
lastNode?.AssetsList.Add(entry);
|
||||
}
|
||||
|
||||
Folders.AddRange(treeItems);
|
||||
|
||||
if (treeItems.Count > 0)
|
||||
@@ -299,26 +294,19 @@ public class AssetsFolderViewModel
|
||||
}
|
||||
|
||||
ApplicationService.ApplicationView.CUE4Parse.SearchVm.ChangeCollection(entries);
|
||||
|
||||
foreach (var folder in Folders)
|
||||
InvokeOnCollectionChanged(folder);
|
||||
|
||||
static void InvokeOnCollectionChanged(TreeItem item)
|
||||
{
|
||||
item.Folders.SetSuppressionState(false);
|
||||
item.AssetsList.Assets.SetSuppressionState(false);
|
||||
|
||||
if (item.Folders.Count != 0)
|
||||
{
|
||||
item.Folders.InvokeOnCollectionChanged();
|
||||
|
||||
foreach (var folderItem in item.Folders)
|
||||
InvokeOnCollectionChanged(folderItem);
|
||||
}
|
||||
|
||||
if (item.AssetsList.Assets.Count != 0)
|
||||
item.AssetsList.Assets.InvokeOnCollectionChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static TreeItem GetOrAddContentFolder(Dictionary<string, TreeItem> foldersByPath, GameFile entry,
|
||||
List<TreeItem> roots)
|
||||
{
|
||||
const string content = "Content";
|
||||
if (foldersByPath.TryGetValue(content, out var node))
|
||||
return node;
|
||||
|
||||
node = new TreeItem(content, entry, content);
|
||||
foldersByPath.Add(content, node);
|
||||
roots.Add(node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Data;
|
||||
using CUE4Parse.FileProvider.Objects;
|
||||
@@ -7,20 +9,58 @@ namespace FModel.ViewModels;
|
||||
|
||||
public class AssetsListViewModel
|
||||
{
|
||||
public RangeObservableCollection<GameFileViewModel> Assets { get; } = [];
|
||||
private List<GameFile> _pendingAssets;
|
||||
private RangeObservableCollection<GameFileViewModel> _assets;
|
||||
public RangeObservableCollection<GameFileViewModel> Assets
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_assets != null)
|
||||
return _assets;
|
||||
|
||||
_assets = [];
|
||||
if (_pendingAssets == null)
|
||||
return _assets;
|
||||
|
||||
foreach (var asset in _pendingAssets)
|
||||
_assets.AddWithoutNotification(new GameFileViewModel(asset));
|
||||
|
||||
_pendingAssets = null;
|
||||
return _assets;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => _assets?.Count ?? _pendingAssets?.Count ?? 0;
|
||||
|
||||
private ICollectionView _assetsView;
|
||||
private Predicate<object> _filter;
|
||||
public ICollectionView AssetsView
|
||||
{
|
||||
get
|
||||
{
|
||||
_assetsView ??= new ListCollectionView(Assets)
|
||||
{
|
||||
SortDescriptions = { new SortDescription("Asset.Path", ListSortDirection.Ascending) }
|
||||
SortDescriptions = { new SortDescription("Asset.Path", ListSortDirection.Ascending) },
|
||||
Filter = _filter
|
||||
};
|
||||
return _assetsView;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(GameFile gameFile) => Assets.Add(new GameFileViewModel(gameFile));
|
||||
public void Add(GameFile gameFile)
|
||||
{
|
||||
if (_assets == null)
|
||||
(_pendingAssets ??= []).Add(gameFile);
|
||||
else
|
||||
_assets.Add(new GameFileViewModel(gameFile));
|
||||
}
|
||||
|
||||
public void SetFilter(Predicate<object> filter)
|
||||
{
|
||||
_filter = filter;
|
||||
if (_assetsView != null)
|
||||
_assetsView.Filter = filter;
|
||||
}
|
||||
|
||||
public void RefreshView() => _assetsView?.Refresh();
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
if (Provider == null) return;
|
||||
|
||||
AssetsFolder.Folders.Clear();
|
||||
SearchVm.SearchResults.Clear();
|
||||
SearchVm.Clear();
|
||||
Helper.CloseWindow<AdonisWindow>("Search For Packages");
|
||||
Provider.UnloadNonStreamedVfs();
|
||||
GC.Collect();
|
||||
|
||||
@@ -54,7 +54,7 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
|
||||
var loadingTime = Stopwatch.StartNew();
|
||||
#endif
|
||||
_applicationView.CUE4Parse.AssetsFolder.Folders.Clear();
|
||||
_applicationView.CUE4Parse.SearchVm.SearchResults.Clear();
|
||||
_applicationView.CUE4Parse.SearchVm.Clear();
|
||||
_applicationView.SelectedLeftTabIndex = 1; // folders tab
|
||||
_applicationView.IsAssetsExplorerVisible = true;
|
||||
Helper.CloseWindow<AdonisWindow>("Search For Packages"); // close search window if opened
|
||||
|
||||
@@ -61,17 +61,32 @@ public class SearchViewModel : ViewModel
|
||||
private set => SetProperty(ref _refFile, value);
|
||||
}
|
||||
|
||||
public RangeObservableCollection<GameFile> SearchResults { get; }
|
||||
public ListCollectionView SearchResultsView { get; }
|
||||
private List<GameFile> _searchResults = [];
|
||||
public List<GameFile> SearchResults
|
||||
{
|
||||
get => _searchResults;
|
||||
private set => SetProperty(ref _searchResults, value);
|
||||
}
|
||||
private ListCollectionView _searchResultsView;
|
||||
public ListCollectionView SearchResultsView
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_searchResultsView != null)
|
||||
return _searchResultsView;
|
||||
|
||||
_searchResultsView = new ListCollectionView(SearchResults)
|
||||
{
|
||||
Filter = e => ItemFilter(e, FilterText.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries)),
|
||||
};
|
||||
ResultsCount = _searchResultsView.Count;
|
||||
return _searchResultsView;
|
||||
}
|
||||
}
|
||||
|
||||
public SearchViewModel()
|
||||
{
|
||||
SearchResults = [];
|
||||
SearchResultsView = new ListCollectionView(SearchResults)
|
||||
{
|
||||
Filter = e => ItemFilter(e, FilterText.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries)),
|
||||
};
|
||||
ResultsCount = SearchResultsView.Count;
|
||||
ResultsCount = 0;
|
||||
}
|
||||
|
||||
public void RefreshFilter()
|
||||
@@ -82,12 +97,16 @@ public class SearchViewModel : ViewModel
|
||||
|
||||
public void ChangeCollection(IEnumerable<GameFile> files, GameFile refFile = null)
|
||||
{
|
||||
SearchResults.Clear();
|
||||
SearchResults.AddRange(files);
|
||||
var results = files as List<GameFile> ?? files.ToList();
|
||||
_searchResultsView = null;
|
||||
SearchResults = results;
|
||||
RaisePropertyChanged(nameof(SearchResultsView));
|
||||
RefFile = refFile;
|
||||
ResultsCount = SearchResultsView.Count;
|
||||
ResultsCount = results.Count;
|
||||
}
|
||||
|
||||
public void Clear() => ChangeCollection([]);
|
||||
|
||||
public async Task CycleSortSizeMode()
|
||||
{
|
||||
CurrentSortSizeMode = CurrentSortSizeMode switch
|
||||
@@ -126,8 +145,7 @@ public class SearchViewModel : ViewModel
|
||||
};
|
||||
});
|
||||
|
||||
SearchResults.Clear();
|
||||
SearchResults.AddRange(sorted);
|
||||
ChangeCollection(sorted, RefFile);
|
||||
}
|
||||
|
||||
private bool ItemFilter(object item, IEnumerable<string> filters)
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}"
|
||||
Opacity="0.8" />
|
||||
<TextBlock Grid.Row="3"
|
||||
Text="{Binding AssetsList.Assets.Count, StringFormat=Assets: {0}}"
|
||||
Text="{Binding AssetsList.Count, StringFormat=Assets: {0}}"
|
||||
FontSize="11"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}"
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<ColumnDefinition.Width>
|
||||
<MultiBinding Converter="{x:Static converters:RatioToGridLengthConverter.Instance}">
|
||||
<Binding Path="Folders.Count" />
|
||||
<Binding Path="AssetsList.Assets.Count" />
|
||||
<Binding Path="AssetsList.Count" />
|
||||
</MultiBinding>
|
||||
</ColumnDefinition.Width>
|
||||
</ColumnDefinition>
|
||||
|
||||
@@ -39,7 +39,7 @@ public partial class ResourcesDictionary
|
||||
|
||||
// Auto expand single child folders
|
||||
var childFolder = folder;
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Assets.Count == 0)
|
||||
while (childFolder.Folders.Count == 1 && childFolder.AssetsList.Count == 0)
|
||||
{
|
||||
childFolder.IsExpanded = true;
|
||||
childFolder = childFolder.Folders[0];
|
||||
|
||||
@@ -308,7 +308,7 @@
|
||||
Background="#705542"
|
||||
Margin="-10.5 0 4.5 0"
|
||||
VerticalAlignment="Bottom">
|
||||
<TextBlock Text="{Binding AssetsList.Assets.Count}"
|
||||
<TextBlock Text="{Binding AssetsList.Count}"
|
||||
Margin="2.5 0 2.5 0"
|
||||
Padding="1 0 0 0"
|
||||
FontSize="7"
|
||||
@@ -325,7 +325,7 @@
|
||||
<MultiBinding StringFormat="{}{0} has {1} folders and {2} packages">
|
||||
<Binding Path="Header" />
|
||||
<Binding Path="FoldersView.Count" />
|
||||
<Binding Path="AssetsList.Assets.Count" />
|
||||
<Binding Path="AssetsList.Count" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
@@ -340,7 +340,7 @@
|
||||
Property="Source"
|
||||
Value="/FModel;component/Resources/empty_folder.png" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding AssetsList.Assets.Count}"
|
||||
<DataTrigger Binding="{Binding AssetsList.Count}"
|
||||
Value="0">
|
||||
<Setter TargetName="TreeBadge"
|
||||
Property="Visibility"
|
||||
|
||||
@@ -150,7 +150,7 @@ public partial class SearchView
|
||||
MainWindow.YesWeCats.Activate();
|
||||
|
||||
do
|
||||
{ await Task.Delay(100); } while (MainWindow.YesWeCats.AssetsListName.Items.Count < folder.AssetsList.Assets.Count);
|
||||
{ await Task.Delay(100); } while (MainWindow.YesWeCats.AssetsListName.Items.Count < folder.AssetsList.Count);
|
||||
|
||||
while (!folder.IsSelected || MainWindow.YesWeCats.AssetsFolderName.SelectedItem != folder)
|
||||
await Task.Delay(50); // stops assets tab from opening too early
|
||||
|
||||
Reference in New Issue
Block a user