Browse Source

Add EnhancedScrollBar.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
51c28dc006
  1. 10
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  2. 1
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  3. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  4. 277
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EnhancedScrollBar.cs
  5. 43
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs
  6. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/generic.xaml
  7. 30
      src/Main/Base/Project/Src/Editor/ITextMarker.cs
  8. 2
      src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs
  9. 2
      src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs

10
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -166,12 +166,14 @@ namespace CSharpBinding.Refactoring @@ -166,12 +166,14 @@ namespace CSharpBinding.Refactoring
return;
marker = markerService.Create(startOffset, endOffset - startOffset);
marker.ToolTip = this.Description;
Color color = GetColor(this.Severity);
color.A = 186;
marker.MarkerColor = color;
marker.MarkerTypes = TextMarkerTypes.ScrollBarRightTriangle;
switch (Provider.DefaultMarker) {
case IssueMarker.Underline:
Color underlineColor = GetColor(this.Severity);
underlineColor.A = 186;
marker.MarkerType = TextMarkerType.SquigglyUnderline;
marker.MarkerColor = underlineColor;
marker.MarkerTypes |= TextMarkerTypes.SquigglyUnderline;
break;
case IssueMarker.GrayOut:
marker.ForegroundColor = SystemColors.GrayTextColor;

1
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -98,6 +98,7 @@ @@ -98,6 +98,7 @@
<Compile Include="Src\ContextActions\FindDerivedClassesOrOverrides.cs" />
<Compile Include="Src\ContextActions\GoToEntityAction.cs" />
<Compile Include="Src\DocumentSequence.cs" />
<Compile Include="Src\EnhancedScrollBar.cs" />
<Compile Include="Src\Utils.cs" />
<Compile Include="Src\XmlDoc\DocumentationUIBuilder.cs" />
<Compile Include="Src\XmlDoc\XmlDocTooltipProvider.cs" />

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -213,6 +213,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -213,6 +213,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (changeWatcher != null) {
codeEditorView.TextArea.LeftMargins.Add(new ChangeMarkerMargin(changeWatcher));
}
textView.Services.AddService(typeof(EnhancedScrollBar), new EnhancedScrollBar(codeEditorView, textMarkerService, changeWatcher));
codeEditorView.TextArea.MouseRightButtonDown += TextAreaMouseRightButtonDown;
codeEditorView.TextArea.ContextMenuOpening += TextAreaContextMenuOpening;
@ -234,6 +235,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -234,6 +235,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
foreach (var d in textEditor.TextArea.LeftMargins.OfType<IDisposable>())
d.Dispose();
((EnhancedScrollBar)textEditor.TextArea.GetService(typeof(EnhancedScrollBar))).Dispose();
textEditor.Dispose();
}

277
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EnhancedScrollBar.cs

