I have a couple of editors with some detail views each that aren't relevant for the other editors. In fact, the customer doesn't want them there because they confuse them.
So I want to toggle the visibility of the views and thought the build-in perspectives in Eclipse might do the trick. I created a IPartListener
like this:
public class ToEachTheirOwnPartListener implements IPartListener {
private final Map<IWorkbenchPart, String> partToPerspectiveId = new IdentityHashMap<>(5);
@Override
public void partOpened(IWorkbenchPart part) {
if (hasOwnPerspective(part)) {
String perspectiveId = cloneEditorPerspective(part);
this.partToPerspectiveId.put(part, perspectiveId);
}
}
private static boolean hasOwnPerspective(IWorkbenchPart part) {
return part instanceof IEditorPart;
}
String cloneEditorPerspective(IWorkbenchPart part) {
final IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
IWorkbenchPage page = part.getSite().getPage();
// more later
}
@Override
public void partBroughtToTop(IWorkbenchPart part) {
if (hasOwnPerspective(part)) {
final IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
part.getSite().getPage().setPerspective(registry.findPerspectiveWithId(this.partToPerspectiveId.get(part)));
}
}
@Override
public void partClosed(IWorkbenchPart part) {
if (hasOwnPerspective(part)) {
final IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
registry.deletePerspective(registry.findPerspectiveWithId(this.partToPerspectiveId.get(part)));
this.partToPerspectiveId.remove(part);
}
}
}
I'm struggeling with the cloneEditorPerspective()
method because allmost all methods are not implemented in E4 or plain buggy.
What I want to do is to just clone an existing perspective like this (okay honestly I would rather use IPerspectiveRegistry#clonePerspective but... E4):
page.savePerspectiveAs(page.getPerspective());
String defaultPerspectiveId = PlatformUI.getWorkbench().getPerspectiveRegistry().getDefaultPerspective();
final IPerspectiveDescriptor defaultPerspective = registry.findPerspectiveWithId(defaultPerspectiveId);
IPerspectiveDescriptor clone = ((PerspectiveRegistry) registry).createPerspective(UUID.randomUUID().toString(),
(PerspectiveDescriptor) defaultPerspective);
But that throws the following exception (evidently the field PerspectiveDescriptor.configElement
is null for the cloned perspective):
java.lang.NullPointerException at org.eclipse.ui.internal.registry.PerspectiveDescriptor.createFactory(PerspectiveDescriptor.java:74) at org.eclipse.ui.internal.WorkbenchPage.setPerspective(WorkbenchPage.java:4053) at ToEachTheirOwnPartListener.partBroughtToTop(ToEachTheirOwnPartListener.java:65)
I could add page.savePerspectiveAs(clone)
to remove the exception, but then for reasons that are completely beyond me not the default perspective is cloned but the currently active one.
So another try; we set the application to an empty perspective, then clone this one:
IPerspectiveDescriptor perspective = registry.findPerspectiveWithId("org.acme.plugin.perspective");
window.getActivePage().setPerspective(perspective);
IPerspectiveDescriptor clone = ((PerspectiveRegistry) registry).createPerspective(UUID.randomUUID().toString(),
(PerspectiveDescriptor) page.getPerspective());
page.savePerspectiveAs(clone);
That code works, but clones all views.
If I close the views manually all hell breaks lose with something like that:
java.lang.NullPointerException at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.canExecuteItem(HandledContributionItem.java:808) at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.access$1(HandledContributionItem.java:802) at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem$3.run(HandledContributionItem.java:167) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
All variations I have tried seem to come down to these three: NPE, cloning the wrong perspective or duplicating the views.
Is there a way to give every editor its own perspective? If so, how?
Evidently the trick is to only clone the currently active perspective. Which means to switch to an empty perspective and then clone:
There are still a bunch of random NPEs because the perspective is null, but that's how E4 rolls.