using Qrakhen.Qamp.Memory; using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; namespace Qrakhen.Qamp.Editor.Controls; public partial class LineRenderer : UserControl { private readonly Typeface _typeface = new(new FontFamily("Consolas"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); private const double FontSize = 14; private const double LineHeight = 18; public Pen Pen { get; set; } public Brush Highlighter { get; set; } public LineRenderer() { Height = LineHeight; SnapsToDevicePixels = true; Highlighter = new SolidColorBrush(Color.FromArgb(0xff, 0x24, 0x92, 0x72)); Pen = new Pen(Highlighter, 2); } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if (string.IsNullOrEmpty(LineBuffer.Cached)) return; var formattedText = TextHelper.GetText( LineBuffer.Cached, FontSize, Brushes.White, VisualTreeHelper.GetDpi(this).PixelsPerDip ); var x = Random.Shared.Next(0, LineBuffer.Tail); var s = new BufferSpan(x, Random.Shared.Next(x, LineBuffer.Tail)); Selection = s; var highlighter = TextHelper.GetText( new string(' ', Selection.Start) + new string('█', Selection.End - Selection.Start), FontSize, Highlighter, VisualTreeHelper.GetDpi(this).PixelsPerDip ); drawingContext.DrawText(highlighter, new Point(2, 0)); drawingContext.DrawText(formattedText, new Point(2, 0)); } public static readonly DependencyProperty LineBufferProperty = DependencyProperty.Register( nameof(LineBuffer), typeof(LineBuffer), typeof(LineRenderer), new FrameworkPropertyMetadata(null, OnLineBufferChanged)); public LineBuffer LineBuffer { get => (LineBuffer)GetValue(LineBufferProperty); set => SetValue(LineBufferProperty, value); } private static void OnLineBufferChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is LineRenderer renderer) { if (e.OldValue is LineBuffer oldBuffer && oldBuffer != null) { oldBuffer.PropertyChanged -= renderer.OnLineBufferPropertyChanged; } if (e.NewValue is LineBuffer newBuffer && newBuffer != null) { newBuffer.PropertyChanged += renderer.OnLineBufferPropertyChanged; } renderer.InvalidateVisual(); } } private void OnLineBufferPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(LineBuffer.Cached)) InvalidateVisual(); } public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register( nameof(Selection), typeof(BufferSpan), typeof(LineRenderer), new FrameworkPropertyMetadata(BufferSpan.None, OnSelectionChanged)); public BufferSpan Selection { get => (BufferSpan)GetValue(SelectionProperty); set => SetValue(SelectionProperty, value); } private static void OnSelectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is LineRenderer renderer) { if (e.OldValue is LineBuffer oldBuffer && oldBuffer != null) { oldBuffer.PropertyChanged -= renderer.OnLineBufferPropertyChanged; } if (e.NewValue is LineBuffer newBuffer && newBuffer != null) { newBuffer.PropertyChanged += renderer.OnLineBufferPropertyChanged; } renderer.InvalidateVisual(); } } }