New icon for annotated tag, to distinguish from lightweight tag

The new icon is applied everywhere - except for Models.Decorator and Models.Filter, since these are not (yet) updated to discern the specific tag type.
This commit is contained in:
Göran W 2025-05-12 22:45:27 +02:00
parent 8a45e25106
commit 47fa073b40
11 changed files with 76 additions and 17 deletions

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
Context = repo;
WorkingDirectory = repo;
Args = $"tag -l --format=\"{_boundary}%(refname)%00%(objectname)%00%(*objectname)%00%(creatordate:unix)%00%(contents:subject)%0a%0a%(contents:body)\"";
Args = $"tag -l --format=\"{_boundary}%(refname)%00%(objecttype)%00%(objectname)%00%(*objectname)%00%(creatordate:unix)%00%(contents:subject)%0a%0a%(contents:body)\"";
}
public List<Models.Tag> Result()
@ -25,16 +25,17 @@ namespace SourceGit.Commands
foreach (var record in records)
{
var subs = record.Split('\0', StringSplitOptions.None);
if (subs.Length != 5)
if (subs.Length != 6)
continue;
var name = subs[0].Substring(10);
var message = subs[4].Trim();
var name = subs[0].Substring(10); // Skip the prefix "refs/tags/"
var message = subs[5].Trim();
tags.Add(new Models.Tag()
{
Name = name,
SHA = string.IsNullOrEmpty(subs[2]) ? subs[1] : subs[2],
CreatorDate = ulong.Parse(subs[3]),
Type = (subs[1] == "tag") ? Models.TagType.Annotated : Models.TagType.Lightweight, // tag/commit
SHA = string.IsNullOrEmpty(subs[3]) ? subs[2] : subs[3],
CreatorDate = ulong.Parse(subs[4]),
Message = string.IsNullOrEmpty(message) ? name : message,
});
}

View file

@ -9,9 +9,16 @@ namespace SourceGit.Models
NameInDescending,
}
public enum TagType
{
Lightweight = 0,
Annotated,
}
public class Tag : ObservableObject
{
public string Name { get; set; } = string.Empty;
public TagType Type { get; set; } = TagType.Lightweight;
public string SHA { get; set; } = string.Empty;
public ulong CreatorDate { get; set; } = 0;
public string Message { get; set; } = string.Empty;
@ -23,5 +30,7 @@ namespace SourceGit.Models
}
private FilterMode _filterMode = FilterMode.None;
public bool IsLightweight => (Type == TagType.Lightweight);
}
}

View file

@ -123,6 +123,7 @@
<StreamGeometry x:Key="Icons.SyntaxHighlight">M875 128h-725A107 107 0 0043 235v555A107 107 0 00149 896h725a107 107 0 00107-107v-555A107 107 0 00875 128zm-115 640h-183v-58l25-3c15 0 19-8 14-24l-22-61H419l-28 82 39 2V768h-166v-58l18-3c18-2 22-11 26-24l125-363-40-4V256h168l160 448 39 3zM506 340l-72 218h145l-71-218h-2z</StreamGeometry>
<StreamGeometry x:Key="Icons.Tag">M177 156c-22 5-33 17-36 37c-10 57-33 258-13 278l445 445c23 23 61 23 84 0l246-246c23-23 23-61 0-84l-445-445C437 120 231 145 177 156zM331 344c-26 26-69 26-95 0c-26-26-26-69 0-95s69-26 95 0C357 276 357 318 331 344z</StreamGeometry>
<StreamGeometry x:Key="Icons.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</StreamGeometry>
<StreamGeometry x:Key="Icons.Tag.Annotated">M 177 156 c -22 5 -33 17 -36 37 c -10 57 -33 258 -13 278 l 445 445 c 23 23 61 23 84 0 l 246 -246 c 23 -23 23 -61 0 -84 l -445 -445 c -21 -21 -227 4 -281 15 z M 331 344 c -26 26 -69 26 -95 0 c -26 -26 -26 -69 0 -95 s 69 -26 95 0 c 26 27 26 69 0 95 m 115 -15 l 30 -30 l 340 340 l -60 60 l -340 -340 l 30 -30 m -125 125 l 30 -30 l 340 340 l -60 60 l -340 -340 l 30 -30 z</StreamGeometry>
<StreamGeometry x:Key="Icons.Tags">M996 452 572 28A96 96 0 00504 0H96C43 0 0 43 0 96v408a96 96 0 0028 68l424 424c37 37 98 37 136 0l408-408c37-37 37-98 0-136zM224 320c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96zm1028 268L844 996c-37 37-98 37-136 0l-1-1L1055 647c34-34 53-79 53-127s-19-93-53-127L663 0h97a96 96 0 0168 28l424 424c37 37 37 98 0 136z</StreamGeometry>
<StreamGeometry x:Key="Icons.Target">M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z</StreamGeometry>
<StreamGeometry x:Key="Icons.Terminal">M144 112h736c18 0 32 14 32 32v736c0 18-14 32-32 32H144c-18 0-32-14-32-32V144c0-18 14-32 32-32zm112 211v72a9 9 0 003 7L386 509 259 615a9 9 0 00-3 7v72a9 9 0 0015 7L493 516a9 9 0 000-14l-222-186a9 9 0 00-15 7zM522 624a10 10 0 00-10 10v60a10 10 0 0010 10h237a10 10 0 0010-10v-60a10 10 0 00-10-10H522z</StreamGeometry>

