Skip to content

Commit

Permalink
Load settings in Avalonia desktop project
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-lerch committed Nov 26, 2024
1 parent 451db25 commit 52859f4
Show file tree
Hide file tree
Showing 21 changed files with 304 additions and 87 deletions.
15 changes: 15 additions & 0 deletions src/Vocup.Desktop/App.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Vocup.Settings;
using Vocup.Settings.Core;

namespace Vocup.Desktop;

public class App : Vocup.App
{
protected override void ConfigureSettings(IServiceCollection services)
{
base.ConfigureSettings(services);

services.AddSingleton<SettingsLoaderBase<VocupSettings>, DesktopSettingsLoader>();
}
}
18 changes: 18 additions & 0 deletions src/Vocup.Desktop/DesktopSettingsLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.IO;
using Vocup.Settings;
using Vocup.Settings.Core;

namespace Vocup.Desktop;

public class DesktopSettingsLoader : SettingsLoaderBase<VocupSettings>
{
public DesktopSettingsLoader()
: base(
new DirectoryInfo(
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Vocup")),
"settings.2.json")
{ }
}
18 changes: 12 additions & 6 deletions src/Vocup.WinForms/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace Vocup;
public partial class MainForm : Form, IMainForm
{
private int lastSearchResult;
private SizeF scaleFactor = new(1, 1);

public MainForm()
{
Expand Down Expand Up @@ -143,26 +144,31 @@ private void StoreSettings()
_ => throw new ArgumentException($"Unknown FormWindowState {WindowState}")
};

Rectangle logicalBounds = new(bounds.Location, bounds.Size.Multiply(96f / DeviceDpi).Round());
Program.Settings.WindowWidth = bounds.Width / scaleFactor.Width;
Program.Settings.WindowHeight = bounds.Height / scaleFactor.Height;

Program.Settings.MainFormBounds = logicalBounds.ToAvaloniaRect();
Program.Settings.WindowPosition = bounds.Location.ToAvaloniaPixelPoint();

Program.Settings.MainFormWindowState = WindowState.ToAvaloniaWindowState();
Program.Settings.WindowState = WindowState.ToAvaloniaWindowState();

Program.Settings.MainFormSplitterDistance = SplitContainer.SplitterDistance;
}

protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
base.ScaleControl(factor, specified);

scaleFactor = scaleFactor.Multiply(factor);
}

/// <summary>
/// Restore the saved bounds and the splitter distance of this form.
/// </summary>
private void RestoreSettings()
{
Rectangle mainFormBounds = Program.Settings.MainFormBounds.ToSystemDrawingRect();
Point position = Program.Settings.WindowPosition.ToSystemDrawingPoint();
Size size = new((int)(Program.Settings.WindowWidth * scaleFactor.Width), (int)(Program.Settings.WindowHeight * scaleFactor.Height));
Rectangle mainFormBounds = new(position, size);

// check if stored form bound is visible on any screen
bool isVisible = false;
Expand All @@ -180,12 +186,12 @@ private void RestoreSettings()
SplitContainer.SplitterDistance = Program.Settings.MainFormSplitterDistance;
}

