using System.Windows; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Threading; namespace Qrakhen.Qamp.Editor.Controls; public class Caret : Adorner { private readonly Pen _pen; private readonly double _height; private readonly Brush _brush; private bool _blink; private Point _cursorPosition; private Point _targetPosition; private (Point from, Point to)[] _lines = []; private DispatcherTimer _blinkTimer; private DispatcherTimer _moveTimer; public Caret(UIElement adornedElement, Brush brush, double height = 18, double thickness = 1.72) : base(adornedElement) { IsHitTestVisible = false; _height = height; _brush = brush; _pen = new Pen(brush, 1.92); _blinkTimer = new DispatcherTimer(); _blinkTimer.Interval = TimeSpan.FromMilliseconds(428); _blinkTimer.Tick += new EventHandler((s, e) => { Toggle(_blink = !_blink); }); _blinkTimer.Start(); _moveTimer = new DispatcherTimer(); _moveTimer.Interval = TimeSpan.FromMilliseconds(12); _moveTimer.Tick += new EventHandler((s, e) => { var delta = _targetPosition - _cursorPosition; if (delta.Length > 2.4) _cursorPosition += delta * .84; else { _cursorPosition = _targetPosition; _moveTimer.Stop(); _blinkTimer.Start(); } InvalidateVisual(); }); } public void Toggle(bool hide) { _pen.Brush = hide ? Brushes.Transparent : _brush; } public void UpdateSelection((Point from, Point to)[] lines) { _lines = lines; InvalidateVisual(); } public void UpdatePosition(Point newPosition) { _cursorPosition = _targetPosition = newPosition; Toggle(_blink = false); //_blinkTimer.Stop(); //_moveTimer.Start(); InvalidateVisual(); } protected override void OnRender(DrawingContext drawingContext) { Point startPoint = new(_cursorPosition.X, _cursorPosition.Y); Point endPoint = new(_cursorPosition.X, _cursorPosition.Y + _height); drawingContext.DrawLine(_pen, startPoint, endPoint); } }