Browse Source

Replacing inheritance-based smooth scrolling with Behavior implementation

pull/3234/head
SlimeNull 11 months ago
parent
commit
050bb96c80
  1. 3
      Directory.Packages.props
  2. 6
      EleCho.WpfSuite/AssemblyInfo.cs
  3. 69
      EleCho.WpfSuite/Controls/ListBox.cs
  4. 68
      EleCho.WpfSuite/Controls/ListBoxResources.xaml
  5. 60
      EleCho.WpfSuite/Controls/ListView.cs
  6. 68
      EleCho.WpfSuite/Controls/ListViewResources.xaml
  7. 71
      EleCho.WpfSuite/EleCho.WpfSuite.csproj
  8. 75
      EleCho.WpfSuite/MathHelper.cs
  9. 7
      EleCho.WpfSuite/Themes/Generic.xaml
  10. 26
      EleCho.WpfSuite/ValueConverters/FallbackConverter.cs
  11. 22
      EleCho.WpfSuite/ValueConverters/MultiValueConverterBase.cs
  12. 17
      EleCho.WpfSuite/ValueConverters/SingletonMultiValueConverterBase.cs
  13. 10
      ILSpy.sln
  14. 7
      ILSpy/Controls/ZoomScrollViewer.cs
  15. 2
      ILSpy/ILSpy.csproj
  16. 5
      ILSpy/MainWindow.xaml
  17. 18
      ILSpy/Options/DecompilerSettingsPanel.xaml
  18. 10
      ILSpy/Options/DisplaySettingsPanel.xaml
  19. 7
      ILSpy/Search/SearchPane.xaml
  20. 10
      ILSpy/TextView/DecompilerTextView.xaml
  21. 14
      LibScrollingOptimization/LibScrollingOptimization.csproj
  22. 2
      LibScrollingOptimization/ScrollViewerUtils.cs
  23. 166
      LibScrollingOptimization/SmoothScrollingBehavior.cs
  24. 4
      SharpTreeView/ICSharpCode.TreeView.csproj
  25. 2
      SharpTreeView/SharpTreeView.cs
  26. 6
      SharpTreeView/Themes/Generic.xaml

3
Directory.Packages.props

@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
<PackageVersion Include="Microsoft.NETCore.ILDAsm" Version="8.0.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.VisualStudio.Composition" Version="17.10.37" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.122" />
<PackageVersion Include="Mono.Cecil" Version="0.11.5" />
<PackageVersion Include="NaturalSort.Extension" Version="4.3.0" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
@ -46,6 +46,7 @@ @@ -46,6 +46,7 @@
<PackageVersion Include="System.Reflection.Metadata" Version="8.0.0" />
<PackageVersion Include="System.Resources.Extensions" Version="8.0.0" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageVersion Include="TomsToolbox.Wpf" Version="2.15.0" />
<PackageVersion Include="TomsToolbox.Wpf.Styles" Version="2.14.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>

6
EleCho.WpfSuite/AssemblyInfo.cs

@ -1,6 +0,0 @@ @@ -1,6 +0,0 @@
using System.Runtime.CompilerServices;
using System.Windows.Markup;
[assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)]
[assembly: XmlnsDefinition("https://schemas.elecho.dev/wpfsuite", "EleCho.WpfSuite")]
//[assembly: XmlnsDefinition("https://schemas.elecho.dev/wpfsuite", "EleCho.WpfSuite.Markup")]

69
EleCho.WpfSuite/Controls/ListBox.cs

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace EleCho.WpfSuite
{
/// <inheritdoc/>
public class ListBox : System.Windows.Controls.ListBox
{
static ListBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ListBox), new FrameworkPropertyMetadata(typeof(ListBox)));
}
/// <summary>
/// The CornerRadius property allows users to control the roundness of the corners independently by
/// setting a radius value for each corner. Radius values that are too large are scaled so that they
/// smoothly blend from corner to corner.
/// </summary>
public CornerRadius CornerRadius {
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
/// <summary>
/// Background when disabled
/// </summary>
public Brush DisabledBackground {
get { return (Brush)GetValue(DisabledBackgroundProperty); }
set { SetValue(DisabledBackgroundProperty, value); }
}
/// <summary>
/// BorderBrush when pressed by mouse
/// </summary>
public Brush DisabledBorderBrush {
get { return (Brush)GetValue(DisabledBorderBrushProperty); }
set { SetValue(DisabledBorderBrushProperty, value); }
}
/// <summary>
/// DependencyProperty of <see cref="CornerRadius"/> property
/// </summary>
public static readonly DependencyProperty CornerRadiusProperty =
System.Windows.Controls.Border.CornerRadiusProperty.AddOwner(typeof(ListBox));
/// <summary>
/// The DependencyProperty of <see cref="DisabledBackground"/> property
/// </summary>
public static readonly DependencyProperty DisabledBackgroundProperty =
DependencyProperty.Register(nameof(DisabledBackground), typeof(Brush), typeof(ListBox), new FrameworkPropertyMetadata(null));
/// <summary>
/// The DependencyProperty of <see cref="DisabledBorderBrush"/> property
/// </summary>
public static readonly DependencyProperty DisabledBorderBrushProperty =
DependencyProperty.Register(nameof(DisabledBorderBrush), typeof(Brush), typeof(ListBox), new FrameworkPropertyMetadata(null));
}
}

