Skip to content

Commit

Permalink
Modify the 'Close Editor' handler and enabled when evaluation to supp…
Browse files Browse the repository at this point in the history
…ort for Compatibility parts and new Parts which represent an Editor and are contributed via eg. PartDescriptors in a Model Fragment. Associated with Issue#2176.
  • Loading branch information
feilimb authored and mickaelistria committed Oct 1, 2024
1 parent 419bb61 commit 04dc50b
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@

package org.eclipse.ui.internal;

import java.util.List;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionInfo;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;

/**
* Closes the active editor.
Expand All @@ -33,43 +38,53 @@
*
* @since 3.3
*/
public class CloseEditorHandler extends AbstractEvaluationHandler {

private Expression enabledWhen;

public CloseEditorHandler() {
registerEnablement();
}
public class CloseEditorHandler extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
IEditorPart part = HandlerUtil.getActiveEditorChecked(event);
window.getActivePage().closeEditor(part, true);

return null;
}

@Override
protected Expression getEnabledWhenExpression() {
if (enabledWhen == null) {
enabledWhen = new Expression() {
@Override
public EvaluationResult evaluate(IEvaluationContext context) {
IEditorPart part = InternalHandlerUtil.getActiveEditor(context);
if (part != null) {
return EvaluationResult.TRUE;
IWorkbenchPart activePart = HandlerUtil.getActivePart(event);
if (activePart instanceof IEditorPart) {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
window.getActivePage().closeEditor((IEditorPart) activePart, true);
} else {
// we may have an E4PartWrapper for a part which has been contributed eg. via a
// PartDescriptor in a model fragment, and which has been tagged as
// representing an Editor
if (activePart instanceof E4PartWrapper) {
// derive the IEclipseContext & EPartService
BundleContext context = FrameworkUtil.getBundle(IWorkbench.class).getBundleContext();
ServiceReference<IWorkbench> reference = context.getServiceReference(IWorkbench.class);
IEclipseContext eclipseContext = context.getService(reference).getApplication().getContext();
EPartService partService = eclipseContext.get(EPartService.class);

// access the wrapped part => save & close it
MPart wrappedPart = ((E4PartWrapper) activePart).wrappedPart;
if (wrappedPart != null && partService != null) {
// ensure the active part does indeed represent an editor
// (and not eg. a view) - checking here is just for extra
// redundancy
if (representsEditor(wrappedPart)) {
if (partService.savePart(wrappedPart, true)) {
partService.hidePart(wrappedPart);
}
}
return EvaluationResult.FALSE;
}

@Override
public void collectExpressionInfo(ExpressionInfo info) {
info.addVariableNameAccess(ISources.ACTIVE_EDITOR_NAME);
}
};
}
}
return enabledWhen;

return null;
}

/**
* Checks whether the specified part represents an editor instance.
*
* @param part the part to query
* @return true if the specified part represents an editor, false otherwise
*/
private boolean representsEditor(MPart part) {
List<String> partTags = part.getTags();
return partTags == null || partTags.isEmpty() ? false
: partTags.stream().anyMatch(tag -> Workbench.EDITOR_TAG.equals(tag));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2007, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/

package org.eclipse.ui.internal;

import java.util.List;
import org.eclipse.core.expressions.PropertyTester;

/**
* <p>
* Tests whether the object under test represents an MPart instance which is
* tagged as being one which represents an Editor (rather than a View).
* </p>
*
* <p>
* This test is performed via a query of the tags associated with the MPart, and
* checking whether this collection contains the
* {@link org.eclipse.ui.internal.Workbench#EDITOR_TAG} identifier.
* </p>
*
*/
public class PartTaggedAsEditorPropertyTester extends PropertyTester {

@Override
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
if (receiver instanceof E4PartWrapper) {
E4PartWrapper partWrapper = (E4PartWrapper) receiver;
if (partWrapper.wrappedPart != null) {
List<String> partTags = partWrapper.wrappedPart.getTags();
return partTags == null || partTags.isEmpty() ? false
: partTags.stream().anyMatch(tag -> Workbench.EDITOR_TAG.equals(tag));
}
}
return false;
}
}
17 changes: 12 additions & 5 deletions bundles/org.eclipse.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,13 @@
properties="isPerspectiveOpen"
type="org.eclipse.ui.IWorkbenchWindow">
</propertyTester>
<propertyTester
class="org.eclipse.ui.internal.PartTaggedAsEditorPropertyTester"
id="org.eclipse.ui.isPartTaggedAsEditor"
namespace="org.eclipse.ui"
properties="isPartTaggedAsEditor"
type="org.eclipse.ui.IWorkbenchPart">
</propertyTester>
</extension>
<extension
point="org.eclipse.core.expressions.definitions">
Expand Down Expand Up @@ -2207,11 +2214,11 @@
class="org.eclipse.ui.internal.CloseEditorHandler"
commandId="org.eclipse.ui.file.close">
<enabledWhen>
<with
variable="activeEditor">
<instanceof
value="org.eclipse.ui.IEditorPart">
</instanceof>
<with variable="activePart">
<or>
<instanceof value="org.eclipse.ui.IEditorPart" />
<test property="org.eclipse.ui.isPartTaggedAsEditor" />
</or>
</with>
</enabledWhen>
</handler>
Expand Down

0 comments on commit 04dc50b

Please sign in to comment.