瀏覽代碼

Refactor to R3: move window-related properties to `MainWindowViewModel`. Update bindings across views, remove redundant properties and methods from `MainViewModel`, and enhance property structure for window management.

Ruben 3 月之前
父節點
當前提交
930be99710
共有 28 個文件被更改,包括 165 次插入203 次删除
  1. 4 4
      src/PicView.Avalonia.MacOS/Views/MacMainWindow.axaml
  2. 2 2
      src/PicView.Avalonia.MacOS/Views/OpenWithView.axaml
  3. 7 7
      src/PicView.Avalonia.MacOS/WindowImpl/MacOSWindow.cs
  4. 4 4
      src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml
  5. 2 2
      src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml
  6. 14 14
      src/PicView.Avalonia.Win32/WindowImpl/Win32Window.cs
  7. 5 10
      src/PicView.Avalonia/ColorManagement/BackgroundManager.cs
  8. 2 2
      src/PicView.Avalonia/Crop/CropFunctions.cs
  9. 2 2
      src/PicView.Avalonia/DragAndDrop/DragAndDropHelper.cs
  10. 1 1
      src/PicView.Avalonia/Input/MainKeyboardShortcuts.cs
  11. 2 2
      src/PicView.Avalonia/Navigation/ErrorHandling.cs
  12. 5 5
      src/PicView.Avalonia/Navigation/ImageLoader.cs
  13. 4 4
      src/PicView.Avalonia/Navigation/UpdateImage.cs
  14. 8 8
      src/PicView.Avalonia/SettingsManagement/SettingsUpdater.cs
  15. 6 6
      src/PicView.Avalonia/StartUp/StartUpHelper.cs
  16. 3 3
      src/PicView.Avalonia/UI/HideInterfaceLogic.cs
  17. 4 87
      src/PicView.Avalonia/ViewModels/MainViewModel.cs
  18. 52 0
      src/PicView.Avalonia/ViewModels/MainWindowViewModel.cs
  19. 4 6
      src/PicView.Avalonia/Views/AppearanceView.axaml.cs
  20. 5 5
      src/PicView.Avalonia/Views/BottomBar.axaml
  21. 2 2
      src/PicView.Avalonia/Views/ImageViewer.axaml
  22. 3 3
      src/PicView.Avalonia/Views/MainView.axaml
  23. 2 2
      src/PicView.Avalonia/Views/StartUpMenu.axaml
  24. 1 1
      src/PicView.Avalonia/Views/UC/DragDrogView.axaml.cs
  25. 3 3
      src/PicView.Avalonia/Views/UC/EditableTitlebar.axaml
  26. 2 2
      src/PicView.Avalonia/Views/UC/TitleTextBox.axaml
  27. 12 12
      src/PicView.Avalonia/WindowBehavior/WindowFunctions.cs
  28. 4 4
      src/PicView.Avalonia/WindowBehavior/WindowResizing.cs

+ 4 - 4
src/PicView.Avalonia.MacOS/Views/MacMainWindow.axaml

@@ -1,13 +1,13 @@
 <Window
     BorderBrush="{DynamicResource SecondaryBackgroundColor}"
     BorderThickness="1"
-    CanResize="{Binding CanResize}"
+    CanResize="{Binding MainWindow.CanResize.Value}"
     ExtendClientAreaChromeHints="SystemChrome"
     ExtendClientAreaTitleBarHeightHint="-1"
-    MinHeight="{CompiledBinding WindowMinSize}"
-    MinWidth="{CompiledBinding WindowMinSize}"
+    MinHeight="{CompiledBinding MainWindow.WindowMinSize.Value}"
+    MinWidth="{CompiledBinding MainWindow.WindowMinSize.Value}"
     SizeChanged="Control_OnSizeChanged"
-    SizeToContent="{CompiledBinding SizeToContent}"
+    SizeToContent="{CompiledBinding MainWindow.SizeToContent.Value}"
     Title="{CompiledBinding PicViewer.WindowTitle.Value}"
     x:Class="PicView.Avalonia.MacOS.Views.MacMainWindow"
     x:DataType="viewModels:MainViewModel"

+ 2 - 2
src/PicView.Avalonia.MacOS/Views/OpenWithView.axaml

@@ -29,7 +29,7 @@
             FontFamily="avares://PicView.Avalonia/Assets/Fonts/Roboto-Medium.ttf#Roboto"
             FontSize="13"
             FontWeight="Medium"
-            Height="{CompiledBinding TitlebarHeight,
+            Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                      Mode=OneWay}"
             Padding="7"
             Text="{CompiledBinding Translation.OpenWith.Value,
@@ -41,7 +41,7 @@
         </customControls:AutoScrollViewer>
         <Button
             Classes=" altHover"
-            Height="{CompiledBinding TitlebarHeight,
+            Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                      Mode=OneWay}"
             Padding="7"
             VerticalAlignment="Bottom"

+ 7 - 7
src/PicView.Avalonia.MacOS/WindowImpl/MacOSWindow.cs

