Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Flow.Launcher/Flow.Launcher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="iNKORE.UI.WPF.Modern" Version="0.10.2.1" />
<PackageReference Include="iNKORE.UI.WPF.Modern" Version="0.10.1" />
<PackageReference Include="MdXaml" Version="1.27.0" />
<PackageReference Include="MdXaml.AnimatedGif" Version="1.27.0" />
<PackageReference Include="MdXaml.Html" Version="1.27.0" />
Expand Down
253 changes: 253 additions & 0 deletions Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
using iNKORE.UI.WPF.Modern.Controls;

Check warning on line 1 in Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`NKORE` is not a recognized word. (unrecognized-spelling)
using iNKORE.UI.WPF.Modern.Controls.Helpers;

Check warning on line 2 in Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`NKORE` is not a recognized word. (unrecognized-spelling)
using iNKORE.UI.WPF.Modern.Controls.Primitives;

Check warning on line 3 in Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`NKORE` is not a recognized word. (unrecognized-spelling)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Flow.Launcher.Resources.Controls
{
// TODO: Use IsScrollAnimationEnabled property in future: https://github.com/iNKORE-NET/UI.WPF.Modern/pull/347
public class CustomScrollViewerEx : ScrollViewer
{
private double LastVerticalLocation = 0;
private double LastHorizontalLocation = 0;

public CustomScrollViewerEx()
{
Loaded += OnLoaded;
var valueSource = DependencyPropertyHelper.GetValueSource(this, AutoPanningMode.IsEnabledProperty).BaseValueSource;
if (valueSource == BaseValueSource.Default)
{
AutoPanningMode.SetIsEnabled(this, true);
}
}

#region Orientation

public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register(
nameof(Orientation),
typeof(Orientation),
typeof(CustomScrollViewerEx),
new PropertyMetadata(Orientation.Vertical));

public Orientation Orientation
{
get => (Orientation)GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}

#endregion

#region AutoHideScrollBars

public static readonly DependencyProperty AutoHideScrollBarsProperty =
ScrollViewerHelper.AutoHideScrollBarsProperty
.AddOwner(
typeof(CustomScrollViewerEx),
new PropertyMetadata(true, OnAutoHideScrollBarsChanged));

public bool AutoHideScrollBars
{
get => (bool)GetValue(AutoHideScrollBarsProperty);
set => SetValue(AutoHideScrollBarsProperty, value);
}

private static void OnAutoHideScrollBarsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is CustomScrollViewerEx sv)
{
sv.UpdateVisualState();
}
}

#endregion

private void OnLoaded(object sender, RoutedEventArgs e)
{
LastVerticalLocation = VerticalOffset;
LastHorizontalLocation = HorizontalOffset;
UpdateVisualState(false);
}

/// <inheritdoc/>
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);

if (Style == null && ReadLocalValue(StyleProperty) == DependencyProperty.UnsetValue)
{
SetResourceReference(StyleProperty, typeof(ScrollViewer));
}
}

/// <inheritdoc/>
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
var Direction = GetDirection();
ScrollViewerBehavior.SetIsAnimating(this, true);

if (Direction == Orientation.Vertical)
{
if (ScrollableHeight > 0)
{
e.Handled = true;
}

var WheelChange = e.Delta * (ViewportHeight / 1.5) / ActualHeight;
var newOffset = LastVerticalLocation - WheelChange;

if (newOffset < 0)
{
newOffset = 0;
}

if (newOffset > ScrollableHeight)
{
newOffset = ScrollableHeight;
}

if (newOffset == LastVerticalLocation)
{
return;
}

ScrollToVerticalOffset(LastVerticalLocation);

ScrollToValue(newOffset, Direction);
LastVerticalLocation = newOffset;
}
else
{
if (ScrollableWidth > 0)
{
e.Handled = true;
}

var WheelChange = e.Delta * (ViewportWidth / 1.5) / ActualWidth;
var newOffset = LastHorizontalLocation - WheelChange;

if (newOffset < 0)
{
newOffset = 0;
}

if (newOffset > ScrollableWidth)
{
newOffset = ScrollableWidth;
}

if (newOffset == LastHorizontalLocation)
{
return;
}

ScrollToHorizontalOffset(LastHorizontalLocation);

ScrollToValue(newOffset, Direction);
LastHorizontalLocation = newOffset;
}
}

/// <inheritdoc/>
protected override void OnScrollChanged(ScrollChangedEventArgs e)
{
base.OnScrollChanged(e);
if (!ScrollViewerBehavior.GetIsAnimating(this))
{
LastVerticalLocation = VerticalOffset;
LastHorizontalLocation = HorizontalOffset;
}
}

