diff --git a/src/AtomUI.Controls/TabControl/BaseTabControl.cs b/src/AtomUI.Controls/TabControl/BaseTabControl.cs index 68fc971a8..bc0dd0f18 100644 --- a/src/AtomUI.Controls/TabControl/BaseTabControl.cs +++ b/src/AtomUI.Controls/TabControl/BaseTabControl.cs @@ -11,6 +11,7 @@ using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.LogicalTree; using Avalonia.Media; +using Avalonia.VisualTree; namespace AtomUI.Controls; @@ -126,7 +127,6 @@ public class BaseTabControl : AvaloniaTabControl, base.OnApplyTemplate(e); _frame = e.NameScope.Find(BaseTabControlTheme.FramePart); _alignWrapper = e.NameScope.Find(BaseTabControlTheme.AlignWrapperPart); - HandlePlacementChanged(); } protected override void PrepareContainerForItemOverride(Control container, object? item, int index) @@ -142,10 +142,6 @@ public class BaseTabControl : AvaloniaTabControl, { base.OnAttachedToLogicalTree(e); _tokenBindingsDisposable = new CompositeDisposable(); - - this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, TabAndContentGutterProperty, - TabControlTokenKey.TabAndContentGutter)); - UpdatePseudoClasses(); } protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) @@ -163,14 +159,22 @@ public class BaseTabControl : AvaloniaTabControl, SharedTokenKey.BorderThickness, BindingPriority.Template, new RenderScaleAwareThicknessConfigure(this))); } + this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, TabAndContentGutterProperty, + TabControlTokenKey.TabAndContentGutter)); + UpdatePseudoClasses(); + HandlePlacementChanged(); } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); - if (change.Property == TabStripPlacementProperty) + if (this.IsAttachedToVisualTree()) { - HandlePlacementChanged(); + if (change.Property == TabStripPlacementProperty) + { + UpdatePseudoClasses(); + HandlePlacementChanged(); + } } } @@ -184,7 +188,6 @@ public class BaseTabControl : AvaloniaTabControl, private void HandlePlacementChanged() { - UpdatePseudoClasses(); if (TabStripPlacement == Dock.Top) { TabStripMargin = new Thickness(0, 0, 0, _tabAndContentGutter); diff --git a/src/AtomUI.Controls/TabControl/BaseTabScrollViewer.cs b/src/AtomUI.Controls/TabControl/BaseTabScrollViewer.cs index 258f24b9d..080339229 100644 --- a/src/AtomUI.Controls/TabControl/BaseTabScrollViewer.cs +++ b/src/AtomUI.Controls/TabControl/BaseTabScrollViewer.cs @@ -92,25 +92,13 @@ internal abstract class BaseTabScrollViewer : ScrollViewer, AffectsMeasure(TabStripPlacementProperty); } - public BaseTabScrollViewer() - { - HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; - } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); - if (change.Property == TabStripPlacementProperty) - { - if (Presenter is TabScrollContentPresenter tabStripScrollContentPresenter) - { - tabStripScrollContentPresenter.TabStripPlacement = TabStripPlacement; - } - } - else if (change.Property == VerticalScrollBarVisibilityProperty || - change.Property == OffsetProperty || - change.Property == ExtentProperty || - change.Property == ViewportProperty) + if (change.Property == VerticalScrollBarVisibilityProperty || + change.Property == OffsetProperty || + change.Property == ExtentProperty || + change.Property == ViewportProperty) { SetupIndicatorsVisibility(); } diff --git a/src/AtomUI.Controls/TabControl/BaseTabScrollViewerTheme.cs b/src/AtomUI.Controls/TabControl/BaseTabScrollViewerTheme.cs index dfcbb95a7..0d55ff4b5 100644 --- a/src/AtomUI.Controls/TabControl/BaseTabScrollViewerTheme.cs +++ b/src/AtomUI.Controls/TabControl/BaseTabScrollViewerTheme.cs @@ -89,6 +89,8 @@ internal class BaseTabScrollViewerTheme : BaseControlTheme Name = ScrollViewContentPart }; + CreateTemplateParentBinding(scrollViewContent, TabScrollContentPresenter.TabStripPlacementProperty, + BaseTabScrollViewer.TabStripPlacementProperty); CreateTemplateParentBinding(scrollViewContent, Layoutable.MarginProperty, TemplatedControl.PaddingProperty); CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.HorizontalSnapPointsAlignmentProperty, @@ -117,6 +119,7 @@ internal class BaseTabScrollViewerTheme : BaseControlTheme protected override void BuildStyles() { + this.Add(BaseTabScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Auto); { var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(ScrollMenuIndicatorPart)); diff --git a/src/AtomUI.Controls/TabControl/CardTabControl.cs b/src/AtomUI.Controls/TabControl/CardTabControl.cs index e6bd2053e..b40b1b75e 100644 --- a/src/AtomUI.Controls/TabControl/CardTabControl.cs +++ b/src/AtomUI.Controls/TabControl/CardTabControl.cs @@ -11,6 +11,7 @@ using Avalonia.Data; using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.LogicalTree; +using Avalonia.VisualTree; namespace AtomUI.Controls; @@ -126,7 +127,7 @@ public class CardTabControl : BaseTabControl { base.OnPropertyChanged(change); - if (this.IsAttachedToLogicalTree()) + if (this.IsAttachedToVisualTree()) { if (change.Property == SizeTypeProperty) { @@ -164,20 +165,15 @@ public class CardTabControl : BaseTabControl } } - protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) - { - base.OnAttachedToLogicalTree(e); - SetupSizeTypeBinding(); - this.AddTokenBindingDisposable( - TokenResourceBinder.CreateTokenBinding(this, CardSizeProperty, TabControlTokenKey.CardSize)); - } - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, CardBorderThicknessProperty, SharedTokenKey.BorderThickness, BindingPriority.Template, new RenderScaleAwareThicknessConfigure(this))); + this.AddTokenBindingDisposable( + TokenResourceBinder.CreateTokenBinding(this, CardSizeProperty, TabControlTokenKey.CardSize)); + SetupSizeTypeBinding(); } protected override Size ArrangeOverride(Size finalSize) diff --git a/src/AtomUI.Controls/TabControl/TabControl.cs b/src/AtomUI.Controls/TabControl/TabControl.cs index 3b64bbe74..407a07050 100644 --- a/src/AtomUI.Controls/TabControl/TabControl.cs +++ b/src/AtomUI.Controls/TabControl/TabControl.cs @@ -151,9 +151,9 @@ public class TabControl : BaseTabControl _itemsPresenter = e.NameScope.Find(BaseTabControlTheme.ItemsPresenterPart); } - protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { - base.OnAttachedToLogicalTree(e); + base.OnAttachedToVisualTree(e); this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, SelectedIndicatorThicknessProperty, SharedTokenKey.LineWidthBold)); } diff --git a/src/AtomUI.Controls/TabControl/TabItem.cs b/src/AtomUI.Controls/TabControl/TabItem.cs index 613a16710..3854b20ba 100644 --- a/src/AtomUI.Controls/TabControl/TabItem.cs +++ b/src/AtomUI.Controls/TabControl/TabItem.cs @@ -108,8 +108,6 @@ public class TabItem : AvaloniaTabItem, base.OnApplyTemplate(e); _closeButton = e.NameScope.Find(BaseTabItemTheme.ItemCloseButtonPart); - SetupTransitions(); - if (_closeButton is not null) { _closeButton.Click += HandleCloseRequest; @@ -188,7 +186,7 @@ public class TabItem : AvaloniaTabItem, newIcon.SetTemplatedParent(this); } - if (change.Property == CloseIconProperty) + if (change.Property == CloseIconProperty && CloseIcon is null) { SetupDefaultCloseIcon(); } @@ -200,7 +198,6 @@ public class TabItem : AvaloniaTabItem, _tokenBindingsDisposable = new CompositeDisposable(); SetupShapeThemeBindings(); base.OnAttachedToLogicalTree(e); - SetupDefaultCloseIcon(); } protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) @@ -209,6 +206,13 @@ public class TabItem : AvaloniaTabItem, this.DisposeTokenBindings(); } + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + SetupTransitions(); + SetupDefaultCloseIcon(); + } + private void SetupShapeThemeBindings() { if (Shape == TabSharp.Line) diff --git a/src/AtomUI.Controls/TabControl/TabScrollContentPresenter.cs b/src/AtomUI.Controls/TabControl/TabScrollContentPresenter.cs index 39070a50c..087f97a00 100644 --- a/src/AtomUI.Controls/TabControl/TabScrollContentPresenter.cs +++ b/src/AtomUI.Controls/TabControl/TabScrollContentPresenter.cs @@ -8,9 +8,21 @@ using Avalonia.Rendering; namespace AtomUI.Controls; -internal class TabScrollContentPresenter : ScrollContentPresenter, ICustomHitTest +internal class TabScrollContentPresenter : ScrollContentPresenter, + ICustomHitTest { - internal Dock TabStripPlacement { get; set; } = Dock.Top; + internal static readonly DirectProperty TabStripPlacementProperty = + AvaloniaProperty.RegisterDirect(nameof(TabStripPlacement), + o => o.TabStripPlacement, + (o, v) => o.TabStripPlacement = v); + + private Dock _tabStripPlacement = Dock.Top; + + internal Dock TabStripPlacement + { + get => _tabStripPlacement; + set => SetAndRaise(TabStripPlacementProperty, ref _tabStripPlacement, value); + } private static readonly MethodInfo SnapOffsetMethodInfo;