Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions Quantum.Editor.Avalonia/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,7 @@
<MenuItem Header="Toggle Transported _Frames" Click="OnMenuShowFramesClick" />
<MenuItem Header="Math _Plots" Click="OnShowEngineeringPlotsClick" />
<Separator />
<MenuItem Header="_Panes">
<MenuItem Header="_Route" Tag="route" Click="OnShowPaneClick" />
<MenuItem Header="_Viewport" Tag="viewport" Click="OnShowPaneClick" />
<MenuItem Header="_Inspector" Tag="inspector" Click="OnShowPaneClick" />
<MenuItem Header="_Math Plots" Tag="math-plots" Click="OnShowPaneClick" />
<MenuItem Header="_Diagnostics" Tag="diagnostics" Click="OnShowPaneClick" />
</MenuItem>
<MenuItem x:Name="PanesMenu" Header="_Panes" />
<Separator />
<MenuItem Header="_Reset Layout" Click="OnResetLayoutClick" />
</MenuItem>
Expand All @@ -88,7 +82,7 @@
BorderBrush="#2B3948"
BorderThickness="0,0,0,1"
Padding="10,7">
<Grid ColumnDefinitions="Auto,Auto,Auto,16,Auto,Auto,16,Auto,Auto,*,Auto">
<Grid ColumnDefinitions="Auto,Auto,Auto,16,Auto,Auto,16,Auto,Auto,*,Auto,12,Auto">
<Button x:Name="NewButton" Classes="toolbar" Content="New" Click="OnNewDocumentClick" />
<Button x:Name="OpenButton" Grid.Column="1" Classes="toolbar" Content="Open" Click="OnOpenDocumentClick" />
<Button x:Name="SaveButton" Grid.Column="2" Classes="toolbar" Content="Save" Click="OnSaveDocumentClick" />
Expand All @@ -103,9 +97,20 @@
Content="Frames"
IsChecked="True"
IsCheckedChanged="OnShowFramesChanged" />
<StackPanel
Grid.Column="10"
Orientation="Horizontal"
VerticalAlignment="Center"
Spacing="8">
<TextBlock VerticalAlignment="Center" Foreground="#9EB3C7" Text="Workspace" />
<ComboBox
x:Name="WorkspaceSelectorComboBox"
Width="190"
SelectionChanged="OnWorkspaceSelectorChanged" />
</StackPanel>
<ComboBox
x:Name="ProjectionComboBox"
Grid.Column="10"
Grid.Column="12"
Width="145"
SelectedIndex="0"
SelectionChanged="OnProjectionChanged">
Expand Down
154 changes: 125 additions & 29 deletions Quantum.Editor.Avalonia/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ public partial class MainWindow : Window

