Skip to content

Commit 2597f7f

Browse files
akurtakovclaude
andcommitted
Register model-contributed perspectives in PerspectiveRegistry
Perspectives contributed directly into the application model (e.g. as children of a perspective stack via a model fragment) rather than through the org.eclipse.ui.perspectives extension point or as application snippets were unknown to the PerspectiveRegistry, and therefore invisible to the "Open Perspective" dialog and unresolvable by id. Scan the model for such perspectives and register descriptors for them, both at startup and lazily from getPerspectives(). Add a test covering a model-contributed perspective. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 51815e5 commit 2597f7f

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/registry/PerspectiveRegistry.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ void postConstruct(MApplication application) {
104104
}
105105
}
106106

107+
registerModelPerspectives();
108+
107109
impExpHandlerContext = context.createChild();
108110
impExpHandlerContext.set(PerspectiveRegistry.class, this);
109111
ContextInjectionFactory.make(ImportExportPespectiveHandler.class, impExpHandlerContext);
@@ -114,6 +116,20 @@ public void addPerspective(MPerspective perspective) {
114116
createDescriptor(perspective);
115117
}
116118

119+
/**
120+
* Registers descriptors for perspectives contributed directly into the model
121+
* (not via the extension point or as snippets), leaving already known ones
122+
* untouched, so they are visible to the "Open Perspective" dialog.
123+
*/
124+
private void registerModelPerspectives() {
125+
for (MPerspective perspective : modelService.findElements(application, null, MPerspective.class)) {
126+
String id = perspective.getElementId();
127+
if (id != null && !descriptors.containsKey(id)) {
128+
createDescriptor(perspective);
129+
}
130+
}
131+
}
132+
117133
public void createDescriptor(MPerspective perspective) {
118134
String label = perspective.getLocalizedLabel();
119135
String originalId = getOriginalId(perspective);
@@ -221,6 +237,9 @@ public String getDefaultPerspective() {
221237

222238
@Override
223239
public IPerspectiveDescriptor[] getPerspectives() {
240+
// Pick up perspectives contributed into the model after this registry was
241+
// created so the returned list stays in sync with what is available.
242+
registerModelPerspectives();
224243
Collection<?> descs = WorkbenchActivityHelper.restrictCollection(descriptors.values(), new ArrayList<>());
225244
return descs.toArray(new IPerspectiveDescriptor[descs.size()]);
226245
}

tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/api/IPerspectiveRegistryTest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2013 IBM Corporation and others.
2+
* Copyright (c) 2000, 2026 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,13 +14,22 @@
1414
package org.eclipse.ui.tests.api;
1515

1616
import static org.junit.Assert.assertEquals;
17+
import static org.junit.Assert.assertFalse;
1718
import static org.junit.Assert.assertNotNull;
1819
import static org.junit.Assert.assertNull;
20+
import static org.junit.Assert.assertTrue;
1921

22+
import java.util.Arrays;
23+
import java.util.List;
24+
25+
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
26+
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
27+
import org.eclipse.e4.ui.workbench.modeling.EModelService;
2028
import org.eclipse.ui.IPerspectiveDescriptor;
2129
import org.eclipse.ui.IPerspectiveRegistry;
2230
import org.eclipse.ui.IWorkbenchPage;
2331
import org.eclipse.ui.PlatformUI;
32+
import org.eclipse.ui.internal.WorkbenchWindow;
2433
import org.eclipse.ui.tests.harness.util.ArrayUtil;
2534
import org.junit.Before;
2635
import org.junit.Ignore;
@@ -90,6 +99,46 @@ public void testGetPerspectives() throws Throwable {
9099
}
91100
}
92101

102+
/**
103+
* Perspectives contributed directly into the model (not via the extension
104+
* point) must still be registered so they are listed and can be opened by id.
105+
*/
106+
@Test
107+
public void testModelPerspective() {
108+
WorkbenchWindow window = (WorkbenchWindow) PlatformUI.getWorkbench().getActiveWorkbenchWindow();
109+
EModelService modelService = window.getService(EModelService.class);
110+
111+
List<MPerspectiveStack> stacks = modelService.findElements(window.getModel(), null, MPerspectiveStack.class);
112+
assertFalse("expected a perspective stack in the active window", stacks.isEmpty());
113+
MPerspectiveStack stack = stacks.get(0);
114+
115+
String id = "org.eclipse.ui.tests.modelContributedPerspective";
116+
String label = "Model Contributed Perspective";
117+
MPerspective perspective = modelService.createModelElement(MPerspective.class);
118+
perspective.setElementId(id);
119+
perspective.setLabel(label);
120+
perspective.setToBeRendered(false);
121+
stack.getChildren().add(perspective);
122+
123+
try {
124+
// It must appear in the list backing the "Open Perspective" dialog.
125+
assertTrue("the model-contributed perspective should be listed in the registry",
126+
Arrays.stream(fReg.getPerspectives()).anyMatch(d -> id.equals(d.getId())));
127+
128+
// It must be resolvable by id so that opening it actually works.
129+
IPerspectiveDescriptor descriptor = fReg.findPerspectiveWithId(id);
130+
assertNotNull("model-contributed perspective must be resolvable by id", descriptor);
131+
assertEquals(id, descriptor.getId());
132+
assertEquals(label, descriptor.getLabel());
133+
} finally {
134+
stack.getChildren().remove(perspective);
135+
IPerspectiveDescriptor descriptor = fReg.findPerspectiveWithId(id);
136+
if (descriptor != null) {
137+
fReg.deletePerspective(descriptor);
138+
}
139+
}
140+
}
141+
93142
@Test
94143
@Ignore
95144
public void XXXtestDeleteClonedPerspective() {

0 commit comments

Comments
 (0)