A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

125 lines
4.1 KiB

using System.Diagnostics;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Primitives;
using Avalonia.Diagnostics.ViewModels;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.VisualTree;
namespace Avalonia.Diagnostics.Views
{
internal class TreePageView : UserControl
{
private readonly Panel _adorner;
private AdornerLayer? _currentLayer;
private TreeView _tree;
public TreePageView()
{
InitializeComponent();
_tree = this.FindControl<TreeView>("tree");
_tree.ItemContainerGenerator.Index.Materialized += TreeViewItemMaterialized;
_adorner = new Panel
{
ClipToBounds = false,
Children =
{
//Padding frame
new Border { BorderBrush = new SolidColorBrush(Colors.Green, 0.5) },
//Content frame
new Border { Background = new SolidColorBrush(Color.FromRgb(160, 197, 232), 0.5) },
//Margin frame
new Border { BorderBrush = new SolidColorBrush(Colors.Yellow, 0.5) }
},
};
}
protected void AddAdorner(object? sender, PointerEventArgs e)
{
var node = (TreeNode?)((Control)sender!).DataContext;
var vm = (TreePageViewModel?)DataContext;
if (node is null || vm is null)
{
return;
}
var visual = (Visual)node.Visual;
_currentLayer = AdornerLayer.GetAdornerLayer(visual);
if (_currentLayer == null ||
_currentLayer.Children.Contains(_adorner))
{
return;
}
_currentLayer.Children.Add(_adorner);
AdornerLayer.SetAdornedElement(_adorner, visual);
if (vm.MainView.ShouldVisualizeMarginPadding)
{
var paddingBorder = (Border)_adorner.Children[0];
paddingBorder.BorderThickness = visual.GetValue(PaddingProperty);
var contentBorder = (Border)_adorner.Children[1];
contentBorder.Margin = visual.GetValue(PaddingProperty);
var marginBorder = (Border)_adorner.Children[2];
marginBorder.BorderThickness = visual.GetValue(MarginProperty);
marginBorder.Margin = InvertThickness(visual.GetValue(MarginProperty));
}
}
private static Thickness InvertThickness(Thickness input)
{
return new Thickness(-input.Left, -input.Top, -input.Right, -input.Bottom);
}
protected void RemoveAdorner(object? sender, PointerEventArgs e)
{
foreach (var border in _adorner.Children.OfType<Border>())
{
border.Margin = default;
border.Padding = default;
border.BorderThickness = default;
}
_currentLayer?.Children.Remove(_adorner);
_currentLayer = null;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void TreeViewItemMaterialized(object? sender, ItemContainerEventArgs e)
{
var item = (TreeViewItem)e.Containers[0].ContainerControl;
item.TemplateApplied += TreeViewItemTemplateApplied;
}
private void TreeViewItemTemplateApplied(object? sender, TemplateAppliedEventArgs e)
{
var item = (TreeViewItem)sender!;
// This depends on the default tree item template.
// We want to handle events in the item header but exclude events coming from children.
var header = item.FindDescendantOfType<Border>();
Debug.Assert(header != null);
if (header != null)
{
header.PointerEnter += AddAdorner;
header.PointerLeave += RemoveAdorner;
}
item.TemplateApplied -= TreeViewItemTemplateApplied;
}
}
}