@ -0,0 +1,277 @@ @@ -0,0 +1,277 @@
// 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.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.AvalonEdit.AddIn
{
/// <summary>
/// Scrollbar that shows markers.
/// </summary>
public class EnhancedScrollBar : IDisposable
{
readonly TextEditor editor;
readonly TextMarkerService textMarkerService;
readonly IChangeWatcher changeWatcher;
TrackBackground trackBackground;
TrackAdorner trackAdorner;
public EnhancedScrollBar(TextEditor editor, TextMarkerService textMarkerService, IChangeWatcher changeWatcher)
{
if (editor == null)
throw new ArgumentNullException("editor");
this.editor = editor;
this.textMarkerService = textMarkerService;
this.changeWatcher = changeWatcher;
editor.Loaded += editor_Loaded;
if (editor.IsLoaded) {
editor_Loaded(null, null);
}
}
public void Dispose()
{
editor.Loaded -= editor_Loaded;
if (trackBackground != null) {
trackBackground.Remove();
trackBackground = null;
}
if (trackAdorner != null) {
trackAdorner.Remove();
trackAdorner = null;
}
}
#region Initialize UI
bool isUIInitialized;
void editor_Loaded(object sender, RoutedEventArgs e)
{
if (isUIInitialized)
return;
isUIInitialized = true;
editor.ApplyTemplate();
var scrollViewer = (ScrollViewer)editor.Template.FindName("PART_ScrollViewer", editor);
if (scrollViewer == null)
return;
scrollViewer.ApplyTemplate();
var vScrollBar = (ScrollBar)scrollViewer.Template.FindName("PART_VerticalScrollBar", scrollViewer);
var hScrollBar = (ScrollBar)scrollViewer.Template.FindName("PART_HorizontalScrollBar", scrollViewer);
// make both scrollbars transparent so that they look consistent
MakeThumbTransparent(vScrollBar);
MakeThumbTransparent(hScrollBar);
if (vScrollBar == null)
return;
Track track = (Track)vScrollBar.Template.FindName("PART_Track", vScrollBar);
if (track == null)
return;
Grid grid = VisualTreeHelper.GetParent(track) as Grid;
if (grid != null) {
trackBackground = new TrackBackground(this);
Grid.SetColumn(trackBackground, Grid.GetColumn(track));
Grid.SetRow(trackBackground, Grid.GetRow(track));
Grid.SetColumnSpan(trackBackground, Grid.GetColumnSpan(track));
Grid.SetRowSpan(trackBackground, Grid.GetRowSpan(track));
Panel.SetZIndex(track, 1);
grid.Children.Add(trackBackground);
}
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(track);
if (adornerLayer != null) {
trackAdorner = new TrackAdorner(this, adornerLayer, track);
}
}
#endregion
#region MakeThumbTransparent
List<Thumb> transparentThumbs = new List<Thumb>();
const double thumbOpacity = 0.7;
static readonly Duration animationDuration = new Duration(TimeSpan.FromSeconds(0.25));
void MakeThumbTransparent(ScrollBar scrollBar)
{
if (scrollBar == null)
return;
Track track = (Track)scrollBar.Template.FindName("PART_Track", scrollBar);
if (track == null)
return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(track); i++) {
var thumb = VisualTreeHelper.GetChild(track, i) as Thumb;
if (thumb != null) {
thumb.Opacity = thumbOpacity;
thumb.MouseEnter += thumb_MouseEnter;
thumb.MouseLeave += thumb_MouseLeave;
transparentThumbs.Add(thumb);
break;
}
}
}
void ClearTransparencyFromThumbs()
{
foreach (var thumb in transparentThumbs) {
thumb.MouseEnter -= thumb_MouseEnter;
thumb.MouseLeave -= thumb_MouseLeave;
thumb.ClearValue(Thumb.OpacityProperty);
}
}
void thumb_MouseEnter(object sender, MouseEventArgs e)
{
var thumb = (Thumb)sender;
thumb.BeginAnimation(Thumb.OpacityProperty, new DoubleAnimation(1, animationDuration, FillBehavior.HoldEnd));
}
void thumb_MouseLeave(object sender, MouseEventArgs e)
{
var thumb = (Thumb)sender;
thumb.BeginAnimation(Thumb.OpacityProperty, new DoubleAnimation(thumbOpacity, animationDuration, FillBehavior.HoldEnd));
}
#endregion
static Brush GetBrush(Color markerColor)
{
SolidColorBrush brush = new SolidColorBrush(markerColor);
brush.Freeze();
return brush;
}
#region TrackBackground
sealed class TrackBackground : UIElement
{
readonly TextEditor editor;
readonly TextMarkerService textMarkerService;
readonly IChangeWatcher changeWatcher;
public TrackBackground(EnhancedScrollBar enhanchedScrollBar)
{
this.editor = enhanchedScrollBar.editor;
this.textMarkerService = enhanchedScrollBar.textMarkerService;
this.changeWatcher = enhanchedScrollBar.changeWatcher;
textMarkerService.RedrawRequested += textMarkerService_RedrawRequested;
}
public void Remove()
{
textMarkerService.RedrawRequested -= textMarkerService_RedrawRequested;
Grid grid = (Grid)VisualTreeHelper.GetParent(this);
grid.Children.Remove(this);
}
void textMarkerService_RedrawRequested(object sender, EventArgs e)
{
InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
var renderSize = this.RenderSize;
var document = editor.Document;
var textView = editor.TextArea.TextView;
double documentHeight = textView.DocumentHeight;
foreach (var marker in textMarkerService.TextMarkers) {
if ((marker.MarkerTypes & (TextMarkerTypes.LineInScrollBar | TextMarkerTypes.CircleInScrollBar)) == 0)
continue;
var location = document.GetLocation(marker.StartOffset);
double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
double renderPos = visualTop / documentHeight * renderSize.Height;
var brush = GetBrush(marker.MarkerColor);
if ((marker.MarkerTypes & (TextMarkerTypes.LineInScrollBar)) != 0) {
drawingContext.DrawRectangle(brush, null, new Rect(3, renderPos - 1, renderSize.Width - 6, 2));
}
if ((marker.MarkerTypes & (TextMarkerTypes.CircleInScrollBar)) != 0) {
const double radius = 3;
drawingContext.DrawEllipse(brush, null, new Point(renderSize.Width / 2, renderPos), radius, radius);
}
}
}
}
#endregion
#region TrackAdorner
sealed class TrackAdorner : Adorner
{
readonly AdornerLayer adornerLayer;
readonly TextEditor editor;
readonly TextMarkerService textMarkerService;
readonly StreamGeometry triangleGeometry;
public TrackAdorner(EnhancedScrollBar enhanchedScrollBar, AdornerLayer adornerLayer, UIElement adornedElement)
: base(adornedElement)
{
this.adornerLayer = adornerLayer;
this.editor = enhanchedScrollBar.editor;
this.textMarkerService = enhanchedScrollBar.textMarkerService;
triangleGeometry = new StreamGeometry();
using (var ctx = triangleGeometry.Open()) {
const double triangleSize = 6.5;
const double right = (triangleSize * 0.866) / 2;
const double left = -right;
ctx.BeginFigure(new Point(left, triangleSize / 2), true, true);
ctx.LineTo(new Point(left, -triangleSize / 2), true, false);
ctx.LineTo(new Point(right, 0), true, false);
}
triangleGeometry.Freeze();
adornerLayer.Add(this);
textMarkerService.RedrawRequested += textMarkerService_RedrawRequested;
}
public void Remove()
{
textMarkerService.RedrawRequested -= textMarkerService_RedrawRequested;
adornerLayer.Remove(this);
}
void textMarkerService_RedrawRequested(object sender, EventArgs e)
{
InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
var renderSize = this.RenderSize;
var document = editor.Document;
var textView = editor.TextArea.TextView;
double documentHeight = textView.DocumentHeight;
foreach (var marker in textMarkerService.TextMarkers) {
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle | TextMarkerTypes.ScrollBarRightTriangle)) == 0)
continue;
var location = document.GetLocation(marker.StartOffset);
double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
double renderPos = visualTop / documentHeight * renderSize.Height;
var brush = GetBrush(marker.MarkerColor);
var translateTransform = new TranslateTransform(6, renderPos);
translateTransform.Freeze();
drawingContext.PushTransform(translateTransform);
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle)) != 0) {
var scaleTransform = new ScaleTransform(-1, 1);
scaleTransform.Freeze();
drawingContext.PushTransform(scaleTransform);
drawingContext.DrawGeometry(brush, null, triangleGeometry);
drawingContext.Pop();
}
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarRightTriangle)) != 0) {
drawingContext.DrawGeometry(brush, null, triangleGeometry);
}
drawingContext.Pop();
}
}
}
#endregion
}
}