@@ -54,14 +54,14 @@ public static class MacOSWindow
 
         if (Settings.WindowProperties.AutoFit)
         {
-            vm.SizeToContent = SizeToContent.WidthAndHeight;
-            vm.CanResize = false;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
+            vm.MainWindow.CanResize.Value = false;
             await WindowResizing.SetSizeAsync(vm);
         }
         else
         {
-            vm.SizeToContent = SizeToContent.Manual;
-            vm.CanResize = true;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+            vm.MainWindow.CanResize.Value = true;
             WindowFunctions.InitializeWindowSizeAndPosition(window);
         }
         
@@ -83,7 +83,7 @@ public static class MacOSWindow
         
         vm.IsFullscreen = true;
         vm.IsMaximized = false;
-        vm.CanResize = false;
+        vm.MainWindow.CanResize.Value = false;
         await WindowResizing.SetSizeAsync(vm);
         
         if (saveSettings)
@@ -107,10 +107,10 @@ public static class MacOSWindow
         Settings.WindowProperties.Maximized = true;
         Settings.WindowProperties.Fullscreen = false;
         
-        vm.SizeToContent = SizeToContent.Manual;
+        vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
         vm.IsMaximized = true;
         vm.IsFullscreen = false;
-        vm.CanResize = false;
+        vm.MainWindow.CanResize.Value = false;
         
         window.WindowState = WindowState.Maximized;
         

+ 4 - 4
src/PicView.Avalonia.Win32/Views/WinMainWindow.axaml

@@ -1,10 +1,10 @@
 <Window
-    CanResize="{CompiledBinding CanResize}"
+    CanResize="{CompiledBinding MainWindow.CanResize.Value}"
     Icon="/icon.ico"
-    MinHeight="{CompiledBinding WindowMinSize}"
-    MinWidth="{CompiledBinding WindowMinSize}"
+    MinHeight="{CompiledBinding MainWindow.WindowMinSize.Value}"
+    MinWidth="{CompiledBinding MainWindow.WindowMinSize.Value}"
     SizeChanged="Control_OnSizeChanged"
-    SizeToContent="{CompiledBinding SizeToContent}"
+    SizeToContent="{CompiledBinding MainWindow.SizeToContent.Value}"
     Title="{CompiledBinding PicViewer.WindowTitle.Value,
                             Mode=OneWay}"
     TransparencyLevelHint="AcrylicBlur"

+ 2 - 2
src/PicView.Avalonia.Win32/Views/WinTitleBar.axaml

@@ -1,9 +1,9 @@
 <UserControl
-    Height="{CompiledBinding TitlebarHeight,
+    Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                              Mode=OneWay}"
     IsVisible="{CompiledBinding IsTopToolbarShown,
                                 Mode=OneWay}"
-    Margin="{CompiledBinding TopScreenMargin,
+    Margin="{CompiledBinding MainWindow.TopScreenMargin.Value,
                              Mode=OneWay}"
     x:Class="PicView.Avalonia.Win32.Views.WinTitleBar"
     x:DataType="vm:MainViewModel"

+ 14 - 14
src/PicView.Avalonia.Win32/WindowImpl/Win32Window.cs

@@ -18,10 +18,10 @@ public static class Win32Window
         MenuManager.CloseMenus(vm);
 
         // Update view model properties
-        vm.SizeToContent = SizeToContent.Manual;
+        vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
         vm.IsFullscreen = true;
         vm.IsMaximized = false;
-        vm.CanResize = false;
+        vm.MainWindow.CanResize.Value = false;
 
         // Update settings
         Settings.WindowProperties.Fullscreen = true;
@@ -54,7 +54,7 @@ public static class Win32Window
         {
             if (Settings.WindowProperties.AutoFit)
             {
-                vm.SizeToContent = SizeToContent.Manual;
+                vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
             }
             
             // Save window size, so that restoring it will return to the same size and position
@@ -68,7 +68,7 @@ public static class Win32Window
 
         vm.IsMaximized = true;
         vm.IsFullscreen = false;
-        vm.CanResize = false;
+        vm.MainWindow.CanResize.Value = false;
 
         if (saveSettings)
         {
@@ -94,8 +94,8 @@ public static class Win32Window
 
         if (Settings.WindowProperties.AutoFit)
         {
-            vm.SizeToContent = SizeToContent.WidthAndHeight;
-            vm.CanResize = false;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
+            vm.MainWindow.CanResize.Value = false;
             vm.IsAutoFit = true;
             if (Settings.WindowProperties.KeepCentered)
             {
@@ -110,8 +110,8 @@ public static class Win32Window
         }
         else
         {
-            vm.SizeToContent = SizeToContent.Manual;
-            vm.CanResize = true;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+            vm.MainWindow.CanResize.Value = true;
             WindowFunctions.InitializeWindowSizeAndPosition(window);
         }
         
@@ -211,7 +211,7 @@ public static class Win32Window
         }
 
         vm.IsTopToolbarShown = true;
-        vm.TitlebarHeight = SizeDefaults.MainTitlebarHeight;
+        vm.MainWindow.TitlebarHeight.Value = SizeDefaults.MainTitlebarHeight;
 
         if (!Settings.UIProperties.ShowBottomNavBar)
         {
@@ -219,7 +219,7 @@ public static class Win32Window
         }
 
         vm.IsBottomToolbarShown = true;
-        vm.BottombarHeight = SizeDefaults.BottombarHeight;
+        vm.MainWindow.BottombarHeight.Value = SizeDefaults.BottombarHeight;
     }
 
     /// <summary>
@@ -244,14 +244,14 @@ public static class Win32Window
             var top = window.OffScreenMargin.Top is 0 ? 7 : window.OffScreenMargin.Top;
             var right = window.OffScreenMargin.Right is 0 ? 7 : window.OffScreenMargin.Right;
             var bottom = window.OffScreenMargin.Bottom is 0 ? 7 : window.OffScreenMargin.Bottom;
-            vm.TopScreenMargin = new Thickness(left, top, right, 0);
-            vm.BottomScreenMargin = new Thickness(left, 0, right, bottom);
+            vm.MainWindow.TopScreenMargin.Value = new Thickness(left, top, right, 0);
+            vm.MainWindow.BottomScreenMargin.Value = new Thickness(left, 0, right, bottom);
         }
         else
         {
             var noThickness = new Thickness(0);
-            vm.TopScreenMargin = noThickness;
-            vm.BottomScreenMargin = noThickness;
+            vm.MainWindow.TopScreenMargin.Value = noThickness;
+            vm.MainWindow.BottomScreenMargin.Value = noThickness;
         }
     }
 

