added multilang and settings

This commit is contained in:
2026-08-08 21:48:16 +05:00
parent 3d614255d8
commit d146fd442a
18 changed files with 1115 additions and 72 deletions
@@ -0,0 +1,93 @@
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CursorLang.Models;
using CursorLang.Services;
namespace CursorLang.ViewModels;
/// <summary>Вариант выбора в списке: значение и его подпись на текущем языке.</summary>
public sealed record EnumOption<T>(T Value, string Display);
/// <summary>
/// Окно настроек. Значения правятся прямо в <see cref="AppSettings"/>,
/// поэтому подсказка подхватывает их сразу, без кнопки «Применить».
/// </summary>
public sealed partial class SettingsViewModel : ObservableObject, IDisposable
{
private static readonly Color[] Palette =
[
Color.FromRgb(0x20, 0x20, 0x20),
Color.FromRgb(0x00, 0x00, 0x00),
Color.FromRgb(0x1E, 0x3A, 0x8A),
Color.FromRgb(0x0F, 0x76, 0x6E),
Color.FromRgb(0x7C, 0x2D, 0x12),
Color.FromRgb(0x86, 0x19, 0x8F),
Color.FromRgb(0xB9, 0x1C, 0x1C),
Color.FromRgb(0xF5, 0xF5, 0xF5),
];
public SettingsViewModel(AppSettings settings, ILocalizationService localization)
{
Settings = settings;
Localization = localization;
// Язык интерфейса — такая же настройка, как остальные, и хранится там же
Localization.CurrentLanguage = settings.Language;
Settings.PropertyChanged += OnSettingsChanged;
Localization.PropertyChanged += OnLocalizationChanged;
BuildLocalizedOptions();
}
public AppSettings Settings { get; }
public ILocalizationService Localization { get; }
public IReadOnlyList<Color> BackgroundPalette { get; } = Palette;
public IReadOnlyList<EnumOption<PopupPlacementMode>> PlacementModes { get; private set; } = [];
public IReadOnlyList<EnumOption<CursorCorner>> CursorCorners { get; private set; } = [];
public IReadOnlyList<EnumOption<ScreenPosition>> ScreenPositions { get; private set; } = [];
public void Dispose()
{
Settings.PropertyChanged -= OnSettingsChanged;
Localization.PropertyChanged -= OnLocalizationChanged;
}
private void OnSettingsChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(AppSettings.Language))
{
Localization.CurrentLanguage = Settings.Language;
}
}
// Подписи вариантов приходят из ресурсов, поэтому при смене языка
// списки нужно собрать заново — привязки сами перечитают их
private void OnLocalizationChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == Binding.IndexerName)
{
BuildLocalizedOptions();
}
}
private void BuildLocalizedOptions()
{
PlacementModes = BuildOptions<PopupPlacementMode>(nameof(PopupPlacementMode));
CursorCorners = BuildOptions<CursorCorner>(nameof(CursorCorner));
ScreenPositions = BuildOptions<ScreenPosition>(nameof(ScreenPosition));
OnPropertyChanged(nameof(PlacementModes));
OnPropertyChanged(nameof(CursorCorners));
OnPropertyChanged(nameof(ScreenPositions));
}
private EnumOption<T>[] BuildOptions<T>(string resourcePrefix) where T : struct, Enum =>
[.. Enum.GetValues<T>().Select(value => new EnumOption<T>(value, Localization[$"{resourcePrefix}_{value}"]))];
}