Forge
csharpdeeb25a2
1#nullable enable
2using Avalonia;
3using Avalonia.Input.TextInput;
4using Avalonia.Media;
5
6namespace CascadeIDE.Views.Chat;
7
8/// <summary>IME/ввод для Skia composer и поля поиска Topic Navigator (ADR 0123 фаза 2).</summary>
9internal sealed class IntercomSkiaTextInputClient : TextInputMethodClient
10{
11 private readonly SkiaChatSurfaceControl _host;
12
13 public IntercomSkiaTextInputClient(SkiaChatSurfaceControl host) => _host = host;
14
15 public override Visual TextViewVisual => _host;
16
17 public override bool SupportsPreedit => !_host.IsNavigatorSearchInputActive;
18
19 public override bool SupportsSurroundingText => true;
20
21 public override string SurroundingText =>
22 _host.IsNavigatorSearchInputActive
23 ? _host.TopicNavigatorSearchQuery ?? ""
24 : _host.IsCommandLineInputActive
25 ? _host.CommandLineText ?? "/"
26 : _host.ComposerText ?? "";
27
28 public override TextSelection Selection
29 {
30 get
31 {
32 var text = SurroundingText;
33 if (_host.IsNavigatorSearchInputActive)
34 {
35 var navCaret = Math.Clamp(_host.NavigatorSearchCaretIndex, 0, text.Length);
36 return new TextSelection(navCaret, navCaret);
37 }
38
39 var caret = _host.IsCommandLineInputActive
40 ? Math.Clamp(_host.CommandLineCaretIndex, 0, text.Length)
41 : Math.Clamp(_host.ComposerCaretIndex, 0, text.Length);
42 var anchor = _host.IsCommandLineInputActive
43 ? Math.Clamp(_host.CommandLineSelectionAnchor, 0, text.Length)
44 : Math.Clamp(_host.ComposerSelectionAnchor, 0, text.Length);
45 if (anchor == caret)
46 return new TextSelection(caret, caret);
47
48 var start = Math.Min(anchor, caret);
49 var end = Math.Max(anchor, caret);
50 return new TextSelection(start, end);
51 }
52 set
53 {
54 var len = SurroundingText.Length;
55 var start = Math.Clamp(value.Start, 0, len);
56 var end = Math.Clamp(value.End, 0, len);
57 if (_host.IsNavigatorSearchInputActive)
58 {
59 _host.NavigatorSearchCaretIndex = start;
60 return;
61 }
62
63 if (_host.IsCommandLineInputActive)
64 {
65 _host.CommandLineCaretIndex = end;
66 if (start != end)
67 _host.SetCommandLineSelectionAnchor(start);
68 else
69 _host.CollapseCommandLineSelection();
70
71 return;
72 }
73
74 _host.ComposerCaretIndex = end;
75 if (start != end)
76 _host.SetComposerSelectionAnchor(start);
77 else
78 _host.CollapseComposerSelection();
79 }
80 }
81
82 public override Rect CursorRectangle =>
83 _host.IsNavigatorSearchInputActive
84 ? _host.GetNavigatorSearchCaretScreenRect()
85 : _host.IsCommandLineInputActive
86 ? _host.GetCommandLineCaretScreenRect()
87 : _host.GetComposerCaretScreenRect();
88
89 public void NotifyTextChanged() => RaiseSurroundingTextChanged();
90
91 public void NotifyCursorMoved() => RaiseCursorRectangleChanged();
92
93 public override void SetPreeditText(string? preedit)
94 {
95 if (_host.IsNavigatorSearchInputActive || _host.IsCommandLineInputActive)
96 return;
97
98 _host.ComposerPreeditText = string.IsNullOrEmpty(preedit) ? null : preedit;
99 NotifyCursorMoved();
100 _host.InvalidateVisual();
101 }
102}
103
View only · write via MCP/CIDE