diff --git a/Directory.Build.props b/Directory.Build.props index 31a7bf2b..c61df258 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,6 +9,7 @@ https://github.com/jinek/Consolonia/graphs/contributors Text User Interface implementation of Avalonia UI (GUI Framework) Copyright Β© Evgeny Gorbovoy 2021 - 2022 + AVA3001 11.0.9 diff --git a/src/.editorconfig b/src/.editorconfig index 45b7f78a..dc887c0f 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -74,6 +74,7 @@ dotnet_diagnostic.ca1043.severity = none # todo: why not to use indexer rather t dotnet_diagnostic.ca1814.severity = none # sometimes we need rectangle array dotnet_diagnostic.ca1058.severity = none # check why new documentation warns not to derive from ApplicationException. The purpose of last is to distinguish system exceptions like OOM, AssemblyLoadException etc from application logic dotnet_diagnostic.ca2000.severity = none # exceptions which are listed in the rule can be applied to any type +dotnet_diagnostic.CA2007.severity = none # we are assuming task continuation thread is fine by default dotnet_diagnostic.ca2213.severity = none # keeping field does not mean necessarity to dispose - it can be dispose somwhere else dotnet_diagnostic.ca2248.severity = none # https://github.com/dotnet/roslyn-analyzers/issues/4432 dotnet_diagnostic.ca1062.severity = none # we are fine with NRE - no need for additional checks diff --git a/src/Consolonia.Core/Consolonia.Core.csproj b/src/Consolonia.Core/Consolonia.Core.csproj index 00b7142a..d059e8af 100644 --- a/src/Consolonia.Core/Consolonia.Core.csproj +++ b/src/Consolonia.Core/Consolonia.Core.csproj @@ -1,15 +1,22 @@ - + + + + + + + + + - \ No newline at end of file diff --git a/src/Consolonia.Themes.TurboVision/Templates/Controls/Dialog/DialogHelpers.cs b/src/Consolonia.Core/Controls/Dialog/DialogHelpers.cs similarity index 98% rename from src/Consolonia.Themes.TurboVision/Templates/Controls/Dialog/DialogHelpers.cs rename to src/Consolonia.Core/Controls/Dialog/DialogHelpers.cs index a7407024..80f6a80c 100644 --- a/src/Consolonia.Themes.TurboVision/Templates/Controls/Dialog/DialogHelpers.cs +++ b/src/Consolonia.Core/Controls/Dialog/DialogHelpers.cs @@ -11,7 +11,7 @@ using Avalonia.VisualTree; using Consolonia.Core.Helpers; -namespace Consolonia.Themes.TurboVision.Templates.Controls.Dialog +namespace Consolonia.Core.Controls.Dialog { public class DialogHost { diff --git a/src/Consolonia.Themes.TurboVision/Templates/Controls/DialogWrap.axaml b/src/Consolonia.Core/Controls/Dialog/DialogWrap.axaml similarity index 90% rename from src/Consolonia.Themes.TurboVision/Templates/Controls/DialogWrap.axaml rename to src/Consolonia.Core/Controls/Dialog/DialogWrap.axaml index 49501ce7..89fcd51e 100644 --- a/src/Consolonia.Themes.TurboVision/Templates/Controls/DialogWrap.axaml +++ b/src/Consolonia.Core/Controls/Dialog/DialogWrap.axaml @@ -1,7 +1,7 @@ + x:Class="Consolonia.Core.Controls.Dialog.DialogWrap"> IsCloseButtonVisibleProperty = AvaloniaProperty.Register(nameof(IsCloseButtonVisible), true); + public static readonly StyledProperty WindowStartupLocationProperty = + AvaloniaProperty.Register(nameof(WindowStartupLocation)); + + public static readonly StyledProperty CanResizeProperty = + AvaloniaProperty.Register(nameof(CanResize), true); + + public static readonly StyledProperty IconProperty = + AvaloniaProperty.Register(nameof(Icon)); + private Size _contentSize; private ContentPresenter _partContentPresenter; - private TaskCompletionSource _taskCompletionSource; + private TaskCompletionSource _taskCompletionSource; + static DialogWindow() { @@ -61,6 +72,43 @@ public bool IsCloseButtonVisible // ReSharper disable once MemberCanBePrivate.Global public bool CancelOnEscape { get; set; } = true; + + /// + /// Enables or disables resizing of the window. + /// + public bool CanResize + { + get => GetValue(CanResizeProperty); + set => SetValue(CanResizeProperty, value); + } + + /// + /// Gets or sets the icon of the window. + /// + public string Icon + { + get => GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + /// + /// Gets or sets the startup location of the window. + /// + public WindowStartupLocation WindowStartupLocation + { + get => GetValue(WindowStartupLocationProperty); + set => SetValue(WindowStartupLocationProperty, value); + } + + /// + /// Gets or sets the window position in screen coordinates. + /// + //public PixelPoint Position + //{ + // get => PlatformImpl?.Position ?? PixelPoint.Origin; + // set => PlatformImpl?.Move(value); + //} + // ReSharper disable once UnusedMember.Global Used by template public void CloseClick() { @@ -83,31 +131,60 @@ protected override Size ArrangeOverride(Size finalSize) return arrangeOverride; } - private void ShowDialogInternal(Visual parent) + protected void ShowDialogInternal(Visual parent) { + if (WindowStartupLocation == WindowStartupLocation.CenterScreen) + { + Width = (ushort)(parent.Bounds.Width * .9); + Height = (ushort)(parent.Bounds.Height * .9); + if (parent is Window window) window.SizeChanged += Window_SizeChanged; + } + DialogHost dialogHost = GetDialogHost(parent); dialogHost.OpenInternal(this); } + private void Window_SizeChanged(object sender, SizeChangedEventArgs e) + { + var window = (Window)sender; + if (WindowStartupLocation == WindowStartupLocation.CenterScreen) + { + Width = (ushort)(window.Bounds.Width * .9); + Height = (ushort)(window.Bounds.Height * .9); + } + } + // ReSharper disable once VirtualMemberNeverOverridden.Global overriden in other packages, why resharper suggests this? - public virtual void CloseDialog() + public virtual void CloseDialog(object result = null) { DialogHost dialogHost = GetDialogHost(this); dialogHost.PopInternal(this); - _taskCompletionSource.SetResult(); + if (Parent is Window window) window.SizeChanged -= Window_SizeChanged; + _taskCompletionSource.SetResult(result); + } + + public async Task ShowDialogAsync(Control parent) + { + if (_taskCompletionSource != null) + throw new InvalidOperationException("Dialog is already shown."); + + _taskCompletionSource = new TaskCompletionSource(); + ShowDialogInternal(parent); + await _taskCompletionSource.Task; } - public Task ShowDialogAsync(Control parent) + public async Task ShowDialogAsync(Control parent) { if (_taskCompletionSource != null) - throw new NotImplementedException(); + throw new InvalidOperationException("Dialog is already shown."); - _taskCompletionSource = new TaskCompletionSource(); + _taskCompletionSource = new TaskCompletionSource(); ShowDialogInternal(parent); - return _taskCompletionSource.Task; + object result = await _taskCompletionSource.Task; + return (T)result; } - private static DialogHost GetDialogHost(Visual parent) + protected static DialogHost GetDialogHost(Visual parent) { var window = parent.FindAncestorOfType(true); DialogHost dialogHost = window!.GetValue(DialogHost.DialogHostProperty); diff --git a/src/Consolonia.Core/Controls/FileOpenPicker.axaml b/src/Consolonia.Core/Controls/FileOpenPicker.axaml new file mode 100644 index 00000000..33fbc7ad --- /dev/null +++ b/src/Consolonia.Core/Controls/FileOpenPicker.axaml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +