You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.5 KiB
126 lines
3.5 KiB
using System; |
|
using System.Text.Json.Nodes; |
|
using System.Threading.Tasks; |
|
using Avalonia; |
|
using Avalonia.Collections; |
|
using Avalonia.Controls; |
|
using Avalonia.Controls.Primitives; |
|
using Avalonia.Threading; |
|
using Dock.Avalonia.Controls; |
|
using Dock.Model; |
|
using Dock.Model.Core; |
|
using Dock.Serializer; |
|
using StabilityMatrix.Avalonia.Models.Inference; |
|
using StabilityMatrix.Avalonia.ViewModels.Base; |
|
|
|
namespace StabilityMatrix.Avalonia.Controls.Dock; |
|
|
|
/// <summary> |
|
/// Base for Dock controls |
|
/// Expects a <see cref="DockControl"/> named "Dock" in the XAML |
|
/// </summary> |
|
public abstract class DockUserControlBase : DropTargetUserControlBase |
|
{ |
|
private DockControl? baseDock; |
|
private readonly DockSerializer dockSerializer = new(typeof(AvaloniaList<>)); |
|
private readonly DockState dockState = new(); |
|
|
|
/// <inheritdoc /> |
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
|
{ |
|
base.OnApplyTemplate(e); |
|
|
|
baseDock = |
|
this.FindControl<DockControl>("Dock") |
|
?? throw new NullReferenceException("DockControl not found"); |
|
|
|
if (baseDock.Layout is { } layout) |
|
{ |
|
dockState.Save(layout); |
|
// Dispatcher.UIThread.Post(() => dockState.Save(layout), DispatcherPriority.Background); |
|
} |
|
} |
|
|
|
/// <inheritdoc /> |
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
|
{ |
|
base.OnAttachedToVisualTree(e); |
|
|
|
// Attach handlers for view state saving and loading |
|
if (DataContext is InferenceTabViewModelBase vm) |
|
{ |
|
vm.SaveViewStateRequested += DataContext_OnSaveViewStateRequested; |
|
vm.LoadViewStateRequested += DataContext_OnLoadViewStateRequested; |
|
} |
|
} |
|
|
|
/// <inheritdoc /> |
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) |
|
{ |
|
base.OnDetachedFromVisualTree(e); |
|
|
|
// Detach handlers for view state saving and loading |
|
if (DataContext is InferenceTabViewModelBase vm) |
|
{ |
|
vm.SaveViewStateRequested -= DataContext_OnSaveViewStateRequested; |
|
vm.LoadViewStateRequested -= DataContext_OnLoadViewStateRequested; |
|
} |
|
} |
|
|
|
private void DataContext_OnSaveViewStateRequested(object? sender, SaveViewStateEventArgs args) |
|
{ |
|
var saveTcs = new TaskCompletionSource<ViewState>(); |
|
|
|
Dispatcher.UIThread.Post(() => |
|
{ |
|
var state = new ViewState { DockLayout = SaveDockLayout() }; |
|
saveTcs.SetResult(state); |
|
}); |
|
|
|
args.StateTask ??= saveTcs.Task; |
|
} |
|
|
|
private void DataContext_OnLoadViewStateRequested(object? sender, LoadViewStateEventArgs args) |
|
{ |
|
if (args.State?.DockLayout is { } layout) |
|
{ |
|
// Provided |
|
LoadDockLayout(layout); |
|
} |
|
else |
|
{ |
|
// Restore default |
|
RestoreDockLayout(); |
|
} |
|
} |
|
|
|
private void LoadDockLayout(JsonObject data) |
|
{ |
|
LoadDockLayout(data.ToJsonString()); |
|
} |
|
|
|
private void LoadDockLayout(string data) |
|
{ |
|
if (baseDock is null) |
|
return; |
|
|
|
if (dockSerializer.Deserialize<IDock?>(data) is { } layout) |
|
{ |
|
baseDock.Layout = layout; |
|
} |
|
} |
|
|
|
private void RestoreDockLayout() |
|
{ |
|
// TODO: idk this doesn't work |
|
if (baseDock?.Layout != null) |
|
{ |
|
dockState.Restore(baseDock.Layout); |
|
} |
|
} |
|
|
|
protected string? SaveDockLayout() |
|
{ |
|
return baseDock is null ? null : dockSerializer.Serialize(baseDock.Layout); |
|
} |
|
}
|
|
|