Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using CodingWithCalvin.GitRanger.Core.Models;
using CodingWithCalvin.GitRanger.Options;
Expand Down Expand Up @@ -35,6 +36,7 @@ internal sealed class BlameAdornment
private IReadOnlyList<BlameLineInfo> _blameData = Array.Empty<BlameLineInfo>();
private string? _currentFilePath;
private bool _isLoading;
private int _activeLineNumber = -1;

/// <summary>
/// Creates a new blame adornment for the given text view.
Expand All @@ -60,6 +62,9 @@ public BlameAdornment(
// Subscribe to events
_view.LayoutChanged += OnLayoutChanged;
_view.Closed += OnViewClosed;
_view.Caret.PositionChanged += OnCaretPositionChanged;
_view.VisualElement.MouseMove += OnMouseMove;
_view.VisualElement.MouseLeave += OnMouseLeave;
_blameService.BlameLoaded += OnBlameLoaded;
GeneralOptions.Saved += OnOptionsSaved;

Expand All @@ -71,10 +76,63 @@ private void OnViewClosed(object sender, EventArgs e)
{
_view.LayoutChanged -= OnLayoutChanged;
_view.Closed -= OnViewClosed;
_view.Caret.PositionChanged -= OnCaretPositionChanged;
_view.VisualElement.MouseMove -= OnMouseMove;
_view.VisualElement.MouseLeave -= OnMouseLeave;
_blameService.BlameLoaded -= OnBlameLoaded;
GeneralOptions.Saved -= OnOptionsSaved;
}

private void OnCaretPositionChanged(object sender, CaretPositionChangedEventArgs e)
{
var options = GeneralOptions.Instance;
if (options == null || !options.EnableInlineBlame || options.InlineBlameDisplayMode != InlineBlameMode.CurrentLine)
return;

var caretLineNumber = _view.TextSnapshot.GetLineNumberFromPosition(
_view.Caret.Position.BufferPosition.Position) + 1;

if (caretLineNumber == _activeLineNumber)
return;

_activeLineNumber = caretLineNumber;
ClearAdornments();
UpdateAdornments();
}

private void OnMouseMove(object sender, MouseEventArgs e)
{
var options = GeneralOptions.Instance;
if (options == null || !options.EnableInlineBlame || options.InlineBlameDisplayMode != InlineBlameMode.Hover)
return;

var position = e.GetPosition(_view.VisualElement);
var viewportPoint = new Point(position.X + _view.ViewportLeft, position.Y + _view.ViewportTop);

var hoveredLine = _view.TextViewLines.GetTextViewLineContainingYCoordinate(viewportPoint.Y);
if (hoveredLine == null)
return;

var lineNumber = _view.TextSnapshot.GetLineNumberFromPosition(hoveredLine.Start.Position) + 1;

if (lineNumber == _activeLineNumber)
return;

_activeLineNumber = lineNumber;
ClearAdornments();
UpdateAdornments();
}

private void OnMouseLeave(object sender, MouseEventArgs e)
{
var options = GeneralOptions.Instance;
if (options == null || !options.EnableInlineBlame || options.InlineBlameDisplayMode != InlineBlameMode.Hover)
return;

_activeLineNumber = -1;
ClearAdornments();
}

private void OnOptionsSaved(GeneralOptions options)
{
_ = ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
Expand Down Expand Up @@ -173,6 +231,12 @@ private void UpdateAdornments()
if (_isLoading || _blameData.Count == 0)
return;

if (options.InlineBlameDisplayMode == InlineBlameMode.CurrentLine)
{
_activeLineNumber = _view.TextSnapshot.GetLineNumberFromPosition(
_view.Caret.Position.BufferPosition.Position) + 1;
}

var viewportTop = _view.ViewportTop;
var viewportBottom = _view.ViewportBottom;

Expand All @@ -182,6 +246,10 @@ private void UpdateAdornments()
continue;

var lineNumber = _view.TextSnapshot.GetLineNumberFromPosition(line.Start.Position) + 1;

if (options.InlineBlameDisplayMode != InlineBlameMode.Always && lineNumber != _activeLineNumber)
continue;

var blameInfo = _blameData.FirstOrDefault(b => b.LineNumber == lineNumber);
if (blameInfo == null)
continue;
Expand Down
29 changes: 25 additions & 4 deletions src/CodingWithCalvin.GitRanger/Options/GeneralOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ public class GeneralOptions : BaseOptionModel<GeneralOptions>
public bool CompactMode { get; set; } = false;

[Category("Display")]
[DisplayName("Show On Hover Only")]
[Description("Only show detailed blame information on mouse hover.")]
[DefaultValue(false)]
public bool ShowOnHoverOnly { get; set; } = false;
[DisplayName("Inline Blame Display Mode")]
[Description("Controls when inline blame is shown: Always (all lines), CurrentLine (caret line only), or Hover (mouse hover only).")]
[DefaultValue(InlineBlameMode.Always)]
public InlineBlameMode InlineBlameDisplayMode { get; set; } = InlineBlameMode.Always;

// Gutter Settings
[Category("Gutter")]
Expand Down Expand Up @@ -136,6 +136,27 @@ public class GeneralOptions : BaseOptionModel<GeneralOptions>
public LogLevel LogLevel { get; set; } = LogLevel.Error;
}

/// <summary>
/// Controls when inline blame annotations are displayed.
/// </summary>
public enum InlineBlameMode
{
/// <summary>
/// Show inline blame on all visible lines.
/// </summary>
Always,

/// <summary>
/// Show inline blame only on the current caret line.
/// </summary>
CurrentLine,

/// <summary>
/// Show inline blame only when the mouse hovers over a line.
/// </summary>
Hover
}

/// <summary>
/// Color mode for blame annotations.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/CodingWithCalvin.GitRanger/Options/GeneralOptionsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ public bool CompactMode
set => _options.CompactMode = value;
}

[Category("Display")]
[DisplayName("Inline Blame Display Mode")]
[Description("Controls when inline blame is shown: Always (all lines), CurrentLine (caret line only), or Hover (mouse hover only).")]
public InlineBlameMode InlineBlameDisplayMode
{
get => _options.InlineBlameDisplayMode;
set => _options.InlineBlameDisplayMode = value;
}

// Gutter Settings
[Category("Gutter")]
[DisplayName("Gutter Width")]
Expand Down
Loading