public Span GetSpan(Line line, string style) { var lineNumber = line.Number; if (Start == End) return null; if (lineNumber < Start.Line) return null; if (lineNumber > End.Line) return null; var columnStart = (lineNumber == Start.Line) ? Start.Column : 0; var columnEnd = (lineNumber == End.Line) ? End.Column : line.Text.Length; var selection = new Span(columnStart, columnEnd - columnStart, style); return selection; }
public IEnumerable<Span> SplitWith(Span splitter) { if (!Intersects(splitter) || splitter.Length == 0) { yield return this; yield break; } if (Start < splitter.Start) yield return new Span(Start, splitter.Start - Start, Style); yield return splitter; if (End > splitter.End) yield return new Span(splitter.End, End - splitter.End, Style); }
void PaintSpan(Span span, float offset) { var style = styleProvider.GetStyle(span.Style); if (style.background != null) g.FillRectangle(style.background, offset, lineOffset, span.renderCache.Width, geometry.LineHeight); g.DrawString(span.renderCache.Text, geometry.Font, style.foreground, offset, lineOffset, geometry.Format); switch (style.decoration) { case Decoration.RedSquiggle: PaintSquigglyUnderline(span, offset, Pens.Red); break; case Decoration.GreenSquiggle: PaintSquigglyUnderline(span, offset, Pens.Green); break; case Decoration.BlueSquiggle: PaintSquigglyUnderline(span, offset, Pens.Blue); break; } }
void PaintSquigglyUnderline(Span span, float offset, Pen pen) { int dy = 1; float bl = lineOffset + geometry.LineHeight - 2.0f; for (var x = offset; x < offset + span.renderCache.Width; x += 2) { g.DrawLine(pen, x, bl + dy, x + 2, bl - dy); dy = -dy; } }
public RenderCache(Span span, TextGeometry geometry, Line line, int charOffset) { Width = geometry.MeasureString(line.Text.Substring(span.Start, span.Length), charOffset, out Text); }
bool Intersects(Span other) { return End > other.Start && Start < other.End; }
bool Engulfs(Span other) { return Start <= other.Start && End >= other.End; }
IEnumerable<Span> ChopWith(Span other) { if (!Intersects(other)) yield return this; else if (other.Engulfs(this)) yield return other; else { if (Start < other.Start) yield return ChopEnd(other.Start); yield return other; if (End > other.End) yield return ChopStart(other.End); } }