+ 5 - 10
src/PicView.Avalonia/ColorManagement/BackgroundManager.cs

@@ -72,11 +72,6 @@ public static class BackgroundManager
     /// <param name="vm">The main view model where the background is updated.</param>
     public static void ChangeBackground(MainViewModel vm)
     {
-        if (vm.CurrentView != vm.ImageViewer)
-        {
-            return;
-        }
-
         // Cycle to the next background choice
         var nextChoice = (Settings.UIProperties.BgColorChoice + 1) % ((int)BackgroundType.MaxValue + 1);
         SetBackground(vm, nextChoice);
@@ -109,16 +104,16 @@ public static class BackgroundManager
         Settings.UIProperties.BgColorChoice = choice;
         if (Settings.UIProperties.IsConstrainBackgroundColorEnabled)
         {
-            vm.ImageBackground = new SolidColorBrush(Colors.Transparent);
-            vm.ConstrainedImageBackground = GetBackgroundBrush((BackgroundType)choice);
+            vm.MainWindow.ImageBackground.Value = new SolidColorBrush(Colors.Transparent);
+            vm.MainWindow.ConstrainedImageBackground.Value = GetBackgroundBrush((BackgroundType)choice);
         }
         else
         {
-            vm.ImageBackground = GetBackgroundBrush((BackgroundType)choice);
-            vm.ConstrainedImageBackground = new SolidColorBrush(Colors.Transparent);
+            vm.MainWindow.ImageBackground.Value = GetBackgroundBrush((BackgroundType)choice);
+            vm.MainWindow.ConstrainedImageBackground.Value = new SolidColorBrush(Colors.Transparent);
         }
         
-        vm.BackgroundChoice = choice;
+        vm.MainWindow.BackgroundChoice.Value = choice;
     }
 
     /// <summary>

+ 2 - 2
src/PicView.Avalonia/Crop/CropFunctions.cs

@@ -63,7 +63,7 @@ public static class CropFunctions
                 Height = size.Height,
                 Margin = new Thickness(0)
             };
-            vm.CurrentView = cropControl;
+            vm.MainWindow.CurrentView.Value = cropControl;
         });
 
         IsCropping = true;
@@ -90,7 +90,7 @@ public static class CropFunctions
             WindowResizing.SetSize(vm);
         }
 
-        vm.CurrentView = vm.ImageViewer;
+        vm.MainWindow.CurrentView.Value = vm.ImageViewer;
         IsCropping = false;
         TitleManager.SetTitle(vm);
 

+ 2 - 2
src/PicView.Avalonia/DragAndDrop/DragAndDropHelper.cs

@@ -376,9 +376,9 @@ public static class DragAndDropHelper
 
     private static async Task EnsureImageViewerDisplayed(MainViewModel vm)
     {
-        if (vm.CurrentView != vm.ImageViewer)
+        if (vm.MainWindow.CurrentView.CurrentValue != vm.ImageViewer)
         {
-            await Dispatcher.UIThread.InvokeAsync(() => vm.CurrentView = vm.ImageViewer);
+            await Dispatcher.UIThread.InvokeAsync(() => vm.MainWindow.CurrentView.Value = vm.ImageViewer);
         }
     }
 

+ 1 - 1
src/PicView.Avalonia/Input/MainKeyboardShortcuts.cs

