refactor: new tooltip for change

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-06-01 10:34:24 +08:00
parent db5bb0aec9
commit 26307e2343
No known key found for this signature in database
4 changed files with 60 additions and 30 deletions

View file

@ -54,6 +54,9 @@ namespace SourceGit.Models
public string ConflictMarker => CONFLICT_MARKERS[(int)ConflictReason]; public string ConflictMarker => CONFLICT_MARKERS[(int)ConflictReason];
public string ConflictDesc => CONFLICT_DESCS[(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) public void Set(ChangeState index, ChangeState workTree = ChangeState.None)
{ {
Index = index; Index = index;
@ -85,6 +88,18 @@ namespace SourceGit.Models
OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2); 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 = private static readonly string[] CONFLICT_MARKERS =
[ [
string.Empty, string.Empty,

View file

@ -41,7 +41,7 @@
Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}" Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
Background="Transparent" Background="Transparent"
DoubleTapped="OnRowDoubleTapped" DoubleTapped="OnRowDoubleTapped"
ToolTip.Tip="{Binding FullPath}"> DataContextChanged="OnRowDataContextChanged">
<v:ChangeTreeNodeToggleButton Grid.Column="0" <v:ChangeTreeNodeToggleButton Grid.Column="0"
Classes="tree_expander" Classes="tree_expander"
Focusable="False" Focusable="False"
@ -85,7 +85,7 @@
<Grid ColumnDefinitions="Auto,Auto,Auto,*" <Grid ColumnDefinitions="Auto,Auto,Auto,*"
Background="Transparent" Background="Transparent"
DoubleTapped="OnRowDoubleTapped" DoubleTapped="OnRowDoubleTapped"
ToolTip.Tip="{Binding Path}"> DataContextChanged="OnRowDataContextChanged">
<v:ChangeStatusIcon Grid.Column="0" <v:ChangeStatusIcon Grid.Column="0"
Width="14" Height="14" Width="14" Height="14"
Margin="4,0,0,0" Margin="4,0,0,0"
@ -118,7 +118,7 @@
<Grid ColumnDefinitions="Auto,Auto,*" <Grid ColumnDefinitions="Auto,Auto,*"
Background="Transparent" Background="Transparent"
DoubleTapped="OnRowDoubleTapped" DoubleTapped="OnRowDoubleTapped"
ToolTip.Tip="{Binding Path}"> DataContextChanged="OnRowDataContextChanged">
<v:ChangeStatusIcon Grid.Column="0" <v:ChangeStatusIcon Grid.Column="0"
Width="14" Height="14" Width="14" Height="14"
Margin="4,0,0,0" Margin="4,0,0,0"

View file

@ -3,9 +3,11 @@ using System.Collections.Generic;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace SourceGit.Views namespace SourceGit.Views
@ -86,7 +88,7 @@ namespace SourceGit.Views
} }
public static readonly StyledProperty<bool> AutoSelectFirstChangeProperty = public static readonly StyledProperty<bool> AutoSelectFirstChangeProperty =
AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(AutoSelectFirstChange), false); AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(AutoSelectFirstChange));
public bool AutoSelectFirstChange public bool AutoSelectFirstChange
{ {
@ -229,6 +231,28 @@ namespace SourceGit.Views
UpdateSelection(); 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) private void OnRowDoubleTapped(object sender, TappedEventArgs e)
{ {
var grid = sender as Grid; 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; private bool _disableSelectionChangingEvent = false;
} }
} }

View file

@ -9,6 +9,7 @@ namespace SourceGit.Views
{ {
public class ChangeStatusIcon : Control public class ChangeStatusIcon : Control
{ {
private static readonly string[] INDICATOR = ["?", "±", "T", "+", "", "➜", "❏", "★", "!"];
private static readonly IBrush[] BACKGROUNDS = [ private static readonly IBrush[] BACKGROUNDS = [
Brushes.Transparent, Brushes.Transparent,
new LinearGradientBrush new LinearGradientBrush
@ -56,9 +57,6 @@ namespace SourceGit.Views
Brushes.OrangeRed, 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<bool> IsUnstagedChangeProperty = public static readonly StyledProperty<bool> IsUnstagedChangeProperty =
AvaloniaProperty.Register<ChangeStatusIcon, bool>(nameof(IsUnstagedChange)); AvaloniaProperty.Register<ChangeStatusIcon, bool>(nameof(IsUnstagedChange));
@ -116,29 +114,7 @@ namespace SourceGit.Views
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == IsUnstagedChangeProperty || change.Property == ChangeProperty) 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(); InvalidateVisual();
} }
} }
}
} }