private Orientation GetDirection()
{
var isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);

if (Orientation == Orientation.Horizontal)
{
return isShiftDown ? Orientation.Vertical : Orientation.Horizontal;
}
else
{
return isShiftDown ? Orientation.Horizontal : Orientation.Vertical;
}
}

/// <summary>
/// Causes the <see cref="ScrollViewerEx"/> to load a new view into the viewport using the specified offsets and zoom factor.
/// </summary>
/// <param name="horizontalOffset">A value between 0 and <see cref="ScrollViewer.ScrollableWidth"/> that specifies the distance the content should be scrolled horizontally.</param>
/// <param name="verticalOffset">A value between 0 and <see cref="ScrollViewer.ScrollableHeight"/> that specifies the distance the content should be scrolled vertically.</param>
/// <param name="zoomFactor">A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor.</param>
/// <returns><see langword="true"/> if the view is changed; otherwise, <see langword="false"/>.</returns>
public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor)
{
return ChangeView(horizontalOffset, verticalOffset, zoomFactor, false);
}

/// <summary>
/// Causes the <see cref="ScrollViewerEx"/> to load a new view into the viewport using the specified offsets and zoom factor, and optionally disables scrolling animation.
/// </summary>
/// <param name="horizontalOffset">A value between 0 and <see cref="ScrollViewer.ScrollableWidth"/> that specifies the distance the content should be scrolled horizontally.</param>
/// <param name="verticalOffset">A value between 0 and <see cref="ScrollViewer.ScrollableHeight"/> that specifies the distance the content should be scrolled vertically.</param>
/// <param name="zoomFactor">A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor.</param>
/// <param name="disableAnimation"><see langword="true"/> to disable zoom/pan animations while changing the view; otherwise, <see langword="false"/>. The default is false.</param>
/// <returns><see langword="true"/> if the view is changed; otherwise, <see langword="false"/>.</returns>
public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation)
{
if (disableAnimation)
{
if (horizontalOffset.HasValue)
{
ScrollToHorizontalOffset(horizontalOffset.Value);
}

if (verticalOffset.HasValue)
{
ScrollToVerticalOffset(verticalOffset.Value);
}
}
else
{
if (horizontalOffset.HasValue)
{
ScrollToHorizontalOffset(LastHorizontalLocation);
ScrollToValue(Math.Min(ScrollableWidth, horizontalOffset.Value), Orientation.Horizontal);
LastHorizontalLocation = horizontalOffset.Value;
}

if (verticalOffset.HasValue)
{
ScrollToVerticalOffset(LastVerticalLocation);
ScrollToValue(Math.Min(ScrollableHeight, verticalOffset.Value), Orientation.Vertical);
LastVerticalLocation = verticalOffset.Value;
}
}

return true;
}

private void ScrollToValue(double value, Orientation Direction)
{
if (Direction == Orientation.Vertical)
{
ScrollToVerticalOffset(value);
}
else
{
ScrollToHorizontalOffset(value);
}

ScrollViewerBehavior.SetIsAnimating(this, false);
}