@@ -172,7 +172,7 @@ public static class MainKeyboardShortcuts
         // Handle cropping mode
         if (CropFunctions.IsCropping)
         {
-            if (UIHelper.GetMainView.MainGrid.DataContext is MainViewModel { CurrentView: CropControl cropControl })
+            if (UIHelper.GetMainView.MainGrid.DataContext is MainViewModel { MainWindow.CurrentView.CurrentValue: CropControl cropControl })
             {
                 await cropControl.KeyDownHandler(null, e);
             }

+ 2 - 2
src/PicView.Avalonia/Navigation/ErrorHandling.cs

@@ -34,7 +34,7 @@ public static class ErrorHandling
         return;
         void Start()
         {
-            if (vm.CurrentView is not StartUpMenu)
+            if (vm.MainWindow.CurrentView.CurrentValue is not StartUpMenu)
             {
                 var startUpMenu = new StartUpMenu();
                 if (Settings.WindowProperties.AutoFit)
@@ -44,7 +44,7 @@ public static class ErrorHandling
                     vm.PicViewer.GalleryWidth.Value = SizeDefaults.WindowMinSize;
                 }
 
-                vm.CurrentView = startUpMenu;
+                vm.MainWindow.CurrentView.Value = startUpMenu;
             }
             
             TitleManager.SetNoImageTitle(vm);

+ 5 - 5
src/PicView.Avalonia/Navigation/ImageLoader.cs

@@ -50,31 +50,31 @@ public static class ImageLoader
             switch (check.Value.Type)
             {
                 case FileTypeResolver.LoadAbleFileType.File:
-                    vm.CurrentView = vm.ImageViewer;
+                    vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                     await LoadPicFromFile(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
                     vm.IsLoading = false;
                     ArchiveExtraction.Cleanup();
                     return;
                 case FileTypeResolver.LoadAbleFileType.Directory:
-                    vm.CurrentView = vm.ImageViewer;
+                    vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                     await LoadPicFromDirectoryAsync(check.Value.Data, vm).ConfigureAwait(false);
                     vm.IsLoading = false;
                     ArchiveExtraction.Cleanup();
                     return;
                 case FileTypeResolver.LoadAbleFileType.Web:
-                    vm.CurrentView = vm.ImageViewer;
+                    vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                     await LoadPicFromUrlAsync(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
                     vm.IsLoading = false;
                     ArchiveExtraction.Cleanup();
                     return;
                 case FileTypeResolver.LoadAbleFileType.Base64:
-                    vm.CurrentView = vm.ImageViewer;
+                    vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                     await LoadPicFromBase64Async(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
                     vm.IsLoading = false;
                     ArchiveExtraction.Cleanup();
                     return;
                 case FileTypeResolver.LoadAbleFileType.Zip:
-                    vm.CurrentView = vm.ImageViewer;
+                    vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                     await LoadPicFromArchiveAsync(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
                     vm.IsLoading = false;
                     return;

+ 4 - 4
src/PicView.Avalonia/Navigation/UpdateImage.cs

@@ -195,9 +195,9 @@ public static class UpdateImage
         
         await Dispatcher.UIThread.InvokeAsync(() =>
         {
-            if (vm.CurrentView != vm.ImageViewer)
+            if (vm.MainWindow.CurrentView.CurrentValue != vm.ImageViewer)
             {
-                vm.CurrentView = vm.ImageViewer;
+                vm.MainWindow.CurrentView.Value = vm.ImageViewer;
             }
             
             WindowResizing.SetSize(width, height, 0, 0, 0, vm);
@@ -265,9 +265,9 @@ public static class UpdateImage
 
         await Dispatcher.UIThread.InvokeAsync(() =>
         {
-            if (vm.CurrentView != vm.ImageViewer)
+            if (vm.MainWindow.CurrentView.CurrentValue != vm.ImageViewer)
             {
-                vm.CurrentView = vm.ImageViewer;
+                vm.MainWindow.CurrentView.Value = vm.ImageViewer;
             }
             WindowResizing.SetSize(width, height, 0, 0, 0, vm);
         }, DispatcherPriority.Send);

+ 8 - 8
src/PicView.Avalonia/SettingsManagement/SettingsUpdater.cs

@@ -64,15 +64,15 @@ public static class SettingsUpdater
         // Set corner radius on macOS
         if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
         {
-            vm.BottomCornerRadius = new CornerRadius(0, 0, 8, 8);
+            vm.MainWindow.BottomCornerRadius.Value = new CornerRadius(0, 0, 8, 8);
         }
         
-        vm.TitlebarHeight = Settings.WindowProperties.Fullscreen
-            || !Settings.UIProperties.ShowInterface
+        vm.MainWindow.TitlebarHeight.Value = Settings.WindowProperties.Fullscreen
+                                       || !Settings.UIProperties.ShowInterface
             ? 0
             : SizeDefaults.MainTitlebarHeight;
-        vm.BottombarHeight = Settings.WindowProperties.Fullscreen
-                             || !Settings.UIProperties.ShowInterface
+        vm.MainWindow.BottombarHeight.Value = Settings.WindowProperties.Fullscreen
+                                              || !Settings.UIProperties.ShowInterface
             ? 0
             : SizeDefaults.BottombarHeight;
         vm.GetNavSpeed = Settings.UIProperties.NavSpeed;
@@ -96,7 +96,7 @@ public static class SettingsUpdater
         vm.IsShowingConfirmationOnEsc  = Settings.UIProperties.ShowConfirmationOnEsc;   
         vm.IsUsingTouchpad  = Settings.Zoom.IsUsingTouchPad;
         vm.IsAscending  = Settings.Sorting.Ascending;
-        vm.BackgroundChoice = Settings.UIProperties.BgColorChoice;
+        vm.MainWindow.BackgroundChoice.Value = Settings.UIProperties.BgColorChoice;
         vm.IsConstrainingBackgroundColor = Settings.UIProperties.IsConstrainBackgroundColorEnabled;
     }
     
@@ -392,7 +392,7 @@ public static class SettingsUpdater
         vm.Translation.IsScrolling.Value = TranslationManager.Translation.ScrollingDisabled;
         vm.IsScrollingEnabled = false;
         Settings.Zoom.ScrollEnabled = false;
-        vm.RightControlOffSetMargin = new Thickness(0);
+        vm.MainWindow.RightControlOffSetMargin.Value = new Thickness(0);
     }
     
     public static void TurnOnScroll(MainViewModel vm)
@@ -401,7 +401,7 @@ public static class SettingsUpdater
         vm.Translation.IsScrolling.Value = TranslationManager.Translation.ScrollingEnabled;
         vm.IsScrollingEnabled = true;
         Settings.Zoom.ScrollEnabled = true;
-        vm.RightControlOffSetMargin = new Thickness(0,0,30,0);
+        vm.MainWindow.RightControlOffSetMargin.Value = new Thickness(0,0,30,0);
     }
     
     public static async Task ToggleCtrlZoom(MainViewModel vm)

+ 6 - 6
src/PicView.Avalonia/StartUp/StartUpHelper.cs

@@ -203,7 +203,7 @@ public static class StartUpHelper
         
         if (args.Length > 1)
         {
-            vm.CurrentView = vm.ImageViewer;
+            vm.MainWindow.CurrentView.Value = vm.ImageViewer;
             Task.Run(() => QuickLoad.QuickLoadAsync(vm, args[1]));
         }
         else StartUpMenuOrLastFile(vm);
@@ -215,7 +215,7 @@ public static class StartUpHelper
         
         if (arg is not null)
         {
-            vm.CurrentView = vm.ImageViewer;
+            vm.MainWindow.CurrentView.Value = vm.ImageViewer;
             Task.Run(() => QuickLoad.QuickLoadAsync(vm, arg));
         }
         else StartUpMenuOrLastFile(vm);
@@ -231,7 +231,7 @@ public static class StartUpHelper
             }
             else
             {
-                vm.CurrentView = vm.ImageViewer;
+                vm.MainWindow.CurrentView.Value = vm.ImageViewer;
                 Task.Run(() => QuickLoad.QuickLoadAsync(vm, Settings.StartUp.LastFile));
             }
         }
@@ -255,7 +255,7 @@ public static class StartUpHelper
 
     private static void HandleNormalWindow(MainViewModel vm, Window window)
     {
-        vm.CanResize = true;
+        vm.MainWindow.CanResize.Value = true;
         vm.IsAutoFit = false;
         if (Settings.UIProperties.ShowInterface)
         {
@@ -267,8 +267,8 @@ public static class StartUpHelper
 
     private static void HandleAutoFit(MainViewModel vm, Window window)
     {
-        vm.SizeToContent = SizeToContent.WidthAndHeight;
-        vm.CanResize = false;
+        vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
+        vm.MainWindow.CanResize.Value = false;
         vm.IsAutoFit = true;
         if (Settings.UIProperties.ShowInterface)
         {

+ 3 - 3
src/PicView.Avalonia/UI/HideInterfaceLogic.cs

@@ -53,10 +53,10 @@ public static class HideInterfaceLogic
             if (Settings.UIProperties.ShowBottomNavBar)
             {
                 vm.IsBottomToolbarShown = true;
-                vm.BottombarHeight = SizeDefaults.BottombarHeight;
+                vm.MainWindow.BottombarHeight.Value = SizeDefaults.BottombarHeight;
             }
             Settings.UIProperties.ShowInterface = true;
-            vm.TitlebarHeight = SizeDefaults.MainTitlebarHeight;
+            vm.MainWindow.TitlebarHeight.Value = SizeDefaults.MainTitlebarHeight;
             if (!GalleryFunctions.IsFullGalleryOpen)
             {
                 if (Settings.Gallery.IsBottomGalleryShown)
@@ -105,7 +105,7 @@ public static class HideInterfaceLogic
         {
             vm.IsBottomToolbarShown = true;
             Settings.UIProperties.ShowBottomNavBar = true;
-            vm.BottombarHeight = SizeDefaults.BottombarHeight;
+            vm.MainWindow.BottombarHeight.Value = SizeDefaults.BottombarHeight;
             vm.Translation.IsShowingBottomToolbar.Value = TranslationManager.Translation.HideBottomToolbar;
         }
         await Dispatcher.UIThread.InvokeAsync(() =>

+ 4 - 87
src/PicView.Avalonia/ViewModels/MainViewModel.cs

@@ -1,6 +1,4 @@
 using System.Reactive;
-using Avalonia;
-using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
 using Avalonia.Media;
 using PicView.Avalonia.Functions;
@@ -10,7 +8,6 @@ using PicView.Avalonia.UI;
 using PicView.Avalonia.WindowBehavior;
 using PicView.Core.FileSorting;
 using PicView.Core.ProcessHandling;
-using PicView.Core.Sizing;
 using PicView.Core.ViewModels;
 using ReactiveUI;
 using ImageViewer = PicView.Avalonia.Views.ImageViewer;
@@ -23,13 +20,14 @@ public class MainViewModel : ReactiveObject
     public readonly IPlatformWindowService? PlatformWindowService;
     
     public TranslationViewModel Translation { get; } = new();
-    public ToolsViewModel? GLobalSettings { get; } = new();
+    public MainWindowViewModel MainWindow { get; } = new();
+    public GlobalSettingsViewModel GlobalSettings { get; } = new();
     public SettingsViewModel? SettingsViewModel { get; set; }
     public ImageCropperViewModel? Crop { get; set; }
     public NavigationViewModel Navigation { get; } = new();
     public PicViewerModel PicViewer { get; } = new();
-    public GalleryViewModel? Gallery { get; } = new();
-    public ToolsViewModel? Tools { get; } = new();
+    public GalleryViewModel Gallery { get; } = new();
+    public ToolsViewModel Tools { get; } = new();
     public ExifViewModel? Exif { get; set;  }
     
     public FileAssociationsViewModel? AssociationsViewModel { get; set; }
@@ -471,71 +469,6 @@ public class MainViewModel : ReactiveObject
 
     #endregion Booleans
     
-    public Brush? ImageBackground
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-    
-    public Brush? ConstrainedImageBackground
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-    
-    public Thickness RightControlOffSetMargin
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public Thickness TopScreenMargin
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public Thickness BottomScreenMargin
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public CornerRadius BottomCornerRadius
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public int BackgroundChoice
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public double WindowMinSize
-    {
-        get { return SizeDefaults.WindowMinSize; }
-    }
-
-    public double TitlebarHeight
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public double BottombarHeight
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public UserControl? CurrentView
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
     public ImageViewer? ImageViewer;
 
     public int GetIndex
@@ -575,22 +508,6 @@ public class MainViewModel : ReactiveObject
             Settings.Zoom.ZoomSpeed = roundedValue;
         }
     }
-    
-    #region Window Properties
-
-    public SizeToContent SizeToContent
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    public bool CanResize
-    {
-        get;
-        set => this.RaiseAndSetIfChanged(ref field, value);
-    }
-
-    #endregion Window Properties
 
     #region Size
 

+ 52 - 0
src/PicView.Avalonia/ViewModels/MainWindowViewModel.cs

@@ -0,0 +1,52 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Media;
+using R3;
+
+namespace PicView.Avalonia.ViewModels;
+
+public class MainWindowViewModel : IDisposable
+{
+    public BindableReactiveProperty<Brush?> ImageBackground { get; } = new();
+
+    public BindableReactiveProperty<Brush?> ConstrainedImageBackground { get; } = new();
+
+    public BindableReactiveProperty<Thickness> RightControlOffSetMargin { get; } = new();
+
+    public BindableReactiveProperty<Thickness> TopScreenMargin { get; } = new();
+
+    public BindableReactiveProperty<Thickness> BottomScreenMargin { get; } = new();
+
+    public BindableReactiveProperty<CornerRadius> BottomCornerRadius { get; } = new();
+
+    public BindableReactiveProperty<int> BackgroundChoice { get; } = new();
+
+    public BindableReactiveProperty<double> WindowMinSize { get; } = new();
+
+    public BindableReactiveProperty<double> TitlebarHeight { get; } = new();
+
+    public BindableReactiveProperty<double> BottombarHeight { get; } = new();
+    
+    public BindableReactiveProperty<SizeToContent> SizeToContent { get; } = new();
+
+    public BindableReactiveProperty<bool> CanResize { get; } = new();
+
+    public BindableReactiveProperty<UserControl?> CurrentView { get; } = new();
+
+    public void Dispose()
+    {
+        Disposable.Dispose(ImageBackground,
+            ConstrainedImageBackground,
+            RightControlOffSetMargin,
+            TopScreenMargin,
+            BottomScreenMargin,
+            BottomCornerRadius,
+            BackgroundChoice,
+            WindowMinSize,
+            TitlebarHeight,
+            BottombarHeight,
+            SizeToContent,
+            CanResize,
+            CurrentView);
+    }
+}

+ 4 - 6
src/PicView.Avalonia/Views/AppearanceView.axaml.cs

@@ -1,13 +1,12 @@
-using System.Reactive.Disposables;
 using Avalonia.Controls;
 using Avalonia.Interactivity;
 using Avalonia.Media;
 using PicView.Avalonia.ColorManagement;
 using PicView.Avalonia.Gallery;
+using PicView.Avalonia.UI;
 using PicView.Avalonia.ViewModels;
 using PicView.Core.ColorHandling;
-using PicView.Core.Localization;
-using ReactiveUI;
+using R3;
 
 namespace PicView.Avalonia.Views;
 
@@ -114,10 +113,9 @@ public partial class AppearanceView : UserControl
         CheckerboardButton.Background = BackgroundManager.CreateCheckerboardBrush(default, default,10);
         CheckerboardAltButton.Background = BackgroundManager.CreateCheckerboardBrushAlt(25);
         
-        // Subscribe to background color changes with ReactiveUI
-        vm.WhenAnyValue(x => x.BackgroundChoice)
+        Observable.EveryValueChanged(vm.MainWindow, x => x.BackgroundChoice, UIHelper.GetFrameProvider)
             .Subscribe(_ => SetBackgroundTheme(Settings.UIProperties.BgColorChoice))
-            .DisposeWith(_disposables);
+            .AddTo(_disposables);
     }
     
     // New method to update color buttons with values from ColorManager

+ 5 - 5
src/PicView.Avalonia/Views/BottomBar.axaml

@@ -1,7 +1,7 @@
 <UserControl
-    Height="{CompiledBinding BottombarHeight}"
+    Height="{CompiledBinding MainWindow.BottombarHeight.Value}"
     IsVisible="{CompiledBinding IsBottomToolbarShown}"
-    Margin="{CompiledBinding BottomScreenMargin,
+    Margin="{CompiledBinding MainWindow.BottomScreenMargin.Value,
                              Mode=OneWay}"
     x:Class="PicView.Avalonia.Views.BottomBar"
     x:DataType="viewModels:MainViewModel"
@@ -195,8 +195,8 @@
         Background="{DynamicResource WindowBackgroundColor}"
         BorderBrush="{DynamicResource MainBorderColor}"
         BorderThickness="0,1,0,0"
-        CornerRadius="{CompiledBinding BottomCornerRadius}"
-        Height="{CompiledBinding BottombarHeight,
+        CornerRadius="{CompiledBinding MainWindow.BottomCornerRadius.Value}"
+        Height="{CompiledBinding MainWindow.BottombarHeight.Value,
                                  Mode=OneWay}"
         x:Name="MainBottomBorder">
         <Panel>
@@ -359,7 +359,7 @@
                 Fill="{DynamicResource MainTextColor}"
                 Height="12"
                 HorizontalAlignment="Right"
-                IsVisible="{CompiledBinding CanResize,
+                IsVisible="{CompiledBinding MainWindow.CanResize.Value,
                                             Mode=OneWay}"
                 Margin="0,0,5,5"
                 Stretch="Fill"

+ 2 - 2
src/PicView.Avalonia/Views/ImageViewer.axaml

@@ -1,5 +1,5 @@
 <UserControl
-    Background="{CompiledBinding ImageBackground,
+    Background="{CompiledBinding MainWindow.ImageBackground,
                                  Mode=OneWay}"
     PointerPressed="InputElement_OnPointerPressed"
     mc:Ignorable="d"
@@ -26,7 +26,7 @@
                                     Mode=OneWay}"
             x:Name="ImageScrollViewer">
             <Border
-                Background="{CompiledBinding ConstrainedImageBackground,
+                Background="{CompiledBinding MainWindow.ConstrainedImageBackground.Value,
                                              Mode=OneWay}"
                 Height="{CompiledBinding PicViewer.ImageHeight.Value,
                                          Mode=OneWay}"

