From 21d378461b914c1df14cfb5722bba54353efca61 Mon Sep 17 00:00:00 2001 From: bcssov Date: Wed, 20 Nov 2024 21:43:29 +0100 Subject: [PATCH] Add non-native title bar pointer over effects --- .../IronyCaptionButtons.cs | 97 +++++++++++++++---- .../ThemeCaptionButton.cs | 13 ++- .../Themes/Dark/IronyCaptionButtons.axaml | 42 +++++--- .../FluentDark/IronyCaptionButtons.axaml | 42 +++++--- .../FluentLight/IronyCaptionButtons.axaml | 42 +++++--- .../Themes/Light/IronyCaptionButtons.axaml | 42 +++++--- .../MaterialDark/IronyCaptionButtons.axaml | 42 +++++--- .../MaterialLight/IronyCaptionButtons.axaml | 42 +++++--- 8 files changed, 252 insertions(+), 110 deletions(-) diff --git a/src/IronyModManager/Controls/ClientSideDecorations/IronyCaptionButtons.cs b/src/IronyModManager/Controls/ClientSideDecorations/IronyCaptionButtons.cs index 86d0f3ee..762ab7f5 100644 --- a/src/IronyModManager/Controls/ClientSideDecorations/IronyCaptionButtons.cs +++ b/src/IronyModManager/Controls/ClientSideDecorations/IronyCaptionButtons.cs @@ -4,13 +4,14 @@ // Created : 11-23-2022 // // Last Modified By : Mario -// Last Modified On : 11-23-2022 +// Last Modified On : 11-20-2024 // *********************************************************************** // // Avalonia // // Taken from avalonia. // *********************************************************************** + using System; using System.Collections.Generic; using System.Linq; @@ -19,6 +20,8 @@ using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; +using Avalonia.Controls.Shapes; +using Avalonia.Media; using Avalonia.Styling; namespace IronyModManager.Controls.ClientSideDecorations @@ -36,10 +39,40 @@ public class IronyCaptionButtons : TemplatedControl, IStyleable { #region Fields + /// + /// The full screen active + /// + private static readonly PathGeometry fullScreenActive = PathGeometry.Parse("M205 1024h819v-819h-205v469l-674 -674l-145 145l674 674h-469v205zM1374 1229h469v-205h-819v819h205v-469l674 674l145 -145z"); + + /// + /// The full screen normal + /// + private static readonly PathGeometry fullScreenNormal = PathGeometry.Parse("M2048 2048v-819h-205v469l-1493 -1493h469v-205h-819v819h205v-469l1493 1493h-469v205h819z"); + + /// + /// The restore screen active + /// + private static readonly PathGeometry restoreScreenActive = PathGeometry.Parse("M2048 410h-410v-410h-1638v1638h410v410h1638v-1638zM1434 1434h-1229v-1229h1229v1229zM1843 1843h-1229v-205h1024v-1024h205v1229z"); + + /// + /// The restore screen normal + /// + private static readonly PathGeometry restoreScreenNormal = PathGeometry.Parse("M2048 2048v-2048h-2048v2048h2048zM1843 1843h-1638v-1638h1638v1638z"); + /// /// The disposables /// - private CompositeDisposable? _disposables; + private CompositeDisposable? disposables; + + /// + /// The full screen button path + /// + private Path? fullScreenButtonPath; + + /// + /// The restore button path + /// + private Path? restoreButtonPath; #endregion Fields @@ -67,20 +100,44 @@ public class IronyCaptionButtons : TemplatedControl, IStyleable /// The host window. public virtual void Attach(Window hostWindow) { - if (_disposables == null) + if (disposables == null) { HostWindow = hostWindow; - _disposables = new CompositeDisposable + disposables = new CompositeDisposable { 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); - }) + .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); + + // Why here? Because I'm tired of dealing with a bug in pseudo classes. + if (fullScreenButtonPath != null && restoreButtonPath != null) + { + // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault + switch (x) + { + case WindowState.FullScreen: + fullScreenButtonPath.Data = fullScreenActive; + fullScreenButtonPath.IsVisible = true; + restoreButtonPath.Data = restoreScreenNormal; + break; + case WindowState.Maximized: + fullScreenButtonPath.Data = fullScreenNormal; + fullScreenButtonPath.IsVisible = false; + restoreButtonPath.Data = restoreScreenActive; + break; + default: + fullScreenButtonPath.Data = fullScreenNormal; + fullScreenButtonPath.IsVisible = true; + restoreButtonPath.Data = restoreScreenNormal; + break; + } + } + }) }; } } @@ -90,10 +147,10 @@ public virtual void Attach(Window hostWindow) /// public virtual void Detach() { - if (_disposables != null) + if (disposables != null) { - _disposables.Dispose(); - _disposables = null; + disposables.Dispose(); + disposables = null; HostWindow = null; } @@ -102,7 +159,7 @@ public virtual void Detach() /// /// Handles the event. /// - /// The instance containing the event data. + /// The instance containing the event data. protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -111,11 +168,13 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) var restoreButton = e.NameScope.Get