private void UpdateVisualState(bool useTransitions = true)
{
var stateName = AutoHideScrollBars ? "NoIndicator" : "MouseIndicator";
VisualStateManager.GoToState(this, stateName, useTransitions);
}
}
}
12 changes: 5 additions & 7 deletions Flow.Launcher/Themes/Base.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,12 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ui:ScrollViewerEx
<cc:CustomScrollViewerEx
x:Name="ListBoxScrollViewer"
Focusable="False"
IsScrollAnimationEnabled="False"
RewriteWheelChange="True"
Template="{DynamicResource ScrollViewerControlTemplate}">
<ui:ScrollViewerEx.Style>
<Style TargetType="ui:ScrollViewerEx">
<cc:CustomScrollViewerEx.Style>
<Style TargetType="cc:CustomScrollViewerEx">
<Style.Triggers>
<Trigger Property="ComputedVerticalScrollBarVisibility" Value="Visible">
<Setter Property="Margin" Value="0 0 0 0" />
Expand All @@ -271,9 +269,9 @@
</Trigger>
</Style.Triggers>
</Style>
</ui:ScrollViewerEx.Style>
</cc:CustomScrollViewerEx.Style>
<VirtualizingStackPanel IsItemsHost="True" />
</ui:ScrollViewerEx>
</cc:CustomScrollViewerEx>
</ControlTemplate>
</Setter.Value>
</Setter>
Expand Down
10 changes: 5 additions & 5 deletions Flow.Launcher/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
},
"iNKORE.UI.WPF.Modern": {
"type": "Direct",
"requested": "[0.10.2.1, )",
"resolved": "0.10.2.1",
"contentHash": "nGwuuVul+TcLCTgPmaAZCc0fYFqUpCNZ8PiulVT3gZnsWt/AvxMZ0DSPpuyI/iRPc/NhFIg9lSIR7uaHWV0I/Q==",
"requested": "[0.10.1, )",
"resolved": "0.10.1",
"contentHash": "nRYmBosiL+42eUpLbHeqP7qJqtp5EpzuIMZTpvq4mFV33VB/JjkFg1y82gk50pjkXlAQWDvRyrfSAmPR5AM+3g==",
"dependencies": {
"iNKORE.UI.WPF": "1.2.8"
}
Expand Down Expand Up @@ -390,7 +390,7 @@
"Microsoft.Extensions.Primitives": "9.0.9"
}
},
"Microsoft.Extensions.FileSystemGlobbing": {

Check warning on line 393 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`Globbing` is not a recognized word. (unrecognized-spelling)
"type": "Transitive",
"resolved": "9.0.9",
"contentHash": "iQAgORaVIlkhcpxFnVEfjqNWfQCwBEEH7x2IanTwGafA6Tb4xiBoDWySTxUo3MV2NUV/PmwS/8OhT/elPnJCnw=="
Expand Down Expand Up @@ -660,12 +660,12 @@
"resolved": "3.0.0",
"contentHash": "IEghs0QqWsQYH0uUmvIl0Ye6RaebWRh38eB6ToOkDnQucTYRGFOgtig0gSxlwCszTilYFz3n1ZuY762x+kDR3A=="
},
"NHotkey.Wpf": {

Check warning on line 663 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`NHotkey` is not a recognized word. (unrecognized-spelling)
"type": "Transitive",
"resolved": "3.0.0",
"contentHash": "BIUKlhTG5KtFf9OQzWvkmVmktt5/FFj6AOEgag8Uf0R2YdZt5ajUzs3sVskcJcT2TztWlEHKQr1jFj3KQ0D9Nw==",
"dependencies": {
"NHotkey": "3.0.0"

Check warning on line 668 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`NHotkey` is not a recognized word. (unrecognized-spelling)
}
},
"NLog": {
Expand All @@ -673,12 +673,12 @@
"resolved": "6.0.4",
"contentHash": "Xr+lIk1ZlTTFXEqnxQVLxrDqZlt2tm5X+/AhJbaY2emb/dVtGDiU5QuEtj3gHtwV/SWlP/rJ922I/BPuOJXlRw=="
},
"NLog.OutputDebugString": {

Check warning on line 676 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`NLog` is not a recognized word. (unrecognized-spelling)
"type": "Transitive",
"resolved": "6.0.4",
"contentHash": "TOP2Ap9BbE98B/l/TglnguowOD0rXo8B/20xAgvj9shO/kf6IJ5M4QMhVxq72mrneJ/ANhHY7Jcd+xJbzuI5PA==",
"dependencies": {
"NLog": "6.0.4"

Check warning on line 681 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`NLog` is not a recognized word. (unrecognized-spelling)
}
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
Expand Down Expand Up @@ -736,7 +736,7 @@
"resolved": "4.3.0",
"contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
"dependencies": {
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",

Check warning on line 739 in Flow.Launcher/packages.lock.json

View workflow job for this annotation

GitHub Actions / Check Spelling

`debian` is not a recognized word. (unrecognized-spelling)
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
Expand Down Expand Up @@ -1619,7 +1619,7 @@
"FSharp.Core": "[9.0.303, )",
"Flow.Launcher.Infrastructure": "[1.0.0, )",
"Flow.Launcher.Localization": "[0.0.6, )",
"Flow.Launcher.Plugin": "[5.1.0, )",
"Flow.Launcher.Plugin": "[5.0.0, )",
"Meziantou.Framework.Win32.Jobs": "[3.4.5, )",
"Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
"SemanticVersioning": "[3.0.0, )",
Expand All @@ -1634,7 +1634,7 @@
"BitFaster.Caching": "[2.5.4, )",
"CommunityToolkit.Mvvm": "[8.4.0, )",
"Flow.Launcher.Localization": "[0.0.6, )",
"Flow.Launcher.Plugin": "[5.1.0, )",
"Flow.Launcher.Plugin": "[5.0.0, )",
"InputSimulator": "[1.0.4, )",
"MemoryPack": "[1.21.4, )",
"Microsoft.VisualStudio.Threading": "[17.14.15, )",
Expand Down
Loading