+ 3 - 3
src/PicView.Avalonia/Views/MainView.axaml

@@ -1089,12 +1089,12 @@
             ZIndex="3" />
         <ContentControl
             ClipToBounds="True"
-            Content="{CompiledBinding CurrentView,
+            Content="{CompiledBinding MainWindow.CurrentView.Value,
                                       Mode=OneWay}"
             Margin="{CompiledBinding Gallery.GalleryMargin.Value}" />
         <buttons:ClickArrowRight
             HorizontalAlignment="Right"
-            Margin="{CompiledBinding RightControlOffSetMargin}"
+            Margin="{CompiledBinding MainWindow.RightControlOffSetMargin.Value}"
             Opacity="0"
             VerticalAlignment="Center"
             x:Name="ClickArrowRight" />
@@ -1108,7 +1108,7 @@
             Height="150"
             HorizontalAlignment="Right"
             IsVisible="{CompiledBinding !IsUIShown}"
-            Margin="{CompiledBinding RightControlOffSetMargin}"
+            Margin="{CompiledBinding MainWindow.RightControlOffSetMargin.Value}"
             Opacity="0"
             Orientation="Horizontal"
             VerticalAlignment="Top"

+ 2 - 2
src/PicView.Avalonia/Views/StartUpMenu.axaml

