using System.Linq;
using Avalonia.Collections;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
namespace Avalonia.Controls
{
///
/// A tab control that displays a tab strip along with the content of the selected tab.
///
public class TabControl : SelectingItemsControl, IContentPresenterHost
{
///
/// Defines the property.
///
public static readonly StyledProperty TabStripPlacementProperty =
AvaloniaProperty.Register(nameof(TabStripPlacement), defaultValue: Dock.Top);
///
/// Defines the property.
///
public static readonly StyledProperty HorizontalContentAlignmentProperty =
ContentControl.HorizontalContentAlignmentProperty.AddOwner();
///
/// Defines the property.
///
public static readonly StyledProperty VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner();
///
/// Defines the property.
///
public static readonly StyledProperty ContentTemplateProperty =
ContentControl.ContentTemplateProperty.AddOwner();
///
/// The selected content property
///
public static readonly StyledProperty SelectedContentProperty =
AvaloniaProperty.Register(nameof(SelectedContent));
///
/// The selected content template property
///
public static readonly StyledProperty SelectedContentTemplateProperty =
AvaloniaProperty.Register(nameof(SelectedContentTemplate));
///
/// The default value for the property.
///
private static readonly FuncTemplate DefaultPanel =
new FuncTemplate(() => new WrapPanel());
///
/// Initializes static members of the class.
///
static TabControl()
{
SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected);
ItemsPanelProperty.OverrideDefaultValue(DefaultPanel);
AffectsMeasure(TabStripPlacementProperty);
SelectedIndexProperty.Changed.AddClassHandler((x, e) => x.UpdateSelectedContent(e));
}
///
/// Gets or sets the horizontal alignment of the content within the control.
///
public HorizontalAlignment HorizontalContentAlignment
{
get { return GetValue(HorizontalContentAlignmentProperty); }
set { SetValue(HorizontalContentAlignmentProperty, value); }
}
///
/// Gets or sets the vertical alignment of the content within the control.
///
public VerticalAlignment VerticalContentAlignment
{
get { return GetValue(VerticalContentAlignmentProperty); }
set { SetValue(VerticalContentAlignmentProperty, value); }
}
///
/// Gets or sets the tabstrip placement of the TabControl.
///
public Dock TabStripPlacement
{
get { return GetValue(TabStripPlacementProperty); }
set { SetValue(TabStripPlacementProperty, value); }
}
///
/// Gets or sets the default data template used to display the content of the selected tab.
///
public IDataTemplate ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
}
///
/// Gets or sets the content of the selected tab.
///
///
/// The content of the selected tab.
///
public object SelectedContent
{
get { return GetValue(SelectedContentProperty); }
internal set { SetValue(SelectedContentProperty, value); }
}
///
/// Gets or sets the content template for the selected tab.
///
///
/// The content template of the selected tab.
///
public IDataTemplate SelectedContentTemplate
{
get { return GetValue(SelectedContentTemplateProperty); }
internal set { SetValue(SelectedContentTemplateProperty, value); }
}
internal ItemsPresenter ItemsPresenterPart { get; private set; }
internal IContentPresenter ContentPart { get; private set; }
///
IAvaloniaList IContentPresenterHost.LogicalChildren => LogicalChildren;
///
bool IContentPresenterHost.RegisterContentPresenter(IContentPresenter presenter)
{
return RegisterContentPresenter(presenter);
}
protected override void OnContainersMaterialized(ItemContainerEventArgs e)
{
base.OnContainersMaterialized(e);
if (SelectedContent != null || SelectedIndex == -1)
{
return;
}
var container = (TabItem)ItemContainerGenerator.ContainerFromIndex(SelectedIndex);
if (container == null)
{
return;
}
UpdateSelectedContent(container);
}
private void UpdateSelectedContent(AvaloniaPropertyChangedEventArgs e)
{
var index = (int)e.NewValue;
if (index == -1)
{
SelectedContentTemplate = null;
SelectedContent = null;
return;
}
var container = (TabItem)ItemContainerGenerator.ContainerFromIndex(index);
if (container == null)
{
return;
}
UpdateSelectedContent(container);
}
private void UpdateSelectedContent(IContentControl item)
{
if (SelectedContentTemplate != item.ContentTemplate)
{
SelectedContentTemplate = item.ContentTemplate;
}
if (SelectedContent != item.Content)
{
SelectedContent = item.Content;
}
}
///
/// Called when an is registered with the control.
///
/// The presenter.
protected virtual bool RegisterContentPresenter(IContentPresenter presenter)
{
if (presenter.Name == "PART_SelectedContentHost")
{
ContentPart = presenter;
return true;
}
return false;
}
protected override IItemContainerGenerator CreateItemContainerGenerator()
{
return new TabItemContainerGenerator(this);
}
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
{
base.OnTemplateApplied(e);
ItemsPresenterPart = e.NameScope.Get("PART_ItemsPresenter");
}
///
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
if (e.NavigationMethod == NavigationMethod.Directional)
{
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}
///
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse)
{
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Left && e.Pointer.Type != PointerType.Mouse)
{
var container = GetContainerFromEventSource(e.Source);
if (container != null
&& container.GetVisualsAt(e.GetPosition(container))
.Any(c => container == c || container.IsVisualAncestorOf(c)))
{
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}
}
}
}