diff --git a/src/Sextant.Avalonia/DependencyResolverMixins.cs b/src/Sextant.Avalonia/DependencyResolverMixins.cs index 67789fa1..d6e7b007 100644 --- a/src/Sextant.Avalonia/DependencyResolverMixins.cs +++ b/src/Sextant.Avalonia/DependencyResolverMixins.cs @@ -4,6 +4,7 @@ // See the LICENSE file in the project root for full license information. using System; + using Splat; namespace Sextant.Avalonia @@ -19,7 +20,7 @@ public static class DependencyResolverMixins /// The dependency resolver. /// The navigation view factory. /// The view type. - /// The dependency resolver. + /// The dependency resolver for builder use. public static IMutableDependencyResolver RegisterNavigationView( this IMutableDependencyResolver dependencyResolver, Func navigationViewFactory) @@ -35,9 +36,9 @@ public static IMutableDependencyResolver RegisterNavigationView( /// /// Resolves navigation view from a dependency resolver. /// - /// - /// - /// The dependency resolver. + /// The dependency resolver. + /// Optional contract. + /// The dependency resolver for builder use. public static IView GetNavigationView( this IReadonlyDependencyResolver dependencyResolver, string? contract = null) => diff --git a/src/Sextant.Avalonia/Navigation.cs b/src/Sextant.Avalonia/Navigation.cs new file mode 100644 index 00000000..d37ff27c --- /dev/null +++ b/src/Sextant.Avalonia/Navigation.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive.Linq; + +using Avalonia.Animation; +using Avalonia.ReactiveUI; + +using DynamicData.Aggregation; +using DynamicData.Binding; + +using ReactiveUI; + +namespace Sextant.Avalonia +{ + /// + /// A view used within navigation in Sextant with Avalonia. + /// + public sealed partial class NavigationView + { + /// + /// This class represents a single navigation layer. + /// + private class Navigation + { + private readonly ObservableCollection _navigationStack = new ObservableCollection(); + private readonly IPageTransition _transition; + + /// + /// Initializes a new instance of the class. + /// + public Navigation() + { + var navigationStackObservable = _navigationStack + .ToObservableChangeSet() + .Publish() + .RefCount(); + + navigationStackObservable + .Select(_ => _navigationStack.LastOrDefault()) + .Subscribe(page => Control.Content = page); + + CountChanged = navigationStackObservable.Count().AsObservable(); + _transition = Control.PageTransition; + } + + /// + /// Gets a value indicating whether the control is visible. + /// + public bool IsVisible => _navigationStack.Count > 1; + + /// + /// Gets a the page count. + /// + public IObservable CountChanged { get; } + + /// + /// Gets the control responsible for rendering the current view. + /// + public TransitioningContentControl Control { get; } = new TransitioningContentControl(); + + /// + /// Toggles the animations. + /// + /// Returns true if we are enabling the animations. + public void ToggleAnimations(bool enable) => Control.PageTransition = enable ? _transition : null; + + /// + /// Adds a to the navigation stack. + /// + /// The view to add to the navigation stack. + /// Defines if we should reset the navigation stack. + public void Push(IViewFor view, bool resetStack = false) + { + if (resetStack) + { + _navigationStack.Clear(); + } + + _navigationStack.Add(view); + } + + /// + /// Removes the last from the navigation stack. + /// + public void Pop() + { + var indexToRemove = _navigationStack.Count - 1; + _navigationStack.RemoveAt(indexToRemove); + } + + /// + /// Removes all pages except the first one from the navigation stack. + /// + public void PopToRoot() + { + var view = _navigationStack[0]; + _navigationStack.Clear(); + _navigationStack.Add(view); + } + } + } +} diff --git a/src/Sextant.Avalonia/NavigationView.cs b/src/Sextant.Avalonia/NavigationView.cs index 108358dc..ce4d0dfe 100644 --- a/src/Sextant.Avalonia/NavigationView.cs +++ b/src/Sextant.Avalonia/NavigationView.cs @@ -4,28 +4,24 @@ // See the LICENSE file in the project root for full license information. using System; -using System.Collections.ObjectModel; using System.Linq; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; + using Avalonia; -using Avalonia.Animation; using Avalonia.Controls; using Avalonia.Media; -using Avalonia.ReactiveUI; using Avalonia.Styling; -using DynamicData.Aggregation; -using DynamicData.Binding; + using ReactiveUI; -using Sextant; namespace Sextant.Avalonia { /// /// The implementation for Avalonia. /// - public sealed class NavigationView : ContentControl, IStyleable, IView + public sealed partial class NavigationView : ContentControl, IStyleable, IView { private readonly Navigation _modalNavigation = new Navigation(); private readonly Navigation _pageNavigation = new Navigation(); @@ -56,7 +52,7 @@ public NavigationView() { _modalNavigation.Control }, - [!Panel.BackgroundProperty] = + [!Panel.BackgroundProperty] = _modalNavigation .CountChanged .Select(count => count > 0 ? new SolidColorBrush(Colors.Transparent) : null) @@ -144,87 +140,5 @@ private IViewFor LocateView(IViewModel viewModel, string? contract) view.ViewModel = viewModel; return view; } - - /// - /// This class represents a single navigation layer. - /// - private class Navigation - { - private readonly ObservableCollection _navigationStack = new ObservableCollection(); - private readonly IPageTransition _transition; - - /// - /// Initializes a new instance of the helper. - /// - public Navigation() - { - var navigationStackObservable = _navigationStack - .ToObservableChangeSet() - .Publish() - .RefCount(); - - navigationStackObservable - .Select(_ => _navigationStack.LastOrDefault()) - .Subscribe(page => Control.Content = page); - - CountChanged = navigationStackObservable.Count().AsObservable(); - _transition = Control.PageTransition; - } - - /// - /// Toggles the animations. - /// - /// Returns true if we are enabling the animations. - public void ToggleAnimations(bool enable) => Control.PageTransition = enable ? _transition : null; - - /// - /// Gets a bool indicating whether the control is visible. - /// - public bool IsVisible => _navigationStack.Count > 1; - - /// - /// Publishes new values when page count changes. - /// - public IObservable CountChanged { get; } - - /// - /// The control responsible for rendering the current view. - /// - public TransitioningContentControl Control { get; } = new TransitioningContentControl(); - - /// - /// Adds a to the navigation stack. - /// - /// The view to add to the navigation stack. - /// Defines if we should reset the navigation stack. - public void Push(IViewFor view, bool resetStack = false) - { - if (resetStack) - { - _navigationStack.Clear(); - } - - _navigationStack.Add(view); - } - - /// - /// Removes the last from the navigation stack. - /// - public void Pop() - { - var indexToRemove = _navigationStack.Count - 1; - _navigationStack.RemoveAt(indexToRemove); - } - - /// - /// Removes all pages except the first one from the navigation stack. - /// - public void PopToRoot() - { - var view = _navigationStack[0]; - _navigationStack.Clear(); - _navigationStack.Add(view); - } - } } } diff --git a/src/Sextant.sln b/src/Sextant.sln index ae3d1c20..e36b06cc 100644 --- a/src/Sextant.sln +++ b/src/Sextant.sln @@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Plugins.Popup", "Se EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Plugins.Popup.Tests", "Sextant.Plugins.Popup.Tests\Sextant.Plugins.Popup.Tests.csproj", "{BD186721-EE51-40B2-A546-91EDDE122998}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sextant.Avalonia", "Sextant.Avalonia\Sextant.Avalonia.csproj", "{A91CDEEB-C4D5-402B-9B42-D91E0151F30E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -68,6 +70,10 @@ Global {BD186721-EE51-40B2-A546-91EDDE122998}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD186721-EE51-40B2-A546-91EDDE122998}.Release|Any CPU.ActiveCfg = Release|Any CPU {BD186721-EE51-40B2-A546-91EDDE122998}.Release|Any CPU.Build.0 = Release|Any CPU + {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/version.json b/version.json index c5bf44d7..087cbbf7 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "version": "2.10", + "version": "2.11", "publicReleaseRefSpec": [ "^refs/heads/main", // we release out of master "^refs/heads/rel/\\d+\\.\\d+\\.\\d+" // we also release branches starting with rel/N.N.N