You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.0 KiB
187 lines
5.0 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using System.Windows.Media; |
|
using ICSharpCode.AvalonEdit.Document; |
|
using ICSharpCode.Core; |
|
using ICSharpCode.Editor; |
|
using ICSharpCode.SharpDevelop.Debugging; |
|
using ICSharpCode.SharpDevelop.Editor; |
|
|
|
namespace ICSharpCode.SharpDevelop |
|
{ |
|
/// <summary> |
|
/// Synchronizes the ITextEditors with the TaskService. It adds and removes error markers. |
|
/// </summary> |
|
public class ErrorPainter : IDisposable |
|
{ |
|
ITextEditor textEditor; |
|
ITextMarkerService markerService; |
|
|
|
public ErrorPainter(ITextEditor textEditor) |
|
{ |
|
this.textEditor = textEditor; |
|
this.markerService = this.textEditor.GetService(typeof(ITextMarkerService)) as ITextMarkerService; |
|
|
|
if (this.markerService == null) |
|
throw new InvalidOperationException("this ITextEditor has no text marker service!"); |
|
|
|
TaskService.Added += OnAdded; |
|
TaskService.Removed += OnRemoved; |
|
TaskService.Cleared += OnCleared; |
|
DebuggerService.DebugStarted += OnDebugStartedStopped; |
|
DebuggerService.DebugStopped += OnDebugStartedStopped; |
|
textEditor.Options.PropertyChanged += textEditor_Options_PropertyChanged; |
|
|
|
UpdateEnabled(); |
|
} |
|
|
|
bool isDisposed; |
|
|
|
/// <summary> |
|
/// Deregisters the event handlers so the error painter (and associated TextEditor) |
|
/// can be garbage collected. |
|
/// </summary> |
|
public void Dispose() |
|
{ |
|
if (isDisposed) |
|
return; |
|
isDisposed = true; |
|
TaskService.Added -= OnAdded; |
|
TaskService.Removed -= OnRemoved; |
|
TaskService.Cleared -= OnCleared; |
|
DebuggerService.DebugStarted -= OnDebugStartedStopped; |
|
DebuggerService.DebugStopped -= OnDebugStartedStopped; |
|
textEditor.Options.PropertyChanged -= textEditor_Options_PropertyChanged; |
|
ClearErrors(); |
|
} |
|
|
|
bool isEnabled; |
|
|
|
void OnDebugStartedStopped(object sender, EventArgs e) |
|
{ |
|
UpdateEnabled(); |
|
} |
|
|
|
void textEditor_Options_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) |
|
{ |
|
if (e.PropertyName == "UnderlineErrors") { |
|
UpdateEnabled(); |
|
} |
|
} |
|
|
|
void UpdateEnabled() |
|
{ |
|
bool newEnabled = textEditor.Options.UnderlineErrors; |
|
if (DebuggerService.IsDebuggerStarted) |
|
newEnabled = false; |
|
|
|
if (isEnabled != newEnabled) { |
|
isEnabled = newEnabled; |
|
|
|
ClearErrors(); |
|
if (newEnabled) { |
|
foreach (Task task in TaskService.Tasks) { |
|
AddTask(task); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void OnAdded(object sender, TaskEventArgs e) |
|
{ |
|
AddTask(e.Task); |
|
} |
|
|
|
void OnRemoved(object sender, TaskEventArgs e) |
|
{ |
|
markerService.RemoveAll(marker => marker.Tag == e.Task); |
|
} |
|
|
|
void OnCleared(object sender, EventArgs e) |
|
{ |
|
ClearErrors(); |
|
} |
|
|
|
/// <summary> |
|
/// Clears all TextMarkers representing errors. |
|
/// </summary> |
|
/// <returns>Returns true when there were markers deleted, false when there were no error markers.</returns> |
|
void ClearErrors() |
|
{ |
|
markerService.RemoveAll(marker => marker.Tag is Task); |
|
} |
|
|
|
bool CheckTask(Task task) |
|
{ |
|
if (textEditor.FileName == null) |
|
return false; |
|
if (task.FileName == null || task.Column <= 0) |
|
return false; |
|
if (task.TaskType != TaskType.Warning && task.TaskType != TaskType.Error) |
|
return false; |
|
return FileUtility.IsEqualFileName(task.FileName, textEditor.FileName); |
|
} |
|
|
|
void AddTask(Task task) |
|
{ |
|
if (!isEnabled) |
|
return; |
|
if (!CheckTask(task)) |
|
return; |
|
|
|
if (task.Line >= 1 && task.Line <= textEditor.Document.LineCount) { |
|
LoggingService.Debug(task.ToString()); |
|
int offset = textEditor.Document.GetOffset(task.Line, task.Column); |
|
int endOffset = TextUtilities.GetNextCaretPosition(DocumentUtilitites.GetTextSource(textEditor.Document), offset, System.Windows.Documents.LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol); |
|
if (endOffset < 0) endOffset = textEditor.Document.TextLength; |
|
int length = endOffset - offset; |
|
|
|
if (length < 2) { |
|
// marker should be at least 2 characters long, but take care that we don't make |
|
// it longer than the document |
|
length = Math.Min(2, textEditor.Document.TextLength - offset); |
|
} |
|
|
|
ITextMarker marker = this.markerService.Create(offset, length); |
|
|
|
Color markerColor = Colors.Transparent; |
|
|
|
switch (task.TaskType) { |
|
case TaskType.Error: |
|
markerColor = Colors.Red; |
|
break; |
|
case TaskType.Message: |
|
markerColor = Colors.Blue; |
|
break; |
|
case TaskType.Warning: |
|
markerColor = Colors.Orange; |
|
break; |
|
} |
|
|
|
marker.MarkerColor = markerColor; |
|
marker.MarkerType = TextMarkerType.SquigglyUnderline; |
|
|
|
marker.ToolTip = task.Description; |
|
|
|
marker.Tag = task; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Clears all errors and adds them again. |
|
/// </summary> |
|
public void UpdateErrors() |
|
{ |
|
if (isDisposed) |
|
return; |
|
ClearErrors(); |
|
if (!isEnabled) |
|
return; |
|
foreach (Task task in TaskService.Tasks) { |
|
AddTask(task); |
|
} |
|
} |
|
} |
|
}
|
|
|