How to add kind of validation for text? #411
-
Hey everyone, Do you know how to add visual styles to text in editor? TextMate adding great syntax highlighting, but now I want to add some text validation and didn't find yet how to add visually "incorrect" text indication. If you already did it, or have any ideas, please share with me |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Unfortunately there is no squiggly lines support as far as I know. I think that it can be easily implemented using a custom background renderer. @Gillibald are there any primitives in Avalonia to draw them or should be manually done? |
Beta Was this translation helpful? Give feedback.
-
I found transformers, and at least we can set Transformer example public class ValidationDocumentTransformer : DocumentColorizingTransformer
{
protected override void ColorizeLine(DocumentLine line)
{
var lineStartOffset = line.Offset;
var text = CurrentContext.Document.GetText(line.Offset, line.Length);
// check for {{...}} in the text
var matches = Regex.Matches(text, @"{{(.+)}}");
foreach (Match match in matches)
{
// TODO validation logic here
if (match.Groups[1].Value.Equals("valid_text", StringComparison.Ordinal))
continue;
var startOffset = lineStartOffset + match.Index;
ChangeLinePart(
startOffset,
startOffset + match.Length,
element =>
{
// TODO apply text decorations here
element.TextRunProperties.SetBackgroundBrush(Brushes.Red);
});
}
}
} In example project I added line transformer in // custom transformers
_textEditor!.TextArea.TextView.LineTransformers.Add(new ValidationDocumentTransformer()); And result: |
Beta Was this translation helpful? Give feedback.
-
In case it is still relevant, I have a different solution: I am using a custom Screenshot: Example: public class MarkerRenderer : IBackgroundRenderer
{
public TextSegmentCollection<Marker> Markers { get; } = [];
public KnownLayer Layer => KnownLayer.Background;
void IBackgroundRenderer.Draw(TextView textView, DrawingContext drawingContext)
{
ArgumentNullException.ThrowIfNull(textView);
ArgumentNullException.ThrowIfNull(drawingContext);
if (Markers.Count == 0)
return;
var visualLines = textView.VisualLines;
if (visualLines.Count == 0)
return;
int viewStart = visualLines[0].FirstDocumentLine.Offset;
int viewEnd = visualLines[^1].LastDocumentLine.EndOffset;
foreach (var marker in Markers.FindOverlappingSegments(viewStart, viewEnd - viewStart))
marker.Draw(textView, drawingContext);
}
}
public abstract class Marker : TextSegment
{
public abstract void Draw(TextView textView, DrawingContext drawingContext);
}
public class ZigzagMarker : Marker
{
private static readonly ImmutablePen s_defaultPen = new(Brushes.Red, 0.75);
public IPen? Pen { get; set; }
public override void Draw(TextView textView, DrawingContext drawingContext)
{
foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, this))
{
if (rect.Width <= 1 || rect.Height <= 1)
{
// Current segment is inside a fold.
continue;
}
var pen = Pen ?? s_defaultPen;
var start = rect.BottomLeft;
var end = rect.BottomRight;
var geometry = new StreamGeometry();
using (var context = geometry.Open())
{
context.BeginFigure(start, false);
const double zigLength = 3;
const double zigHeight = 3;
int numberOfZigs = (int)double.Round((end.X - start.X) / zigLength);
if (numberOfZigs < 2)
numberOfZigs = 2;
for (int i = 0; i < numberOfZigs; i++)
{
var p = new Point(
start.X + (i + 1) * zigLength,
start.Y - (i % 2) * zigHeight + 1);
context.LineTo(p);
}
}
drawingContext.DrawGeometry(null, pen, geometry);
}
}
}
// Add a squiggly line.
MarkerRenderer markerRenderer = new();
MyTextEditor.TextArea.TextView.BackgroundRenderers.Add(markerRenderer);
markerRenderer.Markers.Add(new ZigzagMarker
{
StartOffset = 10,
Length = 10
});
MyTextEditor.TextArea.TextView.InvalidateLayer(markerRenderer.Layer); |
Beta Was this translation helpful? Give feedback.
I found transformers, and at least we can set
Background
if it wasn't set by TextMate rules before.Transformer example