@@ -1,6 +1,6 @@
 <UserControl
-    MinHeight="{CompiledBinding WindowMinSize}"
-    MinWidth="{CompiledBinding WindowMinSize}"
+    MinHeight="{CompiledBinding MainWindow.WindowMinSize.Value}"
+    MinWidth="{CompiledBinding MainWindow.WindowMinSize.Value}"
     d:DesignHeight="450"
     d:DesignWidth="800"
     mc:Ignorable="d"

+ 1 - 1
src/PicView.Avalonia/Views/UC/DragDrogView.axaml.cs

@@ -106,7 +106,7 @@ public partial class DragDropView : UserControl
     private static double CalculateScale(double width, double height, MainViewModel vm)
     {
         var screen = ScreenHelper.ScreenSize;
-        var padding = vm.BottombarHeight + vm.TitlebarHeight + 50;
+        var padding = vm.MainWindow.BottombarHeight.CurrentValue + vm.MainWindow.TitlebarHeight.CurrentValue + 50;
         var boxedWidth = UIHelper.GetMainView.Bounds.Width * screen.Scaling - padding;
         var boxedHeight = UIHelper.GetMainView.Bounds.Height * screen.Scaling - padding;
         var scaledWidth = boxedWidth / width;

+ 3 - 3
src/PicView.Avalonia/Views/UC/EditableTitlebar.axaml

@@ -1,5 +1,5 @@
 <UserControl
-    Height="{CompiledBinding TitlebarHeight,
+    Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                              Mode=OneWay}"
     ToolTip.Tip="{Binding PicViewer.TitleTooltip.Value, Mode=OneWay}"
     Width="{CompiledBinding TitleMaxWidth,
