From b88ec08b54d279f42c9355679f78098d758ee92b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 21 Jul 2020 16:56:28 -0300 Subject: [PATCH] managed titlebar declared in xaml. --- src/Avalonia.Controls/Chrome/TitleBar.cs | 110 +++++++----------- .../Primitives/ChromeOverlayLayer.cs | 5 + .../Primitives/VisualLayerManager.cs | 34 +++--- src/Avalonia.Controls/Window.cs | 27 +---- src/Avalonia.Themes.Default/Window.xaml | 3 + src/Avalonia.Themes.Fluent/Window.xaml | 3 + 6 files changed, 73 insertions(+), 109 deletions(-) diff --git a/src/Avalonia.Controls/Chrome/TitleBar.cs b/src/Avalonia.Controls/Chrome/TitleBar.cs index 91cbc8b497..8d53c88b00 100644 --- a/src/Avalonia.Controls/Chrome/TitleBar.cs +++ b/src/Avalonia.Controls/Chrome/TitleBar.cs @@ -12,91 +12,34 @@ namespace Avalonia.Controls.Chrome public class TitleBar : TemplatedControl { private CompositeDisposable? _disposables; - private readonly Window? _hostWindow; private CaptionButtons? _captionButtons; - public TitleBar(Window hostWindow) - { - _hostWindow = hostWindow; - } - public TitleBar() { } - public void Attach() - { - if (_disposables == null) - { - if (_hostWindow != null) - { - var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow); - - layer?.Children.Add(this); - - _disposables = new CompositeDisposable - { - _hostWindow.GetObservable(Window.WindowDecorationMarginProperty) - .Subscribe(x => UpdateSize()), - - _hostWindow.GetObservable(Window.ExtendClientAreaTitleBarHeightHintProperty) - .Subscribe(x => UpdateSize()), - - _hostWindow.GetObservable(Window.OffScreenMarginProperty) - .Subscribe(x => UpdateSize()), - - _hostWindow.GetObservable(Window.WindowStateProperty) - .Subscribe(x => - { - PseudoClasses.Set(":minimized", x == WindowState.Minimized); - PseudoClasses.Set(":normal", x == WindowState.Normal); - PseudoClasses.Set(":maximized", x == WindowState.Maximized); - PseudoClasses.Set(":fullscreen", x == WindowState.FullScreen); - }) - }; - - _captionButtons?.Attach(_hostWindow); - } - - UpdateSize(); - } - } - - private void UpdateSize() + private void UpdateSize(Window window) { - if (_hostWindow != null) + if (window != null) { Margin = new Thickness( - _hostWindow.OffScreenMargin.Left, - _hostWindow.OffScreenMargin.Top, - _hostWindow.OffScreenMargin.Right, - _hostWindow.OffScreenMargin.Bottom); + window.OffScreenMargin.Left, + window.OffScreenMargin.Top, + window.OffScreenMargin.Right, + window.OffScreenMargin.Bottom); - if (_hostWindow.WindowState != WindowState.FullScreen) + if (window.WindowState != WindowState.FullScreen) { - Height = _hostWindow.WindowDecorationMargin.Top; + Height = window.WindowDecorationMargin.Top; if (_captionButtons != null) { _captionButtons.Height = Height; } } - } - } - - public void Detach() - { - if (_disposables != null) - { - var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow); - - layer?.Children.Remove(this); - _disposables.Dispose(); - _disposables = null; - - _captionButtons?.Detach(); + IsVisible = window.PlatformImpl.NeedsManagedDecorations; } } @@ -106,12 +49,39 @@ namespace Avalonia.Controls.Chrome _captionButtons = e.NameScope.Get("PART_CaptionButtons"); - if (_hostWindow != null) + if (VisualRoot is Window window) { - _captionButtons.Attach(_hostWindow); - } + _disposables = new CompositeDisposable + { + window.GetObservable(Window.WindowDecorationMarginProperty) + .Subscribe(x => UpdateSize(window)), + + window.GetObservable(Window.ExtendClientAreaTitleBarHeightHintProperty) + .Subscribe(x => UpdateSize(window)), - UpdateSize(); + window.GetObservable(Window.OffScreenMarginProperty) + .Subscribe(x => UpdateSize(window)), + + window.GetObservable(Window.ExtendClientAreaChromeHintsProperty) + .Subscribe(x => UpdateSize(window)), + + window.GetObservable(Window.WindowStateProperty) + .Subscribe(x => + { + PseudoClasses.Set(":minimized", x == WindowState.Minimized); + PseudoClasses.Set(":normal", x == WindowState.Normal); + PseudoClasses.Set(":maximized", x == WindowState.Maximized); + PseudoClasses.Set(":fullscreen", x == WindowState.FullScreen); + }), + + window.GetObservable(Window.IsExtendedIntoWindowDecorationsProperty) + .Subscribe(x => UpdateSize(window)) + }; + + _captionButtons.Attach(window); + + UpdateSize(window); + } } } } diff --git a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs index 7e4c66591e..7171ecc302 100644 --- a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs +++ b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs @@ -24,6 +24,11 @@ namespace Avalonia.Controls.Primitives return null; } + public void Add(Control c) + { + base.Children.Add(c); + } + public bool HitTest(Point point) => Children.HitTestCustom(point); } } diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs index 8247199a84..dc617d32dc 100644 --- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs +++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Avalonia.LogicalTree; +using Avalonia.Metadata; namespace Avalonia.Controls.Primitives { @@ -12,15 +13,8 @@ namespace Avalonia.Controls.Primitives private ILogicalRoot _logicalRoot; private readonly List _layers = new List(); - public static readonly StyledProperty ChromeOverlayLayerProperty = - AvaloniaProperty.Register(nameof(ChromeOverlayLayer)); - - public VisualLayerManager() - { - var chromeOverlayLayer = new ChromeOverlayLayer(); - AddLayer(chromeOverlayLayer, ChromeZIndex); - ChromeOverlayLayer = chromeOverlayLayer; - } + public static readonly StyledProperty ChromeOverlayLayerProperty = + AvaloniaProperty.Register(nameof(ChromeOverlayLayer)); public bool IsPopup { get; set; } @@ -34,11 +28,25 @@ namespace Avalonia.Controls.Primitives return rv; } } - - public Panel ChromeOverlayLayer + + public ChromeOverlayLayer ChromeOverlayLayer { - get => GetValue(ChromeOverlayLayerProperty); - private set => SetValue(ChromeOverlayLayerProperty, value); + get + { + var current = GetValue(ChromeOverlayLayerProperty); + + if (current is null) + { + var chromeOverlayLayer = new ChromeOverlayLayer(); + AddLayer(chromeOverlayLayer, ChromeZIndex); + + SetValue(ChromeOverlayLayerProperty, chromeOverlayLayer); + + current = chromeOverlayLayer; + } + + return current; + } } public OverlayLayer OverlayLayer diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 874c94a974..d8e7f3a387 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -71,12 +71,10 @@ namespace Avalonia.Controls /// public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot { - private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>(); - private TitleBar _managedTitleBar; + private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>(); private bool _isExtendedIntoWindowDecorations; private Thickness _windowDecorationMargin; private Thickness _offScreenMargin; - private bool _templateApplied; /// /// Defines the property. @@ -554,29 +552,6 @@ namespace Avalonia.Controls IsExtendedIntoWindowDecorations = isExtended; WindowDecorationMargin = PlatformImpl.ExtendedMargins; OffScreenMargin = PlatformImpl.OffScreenMargin; - - if (PlatformImpl.NeedsManagedDecorations && _templateApplied) - { - if (_managedTitleBar == null) - { - _managedTitleBar = new TitleBar(this); - _managedTitleBar.Attach(); - } - } - else - { - _managedTitleBar?.Detach(); - _managedTitleBar = null; - } - } - - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) - { - base.OnApplyTemplate(e); - - _templateApplied = true; - - ExtendClientAreaToDecorationsChanged(PlatformImpl.IsClientAreaExtendedToDecorations); } /// diff --git a/src/Avalonia.Themes.Default/Window.xaml b/src/Avalonia.Themes.Default/Window.xaml index 2aa62df01f..1856eec206 100644 --- a/src/Avalonia.Themes.Default/Window.xaml +++ b/src/Avalonia.Themes.Default/Window.xaml @@ -10,6 +10,9 @@ + + + + + +