mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 23:39:18 +08:00
271 lines
12 KiB
C#
271 lines
12 KiB
C#
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using Avalonia.Controls;
|
|
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace AtomUI.Desktop.Controls.Tests.Window;
|
|
|
|
public class WindowTitleBarLogoVisibilityTests
|
|
{
|
|
static WindowTitleBarLogoVisibilityTests()
|
|
{
|
|
AvaloniaTestApp.EnsureInitialized();
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Visibility_Mode_Defaults_To_Auto()
|
|
{
|
|
var enumSource = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/WindowTitleBar/WindowTitleBarLogoVisibility.cs"));
|
|
var titleBarSource = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/WindowTitleBar/WindowTitleBar.cs"));
|
|
|
|
enumSource.ShouldContain("Auto");
|
|
enumSource.ShouldContain("Always");
|
|
enumSource.ShouldContain("Never");
|
|
titleBarSource.ShouldContain("WindowTitleBarLogoVisibility.Auto");
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Title_Alignment_Exposes_The_Approved_Public_Values()
|
|
{
|
|
var enumSource = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/WindowTitleBar/WindowTitleBarTitleAlignment.cs"));
|
|
|
|
enumSource.ShouldContain("public enum WindowTitleBarTitleAlignment");
|
|
enumSource.ShouldContain("Auto");
|
|
enumSource.ShouldContain("Left");
|
|
enumSource.ShouldContain("Center");
|
|
enumSource.ShouldContain("WindowCenter");
|
|
enumSource.ShouldContain("Right");
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Title_Alignment_Defaults_To_Auto()
|
|
{
|
|
var property = typeof(AtomUI.Desktop.Controls.WindowTitleBar)
|
|
.GetProperty("TitleAlignment", BindingFlags.Instance | BindingFlags.Public);
|
|
var propertyField = typeof(AtomUI.Desktop.Controls.WindowTitleBar)
|
|
.GetField("TitleAlignmentProperty", BindingFlags.Static | BindingFlags.Public);
|
|
|
|
property.ShouldNotBeNull();
|
|
propertyField.ShouldNotBeNull();
|
|
property.PropertyType.ShouldBe(typeof(AtomUI.Desktop.Controls.WindowTitleBarTitleAlignment));
|
|
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar();
|
|
property.GetValue(titleBar).ShouldBe(AtomUI.Desktop.Controls.WindowTitleBarTitleAlignment.Auto);
|
|
}
|
|
|
|
[Fact]
|
|
public void Window_Adds_Owner_And_Projects_Title_Alignment_To_The_Title_Bar()
|
|
{
|
|
var property = typeof(AtomUI.Desktop.Controls.Window)
|
|
.GetProperty("TitleAlignment", BindingFlags.Instance | BindingFlags.Public);
|
|
var propertyField = typeof(AtomUI.Desktop.Controls.Window)
|
|
.GetField("TitleAlignmentProperty", BindingFlags.Static | BindingFlags.Public);
|
|
var source = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Window.cs"));
|
|
|
|
property.ShouldNotBeNull();
|
|
propertyField.ShouldNotBeNull();
|
|
property.PropertyType.ShouldBe(typeof(AtomUI.Desktop.Controls.WindowTitleBarTitleAlignment));
|
|
source.ShouldContain("WindowTitleBar.TitleAlignmentProperty.AddOwner<Window>()");
|
|
source.ShouldContain(
|
|
"titleBar.Bind(WindowTitleBar.TitleAlignmentProperty, this.GetObservable(TitleAlignmentProperty))");
|
|
}
|
|
|
|
[Fact]
|
|
public void Window_Projects_Chrome_Layout_Inputs_To_The_Title_Bar()
|
|
{
|
|
var windowInsetsProperty = typeof(AtomUI.Desktop.Controls.Window)
|
|
.GetField(
|
|
"NativeChromeInsetsProperty",
|
|
BindingFlags.Static | BindingFlags.NonPublic);
|
|
var titleBarInsetsProperty = typeof(AtomUI.Desktop.Controls.WindowTitleBar)
|
|
.GetField(
|
|
"NativeChromeInsetsProperty",
|
|
BindingFlags.Static | BindingFlags.NonPublic);
|
|
var source = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Window.cs"));
|
|
|
|
windowInsetsProperty.ShouldNotBeNull();
|
|
titleBarInsetsProperty.ShouldNotBeNull();
|
|
source.ShouldContain("internal IDisposable CreateTitleBarHostProjection(WindowTitleBar titleBar)");
|
|
source.ShouldContain("lease.Add(titleBar.Bind(");
|
|
source.ShouldContain("WindowTitleBar.NativeChromeInsetsProperty");
|
|
source.ShouldContain("this.GetObservable(NativeChromeInsetsProperty)");
|
|
source.ShouldContain("WindowTitleBar.IsCsdEnabledProperty");
|
|
source.ShouldContain("this.GetObservable(IsCsdEnabledProperty)");
|
|
source.ShouldContain("WindowTitleBar.HostWindowStateProperty");
|
|
source.ShouldContain("this.GetObservable(WindowStateProperty)");
|
|
}
|
|
|
|
[Fact]
|
|
public void MacOS_Uses_The_Existing_Button_Frame_Metric_As_A_Layout_Input_Not_Host_Padding()
|
|
{
|
|
var windowSource = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Window.cs"));
|
|
var windowTheme = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Window/Themes/WindowTheme.axaml"));
|
|
var macButtonsSource = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Window/MacStandardWindowButtons.cs"));
|
|
|
|
windowSource.ShouldContain("GetRecommendedTitleBarContentLeftMargin(effectSpacing)");
|
|
windowSource.ShouldContain("NativeChromeInsets = new Thickness(titleBarOffset, 0, 0, 0)");
|
|
windowSource.ShouldContain("NativeChromeInsets = default;");
|
|
windowSource.ShouldNotContain("TitleBarOffsetMargin");
|
|
windowTheme.ShouldNotContain("TitleBarOffsetMargin");
|
|
macButtonsSource.ShouldNotContain("NativeChromeInsets");
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Auto_Mode_Uses_Title_Content_Platform_And_Fullscreen_State()
|
|
{
|
|
var source = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/WindowTitleBar/WindowTitleBar.cs"));
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar
|
|
{
|
|
Logo = new object()
|
|
};
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.Windows);
|
|
|
|
source.ShouldContain("UpdateEffectiveLogoVisible()");
|
|
source.ShouldContain("WindowTitleBarLogoVisibility.Always => hasLogo");
|
|
source.ShouldContain("WindowTitleBarLogoVisibility.Never => false");
|
|
source.ShouldContain("_ => hasLogo && ShouldShowLogoInAutoMode()");
|
|
source.ShouldContain("HostWindowState != WindowState.FullScreen");
|
|
source.ShouldContain("OsType == OsType.macOS");
|
|
source.ShouldContain("string text => !string.IsNullOrWhiteSpace(text)");
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
|
titleBar.HostWindowState = WindowState.FullScreen;
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeFalse();
|
|
titleBar.HostWindowState = WindowState.Normal;
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Auto_Mode_Hides_Titleless_Logo_On_MacOS()
|
|
{
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar();
|
|
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.macOS);
|
|
titleBar.Logo = new object();
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Auto_Mode_Keeps_Titleless_Logo_On_Non_MacOS_When_Not_Fullscreen()
|
|
{
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar();
|
|
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.Windows);
|
|
titleBar.Logo = new object();
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Always_Mode_Keeps_Titleless_Logo_On_MacOS()
|
|
{
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar();
|
|
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.macOS);
|
|
titleBar.LogoVisibility = AtomUI.Desktop.Controls.WindowTitleBarLogoVisibility.Always;
|
|
titleBar.Logo = new object();
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Logo_Auto_Mode_Recomputes_When_OsType_Changes()
|
|
{
|
|
var titleBar = new AtomUI.Desktop.Controls.WindowTitleBar();
|
|
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.Windows);
|
|
titleBar.Logo = new object();
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
|
|
|
titleBar.SetValue(AtomUI.Desktop.Controls.WindowTitleBar.OsTypeProperty, OsType.macOS);
|
|
|
|
GetIsEffectiveLogoVisible(titleBar).ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Window_Propagates_Logo_Visibility_To_Title_Bar_Without_Clearing_Window_Icon()
|
|
{
|
|
var source = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Window.cs"));
|
|
|
|
source.ShouldContain("WindowTitleBar.LogoVisibilityProperty.AddOwner<Window>()");
|
|
source.ShouldContain("public WindowTitleBarLogoVisibility LogoVisibility");
|
|
source.ShouldContain(
|
|
"titleBar.Bind(WindowTitleBar.LogoVisibilityProperty, this.GetObservable(LogoVisibilityProperty))");
|
|
source.ShouldContain("IsEffectiveFullscreenLogoVisibleProperty");
|
|
source.ShouldContain("UpdateEffectiveFullscreenLogoVisible()");
|
|
source.ShouldContain("_ => hasLogo && HasTitleContent(Title) && IsEffectiveFullscreenTitleVisible");
|
|
// Effective Logo 模式:回退解析只进 EffectiveLogo/EffectiveLogoTemplate 渲染层,
|
|
// 框架不再向 Logo/LogoTemplate/Icon 写入任何默认值
|
|
source.ShouldContain("UpdateEffectiveLogo()");
|
|
source.ShouldContain("ResolveEffectiveLogo");
|
|
source.ShouldContain("EffectiveLogoProperty");
|
|
source.ShouldNotContain("TryApplyWindowIconLogo");
|
|
source.ShouldNotContain("ApplyDefaultLogoIfNeeded");
|
|
source.ShouldNotContain("SetCurrentValue(LogoProperty");
|
|
source.ShouldNotContain("SetCurrentValue(LogoTemplateProperty");
|
|
}
|
|
|
|
[Fact]
|
|
public void Title_Bar_Templates_Bind_Logo_Visibility_To_Effective_State()
|
|
{
|
|
var source = File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/WindowTitleBar/Themes/WindowTitleBarTheme.axaml"));
|
|
|
|
Regex.Matches(source, "IsVisible=\"\\{TemplateBinding IsEffectiveLogoVisible\\}\"")
|
|
.Count
|
|
.ShouldBe(3);
|
|
}
|
|
|
|
[Fact]
|
|
public void Fullscreen_Title_Bar_Templates_Hide_Logo_With_Effective_Fullscreen_State()
|
|
{
|
|
var fullscreenPopoverSource =
|
|
File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Themes/FullscreenPopoverLayerTheme.axaml"));
|
|
var drawnDecorationsSource =
|
|
File.ReadAllText(GetRepoFile("src/AtomUI.Desktop.Controls/Window/Themes/WindowDrawnDecorationsTheme.axaml"));
|
|
|
|
fullscreenPopoverSource.ShouldContain(
|
|
"IsVisible=\"{Binding $parent[atom:Window].IsEffectiveFullscreenLogoVisible}\"");
|
|
drawnDecorationsSource.ShouldContain(
|
|
"IsVisible=\"{Binding $parent[atom:Window].IsEffectiveFullscreenLogoVisible}\"");
|
|
|
|
foreach (var source in new[] { fullscreenPopoverSource, drawnDecorationsSource })
|
|
{
|
|
source.ShouldContain("Content=\"{Binding $parent[atom:Window].EffectiveLogo}\"");
|
|
source.ShouldContain(
|
|
"ContentTemplate=\"{Binding $parent[atom:Window].EffectiveLogoTemplate}\"");
|
|
}
|
|
}
|
|
|
|
private static string GetRepoFile(string relativePath)
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory is not null)
|
|
{
|
|
var candidate = Path.Combine(directory.FullName, relativePath);
|
|
if (File.Exists(candidate))
|
|
{
|
|
return candidate;
|
|
}
|
|
|
|
directory = directory.Parent;
|
|
}
|
|
|
|
throw new FileNotFoundException($"Could not find repository file: {relativePath}");
|
|
}
|
|
|
|
private static bool GetIsEffectiveLogoVisible(AtomUI.Desktop.Controls.WindowTitleBar titleBar)
|
|
{
|
|
var property = typeof(AtomUI.Desktop.Controls.WindowTitleBar)
|
|
.GetProperty("IsEffectiveLogoVisible", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
|
|
property.ShouldNotBeNull();
|
|
return (bool)property.GetValue(titleBar)!;
|
|
}
|
|
}
|