refactor: use a custom indent icon instead of tree depth margin for worktrees

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2026-03-06 12:02:10 +08:00
parent 242ab5b018
commit 90dd88a4c6
3 changed files with 70 additions and 12 deletions

View File

@@ -10,10 +10,10 @@ namespace SourceGit.ViewModels
public Models.Worktree Backend { get; private set; }
public bool IsMain { get; private set; }
public bool IsCurrent { get; private set; }
public bool IsLast { get; private set; }
public string DisplayPath { get; private set; }
public string Name { get; private set; }
public string Branch { get; private set; }
public int Depth { get; private set; }
public bool IsLocked
{
@@ -24,15 +24,15 @@ namespace SourceGit.ViewModels
public string FullPath => Backend.FullPath;
public string Head => Backend.Head;
public Worktree(DirectoryInfo repo, Models.Worktree wt, bool isMain)
public Worktree(DirectoryInfo repo, Models.Worktree wt, bool isMain, bool isLast)
{
Backend = wt;
IsMain = isMain;
IsCurrent = IsCurrentWorktree(repo, wt);
IsLast = isLast;
DisplayPath = IsCurrent ? string.Empty : Path.GetRelativePath(repo.FullName, wt.FullPath);
Name = GenerateName();
Branch = GenerateBranchName();
Depth = isMain ? 0 : 1;
IsLocked = wt.IsLocked;
}
@@ -43,9 +43,9 @@ namespace SourceGit.ViewModels
var repoDir = new DirectoryInfo(repo);
var nodes = new List<Worktree>();
nodes.Add(new(repoDir, worktrees[0], true));
nodes.Add(new(repoDir, worktrees[0], true, false));
for (int i = 1; i < worktrees.Count; i++)
nodes.Add(new(repoDir, worktrees[i], false));
nodes.Add(new(repoDir, worktrees[i], false, i == worktrees.Count - 1));
return nodes;
}

View File

@@ -412,7 +412,7 @@
Height="0"
Margin="12,0,4,0"
Classes="repo_left_content_list"
ItemsSource="{Binding Worktrees}"
ItemsSource="{Binding Worktrees, Mode=OneWay}"
SelectionMode="Single"
PropertyChanged="OnWorktreeListPropertyChanged"
IsVisible="{Binding IsWorktreeGroupExpanded, Mode=OneWay}">
@@ -473,13 +473,12 @@
</Grid>
</StackPanel>
</ToolTip.Tip>
<Grid ColumnDefinitions="Auto,*,22"
Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
VerticalAlignment="Center">
<v:WorktreeIcon Grid.Column="0"
<Grid ColumnDefinitions="Auto,Auto,*,22" VerticalAlignment="Center">
<v:WorktreeDepthIcon Grid.Column="0" Brush="{DynamicResource Brush.Border1}"/>
<v:WorktreeIcon Grid.Column="1"
Width="10" Height="10"
Margin="8,0,0,0"/>
<TextBlock Grid.Column="1"
<TextBlock Grid.Column="2"
Margin="8,0,0,0"
Foreground="{DynamicResource Brush.FG2}"
TextTrimming="CharacterEllipsis">
@@ -488,7 +487,7 @@
Foreground="{DynamicResource Brush.FG1}"/>
<Run Text="{Binding DisplayPath, Mode=OneWay}"/>
</TextBlock>
<Path Grid.Column="2"
<Path Grid.Column="3"
Width="10" Height="10"
Margin="4,0,0,0"
Data="{StaticResource Icons.Lock}"

View File

@@ -0,0 +1,59 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
namespace SourceGit.Views
{
public class WorktreeDepthIcon : Control
{
public static readonly StyledProperty<IBrush> BrushProperty =
AvaloniaProperty.Register<WorktreeDepthIcon, IBrush>(nameof(Brush), Brushes.Transparent);
public IBrush Brush
{
get => GetValue(BrushProperty);
set => SetValue(BrushProperty, value);
}
public override void Render(DrawingContext context)
{
if (DataContext is ViewModels.Worktree wt)
{
if (wt.IsMain)
return;
var pen = new Pen(Brush);
var h = Bounds.Height;
var halfH = h * 0.5;
if (wt.IsLast)
context.DrawLine(pen, new Point(12.5, 0), new Point(12.5, halfH));
else
context.DrawLine(pen, new Point(12.5, 0), new Point(12.5, h));
context.DrawLine(pen, new Point(12.5, halfH), new Point(18, halfH));
}
}
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
InvalidateMeasure();
}
protected override Size MeasureOverride(Size availableSize)
{
if (DataContext is ViewModels.Worktree wt)
{
if (wt.IsMain)
return new Size(0, 0);
return new Size(18, availableSize.Height);
}
return new Size(0, 0);
}
}
}