private readonly EditorWorkspace workspace;
private readonly WorkspaceProfileManager workspaceProfiles;
private readonly EditorDockingAdapter docking;
private readonly WorkspaceSelectorModel workspaceSelector;
private readonly IReadOnlyDictionary<string, object> paneContexts;
private readonly Dictionary<WorkspaceProfileId, EditorDockingAdapter> dockingByWorkspace = new();
private EditorDockingAdapter docking;
private bool synchronizingWorkspaceSelector;
private readonly RoutePaneControl RoutePane;
private readonly ViewportPaneControl ViewportPane;
private readonly InspectorPaneControl InspectorPane;
Expand Down Expand Up @@ -72,20 +76,24 @@ public MainWindow(
DiagnosticsPane = new DiagnosticsPaneControl();
WirePaneInteractions();

DockPaneRegistry paneRegistry = DockPaneRegistry.CreateDefaultTrack();
paneContexts = new Dictionary<string, object>(StringComparer.Ordinal)
{
[WorkspacePaneIds.Route] = RoutePane,
[WorkspacePaneIds.Viewport] = ViewportPane,
[WorkspacePaneIds.Inspector] = InspectorPane,
[WorkspacePaneIds.MathPlots] = MathPlotsPane,
[WorkspacePaneIds.Diagnostics] = DiagnosticsPane
};
workspaceSelector = new WorkspaceSelectorModel(this.workspaceProfiles);
docking = new EditorDockingAdapter(
paneRegistry,
new Dictionary<string, object>(StringComparer.Ordinal)
{
[WorkspacePaneIds.Route] = RoutePane,
[WorkspacePaneIds.Viewport] = ViewportPane,
[WorkspacePaneIds.Inspector] = InspectorPane,
[WorkspacePaneIds.MathPlots] = MathPlotsPane,
[WorkspacePaneIds.Diagnostics] = DiagnosticsPane
},
this.workspaceProfiles.CurrentProfile.Composition,
ResolvePaneContexts(this.workspaceProfiles.CurrentProfile.Composition),
layoutPersistence);
dockingByWorkspace.Add(this.workspaceProfiles.CurrentProfileId, docking);
DockHost.Factory = docking.Factory;
DockHost.Layout = docking.Layout;
InitializeWorkspaceSelector();
PopulatePaneMenu();

this.workspace.WorkspaceChanged += OnWorkspaceChanged;
this.workspace.StationCursorChanged += OnStationCursorChanged;
Expand All @@ -104,6 +112,8 @@ public MainWindow(

public WorkspaceProfileManager WorkspaceProfiles => workspaceProfiles;

public WorkspaceSelectorModel WorkspaceSelector => workspaceSelector;

public EditorDockingAdapter Docking => docking;

private static EditorWorkspace CreateWorkspace()
Expand Down Expand Up @@ -131,33 +141,97 @@ private void OnWorkspaceChanged(object? sender, EventArgs eventArgs)

private void OnCurrentProfileChanged(object? sender, EventArgs eventArgs)
{
ActivateWorkspaceComposition(workspaceProfiles.CurrentProfile);
ApplyWorkspaceProfile(
workspaceProfiles.CurrentProfile,
applyPaneVisibilityDefaults: true);
applyPaneVisibilityDefaults: !docking.RestoredSavedLayout);
SynchronizeWorkspaceSelector();
UpdateWorkspaceView();
}

private void ActivateWorkspaceComposition(WorkspaceProfile profile)
{
docking.TrySaveLayout();
if (!dockingByWorkspace.TryGetValue(profile.Id, out EditorDockingAdapter? nextDocking))
{
nextDocking = new EditorDockingAdapter(
profile.Composition,
ResolvePaneContexts(profile.Composition),
new DockLayoutPersistenceService(
DockLayoutPersistenceService.GetDefaultLayoutFilePath(profile.Id)));
dockingByWorkspace.Add(profile.Id, nextDocking);
}

docking = nextDocking;
DockHost.Factory = docking.Factory;
DockHost.Layout = docking.Layout;
PopulatePaneMenu();
}

private IReadOnlyDictionary<string, object> ResolvePaneContexts(
WorkspaceComposition composition)
{
return composition.Panes.Panes.ToDictionary(
pane => pane.Id,
pane => paneContexts.TryGetValue(pane.Id, out object? context)
? context
: throw new InvalidOperationException(
$"Workspace pane '{pane.Id}' has no registered frontend content."),
StringComparer.Ordinal);
}

private void InitializeWorkspaceSelector()
{
WorkspaceSelectorComboBox.ItemsSource = workspaceSelector.Items
.Select(item => new ComboBoxItem
{
Content = item.DisplayText,
IsEnabled = item.IsEnabled,
Tag = item.Id
})
.ToArray();
SynchronizeWorkspaceSelector();
}

private void SynchronizeWorkspaceSelector()
{
synchronizingWorkspaceSelector = true;
WorkspaceSelectorComboBox.SelectedItem =
WorkspaceSelectorComboBox.Items
.OfType<ComboBoxItem>()
.Single(item => item.Tag is WorkspaceProfileId id &&
id == workspaceProfiles.CurrentProfileId);
synchronizingWorkspaceSelector = false;
}

private void PopulatePaneMenu()
{
PanesMenu.ItemsSource = docking.Registry.Panes
.Select(pane =>
{
var menuItem = new MenuItem
{
Header = pane.Title,
Tag = pane.Id
};
menuItem.Click += OnShowPaneClick;
return menuItem;
})
.ToArray();
}

private void ApplyWorkspaceProfile(
WorkspaceProfile profile,
bool applyPaneVisibilityDefaults)
{
if (applyPaneVisibilityDefaults)
{
docking.SetPaneVisible(
WorkspacePaneIds.Route,
profile.IsPaneVisibleByDefault(WorkspacePaneIds.Route));
docking.SetPaneVisible(
WorkspacePaneIds.Viewport,
profile.IsPaneVisibleByDefault(WorkspacePaneIds.Viewport));
docking.SetPaneVisible(
WorkspacePaneIds.Inspector,
profile.IsPaneVisibleByDefault(WorkspacePaneIds.Inspector));
docking.SetPaneVisible(
WorkspacePaneIds.MathPlots,
profile.IsPaneVisibleByDefault(WorkspacePaneIds.MathPlots));
docking.SetPaneVisible(
WorkspacePaneIds.Diagnostics,
profile.IsPaneVisibleByDefault(WorkspacePaneIds.Diagnostics));
foreach (DockPaneRegistration pane in docking.Registry.Panes)
{
docking.SetPaneVisible(
pane.Id,
profile.IsPaneVisibleByDefault(pane.Id));
}
}

bool showFileCommands = profile.HasCommandGroup(WorkspaceCommandGroupIds.File);
Expand Down Expand Up @@ -401,6 +475,24 @@ private void OnProjectionChanged(object? sender, SelectionChangedEventArgs event
};
}

private void OnWorkspaceSelectorChanged(object? sender, SelectionChangedEventArgs eventArgs)
{
if (synchronizingWorkspaceSelector)
{
return;
}

if (WorkspaceSelectorComboBox.SelectedItem is ComboBoxItem
{
Tag: WorkspaceProfileId profileId
} && workspaceSelector.TryActivate(profileId))
{
return;
}

SynchronizeWorkspaceSelector();
}

private void OnShowFramesChanged(object? sender, RoutedEventArgs eventArgs)
{
if (ViewportPane != null && ShowFramesCheckBox != null)
Expand All @@ -416,7 +508,10 @@ private void OnMenuShowFramesClick(object? sender, RoutedEventArgs eventArgs)

private void OnShowEngineeringPlotsClick(object? sender, RoutedEventArgs eventArgs)
{
docking.ShowPane(WorkspacePaneIds.MathPlots);
if (docking.Registry.Contains(WorkspacePaneIds.MathPlots))
{
docking.ShowPane(WorkspacePaneIds.MathPlots);
}
}

private void OnShowPaneClick(object? sender, RoutedEventArgs eventArgs)
Expand All @@ -430,7 +525,8 @@ private void OnShowPaneClick(object? sender, RoutedEventArgs eventArgs)
private void OnResetLayoutClick(object? sender, RoutedEventArgs eventArgs)
{
DockHost.Layout = docking.ResetLayout();
workspace.SetStatus("Docking layout reset to the default Track workspace.");
workspace.SetStatus(
$"Docking layout reset to the default {workspaceProfiles.CurrentProfile.DisplayName} workspace.");
}

private void OnEngineeringPlotStationChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Dock.Model.Controls;
using Dock.Model.Core;
using Dock.Serializer;
using Quantum.Editor.Avalonia.Services.Workspaces;

namespace Quantum.Editor.Avalonia.Services.Docking;

Expand Down Expand Up @@ -44,13 +45,26 @@ internal DockLayoutPersistenceService(

public static string GetDefaultLayoutFilePath()
{
return GetDefaultLayoutFilePath(WorkspaceProfileId.Track);
}

public static string GetDefaultLayoutFilePath(WorkspaceProfileId workspaceId)
{
if (workspaceId.IsEmpty)
{
throw new ArgumentException("A workspace identifier is required.", nameof(workspaceId));
}

string localApplicationData = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData);
string fileName = workspaceId == WorkspaceProfileId.Track
? LayoutFileName
: workspaceId.Value + "-docking-layout.json";
return Path.Combine(
localApplicationData,
"QuantumCoasterWorks",
"Editor",
LayoutFileName);
fileName);
}

public DockLayoutLoadStatus TryLoadLayout(out IRootDock? layout)
Expand Down
Loading
Loading