| 1 | #nullable enable |
| 2 | using Avalonia.Input; |
| 3 | |
| 4 | namespace CascadeIDE.Services; |
| 5 | |
| 6 | /// <summary>Разбор корневого жеста CascadeChord из merged <c>hotkeys.toml</c> (ADR 0060).</summary> |
| 7 | public static class CascadeChordHotkey |
| 8 | { |
| 9 | public const string TomlKey = "cascade_chord"; |
| 10 | public const string DefaultGestureString = "Ctrl+K"; |
| 11 | |
| 12 | /// <summary> |
| 13 | /// Жест для первого шага аккорда: ключ <see cref="TomlKey"/> или <see cref="DefaultGestureString"/>; |
| 14 | /// при неразборчивой строке — повторный разбор <see cref="DefaultGestureString"/>. |
| 15 | /// </summary> |
| 16 | public static KeyGesture ResolveRootGesture(IReadOnlyDictionary<string, string> mergedMap) |
| 17 | { |
| 18 | var s = DefaultGestureString; |
| 19 | if (mergedMap.TryGetValue(TomlKey, out var v) && !string.IsNullOrWhiteSpace(v)) |
| 20 | s = v.Trim(); |
| 21 | try |
| 22 | { |
| 23 | return KeyGesture.Parse(s); |
| 24 | } |
| 25 | catch |
| 26 | { |
| 27 | return KeyGesture.Parse(DefaultGestureString); |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | /// <summary> |
| 32 | /// Совпадение корня аккорда с событием: сначала <see cref="KeyGesture.Matches(KeyEventArgs)"/>, |
| 33 | /// затем fallback по <see cref="KeyEventArgs.PhysicalKey"/> = <see cref="PhysicalKey.K"/> при тех же |
| 34 | /// <see cref="KeyEventArgs.KeyModifiers"/>, что у <paramref name="resolved"/>. |
| 35 | /// Иначе при русской (и др.) раскладке <c>e.Key</c> ≠ <c>Key.K</c>, хотя нажата та же физическая клавиша — корень не срабатывал. |
| 36 | /// </summary> |
| 37 | public static bool RootGestureMatches(KeyGesture resolved, KeyEventArgs e) => |
| 38 | KeyGestureChordMatching.Matches(resolved, e); |
| 39 | |
| 40 | /// <summary>Вторая ветка сопоставления (тесты): нормализованные модификаторы + физическая K.</summary> |
| 41 | public static bool MatchesPhysicalKeyFallback(KeyGesture resolved, PhysicalKey physicalKey, KeyModifiers modifiers) |
| 42 | { |
| 43 | if (KeyGestureChordMatching.NormalizeChordModifiers(modifiers) != |
| 44 | KeyGestureChordMatching.NormalizeChordModifiers(resolved.KeyModifiers)) |
| 45 | return false; |
| 46 | return physicalKey == PhysicalKey.K && resolved.Key == Key.K; |
| 47 | } |
| 48 | } |
| 49 | |