using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CursorLang.Models;
using CursorLang.Services;
namespace CursorLang.ViewModels;
///
/// Вариант выбора в списке. Подпись меняется вместе с языком, а сам объект
/// живёт всё время работы окна: если пересоздавать элементы списка,
/// ComboBox сбрасывает выбранное значение.
///
public sealed class EnumOption : ObservableObject where T : struct, Enum
{
private string _display;
public EnumOption(T value, string display)
{
Value = value;
_display = display;
}
public T Value { get; }
public string Display
{
get => _display;
set => SetProperty(ref _display, value);
}
// Средства доступности берут имя элемента списка отсюда
public override string ToString() => Display;
}
///
/// Окно настроек. Значения правятся прямо в ,
/// поэтому подсказка подхватывает их сразу, без кнопки «Применить».
///
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;
PlacementModes = CreateOptions();
AnchorSides = CreateOptions();
ScreenPositions = CreateOptions();
}
public AppSettings Settings { get; }
public ILocalizationService Localization { get; }
public IReadOnlyList BackgroundPalette { get; } = Palette;
public IReadOnlyList> PlacementModes { get; }
public IReadOnlyList> AnchorSides { get; }
public IReadOnlyList> ScreenPositions { get; }
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)
{
return;
}
Translate(PlacementModes);
Translate(AnchorSides);
Translate(ScreenPositions);
}
private EnumOption[] CreateOptions() where T : struct, Enum =>
[.. Enum.GetValues().Select(value => new EnumOption(value, GetDisplayName(value)))];
private void Translate(IReadOnlyList> options) where T : struct, Enum
{
foreach (EnumOption option in options)
{
option.Display = GetDisplayName(option.Value);
}
}
// Ключ ресурса собирается из имени типа и значения: PopupPlacementMode_AtCursor
private string GetDisplayName(T value) where T : struct, Enum =>
Localization[$"{typeof(T).Name}_{value}"];
}