@@ -20,7 +20,7 @@
             FontFamily="avares://PicView.Avalonia/Assets/Fonts/Roboto-Medium.ttf#Roboto"
             FontSize="13"
             FontWeight="Medium"
-            Height="{CompiledBinding TitlebarHeight,
+            Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                      Mode=OneWay}"
             IsTabStop="False"
             IsVisible="{CompiledBinding !IsEditableTitlebarOpen}"
@@ -39,7 +39,7 @@
                 FontFamily="avares://PicView.Avalonia/Assets/Fonts/Roboto-Medium.ttf#Roboto"
                 FontSize="13"
                 FontWeight="Medium"
-                Height="{CompiledBinding TitlebarHeight,
+                Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                          Mode=OneWay}"
                 IsTabStop="False"
                 Padding="0,7,0,5"

+ 2 - 2
src/PicView.Avalonia/Views/UC/TitleTextBox.axaml

@@ -21,7 +21,7 @@
             FontFamily="avares://PicView.Avalonia/Assets/Fonts/Roboto-Medium.ttf#Roboto"
             FontSize="13"
             FontWeight="Medium"
-            Height="{CompiledBinding TitlebarHeight,
+            Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                      Mode=OneWay}"
             IsTabStop="False"
             Padding="0,7,0,5"
@@ -36,7 +36,7 @@
             FontFamily="avares://PicView.Avalonia/Assets/Fonts/Roboto-Medium.ttf#Roboto"
             FontSize="13"
             FontWeight="Medium"
