Forge
csharp4405de34
1using System.Text;
2
3namespace CascadeIDE.Services.ChordNotation;
4
5/// <summary>Фабрика и общая логика порядка модификаторов (Control → Alt → Shift → Meta).</summary>
6public static class ChordNotationRenderer
7{
8 /// <summary>Пробел между шагами последовательности (как во вводе KeyGesture).</summary>
9 public const char StepSeparator = ' ';
10
11 public static IChordNotationRenderer Windows { get; } = new WindowsChordNotationRenderer();
12
13 public static IChordNotationRenderer MacSymbols { get; } = new MacSymbolChordNotationRenderer();
14
15 /// <summary>Третий вид: сегменты для визуальных «клавиш» (<see cref="ChordKeycapStrip"/>).</summary>
16 public static ChordKeycapSequence BuildKeycapLayout(NormalizedKeySequence? sequence, ChordKeycapLabelFlavor flavor = ChordKeycapLabelFlavor.WindowsWords) =>
17 ChordKeycapLayoutBuilder.Build(sequence, flavor);
18
19 /// <summary>Один аккорд (без последовательности шагов) — для подписи к одному жесту.</summary>
20 public static string FormatChord(ChordModifierKeys modifiers, string keySymbol, ChordNotationRenderFlavor flavor) =>
21 flavor == ChordNotationRenderFlavor.MacSymbols
22 ? MacSymbolChordNotationRenderer.RenderChord(modifiers, keySymbol)
23 : WindowsChordNotationRenderer.RenderChord(modifiers, keySymbol);
24}
25
26public enum ChordNotationRenderFlavor
27{
28 /// <summary>Ctrl+, Alt+, Shift+, Win+ (Meta).</summary>
29 Windows,
30
31 /// <summary>⌃ ⌥ ⇧ ⌘ и ключ (Meta → ⌘).</summary>
32 MacSymbols
33}
34
35/// <summary>Ctrl+, Alt+, Shift+, Win+ между частями.</summary>
36public sealed class WindowsChordNotationRenderer : IChordNotationRenderer
37{
38 public string Render(NormalizedKeySequence? sequence)
39 {
40 if (sequence is null || sequence.Steps.Count == 0)
41 return "";
42
43 var sb = new StringBuilder();
44 for (var i = 0; i < sequence.Steps.Count; i++)
45 {
46 if (i > 0)
47 sb.Append(ChordNotationRenderer.StepSeparator);
48 switch (sequence.Steps[i])
49 {
50 case NormalizedChordStep ch:
51 sb.Append(RenderChord(ch.Modifiers, ch.KeySymbol));
52 break;
53 case NormalizedPlainKeyStep pl:
54 sb.Append(pl.KeySymbol);
55 break;
56 }
57 }
58
59 return sb.ToString();
60 }
61
62 internal static string RenderChord(ChordModifierKeys modifiers, string keySymbol)
63 {
64 var sb = new StringBuilder(24);
65 AppendWindowsModifiers(sb, modifiers);
66 if (sb.Length > 0)
67 sb.Append('+');
68 sb.Append(keySymbol);
69 return sb.ToString();
70 }
71
72 private static void AppendWindowsModifiers(StringBuilder sb, ChordModifierKeys m)
73 {
74 void Part(string label)
75 {
76 if (sb.Length > 0)
77 sb.Append('+');
78 sb.Append(label);
79 }
80
81 if (m.HasFlag(ChordModifierKeys.Control))
82 Part("Ctrl");
83 if (m.HasFlag(ChordModifierKeys.Alt))
84 Part("Alt");
85 if (m.HasFlag(ChordModifierKeys.Shift))
86 Part("Shift");
87 if (m.HasFlag(ChordModifierKeys.Meta))
88 Part("Win");
89 }
90}
91
92/// <summary>⌃⌥⇧⌘ без «+» между глифами; ключ в конце.</summary>
93public sealed class MacSymbolChordNotationRenderer : IChordNotationRenderer
94{
95 public string Render(NormalizedKeySequence? sequence)
96 {
97 if (sequence is null || sequence.Steps.Count == 0)
98 return "";
99
100 var sb = new StringBuilder();
101 for (var i = 0; i < sequence.Steps.Count; i++)
102 {
103 if (i > 0)
104 sb.Append(ChordNotationRenderer.StepSeparator);
105 switch (sequence.Steps[i])
106 {
107 case NormalizedChordStep ch:
108 sb.Append(RenderChord(ch.Modifiers, ch.KeySymbol));
109 break;
110 case NormalizedPlainKeyStep pl:
111 sb.Append(pl.KeySymbol);
112 break;
113 }
114 }
115
116 return sb.ToString();
117 }
118
119 internal static string RenderChord(ChordModifierKeys modifiers, string keySymbol)
120 {
121 var sb = new StringBuilder(16);
122 if (modifiers.HasFlag(ChordModifierKeys.Control))
123 sb.Append('\u2303'); // ⌃
124 if (modifiers.HasFlag(ChordModifierKeys.Alt))
125 sb.Append('\u2325'); // ⌥
126 if (modifiers.HasFlag(ChordModifierKeys.Shift))
127 sb.Append('\u21E7'); // ⇧
128 if (modifiers.HasFlag(ChordModifierKeys.Meta))
129 sb.Append('\u2318'); // ⌘
130 sb.Append(keySymbol);
131 return sb.ToString();
132 }
133}
134
View only · write via MCP/CIDE