Browse Source

Update maximized and fullscreen size calculations and toggle stretch #227

Refactor image sizing and fullscreen logic

- Simplified and modularized `CalculateWorkArea` and related methods.
- Introduced descriptive variables for settings and parameters to improve readability.
- Reorganized fullscreen handling in `WindowImpl` for better state management.
- Removed outdated or redundant methods (`Fix1to1`, `FixBorderLayout`, `InvokeOnUIThreadAsync`).
- Enhanced toggle functionality for `Stretch` to improve user experience.
Ruben 4 months ago
parent
commit
cf48d15502

+ 15 - 38
src/PicView.Avalonia.Win32/WindowImpl/Win32Window.cs

@@ -14,49 +14,41 @@ public static class Win32Window
 
     public static async Task Fullscreen(Window window, MainViewModel vm, bool saveSettings = true)
     {
+        // Need to set changing state to true, to prevent image resize subscription from firing
         IsChangingWindowState = true;
 
         // Save window size, so that restoring it will return to the same size and position
         WindowResizing.SaveSize(window);
 
         MenuManager.CloseMenus(vm);
+        
+        // Update settings
+        Settings.WindowProperties.Fullscreen = true;
 
         // Update view model properties
         vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
         vm.MainWindow.IsFullscreen.Value = true;
         vm.MainWindow.IsMaximized.Value = false;
         vm.MainWindow.CanResize.Value = false;
-
-        // Update settings
-        Settings.WindowProperties.Fullscreen = true;
-
-        // Apply fullscreen state
-        await InvokeOnUIThreadAsync(() => window.WindowState = WindowState.FullScreen);
-
+        
         // Hide interface in fullscreen
         HideInterface(vm);
-
+        
+        // Gallery needs to take up all space 
         vm.PicViewer.GalleryWidth.Value = double.NaN;
 
-        await WindowResizing.SetSizeAsync(vm);
-
-        // Center it, to make sure it is positioned correctly
-        CenterWindowOnScreen(window);
-
-        // Fixes https://github.com/Ruben2776/PicView/issues/226
-        await WindowFunctions.ResizeAndFixRenderingError(vm);
+        // Apply fullscreen state
+        await Dispatcher.UIThread.InvokeAsync(() => window.WindowState = WindowState.FullScreen, DispatcherPriority.Send);
 
-        // Fix 1to1 incorrect rendering and not filling the whole window #226
-        if (vm.PicViewer.PixelWidth.CurrentValue == vm.PicViewer.PixelHeight.CurrentValue)
+        var size = WindowResizing.GetSize(vm);
+        if (size.HasValue)
         {
-            WindowFunctions.Fix1to1(vm);
+            Dispatcher.UIThread.Post(() => WindowResizing.SetSize(size.Value, vm),  DispatcherPriority.Send);
         }
 
-        WindowFunctions.FixBorderLayout(vm);
-
+        // Reset changing state flag so subscription can fire again. Need to be delayed by dispatcher to not be misfired. 
         Dispatcher.UIThread.Post(() => IsChangingWindowState = false, DispatcherPriority.SystemIdle);
 
-
         if (saveSettings)
         {
             await SaveSettingsAsync().ConfigureAwait(false);
@@ -114,8 +106,8 @@ public static class Win32Window
         RestoreInterface(vm);
 
         // Update window state
-        await InvokeOnUIThreadAsync(() => window.WindowState = WindowState.Normal);
-
+        await Dispatcher.UIThread.InvokeAsync(() => window.WindowState = WindowState.Normal, DispatcherPriority.Send);
+        
         if (Settings.WindowProperties.AutoFit)
         {
             vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
@@ -282,20 +274,5 @@ public static class Win32Window
         }
     }
 
-    /// <summary>
-    /// Invokes an action on the UI thread
-    /// </summary>
-    private static async Task InvokeOnUIThreadAsync(Action action)
-    {
-        if (Dispatcher.UIThread.CheckAccess())
-        {
-            action();
-        }
-        else
-        {
-            await Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Render);
-        }
-    }
-
     #endregion Helpers
 }

+ 11 - 21
src/PicView.Avalonia/WindowBehavior/WindowFunctions.cs

@@ -164,24 +164,6 @@ public static class WindowFunctions
         }
     }
 
-    public static void Fix1to1(MainViewModel vm)
-    {
-        var size = WindowResizing.GetSize(vm);
-        if (size is null)
-        {
-            return;
-        }
-
-        WindowResizing.SetSize(size.Value, vm);
-        vm.ImageViewer.MainBorder.Height = size!.Value.Width;
-        vm.ImageViewer.MainBorder.Width = size.Value.Height;
-    }
-    
-    public static void FixBorderLayout(MainViewModel vm)
-    {
-        vm.ImageViewer.MainBorder.Height = double.NaN;
-    }
-
     public static void ShowMinimizedWindow(Window window)
     {
         window.BringIntoView();
@@ -283,10 +265,18 @@ public static class WindowFunctions
 
     public static async Task Stretch(MainViewModel vm)
     {
-        Settings.ImageScaling.StretchImage = true;
-        vm.GlobalSettings.IsStretched.Value = true;
+        if (Settings.ImageScaling.StretchImage)
+        {
+            Settings.ImageScaling.StretchImage = false;
+            vm.GlobalSettings.IsStretched.Value = false;
+        }
+        else
+        {
+            Settings.ImageScaling.StretchImage = true;
+            vm.GlobalSettings.IsStretched.Value = true;
+        }
+        //vm.ImageViewer.MainImage.InvalidateVisual();
         await WindowResizing.SetSizeAsync(vm);
-        vm.ImageViewer.MainImage.InvalidateVisual();
         await SaveSettingsAsync().ConfigureAwait(false);
     }
 

+ 42 - 13
src/PicView.Core/Sizing/ImageSizeCalculationHelper.cs

@@ -26,30 +26,43 @@ public static class ImageSizeCalculationHelper
             return ErrorImageSize(minWidth, minHeight, interfaceSize, containerWidth);
         }
 
