mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-30 00:24:59 +00:00
refactor: rewrite the histories filter function to supports both include
and exclude
modes (#690)
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
e3ffe3ef6c
commit
ca5bc4b4df
27 changed files with 767 additions and 309 deletions
|
@ -24,6 +24,10 @@
|
|||
<Style Selector="ListBoxItem" x:DataType="vm:BranchTreeNode">
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:pointerover v|FilterModeSwitchButton">
|
||||
<Setter Property="IsNoneVisible" Value="True"/>
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
|
@ -67,15 +71,10 @@
|
|||
Foreground="{DynamicResource Brush.BadgeFG}"
|
||||
Background="{DynamicResource Brush.Badge}"/>
|
||||
|
||||
<!-- Filter Toggle Button -->
|
||||
<ToggleButton Grid.Column="3"
|
||||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
IsVisible="{Binding IsBranch}"
|
||||
IsChecked="{Binding IsFiltered}"
|
||||
Click="OnToggleFilterClicked"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
<!-- Filter Mode Switcher -->
|
||||
<v:FilterModeSwitchButton Grid.Column="3"
|
||||
Margin="0,0,8,0"
|
||||
Mode="{Binding FilterMode}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -428,28 +428,6 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void OnToggleFilterClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo &&
|
||||
sender is ToggleButton toggle &&
|
||||
toggle.DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch } node)
|
||||
{
|
||||
bool filtered = toggle.IsChecked == true;
|
||||
List<string> filters = [branch.FullName];
|
||||
if (branch.IsLocal && !string.IsNullOrEmpty(branch.Upstream))
|
||||
{
|
||||
filters.Add(branch.Upstream);
|
||||
|
||||
node.IsFiltered = filtered;
|
||||
UpdateUpstreamFilterState(repo.RemoteBranchTrees, branch.Upstream, filtered);
|
||||
}
|
||||
|
||||
repo.UpdateFilters(filters, filtered);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MakeRows(List<ViewModels.BranchTreeNode> rows, List<ViewModels.BranchTreeNode> nodes, int depth)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
|
@ -477,23 +455,6 @@ namespace SourceGit.Views
|
|||
CollectBranchesInNode(outs, sub);
|
||||
}
|
||||
|
||||
private bool UpdateUpstreamFilterState(List<ViewModels.BranchTreeNode> collection, string upstream, bool isFiltered)
|
||||
{
|
||||
foreach (var node in collection)
|
||||
{
|
||||
if (node.Backend is Models.Branch b && b.FullName == upstream)
|
||||
{
|
||||
node.IsFiltered = isFiltered;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.Backend is Models.Remote r && upstream.StartsWith($"refs/remotes/{r.Name}/", StringComparison.Ordinal))
|
||||
return UpdateUpstreamFilterState(node.Children, upstream, isFiltered);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool _disableSelectionChangingEvent = false;
|
||||
}
|
||||
}
|
||||
|
|
32
src/Views/FilterModeSwitchButton.axaml
Normal file
32
src/Views/FilterModeSwitchButton.axaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.FilterModeSwitchButton"
|
||||
x:Name="ThisControl">
|
||||
<Button Classes="icon_button"
|
||||
Width="12" Height="12"
|
||||
Padding="0"
|
||||
Background="Transparent"
|
||||
VerticalContentAlignment="Center"
|
||||
Click="OnChangeFilterModeButtonClicked">
|
||||
<Grid>
|
||||
<Path Width="12" Height="12"
|
||||
Data="{StaticResource Icons.Eye}"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
IsVisible="{Binding #ThisControl.Mode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.None}}"/>
|
||||
|
||||
<Path Width="12" Height="12"
|
||||
Data="{StaticResource Icons.Filter}"
|
||||
Fill="{DynamicResource Brush.Accent}"
|
||||
IsVisible="{Binding #ThisControl.Mode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Included}}"/>
|
||||
|
||||
<Path Width="12" Height="12"
|
||||
Data="{StaticResource Icons.EyeClose}"
|
||||
Fill="{DynamicResource Brush.Accent}"
|
||||
IsVisible="{Binding #ThisControl.Mode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
</UserControl>
|
299
src/Views/FilterModeSwitchButton.axaml.cs
Normal file
299
src/Views/FilterModeSwitchButton.axaml.cs
Normal file
|
@ -0,0 +1,299 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class FilterModeSwitchButton : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<Models.FilterMode> ModeProperty =
|
||||
AvaloniaProperty.Register<FilterModeSwitchButton, Models.FilterMode>(nameof(Mode));
|
||||
|
||||
public Models.FilterMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsNoneVisibleProperty =
|
||||
AvaloniaProperty.Register<FilterModeSwitchButton, bool>(nameof(IsNoneVisible));
|
||||
|
||||
public bool IsNoneVisible
|
||||
{
|
||||
get => GetValue(IsNoneVisibleProperty);
|
||||
set => SetValue(IsNoneVisibleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsContextMenuOpeningProperty =
|
||||
AvaloniaProperty.Register<FilterModeSwitchButton, bool>(nameof(IsContextMenuOpening));
|
||||
|
||||
public bool IsContextMenuOpening
|
||||
{
|
||||
get => GetValue(IsContextMenuOpeningProperty);
|
||||
set => SetValue(IsContextMenuOpeningProperty, value);
|
||||
}
|
||||
|
||||
public FilterModeSwitchButton()
|
||||
{
|
||||
IsVisible = false;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == ModeProperty ||
|
||||
change.Property == IsNoneVisibleProperty ||
|
||||
change.Property == IsContextMenuOpeningProperty)
|
||||
{
|
||||
var visible = (Mode != Models.FilterMode.None || IsNoneVisible || IsContextMenuOpening);
|
||||
SetCurrentValue(IsVisibleProperty, visible);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnChangeFilterModeButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var repoView = this.FindAncestorOfType<Repository>();
|
||||
if (repoView == null)
|
||||
return;
|
||||
|
||||
var repo = repoView.DataContext as ViewModels.Repository;
|
||||
if (repo == null)
|
||||
return;
|
||||
|
||||
var button = sender as Button;
|
||||
if (button == null)
|
||||
return;
|
||||
|
||||
if (DataContext is Models.Tag tag)
|
||||
{
|
||||
var mode = tag.FilterMode;
|
||||
|
||||
var none = new MenuItem();
|
||||
none.Icon = App.CreateMenuIcon("Icons.Eye");
|
||||
none.Header = App.Text("Repository.FilterCommits.Default");
|
||||
none.IsEnabled = mode != Models.FilterMode.None;
|
||||
none.Click += (_, ev) =>
|
||||
{
|
||||
UpdateTagFilterMode(repo, tag, Models.FilterMode.None);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var include = new MenuItem();
|
||||
include.Icon = App.CreateMenuIcon("Icons.Filter");
|
||||
include.Header = App.Text("Repository.FilterCommits.Include");
|
||||
include.IsEnabled = mode != Models.FilterMode.Included;
|
||||
include.Click += (_, ev) =>
|
||||
{
|
||||
UpdateTagFilterMode(repo, tag, Models.FilterMode.Included);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var exclude = new MenuItem();
|
||||
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
|
||||
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
|
||||
exclude.IsEnabled = mode != Models.FilterMode.Excluded;
|
||||
exclude.Click += (_, ev) =>
|
||||
{
|
||||
UpdateTagFilterMode(repo, tag, Models.FilterMode.Excluded);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(none);
|
||||
menu.Items.Add(include);
|
||||
menu.Items.Add(exclude);
|
||||
|
||||
if (mode == Models.FilterMode.None)
|
||||
{
|
||||
IsContextMenuOpening = true;
|
||||
menu.Closed += (_, _) => IsContextMenuOpening = false;
|
||||
}
|
||||
|
||||
menu.Open(button);
|
||||
}
|
||||
else if (DataContext is ViewModels.BranchTreeNode node)
|
||||
{
|
||||
var mode = node.FilterMode;
|
||||
|
||||
var none = new MenuItem();
|
||||
none.Icon = App.CreateMenuIcon("Icons.Eye");
|
||||
none.Header = App.Text("Repository.FilterCommits.Default");
|
||||
none.IsEnabled = mode != Models.FilterMode.None;
|
||||
none.Click += (_, ev) =>
|
||||
{
|
||||
UpdateBranchFilterMode(repo, node, Models.FilterMode.None);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var include = new MenuItem();
|
||||
include.Icon = App.CreateMenuIcon("Icons.Filter");
|
||||
include.Header = App.Text("Repository.FilterCommits.Include");
|
||||
include.IsEnabled = mode != Models.FilterMode.Included;
|
||||
include.Click += (_, ev) =>
|
||||
{
|
||||
UpdateBranchFilterMode(repo, node, Models.FilterMode.Included);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var exclude = new MenuItem();
|
||||
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
|
||||
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
|
||||
exclude.IsEnabled = mode != Models.FilterMode.Excluded;
|
||||
exclude.Click += (_, ev) =>
|
||||
{
|
||||
UpdateBranchFilterMode(repo, node, Models.FilterMode.Excluded);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(none);
|
||||
menu.Items.Add(include);
|
||||
menu.Items.Add(exclude);
|
||||
|
||||
if (mode == Models.FilterMode.None)
|
||||
{
|
||||
IsContextMenuOpening = true;
|
||||
menu.Closed += (_, _) => IsContextMenuOpening = false;
|
||||
}
|
||||
|
||||
menu.Open(button);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateTagFilterMode(ViewModels.Repository repo, Models.Tag tag, Models.FilterMode mode)
|
||||
{
|
||||
var changed = repo.Settings.UpdateHistoriesFilter(tag.Name, Models.FilterType.Tag, mode);
|
||||
if (changed)
|
||||
{
|
||||
tag.FilterMode = mode;
|
||||
Task.Run(repo.RefreshCommits);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBranchFilterMode(ViewModels.Repository repo, ViewModels.BranchTreeNode node, Models.FilterMode mode)
|
||||
{
|
||||
var isLocal = node.Path.StartsWith("refs/heads/", StringComparison.Ordinal);
|
||||
var type = isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch;
|
||||
var tree = isLocal ? repo.LocalBranchTrees : repo.RemoteBranchTrees;
|
||||
|
||||
if (node.Backend is Models.Branch branch)
|
||||
{
|
||||
var changed = repo.Settings.UpdateHistoriesFilter(node.Path, type, mode);
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
node.FilterMode = mode;
|
||||
|
||||
// Try to update its upstream.
|
||||
if (isLocal && !string.IsNullOrEmpty(branch.Upstream) && mode != Models.FilterMode.Excluded)
|
||||
{
|
||||
var upstream = branch.Upstream;
|
||||
var upstreamNode = FindBranchNode(repo.RemoteBranchTrees, upstream);
|
||||
if (upstreamNode != null)
|
||||
{
|
||||
var canUpdateUpstream = true;
|
||||
foreach (var filter in repo.Settings.HistoriesFilters)
|
||||
{
|
||||
bool matched = false;
|
||||
if (filter.Type == Models.FilterType.RemoteBranch)
|
||||
matched = filter.Pattern.Equals(upstream, StringComparison.Ordinal);
|
||||
else if (filter.Type == Models.FilterType.RemoteBranchFolder)
|
||||
matched = upstream.StartsWith(filter.Pattern, StringComparison.Ordinal);
|
||||
|
||||
if (matched && filter.Mode == Models.FilterMode.Excluded)
|
||||
{
|
||||
canUpdateUpstream = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (canUpdateUpstream)
|
||||
{
|
||||
changed = repo.Settings.UpdateHistoriesFilter(upstream, Models.FilterType.RemoteBranch, mode);
|
||||
if (changed)
|
||||
upstreamNode.FilterMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var changed = repo.Settings.UpdateHistoriesFilter(node.Path, isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder, mode);
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
node.FilterMode = mode;
|
||||
ResetChildrenBranchNodeFilterMode(repo, node, isLocal);
|
||||
}
|
||||
|
||||
var parentType = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
|
||||
var cur = node;
|
||||
do
|
||||
{
|
||||
var lastSepIdx = cur.Path.LastIndexOf('/');
|
||||
if (lastSepIdx <= 0)
|
||||
break;
|
||||
|
||||
var parentPath = cur.Path.Substring(0, lastSepIdx);
|
||||
var parent = FindBranchNode(tree, parentPath);
|
||||
if (parent == null)
|
||||
break;
|
||||
|
||||
repo.Settings.UpdateHistoriesFilter(parent.Path, parentType, Models.FilterMode.None);
|
||||
parent.FilterMode = Models.FilterMode.None;
|
||||
cur = parent;
|
||||
} while (true);
|
||||
|
||||
Task.Run(repo.RefreshCommits);
|
||||
}
|
||||
|
||||
private void ResetChildrenBranchNodeFilterMode(ViewModels.Repository repo, ViewModels.BranchTreeNode node, bool isLocal)
|
||||
{
|
||||
foreach (var child in node.Children)
|
||||
{
|
||||
child.FilterMode = Models.FilterMode.None;
|
||||
|
||||
if (child.IsBranch)
|
||||
{
|
||||
var type = isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch;
|
||||
repo.Settings.UpdateHistoriesFilter(child.Path, type, Models.FilterMode.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
|
||||
repo.Settings.UpdateHistoriesFilter(child.Path, type, Models.FilterMode.None);
|
||||
ResetChildrenBranchNodeFilterMode(repo, child, isLocal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ViewModels.BranchTreeNode FindBranchNode(List<ViewModels.BranchTreeNode> nodes, string path)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if (node.Path.Equals(path, StringComparison.Ordinal))
|
||||
return node;
|
||||
|
||||
if (path.StartsWith(node.Path, StringComparison.Ordinal))
|
||||
{
|
||||
var founded = FindBranchNode(node.Children, path);
|
||||
if (founded != null)
|
||||
return founded;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -577,14 +577,14 @@
|
|||
<Border.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsZero}"/>
|
||||
<Binding Path="Settings.Filters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
|
||||
<Binding Path="Settings.HistoriesFilters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
|
||||
</MultiBinding>
|
||||
</Border.IsVisible>
|
||||
|
||||
<Grid Height="28" ColumnDefinitions="Auto,*,Auto">
|
||||
<TextBlock Grid.Column="0" Margin="8,0,0,0" Classes="table_header" Text="{DynamicResource Text.Repository.FilterCommitPrefix}"/>
|
||||
<TextBlock Grid.Column="0" Margin="8,0,0,0" Classes="table_header" Text="{DynamicResource Text.Repository.FilterCommits.Prefix}"/>
|
||||
|
||||
<ItemsControl Grid.Column="1" Margin="8,0,0,0" ItemsSource="{Binding Settings.Filters}">
|
||||
<ItemsControl Grid.Column="1" Margin="8,0,0,0" ItemsSource="{Binding Settings.HistoriesFilters}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
|
||||
|
@ -592,9 +592,17 @@
|
|||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Height="20" Margin="0,0,6,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="12">
|
||||
<TextBlock Classes="primary" Text="{Binding Converter={x:Static c:StringConverters.TrimRefsPrefix}}" Margin="8,0"/>
|
||||
<DataTemplate DataType="m:Filter">
|
||||
<Border Height="20"
|
||||
Margin="0,0,6,0"
|
||||
CornerRadius="12"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{Binding Mode, Converter={x:Static c:FilterModeConverters.ToBorderBrush}}">
|
||||
<StackPanel Orientation="Horizontal" Margin="8,0">
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Branch}" IsVisible="{Binding IsBranch}"/>
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Tag}" IsVisible="{Binding !IsBranch}"/>
|
||||
<TextBlock Classes="primary" Text="{Binding Pattern, Converter={x:Static c:StringConverters.TrimRefsPrefix}}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:pointerover v|FilterModeSwitchButton">
|
||||
<Setter Property="IsNoneVisible" Value="True"/>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<UserControl.DataTemplates>
|
||||
|
@ -43,15 +47,14 @@
|
|||
Classes="primary"
|
||||
Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}}"
|
||||
Margin="8,0,0,0"/>
|
||||
|
||||
<ToggleButton Grid.Column="3"
|
||||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
Click="OnToggleFilterClicked"
|
||||
IsChecked="{Binding IsFiltered, Mode=TwoWay}"
|
||||
IsVisible="{Binding !IsFolder}"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
|
||||
<ContentControl Grid.Column="3" Content="{Binding Tag}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:Tag">
|
||||
<v:FilterModeSwitchButton Mode="{Binding FilterMode}"/>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
@ -60,33 +63,28 @@
|
|||
|
||||
<DataTemplate DataType="vm:TagCollectionAsList">
|
||||
<ListBox Classes="repo_left_content_list"
|
||||
Margin="12,0,0,0"
|
||||
Margin="8,0,0,0"
|
||||
ItemsSource="{Binding Tags}"
|
||||
SelectionMode="Single"
|
||||
SelectionChanged="OnRowSelectionChanged">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="m:Tag">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||
<Grid ColumnDefinitions="Auto,*,20"
|
||||
Background="Transparent"
|
||||
ContextRequested="OnRowContextRequested"
|
||||
ToolTip.Tip="{Binding Message}">
|
||||
<Path Grid.Column="0"
|
||||
Margin="4,0,0,0"
|
||||
Margin="8,0,0,0"
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.Tag}"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="primary"
|
||||
Text="{Binding Name}"
|
||||
Margin="8,0,0,0"/>
|
||||
Margin="8,0,0,0"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
|
||||
<ToggleButton Grid.Column="2"
|
||||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
Click="OnToggleFilterClicked"
|
||||
IsChecked="{Binding IsFiltered, Mode=TwoWay}"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
<v:FilterModeSwitchButton Grid.Column="2" Mode="{Binding FilterMode}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
|
|
@ -247,23 +247,6 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void OnToggleFilterClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton toggle && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var target = null as Models.Tag;
|
||||
if (toggle.DataContext is ViewModels.TagTreeNode node)
|
||||
target = node.Tag;
|
||||
else if (toggle.DataContext is Models.Tag tag)
|
||||
target = tag;
|
||||
|
||||
if (target != null)
|
||||
repo.UpdateFilters([target.Name], toggle.IsChecked == true);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MakeTreeRows(List<ViewModels.TagTreeNode> rows, List<ViewModels.TagTreeNode> nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue