添加项目文件。

This commit is contained in:
GG Z
2026-02-23 16:55:06 +08:00
parent 7a0bf44207
commit 37217063b9
117 changed files with 4885 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using Microsoft.CodeAnalysis;
using ScriptPad.Roslyn;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace ScriptPad.Editor
{
public class TextMarkerService : IBackgroundRenderer
{
private readonly TextEditor textEditor;
public CsScript Script { get; set; }
private readonly TextSegmentCollection<TextMarker> markers;
private ToolTip toolTip;
DispatcherTimer Timer = new DispatcherTimer();
public TextMarkerService(TextEditor textEditor, CsScript script)
{
this.textEditor = textEditor;
this.Script = script;
this.markers = new TextSegmentCollection<TextMarker>(textEditor.Document);
TextView textView = textEditor.TextArea.TextView;
textView.BackgroundRenderers.Add(this);
textView.MouseHover += TextViewMouseHover;
textView.MouseHoverStopped += TextViewMouseHoverStopped;
textView.VisualLinesChanged += TextViewVisualLinesChanged;
Timer.Interval = TimeSpan.FromSeconds(2);
Timer.Tick += Timer_Tick;
Timer.Start();
}
private async void Timer_Tick(object sender, EventArgs e)
{
var document = textEditor.Document;
Clear();
var diagnostics = await Script.GetDiagnostics();
var listItems = diagnostics
.Where(x => x.Severity != DiagnosticSeverity.Hidden)
.Select(ErrorListItem.CreateErrorListItem);
foreach (var item in listItems)
{
if (item.ErrorSeverity == ErrorSeverity.Info)
continue;
var startOffset = document.GetOffset(new TextLocation(item.StartLine + 1, item.StartColumn + 1));
var endOffset = document.GetOffset(new TextLocation(item.EndLine + 1, item.EndColumn + 1));
if (item.ErrorSeverity == ErrorSeverity.Error)
Create(startOffset, endOffset - startOffset, item.Description, Colors.Red);
else
Create(startOffset, endOffset - startOffset, item.Description, Colors.DarkGreen);
}
}
public KnownLayer Layer => KnownLayer.Selection;
public void Create(int offset, int length, string message, Color color)
{
var marker = new TextMarker(offset, length, message, color);
markers.Add(marker);
textEditor.TextArea.TextView.Redraw(marker);
}
public void Clear()
{
var oldMarkers = markers.ToArray();
markers.Clear();
foreach (TextMarker m in oldMarkers)
{
textEditor.TextArea.TextView.Redraw(m);
}
}
public void Draw(TextView textView, DrawingContext drawingContext)
{
if (!markers.Any() || !textView.VisualLinesValid)
{
return;
}
var visualLines = textView.VisualLines;
if (visualLines.Count == 0)
{
return;
}
int viewStart = visualLines.First().FirstDocumentLine.Offset;
int viewEnd = visualLines.Last().LastDocumentLine.EndOffset;
foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart))
{
foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker))
{
Point startPoint = rect.BottomLeft;
Point endPoint = rect.BottomRight;
var pen = new Pen(new SolidColorBrush(marker.MarkerColor), 1);
pen.Freeze();
const double offset = 2.5;
int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
var geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open())
{
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, offset, count).ToArray(), true, false);
}
geometry.Freeze();
drawingContext.DrawGeometry(Brushes.Transparent, pen, geometry);
break;
}
}
}
public void Transform(ITextRunConstructionContext context, IList<VisualLineElement> elements)
{
}
private void TextViewMouseHover(object sender, MouseEventArgs e)
{
if (!markers.Any()) { return; }
TextViewPosition? position = textEditor.TextArea.TextView.GetPositionFloor(
e.GetPosition(textEditor.TextArea.TextView) + textEditor.TextArea.TextView.ScrollOffset);
if (position.HasValue)
{
TextLocation logicalPosition = position.Value.Location;
int offset = textEditor.Document.GetOffset(logicalPosition);
var markersAtOffset = markers.FindSegmentsContaining(offset);
TextMarker marker = markersAtOffset.LastOrDefault(m => !string.IsNullOrEmpty(m.Message));
if (marker != null)
{
if (toolTip == null)
{
toolTip = new ToolTip();
toolTip.Closed += (s2, e2) => toolTip = null;
toolTip.PlacementTarget = textEditor;
toolTip.Content = new TextBlock
{
Text = marker.Message,
TextWrapping = TextWrapping.Wrap
};
toolTip.IsOpen = true;
e.Handled = true;
}
}
}
}
private void TextViewMouseHoverStopped(object sender, MouseEventArgs e)
{
if (toolTip != null)
{
toolTip.IsOpen = false;
e.Handled = true;
}
}
private void TextViewVisualLinesChanged(object sender, EventArgs e)
{
//if (toolTip != null)
//{
// toolTip.IsOpen = false;
//}
}
private static IEnumerable<Point> CreatePoints(Point start, double offset, int count)
{
for (int i = 0; i < count; i++)
{
yield return new Point(start.X + (i * offset), start.Y - ((i + 1) % 2 == 0 ? offset : 0));
}
}
}
}