MainWindow.axaml.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using Avalonia;
  4. using Avalonia.Automation;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.ApplicationLifetimes;
  7. using Avalonia.Controls.Primitives;
  8. using Avalonia.Controls.Primitives.PopupPositioning;
  9. using Avalonia.Input;
  10. using Avalonia.Interactivity;
  11. using Avalonia.Media;
  12. using Avalonia.Platform;
  13. using Avalonia.VisualTree;
  14. namespace IntegrationTestApp
  15. {
  16. public partial class MainWindow : Window
  17. {
  18. public MainWindow()
  19. {
  20. // Set name in code behind, so source generator will ignore it.
  21. Name = "MainWindow";
  22. InitializeComponent();
  23. InitializeViewMenu();
  24. InitializeGesturesTab();
  25. this.AttachDevTools();
  26. AppOverlayPopups.Text = Program.OverlayPopups ? "Overlay Popups" : "Native Popups";
  27. AddHandler(Button.ClickEvent, OnButtonClick);
  28. ListBoxItems = Enumerable.Range(0, 100).Select(x => "Item " + x).ToList();
  29. DataContext = this;
  30. }
  31. public List<string> ListBoxItems { get; }
  32. private void InitializeViewMenu()
  33. {
  34. var viewMenu = (NativeMenuItem?)NativeMenu.GetMenu(this)?.Items[1];
  35. foreach (var tabItem in MainTabs.Items.Cast<TabItem>())
  36. {
  37. var menuItem = new NativeMenuItem
  38. {
  39. Header = (string?)tabItem.Header,
  40. ToolTip = $"Tip:{(string?)tabItem.Header}",
  41. IsChecked = tabItem.IsSelected,
  42. ToggleType = NativeMenuItemToggleType.Radio,
  43. };
  44. menuItem.Click += (_, _) => tabItem.IsSelected = true;
  45. viewMenu?.Menu?.Items.Add(menuItem);
  46. }
  47. }
  48. private void OnShowWindow()
  49. {
  50. var sizeTextBox = ShowWindowSize;
  51. var modeComboBox = ShowWindowMode;
  52. var locationComboBox = ShowWindowLocation;
  53. var stateComboBox = ShowWindowState;
  54. var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
  55. var systemDecorations = ShowWindowSystemDecorations;
  56. var extendClientArea = ShowWindowExtendClientAreaToDecorationsHint;
  57. var canResizeCheckBox = ShowWindowCanResize;
  58. var owner = (Window)this.GetVisualRoot()!;
  59. var window = new ShowWindowTest
  60. {
  61. WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex,
  62. CanResize = canResizeCheckBox.IsChecked ?? false,
  63. };
  64. if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
  65. {
  66. // Make sure the windows have unique names and AutomationIds.
  67. var existing = lifetime.Windows.OfType<ShowWindowTest>().Count();
  68. if (existing > 0)
  69. {
  70. AutomationProperties.SetAutomationId(window, window.Name + (existing + 1));
  71. window.Title += $" {existing + 1}";
  72. }
  73. }
  74. if (size.HasValue)
  75. {
  76. window.Width = size.Value.Width;
  77. window.Height = size.Value.Height;
  78. }
  79. sizeTextBox.Text = string.Empty;
  80. window.ExtendClientAreaToDecorationsHint = extendClientArea.IsChecked ?? false;
  81. window.SystemDecorations = (SystemDecorations)systemDecorations.SelectedIndex;
  82. window.WindowState = (WindowState)stateComboBox.SelectedIndex;
  83. switch (modeComboBox.SelectedIndex)
  84. {
  85. case 0:
  86. window.Show();
  87. break;
  88. case 1:
  89. window.Show(owner);
  90. break;
  91. case 2:
  92. window.ShowDialog(owner);
  93. break;
  94. }
  95. }
  96. private void OnShowTransparentWindow()
  97. {
  98. // Show a background window to make sure the color behind the transparent window is
  99. // a known color (green).
  100. var backgroundWindow = new Window
  101. {
  102. Title = "Transparent Window Background",
  103. Name = "TransparentWindowBackground",
  104. Width = 300,
  105. Height = 300,
  106. Background = Brushes.Green,
  107. WindowStartupLocation = WindowStartupLocation.CenterOwner,
  108. };
  109. // This is the transparent window with a red circle.
  110. var window = new Window
  111. {
  112. Title = "Transparent Window",
  113. Name = "TransparentWindow",
  114. SystemDecorations = SystemDecorations.None,
  115. Background = Brushes.Transparent,
  116. TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent },
  117. WindowStartupLocation = WindowStartupLocation.CenterOwner,
  118. Width = 200,
  119. Height = 200,
  120. Content = new Border
  121. {
  122. Background = Brushes.Red,
  123. CornerRadius = new CornerRadius(100),
  124. }
  125. };
  126. window.PointerPressed += (_, _) =>
  127. {
  128. window.Close();
  129. backgroundWindow.Close();
  130. };
  131. backgroundWindow.Show(this);
  132. window.Show(backgroundWindow);
  133. }
  134. private void OnShowTransparentPopup()
  135. {
  136. var popup = new Popup
  137. {
  138. WindowManagerAddShadowHint = false,
  139. Placement = PlacementMode.AnchorAndGravity,
  140. PlacementAnchor = PopupAnchor.Top,
  141. PlacementGravity = PopupGravity.Bottom,
  142. Width= 200,
  143. Height= 200,
  144. Child = new Border
  145. {
  146. Background = Brushes.Red,
  147. CornerRadius = new CornerRadius(100),
  148. }
  149. };
  150. // Show a background window to make sure the color behind the transparent window is
  151. // a known color (green).
  152. var backgroundWindow = new Window
  153. {
  154. Title = "Transparent Popup Background",
  155. Name = "TransparentPopupBackground",
  156. Width = 200,
  157. Height = 200,
  158. Background = Brushes.Green,
  159. WindowStartupLocation = WindowStartupLocation.CenterOwner,
  160. Content = new Border
  161. {
  162. Name = "PopupContainer",
  163. Child = popup,
  164. [AutomationProperties.AccessibilityViewProperty] = AccessibilityView.Content,
  165. }
  166. };
  167. backgroundWindow.PointerPressed += (_, _) => backgroundWindow.Close();
  168. backgroundWindow.Show(this);
  169. popup.Open();
  170. }
  171. private void OnSendToBack()
  172. {
  173. var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!;
  174. foreach (var window in lifetime.Windows.ToArray())
  175. {
  176. window.Activate();
  177. }
  178. }
  179. private void OnRestoreAll()
  180. {
  181. var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!;
  182. foreach (var window in lifetime.Windows.ToArray())
  183. {
  184. window.Show();
  185. if (window.WindowState == WindowState.Minimized)
  186. window.WindowState = WindowState.Normal;
  187. }
  188. }
  189. private void OnShowTopmostWindow()
  190. {
  191. var mainWindow = new TopmostWindowTest("OwnerWindow") { Topmost = true, Title = "Owner Window"};
  192. var ownedWindow = new TopmostWindowTest("OwnedWindow") { WindowStartupLocation = WindowStartupLocation.CenterOwner, Title = "Owned Window"};
  193. mainWindow.Show();
  194. ownedWindow.Show(mainWindow);
  195. }
  196. private void InitializeGesturesTab()
  197. {
  198. var gestureBorder = GestureBorder;
  199. var gestureBorder2 = GestureBorder2;
  200. var lastGesture = LastGesture;
  201. var resetGestures = ResetGestures;
  202. gestureBorder.Tapped += (_, _) => lastGesture.Text = "Tapped";
  203. gestureBorder.DoubleTapped += (_, _) =>
  204. {
  205. lastGesture.Text = "DoubleTapped";
  206. // Testing #8733
  207. gestureBorder.IsVisible = false;
  208. gestureBorder2.IsVisible = true;
  209. };
  210. gestureBorder2.DoubleTapped += (_, _) =>
  211. {
  212. lastGesture.Text = "DoubleTapped2";
  213. };
  214. Gestures.AddRightTappedHandler(gestureBorder, (_, _) => lastGesture.Text = "RightTapped");
  215. resetGestures.Click += (_, _) =>
  216. {
  217. lastGesture.Text = string.Empty;
  218. gestureBorder.IsVisible = true;
  219. gestureBorder2.IsVisible = false;
  220. };
  221. }
  222. private void MenuClicked(object? sender, RoutedEventArgs e)
  223. {
  224. var clickedMenuItemTextBlock = ClickedMenuItem;
  225. clickedMenuItemTextBlock.Text = (sender as MenuItem)?.Header?.ToString();
  226. }
  227. private void OnButtonClick(object? sender, RoutedEventArgs e)
  228. {
  229. var source = e.Source as Button;
  230. if (source?.Name == nameof(ComboBoxSelectionClear))
  231. BasicComboBox.SelectedIndex = -1;
  232. if (source?.Name == nameof(ComboBoxSelectFirst))
  233. BasicComboBox.SelectedIndex = 0;
  234. if (source?.Name == nameof(ListBoxSelectionClear))
  235. BasicListBox.SelectedIndex = -1;
  236. if (source?.Name == nameof(MenuClickedMenuItemReset))
  237. ClickedMenuItem.Text = "None";
  238. if (source?.Name == nameof(ResetSliders))
  239. HorizontalSlider.Value = 50;
  240. if (source?.Name == nameof(ShowTransparentWindow))
  241. OnShowTransparentWindow();
  242. if (source?.Name == nameof(ShowTransparentPopup))
  243. OnShowTransparentPopup();
  244. if (source?.Name == nameof(ShowWindow))
  245. OnShowWindow();
  246. if (source?.Name == nameof(SendToBack))
  247. OnSendToBack();
  248. if (source?.Name == nameof(EnterFullscreen))
  249. WindowState = WindowState.FullScreen;
  250. if (source?.Name == nameof(ExitFullscreen))
  251. WindowState = WindowState.Normal;
  252. if (source?.Name == nameof(ShowTopmostWindow))
  253. OnShowTopmostWindow();
  254. if (source?.Name == nameof(RestoreAll))
  255. OnRestoreAll();
  256. if (source?.Name == nameof(ApplyWindowDecorations))
  257. OnApplyWindowDecorations(this);
  258. if (source?.Name == nameof(ShowNewWindowDecorations))
  259. OnShowNewWindowDecorations();
  260. }
  261. private void OnApplyWindowDecorations(Window window)
  262. {
  263. window.ExtendClientAreaToDecorationsHint = WindowExtendClientAreaToDecorationsHint.IsChecked!.Value;
  264. window.ExtendClientAreaTitleBarHeightHint =
  265. int.TryParse(WindowTitleBarHeightHint.Text, out var val) ? val / DesktopScaling : -1;
  266. window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome
  267. | (WindowForceSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.SystemChrome : 0)
  268. | (WindowPreferSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.PreferSystemChrome : 0)
  269. | (WindowMacThickSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.OSXThickTitleBar : 0);
  270. AdjustOffsets(window);
  271. window.Background = Brushes.Transparent;
  272. window.PropertyChanged += WindowOnPropertyChanged;
  273. void WindowOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
  274. {
  275. var window = (Window)sender!;
  276. if (e.Property == OffScreenMarginProperty || e.Property == WindowDecorationMarginProperty)
  277. {
  278. AdjustOffsets(window);
  279. }
  280. }
  281. void AdjustOffsets(Window window)
  282. {
  283. window.Padding = window.OffScreenMargin;
  284. ((Control)window.Content!).Margin = window.WindowDecorationMargin;
  285. WindowDecorationProperties.Text =
  286. $"{window.OffScreenMargin.Top * DesktopScaling} {window.WindowDecorationMargin.Top * DesktopScaling} {window.IsExtendedIntoWindowDecorations}";
  287. }
  288. }
  289. private void OnShowNewWindowDecorations()
  290. {
  291. var window = new ShowWindowTest();
  292. OnApplyWindowDecorations(window);
  293. window.Show();
  294. }
  295. }
  296. }