Skip to content

Commit

Permalink
CHange startup procedure to load image first and the rest later #125
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruben2776 committed Dec 16, 2023
1 parent 1ae5ad3 commit ed95e6b
Show file tree
Hide file tree
Showing 20 changed files with 424 additions and 140 deletions.
132 changes: 132 additions & 0 deletions src/PicView.Core/Calculations/ImageSizeCalculationHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
namespace PicView.Core.Calculations;

/// <summary>
/// Provides methods for calculating image size based on monitor dimensions, rotation angle, and stretch parameter.
/// </summary>
public static class ImageSizeCalculationHelper
{
/// <summary>
/// Represents the dimensions of an image.
/// </summary>
public struct ImageSize
{
/// <summary>
/// Gets the width of the image.
/// </summary>
public double Width { get; private set; }

/// <summary>
/// Gets the height of the image.
/// </summary>
public double Height { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="ImageSize"/> struct with the specified width and height.
/// </summary>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
public ImageSize(double width, double height)
{
Width = width;
Height = height;
}
}

/// <summary>
/// Calculates the adjusted image size based on specified parameters.
/// </summary>
/// <param name="width">The original width of the image.</param>
/// <param name="height">The original height of the image.</param>
/// <param name="monitorWidth">The width of the monitor.</param>
/// <param name="monitorHeight">The height of the monitor.</param>
/// <param name="rotationAngle">The rotation angle of the image in degrees.</param>
/// <param name="stretch">A boolean indicating whether to stretch the image to fit the container.</param>
/// <param name="padding">The padding applied to the image.</param>
/// <param name="dpiScaling">The DPI scaling factor of the monitor.</param>
/// <param name="fullscreen">A boolean indicating whether the image is displayed in fullscreen mode.</param>
/// <param name="uiTopSize">The size of the top UI element.</param>
/// <param name="uiBottomSize">The size of the bottom UI element.</param>
/// <param name="galleryHeight">The height of the gallery.</param>
/// <param name="autoFit">A boolean indicating whether to automatically fit the image within the monitor.</param>
/// <param name="containerWidth">The width of the container.</param>
/// <param name="containerHeight">The height of the container.</param>
/// <param name="scrollEnabled">A boolean indicating whether scrolling is enabled.</param>
/// <returns>An <see cref="ImageSize"/> struct representing the adjusted image size.</returns>
public static ImageSize GetImageSize(double width,
double height,
double monitorWidth,
double monitorHeight,
int rotationAngle,
bool stretch,
double padding,
double dpiScaling,
bool fullscreen,
double uiTopSize,
double uiBottomSize,
double galleryHeight,
bool autoFit,
double containerWidth,
double containerHeight,
bool scrollEnabled)
{
if (width <= 0 || height <= 0 || rotationAngle > 360 || rotationAngle < 0)
{
// Invalid input, return zero-sized image
return new ImageSize(0, 0);
}

double aspectRatio;
double maxWidth, maxHeight;

var borderSpaceHeight = fullscreen ? 0 : uiTopSize + uiBottomSize + galleryHeight;
var borderSpaceWidth = fullscreen ? 0 : padding;

var workAreaWidth = (monitorWidth * dpiScaling) - borderSpaceWidth;
var workAreaHeight = (monitorHeight * dpiScaling) - borderSpaceHeight;

if (autoFit)
{
maxWidth = stretch ? workAreaWidth : Math.Min(workAreaWidth - padding, width);
maxHeight = stretch ? workAreaHeight : Math.Min(workAreaHeight - padding, height);
}
else
{
maxWidth = stretch ? containerWidth : Math.Min(containerWidth, width);
if (scrollEnabled)
{
maxHeight = stretch ? containerHeight : height;
}
else
{
maxHeight = stretch
? containerHeight - galleryHeight
: Math.Min(containerHeight - galleryHeight, height);
}
}

// aspect ratio calculation
switch (rotationAngle)
{
case 0:
case 180:
aspectRatio = Math.Min(maxWidth / width, maxHeight / height);
break;

case 90:
case 270:
aspectRatio = Math.Min(maxWidth / height, maxHeight / width);
break;

default:
var rotationRadians = rotationAngle * Math.PI / 180;
var newWidth = Math.Abs(width * Math.Cos(rotationRadians)) +
Math.Abs(height * Math.Sin(rotationRadians));
var newHeight = Math.Abs(width * Math.Sin(rotationRadians)) +
Math.Abs(height * Math.Cos(rotationRadians));
aspectRatio = Math.Min(maxWidth / newWidth, maxHeight / newHeight);
break;
}

return new ImageSize(width * aspectRatio, height * aspectRatio);
}
}
2 changes: 1 addition & 1 deletion src/PicView.WPF/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
x:Class="PicView.WPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="/Views/Windows/MainWindow.xaml">
StartupUri="/Views/Windows/Startup-Window.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
Expand Down
4 changes: 4 additions & 0 deletions src/PicView.WPF/ChangeImage/ErrorHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ internal static class ErrorHandling
/// <returns>True if not intended to change image or index is not valid</returns>
internal static bool CheckOutOfRange()
{
if (Pics is null)
{
return true;
}
var value = true;
ConfigureWindows.GetMainWindow.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
Expand Down
76 changes: 42 additions & 34 deletions src/PicView.WPF/ChangeImage/QuickLoad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using XamlAnimatedGif;
using static PicView.WPF.ChangeImage.LoadPic;
Expand All @@ -25,29 +26,29 @@ internal static class QuickLoad
/// Load Image from blank values and show loading preview
/// </summary>
/// <param name="file"></param>
internal static async Task QuickLoadAsync(string file) => await Task.Run(async () =>
internal static async Task QuickLoadAsync(string file, FileInfo? fileInfo = null, BitmapSource? preparedSource = null) => await Task.Run(async () =>
{
var mainWindow = ConfigureWindows.GetMainWindow;
var fileInfo = new FileInfo(file);
if (!fileInfo.Exists) // If not file, try to load if URL, base64 or directory
fileInfo ??= new FileInfo(file);
if (preparedSource is not null)
{
await LoadPicFromStringAsync(file, fileInfo).ConfigureAwait(false);
return;
}
if (!fileInfo.Exists) // If not file, try to load if URL, base64 or directory
{
await LoadPicFromStringAsync(file, fileInfo).ConfigureAwait(false);
return;
}
if (file.IsArchive()) // Handle if file exist and is archive
{
await LoadPicFromArchiveAsync(file).ConfigureAwait(false);
return;
if (file.IsArchive()) // Handle if file exist and is archive
{
await LoadPicFromArchiveAsync(file).ConfigureAwait(false);
return;
}
}
var bitmapSource = await Image2BitmapSource.ReturnBitmapSourceAsync(fileInfo).ConfigureAwait(false);
var bitmapSource = preparedSource ?? await Image2BitmapSource.ReturnBitmapSourceAsync(fileInfo).ConfigureAwait(false);
await mainWindow.MainImage.Dispatcher.InvokeAsync(() =>
{
mainWindow.MainImage.Source = bitmapSource;
FitImage(bitmapSource.Width, bitmapSource.Height);
}, DispatcherPriority.Send);
if (fileInfo.Extension.Equals(".gif", StringComparison.OrdinalIgnoreCase))
Expand All @@ -73,6 +74,10 @@ await mainWindow.Dispatcher.InvokeAsync(() =>
if (Settings.Default.IsBottomGalleryShown)
{
GalleryToggle.ShowBottomGallery();
}
if (preparedSource is not null)
{
FitImage(bitmapSource.Width, bitmapSource.Height);
}
}, DispatcherPriority.Normal);
Expand All @@ -87,32 +92,35 @@ await mainWindow.Dispatcher.InvokeAsync(() =>
if (Settings.Default.IsBottomGalleryShown)
{
try
_ = Task.Run(async () =>
{
await GalleryLoad.LoadAsync().ConfigureAwait(false);
// Update gallery selections
await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
try
{
await GalleryLoad.LoadAsync().ConfigureAwait(false);
// Update gallery selections
await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
{
// Select current item
GalleryNavigation.SetSelected(FolderIndex, true);
GalleryNavigation.SelectedGalleryItem = FolderIndex;
GalleryNavigation.ScrollToGalleryCenter();
});
}
catch (TaskCanceledException exception)
{
// Select current item
GalleryNavigation.SetSelected(FolderIndex, true);
GalleryNavigation.SelectedGalleryItem = FolderIndex;
GalleryNavigation.ScrollToGalleryCenter();
});
}
catch (TaskCanceledException exception)
{
#if DEBUG
Trace.WriteLine($"{nameof(QuickLoadAsync)} exception:\n{exception.Message}");
Trace.WriteLine($"{nameof(QuickLoadAsync)} exception:\n{exception.Message}");
#endif
if (ConfigureWindows.GetMainWindow.Visibility == Visibility.Hidden)
if (ConfigureWindows.GetMainWindow.Visibility == Visibility.Hidden)
{
Environment.Exit(0);
}
}
catch (Exception)
{
Environment.Exit(0);
//
}
}
catch (Exception)
{
//
}
});
}
// Add recent files, except when browsing archive
Expand Down
9 changes: 8 additions & 1 deletion src/PicView.WPF/ChangeTitlebar/EditTitleBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ internal static void Bar_PreviewMouseLeftButtonDown(object sender, MouseButtonEv
return;
}

WindowSizing.Move(sender, e);
try
{
WindowSizing.Move(sender, e);
}
catch (Exception)
{
//
}
Refocus();
e.Handled = true; // Disable text clicking
}
Expand Down
1 change: 0 additions & 1 deletion src/PicView.WPF/PicView.WPF.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PicView.Core\PicView.Core.csproj" />
<ProjectReference Include="..\PicView.Tools\PicView.Tools.csproj" />
<ProjectReference Include="..\XamlAnimatedGif\XamlAnimatedGif.csproj" />
</ItemGroup>
<ItemGroup>
Expand Down
23 changes: 15 additions & 8 deletions src/PicView.WPF/SystemIntegration/MonitorSize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,32 @@ private MonitorSize(double width, double height, double dpiScaling, Rect workAre
/// Gets the size and DPI scaling of the current monitor screen.
/// </summary>
/// <returns>A new instance of the <see cref="MonitorSize"/> struct representing the current monitor screen.</returns>
internal static MonitorSize GetMonitorSize()
internal static MonitorSize GetMonitorSize(Window? window)
{
if (Application.Current is null) // Fixes bug when closing window
if (Application.Current is null || window is null) // Fixes bug when closing window
return new MonitorSize(SystemParameters.WorkArea.Width, SystemParameters.WorkArea.Height, 1,
SystemParameters.WorkArea);

Screen? currentMonitor = null;
PresentationSource? source;
double dpiScaling = 0;
ConfigureWindows.GetMainWindow.Dispatcher.Invoke(DispatcherPriority.Send, () => // Avoid threading errors
window?.Dispatcher.Invoke(DispatcherPriority.Send, () => // Avoid threading errors
{
// Get the current monitor screen information
currentMonitor = Screen.FromHandle(new WindowInteropHelper(Application.Current.MainWindow!).Handle);
currentMonitor = Screen.FromHandle(new WindowInteropHelper(Application.Current.MainWindow ?? window).Handle);
// Find out if the app is being scaled by the monitor
source = PresentationSource.FromVisual(Application.Current.MainWindow!);
dpiScaling = source is { CompositionTarget: not null }
? source.CompositionTarget.TransformFromDevice.M11
: 1;
try
{
source = PresentationSource.FromVisual(window);
dpiScaling = source is { CompositionTarget: not null }
? source.CompositionTarget.TransformFromDevice.M11
: 1;
}
catch (Exception)
{
//
}
});

var monitorWidth = currentMonitor.Bounds.Width * dpiScaling;
Expand Down
2 changes: 1 addition & 1 deletion src/PicView.WPF/UILogic/ConfigureWindows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class ConfigureWindows
/// <summary>
/// The Main Window?
/// </summary>
internal static readonly MainWindow GetMainWindow = (MainWindow)Application.Current.MainWindow;
internal static MainWindow GetMainWindow { get; set; }

/// <summary>
/// Primary ContextMenu
Expand Down
14 changes: 12 additions & 2 deletions src/PicView.WPF/UILogic/DragAndDrop/Image_DragAndDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,17 @@ await LoadPic.LoadPicFromStringAsync((string)e.Data.GetData(DataFormats.StringFo
await Task.Run(async () =>
{
InitialPath = files[0];
await QuickLoad.QuickLoadAsync(files[0]).ConfigureAwait(false);
var fileInfo = new FileInfo(files[0]);
//detect whether its a directory or file
if (fileInfo.Attributes.HasFlag(FileAttributes.Directory))
{
await LoadPic.LoadPicFromFolderAsync(fileInfo).ConfigureAwait(false);
}
else
{
await QuickLoad.QuickLoadAsync(files[0], fileInfo).ConfigureAwait(false);
}
// Open additional windows if multiple files dropped
foreach (var file in files.Skip(1))
Expand Down Expand Up @@ -230,7 +240,7 @@ private static void UpdateDragOverlay(UIElement element)

try
{
_dropOverlay.UpdateContent(element);
_dropOverlay?.UpdateContent(element);
}
catch (Exception)
{
Expand Down
6 changes: 0 additions & 6 deletions src/PicView.WPF/UILogic/Loading/LoadControls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,5 @@ internal static void LoadQuickResize()
Trace.WriteLine(nameof(GetQuickResize) + " loaded ");
#endif
}

internal static void LoadSpinWaiter()
{
GetSpinWaiter = new SpinWaiter();
ConfigureWindows.GetMainWindow.ParentContainer.Children.Add(GetSpinWaiter);
}
}
}
Loading

0 comments on commit ed95e6b

Please sign in to comment.