68
EleCho.WpfSuite/Controls/ListBoxResources.xaml

@ -1,68 +0,0 @@ @@ -1,68 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ws="https://schemas.elecho.dev/wpfsuite">
<SolidColorBrush x:Key="ListBox.Static.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ListBox.Static.Border" Color="#FFABADB3"/>
<SolidColorBrush x:Key="ListBox.Disabled.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ListBox.Disabled.Border" Color="#FFD9D9D9"/>
<Style TargetType="{x:Type ws:ListBox}">
<Setter Property="Background" Value="{StaticResource ListBox.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBox.Static.Border}"/>
<Setter Property="DisabledBackground" Value="{StaticResource ListBox.Disabled.Background}"/>
<Setter Property="DisabledBorderBrush" Value="{StaticResource ListBox.Disabled.Border}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ws:ListBox}">
<Border x:Name="Part_BD"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
Padding="1"
SnapsToDevicePixels="true">
<ws:ScrollViewer x:Name="PART_Content"
Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ws:ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Part_BD" Property="Background">
<Setter.Value>
<MultiBinding Converter="{x:Static ws:FallbackConverter.Instance}">
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="DisabledBackground"/>
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="Background"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter TargetName="Part_BD" Property="BorderBrush">
<Setter.Value>
<MultiBinding Converter="{x:Static ws:FallbackConverter.Instance}">
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="DisabledBorderBrush"/>
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="BorderBrush"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="true"/>
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

60
EleCho.WpfSuite/Controls/ListView.cs

@ -1,60 +0,0 @@ @@ -1,60 +0,0 @@
using System.Windows;
using System.Windows.Media;
namespace EleCho.WpfSuite
{
/// <inheritdoc/>
public class ListView : System.Windows.Controls.ListView
{
static ListView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ListView), new FrameworkPropertyMetadata(typeof(ListView)));
}
/// <summary>
/// The CornerRadius property allows users to control the roundness of the corners independently by
/// setting a radius value for each corner. Radius values that are too large are scaled so that they
/// smoothly blend from corner to corner.
/// </summary>
public CornerRadius CornerRadius {
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
/// <summary>
/// Background when disabled
/// </summary>
public Brush DisabledBackground {
get { return (Brush)GetValue(DisabledBackgroundProperty); }
set { SetValue(DisabledBackgroundProperty, value); }
}
/// <summary>
/// BorderBrush when pressed by mouse
/// </summary>
public Brush DisabledBorderBrush {
get { return (Brush)GetValue(DisabledBorderBrushProperty); }
set { SetValue(DisabledBorderBrushProperty, value); }
}
/// <summary>
/// DependencyProperty of <see cref="CornerRadius"/> property
/// </summary>
public static readonly DependencyProperty CornerRadiusProperty =
System.Windows.Controls.Border.CornerRadiusProperty.AddOwner(typeof(ListView));
/// <summary>
/// The DependencyProperty of <see cref="DisabledBackground"/> property
/// </summary>
public static readonly DependencyProperty DisabledBackgroundProperty =
DependencyProperty.Register(nameof(DisabledBackground), typeof(Brush), typeof(ListView), new FrameworkPropertyMetadata(null));
/// <summary>
/// The DependencyProperty of <see cref="DisabledBorderBrush"/> property
/// </summary>
public static readonly DependencyProperty DisabledBorderBrushProperty =
DependencyProperty.Register(nameof(DisabledBorderBrush), typeof(Brush), typeof(ListView), new FrameworkPropertyMetadata(null));
}
}

68
EleCho.WpfSuite/Controls/ListViewResources.xaml

@ -1,68 +0,0 @@ @@ -1,68 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ws="https://schemas.elecho.dev/wpfsuite">
<SolidColorBrush x:Key="ListBox.Static.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ListBox.Static.Border" Color="#FFABADB3"/>
<SolidColorBrush x:Key="ListBox.Disabled.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ListBox.Disabled.Border" Color="#FFD9D9D9"/>
<Style TargetType="{x:Type ws:ListView}">
<Setter Property="Background" Value="{StaticResource ListBox.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBox.Static.Border}"/>
<Setter Property="DisabledBackground" Value="{StaticResource ListBox.Disabled.Background}"/>
<Setter Property="DisabledBorderBrush" Value="{StaticResource ListBox.Disabled.Border}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ws:ListView}">
<Border x:Name="Part_BD"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
Padding="1"
SnapsToDevicePixels="true">
<ws:ScrollViewer x:Name="PART_Content"
Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ws:ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Part_BD" Property="Background">
<Setter.Value>
<MultiBinding Converter="{x:Static ws:FallbackConverter.Instance}">
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="DisabledBackground"/>
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="Background"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter TargetName="Part_BD" Property="BorderBrush">
<Setter.Value>
<MultiBinding Converter="{x:Static ws:FallbackConverter.Instance}">
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="DisabledBorderBrush"/>
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="BorderBrush"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="true"/>
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

71
EleCho.WpfSuite/EleCho.WpfSuite.csproj

