Skip to content

Commit ba726d2

Browse files
fix icsharpcode#319: Enhanced Scrollbar: Drawing / Navigation Issues
1 parent ce912f6 commit ba726d2

File tree

1 file changed

+36
-142
lines changed

1 file changed

+36
-142
lines changed

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

Lines changed: 36 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public class EnhancedScrollBar : IDisposable
4242
readonly TextEditor editor;
4343
readonly TextMarkerService textMarkerService;
4444
readonly IChangeWatcher changeWatcher;
45-
TrackBackground trackBackground;
4645
TrackAdorner trackAdorner;
4746

4847
public EnhancedScrollBar(TextEditor editor, TextMarkerService textMarkerService, IChangeWatcher changeWatcher)
@@ -62,10 +61,6 @@ public EnhancedScrollBar(TextEditor editor, TextMarkerService textMarkerService,
6261
public void Dispose()
6362
{
6463
editor.Loaded -= editor_Loaded;
65-
if (trackBackground != null) {
66-
trackBackground.Remove();
67-
trackBackground = null;
68-
}
6964
if (trackAdorner != null) {
7065
trackAdorner.Remove();
7166
trackAdorner = null;
@@ -86,78 +81,19 @@ void editor_Loaded(object sender, RoutedEventArgs e)
8681
return;
8782
scrollViewer.ApplyTemplate();
8883
var vScrollBar = (ScrollBar)scrollViewer.Template.FindName("PART_VerticalScrollBar", scrollViewer);
89-
var hScrollBar = (ScrollBar)scrollViewer.Template.FindName("PART_HorizontalScrollBar", scrollViewer);
90-
// make both scrollbars transparent so that they look consistent
91-
MakeThumbTransparent(vScrollBar);
92-
MakeThumbTransparent(hScrollBar);
9384
if (vScrollBar == null)
9485
return;
9586
Track track = (Track)vScrollBar.Template.FindName("PART_Track", vScrollBar);
9687
if (track == null)
9788
return;
9889
Grid grid = VisualTreeHelper.GetParent(track) as Grid;
99-
if (grid != null) {
100-
trackBackground = new TrackBackground(this);
101-
trackAdorner = new TrackAdorner(this);
102-
Grid.SetColumn(trackBackground, Grid.GetColumn(track));
103-
Grid.SetRow(trackBackground, Grid.GetRow(track));
104-
Grid.SetColumnSpan(trackBackground, Grid.GetColumnSpan(track));
105-
Grid.SetRowSpan(trackBackground, Grid.GetRowSpan(track));
106-
Grid.SetColumn(trackAdorner, Grid.GetColumn(track));
107-
Grid.SetRow(trackAdorner, Grid.GetRow(track));
108-
Grid.SetColumnSpan(trackAdorner, Grid.GetColumnSpan(track));
109-
Grid.SetRowSpan(trackAdorner, Grid.GetRowSpan(track));
110-
Panel.SetZIndex(track, 1);
111-
Panel.SetZIndex(trackAdorner, 2);
112-
grid.Children.Add(trackBackground);
113-
grid.Children.Add(trackAdorner);
114-
}
115-
}
116-
#endregion
117-
118-
#region MakeThumbTransparent
119-
List<Thumb> transparentThumbs = new List<Thumb>();
120-
const double thumbOpacity = 0.7;
121-
static readonly Duration animationDuration = new Duration(TimeSpan.FromSeconds(0.25));
122-
123-
void MakeThumbTransparent(ScrollBar scrollBar)
124-
{
125-
if (scrollBar == null)
90+
if (grid == null)
12691
return;
127-
Track track = (Track)scrollBar.Template.FindName("PART_Track", scrollBar);
128-
if (track == null)
92+
var layer = AdornerLayer.GetAdornerLayer(grid);
93+
if (layer == null)
12994
return;
130-
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(track); i++) {
131-
var thumb = VisualTreeHelper.GetChild(track, i) as Thumb;
132-
if (thumb != null) {
133-
thumb.Opacity = thumbOpacity;
134-
thumb.MouseEnter += thumb_MouseEnter;
135-
thumb.MouseLeave += thumb_MouseLeave;
136-
transparentThumbs.Add(thumb);
137-
break;
138-
}
139-
}
140-
}
141-
142-
void ClearTransparencyFromThumbs()
143-
{
144-
foreach (var thumb in transparentThumbs) {
145-
thumb.MouseEnter -= thumb_MouseEnter;
146-
thumb.MouseLeave -= thumb_MouseLeave;
147-
thumb.ClearValue(Thumb.OpacityProperty);
148-
}
149-
}
150-
151-
void thumb_MouseEnter(object sender, MouseEventArgs e)
152-
{
153-
var thumb = (Thumb)sender;
154-
thumb.BeginAnimation(Thumb.OpacityProperty, new DoubleAnimation(1, animationDuration, FillBehavior.HoldEnd));
155-
}
156-
157-
void thumb_MouseLeave(object sender, MouseEventArgs e)
158-
{
159-
var thumb = (Thumb)sender;
160-
thumb.BeginAnimation(Thumb.OpacityProperty, new DoubleAnimation(thumbOpacity, animationDuration, FillBehavior.HoldEnd));
95+
trackAdorner = new TrackAdorner(this, grid);
96+
layer.Add(trackAdorner);
16197
}
16298
#endregion
16399

@@ -168,62 +104,8 @@ static Brush GetBrush(Color markerColor)
168104
return brush;
169105
}
170106