-            Height="{CompiledBinding TitlebarHeight,
+            Height="{CompiledBinding MainWindow.TitlebarHeight.Value,
                                      Mode=OneWay}"
             IsTabStop="False"
             IsVisible="False"

+ 12 - 12
src/PicView.Avalonia/WindowBehavior/WindowFunctions.cs

@@ -167,15 +167,15 @@ public static class WindowFunctions
     {
         if (Settings.WindowProperties.AutoFit)
         {
-            vm.SizeToContent = SizeToContent.Manual;
-            vm.CanResize = true;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+            vm.MainWindow.CanResize.Value = true;
             Settings.WindowProperties.AutoFit = false;
             vm.IsAutoFit = false;
         }
         else
         {
-            vm.SizeToContent = SizeToContent.WidthAndHeight;
-            vm.CanResize = false;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
+            vm.MainWindow.CanResize.Value = false;
             Settings.WindowProperties.AutoFit = true;
             vm.IsAutoFit = true;
         }
@@ -187,8 +187,8 @@ public static class WindowFunctions
     {
         if (Settings.WindowProperties.AutoFit)
         {
-            vm.SizeToContent = SizeToContent.Manual;
-            vm.CanResize = true;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+            vm.MainWindow.CanResize.Value = true;
             Settings.WindowProperties.AutoFit = false;
             Settings.ImageScaling.StretchImage = false;
             vm.IsStretched = false;
@@ -196,8 +196,8 @@ public static class WindowFunctions
         }
         else
         {
-            vm.SizeToContent = SizeToContent.WidthAndHeight;
-            vm.CanResize = false;
+            vm.MainWindow.SizeToContent.Value = SizeToContent.WidthAndHeight;
+            vm.MainWindow.CanResize.Value = false;
             Settings.WindowProperties.AutoFit = true;
             Settings.ImageScaling.StretchImage = true;
             vm.IsAutoFit = true;
@@ -210,8 +210,8 @@ public static class WindowFunctions
 
     public static async Task NormalWindow(MainViewModel vm)
     {
-        vm.SizeToContent = SizeToContent.Manual;
-        vm.CanResize = true;
+        vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+        vm.MainWindow.CanResize.Value = true;
         Settings.WindowProperties.AutoFit = false;
         await WindowResizing.SetSizeAsync(vm);
         vm.ImageViewer.MainImage.InvalidateVisual();
@@ -220,8 +220,8 @@ public static class WindowFunctions
 
     public static async Task NormalWindowStretch(MainViewModel vm)
     {
-        vm.SizeToContent = SizeToContent.Manual;
-        vm.CanResize = true;
+        vm.MainWindow.SizeToContent.Value = SizeToContent.Manual;
+        vm.MainWindow.CanResize.Value = true;
         Settings.WindowProperties.AutoFit = false;
         Settings.ImageScaling.StretchImage = true;
         vm.IsStretched = true;

+ 4 - 4
src/PicView.Avalonia/WindowBehavior/WindowResizing.cs

@@ -251,8 +251,8 @@ public static class WindowResizing
                 vm.PlatformWindowService.CombinedTitleButtonsWidth,
                 rotation,
                 screenSize.Scaling,
-                vm.TitlebarHeight,
-                vm.BottombarHeight,
+                vm.MainWindow.TitlebarHeight.CurrentValue,
+                vm.MainWindow.BottombarHeight.CurrentValue,
                 GalleryFunctions.GetGalleryHeight(vm),
                 containerWidth,
                 containerHeight);
@@ -268,8 +268,8 @@ public static class WindowResizing
                 vm.PlatformWindowService.CombinedTitleButtonsWidth,
                 rotation,
                 screenSize.Scaling,
-                vm.TitlebarHeight,
-                vm.BottombarHeight,
+                vm.MainWindow.TitlebarHeight.CurrentValue,
+                vm.MainWindow.BottombarHeight.CurrentValue,
                 GalleryFunctions.GetGalleryHeight(vm),
                 containerWidth,
                 containerHeight);