mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
Merge pull request #372 from GICodeWarrior/patch-1
Improve TreeView and Export performance
This commit is contained in:
commit
928834fd4b
|
|
@ -4,6 +4,8 @@
|
|||
xmlns:local="clr-namespace:FModel"
|
||||
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
|
||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||
xmlns:settings="clr-namespace:FModel.Settings"
|
||||
xmlns:services="clr-namespace:FModel.Services"
|
||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
||||
|
|
@ -95,7 +97,7 @@
|
|||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Auto Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Views">
|
||||
<MenuItem Header="3D Viewer" Command="{Binding MenuCommand}" CommandParameter="Views_3dViewer">
|
||||
|
|
@ -221,7 +223,7 @@
|
|||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Loading Mode" VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding LoadingModes.Modes}" IsEnabled="{Binding Status.IsReady}"
|
||||
SelectedItem="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}">
|
||||
SelectedItem="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
|
|
@ -327,7 +329,7 @@
|
|||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Grid.Row="1" Style="{StaticResource CustomSeparator}" Margin="0" />
|
||||
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick">
|
||||
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True">
|
||||
<TreeView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Extract Folder's Packages" Click="OnFolderExtractClick">
|
||||
|
|
@ -671,7 +673,7 @@
|
|||
|
||||
<TabControl Grid.Row="0" x:Name="TabControlName" Style="{StaticResource GameFilesTabControl}" />
|
||||
<Expander Grid.Row="1" Margin="0 5 0 5" ExpandDirection="Down"
|
||||
IsExpanded="{Binding IsLoggerExpanded, Source={x:Static local:Settings.UserSettings.Default}}">
|
||||
IsExpanded="{Binding IsLoggerExpanded, Source={x:Static settings:UserSettings.Default}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
|
|
@ -734,7 +736,7 @@
|
|||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding StatusChangeAttempted, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger Binding="{Binding StatusChangeAttempted, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard Duration="0:0:0.8">
|
||||
|
|
@ -751,7 +753,7 @@
|
|||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding OperationCancelled, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger Binding="{Binding OperationCancelled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard Duration="0:0:1">
|
||||
|
|
@ -780,7 +782,7 @@
|
|||
</DataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding CanBeCanceled, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True" />
|
||||
<Condition Binding="{Binding CanBeCanceled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True" />
|
||||
<Condition Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Text" Value="{Binding Status.Label, StringFormat='{}{0} … ESC to Cancel'}" />
|
||||
|
|
@ -805,7 +807,7 @@
|
|||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" Value="False">
|
||||
<DataTrigger Binding="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Hidden" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
{
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
Thread.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs);
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
{
|
||||
foreach (var asset in folder.AssetsList.Assets)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
Thread.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using AdonisUI.Controls;
|
||||
using FModel.Extensions;
|
||||
|
|
@ -79,19 +80,13 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "ToolBox_Expand_All":
|
||||
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
||||
{
|
||||
foreach (var folder in contextViewModel.CUE4Parse.AssetsFolder.Folders)
|
||||
{
|
||||
LoopFolders(cancellationToken, folder, true);
|
||||
}
|
||||
SetFoldersIsExpanded(contextViewModel.CUE4Parse.AssetsFolder, true, cancellationToken);
|
||||
});
|
||||
break;
|
||||
case "ToolBox_Collapse_All":
|
||||
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
||||
{
|
||||
foreach (var folder in contextViewModel.CUE4Parse.AssetsFolder.Folders)
|
||||
{
|
||||
LoopFolders(cancellationToken, folder, false);
|
||||
}
|
||||
SetFoldersIsExpanded(contextViewModel.CUE4Parse.AssetsFolder, false, cancellationToken);
|
||||
});
|
||||
break;
|
||||
case TreeItem selectedFolder:
|
||||
|
|
@ -101,15 +96,44 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
}
|
||||
}
|
||||
|
||||
private void LoopFolders(CancellationToken cancellationToken, TreeItem parent, bool isExpanded)
|
||||
private static void SetFoldersIsExpanded(AssetsFolderViewModel root, bool isExpanded, CancellationToken cancellationToken)
|
||||
{
|
||||
if (parent.IsExpanded != isExpanded)
|
||||
LinkedList<TreeItem> nodes = new();
|
||||
foreach (TreeItem folder in root.Folders)
|
||||
{
|
||||
parent.IsExpanded = isExpanded;
|
||||
Thread.Sleep(10);
|
||||
nodes.AddLast(folder);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
foreach (var f in parent.Folders) LoopFolders(cancellationToken, f, isExpanded);
|
||||
LinkedListNode<TreeItem> current = nodes.First;
|
||||
while (current != null)
|
||||
{
|
||||
TreeItem folder = current.Value;
|
||||
|
||||
// Collapse top-down (reduce layout updates)
|
||||
if (!isExpanded)
|
||||
{
|
||||
folder.IsExpanded = isExpanded;
|
||||
Thread.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
foreach (TreeItem child in folder.Folders)
|
||||
{
|
||||
nodes.AddLast(child);
|
||||
}
|
||||
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
// Expand bottom-up (reduce layout updates)
|
||||
if (isExpanded)
|
||||
{
|
||||
for (LinkedListNode<TreeItem> node = nodes.Last; node != null; node = node.Previous)
|
||||
{
|
||||
node.Value.IsExpanded = isExpanded;
|
||||
Thread.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
xmlns:soundOut="clr-namespace:CSCore.SoundOut;assembly=CSCore"
|
||||
xmlns:audioControls="clr-namespace:FModel.Views.Resources.Controls.Aup"
|
||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||
xmlns:settings="clr-namespace:FModel.Settings"
|
||||
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
|
||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
|
|
@ -182,19 +183,19 @@
|
|||
</Setter.Value>
|
||||
</Setter>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Single}">
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Single}">
|
||||
<Setter Property="SelectionMode" Value="Single" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Multiple}">
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Multiple}">
|
||||
<Setter Property="SelectionMode" Value="Extended" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.All}">
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.All}">
|
||||
<Setter Property="SelectionMode" Value="Extended" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButNew}">
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButNew}">
|
||||
<Setter Property="SelectionMode" Value="Extended" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButModified}">
|
||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButModified}">
|
||||
<Setter Property="SelectionMode" Value="Extended" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
|
|
@ -247,7 +248,7 @@
|
|||
</Style>
|
||||
|
||||
<Style x:Key="AssetsFolderTreeView" TargetType="TreeView" BasedOn="{StaticResource {x:Type TreeView}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.AssetsFolder.FoldersView, IsAsync=True}" />
|
||||
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.AssetsFolder.FoldersView}" />
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode" Value="NeverExpand"/>
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement" Value="Docked"/>
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.HorizontalScrollBarExpansionMode" Value="NeverExpand"/>
|
||||
|
|
@ -255,7 +256,7 @@
|
|||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="ItemTemplate">
|
||||
<Setter.Value>
|
||||
<HierarchicalDataTemplate ItemsSource="{Binding FoldersView, IsAsync=True}">
|
||||
<HierarchicalDataTemplate ItemsSource="{Binding FoldersView}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image x:Name="TreeImage" Source="/FModel;component/Resources/folder.png"
|
||||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3.5 0" />
|
||||
|
|
@ -647,7 +648,7 @@
|
|||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="{Binding AvalonImageSize, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<ColumnDefinition Width="{Binding AvalonImageSize, Source={x:Static settings:UserSettings.Default}, Mode=TwoWay}" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:AvalonEditor x:Name="DynamicArea" Grid.Column="0" DataContext="{Binding SelectedItem, ElementName=TabControlName}" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user