Merge pull request #273 from irihitech/window
Ursa Window: The Window utilizing custom title bar.
This commit is contained in:
75
src/Ursa/Controls/TitleBar/CaptionButtons.cs
Normal file
75
src/Ursa/Controls/TitleBar/CaptionButtons.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Irihi.Avalonia.Shared.Reactive;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_CloseButton, typeof (Button))]
|
||||
[TemplatePart(PART_RestoreButton, typeof (Button))]
|
||||
[TemplatePart(PART_MinimizeButton, typeof (Button))]
|
||||
[TemplatePart(PART_FullScreenButton, typeof (Button))]
|
||||
[PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
|
||||
public class CaptionButtons: Avalonia.Controls.Chrome.CaptionButtons
|
||||
{
|
||||
private const string PART_CloseButton = "PART_CloseButton";
|
||||
private const string PART_RestoreButton = "PART_RestoreButton";
|
||||
private const string PART_MinimizeButton = "PART_MinimizeButton";
|
||||
private const string PART_FullScreenButton = "PART_FullScreenButton";
|
||||
|
||||
private Button? _closeButton;
|
||||
private Button? _restoreButton;
|
||||
private Button? _minimizeButton;
|
||||
private Button? _fullScreenButton;
|
||||
|
||||
private IDisposable? _visibilityDisposable;
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
_closeButton = e.NameScope.Get<Button>(PART_CloseButton);
|
||||
_restoreButton = e.NameScope.Get<Button>(PART_RestoreButton);
|
||||
_minimizeButton = e.NameScope.Get<Button>(PART_MinimizeButton);
|
||||
_fullScreenButton = e.NameScope.Get<Button>(PART_FullScreenButton);
|
||||
Button.ClickEvent.AddHandler((o, args) => OnClose(), _closeButton);
|
||||
Button.ClickEvent.AddHandler((o, args) => OnRestore(), _restoreButton);
|
||||
Button.ClickEvent.AddHandler((o, args) => OnMinimize(), _minimizeButton);
|
||||
Button.ClickEvent.AddHandler((o, args) => OnToggleFullScreen(), _fullScreenButton);
|
||||
if (this.HostWindow is not null && !HostWindow.CanResize)
|
||||
{
|
||||
_restoreButton.IsEnabled = false;
|
||||
}
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
public override void Attach(Window hostWindow)
|
||||
{
|
||||
base.Attach(hostWindow);
|
||||
_visibilityDisposable = HostWindow?.GetObservable(Window.WindowStateProperty).Subscribe((a) =>
|
||||
{
|
||||
UpdateVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateVisibility()
|
||||
{
|
||||
if (HostWindow is not UrsaWindow u)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsVisibleProperty.SetValue(u.IsCloseButtonVisible, _closeButton);
|
||||
IsVisibleProperty.SetValue(u.WindowState != WindowState.FullScreen && u.IsRestoreButtonVisible,
|
||||
_restoreButton);
|
||||
IsVisibleProperty.SetValue(u.WindowState != WindowState.FullScreen && u.IsMinimizeButtonVisible,
|
||||
_minimizeButton);
|
||||
IsVisibleProperty.SetValue(u.IsFullScreenButtonVisible, _fullScreenButton);
|
||||
}
|
||||
|
||||
public override void Detach()
|
||||
{
|
||||
base.Detach();
|
||||
_visibilityDisposable?.Dispose();
|
||||
}
|
||||
}
|
||||
94
src/Ursa/Controls/TitleBar/TitleBar.cs
Normal file
94
src/Ursa/Controls/TitleBar/TitleBar.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Platform;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class TitleBar: ContentControl
|
||||
{
|
||||
private CaptionButtons? _captionButtons;
|
||||
private InputElement? _background;
|
||||
private Window? _visualRoot;
|
||||
|
||||
public static readonly StyledProperty<object?> LeftContentProperty = AvaloniaProperty.Register<TitleBar, object?>(
|
||||
nameof(LeftContent));
|
||||
|
||||
public object? LeftContent
|
||||
{
|
||||
get => GetValue(LeftContentProperty);
|
||||
set => SetValue(LeftContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> RightContentProperty = AvaloniaProperty.Register<TitleBar, object?>(
|
||||
nameof(RightContent));
|
||||
|
||||
public object? RightContent
|
||||
{
|
||||
get => GetValue(RightContentProperty);
|
||||
set => SetValue(RightContentProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
this._captionButtons?.Detach();
|
||||
this._captionButtons = e.NameScope.Get<CaptionButtons>("PART_CaptionButtons");
|
||||
this._background = e.NameScope.Get<InputElement>("PART_Background");
|
||||
if (!(this.VisualRoot is Window visualRoot))
|
||||
return;
|
||||
_visualRoot = visualRoot;
|
||||
DoubleTappedEvent.AddHandler(OnDoubleTapped, _background);
|
||||
PointerPressedEvent.AddHandler(OnPointerPressed, _background);
|
||||
this._captionButtons?.Attach(visualRoot);
|
||||
// this.UpdateSize(visualRoot);
|
||||
}
|
||||
|
||||
private void OnPointerPressed(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
if (e.ClickCount < 2)
|
||||
{
|
||||
_visualRoot?.BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDoubleTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (_visualRoot is not null)
|
||||
{
|
||||
if (_visualRoot.WindowState == WindowState.Maximized)
|
||||
{
|
||||
_visualRoot.WindowState = WindowState.Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
_visualRoot.WindowState = WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSize(Window window)
|
||||
{
|
||||
Thickness offScreenMargin = window.OffScreenMargin;
|
||||
var left = offScreenMargin.Left;
|
||||
offScreenMargin = window.OffScreenMargin;
|
||||
double top = offScreenMargin.Top;
|
||||
offScreenMargin = window.OffScreenMargin;
|
||||
double right = offScreenMargin.Right;
|
||||
offScreenMargin = window.OffScreenMargin;
|
||||
double bottom = offScreenMargin.Bottom;
|
||||
this.Margin = new Thickness(left, top, right, bottom);
|
||||
if (window.WindowState != WindowState.FullScreen)
|
||||
{
|
||||
this.Height = window.WindowDecorationMargin.Top;
|
||||
if (this._captionButtons != null)
|
||||
this._captionButtons.Height = this.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user