| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- // Copyright (c) The Avalonia Project. All rights reserved.
- // Licensed under the MIT license. See licence.md file in the project root for full license information.
- using System;
- using System.Reactive.Linq;
- using System.Threading.Tasks;
- using Avalonia.Controls.Platform;
- using Avalonia.Input;
- using Avalonia.Layout;
- using Avalonia.Media;
- using Avalonia.Platform;
- using Avalonia.Styling;
- using System.Collections.Generic;
- using System.Linq;
- using JetBrains.Annotations;
- namespace Avalonia.Controls
- {
- /// <summary>
- /// Determines how a <see cref="Window"/> will size itself to fit its content.
- /// </summary>
- public enum SizeToContent
- {
- /// <summary>
- /// The window will not automatically size itself to fit its content.
- /// </summary>
- Manual,
- /// <summary>
- /// The window will size itself horizontally to fit its content.
- /// </summary>
- Width,
- /// <summary>
- /// The window will size itself vertically to fit its content.
- /// </summary>
- Height,
- /// <summary>
- /// The window will size itself horizontally and vertically to fit its content.
- /// </summary>
- WidthAndHeight,
- }
- /// <summary>
- /// A top-level window.
- /// </summary>
- public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot, INameScope
- {
- private static IList<Window> s_windows = new List<Window>();
- /// <summary>
- /// Retrieves an enumeration of all Windows in the currently running application.
- /// </summary>
- public static IList<Window> OpenWindows => s_windows;
- /// <summary>
- /// Defines the <see cref="SizeToContent"/> property.
- /// </summary>
- public static readonly StyledProperty<SizeToContent> SizeToContentProperty =
- AvaloniaProperty.Register<Window, SizeToContent>(nameof(SizeToContent));
- /// <summary>
- /// Enables of disables system window decorations (title bar, buttons, etc)
- /// </summary>
- public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
- AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
- /// <summary>
- /// Defines the <see cref="Title"/> property.
- /// </summary>
- public static readonly StyledProperty<string> TitleProperty =
- AvaloniaProperty.Register<Window, string>(nameof(Title), "Window");
- /// <summary>
- /// Defines the <see cref="Icon"/> property.
- /// </summary>
- public static readonly StyledProperty<WindowIcon> IconProperty =
- AvaloniaProperty.Register<Window, WindowIcon>(nameof(Icon));
- private readonly NameScope _nameScope = new NameScope();
- private object _dialogResult;
- private readonly Size _maxPlatformClientSize;
- /// <summary>
- /// Initializes static members of the <see cref="Window"/> class.
- /// </summary>
- static Window()
- {
- BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
- TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetTitle((string)e.NewValue));
- HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
- (s, e) => s.PlatformImpl?.SetSystemDecorations((bool) e.NewValue));
- IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="Window"/> class.
- /// </summary>
- public Window()
- : this(PlatformManager.CreateWindow())
- {
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="Window"/> class.
- /// </summary>
- /// <param name="impl">The window implementation.</param>
- public Window(IWindowImpl impl)
- : base(impl)
- {
- _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
- }
- /// <inheritdoc/>
- event EventHandler<NameScopeEventArgs> INameScope.Registered
- {
- add { _nameScope.Registered += value; }
- remove { _nameScope.Registered -= value; }
- }
- /// <inheritdoc/>
- event EventHandler<NameScopeEventArgs> INameScope.Unregistered
- {
- add { _nameScope.Unregistered += value; }
- remove { _nameScope.Unregistered -= value; }
- }
- /// <summary>
- /// Gets the platform-specific window implementation.
- /// </summary>
- [CanBeNull]
- public new IWindowImpl PlatformImpl => (IWindowImpl)base.PlatformImpl;
- /// <summary>
- /// Gets or sets a value indicating how the window will size itself to fit its content.
- /// </summary>
- public SizeToContent SizeToContent
- {
- get { return GetValue(SizeToContentProperty); }
- set { SetValue(SizeToContentProperty, value); }
- }
- /// <summary>
- /// Gets or sets the title of the window.
- /// </summary>
- public string Title
- {
- get { return GetValue(TitleProperty); }
- set { SetValue(TitleProperty, value); }
- }
- /// <summary>
- /// Enables of disables system window decorations (title bar, buttons, etc)
- /// </summary>
- ///
- public bool HasSystemDecorations
- {
- get { return GetValue(HasSystemDecorationsProperty); }
- set { SetValue(HasSystemDecorationsProperty, value); }
- }
- /// <summary>
- /// Gets or sets the minimized/maximized state of the window.
- /// </summary>
- public WindowState WindowState
- {
- get { return PlatformImpl?.WindowState ?? WindowState.Normal; }
- set
- {
- if (PlatformImpl != null)
- PlatformImpl.WindowState = value;
- }
- }
- /// <summary>
- /// Gets or sets the icon of the window.
- /// </summary>
- public WindowIcon Icon
- {
- get { return GetValue(IconProperty); }
- set { SetValue(IconProperty, value); }
- }
- /// <inheritdoc/>
- Size ILayoutRoot.MaxClientSize => _maxPlatformClientSize;
- /// <inheritdoc/>
- Type IStyleable.StyleKey => typeof(Window);
- /// <summary>
- /// Closes the window.
- /// </summary>
- public void Close()
- {
- s_windows.Remove(this);
- PlatformImpl?.Dispose();
- IsVisible = false;
- }
- protected override void HandleApplicationExiting()
- {
- base.HandleApplicationExiting();
- Close();
- }
- /// <summary>
- /// Closes a dialog window with the specified result.
- /// </summary>
- /// <param name="dialogResult">The dialog result.</param>
- /// <remarks>
- /// When the window is shown with the <see cref="ShowDialog{TResult}"/> method, the
- /// resulting task will produce the <see cref="_dialogResult"/> value when the window
- /// is closed.
- /// </remarks>
- public void Close(object dialogResult)
- {
- _dialogResult = dialogResult;
- Close();
- }
- /// <summary>
- /// Hides the window but does not close it.
- /// </summary>
- public override void Hide()
- {
- using (BeginAutoSizing())
- {
- PlatformImpl?.Hide();
- }
- IsVisible = false;
- }
- /// <summary>
- /// Shows the window.
- /// </summary>
- public override void Show()
- {
- s_windows.Add(this);
- EnsureInitialized();
- IsVisible = true;
- LayoutManager.Instance.ExecuteInitialLayoutPass(this);
- using (BeginAutoSizing())
- {
- PlatformImpl?.Show();
- }
- }
- /// <summary>
- /// Shows the window as a dialog.
- /// </summary>
- /// <returns>
- /// A task that can be used to track the lifetime of the dialog.
- /// </returns>
- public Task ShowDialog()
- {
- return ShowDialog<object>();
- }
- /// <summary>
- /// Shows the window as a dialog.
- /// </summary>
- /// <typeparam name="TResult">
- /// The type of the result produced by the dialog.
- /// </typeparam>
- /// <returns>.
- /// A task that can be used to retrive the result of the dialog when it closes.
- /// </returns>
- public Task<TResult> ShowDialog<TResult>()
- {
- s_windows.Add(this);
- EnsureInitialized();
- IsVisible = true;
- LayoutManager.Instance.ExecuteInitialLayoutPass(this);
- using (BeginAutoSizing())
- {
- var affectedWindows = s_windows.Where(w => w.IsEnabled && w != this).ToList();
- var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault();
- SetIsEnabled(affectedWindows, false);
- var modal = PlatformImpl?.ShowDialog();
- var result = new TaskCompletionSource<TResult>();
- Observable.FromEventPattern<EventHandler, EventArgs>(
- x => this.Closed += x,
- x => this.Closed -= x)
- .Take(1)
- .Subscribe(_ =>
- {
- modal?.Dispose();
- SetIsEnabled(affectedWindows, true);
- activated?.Activate();
- result.SetResult((TResult)_dialogResult);
- });
- return result.Task;
- }
- }
- void SetIsEnabled(IEnumerable<Window> windows, bool isEnabled)
- {
- foreach (var window in windows)
- {
- window.IsEnabled = isEnabled;
- }
- }
- /// <inheritdoc/>
- void INameScope.Register(string name, object element)
- {
- _nameScope.Register(name, element);
- }
- /// <inheritdoc/>
- object INameScope.Find(string name)
- {
- return _nameScope.Find(name);
- }
- /// <inheritdoc/>
- void INameScope.Unregister(string name)
- {
- _nameScope.Unregister(name);
- }
- /// <inheritdoc/>
- protected override Size MeasureOverride(Size availableSize)
- {
- var sizeToContent = SizeToContent;
- var size = ClientSize;
- var desired = base.MeasureOverride(availableSize.Constrain(_maxPlatformClientSize));
- switch (sizeToContent)
- {
- case SizeToContent.Width:
- size = new Size(desired.Width, ClientSize.Height);
- break;
- case SizeToContent.Height:
- size = new Size(ClientSize.Width, desired.Height);
- break;
- case SizeToContent.WidthAndHeight:
- size = new Size(desired.Width, desired.Height);
- break;
- case SizeToContent.Manual:
- size = ClientSize;
- break;
- default:
- throw new InvalidOperationException("Invalid value for SizeToContent.");
- }
- return size;
- }
- protected override void HandleClosed()
- {
- IsVisible = false;
- base.HandleClosed();
- }
- /// <inheritdoc/>
- protected override void HandleResized(Size clientSize)
- {
- if (!AutoSizing)
- {
- SizeToContent = SizeToContent.Manual;
- }
- base.HandleResized(clientSize);
- }
- }
- }
- namespace Avalonia
- {
- public static class WindowApplicationExtensions
- {
- public static void RunWithMainWindow<TWindow>(this Application app) where TWindow : Avalonia.Controls.Window, new()
- {
- var window = new TWindow();
- window.Show();
- app.Run(window);
- }
- }
- }
|