-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathMacroAdornmentManager.cs
137 lines (117 loc) · 4.31 KB
/
MacroAdornmentManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using Microsoft.VisualStudio.Text.Editor;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace VSTextMacros
{
// Manages the visual cue that is shown when recording a macro
public class MacroAdornmentManager
{
// A reference to the text view
private readonly IWpfTextView view;
// The adorner layer, where the visual is added
private readonly IAdornmentLayer layer;
// The visual element shown when recording
private UIElement visual;
// Constructor
private MacroAdornmentManager(IWpfTextView view)
{
this.view = view;
this.layer = view.GetAdornmentLayer("CommentAdornmentLayer");
// Reposition the visual when the editor is resized
this.view.LayoutChanged += (s, e) =>
{
PositionVisual();
};
}
// Shows the visual
public void ShowVisual()
{
if (visual == null)
{
// Create the visual
this.visual = CreateVisual();
// Position it
PositionVisual();
// Add it to the adornment layer
this.layer.AddAdornment(
AdornmentPositioningBehavior.ViewportRelative,
null,
"MacroRecording",
this.visual,
null);
}
}
// Hides the visual
public void HideVisual()
{
this.layer.RemoveAdornmentsByTag("MacroRecording");
this.visual = null;
}
// Repositions the visual in the top-right corner of the view
private void PositionVisual()
{
if (visual != null)
{
Canvas.SetLeft(this.visual, view.ViewportRight - 150);
Canvas.SetTop(this.visual, view.ViewportTop + 10);
}
}
// Creates the visual element
private UIElement CreateVisual()
{
var ellipse = new Ellipse
{
Width = 15,
Height = 15,
Fill = Brushes.DarkRed,
Margin = new Thickness(8),
Opacity = 0
};
var animation = new DoubleAnimationUsingKeyFrames
{
Duration = new Duration(TimeSpan.FromSeconds(1)),
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever,
};
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, KeyTime.FromPercent(0.00)));
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, KeyTime.FromPercent(0.25)));
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, KeyTime.FromPercent(0.50)));
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, KeyTime.FromPercent(0.75)));
Storyboard.SetTarget(animation, ellipse);
Storyboard.SetTargetProperty(animation, new PropertyPath(Ellipse.OpacityProperty));
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin(ellipse);
var text = new TextBlock
{
Text = "Recording Macro",
Foreground = Brushes.DarkSlateGray,
Margin = new Thickness(4, 0, 8, 2),
VerticalAlignment = VerticalAlignment.Center
};
var panel = new StackPanel
{
Orientation = Orientation.Horizontal
};
panel.Children.Add(ellipse);
panel.Children.Add(text);
return new Border
{
Background = Brushes.WhiteSmoke,
BorderThickness = new Thickness(2),
BorderBrush = Brushes.DarkSlateGray,
CornerRadius = new CornerRadius(3),
Child = panel
};
}
// Instanciates this class, and attaches the instance to the view
public static MacroAdornmentManager Create(IWpfTextView view)
{
return view.Properties.GetOrCreateSingletonProperty<MacroAdornmentManager>(() => new MacroAdornmentManager(view));
}
}
}