TitleBarWindow.axaml.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Shapes;
  4. using Avalonia.Markup.Xaml;
  5. using Avalonia.Media;
  6. using Avalonia.VisualTree;
  7. using System;
  8. using System.Runtime.InteropServices;
  9. using System.Threading.Tasks;
  10. /*
  11. MIT License
  12. Original work Copyright (c) 2020 Fichtelcoder
  13. Modified work Copyright 2022 Veloe Aetess
  14. Permission is hereby granted, free of charge, to any person obtaining a copy
  15. of this software and associated documentation files (the "Software"), to deal
  16. in the Software without restriction, including without limitation the rights
  17. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. copies of the Software, and to permit persons to whom the Software is
  19. furnished to do so, subject to the following conditions:
  20. The above copyright notice and this permission notice shall be included in all
  21. copies or substantial portions of the Software.
  22. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. SOFTWARE.
  29. */
  30. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
  31. namespace VeloeMinecraftLauncher.Views.TitleBar
  32. {
  33. public partial class TitleBarWindow : UserControl
  34. {
  35. private Button minimizeButton;
  36. private Button maximizeButton;
  37. private Path maximizeIcon;
  38. private ToolTip maximizeToolTip;
  39. private Button closeButton;
  40. private Image windowIcon;
  41. private DockPanel titleBar;
  42. private DockPanel titleBarBackground;
  43. private TextBlock systemChromeTitle;
  44. private NativeMenuBar seamlessMenuBar;
  45. private NativeMenuBar defaultMenuBar;
  46. public static readonly StyledProperty<bool> IsSeamlessProperty =
  47. AvaloniaProperty.Register<TitleBarWindow, bool>(nameof(IsSeamless));
  48. public static readonly StyledProperty<bool> IsIconVisibleProperty =
  49. AvaloniaProperty.Register<TitleBarWindow, bool>(nameof(IsIconVisible));
  50. public static readonly StyledProperty<bool> IsMaximizeVisibleProperty =
  51. AvaloniaProperty.Register<TitleBarWindow, bool>(nameof(IsMaximizeVisible));
  52. public static readonly StyledProperty<string> TitleProperty =
  53. AvaloniaProperty.Register<TitleBarWindow, string>(nameof(TitleText));
  54. public bool IsSeamless
  55. {
  56. get { return GetValue(IsSeamlessProperty); }
  57. set
  58. {
  59. SetValue(IsSeamlessProperty, value);
  60. if (titleBarBackground != null &&
  61. systemChromeTitle != null &&
  62. seamlessMenuBar != null &&
  63. defaultMenuBar != null)
  64. {
  65. titleBarBackground.IsVisible = IsSeamless ? false : true;
  66. systemChromeTitle.IsVisible = IsSeamless ? false : true;
  67. seamlessMenuBar.IsVisible = IsSeamless ? true : false;
  68. defaultMenuBar.IsVisible = IsSeamless ? false : true;
  69. if (IsSeamless == false)
  70. {
  71. //titleBar.Resources["SystemControlForegroundBaseHighBrush"] = new SolidColorBrush { Color = new Color(255, 0, 0, 0) };
  72. }
  73. }
  74. }
  75. }
  76. public bool IsIconVisible
  77. {
  78. get { return GetValue(IsIconVisibleProperty); }
  79. set
  80. {
  81. SetValue(IsIconVisibleProperty, value);
  82. if (windowIcon != null
  83. )
  84. {
  85. windowIcon.IsVisible = IsIconVisible ? true : false;
  86. //systemChromeTitle.IsVisible = IsIconVisible ? true : false;
  87. }
  88. }
  89. }
  90. public bool IsMaximizeVisible
  91. {
  92. get { return GetValue(IsIconVisibleProperty); }
  93. set
  94. {
  95. SetValue(IsIconVisibleProperty, value);
  96. if (maximizeButton != null &&
  97. maximizeIcon != null &&
  98. maximizeToolTip != null)
  99. {
  100. maximizeButton.IsVisible = IsIconVisible ? true : false;
  101. maximizeIcon.IsVisible = IsIconVisible ? true : false;
  102. maximizeToolTip.IsVisible = IsIconVisible ? true : false;
  103. }
  104. }
  105. }
  106. public string TitleText
  107. {
  108. get
  109. {
  110. if (systemChromeTitle != null)
  111. return systemChromeTitle.Text;
  112. return "";
  113. }
  114. set
  115. {
  116. if (systemChromeTitle != null)
  117. systemChromeTitle.Text = value;
  118. }
  119. }
  120. public TitleBarWindow()
  121. {
  122. this.InitializeComponent();
  123. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) == false)
  124. {
  125. this.IsVisible = false;
  126. }
  127. else
  128. {
  129. minimizeButton = this.FindControl<Button>("MinimizeButton");
  130. maximizeButton = this.FindControl<Button>("MaximizeButton");
  131. maximizeIcon = this.FindControl<Path>("MaximizeIcon");
  132. maximizeToolTip = this.FindControl<ToolTip>("MaximizeToolTip");
  133. closeButton = this.FindControl<Button>("CloseButton");
  134. windowIcon = this.FindControl<Image>("WindowIcon");
  135. minimizeButton.Click += MinimizeWindow;
  136. maximizeButton.Click += MaximizeWindow;
  137. closeButton.Click += CloseWindow;
  138. windowIcon.DoubleTapped += CloseWindow;
  139. titleBar = this.FindControl<DockPanel>("TitleBar");
  140. titleBarBackground = this.FindControl<DockPanel>("TitleBarBackground");
  141. systemChromeTitle = this.FindControl<TextBlock>("SystemChromeTitle");
  142. seamlessMenuBar = this.FindControl<NativeMenuBar>("SeamlessMenuBar");
  143. defaultMenuBar = this.FindControl<NativeMenuBar>("DefaultMenuBar");
  144. SubscribeToWindowState();
  145. }
  146. }
  147. private void CloseWindow(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
  148. {
  149. (this.GetVisualRoot() as Window)?.Close();
  150. }
  151. private void MaximizeWindow(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
  152. {
  153. Window? hostWindow = this.GetVisualRoot() as Window;
  154. if (hostWindow is null) return;
  155. if (hostWindow.WindowState == WindowState.Normal)
  156. {
  157. hostWindow.WindowState = WindowState.Maximized;
  158. }
  159. else
  160. {
  161. hostWindow.WindowState = WindowState.Normal;
  162. }
  163. }
  164. private void MinimizeWindow(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
  165. {
  166. Window? hostWindow = this.GetVisualRoot() as Window;
  167. if (hostWindow is null) return;
  168. hostWindow.WindowState = WindowState.Minimized;
  169. }
  170. private async void SubscribeToWindowState()
  171. {
  172. Window? hostWindow = this.GetVisualRoot() as Window;
  173. while (hostWindow == null)
  174. {
  175. hostWindow = this.GetVisualRoot() as Window;
  176. await Task.Delay(50);
  177. }
  178. hostWindow.GetObservable(Window.WindowStateProperty).Subscribe(s =>
  179. {
  180. if (s != WindowState.Maximized)
  181. {
  182. maximizeIcon.Data = Geometry.Parse("M2048 2048v-2048h-2048v2048h2048zM1843 1843h-1638v-1638h1638v1638z");
  183. hostWindow.Padding = new Thickness(0, 0, 0, 0);
  184. maximizeToolTip.Content = "Maximize";
  185. }
  186. if (s == WindowState.Maximized)
  187. {
  188. maximizeIcon.Data = Geometry.Parse("M2048 1638h-410v410h-1638v-1638h410v-410h1638v1638zm-614-1024h-1229v1229h1229v-1229zm409-409h-1229v205h1024v1024h205v-1229z");
  189. hostWindow.Padding = new Thickness(7, 7, 7, 7);
  190. maximizeToolTip.Content = "Restore Down";
  191. // This should be a more universal approach in both cases, but I found it to be less reliable, when for example double-clicking the title bar.
  192. /*hostWindow.Padding = new Thickness(
  193. hostWindow.OffScreenMargin.Left,
  194. hostWindow.OffScreenMargin.Top,
  195. hostWindow.OffScreenMargin.Right,
  196. hostWindow.OffScreenMargin.Bottom);*/
  197. }
  198. });
  199. }
  200. private void InitializeComponent()
  201. {
  202. AvaloniaXamlLoader.Load(this);
  203. }
  204. }
  205. }
  206. #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.