fix: try to fix issue #338

* use custom control to draw badges
This commit is contained in:
leo 2024-08-13 18:24:28 +08:00
parent f3406e93fc
commit 59a7c74fd1
No known key found for this signature in database
5 changed files with 214 additions and 37 deletions

View file

@ -36,11 +36,6 @@ namespace SourceGit.ViewModels
get => Backend is Models.Branch; get => Backend is Models.Branch;
} }
public string TrackStatus
{
get => Backend is Models.Branch { IsLocal: true } branch ? branch.TrackStatus.ToString() : string.Empty;
}
public FontWeight NameFontWeight public FontWeight NameFontWeight
{ {
get => Backend is Models.Branch { IsCurrent: true } ? FontWeight.Bold : FontWeight.Regular; get => Backend is Models.Branch { IsCurrent: true } ? FontWeight.Bold : FontWeight.Regular;

View file

@ -83,20 +83,13 @@
FontWeight="{Binding NameFontWeight}"/> FontWeight="{Binding NameFontWeight}"/>
<!-- Tracking status --> <!-- Tracking status -->
<Border Grid.Column="2" <v:BranchTreeNodeTrackStatusPresenter Grid.Column="2"
Margin="8,0" Margin="8,0"
Height="18"
CornerRadius="9"
VerticalAlignment="Center" VerticalAlignment="Center"
Background="{DynamicResource Brush.Badge}" FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
IsVisible="{Binding TrackStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
<TextBlock Classes="primary"
FontSize="10" FontSize="10"
HorizontalAlignment="Center" Foreground="{DynamicResource Brush.BadgeFG}"
Margin="9,0" Background="{DynamicResource Brush.Badge}"/>
Text="{Binding TrackStatus}"
Foreground="{DynamicResource Brush.BadgeFG}"/>
</Border>
<!-- Filter Toggle Button --> <!-- Filter Toggle Button -->
<ToggleButton Grid.Column="3" <ToggleButton Grid.Column="3"

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using Avalonia; using Avalonia;
using Avalonia.Collections; using Avalonia.Collections;
@ -104,6 +105,99 @@ namespace SourceGit.Views
} }
} }
public class BranchTreeNodeTrackStatusPresenter : Control
{
public static readonly StyledProperty<FontFamily> FontFamilyProperty =
TextBlock.FontFamilyProperty.AddOwner<BranchTreeNodeTrackStatusPresenter>();
public FontFamily FontFamily
{
get => GetValue(FontFamilyProperty);
set => SetValue(FontFamilyProperty, value);
}
public static readonly StyledProperty<double> FontSizeProperty =
TextBlock.FontSizeProperty.AddOwner<BranchTreeNodeTrackStatusPresenter>();
public double FontSize
{
get => GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, value);
}
public static readonly StyledProperty<IBrush> ForegroundProperty =
AvaloniaProperty.Register<BranchTreeNodeTrackStatusPresenter, IBrush>(nameof(Foreground), Brushes.White);
public IBrush Foreground
{
get => GetValue(ForegroundProperty);
set => SetValue(ForegroundProperty, value);
}
public static readonly StyledProperty<IBrush> BackgroundProperty =
AvaloniaProperty.Register<BranchTreeNodeTrackStatusPresenter, IBrush>(nameof(Background), Brushes.White);
public IBrush Background
{
get => GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
static BranchTreeNodeTrackStatusPresenter()
{
AffectsMeasure<BranchTreeNodeTrackStatusPresenter>(
FontSizeProperty,
FontFamilyProperty,
ForegroundProperty);
AffectsRender<BranchTreeNodeTrackStatusPresenter>(
ForegroundProperty,
BackgroundProperty);
}
public override void Render(DrawingContext context)
{
base.Render(context);
if (_label != null)
{
context.DrawRectangle(Background, null, new RoundedRect(new Rect(0, 0, _label.Width + 18, 18), new CornerRadius(9)));
context.DrawText(_label, new Point(9, 9 - _label.Height * 0.5));
}
}
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
InvalidateMeasure();
InvalidateVisual();
}
protected override Size MeasureOverride(Size availableSize)
{
_label = null;
if (DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch })
{
var status = branch.TrackStatus.ToString();
if (!string.IsNullOrEmpty(status))
{
_label = new FormattedText(
status,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(FontFamily),
FontSize,
Foreground);
}
}
return _label != null ? new Size(_label.Width + 18, 18) : new Size(0, 0);
}
private FormattedText _label = null;
}
public partial class BranchTree : UserControl public partial class BranchTree : UserControl
{ {
public static readonly StyledProperty<List<ViewModels.BranchTreeNode>> NodesProperty = public static readonly StyledProperty<List<ViewModels.BranchTreeNode>> NodesProperty =

View file

@ -91,15 +91,14 @@
<Grid Classes="view_mode" ColumnDefinitions="32,*,Auto"> <Grid Classes="view_mode" ColumnDefinitions="32,*,Auto">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Changes}"/> <Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.WorkingCopy}"/> <TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.WorkingCopy}"/>
<Border Grid.Column="2" <v:CounterPresenter Grid.Column="2"
Margin="6,0" Margin="6,0"
Height="18"
CornerRadius="9"
VerticalAlignment="Center" VerticalAlignment="Center"
Background="{DynamicResource Brush.Badge}" Count="{Binding LocalChangesCount}"
IsVisible="{Binding LocalChangesCount, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
<TextBlock Classes="primary" FontSize="10" HorizontalAlignment="Center" Margin="9,0" Text="{Binding LocalChangesCount}" Foreground="{DynamicResource Brush.BadgeFG}"/> FontSize="10"
</Border> Foreground="{DynamicResource Brush.BadgeFG}"
Background="{DynamicResource Brush.Badge}"/>
</Grid> </Grid>
</ListBoxItem> </ListBoxItem>
@ -107,15 +106,14 @@
<Grid Classes="view_mode" ColumnDefinitions="32,*,Auto"> <Grid Classes="view_mode" ColumnDefinitions="32,*,Auto">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Stashes}"/> <Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Stashes}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.Stashes}"/> <TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.Stashes}"/>
<Border Grid.Column="2" <v:CounterPresenter Grid.Column="2"
Margin="6,0" Margin="6,0"
Height="18"
CornerRadius="9"
VerticalAlignment="Center" VerticalAlignment="Center"
Background="{DynamicResource Brush.Badge}" Count="{Binding StashesCount}"
IsVisible="{Binding StashesCount, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
<TextBlock Classes="primary" FontSize="10" HorizontalAlignment="Center" Margin="9,0" Text="{Binding StashesCount}" Foreground="{DynamicResource Brush.BadgeFG}"/> FontSize="10"
</Border> Foreground="{DynamicResource Brush.BadgeFG}"
Background="{DynamicResource Brush.Badge}"/>
</Grid> </Grid>
</ListBoxItem> </ListBoxItem>
</ListBox> </ListBox>

