| /*=============================================================================# |
| # Copyright (c) 2008, 2020 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.ui.actions; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.commands.IHandler; |
| 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.core.internal.expressions.AndExpression; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.ui.ActiveShellExpression; |
| import org.eclipse.ui.ISources; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.handlers.IHandlerActivation; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.services.IServiceLocator; |
| import org.eclipse.ui.swt.IFocusService; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| |
| /** |
| * Helper to use services for one or multiple specified SWT controls. |
| * |
| * DEV: At moment only {@link IHandlerService}, but other services can be added later if required |
| */ |
| @NonNullByDefault |
| public class ControlServicesUtil { |
| |
| |
| private class FocusExpression extends Expression { |
| |
| String getFocusControlId() { |
| return ControlServicesUtil.this.id; |
| } |
| |
| @Override |
| public EvaluationResult evaluate(final IEvaluationContext context) throws CoreException { |
| final Object id= context.getVariable(ISources.ACTIVE_FOCUS_CONTROL_ID_NAME); |
| return EvaluationResult.valueOf(ControlServicesUtil.this.id == id); |
| } |
| |
| @Override |
| public void collectExpressionInfo(final ExpressionInfo info) { |
| info.addVariableNameAccess(ISources.ACTIVE_FOCUS_CONTROL_ID_NAME); |
| } |
| |
| @Override |
| protected int computeHashCode() { |
| return FocusExpression.class.hashCode() * HASH_FACTOR + |
| hashCode(ControlServicesUtil.this.id) * HASH_FACTOR; |
| } |
| |
| @Override |
| public boolean equals(final @Nullable Object obj) { |
| if (obj == this) { |
| return true; |
| } |
| if (obj instanceof FocusExpression) { |
| final FocusExpression other= (FocusExpression)obj; |
| return ControlServicesUtil.this.id.equals(other.getFocusControlId()); |
| } |
| return false; |
| } |
| } |
| |
| |
| private final String id; |
| private final IServiceLocator serviceLocator; |
| private final Expression defaultExpression; |
| |
| private boolean requireDeactivation; |
| private @Nullable IHandlerService handlerService; |
| private @Nullable List<IHandlerActivation> activatedHandlers; |
| |
| |
| /** |
| * Creates a new util for services of the specified service locator. |
| * |
| * @param serviceLocator the servicelocator to be used |
| * @param id for control (group) |
| * @param parentControl used to get shell and listen for dispose event |
| */ |
| public ControlServicesUtil(final IServiceLocator serviceLocator, final String id, |
| final Control parentControl) { |
| assert (serviceLocator != null); |
| assert (id != null); |
| assert (parentControl != null); |
| |
| this.id= id; |
| this.serviceLocator= serviceLocator; |
| this.defaultExpression= initExpression(parentControl); |
| |
| parentControl.addDisposeListener(new DisposeListener() { |
| @Override |
| public void widgetDisposed(final DisposeEvent e) { |
| dispose(); |
| } |
| }); |
| } |
| |
| private Expression initExpression(final Control control) { |
| Expression focusExpression= new FocusExpression(); |
| if (this.serviceLocator instanceof IWorkbench) { |
| final AndExpression and= new AndExpression(); |
| and.add(new ActiveShellExpression(control.getShell())); |
| and.add(focusExpression); |
| this.requireDeactivation= true; |
| return and; |
| } |
| else if (this.serviceLocator instanceof IWorkbenchPage |
| && !control.getShell().equals( |
| ((IWorkbenchPage)this.serviceLocator).getWorkbenchWindow().getShell() )) { |
| final AndExpression and= new AndExpression(); |
| and.add(new ActiveShellExpression(control.getShell())); |
| and.add(focusExpression); |
| this.requireDeactivation= true; |
| return and; |
| } |
| else { |
| this.requireDeactivation= false; |
| return focusExpression; |
| } |
| } |
| |
| |
| public void addControl(final Control control) { |
| final IFocusService focusService= nonNullAssert( |
| this.serviceLocator.getService(IFocusService.class) ); |
| focusService.addFocusTracker(control, this.id); |
| } |
| |
| public Expression getExpression() { |
| return this.defaultExpression; |
| } |
| |
| public void activateHandler(final String commandId, final IHandler handler) { |
| IHandlerService handlerService= this.handlerService; |
| if (handlerService == null) { |
| handlerService= nonNullAssert( |
| this.serviceLocator.getService(IHandlerService.class) ); |
| this.handlerService= handlerService; |
| if (this.requireDeactivation) { |
| this.activatedHandlers= new ArrayList<>(); |
| } |
| } |
| |
| final IHandlerActivation handlerActivation= handlerService.activateHandler( |
| commandId, handler, this.defaultExpression ); |
| final List<IHandlerActivation> activatedHandlers= this.activatedHandlers; |
| if (activatedHandlers != null) { |
| activatedHandlers.add(handlerActivation); |
| } |
| } |
| |
| |
| protected void dispose() { |
| IHandlerService handlerService= this.handlerService; |
| if (handlerService != null) { |
| this.handlerService= null; |
| if (this.activatedHandlers != null) { |
| handlerService.deactivateHandlers(this.activatedHandlers); |
| this.activatedHandlers= null; |
| } |
| } |
| } |
| |
| } |