Batch Update
This commit is contained in:
parent
693d12b61c
commit
4c2b5cca93
32 changed files with 483 additions and 332 deletions
|
|
@ -2,35 +2,29 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
||||||
<AvaloniaVersion>11.0.9</AvaloniaVersion>
|
|
||||||
<DotNetVersion>8.0.2</DotNetVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Avalonia" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.Labs.Controls" Version="11.0.3" />
|
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.Labs.Panels" Version="11.0.3" />
|
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.0.10" />
|
||||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Dock.Avalonia" Version="11.0.0.6" />
|
||||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)" />
|
<PackageVersion Include="Dock.Model.ReactiveUI" Version="11.0.0.6" />
|
||||||
<PackageVersion Include="Avalonia.Themes.Simple" Version="11.0.9" />
|
|
||||||
<PackageVersion Include="Dock.Avalonia" Version="11.0.0.5" />
|
|
||||||
<PackageVersion Include="Dock.Model.ReactiveUI" Version="11.0.0.5" />
|
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="8.0.0" />
|
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="8.0.0" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="$(DotNetVersion)" />
|
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.1" />
|
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.1" />
|
||||||
<PackageVersion Include="ReactiveUI" Version="19.5.41" />
|
|
||||||
<PackageVersion Include="SmartFormat" Version="3.3.2" />
|
<PackageVersion Include="SmartFormat" Version="3.3.2" />
|
||||||
<PackageVersion Include="Splat.Microsoft.Extensions.DependencyInjection" Version="14.8.12" />
|
<PackageVersion Include="Splat.Microsoft.Extensions.DependencyInjection" Version="14.8.12" />
|
||||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Metadata;
|
|
||||||
|
|
||||||
using InkForge.Desktop.Views;
|
using DynamicData;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
|
|
@ -16,15 +17,34 @@ namespace InkForge.Desktop;
|
||||||
|
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
public static readonly StyledProperty<IDataTemplate> AppDataTemplateProperty
|
||||||
|
= AvaloniaProperty.Register<App, IDataTemplate>(
|
||||||
|
name: nameof(AppDataTemplate),
|
||||||
|
coerce: OnAppDataTemplateChanged);
|
||||||
public static readonly StyledProperty<IServiceProvider> ServiceProviderProperty
|
public static readonly StyledProperty<IServiceProvider> ServiceProviderProperty
|
||||||
= AvaloniaProperty.Register<App, IServiceProvider>(
|
= AvaloniaProperty.Register<App, IServiceProvider>(
|
||||||
name: nameof(ServiceProvider),
|
name: nameof(ServiceProvider),
|
||||||
coerce: OnServiceProviderChanged);
|
coerce: OnServiceProviderChanged);
|
||||||
|
|
||||||
|
public IDataTemplate AppDataTemplate => GetValue(AppDataTemplateProperty);
|
||||||
|
|
||||||
public IServiceProvider ServiceProvider => GetValue(ServiceProviderProperty);
|
public IServiceProvider ServiceProvider => GetValue(ServiceProviderProperty);
|
||||||
|
|
||||||
public static void Configure(IServiceCollection services)
|
public static void Configure(IServiceCollection services, ConfigurationManager configuration)
|
||||||
{
|
{
|
||||||
|
configuration.SetBasePath(AppContext.BaseDirectory);
|
||||||
|
configuration.AddJsonFile(
|
||||||
|
new ManifestEmbeddedFileProvider(typeof(App).Assembly),
|
||||||
|
"Properties/appsettings.json", false, false);
|
||||||
|
configuration.AddJsonFile(
|
||||||
|
Path.Combine(
|
||||||
|
Environment.GetFolderPath(
|
||||||
|
Environment.SpecialFolder.ApplicationData,
|
||||||
|
Environment.SpecialFolderOption.DoNotVerify),
|
||||||
|
"InkForge",
|
||||||
|
"usersettings.json"), true, true);
|
||||||
|
configuration.AddJsonFile("appsettings.json", true, true);
|
||||||
|
|
||||||
services.UseMicrosoftDependencyResolver();
|
services.UseMicrosoftDependencyResolver();
|
||||||
Locator.CurrentMutable.InitializeSplat();
|
Locator.CurrentMutable.InitializeSplat();
|
||||||
Locator.CurrentMutable.InitializeReactiveUI();
|
Locator.CurrentMutable.InitializeReactiveUI();
|
||||||
|
|
@ -37,18 +57,34 @@ public partial class App : Application
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnFrameworkInitializationCompleted()
|
private static IDataTemplate OnAppDataTemplateChanged(AvaloniaObject @object, IDataTemplate dataTemplate)
|
||||||
{
|
{
|
||||||
_ = ApplicationLifetime switch
|
var host = (IDataTemplateHost)@object;
|
||||||
|
var original = @object.GetValue(AppDataTemplateProperty);
|
||||||
|
|
||||||
|
if (original is null && dataTemplate is not null)
|
||||||
{
|
{
|
||||||
IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow = new MainWindow(),
|
host.DataTemplates.Add(dataTemplate);
|
||||||
_ => throw new NotSupportedException(),
|
}
|
||||||
};
|
else if (original is not null)
|
||||||
|
{
|
||||||
|
if (dataTemplate is null)
|
||||||
|
{
|
||||||
|
host.DataTemplates.Remove(original);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
host.DataTemplates.ReplaceOrAdd(original, dataTemplate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataTemplate!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IServiceProvider OnServiceProviderChanged(AvaloniaObject @object, IServiceProvider provider)
|
private static IServiceProvider OnServiceProviderChanged(AvaloniaObject @object, IServiceProvider provider)
|
||||||
{
|
{
|
||||||
provider.UseMicrosoftDependencyResolver();
|
provider.UseMicrosoftDependencyResolver();
|
||||||
|
@object.SetValue(AppDataTemplateProperty, provider.GetRequiredService<IDataTemplate>());
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
44
app/InkForge.Desktop/AppViewLocator.cs
Normal file
44
app/InkForge.Desktop/AppViewLocator.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
|
||||||
|
using InkForge.Desktop.ViewModels;
|
||||||
|
using InkForge.Desktop.ViewModels.Documents;
|
||||||
|
using InkForge.Desktop.ViewModels.Workspaces;
|
||||||
|
using InkForge.Desktop.Views.Documents;
|
||||||
|
using InkForge.Desktop.Views.Workspaces;
|
||||||
|
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop;
|
||||||
|
|
||||||
|
public class AppViewLocator : IDataTemplate
|
||||||
|
{
|
||||||
|
public Control? Build(object? param)
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8509 // The switch expression does not handle all possible values of its input type (it is not exhaustive).
|
||||||
|
return param switch
|
||||||
|
#pragma warning restore CS8509 // The switch expression does not handle all possible values of its input type (it is not exhaustive).
|
||||||
|
{
|
||||||
|
ViewModels.Tools.WorkspaceTool viewModel => _(new Views.Tools.WorkspaceTool(), viewModel),
|
||||||
|
WelcomePageDocumentViewModel viewModel => _(new WelcomePageDocument(), viewModel),
|
||||||
|
WorkspaceViewModel viewModel => _(new WorkspaceView(), viewModel),
|
||||||
|
};
|
||||||
|
|
||||||
|
static TView _<TView, TViewModel>(TView view, TViewModel viewModel)
|
||||||
|
where TViewModel : class
|
||||||
|
where TView : IViewFor<TViewModel>
|
||||||
|
{
|
||||||
|
view.ViewModel = viewModel;
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(object? data)
|
||||||
|
{
|
||||||
|
return data is
|
||||||
|
RecentItemViewModel or
|
||||||
|
ViewModels.Tools.WorkspaceTool or
|
||||||
|
WelcomePageDocumentViewModel or
|
||||||
|
WorkspaceViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
using Dock.Model.Controls;
|
|
||||||
using Dock.Model.Core;
|
|
||||||
using Dock.Model.ReactiveUI;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.Dock;
|
|
||||||
|
|
||||||
public class WorkspaceFactory : Factory
|
|
||||||
{
|
|
||||||
public override IRootDock CreateLayout()
|
|
||||||
{
|
|
||||||
var documents = CreateDocumentDock();
|
|
||||||
documents.Id = "Documents";
|
|
||||||
documents.Title = "Documents";
|
|
||||||
|
|
||||||
var root = CreateRootDock();
|
|
||||||
|
|
||||||
root.VisibleDockables = [documents];
|
|
||||||
root.ActiveDockable = documents;
|
|
||||||
root.DefaultDockable = documents;
|
|
||||||
|
|
||||||
DockableLocator = new Dictionary<string, Func<IDockable?>>
|
|
||||||
{
|
|
||||||
["Root"] = () => root,
|
|
||||||
["Documents"] = () => documents,
|
|
||||||
};
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
90
app/InkForge.Desktop/InkForgeFactory.cs
Normal file
90
app/InkForge.Desktop/InkForgeFactory.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
using Dock.Model.ReactiveUI;
|
||||||
|
using Dock.Model.Controls;
|
||||||
|
using Dock.Model.Core;
|
||||||
|
using Dock.Model.ReactiveUI.Controls;
|
||||||
|
using Dock.Avalonia.Controls;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Avalonia;
|
||||||
|
using InkForge.Desktop.ViewModels;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop;
|
||||||
|
|
||||||
|
public class InkForgeFactory : Factory
|
||||||
|
{
|
||||||
|
private readonly IDocumentDock _documentDock;
|
||||||
|
private readonly IRootDock _rootDock;
|
||||||
|
private readonly ViewModels.Tools.WorkspaceTool _workspaceTool;
|
||||||
|
|
||||||
|
public InkForgeFactory()
|
||||||
|
{
|
||||||
|
_rootDock = new RootDock
|
||||||
|
{
|
||||||
|
IsCollapsable = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
_documentDock = new InkForgeDocumentDock
|
||||||
|
{
|
||||||
|
Id = "Documents",
|
||||||
|
Title = "Documents",
|
||||||
|
CanCreateDocument = false,
|
||||||
|
IsCollapsable = false,
|
||||||
|
Proportion = double.NaN,
|
||||||
|
};
|
||||||
|
|
||||||
|
_workspaceTool = CreateWorkspaceTool();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IRootDock CreateLayout()
|
||||||
|
{
|
||||||
|
ProportionalDock workspaceLayout = new()
|
||||||
|
{
|
||||||
|
Proportion = 0.3,
|
||||||
|
VisibleDockables = [_workspaceTool],
|
||||||
|
};
|
||||||
|
|
||||||
|
ProportionalDock windowLayoutContent = new()
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
IsCollapsable = false,
|
||||||
|
VisibleDockables = [workspaceLayout, new ProportionalDockSplitter(), _documentDock]
|
||||||
|
};
|
||||||
|
|
||||||
|
RootDock windowLayout = new()
|
||||||
|
{
|
||||||
|
Title = "Default",
|
||||||
|
IsCollapsable = false,
|
||||||
|
VisibleDockables = [windowLayoutContent],
|
||||||
|
ActiveDockable = windowLayoutContent,
|
||||||
|
};
|
||||||
|
|
||||||
|
_rootDock.VisibleDockables = [windowLayout];
|
||||||
|
_rootDock.ActiveDockable = windowLayout;
|
||||||
|
_rootDock.DefaultDockable = windowLayout;
|
||||||
|
|
||||||
|
return _rootDock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void InitLayout(IDockable layout)
|
||||||
|
{
|
||||||
|
DockableLocator = new Dictionary<string, Func<IDockable?>>
|
||||||
|
{
|
||||||
|
["Root"] = () => _rootDock,
|
||||||
|
["Documents"] = () => _documentDock,
|
||||||
|
["Workspace"] = () => _workspaceTool,
|
||||||
|
};
|
||||||
|
|
||||||
|
HostWindowLocator = new Dictionary<string, Func<IHostWindow?>>
|
||||||
|
{
|
||||||
|
[nameof(IDockWindow)] = () => new HostWindow()
|
||||||
|
};
|
||||||
|
|
||||||
|
base.InitLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ViewModels.Tools.WorkspaceTool CreateWorkspaceTool()
|
||||||
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance<ViewModels.Tools.WorkspaceTool>(
|
||||||
|
Application.Current!.GetValue(App.ServiceProviderProperty)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,48 @@
|
||||||
|
using Avalonia;
|
||||||
|
|
||||||
|
using Dock.Model.Core;
|
||||||
|
|
||||||
|
using InkForge.Desktop.Models;
|
||||||
|
using InkForge.Desktop.ViewModels.Documents;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace InkForge.Desktop.Managers;
|
namespace InkForge.Desktop.Managers;
|
||||||
|
|
||||||
public class DocumentManager
|
public class DocumentManager
|
||||||
{
|
{
|
||||||
|
private readonly IDock _documents;
|
||||||
|
private readonly InkForgeFactory _factory;
|
||||||
|
private readonly WelcomePageDocumentViewModel _welcomePage;
|
||||||
private readonly WorkspaceManager _workspaceManager;
|
private readonly WorkspaceManager _workspaceManager;
|
||||||
|
|
||||||
public DocumentManager(WorkspaceManager workspaceManager)
|
public DocumentManager(WorkspaceManager workspaceManager, InkForgeFactory factory)
|
||||||
{
|
{
|
||||||
_workspaceManager = workspaceManager;
|
_workspaceManager = workspaceManager;
|
||||||
|
_factory = factory;
|
||||||
|
_documents = factory.GetDockable<IDock>("Documents")!;
|
||||||
|
_welcomePage = CreateWelcomePageDocumentViewModel();
|
||||||
|
workspaceManager.WhenAnyValue(v => v.Workspace).Subscribe(OnWorkspaceChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWorkspaceChanged(Workspace? workspace)
|
||||||
|
{
|
||||||
|
if (workspace is null)
|
||||||
|
{
|
||||||
|
_factory.AddDockable(_documents, _welcomePage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_factory.RemoveDockable(_welcomePage, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WelcomePageDocumentViewModel CreateWelcomePageDocumentViewModel()
|
||||||
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance<WelcomePageDocumentViewModel>(
|
||||||
|
Application.Current!.GetValue(App.ServiceProviderProperty)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,14 @@ public class WorkspaceManager(IServiceProvider serviceProvider) : ReactiveObject
|
||||||
private set => this.RaiseAndSetIfChanged(ref _workspace, value);
|
private set => this.RaiseAndSetIfChanged(ref _workspace, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task CloseWorkspace()
|
public ValueTask CloseWorkspace()
|
||||||
{
|
{
|
||||||
_workspace?.Dispose();
|
_workspace?.Dispose();
|
||||||
Workspace = null;
|
Workspace = null;
|
||||||
return Task.CompletedTask;
|
return ValueTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OpenWorkspace(string path, bool createFile = false)
|
public async ValueTask OpenWorkspace(string path, bool createFile = false)
|
||||||
{
|
{
|
||||||
await CloseWorkspace().ConfigureAwait(false);
|
await CloseWorkspace().ConfigureAwait(false);
|
||||||
if (await CreateLocalWorkspace(path, createFile).ConfigureAwait(false) is { } workspace)
|
if (await CreateLocalWorkspace(path, createFile).ConfigureAwait(false) is { } workspace)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
|
||||||
|
using Dock.Model.Core;
|
||||||
|
|
||||||
using InkForge.Data;
|
using InkForge.Data;
|
||||||
|
using InkForge.Desktop;
|
||||||
using InkForge.Desktop.Data;
|
using InkForge.Desktop.Data;
|
||||||
using InkForge.Desktop.Data.Options;
|
using InkForge.Desktop.Data.Options;
|
||||||
using InkForge.Desktop.Dock;
|
|
||||||
using InkForge.Desktop.Managers;
|
using InkForge.Desktop.Managers;
|
||||||
using InkForge.Desktop.Models;
|
using InkForge.Desktop.Models;
|
||||||
using InkForge.Desktop.ViewModels;
|
using InkForge.Desktop.ViewModels.Workspaces;
|
||||||
|
using InkForge.Desktop.ViewModels.Workspaces.Internal;
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
using Splat;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection;
|
namespace Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
public static class InkForgeServiceCollections
|
public static class InkForgeServiceCollections
|
||||||
|
|
@ -23,9 +24,12 @@ public static class InkForgeServiceCollections
|
||||||
// Singletons
|
// Singletons
|
||||||
// - Concrete
|
// - Concrete
|
||||||
services.AddSingleton<DocumentManager>();
|
services.AddSingleton<DocumentManager>();
|
||||||
services.AddSingleton<WorkspaceFactory>();
|
services.AddSingleton<InkForgeFactory>();
|
||||||
services.AddSingleton<WorkspaceManager>();
|
services.AddSingleton<WorkspaceManager>();
|
||||||
services.AddSingleton<WorkspacesViewModel>();
|
|
||||||
|
// - Service
|
||||||
|
services.AddSingleton<IDataTemplate, AppViewLocator>();
|
||||||
|
services.AddSingleton<IWorkspaceViewModelFactory, WorkspaceViewModelFactory>();
|
||||||
|
|
||||||
// Scoped
|
// Scoped
|
||||||
// - Concrete
|
// - Concrete
|
||||||
|
|
@ -38,8 +42,6 @@ public static class InkForgeServiceCollections
|
||||||
// - Forwarders
|
// - Forwarders
|
||||||
services.AddScoped(s => s.GetRequiredService<IWorkspaceContext>().Workspace!);
|
services.AddScoped(s => s.GetRequiredService<IWorkspaceContext>().Workspace!);
|
||||||
|
|
||||||
Locator.CurrentMutable.RegisterViewsForViewModels(typeof(InkForgeServiceCollections).Assembly);
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
|
||||||
{
|
|
||||||
public static class TypeFactory
|
|
||||||
{
|
|
||||||
public static T Create<T>(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
return TypeFactory<EmptyArguments, T>.Create(serviceProvider, default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeFactory<TArguments, T>
|
|
||||||
where TArguments : IFactoryArguments<TArguments>
|
|
||||||
{
|
|
||||||
private static ObjectFactory<T>? s_objectFactory;
|
|
||||||
|
|
||||||
public static T Create(IServiceProvider serviceProvider, in TArguments factory)
|
|
||||||
{
|
|
||||||
s_objectFactory ??= ActivatorUtilities.CreateFactory<T>(TArguments.Types);
|
|
||||||
return s_objectFactory(serviceProvider, (object[])factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly struct EmptyArguments : IFactoryArguments<EmptyArguments>
|
|
||||||
{
|
|
||||||
public static Type[] Types => [];
|
|
||||||
|
|
||||||
public static implicit operator object[](in EmptyArguments _) => [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFactoryArguments<T>
|
|
||||||
where T : IFactoryArguments<T>
|
|
||||||
{
|
|
||||||
abstract static Type[] Types { get; }
|
|
||||||
|
|
||||||
abstract static implicit operator object[](in T self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,11 +28,6 @@ public sealed class Workspace : IDisposable
|
||||||
// {
|
// {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public T CreateViewModel<T>()
|
|
||||||
{
|
|
||||||
return TypeFactory.Create<T>(Services);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(disposing: true);
|
Dispose(disposing: true);
|
||||||
|
|
@ -43,8 +38,12 @@ public sealed class Workspace : IDisposable
|
||||||
{
|
{
|
||||||
if (!_disposedValue)
|
if (!_disposedValue)
|
||||||
{
|
{
|
||||||
_scope!.Dispose();
|
if (_scope is { })
|
||||||
_scope = null;
|
{
|
||||||
|
_scope.Dispose();
|
||||||
|
_scope = null;
|
||||||
|
}
|
||||||
|
|
||||||
_disposedValue = true;
|
_disposedValue = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Metadata;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
using InkForge.Desktop;
|
using InkForge.Desktop;
|
||||||
using InkForge.Desktop.ViewModels;
|
using InkForge.Desktop.Views;
|
||||||
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
[STAThread]
|
[STAThread]
|
||||||
|
|
@ -41,6 +37,11 @@ static class Program
|
||||||
var serviceProvider = services.BuildServiceProvider();
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
app.SetValue(App.ServiceProviderProperty, serviceProvider);
|
app.SetValue(App.ServiceProviderProperty, serviceProvider);
|
||||||
_ = new ServiceProviderDisposer(serviceProvider, dispatcher);
|
_ = new ServiceProviderDisposer(serviceProvider, dispatcher);
|
||||||
|
_ = app.ApplicationLifetime switch
|
||||||
|
{
|
||||||
|
IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow = new MainWindow(),
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AppBuilder UseMicrosoftDependencyInjection(this AppBuilder builder, out ConfigurationManager configuration)
|
private static AppBuilder UseMicrosoftDependencyInjection(this AppBuilder builder, out ConfigurationManager configuration)
|
||||||
|
|
@ -48,7 +49,7 @@ static class Program
|
||||||
configuration = new();
|
configuration = new();
|
||||||
ServiceCollection services = [];
|
ServiceCollection services = [];
|
||||||
services.AddSingleton<IConfiguration>(configuration);
|
services.AddSingleton<IConfiguration>(configuration);
|
||||||
App.Configure(services);
|
App.Configure(services, configuration);
|
||||||
|
|
||||||
builder.AfterSetup(services.SetupApp);
|
builder.AfterSetup(services.SetupApp);
|
||||||
return builder;
|
return builder;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.ReactiveUI;
|
|
||||||
|
|
||||||
public abstract class RoutableReactiveObject(IScreen screen) : ReactiveObject, IRoutableViewModel
|
|
||||||
{
|
|
||||||
public abstract string? UrlPathSegment { get; }
|
|
||||||
|
|
||||||
public IScreen HostScreen => screen;
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,6 +21,7 @@ public class WelcomePageDocumentViewModel : Document
|
||||||
|
|
||||||
public WelcomePageDocumentViewModel(WorkspaceManager workspaceController)
|
public WelcomePageDocumentViewModel(WorkspaceManager workspaceController)
|
||||||
{
|
{
|
||||||
|
CanClose = false;
|
||||||
Title = "Welcome";
|
Title = "Welcome";
|
||||||
|
|
||||||
_workspaceController = workspaceController;
|
_workspaceController = workspaceController;
|
||||||
|
|
@ -33,7 +34,7 @@ public class WelcomePageDocumentViewModel : Document
|
||||||
var storageProvider = this.GetStorageProvider()!;
|
var storageProvider = this.GetStorageProvider()!;
|
||||||
|
|
||||||
var documents = await storageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
|
var documents = await storageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
|
||||||
var file = await storageProvider.SaveFilePickerAsync(new FilePickerSaveOptions()
|
var file = await storageProvider.SaveFilePickerAsync(new()
|
||||||
{
|
{
|
||||||
DefaultExtension = ".ifdb",
|
DefaultExtension = ".ifdb",
|
||||||
FileTypeChoices =
|
FileTypeChoices =
|
||||||
|
|
@ -60,7 +61,7 @@ public class WelcomePageDocumentViewModel : Document
|
||||||
var storageProvider = this.GetStorageProvider()!;
|
var storageProvider = this.GetStorageProvider()!;
|
||||||
|
|
||||||
var documents = await storageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
|
var documents = await storageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
|
||||||
var files = await storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
|
var files = await storageProvider.OpenFilePickerAsync(new()
|
||||||
{
|
{
|
||||||
AllowMultiple = false,
|
AllowMultiple = false,
|
||||||
SuggestedStartLocation = documents,
|
SuggestedStartLocation = documents,
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
using Dock.Model.Controls;
|
|
||||||
|
|
||||||
using InkForge.Desktop.Dock;
|
|
||||||
using InkForge.Desktop.Managers;
|
|
||||||
using InkForge.Desktop.ViewModels.Documents;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.ViewModels;
|
|
||||||
|
|
||||||
public class DocumentsViewModel
|
|
||||||
{
|
|
||||||
private readonly WorkspaceFactory _workspaceFactory;
|
|
||||||
|
|
||||||
public IRootDock Layout { get; }
|
|
||||||
|
|
||||||
public DocumentsViewModel(WorkspaceFactory workspaceFactory, WorkspaceManager workspaceManager)
|
|
||||||
{
|
|
||||||
_workspaceFactory = workspaceFactory;
|
|
||||||
|
|
||||||
Layout = workspaceFactory.CreateLayout();
|
|
||||||
var documents = workspaceFactory.GetDockable<IDocumentDock>("Documents")!;
|
|
||||||
workspaceFactory.AddDockable(documents, new WelcomePageDocumentViewModel(workspaceManager));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
app/InkForge.Desktop/ViewModels/InkForgeDocumentDock.cs
Normal file
13
app/InkForge.Desktop/ViewModels/InkForgeDocumentDock.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Dock.Model.Core;
|
||||||
|
using Dock.Model.ReactiveUI.Controls;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop.ViewModels;
|
||||||
|
|
||||||
|
public class InkForgeDocumentDock : DocumentDock, IDock
|
||||||
|
{
|
||||||
|
bool IDock.IsEmpty
|
||||||
|
{
|
||||||
|
get => false;
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
}
|
||||||
32
app/InkForge.Desktop/ViewModels/MainViewModel.cs
Normal file
32
app/InkForge.Desktop/ViewModels/MainViewModel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
using Avalonia;
|
||||||
|
|
||||||
|
using Dock.Model.Core;
|
||||||
|
|
||||||
|
using InkForge.Desktop.Managers;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop.ViewModels;
|
||||||
|
|
||||||
|
public class MainViewModel : ReactiveObject
|
||||||
|
{
|
||||||
|
private readonly DocumentManager _documentManager;
|
||||||
|
public IDock Layout { get; }
|
||||||
|
|
||||||
|
public MainViewModel(InkForgeFactory factory)
|
||||||
|
{
|
||||||
|
Layout = factory.CreateLayout();
|
||||||
|
factory.InitLayout(Layout);
|
||||||
|
|
||||||
|
_documentManager = CreateDocumentManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DocumentManager CreateDocumentManager()
|
||||||
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance<DocumentManager>(
|
||||||
|
Application.Current!.GetValue(App.ServiceProviderProperty)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
app/InkForge.Desktop/ViewModels/Tools/WorkspaceTool.cs
Normal file
32
app/InkForge.Desktop/ViewModels/Tools/WorkspaceTool.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
using Dock.Model.ReactiveUI.Controls;
|
||||||
|
|
||||||
|
using InkForge.Desktop.Managers;
|
||||||
|
using InkForge.Desktop.ViewModels.Workspaces;
|
||||||
|
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop.ViewModels.Tools;
|
||||||
|
|
||||||
|
public class WorkspaceTool : Tool
|
||||||
|
{
|
||||||
|
private WorkspaceViewModel? _workspace;
|
||||||
|
|
||||||
|
public WorkspaceViewModel? Workspace
|
||||||
|
{
|
||||||
|
get => _workspace;
|
||||||
|
private set => this.RaiseAndSetIfChanged(ref _workspace, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkspaceTool(WorkspaceManager workspaceManager, IWorkspaceViewModelFactory workspaceViewModelFactory)
|
||||||
|
{
|
||||||
|
Title = "Workspace";
|
||||||
|
CanClose = false;
|
||||||
|
|
||||||
|
workspaceManager.WhenAnyValue(v => v.Workspace,
|
||||||
|
v => v switch
|
||||||
|
{
|
||||||
|
{ } => workspaceViewModelFactory.Create(v),
|
||||||
|
_ => null
|
||||||
|
}).BindTo(this, v => v.Workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,50 @@
|
||||||
using InkForge.Desktop.Models;
|
using InkForge.Desktop.Models;
|
||||||
|
|
||||||
namespace InkForge.Desktop.ViewModels.Workspaces;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
public class WorkspaceViewModel(Workspace workspace)
|
namespace InkForge.Desktop.ViewModels.Workspaces
|
||||||
{
|
{
|
||||||
// private readonly Workspace _workspace;
|
public class WorkspaceViewModel(Workspace workspace)
|
||||||
// private readonly ObservableAsPropertyHelper<string> _workspaceNameProperty;
|
{
|
||||||
|
// private readonly Workspace _workspace;
|
||||||
|
// private readonly ObservableAsPropertyHelper<string> _workspaceNameProperty;
|
||||||
|
|
||||||
// public string WorkspaceName => _workspaceNameProperty.Value;
|
// public string WorkspaceName => _workspaceNameProperty.Value;
|
||||||
|
|
||||||
// public ReactiveCommand<Unit, Unit> AddDocument { get; }
|
// public ReactiveCommand<Unit, Unit> AddDocument { get; }
|
||||||
|
|
||||||
// public WorkspacesViewModel(Workspace workspace)
|
// public WorkspacesViewModel(Workspace workspace)
|
||||||
// {
|
// {
|
||||||
// _workspace = workspace;
|
// _workspace = workspace;
|
||||||
// _workspaceNameProperty = this.WhenAnyValue(v => v._workspace.Name).ToProperty(this, nameof(WorkspaceName));
|
// _workspaceNameProperty = this.WhenAnyValue(v => v._workspace.Name).ToProperty(this, nameof(WorkspaceName));
|
||||||
|
|
||||||
// AddDocument = ReactiveCommand.Create(OnAddDocument);
|
// AddDocument = ReactiveCommand.Create(OnAddDocument);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// private void OnAddDocument()
|
// private void OnAddDocument()
|
||||||
// {
|
// {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IWorkspaceViewModelFactory
|
||||||
|
{
|
||||||
|
WorkspaceViewModel Create(Workspace workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
|
internal class WorkspaceViewModelFactory(IServiceProvider services) : IWorkspaceViewModelFactory
|
||||||
|
{
|
||||||
|
private static ObjectFactory<WorkspaceViewModel>? s_workspaceViewModelFactory;
|
||||||
|
|
||||||
|
public WorkspaceViewModel Create(Workspace workspace)
|
||||||
|
{
|
||||||
|
s_workspaceViewModelFactory ??= ActivatorUtilities.CreateFactory<WorkspaceViewModel>([typeof(Workspace)]);
|
||||||
|
return s_workspaceViewModelFactory(services, [workspace]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceViewModel IWorkspaceViewModelFactory.Create(Workspace workspace) => Create(workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using InkForge.Desktop.Managers;
|
|
||||||
using InkForge.Desktop.ViewModels.Workspaces;
|
|
||||||
|
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.ViewModels;
|
|
||||||
|
|
||||||
public class WorkspacesViewModel : ReactiveObject
|
|
||||||
{
|
|
||||||
private readonly WorkspaceManager _workspaceManager;
|
|
||||||
private WorkspaceViewModel? _workspace;
|
|
||||||
|
|
||||||
public WorkspaceViewModel? Workspace
|
|
||||||
{
|
|
||||||
get => _workspace;
|
|
||||||
private set => this.RaiseAndSetIfChanged(ref _workspace, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkspacesViewModel(WorkspaceManager workspaceManager)
|
|
||||||
{
|
|
||||||
_workspaceManager = workspaceManager;
|
|
||||||
workspaceManager.WhenAnyValue(v => v.Workspace, v => v is null ? null : new WorkspaceViewModel(v)).BindTo(this, v => v.Workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,5 +10,29 @@
|
||||||
x:Class="InkForge.Desktop.Views.Documents.WelcomePageDocument"
|
x:Class="InkForge.Desktop.Views.Documents.WelcomePageDocument"
|
||||||
x:DataType="vm:WelcomePageDocumentViewModel"
|
x:DataType="vm:WelcomePageDocumentViewModel"
|
||||||
inkforge:TopLevels.Register="{CompiledBinding}">
|
inkforge:TopLevels.Register="{CompiledBinding}">
|
||||||
Welcome to Avalonia!
|
<Grid RowDefinitions="Auto, *, Auto">
|
||||||
|
<Label Target="RecentItemsList"
|
||||||
|
Content="Open Recent"
|
||||||
|
Grid.Row="0" />
|
||||||
|
|
||||||
|
<DataGrid Name="RecentItemsList"
|
||||||
|
IsEnabled="False"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Grid.Row="1">
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Header="Name"
|
||||||
|
Width="*" />
|
||||||
|
<DataGridTextColumn Header="Last Used" />
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
|
||||||
|
<Menu Grid.Row="2">
|
||||||
|
<MenuItem Header="Create New"
|
||||||
|
Command="{CompiledBinding CreateNew}" />
|
||||||
|
<MenuItem Header="Open"
|
||||||
|
IsEnabled="False" />
|
||||||
|
<MenuItem Header="Open File"
|
||||||
|
Command="{CompiledBinding OpenNew}" />
|
||||||
|
</Menu>
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<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"
|
|
||||||
xmlns:inkforge="using:InkForge.Desktop.ViewModels"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignWidth="800"
|
|
||||||
d:DesignHeight="450"
|
|
||||||
x:Class="InkForge.Desktop.Views.DocumentsView"
|
|
||||||
x:DataType="inkforge:DocumentsViewModel">
|
|
||||||
<DockControl Layout="{CompiledBinding Layout}" />
|
|
||||||
</UserControl>
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
|
|
||||||
using InkForge.Desktop.ViewModels;
|
|
||||||
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.Views;
|
|
||||||
|
|
||||||
public partial class DocumentsView : UserControl
|
|
||||||
{
|
|
||||||
public DocumentsView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
DataContext = CreateViewModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DocumentsViewModel CreateViewModel()
|
|
||||||
{
|
|
||||||
return ActivatorUtilities.CreateInstance<DocumentsViewModel>(
|
|
||||||
Application.Current!.GetValue(App.ServiceProviderProperty)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,12 +2,16 @@
|
||||||
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:inkforge="app:InkForge"
|
||||||
xmlns:local="using:InkForge.Desktop.Views"
|
xmlns:local="using:InkForge.Desktop.Views"
|
||||||
|
xmlns:vm="using:InkForge.Desktop.ViewModels"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Width="800"
|
Width="800"
|
||||||
Height="450"
|
Height="450"
|
||||||
x:Class="InkForge.Desktop.Views.MainWindow"
|
x:Class="InkForge.Desktop.Views.MainWindow"
|
||||||
Title="MainWindow">
|
x:DataType="vm:MainViewModel"
|
||||||
|
Title="MainWindow"
|
||||||
|
inkforge:TopLevels.Register="{CompiledBinding}">
|
||||||
<NativeMenu.Menu>
|
<NativeMenu.Menu>
|
||||||
<NativeMenu />
|
<NativeMenu />
|
||||||
</NativeMenu.Menu>
|
</NativeMenu.Menu>
|
||||||
|
|
@ -15,13 +19,6 @@
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<NativeMenuBar DockPanel.Dock="Top" />
|
<NativeMenuBar DockPanel.Dock="Top" />
|
||||||
|
|
||||||
<SplitView IsPaneOpen="true"
|
<DockControl Layout="{CompiledBinding Layout}" />
|
||||||
DisplayMode="Inline">
|
|
||||||
<SplitView.Pane>
|
|
||||||
<local:WorkspacesView />
|
|
||||||
</SplitView.Pane>
|
|
||||||
|
|
||||||
<local:DocumentsView />
|
|
||||||
</SplitView>
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
@ -1,11 +1,24 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
using InkForge.Desktop.ViewModels;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace InkForge.Desktop.Views;
|
namespace InkForge.Desktop.Views;
|
||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : ReactiveWindow<MainViewModel>
|
||||||
{
|
{
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
ViewModel = CreateViewModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MainViewModel CreateViewModel()
|
||||||
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance<MainViewModel>(
|
||||||
|
Application.Current!.GetValue(App.ServiceProviderProperty)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
app/InkForge.Desktop/Views/Tools/WorkspaceTool.axaml
Normal file
32
app/InkForge.Desktop/Views/Tools/WorkspaceTool.axaml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<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"
|
||||||
|
xmlns:local="using:InkForge.Desktop.Views.Tools"
|
||||||
|
xmlns:workspaces="using:InkForge.Desktop.Views.Workspaces"
|
||||||
|
xmlns:vm="using:InkForge.Desktop.ViewModels.Tools"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:Class="InkForge.Desktop.Views.Tools.WorkspaceTool"
|
||||||
|
x:DataType="vm:WorkspaceTool"
|
||||||
|
Classes.HasWorkspace="{CompiledBinding Workspace, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
|
||||||
|
<UserControl.Styles>
|
||||||
|
<Style Selector="local|WorkspaceTool">
|
||||||
|
<Setter Property="Content">
|
||||||
|
<Template>
|
||||||
|
<TextBlock>No workspace selected.</TextBlock>
|
||||||
|
</Template>
|
||||||
|
</Setter>
|
||||||
|
|
||||||
|
<Style Selector="^.HasWorkspace">
|
||||||
|
<Setter Property="Content">
|
||||||
|
<Template>
|
||||||
|
<workspaces:WorkspaceView DataContext="{CompiledBinding Workspace}" />
|
||||||
|
</Template>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
|
</UserControl>
|
||||||
11
app/InkForge.Desktop/Views/Tools/WorkspaceTool.axaml.cs
Normal file
11
app/InkForge.Desktop/Views/Tools/WorkspaceTool.axaml.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop.Views.Tools;
|
||||||
|
|
||||||
|
public partial class WorkspaceTool : ReactiveUserControl<ViewModels.Tools.WorkspaceTool>
|
||||||
|
{
|
||||||
|
public WorkspaceTool()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
x:Class="InkForge.Desktop.Views.Workspaces.WorkspaceViewModel"
|
x:Class="InkForge.Desktop.Views.Workspaces.WorkspaceView"
|
||||||
x:DataType="vm:WorkspaceViewModel">
|
x:DataType="vm:WorkspaceViewModel">
|
||||||
|
|
||||||
<Grid ColumnDefinitions="*, Auto"
|
<Grid ColumnDefinitions="*, Auto"
|
||||||
13
app/InkForge.Desktop/Views/Workspaces/WorkspaceView.axaml.cs
Normal file
13
app/InkForge.Desktop/Views/Workspaces/WorkspaceView.axaml.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
using InkForge.Desktop.ViewModels.Workspaces;
|
||||||
|
|
||||||
|
namespace InkForge.Desktop.Views.Workspaces;
|
||||||
|
|
||||||
|
public partial class WorkspaceView : ReactiveUserControl<WorkspaceViewModel>
|
||||||
|
{
|
||||||
|
public WorkspaceView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.Views.Workspaces;
|
|
||||||
|
|
||||||
public partial class WorkspaceViewModel : UserControl
|
|
||||||
{
|
|
||||||
public WorkspaceViewModel()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<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"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
|
||||||
xmlns:local="using:InkForge.Desktop.Views"
|
|
||||||
xmlns:inkforge="app:InkForge"
|
|
||||||
xmlns:vm="using:InkForge.Desktop.ViewModels"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignWidth="800"
|
|
||||||
d:DesignHeight="450"
|
|
||||||
x:Class="InkForge.Desktop.Views.WorkspacesView"
|
|
||||||
x:DataType="vm:WorkspacesViewModel"
|
|
||||||
Classes.HasWorkspace="{CompiledBinding Workspace}">
|
|
||||||
|
|
||||||
<UserControl.Styles>
|
|
||||||
<Style Selector="local|WorkspacesView">
|
|
||||||
<Style Selector="^:not(.HasWorkspace)">
|
|
||||||
<Setter Property="Content">
|
|
||||||
<Template>
|
|
||||||
<TextBlock>
|
|
||||||
No workspace selected.
|
|
||||||
</TextBlock>
|
|
||||||
</Template>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="^.HasWorkspace">
|
|
||||||
<Setter Property="Content"
|
|
||||||
Value="{CompiledBinding Workspace}" />
|
|
||||||
</Style>
|
|
||||||
</Style>
|
|
||||||
</UserControl.Styles>
|
|
||||||
</UserControl>
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
using Avalonia.Controls;
|
|
||||||
|
|
||||||
using InkForge.Desktop.ViewModels;
|
|
||||||
|
|
||||||
using Splat;
|
|
||||||
|
|
||||||
namespace InkForge.Desktop.Views;
|
|
||||||
|
|
||||||
public partial class WorkspacesView : UserControl
|
|
||||||
{
|
|
||||||
public WorkspacesView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
DataContext = Locator.Current.GetService<WorkspacesViewModel>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue