From 7394c9019f99232bf05bab023fbfc902224268f8 Mon Sep 17 00:00:00 2001
From: XanatosX <10531466+XanatosX@users.noreply.github.com>
Date: Wed, 2 Aug 2023 20:57:21 +0200
Subject: [PATCH] Fix issue with application not starting minimized
Rework window position on screen
Add strategy to show window in bottom right corner
Add structure to position the window baesed on a strategy
---
.../DependencyInjectionExtension.cs | 6 ++-
.../Enums/WindowPositionEnum.cs | 12 ++++++
.../DefaultWindowPositionStrategyFactory.cs | 20 ++++++++++
.../Services/Ui/IWindowManagementService.cs | 3 +-
.../Services/Ui/IWindowPositionFactory.cs | 17 +++++++++
.../WindowPosition/BottomRightStrategy.cs | 24 ++++++++++++
.../WindowPosition/IWindowPositionStrategy.cs | 17 +++++++++
.../Views/MainWindow.axaml.cs | 37 ++++++++++++-------
8 files changed, 120 insertions(+), 16 deletions(-)
create mode 100644 src/ModularToolManager/Enums/WindowPositionEnum.cs
create mode 100644 src/ModularToolManager/Services/Ui/DefaultWindowPositionStrategyFactory.cs
create mode 100644 src/ModularToolManager/Services/Ui/IWindowPositionFactory.cs
create mode 100644 src/ModularToolManager/Strategies/WindowPosition/BottomRightStrategy.cs
create mode 100644 src/ModularToolManager/Strategies/WindowPosition/IWindowPositionStrategy.cs
diff --git a/src/ModularToolManager/DependencyInjection/DependencyInjectionExtension.cs b/src/ModularToolManager/DependencyInjection/DependencyInjectionExtension.cs
index 95425eaf..01f2570e 100644
--- a/src/ModularToolManager/DependencyInjection/DependencyInjectionExtension.cs
+++ b/src/ModularToolManager/DependencyInjection/DependencyInjectionExtension.cs
@@ -68,7 +68,10 @@ public static IServiceCollection AddViewModels(this IServiceCollection collectio
/// The extended collection
public static IServiceCollection AddViews(this IServiceCollection collection)
{
- return collection.AddTransient(resolver => new MainWindow(resolver.GetRequiredService(), resolver.GetRequiredService())
+ return collection.AddTransient(resolver => new MainWindow(
+ resolver.GetRequiredService(),
+ resolver.GetRequiredService(),
+ resolver.GetRequiredService())
{
DataContext = resolver?.GetService(),
})
@@ -96,6 +99,7 @@ public static IServiceCollection AddServices(this IServiceCollection collection)
.AddSingleton()
.AddSingleton()
.AddSingleton()
+ .AddSingleton()
.AddTransient()
.AddTransient()
.AddTransient()
diff --git a/src/ModularToolManager/Enums/WindowPositionEnum.cs b/src/ModularToolManager/Enums/WindowPositionEnum.cs
new file mode 100644
index 00000000..c02af711
--- /dev/null
+++ b/src/ModularToolManager/Enums/WindowPositionEnum.cs
@@ -0,0 +1,12 @@
+namespace ModularToolManager.Enums;
+
+///
+/// Enum for the correct position of the window
+///
+public enum WindowPositionEnum
+{
+ TopLeft,
+ TopRight,
+ BottomLeft,
+ BottomRight,
+}
diff --git a/src/ModularToolManager/Services/Ui/DefaultWindowPositionStrategyFactory.cs b/src/ModularToolManager/Services/Ui/DefaultWindowPositionStrategyFactory.cs
new file mode 100644
index 00000000..66510cee
--- /dev/null
+++ b/src/ModularToolManager/Services/Ui/DefaultWindowPositionStrategyFactory.cs
@@ -0,0 +1,20 @@
+using ModularToolManager.Enums;
+using ModularToolManager.Strategies.WindowPosition;
+
+namespace ModularToolManager.Services.Ui;
+
+///
+/// Default factory for getting the window position strategy
+///
+public class DefaultWindowPositionStrategyFactory : IWindowPositionFactory
+{
+ ///
+ public IWindowPositionStrategy? GetWindowPositionStrategy(WindowPositionEnum positionEnum)
+ {
+ return positionEnum switch
+ {
+ WindowPositionEnum.BottomRight => new BottomRightStrategy(),
+ _ => new BottomRightStrategy()
+ };
+ }
+}
diff --git a/src/ModularToolManager/Services/Ui/IWindowManagementService.cs b/src/ModularToolManager/Services/Ui/IWindowManagementService.cs
index b3759271..3660f615 100644
--- a/src/ModularToolManager/Services/Ui/IWindowManagementService.cs
+++ b/src/ModularToolManager/Services/Ui/IWindowManagementService.cs
@@ -1,4 +1,5 @@
using Avalonia.Controls;
+using ModularToolManager.Enums;
using ModularToolManager.Models;
using System.Collections;
using System.Collections.Generic;
@@ -26,7 +27,7 @@ public interface IWindowManagementService
///
/// Get the main window of the application
///
- ///
+ /// The main window or nothing if no main window was found
Window? GetMainWindow();
///
diff --git a/src/ModularToolManager/Services/Ui/IWindowPositionFactory.cs b/src/ModularToolManager/Services/Ui/IWindowPositionFactory.cs
new file mode 100644
index 00000000..b6734dfb
--- /dev/null
+++ b/src/ModularToolManager/Services/Ui/IWindowPositionFactory.cs
@@ -0,0 +1,17 @@
+using ModularToolManager.Enums;
+using ModularToolManager.Strategies.WindowPosition;
+
+namespace ModularToolManager.Services.Ui;
+
+///
+/// Factory to get a matching strategy for a requested window position
+///
+public interface IWindowPositionFactory
+{
+ ///
+ /// Get the strategy for the given window
+ ///
+ /// The position enum to use
+ /// The strategy to position the window on the given position
+ IWindowPositionStrategy? GetWindowPositionStrategy(WindowPositionEnum positionEnum);
+}
diff --git a/src/ModularToolManager/Strategies/WindowPosition/BottomRightStrategy.cs b/src/ModularToolManager/Strategies/WindowPosition/BottomRightStrategy.cs
new file mode 100644
index 00000000..76fd860a
--- /dev/null
+++ b/src/ModularToolManager/Strategies/WindowPosition/BottomRightStrategy.cs
@@ -0,0 +1,24 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Platform;
+
+namespace ModularToolManager.Strategies.WindowPosition;
+
+///
+/// Position a Window in the bottom right of a given screen
+///
+public class BottomRightStrategy : IWindowPositionStrategy
+{
+ ///
+ public void PositionWindow(Window window, Screen? screen)
+ {
+ if (screen is null)
+ {
+ return;
+ }
+ PixelRect workingArea = screen.WorkingArea;
+ double newXPos = workingArea.X + workingArea.Width - window.Width;
+ double newYPos = workingArea.Y + workingArea.Height - window.Height;
+ window.Position = new PixelPoint((int)newXPos, (int)newYPos);
+ }
+}
diff --git a/src/ModularToolManager/Strategies/WindowPosition/IWindowPositionStrategy.cs b/src/ModularToolManager/Strategies/WindowPosition/IWindowPositionStrategy.cs
new file mode 100644
index 00000000..1c5b688e
--- /dev/null
+++ b/src/ModularToolManager/Strategies/WindowPosition/IWindowPositionStrategy.cs
@@ -0,0 +1,17 @@
+using Avalonia.Controls;
+using Avalonia.Platform;
+
+namespace ModularToolManager.Strategies.WindowPosition;
+
+///
+/// Strategy to position a window on the screen
+///
+public interface IWindowPositionStrategy
+{
+ ///
+ /// Position the given window on the screen
+ ///
+ /// The window which should be moved
+ /// The screen to position the window on
+ void PositionWindow(Window window, Screen? screen);
+}
diff --git a/src/ModularToolManager/Views/MainWindow.axaml.cs b/src/ModularToolManager/Views/MainWindow.axaml.cs
index 9df860e9..68d4f163 100644
--- a/src/ModularToolManager/Views/MainWindow.axaml.cs
+++ b/src/ModularToolManager/Views/MainWindow.axaml.cs
@@ -3,11 +3,13 @@
using Avalonia.Media;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
+using ModularToolManager.Enums;
using ModularToolManager.Models;
using ModularToolManager.Models.Messages;
using ModularToolManager.Services.Settings;
using ModularToolManager.Services.Ui;
using System;
+using System.Linq;
namespace ModularToolManager.Views;
@@ -27,19 +29,24 @@ public partial class MainWindow : Window, IDisposable
private readonly IWindowManagementService? modalService;
///
- /// Is this the first render of the application
+ /// Is this the first time the window was shown
///
- private bool firstRender;
+ private bool firstTimeShown;
///
/// The settings service to use
///
private readonly ISettingsService? settingsService;
+ ///
+ /// The factory to get the window position strategy to use
+ ///
+ private readonly IWindowPositionFactory? windowPositionFactory;
+
///
/// Create a new empty instance of this class
///
- public MainWindow() : this(null, null)
+ public MainWindow() : this(null, null, null)
{
}
@@ -49,13 +56,13 @@ public MainWindow() : this(null, null)
///
/// The modal service to use
/// The settings service to use
- public MainWindow(IWindowManagementService? modalService, ISettingsService? settingsService)
+ public MainWindow(IWindowManagementService? modalService, ISettingsService? settingsService, IWindowPositionFactory? windowPositionFactory)
{
this.modalService = modalService;
this.settingsService = settingsService;
-
- firstRender = true;
+ this.windowPositionFactory = windowPositionFactory;
+ firstTimeShown = true;
InitializeComponent();
WeakReferenceMessenger.Default.Register(this, (_, _) =>
@@ -99,7 +106,14 @@ public MainWindow(IWindowManagementService? modalService, ISettingsService? sett
public override void Render(DrawingContext context)
{
base.Render(context);
- if (firstRender)
+ PositionWindow();
+ }
+
+ ///
+ public override void Show()
+ {
+ base.Show();
+ if (firstTimeShown)
{
if (settingsService?.GetApplicationSettings().StartMinimized ?? false)
{
@@ -107,9 +121,7 @@ public override void Render(DrawingContext context)
mainWindow?.Hide();
}
}
-
- PositionWindow();
- firstRender = false;
+ firstTimeShown = false;
}
///
@@ -117,10 +129,7 @@ public override void Render(DrawingContext context)
///
private void PositionWindow()
{
- PixelRect workingArea = Screens.Primary.WorkingArea;
- double newXPos = workingArea.X + workingArea.Width - Width;
- double newYPos = workingArea.Y + workingArea.Height - Height;
- Position = new PixelPoint((int)newXPos, (int)newYPos);
+ windowPositionFactory?.GetWindowPositionStrategy(WindowPositionEnum.BottomRight)?.PositionWindow(this, Screens.Primary);
}
///