From 26307e2343b82939247553cfbe39ec8889c016a1 Mon Sep 17 00:00:00 2001 From: leo Date: Sun, 1 Jun 2025 10:34:24 +0800 Subject: [PATCH] refactor: new tooltip for change Signed-off-by: leo --- src/Models/Change.cs | 17 +++++++++- src/Views/ChangeCollectionView.axaml | 6 ++-- src/Views/ChangeCollectionView.axaml.cs | 41 ++++++++++++++++++++++++- src/Views/ChangeStatusIcon.cs | 26 +--------------- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/Models/Change.cs b/src/Models/Change.cs index a7be1f64..aaa2633f 100644 --- a/src/Models/Change.cs +++ b/src/Models/Change.cs @@ -53,6 +53,9 @@ namespace SourceGit.Models public bool IsConflicted => WorkTree == ChangeState.Conflicted; public string ConflictMarker => CONFLICT_MARKERS[(int)ConflictReason]; public string ConflictDesc => CONFLICT_DESCS[(int)ConflictReason]; + + public string WorkTreeDesc => TYPE_DESCS[(int)WorkTree]; + public string IndexDesc => TYPE_DESCS[(int)Index]; public void Set(ChangeState index, ChangeState workTree = ChangeState.None) { @@ -84,7 +87,19 @@ namespace SourceGit.Models if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"') OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2); } - + + private static readonly string[] TYPE_DESCS = + [ + "Unknown", + "Modified", + "Type Changed", + "Added", + "Deleted", + "Renamed", + "Copied", + "Untracked", + "Conflict" + ]; private static readonly string[] CONFLICT_MARKERS = [ string.Empty, diff --git a/src/Views/ChangeCollectionView.axaml b/src/Views/ChangeCollectionView.axaml index 11c9e706..43af3a9a 100644 --- a/src/Views/ChangeCollectionView.axaml +++ b/src/Views/ChangeCollectionView.axaml @@ -41,7 +41,7 @@ Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}" Background="Transparent" DoubleTapped="OnRowDoubleTapped" - ToolTip.Tip="{Binding FullPath}"> + DataContextChanged="OnRowDataContextChanged"> + DataContextChanged="OnRowDataContextChanged"> + DataContextChanged="OnRowDataContextChanged"> AutoSelectFirstChangeProperty = - AvaloniaProperty.Register(nameof(AutoSelectFirstChange), false); + AvaloniaProperty.Register(nameof(AutoSelectFirstChange)); public bool AutoSelectFirstChange { @@ -229,6 +231,28 @@ namespace SourceGit.Views UpdateSelection(); } + private void OnRowDataContextChanged(object sender, EventArgs e) + { + if (sender is not Control control) + return; + + if (control.DataContext is ViewModels.ChangeTreeNode node) + { + if (node.Change is {} c) + UpdateRowTips(control, c); + else + ToolTip.SetTip(control, node.FullPath); + } + else if (control.DataContext is Models.Change change) + { + UpdateRowTips(control, change); + } + else + { + ToolTip.SetTip(control, null); + } + } + private void OnRowDoubleTapped(object sender, TappedEventArgs e) { var grid = sender as Grid; @@ -466,6 +490,21 @@ namespace SourceGit.Views } } + private void UpdateRowTips(Control control, Models.Change change) + { + var tip = new TextBlock() { TextWrapping = TextWrapping.Wrap }; + tip.Inlines!.Add(new Run(change.Path)); + tip.Inlines!.Add(new Run(" • ") { Foreground = Brushes.Gray }); + tip.Inlines!.Add(new Run(IsUnstagedChange ? change.WorkTreeDesc : change.IndexDesc) { Foreground = Brushes.Gray }); + if (change.IsConflicted) + { + tip.Inlines!.Add(new Run(" • ") { Foreground = Brushes.Gray }); + tip.Inlines!.Add(new Run(change.ConflictDesc) { Foreground = Brushes.Gray }); + } + + ToolTip.SetTip(control, tip); + } + private bool _disableSelectionChangingEvent = false; } } diff --git a/src/Views/ChangeStatusIcon.cs b/src/Views/ChangeStatusIcon.cs index 0f0e8da1..d66ac11d 100644 --- a/src/Views/ChangeStatusIcon.cs +++ b/src/Views/ChangeStatusIcon.cs @@ -9,6 +9,7 @@ namespace SourceGit.Views { public class ChangeStatusIcon : Control { + private static readonly string[] INDICATOR = ["?", "±", "T", "+", "−", "➜", "❏", "★", "!"]; private static readonly IBrush[] BACKGROUNDS = [ Brushes.Transparent, new LinearGradientBrush @@ -56,9 +57,6 @@ namespace SourceGit.Views Brushes.OrangeRed, ]; - private static readonly string[] INDICATOR = ["?", "±", "T", "+", "−", "➜", "❏", "★", "!"]; - private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Untracked", "Conflict"]; - public static readonly StyledProperty IsUnstagedChangeProperty = AvaloniaProperty.Register(nameof(IsUnstagedChange)); @@ -116,29 +114,7 @@ namespace SourceGit.Views base.OnPropertyChanged(change); if (change.Property == IsUnstagedChangeProperty || change.Property == ChangeProperty) - { - var isUnstaged = IsUnstagedChange; - var c = Change; - if (c == null) - { - ToolTip.SetTip(this, null); - return; - } - - if (isUnstaged) - { - if (c.IsConflicted) - ToolTip.SetTip(this, $"Conflict ({c.ConflictDesc})"); - else - ToolTip.SetTip(this, TIPS[(int)c.WorkTree]); - } - else - { - ToolTip.SetTip(this, TIPS[(int)c.Index]); - } - InvalidateVisual(); - } } } }