diff --git a/Directory.Build.props b/Directory.Build.props
index 444044d..660064b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -5,7 +5,7 @@
disable
enable
Copyright © Mihnea Rădulescu 2017 - 2024
- 1.2024.07.16
+ 1.2024.07.17
$(AssemblyVersion)
embedded
diff --git a/ImageFanReloaded.Core/Collections/Implementation/CollectionExtensions.cs b/ImageFanReloaded.Core/Collections/Implementation/CollectionExtensions.cs
index d25a24e..64df339 100644
--- a/ImageFanReloaded.Core/Collections/Implementation/CollectionExtensions.cs
+++ b/ImageFanReloaded.Core/Collections/Implementation/CollectionExtensions.cs
@@ -4,9 +4,6 @@ namespace ImageFanReloaded.Core.Collections.Implementation;
public static class CollectionExtensions
{
- public static bool IsIndexWithinBounds(this ICollection collection, int index)
- => 0 <= index && index < collection.Count;
-
public static bool IsIndexWithinBounds(this IReadOnlyCollection collection, int index)
- => 0 <= index && index < collection.Count;
+ => index >= 0 && index < collection.Count;
}
diff --git a/ImageFanReloaded.Core/Controls/IContentTabItem.cs b/ImageFanReloaded.Core/Controls/IContentTabItem.cs
index af836ee..e1e50c3 100644
--- a/ImageFanReloaded.Core/Controls/IContentTabItem.cs
+++ b/ImageFanReloaded.Core/Controls/IContentTabItem.cs
@@ -48,6 +48,4 @@ public interface IContentTabItem
void SetImageStatusBarText(string imageStatusBarText);
void SaveMatchingTreeViewItem(FileSystemEntryInfo selectedFileSystemEntryInfo);
-
- bool IsThumbnailScrollViewerFocused { get; }
}
diff --git a/ImageFanReloaded.Core/Keyboard/Key.cs b/ImageFanReloaded.Core/Keyboard/Key.cs
index 46e28ca..d31de6f 100644
--- a/ImageFanReloaded.Core/Keyboard/Key.cs
+++ b/ImageFanReloaded.Core/Keyboard/Key.cs
@@ -27,5 +27,8 @@ public enum Key
I,
Plus,
- Minus
+ Minus,
+
+ PageUp,
+ PageDown
}
diff --git a/ImageFanReloaded.Core/Settings/IGlobalParameters.cs b/ImageFanReloaded.Core/Settings/IGlobalParameters.cs
index 28febf8..c606021 100644
--- a/ImageFanReloaded.Core/Settings/IGlobalParameters.cs
+++ b/ImageFanReloaded.Core/Settings/IGlobalParameters.cs
@@ -37,6 +37,9 @@ public interface IGlobalParameters
Key PlusKey { get; }
Key MinusKey { get; }
+
+ Key PageUpKey { get; }
+ Key PageDownKey { get; }
bool IsBackwardNavigationKey(Key aKey);
bool IsForwardNavigationKey(Key aKey);
diff --git a/ImageFanReloaded.Core/Settings/Implementation/GlobalParametersBase.cs b/ImageFanReloaded.Core/Settings/Implementation/GlobalParametersBase.cs
index 63ebbf0..cdc0032 100644
--- a/ImageFanReloaded.Core/Settings/Implementation/GlobalParametersBase.cs
+++ b/ImageFanReloaded.Core/Settings/Implementation/GlobalParametersBase.cs
@@ -40,6 +40,9 @@ public abstract class GlobalParametersBase : IGlobalParameters
public Key PlusKey { get; }
public Key MinusKey { get; }
+
+ public Key PageUpKey { get; }
+ public Key PageDownKey { get; }
public bool IsBackwardNavigationKey(Key aKey) => _backwardNavigationKeys.Contains(aKey);
public bool IsForwardNavigationKey(Key aKey) => _forwardNavigationKeys.Contains(aKey);
@@ -109,6 +112,9 @@ protected GlobalParametersBase(
PlusKey = Key.Plus;
MinusKey = Key.Minus;
+
+ PageUpKey = Key.PageUp;
+ PageDownKey = Key.PageDown;
NameComparer = operatingSystemSettings.IsWindows
? new NaturalSortingComparer(StringComparer.InvariantCultureIgnoreCase)
diff --git a/ImageFanReloaded.Test/GlobalParametersTest.cs b/ImageFanReloaded.Test/GlobalParametersTest.cs
index 30c3132..8a94d83 100644
--- a/ImageFanReloaded.Test/GlobalParametersTest.cs
+++ b/ImageFanReloaded.Test/GlobalParametersTest.cs
@@ -76,6 +76,9 @@ public void GlobalParameters_IsCorrectlyInitialized()
_globalParameters.PlusKey.Should().NotBe(Key.None);
_globalParameters.MinusKey.Should().NotBe(Key.None);
+ _globalParameters.PageUpKey.Should().NotBe(Key.None);
+ _globalParameters.PageDownKey.Should().NotBe(Key.None);
+
_globalParameters.NameComparer.Should().NotBeNull();
_globalParameters.ImageFileExtensions.Should().NotBeEmpty();
diff --git a/ImageFanReloaded/Controls/ContentTabItem.axaml.cs b/ImageFanReloaded/Controls/ContentTabItem.axaml.cs
index 1149c26..c8ad286 100644
--- a/ImageFanReloaded/Controls/ContentTabItem.axaml.cs
+++ b/ImageFanReloaded/Controls/ContentTabItem.axaml.cs
@@ -3,7 +3,6 @@
using System.Linq;
using Avalonia;
using Avalonia.Controls;
-using ImageFanReloaded.Core.Collections.Implementation;
using ImageFanReloaded.Core.Controls;
using ImageFanReloaded.Core.CustomEventArgs;
using ImageFanReloaded.Core.DiscAccess;
@@ -45,8 +44,9 @@ public void EnableFolderTreeViewSelectedItemChanged()
public bool ShouldHandleControlKeyFunctions(KeyModifiers keyModifiers, Key keyPressing)
{
var shouldHandleKeyPressing = ShouldSwitchControlFocus(keyModifiers, keyPressing)
- || ShouldToggleRecursiveFolderAccess(keyModifiers, keyPressing)
- || ShouldHandleThumbnailSelection(keyPressing);
+ || ShouldToggleRecursiveFolderAccess(keyModifiers, keyPressing)
+ || ShouldHandleThumbnailSelection(keyPressing)
+ || ShouldHandleThumbnailScrolling(keyPressing);
return shouldHandleKeyPressing;
}
@@ -66,6 +66,10 @@ public void HandleControlKeyFunctions(KeyModifiers keyModifiers, Key keyPressing
BringThumbnailIntoView();
DisplayImage();
}
+ else if (ShouldHandleThumbnailScrolling(keyPressing))
+ {
+ HandleThumbnailScrolling(keyPressing);
+ }
}
public void SetFolderTreeViewSelectedItem()
@@ -214,13 +218,13 @@ public void SaveMatchingTreeViewItem(FileSystemEntryInfo selectedFileSystemEntry
}
}
}
-
- public bool IsThumbnailScrollViewerFocused => _thumbnailScrollViewer.IsFocused;
#region Private
private const string FakeTreeViewItemText = "Loading...";
+ private const int ThumbnailScrollAdvanceCount = 20;
+
private readonly IList _thumbnailBoxCollection;
private int _maxThumbnailIndex;
@@ -304,7 +308,7 @@ private void OnImageChanged(object? sender, ImageChangedEventArgs e)
var imageView = e.ImageView;
var increment = e.Increment;
- if (AdvanceSelectedThumbnailByIncrement(increment))
+ if (AdvanceFromSelectedThumbnail(increment))
{
imageView.SetImage(_selectedThumbnailBox!.ImageFile!, _folderAccessType.IsRecursive());
}
@@ -323,26 +327,37 @@ private void SelectThumbnailBox(IThumbnailBox thumbnailBox)
}
}
- private bool AdvanceSelectedThumbnailByIncrement(int increment)
+ private bool AdvanceFromSelectedThumbnail(int increment)
{
+ var canAdvanceToNewSelectedThumbnailIndex = false;
+
if (_selectedThumbnailBox is not null)
{
var newSelectedThumbnailIndex = _selectedThumbnailIndex + increment;
- if (_thumbnailBoxCollection.IsIndexWithinBounds(newSelectedThumbnailIndex))
+ if (newSelectedThumbnailIndex < 0)
+ {
+ newSelectedThumbnailIndex = 0;
+ }
+ else if (newSelectedThumbnailIndex >= _thumbnailBoxCollection.Count)
{
+ newSelectedThumbnailIndex = _thumbnailBoxCollection.Count - 1;
+ }
+
+ if (_selectedThumbnailIndex != newSelectedThumbnailIndex)
+ {
+ canAdvanceToNewSelectedThumbnailIndex = true;
+
UnselectThumbnail();
_selectedThumbnailIndex = newSelectedThumbnailIndex;
_selectedThumbnailBox = _thumbnailBoxCollection[_selectedThumbnailIndex];
SelectThumbnail();
-
- return true;
}
}
- return false;
+ return canAdvanceToNewSelectedThumbnailIndex;
}
private void BringThumbnailIntoView() => _selectedThumbnailBox?.BringThumbnailIntoView();
@@ -443,6 +458,17 @@ private bool ShouldHandleThumbnailSelection(Key keyPressing)
return false;
}
+ private bool ShouldHandleThumbnailScrolling(Key keyPressing)
+ {
+ if (_selectedThumbnailBox is not null &&
+ (keyPressing == GlobalParameters!.PageUpKey || keyPressing == GlobalParameters!.PageDownKey))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
private void SwitchControlFocus()
{
if (_folderTreeView.SelectedItem is null)
@@ -484,17 +510,32 @@ private void ToggleRecursiveFolderAccess(KeyModifiers keyModifiers)
RaiseFolderChangedEvent();
}
+ private void HandleThumbnailScrolling(Key keyPressing)
+ {
+ if (_selectedThumbnailBox is not null)
+ {
+ if (keyPressing == GlobalParameters!.PageUpKey)
+ {
+ AdvanceFromSelectedThumbnail(-ThumbnailScrollAdvanceCount);
+ }
+ else if (keyPressing == GlobalParameters!.PageDownKey)
+ {
+ AdvanceFromSelectedThumbnail(ThumbnailScrollAdvanceCount);
+ }
+ }
+ }
+
private void ThumbnailScrollViewerOnKeyPressing(object? sender, Avalonia.Input.KeyEventArgs e)
{
var keyPressing = e.Key.ToCoreKey();
if (GlobalParameters!.IsBackwardNavigationKey(keyPressing))
{
- AdvanceSelectedThumbnailByIncrement(-1);
+ AdvanceFromSelectedThumbnail(-1);
}
else if (GlobalParameters!.IsForwardNavigationKey(keyPressing))
{
- AdvanceSelectedThumbnailByIncrement(1);
+ AdvanceFromSelectedThumbnail(1);
}
e.Handled = true;
diff --git a/ImageFanReloaded/Controls/MainWindow.axaml.cs b/ImageFanReloaded/Controls/MainWindow.axaml.cs
index f748bf0..dff01df 100644
--- a/ImageFanReloaded/Controls/MainWindow.axaml.cs
+++ b/ImageFanReloaded/Controls/MainWindow.axaml.cs
@@ -265,7 +265,7 @@ private bool ShouldNavigateToNextTab(KeyModifiers keyModifiers, Key keyPressing)
private bool ShouldDisplayHelp(Key keyPressing) => keyPressing == GlobalParameters!.F1Key;
private bool ShouldAllowKeyPressingEventPropagation(IContentTabItem contentTabItem, Key keyPressing)
- => contentTabItem.IsThumbnailScrollViewerFocused || GlobalParameters!.IsNavigationKey(keyPressing);
+ => GlobalParameters!.IsNavigationKey(keyPressing);
private bool HasAtLeastOneContentTabItem()
{
diff --git a/ImageFanReloaded/Keyboard/KeyExtensions.cs b/ImageFanReloaded/Keyboard/KeyExtensions.cs
index b540b7e..d26676a 100644
--- a/ImageFanReloaded/Keyboard/KeyExtensions.cs
+++ b/ImageFanReloaded/Keyboard/KeyExtensions.cs
@@ -31,6 +31,9 @@ public static ImageFanReloaded.Core.Keyboard.Key ToCoreKey(this Avalonia.Input.K
Avalonia.Input.Key.Add => Core.Keyboard.Key.Plus,
Avalonia.Input.Key.OemMinus => Core.Keyboard.Key.Minus,
Avalonia.Input.Key.Subtract => Core.Keyboard.Key.Minus,
+
+ Avalonia.Input.Key.PageUp => Core.Keyboard.Key.PageUp,
+ Avalonia.Input.Key.PageDown => Core.Keyboard.Key.PageDown,
_ => Core.Keyboard.Key.None
};