Permalink
Browse files

Add EnhancedScrollBar.

  • Loading branch information...
1 parent 5e1642e commit 51c28dc006edc2924051e224ce9d3effe1bdad08 @dgrunwald dgrunwald committed Mar 23, 2012
@@ -166,12 +166,14 @@ public void CreateMarker(IDocument document, ITextMarkerService markerService)
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;
@@ -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" />
@@ -213,6 +213,7 @@ protected virtual CodeEditorView CreateTextEditor()
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 @@ protected virtual void DisposeTextEditor(CodeEditorView textEditor)
{
foreach (var d in textEditor.TextArea.LeftMargins.OfType<IDisposable>())
d.Dispose();
+ ((EnhancedScrollBar)textEditor.TextArea.GetService(typeof(EnhancedScrollBar))).Dispose();
textEditor.Dispose();
}
@@ -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
+ }
+}
Oops, something went wrong.

0 comments on commit 51c28dc

Please sign in to comment.