/// <inheritdoc/> public void OpenCurveEditorWindow([NotNull] object curve, string name) { if (curve == null) { throw new ArgumentNullException(nameof(curve)); } if (dockingLayoutManager == null) { throw new InvalidOperationException("This method can only be invoked on the IEditorDialogService that has the editor main window as parent."); } CurveEditorViewModel editorViewModel = null; LayoutAnchorable editorPane = null; if (curveEditor != null) { // curve editor already exists editorViewModel = curveEditor.Item1; editorPane = curveEditor.Item2; } // Create the editor view model if needed if (editorViewModel == null) { editorViewModel = new CurveEditorViewModel(session.ServiceProvider, session); } // Populate the editor view model if (curve is IComputeCurve <Color4> ) { editorViewModel.AddCurve((IComputeCurve <Color4>)curve, name); } else if (curve is IComputeCurve <float> ) { editorViewModel.AddCurve((IComputeCurve <float>)curve, name); } else if (curve is IComputeCurve <Quaternion> ) { editorViewModel.AddCurve((IComputeCurve <Quaternion>)curve, name); } else if (curve is IComputeCurve <Vector2> ) { editorViewModel.AddCurve((IComputeCurve <Vector2>)curve, name); } else if (curve is IComputeCurve <Vector3> ) { editorViewModel.AddCurve((IComputeCurve <Vector3>)curve, name); } else if (curve is IComputeCurve <Vector4> ) { editorViewModel.AddCurve((IComputeCurve <Vector4>)curve, name); } editorViewModel.Focus(); // Create the editor pane if needed if (editorPane == null) { editorPane = new LayoutAnchorable { Content = new CurveEditorView { DataContext = editorViewModel }, Title = "Curve Editor", CanClose = true, }; editorPane.Closed += CurveEditorClosed; //editorPane.Closed += (s, e) => //{ // if (((LayoutAnchorable)s).IsHidden) // { // RemoveCurveEditor(true); // } //}; AvalonDockHelper.GetDocumentPane(dockingLayoutManager.DockingManager).Children.Add(editorPane); } curveEditor = Tuple.Create(editorViewModel, editorPane); MakeActiveVisible(editorPane); }
/// <summary> /// Opens (and activates) an editor window for the given asset. If an editor window for this asset already exists, simply activates it. /// </summary> /// <param name="asset">The asset for which to show an editor window.</param> /// <param name="saveSettings">True if <see cref="MRUAdditionalData.OpenedAssets"/> should be updated, false otherwise. Note that if the editor fail to load it will not be updated.</param> /// <returns></returns> internal async Task OpenAssetEditorWindow([NotNull] AssetViewModel asset, bool saveSettings) { if (asset == null) { throw new ArgumentNullException(nameof(asset)); } if (dockingLayoutManager == null) { throw new InvalidOperationException("This method can only be invoked on the IEditorDialogService that has the editor main window as parent."); } // Switch to the editor layout before adding any Pane if (assetEditors.Count == 0) { dockingLayoutManager.SwitchToEditorLayout(); } using (await mutex.LockAsync()) { LayoutAnchorable editorPane = null; IEditorView view; // Asset already has an editor? if (asset.Editor != null) { // Look for the corresponding pane if (!assetEditors.TryGetValue(asset.Editor, out editorPane)) { // Inconsistency, clean leaking editor RemoveAssetEditor(asset); // Try to find if another editor currently has this asset var editor = assetEditors.Keys.OfType <IMultipleAssetEditorViewModel>().FirstOrDefault(x => x.OpenedAssets.Contains(asset)); if (editor != null) { editorPane = assetEditors[editor]; asset.Editor = editor; } } } // Existing editor? if (editorPane != null) { // Make the pane visible immediately MakeActiveVisible(editorPane); view = editorPane.Content as IEditorView; if (view?.EditorInitialization != null) { // Wait for the end of the initialization await view.EditorInitialization; } return; } // Create a new editor view view = asset.ServiceProvider.Get <IAssetsPluginService>().ConstructEditionView(asset); if (view != null) { // Pane may already exists (e.g. created from layout saving) editorPane = AvalonDockHelper.GetAllAnchorables(dockingLayoutManager.DockingManager).FirstOrDefault(p => p.Title == asset.Url); if (editorPane == null) { editorPane = new LayoutAnchorable { CanClose = true }; // Stack the asset in the dictionary of editor to prevent double-opening while double-clicking twice on the asset, since the initialization is async AvalonDockHelper.GetDocumentPane(dockingLayoutManager.DockingManager).Children.Add(editorPane); } editorPane.IsActiveChanged += EditorPaneIsActiveChanged; editorPane.IsSelectedChanged += EditorPaneIsSelectedChanged; editorPane.Closing += EditorPaneClosing; editorPane.Closed += EditorPaneClosed; editorPane.Content = view; // Make the pane visible immediately MakeActiveVisible(editorPane); // Initialize the editor view view.DataContext = asset; // Create a binding for the title var binding = new Binding(nameof(AssetViewModel.Url)) { Mode = BindingMode.OneWay, Source = asset }; BindingOperations.SetBinding(editorPane, LayoutContent.TitleProperty, binding); var viewModel = await view.InitializeEditor(asset); if (viewModel == null) { // Could not initialize editor CleanEditorPane(editorPane); RemoveEditorPane(editorPane); } else { assetEditors[viewModel] = editorPane; openedAssets.Add(asset); var multiEditor = viewModel as IMultipleAssetEditorViewModel; if (multiEditor != null) { foreach (var item in multiEditor.OpenedAssets) { if (item.Editor != null) { // Note: this could happen in some case after undo/redo that involves parenting of scenes RemoveAssetEditor(item); } item.Editor = viewModel; } multiEditor.OpenedAssets.CollectionChanged += (_, e) => MultiEditorOpenAssetsChanged(multiEditor, e); } else { asset.Editor = viewModel; } } } } // If the opening of the editor failed, go back to normal layout if (assetEditors.Count == 0) { dockingLayoutManager.SwitchToNormalLayout(); return; } if (saveSettings) { dockingLayoutManager.SaveOpenAssets(OpenedAssets); } }