33using System . Linq ;
44using System . Windows ;
55using System . Windows . Controls ;
6+ using System . Windows . Input ;
67using System . Windows . Media ;
78using CodingWithCalvin . GitRanger . Core . Models ;
89using CodingWithCalvin . GitRanger . Options ;
@@ -35,6 +36,7 @@ internal sealed class BlameAdornment
3536 private IReadOnlyList < BlameLineInfo > _blameData = Array . Empty < BlameLineInfo > ( ) ;
3637 private string ? _currentFilePath ;
3738 private bool _isLoading ;
39+ private int _activeLineNumber = - 1 ;
3840
3941 /// <summary>
4042 /// Creates a new blame adornment for the given text view.
@@ -60,6 +62,9 @@ public BlameAdornment(
6062 // Subscribe to events
6163 _view . LayoutChanged += OnLayoutChanged ;
6264 _view . Closed += OnViewClosed ;
65+ _view . Caret . PositionChanged += OnCaretPositionChanged ;
66+ _view . VisualElement . MouseMove += OnMouseMove ;
67+ _view . VisualElement . MouseLeave += OnMouseLeave ;
6368 _blameService . BlameLoaded += OnBlameLoaded ;
6469 GeneralOptions . Saved += OnOptionsSaved ;
6570
@@ -71,10 +76,63 @@ private void OnViewClosed(object sender, EventArgs e)
7176 {
7277 _view . LayoutChanged -= OnLayoutChanged ;
7378 _view . Closed -= OnViewClosed ;
79+ _view . Caret . PositionChanged -= OnCaretPositionChanged ;
80+ _view . VisualElement . MouseMove -= OnMouseMove ;
81+ _view . VisualElement . MouseLeave -= OnMouseLeave ;
7482 _blameService . BlameLoaded -= OnBlameLoaded ;
7583 GeneralOptions . Saved -= OnOptionsSaved ;
7684 }
7785
86+ private void OnCaretPositionChanged ( object sender , CaretPositionChangedEventArgs e )
87+ {
88+ var options = GeneralOptions . Instance ;
89+ if ( options == null || ! options . EnableInlineBlame || options . InlineBlameDisplayMode != InlineBlameMode . CurrentLine )
90+ return ;
91+
92+ var caretLineNumber = _view . TextSnapshot . GetLineNumberFromPosition (
93+ _view . Caret . Position . BufferPosition . Position ) + 1 ;
94+
95+ if ( caretLineNumber == _activeLineNumber )
96+ return ;
97+
98+ _activeLineNumber = caretLineNumber ;
99+ ClearAdornments ( ) ;
100+ UpdateAdornments ( ) ;
101+ }
102+
103+ private void OnMouseMove ( object sender , MouseEventArgs e )
104+ {
105+ var options = GeneralOptions . Instance ;
106+ if ( options == null || ! options . EnableInlineBlame || options . InlineBlameDisplayMode != InlineBlameMode . Hover )
107+ return ;
108+
109+ var position = e . GetPosition ( _view . VisualElement ) ;
110+ var viewportPoint = new Point ( position . X + _view . ViewportLeft , position . Y + _view . ViewportTop ) ;
111+
112+ var hoveredLine = _view . TextViewLines . GetTextViewLineContainingYCoordinate ( viewportPoint . Y ) ;
113+ if ( hoveredLine == null )
114+ return ;
115+
116+ var lineNumber = _view . TextSnapshot . GetLineNumberFromPosition ( hoveredLine . Start . Position ) + 1 ;
117+
118+ if ( lineNumber == _activeLineNumber )
119+ return ;
120+
121+ _activeLineNumber = lineNumber ;
122+ ClearAdornments ( ) ;
123+ UpdateAdornments ( ) ;
124+ }
125+
126+ private void OnMouseLeave ( object sender , MouseEventArgs e )
127+ {
128+ var options = GeneralOptions . Instance ;
129+ if ( options == null || ! options . EnableInlineBlame || options . InlineBlameDisplayMode != InlineBlameMode . Hover )
130+ return ;
131+
132+ _activeLineNumber = - 1 ;
133+ ClearAdornments ( ) ;
134+ }
135+
78136 private void OnOptionsSaved ( GeneralOptions options )
79137 {
80138 _ = ThreadHelper . JoinableTaskFactory . RunAsync ( async ( ) =>
@@ -173,6 +231,12 @@ private void UpdateAdornments()
173231 if ( _isLoading || _blameData . Count == 0 )
174232 return ;
175233
234+ if ( options . InlineBlameDisplayMode == InlineBlameMode . CurrentLine )
235+ {
236+ _activeLineNumber = _view . TextSnapshot . GetLineNumberFromPosition (
237+ _view . Caret . Position . BufferPosition . Position ) + 1 ;
238+ }
239+
176240 var viewportTop = _view . ViewportTop ;
177241 var viewportBottom = _view . ViewportBottom ;
178242
@@ -182,6 +246,10 @@ private void UpdateAdornments()
182246 continue ;
183247
184248 var lineNumber = _view . TextSnapshot . GetLineNumberFromPosition ( line . Start . Position ) + 1 ;
249+
250+ if ( options . InlineBlameDisplayMode != InlineBlameMode . Always && lineNumber != _activeLineNumber )
251+ continue ;
252+
185253 var blameInfo = _blameData . FirstOrDefault ( b => b . LineNumber == lineNumber ) ;
186254 if ( blameInfo == null )
187255 continue ;
0 commit comments