View file

@ -1,12 +1,109 @@
using System; using System;
using System.Globalization;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class CounterPresenter : Control
{
public static readonly StyledProperty<int> CountProperty =
AvaloniaProperty.Register<CounterPresenter, int>(nameof(Count), 0);
public int Count
{
get => GetValue(CountProperty);
set => SetValue(CountProperty, value);
}
public static readonly StyledProperty<FontFamily> FontFamilyProperty =
TextBlock.FontFamilyProperty.AddOwner<CounterPresenter>();
public FontFamily FontFamily
{
get => GetValue(FontFamilyProperty);
set => SetValue(FontFamilyProperty, value);
}
public static readonly StyledProperty<double> FontSizeProperty =
TextBlock.FontSizeProperty.AddOwner<CounterPresenter>();
public double FontSize
{
get => GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, value);
}
public static readonly StyledProperty<IBrush> ForegroundProperty =
AvaloniaProperty.Register<CounterPresenter, IBrush>(nameof(Foreground), Brushes.White);
public IBrush Foreground
{
get => GetValue(ForegroundProperty);
set => SetValue(ForegroundProperty, value);
}
public static readonly StyledProperty<IBrush> BackgroundProperty =
AvaloniaProperty.Register<CounterPresenter, IBrush>(nameof(Background), Brushes.White);
public IBrush Background
{
get => GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
static CounterPresenter()
{
AffectsMeasure<CounterPresenter>(
FontSizeProperty,
FontFamilyProperty,
ForegroundProperty,
CountProperty);
AffectsRender<CounterPresenter>(
ForegroundProperty,
BackgroundProperty,
CountProperty);
}
public override void Render(DrawingContext context)
{
base.Render(context);
if (_label != null)
{
context.DrawRectangle(Background, null, new RoundedRect(new Rect(0, 0, _label.Width + 18, 18), new CornerRadius(9)));
context.DrawText(_label, new Point(9, 9 - _label.Height * 0.5));
}
}
protected override Size MeasureOverride(Size availableSize)
{
if (Count > 0)
{
_label = new FormattedText(
Count.ToString(),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(FontFamily),
FontSize,
Foreground);
}
else
{
_label = null;
}
return _label != null ? new Size(_label.Width + 18, 18) : new Size(0, 0);
}
private FormattedText _label = null;
}
public partial class Repository : UserControl public partial class Repository : UserControl
{ {
public Repository() public Repository()