src/StructuredLogViewer.Avalonia/Controls/SplitterPanel.cs (205 lines of code) (raw):
using Avalonia;
using Avalonia.Layout;
using Avalonia.Controls;
namespace StructuredLogViewer.Avalonia.Controls
{
public class SplitterPanel : Grid
{
public GridLength FirstChildRelativeSize
{
get { return GetValue(FirstChildRelativeSizeProperty); }
set { SetValue(FirstChildRelativeSizeProperty, value); }
}
public static readonly StyledProperty<GridLength> FirstChildRelativeSizeProperty =
AvaloniaProperty.Register<SplitterPanel, GridLength>(nameof(FirstChildRelativeSize), new GridLength(1, GridUnitType.Star));
public GridLength SecondChildRelativeSize
{
get { return GetValue(SecondChildRelativeSizeProperty); }
set { SetValue(SecondChildRelativeSizeProperty, value); }
}
public static readonly StyledProperty<GridLength> SecondChildRelativeSizeProperty =
AvaloniaProperty.Register<SplitterPanel, GridLength>(nameof(SecondChildRelativeSize), new GridLength(1, GridUnitType.Star));
private readonly GridSplitter gridSplitter = new GridSplitter();
public Orientation Orientation
{
get { return GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<SplitterPanel, Orientation>(nameof(Orientation), Orientation.Horizontal);
static SplitterPanel()
{
AffectsMeasure<SplitterPanel>(OrientationProperty);
}
private Control firstChild;
public Control FirstChild
{
get { return firstChild; }
set
{
if (firstChild != null)
{
firstChild.PropertyChanged -= OnChildIsVisibleChanged;
}
firstChild = value;
if (firstChild != null)
{
UpdateRowColumnInfo();
firstChild.PropertyChanged += OnChildIsVisibleChanged;
}
}
}
private Control secondChild;
public Control SecondChild
{
get { return secondChild; }
set
{
if (secondChild != null)
{
secondChild.PropertyChanged -= OnChildIsVisibleChanged;
}
secondChild = value;
if (secondChild != null)
{
UpdateRowColumnInfo();
secondChild.PropertyChanged += OnChildIsVisibleChanged;
}
}
}
private void OnChildIsVisibleChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == IsVisibleProperty)
{
UpdateSplitterVisibility();
}
}
private void UpdateRowColumnInfo()
{
Children.Clear();
RowDefinitions.Clear();
ColumnDefinitions.Clear();
if (oldFirstSize == default(GridLength))
{
oldFirstSize = FirstChildRelativeSize;
}
if (oldSecondSize == default(GridLength))
{
oldSecondSize = SecondChildRelativeSize;
}
if (Orientation == Orientation.Horizontal)
{
ColumnDefinitions.Add(new ColumnDefinition() { Width = oldFirstSize });
ColumnDefinitions.Add(new ColumnDefinition() { Width = separatorSize });
ColumnDefinitions.Add(new ColumnDefinition() { Width = oldSecondSize });
RowDefinitions.Add(new RowDefinition());
SetRow(gridSplitter, 0);
SetColumn(gridSplitter, 1);
gridSplitter.Width = 5;
gridSplitter.HorizontalAlignment = HorizontalAlignment.Stretch;
gridSplitter.VerticalAlignment = VerticalAlignment.Stretch;
}
else
{
RowDefinitions.Add(new RowDefinition() { Height = oldFirstSize });
RowDefinitions.Add(new RowDefinition() { Height = separatorSize });
RowDefinitions.Add(new RowDefinition() { Height = oldSecondSize });
ColumnDefinitions.Add(new ColumnDefinition());
SetRow(gridSplitter, 1);
SetColumn(gridSplitter, 0);
gridSplitter.Height = 5;
gridSplitter.HorizontalAlignment = HorizontalAlignment.Stretch;
gridSplitter.VerticalAlignment = VerticalAlignment.Stretch;
}
if (FirstChild != null)
{
SetRow(FirstChild, 0);
SetColumn(FirstChild, 0);
SetRowSpan(FirstChild, 1);
SetColumnSpan(FirstChild, 1);
Children.Add(FirstChild);
}
Children.Add(gridSplitter);
if (SecondChild != null)
{
if (Orientation == Orientation.Horizontal)
{
SetRow(SecondChild, 0);
SetColumn(SecondChild, 2);
}
else
{
SetRow(SecondChild, 2);
SetColumn(SecondChild, 0);
}
SetRowSpan(SecondChild, 1);
SetColumnSpan(SecondChild, 1);
Children.Add(SecondChild);
}
UpdateSplitterVisibility();
}
private GridLength oldFirstSize;
private GridLength oldSecondSize;
private static readonly GridLength zero = new GridLength(0);
private static readonly GridLength separatorSize = new GridLength(5);
private void UpdateSplitterVisibility()
{
bool isFirstChildVisible = FirstChild != null && FirstChild.IsVisible;
bool isSecondChildVisible = SecondChild != null && SecondChild.IsVisible;
bool areBothVisible = isFirstChildVisible && isSecondChildVisible;
gridSplitter.IsVisible = areBothVisible;
if (Orientation == Orientation.Horizontal)
{
if (ColumnDefinitions.Count == 3)
{
if (isFirstChildVisible)
{
if (oldFirstSize == default(GridLength) || oldFirstSize == zero)
{
oldFirstSize = FirstChildRelativeSize;
}
if (ColumnDefinitions[0].Width == zero)
{
ColumnDefinitions[0].Width = oldFirstSize;
}
}
else
{
if (ColumnDefinitions[0].Width != zero)
{
oldFirstSize = ColumnDefinitions[0].Width;
}
ColumnDefinitions[0].Width = zero;
}
if (areBothVisible)
{
ColumnDefinitions[1].Width = separatorSize;
}
else
{
ColumnDefinitions[1].Width = zero;
}
if (isSecondChildVisible)
{
if (oldSecondSize == default(GridLength) || oldSecondSize == zero)
{
oldSecondSize = SecondChildRelativeSize;
}
if (ColumnDefinitions[2].Width == zero)
{
ColumnDefinitions[2].Width = oldSecondSize;
}
}
else
{
if (ColumnDefinitions[2].Width != zero)
{
oldSecondSize = ColumnDefinitions[2].Width;
}
ColumnDefinitions[2].Width = zero;
}
}
}
}
}
}