43
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs

@ -118,7 +118,11 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -118,7 +118,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
internal void Redraw(ISegment segment)
{
codeEditor.Redraw(segment, DispatcherPriority.Normal);
if (RedrawRequested != null)
RedrawRequested(this, EventArgs.Empty);
}
public event EventHandler RedrawRequested;
#endregion
#region DocumentColorizingTransformer
@ -182,30 +186,31 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -182,30 +186,31 @@ namespace ICSharpCode.AvalonEdit.AddIn
drawingContext.DrawGeometry(brush, null, geometry);
}
}
if (marker.MarkerType != TextMarkerType.None) {
if ((marker.MarkerTypes & (TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline)) != 0) {
foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) {
Point startPoint = r.BottomLeft;
Point endPoint = r.BottomRight;
Pen usedPen = new Pen(new SolidColorBrush(marker.MarkerColor), 1);
usedPen.Freeze();
switch (marker.MarkerType) {
case TextMarkerType.SquigglyUnderline:
double offset = 2.5;
if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0) {
double offset = 2.5;
int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
StreamGeometry geometry = new StreamGeometry();
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open()) {
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
}
using (StreamGeometryContext ctx = geometry.Open()) {
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
}
geometry.Freeze();
geometry.Freeze();
drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
break;
drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
}
if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0) {
drawingContext.DrawLine(usedPen, startPoint, endPoint);
}
}
}
@ -231,7 +236,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -231,7 +236,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.service = service;
this.StartOffset = startOffset;
this.Length = length;
this.markerType = TextMarkerType.None;
this.markerTypes = TextMarkerTypes.None;
}
public event EventHandler Deleted;
@ -282,13 +287,13 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -282,13 +287,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
public object Tag { get; set; }
TextMarkerType markerType;
TextMarkerTypes markerTypes;
public TextMarkerType MarkerType {
get { return markerType; }
public TextMarkerTypes MarkerTypes {
get { return markerTypes; }
set {
if (markerType != value) {
markerType = value;
if (markerTypes != value) {
markerTypes = value;
Redraw();
}
}

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/generic.xaml

@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
BorderThickness="{TemplateBinding BorderThickness}"
TextOptions.TextFormattingMode="{Binding CurrentZoom, ElementName=PART_ScrollViewer, Converter={x:Static local:ZoomLevelToTextFormattingModeConverter.Instance}}">
<widgets:ZoomScrollViewer.Resources>
<!-- <Style TargetType="{x:Type ae:SearchPanel}">
<!--<Style TargetType="{x:Type ae:SearchPanel}">
<Setter Property="Localization" Value="{x:Static local:SearchPanelLocalization.Instance}" />
</Style>-->
</widgets:ZoomScrollViewer.Resources>

30
src/Main/Base/Project/Src/Editor/ITextMarker.cs

@ -55,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -55,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Editor
/// <summary>
/// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers.
/// </summary>
TextMarkerType MarkerType { get; set; }
TextMarkerTypes MarkerTypes { get; set; }
/// <summary>
/// Gets/Sets the color of the marker.
@ -73,16 +73,38 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -73,16 +73,38 @@ namespace ICSharpCode.SharpDevelop.Editor
object ToolTip { get; set; }
}
public enum TextMarkerType
[Flags]
public enum TextMarkerTypes
{
/// <summary>
/// Use no marker
/// </summary>
None,
None = 0x0000,
/// <summary>
/// Use squiggly underline marker
/// </summary>
SquigglyUnderline
SquigglyUnderline = 0x001,
/// <summary>
/// Normal underline.
/// </summary>
NormalUnderline = 0x002,
/// <summary>
/// Horizontal line in the scroll bar.
/// </summary>
LineInScrollBar = 0x0100,
/// <summary>
/// Small triangle in the scroll bar, pointing to the right.
/// </summary>
ScrollBarRightTriangle = 0x0400,
/// <summary>
/// Small triangle in the scroll bar, pointing to the left.
/// </summary>
ScrollBarLeftTriangle = 0x0800,
/// <summary>
/// Small circle in the scroll bar.
/// </summary>
CircleInScrollBar = 0x1000
}
public interface ITextMarkerService

2
src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs

@ -113,6 +113,8 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -113,6 +113,8 @@ namespace ICSharpCode.SharpDevelop.Debugging
ITextMarker marker = markerService.Create(line.Offset, line.Length);
marker.BackgroundColor = Color.FromRgb(180, 38, 38);
marker.ForegroundColor = Colors.White;
marker.MarkerColor = Color.FromRgb(180, 38, 38);
marker.MarkerTypes = TextMarkerTypes.CircleInScrollBar;
return marker;
}

2
src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs

@ -160,7 +160,7 @@ namespace ICSharpCode.SharpDevelop @@ -160,7 +160,7 @@ namespace ICSharpCode.SharpDevelop
}
marker.MarkerColor = markerColor;
marker.MarkerType = TextMarkerType.SquigglyUnderline;
marker.MarkerTypes = TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.LineInScrollBar;
marker.ToolTip = task.Description;

Loading…
Cancel
Save