171-
#region TrackBackground
172-
sealed class TrackBackground : UIElement
173-
{
174-
readonly TextEditor editor;
175-
readonly TextMarkerService textMarkerService;
176-
readonly IChangeWatcher changeWatcher;
177-
178-
public TrackBackground(EnhancedScrollBar enhanchedScrollBar)
179-
{
180-
this.editor = enhanchedScrollBar.editor;
181-
this.textMarkerService = enhanchedScrollBar.textMarkerService;
182-
this.changeWatcher = enhanchedScrollBar.changeWatcher;
183-
184-
textMarkerService.RedrawRequested += textMarkerService_RedrawRequested;
185-
}
186-
187-
public void Remove()
188-
{
189-
textMarkerService.RedrawRequested -= textMarkerService_RedrawRequested;
190-
191-
Grid grid = (Grid)VisualTreeHelper.GetParent(this);
192-
grid.Children.Remove(this);
193-
}
194-
195-
void textMarkerService_RedrawRequested(object sender, EventArgs e)
196-
{
197-
InvalidateVisual();
198-
}
199-
200-
protected override void OnRender(DrawingContext drawingContext)
201-
{
202-
var renderSize = this.RenderSize;
203-
var document = editor.Document;
204-
var textView = editor.TextArea.TextView;
205-
double documentHeight = textView.DocumentHeight;
206-
foreach (var marker in textMarkerService.TextMarkers) {
207-
if ((marker.MarkerTypes & (TextMarkerTypes.LineInScrollBar | TextMarkerTypes.CircleInScrollBar)) == 0)
208-
continue;
209-
var location = document.GetLocation(marker.StartOffset);
210-
double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
211-
double renderPos = visualTop / documentHeight * renderSize.Height;
212-
var brush = GetBrush(marker.MarkerColor);
213-
if ((marker.MarkerTypes & (TextMarkerTypes.LineInScrollBar)) != 0) {
214-
drawingContext.DrawRectangle(brush, null, new Rect(3, renderPos - 1, renderSize.Width - 6, 2));
215-
}
216-
if ((marker.MarkerTypes & (TextMarkerTypes.CircleInScrollBar)) != 0) {
217-
const double radius = 3;
218-
drawingContext.DrawEllipse(brush, null, new Point(renderSize.Width / 2, renderPos), radius, radius);
219-
}
220-
}
221-
}
222-
}
223-
#endregion
224-
225107
#region TrackAdorner
226-
sealed class TrackAdorner : FrameworkElement
108+
sealed class TrackAdorner : Adorner
227109
{
228110
#region TriangleGeometry
229111
static readonly StreamGeometry triangleGeometry = CreateTriangleGeometry();
@@ -247,7 +129,8 @@ static StreamGeometry CreateTriangleGeometry()
247129
readonly TextEditor editor;
248130
readonly TextMarkerService textMarkerService;
249131

250-
public TrackAdorner(EnhancedScrollBar enhanchedScrollBar)
132+
public TrackAdorner(EnhancedScrollBar enhanchedScrollBar, Grid trackGrid)
133+
: base(trackGrid)
251134
{
252135
this.editor = enhanchedScrollBar.editor;
253136
this.textMarkerService = enhanchedScrollBar.textMarkerService;
@@ -261,9 +144,9 @@ public TrackAdorner(EnhancedScrollBar enhanchedScrollBar)
261144
public void Remove()
262145
{
263146
textMarkerService.RedrawRequested -= textMarkerService_RedrawRequested;
264-
265-
Grid grid = (Grid)VisualTreeHelper.GetParent(this);
266-
grid.Children.Remove(this);
147+
148+
var layer = AdornerLayer.GetAdornerLayer(AdornedElement);
149+
layer.Remove(this);
267150
}
268151

269152
void textMarkerService_RedrawRequested(object sender, EventArgs e)
@@ -284,28 +167,39 @@ protected override void OnRender(DrawingContext drawingContext)
284167
double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
285168
double renderPos = visualTop / documentHeight * renderSize.Height;
286169
var brush = GetBrush(marker.MarkerColor);
170+
bool isLineOrCircle = false;
171+
if ((marker.MarkerTypes & (TextMarkerTypes.LineInScrollBar)) != 0) {
172+
drawingContext.DrawRectangle(brush, null, new Rect(3, renderPos - 1, renderSize.Width - 6, 2));
173+
isLineOrCircle = true;
174+
}
175+
if ((marker.MarkerTypes & (TextMarkerTypes.CircleInScrollBar)) != 0) {
176+
const double radius = 3;
177+
drawingContext.DrawEllipse(brush, null, new Point(renderSize.Width / 2, renderPos), radius, radius);
178+
isLineOrCircle = true;
179+
}
180+
if (!isLineOrCircle) {
181+
var translateTransform = new TranslateTransform(6, renderPos);
182+
translateTransform.Freeze();
183+
drawingContext.PushTransform(translateTransform);
287184

288-
var translateTransform = new TranslateTransform(6, renderPos);
289-
translateTransform.Freeze();
290-
drawingContext.PushTransform(translateTransform);
291-
292-
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle)) != 0) {
293-
var scaleTransform = new ScaleTransform(-1, 1);
294-
scaleTransform.Freeze();
295-
drawingContext.PushTransform(scaleTransform);
296-
drawingContext.DrawGeometry(brush, null, triangleGeometry);
185+
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle)) != 0) {
186+
var scaleTransform = new ScaleTransform(-1, 1);
187+
scaleTransform.Freeze();
188+
drawingContext.PushTransform(scaleTransform);
189+
drawingContext.DrawGeometry(brush, null, triangleGeometry);
190+
drawingContext.Pop();
191+
}
192+
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarRightTriangle)) != 0) {
193+
drawingContext.DrawGeometry(brush, null, triangleGeometry);
194+
}
297195
drawingContext.Pop();
298196
}
299-
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarRightTriangle)) != 0) {
300-
drawingContext.DrawGeometry(brush, null, triangleGeometry);
301-
}
302-
drawingContext.Pop();
303197
}
304198
}
305199

306200
bool IsVisibleInAdorner(ITextMarker marker)
307201
{
308-
return (marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle | TextMarkerTypes.ScrollBarRightTriangle)) != 0;
202+
return (marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle | TextMarkerTypes.ScrollBarRightTriangle | TextMarkerTypes.LineInScrollBar | TextMarkerTypes.CircleInScrollBar)) != 0;
309203
}
310204

311205
protected override void OnMouseDown(MouseButtonEventArgs e)

0 commit comments

Comments
 (0)