From 96465de9205dcc6034ec2fa6f8e279be0ce70062 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 6 Dec 2022 15:01:04 +0000 Subject: [PATCH] Revert "remove integration test app." This reverts commit 46ea1871bc6e15205bffce436b433f63804e00d6. --- samples/IntegrationTestApp/App.axaml | 7 + samples/IntegrationTestApp/App.axaml.cs | 24 +++ .../IntegrationTestApp.csproj | 28 ++++ .../IntegrationTestApp/MacOSIntegration.cs | 27 ++++ samples/IntegrationTestApp/MainWindow.axaml | 131 +++++++++++++++ .../IntegrationTestApp/MainWindow.axaml.cs | 153 ++++++++++++++++++ samples/IntegrationTestApp/Program.cs | 22 +++ .../IntegrationTestApp/ShowWindowTest.axaml | 40 +++++ .../ShowWindowTest.axaml.cs | 62 +++++++ samples/IntegrationTestApp/bundle.sh | 5 + samples/IntegrationTestApp/nuget.config | 11 ++ 11 files changed, 510 insertions(+) create mode 100644 samples/IntegrationTestApp/App.axaml create mode 100644 samples/IntegrationTestApp/App.axaml.cs create mode 100644 samples/IntegrationTestApp/IntegrationTestApp.csproj create mode 100644 samples/IntegrationTestApp/MacOSIntegration.cs create mode 100644 samples/IntegrationTestApp/MainWindow.axaml create mode 100644 samples/IntegrationTestApp/MainWindow.axaml.cs create mode 100644 samples/IntegrationTestApp/Program.cs create mode 100644 samples/IntegrationTestApp/ShowWindowTest.axaml create mode 100644 samples/IntegrationTestApp/ShowWindowTest.axaml.cs create mode 100644 samples/IntegrationTestApp/bundle.sh create mode 100644 samples/IntegrationTestApp/nuget.config diff --git a/samples/IntegrationTestApp/App.axaml b/samples/IntegrationTestApp/App.axaml new file mode 100644 index 0000000000..a833e096df --- /dev/null +++ b/samples/IntegrationTestApp/App.axaml @@ -0,0 +1,7 @@ + + + + + diff --git a/samples/IntegrationTestApp/App.axaml.cs b/samples/IntegrationTestApp/App.axaml.cs new file mode 100644 index 0000000000..022931366d --- /dev/null +++ b/samples/IntegrationTestApp/App.axaml.cs @@ -0,0 +1,24 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; + +namespace IntegrationTestApp +{ + public class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow(); + } + + base.OnFrameworkInitializationCompleted(); + } + } +} diff --git a/samples/IntegrationTestApp/IntegrationTestApp.csproj b/samples/IntegrationTestApp/IntegrationTestApp.csproj new file mode 100644 index 0000000000..4284399357 --- /dev/null +++ b/samples/IntegrationTestApp/IntegrationTestApp.csproj @@ -0,0 +1,28 @@ + + + WinExe + net6.0 + enable + + + + IntegrationTestApp + net.avaloniaui.avalonia.integrationtestapp + true + 1.0.0 + + + + + + + + + + + + + + + + diff --git a/samples/IntegrationTestApp/MacOSIntegration.cs b/samples/IntegrationTestApp/MacOSIntegration.cs new file mode 100644 index 0000000000..f700a5b4e2 --- /dev/null +++ b/samples/IntegrationTestApp/MacOSIntegration.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.InteropServices; +using Avalonia.Controls; + +namespace IntegrationTestApp +{ + public static class MacOSIntegration + { + [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "sel_registerName")] + private static extern IntPtr GetHandle(string name); + + [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + private static extern long Int64_objc_msgSend(IntPtr receiver, IntPtr selector); + + private static readonly IntPtr s_orderedIndexSelector; + + static MacOSIntegration() + { + s_orderedIndexSelector = GetHandle("orderedIndex");; + } + + public static long GetOrderedIndex(Window window) + { + return Int64_objc_msgSend(window.PlatformImpl!.Handle.Handle, s_orderedIndexSelector); + } + } +} diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml new file mode 100644 index 0000000000..8031736953 --- /dev/null +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + WindowState: + + + + + + + TextBlockWithName + + TextBlockWithNameAndAutomationId + + Label for TextBox + + Foo + + + + + + + + + + + + + + + + Unchecked + Checked + ThreeState + + + + + + + Item 0 + Item 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + None + + + + + + + + + + + NonOwned + Owned + Modal + + + Manual + CenterScreen + CenterOwner + + + Normal + Minimized + Maximized + FullScreen + + + + + + + + + + + diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs new file mode 100644 index 0000000000..2b160fce96 --- /dev/null +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Avalonia; +using Avalonia.Automation; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.VisualTree; +using Microsoft.CodeAnalysis; + +namespace IntegrationTestApp +{ + public class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + InitializeViewMenu(); + this.AttachDevTools(); + AddHandler(Button.ClickEvent, OnButtonClick); + ListBoxItems = Enumerable.Range(0, 100).Select(x => "Item " + x).ToList(); + DataContext = this; + } + + public List ListBoxItems { get; } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private void InitializeViewMenu() + { + var mainTabs = this.FindControl("MainTabs"); + var viewMenu = (NativeMenuItem)NativeMenu.GetMenu(this).Items[1]; + + foreach (TabItem tabItem in mainTabs.Items) + { + var menuItem = new NativeMenuItem + { + Header = (string)tabItem.Header!, + IsChecked = tabItem.IsSelected, + ToggleType = NativeMenuItemToggleType.Radio, + }; + + menuItem.Click += (s, e) => tabItem.IsSelected = true; + viewMenu.Menu.Items.Add(menuItem); + } + } + + private void ShowWindow() + { + var sizeTextBox = this.GetControl("ShowWindowSize"); + var modeComboBox = this.GetControl("ShowWindowMode"); + var locationComboBox = this.GetControl("ShowWindowLocation"); + var stateComboBox = this.GetControl("ShowWindowState"); + var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null; + var owner = (Window)this.GetVisualRoot()!; + + var window = new ShowWindowTest + { + WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex, + }; + + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime) + { + // Make sure the windows have unique names and AutomationIds. + var existing = lifetime.Windows.OfType().Count(); + if (existing > 0) + { + AutomationProperties.SetAutomationId(window, window.Name + (existing + 1)); + window.Title += $" {existing + 1}"; + } + } + + if (size.HasValue) + { + window.Width = size.Value.Width; + window.Height = size.Value.Height; + } + + sizeTextBox.Text = string.Empty; + window.WindowState = (WindowState)stateComboBox.SelectedIndex; + + switch (modeComboBox.SelectedIndex) + { + case 0: + window.Show(); + break; + case 1: + window.Show(owner); + break; + case 2: + window.ShowDialog(owner); + break; + } + } + + private void SendToBack() + { + var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!; + + foreach (var window in lifetime.Windows) + { + window.Activate(); + } + } + + private void RestoreAll() + { + var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!; + + foreach (var window in lifetime.Windows) + { + window.Show(); + if (window.WindowState == WindowState.Minimized) + window.WindowState = WindowState.Normal; + } + } + + private void MenuClicked(object? sender, RoutedEventArgs e) + { + var clickedMenuItemTextBlock = this.FindControl("ClickedMenuItem"); + clickedMenuItemTextBlock.Text = ((MenuItem)sender!).Header.ToString(); + } + + private void OnButtonClick(object? sender, RoutedEventArgs e) + { + var source = e.Source as Button; + + if (source?.Name == "ComboBoxSelectionClear") + this.FindControl("BasicComboBox").SelectedIndex = -1; + if (source?.Name == "ComboBoxSelectFirst") + this.FindControl("BasicComboBox").SelectedIndex = 0; + if (source?.Name == "ListBoxSelectionClear") + this.FindControl("BasicListBox").SelectedIndex = -1; + if (source?.Name == "MenuClickedMenuItemReset") + this.FindControl("ClickedMenuItem").Text = "None"; + if (source?.Name == "ShowWindow") + ShowWindow(); + if (source?.Name == "SendToBack") + SendToBack(); + if (source?.Name == "EnterFullscreen") + WindowState = WindowState.FullScreen; + if (source?.Name == "ExitFullscreen") + WindowState = WindowState.Normal; + if (source?.Name == "RestoreAll") + RestoreAll(); + } + } +} diff --git a/samples/IntegrationTestApp/Program.cs b/samples/IntegrationTestApp/Program.cs new file mode 100644 index 0000000000..c09b249cfa --- /dev/null +++ b/samples/IntegrationTestApp/Program.cs @@ -0,0 +1,22 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; + +namespace IntegrationTestApp +{ + class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .LogToTrace(); + } +} diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml new file mode 100644 index 0000000000..ae46c92431 --- /dev/null +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + Normal + Minimized + Maximized + FullScreen + + + + + + + + diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs new file mode 100644 index 0000000000..43875dd990 --- /dev/null +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -0,0 +1,62 @@ +using System; +using System.Runtime.InteropServices; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.Threading; + +namespace IntegrationTestApp +{ + public class ShowWindowTest : Window + { + private readonly DispatcherTimer? _timer; + private readonly TextBox? _orderTextBox; + + public ShowWindowTest() + { + InitializeComponent(); + DataContext = this; + PositionChanged += (s, e) => this.GetControl("Position").Text = $"{Position}"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + _orderTextBox = this.GetControl("Order"); + _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(250) }; + _timer.Tick += TimerOnTick; + _timer.Start(); + } + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + var scaling = PlatformImpl!.DesktopScaling; + this.GetControl("Position").Text = $"{Position}"; + this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; + this.GetControl("Scaling").Text = $"{scaling}"; + + if (Owner is not null) + { + var ownerRect = this.GetControl("OwnerRect"); + var owner = (Window)Owner; + ownerRect.Text = $"{owner.Position}, {PixelSize.FromSize(owner.FrameSize!.Value, scaling)}"; + } + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + _timer?.Stop(); + } + + private void TimerOnTick(object? sender, EventArgs e) + { + _orderTextBox!.Text = MacOSIntegration.GetOrderedIndex(this).ToString(); + } + } +} diff --git a/samples/IntegrationTestApp/bundle.sh b/samples/IntegrationTestApp/bundle.sh new file mode 100644 index 0000000000..505991582e --- /dev/null +++ b/samples/IntegrationTestApp/bundle.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +cd $(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +dotnet restore -r osx-arm64 +dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-arm64 -p:_AvaloniaUseExternalMSBuild=false \ No newline at end of file diff --git a/samples/IntegrationTestApp/nuget.config b/samples/IntegrationTestApp/nuget.config new file mode 100644 index 0000000000..6c273ab3d9 --- /dev/null +++ b/samples/IntegrationTestApp/nuget.config @@ -0,0 +1,11 @@ + + + + + + + + +