SelectionAdorner.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using System.Collections.Generic;
  3. using Avalonia;
  4. using Avalonia.Controls;
  5. using Avalonia.Media;
  6. namespace TextTestApp
  7. {
  8. public class SelectionAdorner : Control
  9. {
  10. public static readonly StyledProperty<IBrush?> FillProperty =
  11. AvaloniaProperty.Register<SelectionAdorner, IBrush?>(nameof(Fill));
  12. public static readonly StyledProperty<IBrush?> StrokeProperty =
  13. AvaloniaProperty.Register<SelectionAdorner, IBrush?>(nameof(Stroke));
  14. public static readonly StyledProperty<Matrix> TransformProperty =
  15. AvaloniaProperty.Register<SelectionAdorner, Matrix>(nameof(Transform), Matrix.Identity);
  16. public Matrix Transform
  17. {
  18. get => this.GetValue(TransformProperty);
  19. set => SetValue(TransformProperty, value);
  20. }
  21. public IBrush? Stroke
  22. {
  23. get => GetValue(StrokeProperty);
  24. set => SetValue(StrokeProperty, value);
  25. }
  26. public IBrush? Fill
  27. {
  28. get => GetValue(FillProperty);
  29. set => SetValue(FillProperty, value);
  30. }
  31. private IList<Rect>? _rectangles;
  32. public IList<Rect>? Rectangles
  33. {
  34. get => _rectangles;
  35. set
  36. {
  37. _rectangles = value;
  38. InvalidateVisual();
  39. }
  40. }
  41. public SelectionAdorner()
  42. {
  43. AffectsRender<SelectionAdorner>(FillProperty, StrokeProperty, TransformProperty);
  44. }
  45. public override void Render(DrawingContext context)
  46. {
  47. var rectangles = Rectangles;
  48. if (rectangles == null)
  49. return;
  50. using (context.PushTransform(Transform))
  51. {
  52. Pen pen = new Pen(Stroke, 1);
  53. for (int i = 0; i < rectangles.Count; i++)
  54. {
  55. Rect rectangle = rectangles[i];
  56. Rect normalized = rectangle.Width < 0 ? new Rect(rectangle.TopRight, rectangle.BottomLeft) : rectangle;
  57. if (rectangles[i].Width == 0)
  58. context.DrawLine(pen, rectangle.TopLeft, rectangle.BottomRight);
  59. else
  60. context.DrawRectangle(Fill, pen, normalized);
  61. RenderCue(context, pen, rectangle.TopLeft, 5, isFilled: true);
  62. RenderCue(context, pen, rectangle.TopRight, 5, isFilled: false);
  63. }
  64. }
  65. }
  66. private void RenderCue(DrawingContext context, IPen pen, Point p, double size, bool isFilled)
  67. {
  68. context.DrawGeometry(pen.Brush, pen, new PolylineGeometry(
  69. [
  70. new Point(p.X - size / 2, p.Y - size),
  71. new Point(p.X + size / 2, p.Y - size),
  72. new Point(p.X, p.Y),
  73. new Point(p.X - size / 2, p.Y - size),
  74. ], isFilled));
  75. }
  76. }
  77. }