View file

@ -1165,7 +1165,7 @@ namespace SourceGit.ViewModels
{
var submenu = new MenuItem();
submenu.Header = tag.Name;
submenu.Icon = App.CreateMenuIcon("Icons.Tag");
submenu.Icon = App.CreateMenuIcon(tag.IsLightweight ? "Icons.Tag" : "Icons.Tag.Annotated");
submenu.MinWidth = 200;
FillTagVisibilityMenu(submenu, tag);

View file

@ -37,7 +37,8 @@
<DataTemplate DataType="m:Tag">
<StackPanel Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}" IsVisible="{Binding IsLightweight}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag.Annotated}" IsVisible="{Binding !IsLightweight}"/>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>

View file

@ -38,7 +38,8 @@
<DataTemplate DataType="m:Tag">
<StackPanel Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}" IsVisible="{Binding IsLightweight}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag.Annotated}" IsVisible="{Binding !IsLightweight}"/>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>

View file

@ -17,7 +17,8 @@
Text="{DynamicResource Text.DeleteTag.Tag}"/>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}" IsVisible="{Binding Target.IsLightweight}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag.Annotated}" IsVisible="{Binding !Target.IsLightweight}"/>
<TextBlock Text="{Binding Target.Name}" Margin="8,0,0,0"/>
</StackPanel>

View file

@ -36,7 +36,8 @@
<DataTemplate DataType="m:Tag">
<StackPanel Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}" IsVisible="{Binding IsLightweight}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag.Annotated}" IsVisible="{Binding !IsLightweight}"/>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>

View file

@ -18,7 +18,8 @@
Text="{DynamicResource Text.PushTag.Tag}"/>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag}" IsVisible="{Binding Target.IsLightweight}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Tag.Annotated}" IsVisible="{Binding !Target.IsLightweight}"/>
<TextBlock Text="{Binding Target.Name}" Margin="8,0,0,0"/>
</StackPanel>

View file

@ -72,10 +72,7 @@
<DataTemplate DataType="m:Tag">
<Border Height="24" Background="Transparent" PointerPressed="OnRowPointerPressed" ContextRequested="OnRowContextRequested">
<Grid ColumnDefinitions="Auto,*,Auto" VerticalAlignment="Center" ToolTip.Tip="{Binding Message}">
<Path Grid.Column="0"
Margin="8,0,0,0"
Width="12" Height="12"
Data="{StaticResource Icons.Tag}"/>
<v:TagIcon Grid.Column="0" Node="{Binding .}"/>
<Border Grid.Column="1" Background="Transparent">
<TextBlock Classes="primary"

View file

@ -65,7 +65,7 @@ namespace SourceGit.Views
}
if (node.Tag != null)
CreateContent(new Thickness(0, 0, 0, 0), "Icons.Tag");
CreateContent(new Thickness(0, 0, 0, 0), node.Tag.IsLightweight ? "Icons.Tag" : "Icons.Tag.Annotated");
else if (node.IsExpanded)
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder.Open");
else
@ -90,6 +90,52 @@ namespace SourceGit.Views
}
}
public class TagIcon : UserControl
{
public static readonly StyledProperty<Models.Tag> NodeProperty =
AvaloniaProperty.Register<TagIcon, Models.Tag>(nameof(Node));
public Models.Tag Node
{
get => GetValue(NodeProperty);
set => SetValue(NodeProperty, value);
}
static TagIcon()
{
NodeProperty.Changed.AddClassHandler<TagIcon>((icon, _) => icon.UpdateContent());
}
private void UpdateContent()
{
var node = Node;
if (node == null)
{
Content = null;
return;
}
CreateContent(new Thickness(8, 0, 0, 0), node.IsLightweight ? "Icons.Tag" : "Icons.Tag.Annotated");
}
private void CreateContent(Thickness margin, string iconKey)
{
var geo = this.FindResource(iconKey) as StreamGeometry;
if (geo == null)
return;
Content = new Avalonia.Controls.Shapes.Path()
{
Width = 12,
Height = 12,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
Margin = margin,
Data = geo,
};
}
}
public partial class TagsView : UserControl
{
public static readonly StyledProperty<bool> ShowTagsAsTreeProperty =