-        var isFullscreen = Settings.WindowProperties.Fullscreen || Settings.WindowProperties.Maximized;
+        // When in fullscreen, we need to capture the entire screen estate
+        var isFullscreen = Settings.WindowProperties.Fullscreen;
+        // When in maximized mode, working area and interface size needs to be taken into consideration
+        var isMaximized = Settings.WindowProperties.Maximized;
+
+        var scrollEnabled = Settings.Zoom.ScrollEnabled;
+        var stretchImage = Settings.ImageScaling.StretchImage;
+        var autoFit = Settings.WindowProperties.AutoFit;
+        var showBottomGallery = Settings.Gallery.IsBottomGalleryShown;
+        var showInterface = Settings.UIProperties.ShowInterface;
+        var showGalleryInHiddenUI = Settings.Gallery.ShowBottomGalleryInHiddenUI;
+
 
         var borderSpaceHeight = CalculateBorderSpaceHeight(isFullscreen, uiTopSize, uiBottomSize, galleryHeight);
         var borderSpaceWidth = isFullscreen ? 0 : screenSize.Margin;
 
-        var workArea = CalculateWorkArea(screenSize, borderSpaceWidth, borderSpaceHeight);
+        var workArea = CalculateWorkArea(screenSize, isFullscreen, borderSpaceWidth, borderSpaceHeight, isMaximized);
+
+        var screenMargin = isFullscreen ? 0 : screenSize.Margin;
 
         var (maxAvailableWidth, maxAvailableHeight, adjustedContainerWidth, adjustedContainerHeight) =
-            CalculateMaxImageSize(Settings.Zoom.ScrollEnabled, Settings.ImageScaling.StretchImage,
-                Settings.WindowProperties.AutoFit,
-                workArea.width, workArea.height, screenSize.Margin, imageWidth, imageHeight, dpiScaling, galleryHeight,
+            CalculateMaxImageSize(scrollEnabled, stretchImage,
+                autoFit,
+                workArea.width, workArea.height, screenMargin, imageWidth, imageHeight, dpiScaling, galleryHeight,
                 containerWidth, containerHeight);
 
-        var margin = CalculateGalleryMargin(Settings.Gallery.IsBottomGalleryShown,
-            Settings.UIProperties.ShowInterface, Settings.Gallery.ShowBottomGalleryInHiddenUI, galleryHeight);
+        var margin = CalculateGalleryMargin(showBottomGallery,
+            showInterface, showGalleryInHiddenUI, galleryHeight);
 
         var aspectRatio =
             CalculateAspectRatio(rotationAngle, maxAvailableWidth, maxAvailableHeight, imageWidth, imageHeight);
 
         double displayedWidth, displayedHeight, scrollWidth, scrollHeight;
-        if (Settings.Zoom.ScrollEnabled)
+        if (scrollEnabled)
         {
             (displayedWidth, displayedHeight, scrollWidth, scrollHeight) = CalculateScrolledImageSize(
-                isFullscreen, Settings.WindowProperties.AutoFit, screenSize, imageWidth, imageHeight, aspectRatio,
+                isFullscreen, autoFit, screenSize, imageWidth, imageHeight, aspectRatio,
                 adjustedContainerWidth, adjustedContainerHeight, containerHeight, margin, dpiScaling
             );
         }
@@ -67,9 +80,23 @@ public static class ImageSizeCalculationHelper
             aspectRatio);
     }
 
-    private static (double width, double height) CalculateWorkArea(ScreenSize screenSize, double borderSpaceWidth,
-        double borderSpaceHeight)
-        => (screenSize.WorkingAreaWidth - borderSpaceWidth, screenSize.WorkingAreaHeight - borderSpaceHeight);
+    private static (double width, double height) CalculateWorkArea(ScreenSize screenSize, bool fullscreen,
+        double borderSpaceWidth, double borderSpaceHeight, bool maximized)
+    {
+        if (fullscreen)
+        {
+            return (screenSize.Width, screenSize.Height);
+        }
+
+        if (maximized)
+        {
+            return (screenSize.WorkingAreaWidth, screenSize.WorkingAreaHeight);
+        }
+
+        return (screenSize.WorkingAreaWidth - borderSpaceWidth,
+            screenSize.WorkingAreaHeight - borderSpaceHeight);
+    }
+
 
     private static double CalculateBorderSpaceHeight(bool fullscreen, double uiTop, double uiBottom, double gallery)
         => fullscreen ? 0 : uiTop + uiBottom + gallery;
@@ -89,6 +116,7 @@ public static class ImageSizeCalculationHelper
                 containerWidth, containerHeight);
         }
 
+        // ReSharper disable once InvertIf
         if (autoFit)
         {
             var mw = stretchImage ? workAreaWidth - margin : Math.Min(workAreaWidth - margin, width);
@@ -181,7 +209,8 @@ public static class ImageSizeCalculationHelper
         double containerWidth,
         double containerHeight)
     {
-        if (width <= 0 || height <= 0 || secondaryWidth <= 0 || secondaryHeight <= 0 || rotationAngle > MaxRotationAngle ||
+        if (width <= 0 || height <= 0 || secondaryWidth <= 0 || secondaryHeight <= 0 ||
+            rotationAngle > MaxRotationAngle ||
             rotationAngle < MinRotationAngle)
         {
             return ErrorImageSize(minWidth, minHeight, interfaceSize, containerWidth);