| 1 | using Avalonia; |
| 2 | using Avalonia.Controls; |
| 3 | using Avalonia.Input; |
| 4 | using Avalonia.Threading; |
| 5 | namespace CascadeIDE.Services; |
| 6 | |
| 7 | /// <summary> |
| 8 | /// Подсветка контрола рамкой для <c>ide_highlight_control</c> в том <see cref="Window"/>, где лежит контрол |
| 9 | /// (главное, вспомогательное и т.д.). Оверлей — <c>AgentHighlightLayer</c> / <c>AgentHighlightOverlay</c> в разметке окна. |
| 10 | /// </summary> |
| 11 | public static class UiAgentHighlight |
| 12 | { |
| 13 | private static Border? _lastOverlay; |
| 14 | private static IDisposable? _hideTimer; |
| 15 | |
| 16 | public static string ShowForControl(Control control) |
| 17 | { |
| 18 | var hostWindow = TopLevel.GetTopLevel(control) as Window; |
| 19 | if (hostWindow is null) |
| 20 | return "No host window for control."; |
| 21 | |
| 22 | var canvas = hostWindow.FindControl<Canvas>("AgentHighlightLayer"); |
| 23 | var overlay = hostWindow.FindControl<Border>("AgentHighlightOverlay"); |
| 24 | if (canvas is null || overlay is null) |
| 25 | return "Highlight overlay not found (AgentHighlightLayer / AgentHighlightOverlay)."; |
| 26 | |
| 27 | if (_lastOverlay is not null && !ReferenceEquals(_lastOverlay, overlay)) |
| 28 | _lastOverlay.IsVisible = false; |
| 29 | |
| 30 | var pt = control.TranslatePoint(new Point(0, 0), canvas); |
| 31 | if (pt is null) |
| 32 | return "Could not get control position."; |
| 33 | |
| 34 | var w = control.Bounds.Width; |
| 35 | var h = control.Bounds.Height; |
| 36 | |
| 37 | Canvas.SetLeft(overlay, pt.Value.X); |
| 38 | Canvas.SetTop(overlay, pt.Value.Y); |
| 39 | overlay.Width = w; |
| 40 | overlay.Height = h; |
| 41 | overlay.IsVisible = true; |
| 42 | _lastOverlay = overlay; |
| 43 | |
| 44 | _hideTimer?.Dispose(); |
| 45 | _hideTimer = DispatcherTimer.RunOnce(() => |
| 46 | { |
| 47 | overlay.IsVisible = false; |
| 48 | _hideTimer = null; |
| 49 | }, TimeSpan.FromSeconds(3)); |
| 50 | |
| 51 | return "OK"; |
| 52 | } |
| 53 | |
| 54 | /// <summary>Контрол под курсором в любом окне приложения (паритет с <see cref="UiColorsUnderCursor"/>).</summary> |
| 55 | public static Control? FindControlUnderCursorAnyWindow(Window fallbackMainWindow) => |
| 56 | UiPointerClientPosition.TryGetPointerOverControlAnywhere() |
| 57 | ?? UiPointerClientPosition.TryGetControlUnderPointer(fallbackMainWindow); |
| 58 | } |
| 59 | |