blob: cec9331ffad9ec37d8ef469dcf1820148485b1ae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Remain BV, Netherlands
*
* 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:
* Wim Jongman - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.function.Predicate;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.INullSelectionListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.SelectionListenerFactory;
import org.eclipse.ui.SelectionListenerFactory.ISelectionModel;
/**
* An intermediate selection listener that filters selection change events based
* on one or more predicates and forwards it to the functional selection
* listener.
*
* Instances of this class can be obtained via the
* {@link SelectionListenerFactory} class.
*/
public class PartSelectionListener implements ISelectionListener, INullSelectionListener {
private final ISelectionListener fCallbackListener;
private final IWorkbenchPart fTargetPart;
private Predicate<ISelectionModel> fPredicate;
private IWorkbenchPart fCurrentSelectionPart;
private IWorkbenchPart fLastDeliveredPart;
private ISelection fCurrentSelection;
private ISelection fLastDeliveredSelection;
/**
* Constructs the intermediate selection listener to filter selections before
* they are passed on the the callback listener.
*
* @param part the part which may not be null.
* @param callbackListener the callback listener which may not be null.
* @param predicate the predicate which may not be null.
*/
public PartSelectionListener(IWorkbenchPart part, ISelectionListener callbackListener,
Predicate<ISelectionModel> predicate) {
Assert.isNotNull(part);
Assert.isNotNull(callbackListener);
Assert.isNotNull(predicate);
fTargetPart = part;
fCallbackListener = callbackListener;
fPredicate = predicate;
addPartListener(part);
}
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
saveCurrentSelection(part, selection);
if (fPredicate.test(getModel())) {
doCallback(part, selection);
}
}
private void doCallback(IWorkbenchPart part, ISelection selection) {
if (selection == null && (fCallbackListener instanceof INullSelectionListener)) {
fCallbackListener.selectionChanged(part, selection);
saveLastDelivered(part, selection);
} else if (selection != null) {
fCallbackListener.selectionChanged(part, selection);
saveLastDelivered(part, selection);
}
}
/**
* @return
*/
private ISelectionModel getModel() {
return new ISelectionModel() {
@Override
public IWorkbenchPart getTargetPart() {
return fTargetPart;
}
@Override
public IWorkbenchPart getLastDeliveredSelectionPart() {
return fLastDeliveredPart;
}
@Override
public ISelection getLastDeliveredSelection() {
return fLastDeliveredSelection;
}
@Override
public IWorkbenchPart getCurrentSelectionPart() {
return fCurrentSelectionPart;
}
@Override
public ISelection getCurrentSelection() {
return fCurrentSelection;
}
@Override
public boolean isTargetPartVisible() {
return fTargetPart.getSite().getPage().isPartVisible(fTargetPart);
}
@Override
public boolean isSelectionPartVisible() {
return getCurrentSelectionPart() != null
&& getCurrentSelectionPart().getSite().getPage().isPartVisible(getCurrentSelectionPart());
}
};
}
private void addPartListener(IWorkbenchPart part) {
IPartService partService = part.getSite().getService(IPartService.class);
partService.addPartListener(new IPartListener2() {
@Override
public void partVisible(IWorkbenchPartReference partRef) {
if (partRef.getPart(false) == fTargetPart) {
selectionChanged(fCurrentSelectionPart, fCurrentSelection);
}
}
@Override
public void partClosed(IWorkbenchPartReference partRef) {
if (partRef.getPart(false) == fTargetPart) {
fTargetPart.getSite().getPage().removeSelectionListener(PartSelectionListener.this);
}
}
});
}
private void saveCurrentSelection(IWorkbenchPart part, ISelection selection) {
fCurrentSelectionPart = part;
fCurrentSelection = selection;
}
private void saveLastDelivered(IWorkbenchPart part, ISelection selection) {
fLastDeliveredPart = part;
fLastDeliveredSelection = selection;
}
/**
* And-chains this predicate to the already existing predicate. Nothing happens
* if the passed predicate is null.
*
* @param predicate the non-null predicate to and-chain to the existing
* predicate
* @return this
*/
public PartSelectionListener addPredicate(Predicate<ISelectionModel> predicate) {
if (predicate != null) {
fPredicate = fPredicate.and(predicate);
}
return this;
}
}