if (isVisible && Program.Settings.MainFormBounds != default)
if (isVisible && mainFormBounds != default)
{
// visible => restore the bounds of the main form
Bounds = mainFormBounds;

FormWindowState windowState = Program.Settings.MainFormWindowState.ToFormWindowState();
FormWindowState windowState = Program.Settings.WindowState.ToFormWindowState();

// Do not restore the window state when the form was minimzed
if (windowState != FormWindowState.Minimized)
Expand Down
12 changes: 8 additions & 4 deletions src/Vocup.WinForms/Settings/WindowsSettingsLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ private async ValueTask<bool> MigrateJsonSettings1(SettingsContext<VocupSettings
settings.Value.EvaluateToleratePunctuationMark = oldSettings.EvaluateToleratePunctuationMark;
settings.Value.EvaluateTolerateSpecialChar = oldSettings.EvaluateTolerateSpecialChar;
settings.Value.EvaluateTolerateArticle = oldSettings.EvaluateTolerateArticle;
settings.Value.MainFormBounds = oldSettings.MainFormBounds.ToAvaloniaRect();
settings.Value.MainFormWindowState = oldSettings.MainFormWindowState.ToAvaloniaWindowState();
settings.Value.WindowWidth = oldSettings.MainFormBounds.Width;
settings.Value.WindowHeight = oldSettings.MainFormBounds.Height;
settings.Value.WindowPosition = oldSettings.MainFormBounds.Location.ToAvaloniaPixelPoint();
settings.Value.WindowState = oldSettings.MainFormWindowState.ToAvaloniaWindowState();
settings.Value.MainFormSplitterDistance = oldSettings.MainFormSplitterDistance;
settings.Value.SpecialCharTab = oldSettings.SpecialCharTab;
settings.Value.PracticeDialogSize = oldSettings.PracticeDialogSize.ToAvaloniaSize();
Expand Down Expand Up @@ -135,8 +137,10 @@ private static void MigrateFromAppConfig(SettingsContext<VocupSettings> settings
settings.Value.EvaluateToleratePunctuationMark = OldSettings.Default.EvaluateToleratePunctuationMark;
settings.Value.EvaluateTolerateSpecialChar = OldSettings.Default.EvaluateTolerateSpecialChar;
settings.Value.EvaluateTolerateArticle = OldSettings.Default.EvaluateTolerateArticle;
settings.Value.MainFormBounds = OldSettings.Default.MainFormBounds.ToAvaloniaRect();
settings.Value.MainFormWindowState = OldSettings.Default.MainFormWindowState.ToAvaloniaWindowState();
settings.Value.WindowWidth = OldSettings.Default.MainFormBounds.Width;
settings.Value.WindowHeight = OldSettings.Default.MainFormBounds.Height;
settings.Value.WindowPosition = OldSettings.Default.MainFormBounds.Location.ToAvaloniaPixelPoint();
settings.Value.WindowState = OldSettings.Default.MainFormWindowState.ToAvaloniaWindowState();
settings.Value.MainFormSplitterDistance = OldSettings.Default.MainFormSplitterDistance;
settings.Value.SpecialCharTab = OldSettings.Default.SpecialCharTab;
if (Version.TryParse(OldSettings.Default.Version, out Version? version)) settings.Value.Version = version;
Expand Down
8 changes: 4 additions & 4 deletions src/Vocup.WinForms/Util/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ public static System.Drawing.Size ToSystemDrawingSize(this Avalonia.Size size)
return new((int)size.Width, (int)size.Height);
}

public static Avalonia.Rect ToAvaloniaRect(this System.Drawing.Rectangle rect)
public static Avalonia.PixelPoint ToAvaloniaPixelPoint(this System.Drawing.Point point)
{
return new(rect.X, rect.Y, rect.Width, rect.Height);
return new(point.X, point.Y);
}

public static System.Drawing.Rectangle ToSystemDrawingRect(this Avalonia.Rect rect)
public static System.Drawing.Point ToSystemDrawingPoint(this Avalonia.PixelPoint point)
{
return new((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
return new(point.X, point.Y);
}

public static Avalonia.Controls.WindowState ToAvaloniaWindowState(this FormWindowState state)
Expand Down
4 changes: 2 additions & 2 deletions src/Vocup.WinForms/Util/RecentFilesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void InteractedWith(string fileName)
else
{
recentFile.LastAccess = DateTime.Now;
recentFile.LastAvalailable = DateTime.Now;
recentFile.LastAvailable = DateTime.Now;
}
}

Expand All @@ -41,7 +41,7 @@ private static bool Exists(RecentFile recentFile)
bool exists = File.Exists(recentFile.FileName);
if (exists)
{
recentFile.LastAvalailable = DateTime.Now;
recentFile.LastAvailable = DateTime.Now;
}
return exists;
}
Expand Down
19 changes: 16 additions & 3 deletions src/Vocup/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

using Microsoft.Extensions.DependencyInjection;
using System;
using Vocup.ViewModels;
using Vocup.Views;

Expand All @@ -16,11 +17,15 @@ public override void Initialize()

public override void OnFrameworkInitializationCompleted()
{
ServiceCollection services = new();
ConfigureSettings(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();

if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
desktop.MainWindow = new HostWindow
{
DataContext = new MainViewModel()
DataContext = new HostWindowViewModel(serviceProvider, ConfigureServices)
};
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
Expand All @@ -33,4 +38,12 @@ public override void OnFrameworkInitializationCompleted()

base.OnFrameworkInitializationCompleted();
}

protected virtual void ConfigureSettings(IServiceCollection services)
{
}

protected virtual void ConfigureServices(IServiceProvider serviceProvider, IServiceCollection services)
{
}
}
2 changes: 1 addition & 1 deletion src/Vocup/Settings/Core/JsonSerializerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class JsonSerializerFactory : ISerializerFactory, IDeserializerFactory
public JsonSerializerFactory()
{
options = new JsonSerializerOptions { WriteIndented = true };
options.Converters.Add(new RectJsonConverter());
options.Converters.Add(new PixelPointJsonConverter());
options.Converters.Add(new SizeJsonConverter());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

namespace Vocup.Settings.Core;

public class RectJsonConverter : JsonConverter<Rect>
public class PixelPointJsonConverter : JsonConverter<PixelPoint>
{
public override Rect Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override PixelPoint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException();

double x = 0, y = 0, width = 0, height = 0;
int x = 0, y = 0;

while (reader.Read())
{
Expand All @@ -23,22 +23,12 @@ public override Rect Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSer
if (propertyName == "X")
{
reader.Read();
x = reader.GetDouble();
x = reader.GetInt32();
}
else if (propertyName == "Y")
{
reader.Read();
y = reader.GetDouble();
}
else if (propertyName == "Width")
{
reader.Read();
width = reader.GetDouble();
}
else if (propertyName == "Height")
{
reader.Read();
height = reader.GetDouble();
y = reader.GetInt32();
}
else
{
Expand All @@ -47,29 +37,20 @@ public override Rect Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSer
}
else if (reader.TokenType == JsonTokenType.EndObject)
{
return new Rect(x, y, width, height);
return new PixelPoint(x, y);
}
}

throw new JsonException();
}

public override void Write(Utf8JsonWriter writer, Rect value, JsonSerializerOptions options)
public override void Write(Utf8JsonWriter writer, PixelPoint value, JsonSerializerOptions options)
{
writer.WriteStartObject();

writer.WritePropertyName("X");
writer.WriteNumberValue(value.X);

writer.WritePropertyName("Y");
writer.WriteNumberValue(value.Y);

writer.WritePropertyName("Width");
writer.WriteNumberValue(value.Width);

writer.WritePropertyName("Height");
writer.WriteNumberValue(value.Height);

writer.WriteEndObject();
}
}
11 changes: 8 additions & 3 deletions src/Vocup/Settings/Core/SettingsLoaderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
using LostTech.App.DataBinding;
using System;
using System.ComponentModel;
#if DEBUG
using System.Diagnostics;
#endif
using System.IO;
using System.Threading.Tasks;
using Vocup.Util;
using LSettings = LostTech.App.Settings;

namespace Vocup.Settings.Core;
Expand All @@ -22,7 +24,6 @@ public SettingsLoaderBase(DirectoryInfo directory, string filename)

public async ValueTask<SettingsContext<T>> LoadAsync()
{
await default(HopToThreadPoolAwaitable); // Force blocking IO to run on a background thread
directory.Create();

LSettings settings = new(directory, ClonableFreezerFactory.Instance, JsonSerializerFactory.Instance, JsonSerializerFactory.Instance);
Expand All @@ -33,7 +34,11 @@ public async ValueTask<SettingsContext<T>> LoadAsync()
{
settingsSet = await settings.Load<T>(filename).ConfigureAwait(false);
}
#if DEBUG
catch (Exception) when (!Debugger.IsAttached)
#else
catch (Exception)
#endif
{
try
{
Expand All @@ -49,7 +54,7 @@ public async ValueTask<SettingsContext<T>> LoadAsync()
}
settingsSet.Autosave = true;
SettingsContext<T> result = new(settings, settingsSet);
if (created)
if (created)
await OnSettingsCreated(result).ConfigureAwait(false);
return result;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Vocup/Settings/Model/RecentFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public RecentFile(string fileName, DateTime lastAccess, DateTime lastAvailable)
{
FileName = fileName;
LastAccess = lastAccess;
LastAvalailable = lastAvailable;
LastAvailable = lastAvailable;
}

public string FileName { get; }
Expand All @@ -25,7 +25,7 @@ public DateTime LastAccess
/// <summary>
/// Gets or sets the last time the file was available on the file system.
/// </summary>
public DateTime LastAvalailable
public DateTime LastAvailable
{
get => _lastAvailable;
set => RaiseAndSetIfChanged(ref _lastAvailable, value);
Expand Down
Loading

0 comments on commit 52859f4

Please sign in to comment.