Factories and Views
This commit is contained in:
parent
4e7dfc56a8
commit
2529b728ba
16 changed files with 188 additions and 4 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
using InkForge.Common.Controllers;
|
using InkForge.Common.Controllers;
|
||||||
using InkForge.Common.Data;
|
using InkForge.Common.Data;
|
||||||
using InkForge.Common.ViewModels;
|
using InkForge.Common.ViewModels;
|
||||||
|
using InkForge.Common.ViewModels.Landing;
|
||||||
using InkForge.Common.Views;
|
using InkForge.Common.Views;
|
||||||
using InkForge.Data;
|
using InkForge.Data;
|
||||||
|
|
||||||
|
|
@ -16,6 +17,8 @@ public static class InkForgeServiceCollections
|
||||||
|
|
||||||
services.AddDbContextFactory<NoteDbContext, NoteDbContextFactory>();
|
services.AddDbContextFactory<NoteDbContext, NoteDbContextFactory>();
|
||||||
|
|
||||||
|
services.AddSingleton<LandingViewModel>();
|
||||||
|
services.AddSingleton<LandingViewModelFactory>();
|
||||||
services.AddSingleton<WorkspaceController>();
|
services.AddSingleton<WorkspaceController>();
|
||||||
|
|
||||||
services.AddTransient<IViewFor<LandingViewModel>, LandingView>();
|
services.AddTransient<IViewFor<LandingViewModel>, LandingView>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
{
|
||||||
|
public static class TypeFactory<TFactory, T>
|
||||||
|
where TFactory : struct, IObjectParameters<TFactory>
|
||||||
|
{
|
||||||
|
private static ObjectFactory<T>? s_objectFactory;
|
||||||
|
|
||||||
|
public static T Create(in TFactory factory, IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
s_objectFactory ??= ActivatorUtilities.CreateFactory<T>(TFactory.Types);
|
||||||
|
return s_objectFactory(serviceProvider, (object[])factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IObjectParameters<T>
|
||||||
|
where T : struct, IObjectParameters<T>
|
||||||
|
{
|
||||||
|
abstract static Type[] Types { get; }
|
||||||
|
|
||||||
|
abstract static implicit operator object[](in T self);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
app/InkForge.Common/ReactiveUI/RoutableReactiveObject.cs
Normal file
10
app/InkForge.Common/ReactiveUI/RoutableReactiveObject.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ReactiveUI;
|
||||||
|
|
||||||
|
public abstract class RoutableReactiveObject(IScreen screen) : ReactiveObject, IRoutableViewModel
|
||||||
|
{
|
||||||
|
public abstract string? UrlPathSegment { get; }
|
||||||
|
|
||||||
|
public IScreen HostScreen => screen;
|
||||||
|
}
|
||||||
23
app/InkForge.Common/ReactiveUI/ViewModelFactory.cs
Normal file
23
app/InkForge.Common/ReactiveUI/ViewModelFactory.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ReactiveUI;
|
||||||
|
|
||||||
|
public interface IViewModelFactory<T, TCreator>
|
||||||
|
{
|
||||||
|
abstract static ObjectFactory<T> CreateObjectFactory();
|
||||||
|
|
||||||
|
abstract static TCreator GetCreator(ObjectFactory<T> factory, IServiceProvider serviceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewModelFactory<T, TFactory, TCreator>
|
||||||
|
where TFactory : IViewModelFactory<T, TCreator>
|
||||||
|
where TCreator : Delegate
|
||||||
|
{
|
||||||
|
private static ObjectFactory<T>? s_factory;
|
||||||
|
|
||||||
|
public TCreator CreateFactory(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
s_factory ??= TFactory.CreateObjectFactory();
|
||||||
|
return TFactory.GetCreator(s_factory, serviceProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,8 +14,8 @@ public class AppViewModel : ReactiveObject
|
||||||
set => this.RaiseAndSetIfChanged(ref _view, value);
|
set => this.RaiseAndSetIfChanged(ref _view, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppViewModel(WorkspaceController workspace)
|
public AppViewModel(WorkspaceController workspace, LandingViewModel landingViewModel)
|
||||||
{
|
{
|
||||||
View = new LandingViewModel();
|
View = landingViewModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using InkForge.Common.ReactiveUI;
|
||||||
|
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
public class CreateWorkspaceViewModel : LandingViewModelBase
|
||||||
|
{
|
||||||
|
public override string? UrlPathSegment => null;
|
||||||
|
|
||||||
|
public CreateWorkspaceViewModel(LandingViewModel landing) : base(landing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
using InkForge.Common.ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
public abstract class LandingViewModelBase(LandingViewModel landing) : RoutableReactiveObject(landing)
|
||||||
|
{
|
||||||
|
public LandingViewModel Landing => landing;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
public class LandingViewModelFactory(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
public T Create<T>(LandingViewModel landing) where T : LandingViewModelBase
|
||||||
|
{
|
||||||
|
LandingViewModelsObjectParameters objectParameters = new(landing);
|
||||||
|
return TypeFactory<LandingViewModelsObjectParameters, T>.Create(objectParameters, serviceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly record struct LandingViewModelsObjectParameters(
|
||||||
|
LandingViewModel Landing
|
||||||
|
) : IObjectParameters<LandingViewModelsObjectParameters>
|
||||||
|
{
|
||||||
|
public static Type[] Types => [typeof(LandingViewModel)];
|
||||||
|
|
||||||
|
public static implicit operator object[](in LandingViewModelsObjectParameters self) => [self.Landing];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using InkForge.Common.ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
public class OpenRecentViewModel : LandingViewModelBase
|
||||||
|
{
|
||||||
|
public override string? UrlPathSegment => null;
|
||||||
|
|
||||||
|
public OpenRecentViewModel(LandingViewModel landing) : base(landing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,28 @@
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
|
||||||
|
using InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace InkForge.Common.ViewModels;
|
namespace InkForge.Common.ViewModels;
|
||||||
|
|
||||||
public class LandingViewModel : ReactiveObject
|
public class LandingViewModel : ReactiveObject, IScreen
|
||||||
{
|
{
|
||||||
|
private readonly LandingViewModelFactory _factory;
|
||||||
|
|
||||||
|
public RoutingState Router { get; } = new();
|
||||||
|
|
||||||
|
public LandingViewModel(LandingViewModelFactory factory)
|
||||||
|
{
|
||||||
|
_factory = factory;
|
||||||
|
|
||||||
|
Router.CurrentViewModel.Where(x => x is null)
|
||||||
|
.InvokeCommand<IRoutableViewModel>(Router.NavigateAndReset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Navigate<T>() where T : LandingViewModelBase
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
|
|
@ -9,5 +10,9 @@
|
||||||
x:Class="InkForge.Common.Views.LandingView"
|
x:Class="InkForge.Common.Views.LandingView"
|
||||||
x:DataType="ifcvm:LandingViewModel">
|
x:DataType="ifcvm:LandingViewModel">
|
||||||
<Grid RowDefinitions="Auto, *, Auto">
|
<Grid RowDefinitions="Auto, *, Auto">
|
||||||
|
<Label Content="InkForge"
|
||||||
|
Grid.Row="0" />
|
||||||
|
|
||||||
|
<reactiveui:RoutedViewHost Router="{CompiledBinding Router}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:Class="InkForge.Common.Views.LandingViews.CreateWorkspaceView">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
using InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
namespace InkForge.Common.Views.LandingViews;
|
||||||
|
|
||||||
|
public partial class CreateWorkspaceView : ReactiveUserControl<CreateWorkspaceViewModel>
|
||||||
|
{
|
||||||
|
public CreateWorkspaceView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
app/InkForge.Common/Views/LandingViews/OpenRecentView.axaml
Normal file
10
app/InkForge.Common/Views/LandingViews/OpenRecentView.axaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:Class="InkForge.Common.Views.LandingViews.OpenRecentView">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
using InkForge.Common.ViewModels.Landing;
|
||||||
|
|
||||||
|
namespace InkForge.Common.Views.LandingViews;
|
||||||
|
|
||||||
|
public partial class OpenRecentView : ReactiveUserControl<OpenRecentViewModel>
|
||||||
|
{
|
||||||
|
public OpenRecentView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue