//
// DockFactory.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reactive;
using Dock.Avalonia.Controls;
using Dock.Model.Controls;
using Dock.Model.Core;
using Dock.Model.Mvvm;
using Dock.Model.Mvvm.Controls;
using NosSmooth.Comms.Local;
using NosSmooth.Core.Stateful;
using PacketLogger.Models;
using PacketLogger.Models.Filters;
using PacketLogger.Models.Packets;
using PacketLogger.Models.Titles;
using PacketLogger.Views;
using ReactiveUI;
using HostWindow = PacketLogger.Views.HostWindow;
namespace PacketLogger.ViewModels;
///
/// A factory for root dock.
///
public class DockFactory : Factory, IDisposable
{
private readonly StatefulRepository _repository;
private readonly IServiceProvider _services;
private readonly FilterProfiles _filterProfiles;
private readonly ObservableCollection _providers;
private readonly NostaleProcesses _processes;
private readonly CommsInjector _injector;
private readonly NumberedTitleGenerator _titleGenerator;
private IRootDock? _rootDock;
private IDocumentDock? _documentDock;
///
/// Initializes a new instance of the class.
///
/// The services.
/// The filter profiles.
/// The providers.
/// The nostale processes.
/// The communications injector.
/// The repository.
public DockFactory
(
IServiceProvider services,
FilterProfiles filterProfiles,
ObservableCollection providers,
NostaleProcesses processes,
CommsInjector injector,
StatefulRepository repository
)
{
_titleGenerator = new NumberedTitleGenerator();
_services = services;
_filterProfiles = filterProfiles;
_providers = providers;
_processes = processes;
_repository = repository;
_injector = injector;
}
///
/// Document loaded event.
///
public event Action? DocumentLoaded;
///
/// Document closed event.
///
public event Action? DocumentClosed;
private void OnDocumentLoaded(DocumentViewModel documentViewModel)
{
DocumentLoaded?.Invoke(documentViewModel);
}
private void OnDocumentClosed(DocumentViewModel documentViewModel)
{
DocumentClosed?.Invoke(documentViewModel);
}
///
/// Gets the document dock.
///
public IDocumentDock DocumentDock
=> _documentDock ?? throw new InvalidOperationException("Dock factory is not initialized");
///
/// Creaate and load a document.
///
/// The function to use to load the document.
public void CreateLoadedDocument(Func> load)
{
if (_documentDock is null)
{
return;
}
var document = new DocumentViewModel
(
_services,
_filterProfiles,
_injector,
_repository,
_providers,
_processes,
_titleGenerator,
OnDocumentLoaded,
OnDocumentClosed
)
{ Id = Guid.NewGuid().ToString() };
var observable = load(document);
observable.Subscribe
(
x =>
{
if (!document.Loaded)
{
return;
}
AddDockable(_documentDock, document);
SetActiveDockable(document);
SetFocusedDockable(_documentDock, document);
}
);
}
///
public override IDocumentDock CreateDocumentDock()
{
var documentDock = new DocumentDock();
documentDock.CreateDocument = ReactiveCommand.Create
(
() =>
{
if (!documentDock.CanCreateDocument)
{
return;
}
var index = documentDock.VisibleDockables?.Count + 1;
var document = new DocumentViewModel
(
_services,
_filterProfiles,
_injector,
_repository,
_providers,
_processes,
_titleGenerator,
OnDocumentLoaded,
OnDocumentClosed
)
{ Id = $"New tab {index}" };
AddDockable(documentDock, document);
SetActiveDockable(document);
SetFocusedDockable(documentDock, document);
}
);
return documentDock;
}
///
public override IRootDock CreateLayout()
{
var initialTab = new DocumentViewModel
(
_services,
_filterProfiles,
_injector,
_repository,
_providers,
_processes,
_titleGenerator,
OnDocumentLoaded,
OnDocumentClosed
)
{ Id = $"New tab" };
var documentDock = CreateDocumentDock();
documentDock.IsCollapsable = false;
documentDock.ActiveDockable = initialTab;
documentDock.VisibleDockables = CreateList(initialTab);
documentDock.CanCreateDocument = true;
var rootDock = CreateRootDock();
rootDock.IsCollapsable = false;
rootDock.ActiveDockable = documentDock;
rootDock.DefaultDockable = documentDock;
rootDock.VisibleDockables = CreateList(documentDock);
_documentDock = documentDock;
_rootDock = rootDock;
return rootDock;
}
///
public override void InitLayout(IDockable layout)
{
ContextLocator = new Dictionary>
{
["Home"] = () => layout
};
DockableLocator = new Dictionary>
{
["Root"] = () => _rootDock,
["Documents"] = () => _documentDock
};
HostWindowLocator = new Dictionary>
{
[nameof(IDockWindow)] = () => new HostWindow()
};
base.InitLayout(layout);
}
///
public void Dispose()
{
_processes.Dispose();
}
}