@ -1,71 +0,0 @@ @@ -1,71 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-windows;net6.0-windows;net48;net47;net46;net45</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<UseWPF>true</UseWPF>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<RootNamespace>EleCho.WpfSuite</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>0.6.0</Version>
<Authors>EleCho</Authors>
<Copyright>Copyright © 2024 EleCho</Copyright>
<PackageProjectUrl>https://wpfsuite.elecho.dev</PackageProjectUrl>
<PackageIcon>logo.png</PackageIcon>
<PackageTags>WPF;MVVM;XAML;Toolkit;Control;Layout;Transition;Converter;Animation;MarkupExtension;BindingProxy</PackageTags>
<Description>WPF layout panels, controls, value converters, markup extensions, transitions and utilities</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/OrgEleCho/EleCho.WpfSuite</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<Page Remove="Controls\ButtonResources.xaml" />
<Page Remove="Controls\CheckBoxResources.xaml" />
<Page Remove="Controls\ComboBoxItemResources.xaml" />
<Page Remove="Controls\ComboBoxResources.xaml" />
<Page Remove="Controls\ConditionalControlResources.xaml" />
<Page Remove="Controls\ContextMenuResources.xaml" />
<Page Remove="Controls\FrameResources.xaml" />
<Page Remove="Controls\GroupBoxResources.xaml" />
<Page Remove="Controls\ImageResources.xaml" />
<Page Remove="Controls\ListBoxResources.xaml" />
<Page Remove="Controls\ListViewResources.xaml" />
<Page Remove="Controls\MenuItemResources.xaml" />
<Page Remove="Controls\MenuResources.xaml" />
<Page Remove="Controls\PasswordBoxResources.xaml" />
<Page Remove="Controls\PopupResources.xaml" />
<Page Remove="Controls\ProgressBarResources.xaml" />
<Page Remove="Controls\SlicedImageResources.xaml" />
<Page Remove="Controls\TabControlResources.xaml" />
<Page Remove="Controls\TabItemResources.xaml" />
<Page Remove="Controls\TextBoxResources.xaml" />
<Page Remove="Controls\ToggleButtonResources.xaml" />
<Page Remove="Controls\TooltipResources.xaml" />
<Page Remove="Controls\TransitioningContentControlResources.xaml" />
</ItemGroup>
<ItemGroup>
<Resource Include="Controls\ListBoxResources.xaml">
<Generator>MSBuild:Compile</Generator>
</Resource>
<Resource Include="Controls\ListViewResources.xaml" />
</ItemGroup>
<ItemGroup>
<None Update="Controls\ListBoxItemResources.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="Controls\ListBoxResources.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="Controls\ScrollViewerResources.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
</ItemGroup>
</Project>

75
EleCho.WpfSuite/MathHelper.cs

@ -1,75 +0,0 @@ @@ -1,75 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
namespace EleCho.WpfSuite
{
internal static class MathHelper
{
internal const double DBL_EPSILON = 2.2204460492503131e-016;
public static bool AreClose(double value1, double value2) =>
// ReSharper disable once CompareOfFloatsByEqualityOperator
value1 == value2 || IsVerySmall(value1 - value2);
public static double Lerp(double x, double y, double alpha) => x * (1.0 - alpha) + y * alpha;
public static bool IsVerySmall(double value) => Math.Abs(value) < 1E-06;
public static bool IsZero(double value) => Math.Abs(value) < 10.0 * DBL_EPSILON;
public static bool IsFiniteDouble(double x) => !double.IsInfinity(x) && !double.IsNaN(x);
public static double DoubleFromMantissaAndExponent(double x, int exp) => x * Math.Pow(2.0, exp);
public static bool GreaterThan(double value1, double value2) => value1 > value2 && !AreClose(value1, value2);
public static bool GreaterThanOrClose(double value1, double value2)
{
if (value1 <= value2)
{
return AreClose(value1, value2);
}
return true;
}
public static double Hypotenuse(double x, double y) => Math.Sqrt(x * x + y * y);
public static bool LessThan(double value1, double value2) => value1 < value2 && !AreClose(value1, value2);
public static bool LessThanOrClose(double value1, double value2)
{
if (value1 >= value2)
{
return AreClose(value1, value2);
}
return true;
}
public static double EnsureRange(double value, double? min, double? max)
{
if (min.HasValue && value < min.Value)
{
return min.Value;
}
if (max.HasValue && value > max.Value)
{
return max.Value;
}
return value;
}
public static double SafeDivide(double lhs, double rhs, double fallback)
{
if (!IsVerySmall(rhs))
{
return lhs / rhs;
}
return fallback;
}
}
}

7
EleCho.WpfSuite/Themes/Generic.xaml

@ -1,7 +0,0 @@ @@ -1,7 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/EleCho.WpfSuite;component/Controls/ListBoxResources.xaml"/>
<ResourceDictionary Source="pack://application:,,,/EleCho.WpfSuite;component/Controls/ListViewResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

26
EleCho.WpfSuite/ValueConverters/FallbackConverter.cs

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
using System;
using System.Globalization;
using System.Windows;
namespace EleCho.WpfSuite
{
/// <summary>
/// Fallback between multiple values, return the first non-null value
/// </summary>
public class FallbackConverter : SingletonMultiValueConverterBase<FallbackConverter>
{
/// <inheritdoc/>
public override object? Convert(object?[] values, Type targetType, object? parameter, CultureInfo culture)
{
foreach (var value in values)
{
if (value is not null &&
value != DependencyProperty.UnsetValue)
return value;
}
return null;
}
}
}

22
EleCho.WpfSuite/ValueConverters/MultiValueConverterBase.cs

@ -1,22 +0,0 @@ @@ -1,22 +0,0 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace EleCho.WpfSuite
{
/// <summary>
/// Base class of multi value converter
/// </summary>
/// <typeparam name="TSelf"></typeparam>
public abstract class MultiValueConverterBase<TSelf> : IMultiValueConverter
{
/// <inheritdoc/>
public abstract object? Convert(object?[] values, Type targetType, object? parameter, CultureInfo culture);
/// <inheritdoc/>
public virtual object?[] ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

17
EleCho.WpfSuite/ValueConverters/SingletonMultiValueConverterBase.cs

@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
namespace EleCho.WpfSuite
{
/// <summary>
/// Base class of singleton multi value converter
/// </summary>
/// <typeparam name="TSelf"></typeparam>
public abstract class SingletonMultiValueConverterBase<TSelf> : MultiValueConverterBase<TSelf>
where TSelf : SingletonMultiValueConverterBase<TSelf>, new()
{
private static TSelf? _instance = null;
/// <summary>
/// Get an instance of <typeparamref name="TSelf"/>
/// </summary>
public static TSelf Instance => _instance ?? new();
}
}

10
ILSpy.sln

@ -38,7 +38,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSha @@ -38,7 +38,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSha
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.BamlDecompiler", "ICSharpCode.BamlDecompiler\ICSharpCode.BamlDecompiler.csproj", "{81A30182-3378-4952-8880-F44822390040}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EleCho.WpfSuite", "EleCho.WpfSuite\EleCho.WpfSuite.csproj", "{486469B9-51AF-43D0-ABCE-F5FA7E5FBE4C}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibScrollingOptimization", "LibScrollingOptimization\LibScrollingOptimization.csproj", "{376D29B0-38FE-4517-A1A2-A54FBFEFF56C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -102,10 +102,10 @@ Global @@ -102,10 +102,10 @@ Global
{81A30182-3378-4952-8880-F44822390040}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.Build.0 = Release|Any CPU
{486469B9-51AF-43D0-ABCE-F5FA7E5FBE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{486469B9-51AF-43D0-ABCE-F5FA7E5FBE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{486469B9-51AF-43D0-ABCE-F5FA7E5FBE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{486469B9-51AF-43D0-ABCE-F5FA7E5FBE4C}.Release|Any CPU.Build.0 = Release|Any CPU
{376D29B0-38FE-4517-A1A2-A54FBFEFF56C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{376D29B0-38FE-4517-A1A2-A54FBFEFF56C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{376D29B0-38FE-4517-A1A2-A54FBFEFF56C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{376D29B0-38FE-4517-A1A2-A54FBFEFF56C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

7
ILSpy/Controls/ZoomScrollViewer.cs

@ -30,7 +30,7 @@ using System.Windows.Media; @@ -30,7 +30,7 @@ using System.Windows.Media;
namespace ICSharpCode.ILSpy.Controls
{
public class ZoomScrollViewer : EleCho.WpfSuite.ScrollViewer
public class ZoomScrollViewer : ScrollViewer
{
static ZoomScrollViewer()
{
@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Controls @@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Controls
z.ComputedZoomButtonCollapsed = (z.AlwaysShowZoomButtons == false) && (z.CurrentZoom == 1.0);
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
if (!e.Handled && Keyboard.Modifiers == ModifierKeys.Control && MouseWheelZoom)
{
@ -165,7 +165,8 @@ namespace ICSharpCode.ILSpy.Controls @@ -165,7 +165,8 @@ namespace ICSharpCode.ILSpy.Controls
e.Handled = true;
}
base.OnMouseWheel(e);
base.OnPreviewMouseWheel(e);
}
internal static double RoundToOneIfClose(double val)

2
ILSpy/ILSpy.csproj

@ -84,9 +84,9 @@ @@ -84,9 +84,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EleCho.WpfSuite\EleCho.WpfSuite.csproj" />
<ProjectReference Include="..\ICSharpCode.ILSpyX\ICSharpCode.ILSpyX.csproj" />
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj" />
<ProjectReference Include="..\LibScrollingOptimization\LibScrollingOptimization.csproj" />
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" />
</ItemGroup>

5
ILSpy/MainWindow.xaml

@ -21,6 +21,8 @@ @@ -21,6 +21,8 @@
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:scroll="clr-namespace:LibScrollingOptimization;assembly=LibScrollingOptimization"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}"
>
<Window.Resources>
@ -34,6 +36,9 @@ @@ -34,6 +36,9 @@
AllowDropOrder="True"
AllowDrop="True"
BorderThickness="0" Visibility="Visible">
<behaviors:Interaction.Behaviors>
<scroll:SmoothScrollingBehavior/>
</behaviors:Interaction.Behaviors>
<tv:SharpTreeView.ItemContainerStyle>
<Style TargetType="tv:SharpTreeViewItem">

18
ILSpy/Options/DecompilerSettingsPanel.xaml

@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options"
xmlns:ws="https://schemas.elecho.dev/wpfsuite">
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:scroll="clr-namespace:LibScrollingOptimization;assembly=LibScrollingOptimization">
<UserControl.Resources>
<CollectionViewSource x:Key="SettingsCollection" Source="{Binding Settings}">
<CollectionViewSource.GroupDescriptions>
@ -21,18 +22,21 @@ @@ -21,18 +22,21 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Margin="3" Grid.ColumnSpan="3" TextWrapping="Wrap" Text="{x:Static properties:Resources.DecompilerSettingsPanelLongText}" />
<ws:ListBox Grid.Row="1"
<ListBox Grid.Row="1"
ItemsSource="{Binding Source={StaticResource SettingsCollection}}"
Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
Padding="-1">
<ws:ListBox.ItemContainerStyle>
<behaviors:Interaction.Behaviors>
<scroll:SmoothScrollingBehavior/>
</behaviors:Interaction.Behaviors>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
</Style>
</ws:ListBox.ItemContainerStyle>
<ws:ListBox.GroupStyle>
</ListBox.ItemContainerStyle>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
@ -57,12 +61,12 @@ @@ -57,12 +61,12 @@
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ws:ListBox.GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Margin="19,0,0,0" IsChecked="{Binding IsEnabled}" Content="{Binding Description}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ws:ListBox>
</ListBox>
</Grid>
</UserControl>

10
ILSpy/Options/DisplaySettingsPanel.xaml

@ -7,12 +7,16 @@ @@ -7,12 +7,16 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:ws="https://schemas.elecho.dev/wpfsuite"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:scroll="clr-namespace:LibScrollingOptimization;assembly=LibScrollingOptimization"
d:DataContext="{d:DesignInstance local:DisplaySettingsViewModel}">
<UserControl.Resources>
<local:FontSizeConverter x:Key="fontSizeConv" />
</UserControl.Resources>
<ws:ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<behaviors:Interaction.Behaviors>
<scroll:SmoothScrollingBehavior/>
</behaviors:Interaction.Behaviors>
<StackPanel Orientation="Vertical">
<DockPanel>
<Label DockPanel.Dock="Left" Content="{x:Static properties:Resources.DisplaySettingsPanel_Theme}" />
@ -106,5 +110,5 @@ @@ -106,5 +110,5 @@
</StackPanel>
</GroupBox>
</StackPanel>
</ws:ScrollViewer>
</ScrollViewer>
</UserControl>

7
ILSpy/Search/SearchPane.xaml

@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d"
xmlns:ws="https://schemas.elecho.dev/wpfsuite"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:scroll="clr-namespace:LibScrollingOptimization;assembly=LibScrollingOptimization"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
@ -40,11 +41,11 @@ @@ -40,11 +41,11 @@
</Grid>
</Border>
<ProgressBar x:Name="searchProgressBar" Grid.Row="1" BorderThickness="0" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<ListView Grid.Row="2" BorderThickness="0,1,0,0" HorizontalContentAlignment="Stretch" KeyDown="ListBox_KeyDown"
<ListView Grid.Row="2" BorderThickness="0,1,0,0" HorizontalContentAlignment="Stretch" KeyDown="ListBox_KeyDown"
MouseDoubleClick="ListBox_MouseDoubleClick" Name="listBox" SelectionMode="Single" controls:SortableGridViewColumn.SortMode="Automatic"
controls:GridViewColumnAutoSize.AutoWidth="40%;40%;20%" BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
ItemsSource="{Binding Results, ElementName=self}">
<ListView.View>
<ListView.View>
<GridView AllowsColumnReorder="False">
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Name}" SortBy="Name">
<controls:SortableGridViewColumn.CellTemplate>

10
ILSpy/TextView/DecompilerTextView.xaml

@ -1,13 +1,15 @@ @@ -1,13 +1,15 @@
<UserControl x:Class="ICSharpCode.ILSpy.TextView.DecompilerTextView" x:ClassModifier="public" x:Name="self"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.TextView"
xmlns:editing="clr-namespace:ICSharpCode.AvalonEdit.Editing;assembly=ICSharpCode.AvalonEdit"
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes">
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:scrolling="clr-namespace:LibScrollingOptimization;assembly=LibScrollingOptimization">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="boolToVisibility" />
<SolidColorBrush x:Key="waitAdornerBackgoundBrush" Color="{DynamicResource {x:Static SystemColors.WindowColorKey}}" Opacity=".75" />
@ -81,7 +83,11 @@ @@ -81,7 +83,11 @@
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
TextOptions.TextFormattingMode="{Binding CurrentZoom, ElementName=PART_ScrollViewer, Converter={x:Static local:ZoomLevelToTextFormattingModeConverter.Instance}}" />
TextOptions.TextFormattingMode="{Binding CurrentZoom, ElementName=PART_ScrollViewer, Converter={x:Static local:ZoomLevelToTextFormattingModeConverter.Instance}}" >
<behaviors:Interaction.Behaviors>
<scrolling:SmoothScrollingBehavior/>
</behaviors:Interaction.Behaviors>
</controls:ZoomScrollViewer>
<ControlTemplate.Triggers>
<Trigger Property="WordWrap"
Value="True">

14
LibScrollingOptimization/LibScrollingOptimization.csproj

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TomsToolbox.Wpf" />
</ItemGroup>
</Project>

2
EleCho.WpfSuite/Utilities/ScrollViewerUtils.cs → LibScrollingOptimization/ScrollViewerUtils.cs

@ -3,7 +3,7 @@ using System.Windows; @@ -3,7 +3,7 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace EleCho.WpfSuite
namespace LibScrollingOptimization
{
/// <summary>
/// ScrollViewer Utilities

166
EleCho.WpfSuite/Controls/ScrollViewer.cs → LibScrollingOptimization/SmoothScrollingBehavior.cs

@ -3,29 +3,41 @@ using System.Collections.Generic; @@ -3,29 +3,41 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace EleCho.WpfSuite
using TomsToolbox.Wpf;
using TomsToolbox.Wpf.Interactivity;
namespace LibScrollingOptimization
{
/// <inheritdoc/>
public class ScrollViewer : System.Windows.Controls.ScrollViewer
/// <summary>
///
/// </summary>
public class SmoothScrollingBehavior : FrameworkElementBehavior<Control>
{
static ScrollViewer()
private ScrollViewer? _scrollViewer;
private ScrollContentPresenter? _scrollContentPresenter;
private delegate bool GetBool(ScrollViewer scrollViewer);
private static readonly GetBool _propertyHandlesMouseWheelScrollingGetter;
private static readonly IEasingFunction _scrollingAnimationEase = new CubicEase() { EasingMode = EasingMode.EaseOut };
private const long _millisecondsBetweenTouchpadScrolling = 100;
private bool _animationRunning = false;
private int _lastScrollDelta = 0;
private int _lastVerticalScrollingDelta = 0;
private int _lastHorizontalScrollingDelta = 0;
private long _lastScrollingTick;
static SmoothScrollingBehavior()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollViewer), new FrameworkPropertyMetadata(typeof(ScrollViewer)));
#if NETCOREAPP
_propertyHandlesMouseWheelScrollingGetter = typeof(ScrollViewer)
@ -40,42 +52,67 @@ namespace EleCho.WpfSuite @@ -40,42 +52,67 @@ namespace EleCho.WpfSuite
#endif
}
private delegate bool GetBool(ScrollViewer scrollViewer);
private static readonly GetBool _propertyHandlesMouseWheelScrollingGetter;
private static readonly IEasingFunction _scrollingAnimationEase = new CubicEase() { EasingMode = EasingMode.EaseOut };
private const long _millisecondsBetweenTouchpadScrolling = 100;
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_ScrollInfo")]
static extern IScrollInfo GetScrollInfo(ScrollViewer scrollViewer);
private bool _animationRunning = false;
private int _lastScrollDelta = 0;
private int _lastVerticalScrollingDelta = 0;
private int _lastHorizontalScrollingDelta = 0;
private long _lastScrollingTick;
/// <inheritdoc />
protected override void OnAssociatedObjectLoaded()
{
base.OnAssociatedObjectLoaded();
_scrollViewer = AssociatedObject.VisualDescendantsAndSelf().OfType<ScrollViewer>().FirstOrDefault();
private FrameworkElement? _scrollContentPresenter;
if (_scrollViewer == null)
return;
/// <inheritdoc/>
public override void OnApplyTemplate()
_scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
_scrollContentPresenter = _scrollViewer.VisualDescendants().OfType<ScrollContentPresenter>().FirstOrDefault();
}
/// <inheritdoc />
protected override void OnAssociatedObjectUnloaded()
{
base.OnApplyTemplate();
base.OnAssociatedObjectUnloaded();
if (_scrollViewer == null)
return;
_scrollContentPresenter = GetTemplateChild("PART_ScrollContentPresenter") as FrameworkElement;
_scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel;
}
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (!ScrollWithWheelDelta)
{
return;
}
else
{
Debug.WriteLine(e.Delta);
CoreScrollWithWheelDelta(e);
}
}
private void CoreScrollWithWheelDelta(MouseWheelEventArgs e)
{
if (_scrollViewer == null || _scrollContentPresenter == null)
return;
if (e.Handled)
{
return;
}
if (!AlwaysHandleMouseWheelScrolling &&
!_propertyHandlesMouseWheelScrollingGetter.Invoke(this))
!_propertyHandlesMouseWheelScrollingGetter.Invoke(_scrollViewer))
{
return;
}
bool vertical = ExtentHeight > 0;
bool horizontal = ExtentWidth > 0;
bool vertical = _scrollViewer.ExtentHeight > 0;
bool horizontal = _scrollViewer.ExtentWidth > 0;
var tickCount = Environment.TickCount;
var isTouchpadScrolling =
@ -99,31 +136,31 @@ namespace EleCho.WpfSuite @@ -99,31 +136,31 @@ namespace EleCho.WpfSuite
if (vertical)
{
if (ScrollInfo is IScrollInfo scrollInfo)
if (GetScrollInfo(_scrollViewer) is IScrollInfo scrollInfo)
{
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
scrollDelta *= scrollInfo.ViewportHeight / (_scrollContentPresenter?.ActualHeight ?? ActualHeight);
scrollDelta *= scrollInfo.ViewportHeight / (_scrollContentPresenter?.ActualHeight ?? _scrollViewer.ActualHeight);
}
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastVerticalScrollingDelta);
var nowOffset = sameDirectionAsLast && _animationRunning ? VerticalOffsetTarget : VerticalOffset;
var nowOffset = sameDirectionAsLast && _animationRunning ? VerticalOffsetTarget : _scrollViewer.VerticalOffset;
var newOffset = nowOffset - scrollDelta;
if (newOffset < 0)
newOffset = 0;
if (newOffset > ScrollableHeight)
newOffset = ScrollableHeight;
if (newOffset > _scrollViewer.ScrollableHeight)
newOffset = _scrollViewer.ScrollableHeight;
SetValue(VerticalOffsetTargetPropertyKey, newOffset);
BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, null);
_scrollViewer.BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, null);
if (!EnableScrollingAnimation || isTouchpadScrolling)
{
ScrollToVerticalOffset(newOffset);
_scrollViewer.ScrollToVerticalOffset(newOffset);
}
else
{
var diff = newOffset - VerticalOffset;
var diff = newOffset - _scrollViewer.VerticalOffset;
var absDiff = Math.Abs(diff);
var duration = ScrollingAnimationDuration;
if (absDiff < Mouse.MouseWheelDeltaForOneLine)
@ -134,45 +171,45 @@ namespace EleCho.WpfSuite @@ -134,45 +171,45 @@ namespace EleCho.WpfSuite
DoubleAnimation doubleAnimation = new DoubleAnimation() {
EasingFunction = _scrollingAnimationEase,
Duration = duration,
From = VerticalOffset,
From = _scrollViewer.VerticalOffset,
To = newOffset,
};
doubleAnimation.Completed += DoubleAnimation_Completed;
_animationRunning = true;
BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace);
_scrollViewer.BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace);
}
_lastVerticalScrollingDelta = e.Delta;
}
else if (horizontal)
{
if (ScrollInfo is IScrollInfo scrollInfo)
if (GetScrollInfo(_scrollViewer) is IScrollInfo scrollInfo)
{
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
scrollDelta *= scrollInfo.ViewportWidth / (_scrollContentPresenter?.ActualWidth ?? ActualWidth);
scrollDelta *= scrollInfo.ViewportWidth / (_scrollContentPresenter?.ActualWidth ?? _scrollViewer.ActualWidth);
}
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastHorizontalScrollingDelta);
var nowOffset = sameDirectionAsLast && _animationRunning ? HorizontalOffsetTarget : HorizontalOffset;
var nowOffset = sameDirectionAsLast && _animationRunning ? HorizontalOffsetTarget : _scrollViewer.HorizontalOffset;
var newOffset = nowOffset - scrollDelta;
if (newOffset < 0)
newOffset = 0;
if (newOffset > ScrollableWidth)
newOffset = ScrollableWidth;
if (newOffset > _scrollViewer.ScrollableWidth)
newOffset = _scrollViewer.ScrollableWidth;
SetValue(HorizontalOffsetTargetPropertyKey, newOffset);
BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, null);
_scrollViewer.BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, null);
if (!EnableScrollingAnimation || isTouchpadScrolling)
{
ScrollToHorizontalOffset(newOffset);
_scrollViewer.ScrollToHorizontalOffset(newOffset);
}
else
{
var diff = newOffset - HorizontalOffset;
var diff = newOffset - _scrollViewer.HorizontalOffset;
var absDiff = Math.Abs(diff);
var duration = ScrollingAnimationDuration;
if (absDiff < Mouse.MouseWheelDeltaForOneLine)
@ -183,14 +220,14 @@ namespace EleCho.WpfSuite @@ -183,14 +220,14 @@ namespace EleCho.WpfSuite
DoubleAnimation doubleAnimation = new DoubleAnimation() {
EasingFunction = _scrollingAnimationEase,
Duration = duration,
From = HorizontalOffset,
From = _scrollViewer.HorizontalOffset,
To = newOffset,
};
doubleAnimation.Completed += DoubleAnimation_Completed;
_animationRunning = true;
BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace);
_scrollViewer.BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace);
}
_lastHorizontalScrollingDelta = e.Delta;
@ -207,21 +244,6 @@ namespace EleCho.WpfSuite @@ -207,21 +244,6 @@ namespace EleCho.WpfSuite
_animationRunning = false;
}
/// <inheritdoc/>
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
if (!ScrollWithWheelDelta)
{
base.OnMouseWheel(e);
}
else
{
Debug.WriteLine(e.Delta);
CoreScrollWithWheelDelta(e);
}
}
/// <summary>
/// The horizontal offset of scrolling target
/// </summary>
@ -297,13 +319,13 @@ namespace EleCho.WpfSuite @@ -297,13 +319,13 @@ namespace EleCho.WpfSuite
/// The key needed set a read-only property
/// </summary>
public static readonly DependencyPropertyKey HorizontalOffsetTargetPropertyKey =
DependencyProperty.RegisterReadOnly(nameof(HorizontalOffsetTarget), typeof(double), typeof(ScrollViewer), new PropertyMetadata(0.0));
DependencyProperty.RegisterReadOnly(nameof(HorizontalOffsetTarget), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(0.0));
/// <summary>
/// The key needed set a read-only property
/// </summary>
public static readonly DependencyPropertyKey VerticalOffsetTargetPropertyKey =
DependencyProperty.RegisterReadOnly(nameof(VerticalOffsetTarget), typeof(double), typeof(ScrollViewer), new PropertyMetadata(0.0));
DependencyProperty.RegisterReadOnly(nameof(VerticalOffsetTarget), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(0.0));
/// <summary>
/// The key needed set a read-only property
@ -405,40 +427,40 @@ namespace EleCho.WpfSuite @@ -405,40 +427,40 @@ namespace EleCho.WpfSuite
/// The DependencyProperty of <see cref="ScrollWithWheelDelta"/> property.
/// </summary>
public static readonly DependencyProperty ScrollWithWheelDeltaProperty =
DependencyProperty.RegisterAttached(nameof(ScrollWithWheelDelta), typeof(bool), typeof(ScrollViewer),
DependencyProperty.RegisterAttached(nameof(ScrollWithWheelDelta), typeof(bool), typeof(SmoothScrollingBehavior),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
/// <summary>
/// The DependencyProperty of <see cref="EnableScrollingAnimation"/> property.
/// </summary>
public static readonly DependencyProperty EnableScrollingAnimationProperty =
DependencyProperty.RegisterAttached(nameof(EnableScrollingAnimation), typeof(bool), typeof(ScrollViewer),
DependencyProperty.RegisterAttached(nameof(EnableScrollingAnimation), typeof(bool), typeof(SmoothScrollingBehavior),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
/// <summary>
/// The DependencyProperty of <see cref="ScrollingAnimationDuration"/> property.
/// </summary>
public static readonly DependencyProperty ScrollingAnimationDurationProperty =
DependencyProperty.RegisterAttached(nameof(ScrollingAnimationDuration), typeof(Duration), typeof(ScrollViewer),
DependencyProperty.RegisterAttached(nameof(ScrollingAnimationDuration), typeof(Duration), typeof(SmoothScrollingBehavior),
new FrameworkPropertyMetadata(new Duration(TimeSpan.FromMilliseconds(250)), FrameworkPropertyMetadataOptions.Inherits), ValidateScrollingAnimationDuration);
/// <summary>
/// The DependencyProperty of <see cref="AlwaysHandleMouseWheelScrolling"/> property
/// </summary>
public static readonly DependencyProperty AlwaysHandleMouseWheelScrollingProperty =
DependencyProperty.RegisterAttached(nameof(AlwaysHandleMouseWheelScrolling), typeof(bool), typeof(ScrollViewer), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
DependencyProperty.RegisterAttached(nameof(AlwaysHandleMouseWheelScrolling), typeof(bool), typeof(SmoothScrollingBehavior), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
/// <summary>
/// The DependencyProperty of <see cref="MouseScrollDeltaFactor"/> property
/// </summary>
public static readonly DependencyProperty MouseScrollDeltaFactorProperty =
DependencyProperty.Register(nameof(MouseScrollDeltaFactor), typeof(double), typeof(ScrollViewer), new PropertyMetadata(1.0));
DependencyProperty.Register(nameof(MouseScrollDeltaFactor), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(1.0));
/// <summary>
/// The DependencyProperty of <see cref="TouchpadScrollDeltaFactor"/> property
/// </summary>
public static readonly DependencyProperty TouchpadScrollDeltaFactorProperty =
DependencyProperty.Register(nameof(TouchpadScrollDeltaFactor), typeof(double), typeof(ScrollViewer), new PropertyMetadata(1.0));
DependencyProperty.Register(nameof(TouchpadScrollDeltaFactor), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(1.0));
private static bool ValidateScrollingAnimationDuration(object value)
=> value is Duration duration && duration.HasTimeSpan;

4
SharpTreeView/ICSharpCode.TreeView.csproj

@ -25,8 +25,4 @@ @@ -25,8 +25,4 @@
<PackageReference Include="TomsToolbox.Wpf.Styles" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EleCho.WpfSuite\EleCho.WpfSuite.csproj" />
</ItemGroup>
</Project>

2
SharpTreeView/SharpTreeView.cs

@ -30,7 +30,7 @@ using System.Windows.Threading; @@ -30,7 +30,7 @@ using System.Windows.Threading;
namespace ICSharpCode.TreeView
{
public class SharpTreeView : EleCho.WpfSuite.ListView
public class SharpTreeView : ListView
{
static SharpTreeView()
{

6
SharpTreeView/Themes/Generic.xaml

@ -86,15 +86,15 @@ @@ -86,15 +86,15 @@
BorderThickness="1"
BorderBrush="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
Padding="0 1 2 0">
<ws:ScrollViewer Name="PART_ContentHost" />
<ScrollViewer Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Default:SharpTreeView}"
BasedOn="{StaticResource {x:Type ws:ListView}}">
<Style TargetType="{x:Type Default:SharpTreeView}"
BasedOn="{StaticResource {x:Static styles:ResourceKeys.ListBoxStyle}}">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="ShowRoot"

Loading…
Cancel
Save