151 lines
6.0 KiB
C#
151 lines
6.0 KiB
C#
using System.Drawing;
|
|
using System.Text.Json.Serialization;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
namespace CursorLang.Core.Models;
|
|
|
|
/// <summary>
|
|
/// The application settings, as the settings window writes them to settings.json.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The colours are <see cref="System.Drawing.Color"/> rather than
|
|
/// <c>System.Windows.Media.Color</c>. The former lives in System.Drawing.Primitives,
|
|
/// which is part of the base runtime and brings neither WPF nor GDI+ along; the latter
|
|
/// is WindowsBase, and this type is read by the agent, which must stay clear of it.
|
|
/// The settings window turns them into brushes in its converters.
|
|
///
|
|
/// Both processes hold an instance of this, but only the settings window writes: the
|
|
/// agent re-reads the file and pours the fresh values into the instance it already has,
|
|
/// so everything subscribed to it stays subscribed. See <see cref="CopyFrom"/>.
|
|
/// </remarks>
|
|
public sealed partial class AppSettings : ObservableObject
|
|
{
|
|
/// <summary>The interface language as a culture code: "ru", "en".</summary>
|
|
[ObservableProperty]
|
|
private string _language = "en";
|
|
|
|
/// <summary>The look of the settings window.</summary>
|
|
[ObservableProperty]
|
|
private AppTheme _theme = AppTheme.System;
|
|
|
|
/// <summary>Where the popup is shown: at the cursor, at the caret or at a fixed point.</summary>
|
|
[ObservableProperty]
|
|
private PopupPlacementMode _placementMode = PopupPlacementMode.AtCursor;
|
|
|
|
// The side and the offset are stored per mode: the cursor and the caret call for
|
|
// different settings, and switching the mode does not reset them
|
|
|
|
/// <summary>The side of the cursor the popup is put on.</summary>
|
|
[ObservableProperty]
|
|
private AnchorSide _cursorSide = AnchorSide.BottomRight;
|
|
|
|
/// <summary>The offset from the cursor in WPF units.</summary>
|
|
[ObservableProperty]
|
|
private double _cursorOffset = 16;
|
|
|
|
/// <summary>The side of the caret the popup is put on.</summary>
|
|
[ObservableProperty]
|
|
private AnchorSide _caretSide = AnchorSide.BottomRight;
|
|
|
|
/// <summary>The offset from the caret in WPF units.</summary>
|
|
[ObservableProperty]
|
|
private double _caretOffset = 16;
|
|
|
|
/// <summary>
|
|
/// The place on the monitor for the <see cref="PopupPlacementMode.FixedPoint"/> mode.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private ScreenPosition _screenPosition = ScreenPosition.BottomRight;
|
|
|
|
/// <summary>The offset from the monitor edge in WPF units.</summary>
|
|
[ObservableProperty]
|
|
private double _screenMargin = 24;
|
|
|
|
/// <summary>The size of the layout name in the popup, in WPF units.</summary>
|
|
[ObservableProperty]
|
|
private double _fontSize = 20;
|
|
|
|
/// <summary>The popup opacity: 1.0 is fully opaque.</summary>
|
|
[ObservableProperty]
|
|
private double _opacity = 0.9;
|
|
|
|
/// <summary>How long the popup stays on screen, in milliseconds.</summary>
|
|
[ObservableProperty]
|
|
private double _durationMilliseconds = 500;
|
|
|
|
/// <summary>
|
|
/// Intercept Caps Lock and switch the layout with it instead of changing the case.
|
|
/// Off by default: the application must not change the behaviour of the system
|
|
/// until it is asked to.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _useCapsLockHotkey;
|
|
|
|
/// <summary>
|
|
/// After how long a Caps Lock hold cancels the switch, in milliseconds.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private double _capsLockHoldMilliseconds = 300;
|
|
|
|
/// <summary>
|
|
/// Ask the repository about new versions on startup. A check can always be
|
|
/// started by hand — this setting turns off only the automatic one.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _checkForUpdates = true;
|
|
|
|
/// <summary>
|
|
/// When the application last asked about new versions successfully.
|
|
/// Stored so as not to go to the network on every startup.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private DateTimeOffset? _lastUpdateCheck;
|
|
|
|
/// <summary>The fill of the popup. The opacity is set by <see cref="Opacity"/>.</summary>
|
|
[ObservableProperty]
|
|
private Color _backgroundColor = Color.FromArgb(0xFF, 0x20, 0x20, 0x20);
|
|
|
|
/// <summary>The colour of the layout name in the popup.</summary>
|
|
[ObservableProperty]
|
|
private Color _foregroundColor = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
|
|
|
|
/// <summary><see cref="DurationMilliseconds"/> as a <see cref="TimeSpan"/>.</summary>
|
|
[JsonIgnore]
|
|
public TimeSpan Duration => TimeSpan.FromMilliseconds(DurationMilliseconds);
|
|
|
|
/// <summary><see cref="CapsLockHoldMilliseconds"/> as a <see cref="TimeSpan"/>.</summary>
|
|
[JsonIgnore]
|
|
public TimeSpan CapsLockHoldDelay => TimeSpan.FromMilliseconds(CapsLockHoldMilliseconds);
|
|
|
|
/// <summary>
|
|
/// Takes the values of another instance over, raising a change notification for
|
|
/// every property that has actually moved.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This is how the agent learns about an edit: the settings window is a separate
|
|
/// process, so the fresh values arrive as a freshly parsed instance and are poured
|
|
/// into the one everything is already bound to, rather than replacing it.
|
|
/// </remarks>
|
|
public void CopyFrom(AppSettings other)
|
|
{
|
|
Language = other.Language;
|
|
Theme = other.Theme;
|
|
PlacementMode = other.PlacementMode;
|
|
CursorSide = other.CursorSide;
|
|
CursorOffset = other.CursorOffset;
|
|
CaretSide = other.CaretSide;
|
|
CaretOffset = other.CaretOffset;
|
|
ScreenPosition = other.ScreenPosition;
|
|
ScreenMargin = other.ScreenMargin;
|
|
FontSize = other.FontSize;
|
|
Opacity = other.Opacity;
|
|
DurationMilliseconds = other.DurationMilliseconds;
|
|
UseCapsLockHotkey = other.UseCapsLockHotkey;
|
|
CapsLockHoldMilliseconds = other.CapsLockHoldMilliseconds;
|
|
CheckForUpdates = other.CheckForUpdates;
|
|
LastUpdateCheck = other.LastUpdateCheck;
|
|
BackgroundColor = other.BackgroundColor;
|
|
ForegroundColor = other.ForegroundColor;
|
|
}
|
|
}
|