blob: 362cd29891f7db67437e1f2d3901f5b8b8b2c674 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654
******************************************************************************/
package org.eclipse.ui.internal.e4.compatibility;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.INullSelectionListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.internal.E4PartWrapper;
import org.eclipse.ui.internal.WorkbenchPage;
public class SelectionService implements ISelectionChangedListener, ISelectionService {
@Inject
private IEclipseContext context;
@Inject
private MApplication application;
private ESelectionService selectionService;
@Inject
@Optional
@Named("org.eclipse.ui.IWorkbenchPage")
private WorkbenchPage page;
private IWorkbenchPart activePart;
private ListenerList<ISelectionListener> listeners = new ListenerList<>();
private ListenerList<ISelectionListener> postSelectionListeners = new ListenerList<>();
private Map<String, Set<ISelectionListener>> targetedListeners = new HashMap<>();
private Map<String, Set<ISelectionListener>> targetedPostSelectionListeners = new HashMap<>();
private org.eclipse.e4.ui.workbench.modeling.ISelectionListener listener = (part, selection) -> handleSelectionChanged(part, selection, false);
private org.eclipse.e4.ui.workbench.modeling.ISelectionListener targetedListener = (part, selection) -> handleSelectionChanged(part, selection, true);
private org.eclipse.e4.ui.workbench.modeling.ISelectionListener postListener = (part, selection) -> handlePostSelectionChanged(part, selection, false);
private org.eclipse.e4.ui.workbench.modeling.ISelectionListener targetedPostListener = (part, selection) -> handlePostSelectionChanged(part, selection, true);
private void handleSelectionChanged(MPart part, Object selection, boolean targeted) {
selection = createCompatibilitySelection(selection);
context.set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
IEclipseContext applicationContext = application.getContext();
if (applicationContext.getActiveChild() == context) {
application.getContext().set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
}
Object client = part.getObject();
if (client instanceof CompatibilityPart) {
IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart();
if (targeted) {
notifyListeners(workbenchPart, (ISelection) selection, part.getElementId(),
targetedListeners);
} else {
notifyListeners(workbenchPart, (ISelection) selection, listeners);
}
} else if (client != null) {
if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) {
IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData()
.get(E4PartWrapper.E4_WRAPPER_KEY);
if (targeted) {
notifyListeners(workbenchPart, (ISelection) selection, part.getElementId(), targetedListeners);
} else {
notifyListeners(workbenchPart, (ISelection) selection, listeners);
}
}
}
}
private void handlePostSelectionChanged(MPart part, Object selection, boolean targeted) {
selection = createCompatibilitySelection(selection);
Object client = part.getObject();
if (client instanceof CompatibilityPart) {
IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart();
if (targeted) {
notifyListeners(workbenchPart, (ISelection) selection, part.getElementId(),
targetedPostSelectionListeners);
} else {
notifyListeners(workbenchPart, (ISelection) selection, postSelectionListeners);
}
} else if (client != null) {
if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) {
IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData()
.get(E4PartWrapper.E4_WRAPPER_KEY);
if (targeted) {
notifyListeners(workbenchPart, (ISelection) selection, part.getElementId(),
targetedPostSelectionListeners);
} else {
notifyListeners(workbenchPart, (ISelection) selection, postSelectionListeners);
}
}
}
}
private static ISelection createCompatibilitySelection(Object selection) {
if (selection instanceof ISelection) {
return (ISelection) selection;
}
return selection == null ? StructuredSelection.EMPTY : new StructuredSelection(
selection);
}
/**
* Updates the selection of the workbench window with that of the active
* part's.
*
* @param activePart
* the currently active part
*/
public void updateSelection(IWorkbenchPart activePart) {
if (activePart != null) {
ISelectionProvider selectionProvider = activePart.getSite().getSelectionProvider();
if (selectionProvider != null) {
ISelection selection = selectionProvider.getSelection();
context.set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
IEclipseContext applicationContext = application.getContext();
if (applicationContext.getActiveChild() == context) {
application.getContext().set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
}
}
}
}
/**
* Notifies selection listeners about selection change caused by active part
* change.
*
* @param activePart
* the currently active part
*/
public void notifyListeners(IWorkbenchPart activePart) {
if (activePart != null) {
ISelectionProvider selectionProvider = activePart.getSite().getSelectionProvider();
if (selectionProvider != null) {
ISelection selection = selectionProvider.getSelection();
notifyListeners(activePart, selection, listeners);
notifyListeners(activePart, selection, activePart.getSite().getId(), targetedListeners);
notifyListeners(activePart, selection, postSelectionListeners);
notifyListeners(activePart, selection, activePart.getSite().getId(), targetedPostSelectionListeners);
}
}
}
@Inject
void setPart(@Optional @Named(IServiceConstants.ACTIVE_PART) final MPart part) {
activePart = null;
if (part != null) {
Object client = part.getObject();
if (client instanceof CompatibilityPart) {
IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart();
activePart = workbenchPart;
} else if (client != null) {
if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) {
activePart = (IWorkbenchPart) part.getTransientData().get(
E4PartWrapper.E4_WRAPPER_KEY);
}
}
}
}
@Inject
void setSelectionService(@Optional ESelectionService selectionService) {
if (this.selectionService != null) {
this.selectionService.removeSelectionListener(listener);
for (String partId : targetedListeners.keySet()) {
this.selectionService.removeSelectionListener(partId, targetedListener);
}
this.selectionService.removePostSelectionListener(postListener);
for (String partId : targetedPostSelectionListeners.keySet()) {
this.selectionService.removePostSelectionListener(partId, targetedPostListener);
}
}
if (selectionService != null) {
selectionService.addSelectionListener(listener);
for (String partId : targetedListeners.keySet()) {
selectionService.addSelectionListener(partId, targetedListener);
}
selectionService.addPostSelectionListener(postListener);
for (String partId : targetedPostSelectionListeners.keySet()) {
selectionService.addPostSelectionListener(partId, targetedPostListener);
}
this.selectionService = selectionService;
}
}
@PreDestroy
public void dispose() {
setSelectionService(null);
selectionService = null;
listeners.clear();
postSelectionListeners.clear();
targetedListeners.clear();
targetedPostSelectionListeners.clear();
}
private void notifyListeners(IWorkbenchPart workbenchPart, ISelection selection,
ListenerList<ISelectionListener> listenerList) {
for (ISelectionListener listener : listenerList) {
if (selection != null || listener instanceof INullSelectionListener) {
listener.selectionChanged(workbenchPart, selection);
}
}
}
private void notifyListeners(IWorkbenchPart workbenchPart, ISelection selection, String id,
Map<String, Set<ISelectionListener>> listenerMap) {
if (id != null) {
Set<ISelectionListener> listeners = listenerMap.get(id);
if (listeners != null) {
for (ISelectionListener listener : listeners) {
if (selection != null || listener instanceof INullSelectionListener) {
listener.selectionChanged(workbenchPart, selection);
}
}
}
}
}
@Override
public void addSelectionListener(ISelectionListener listener) {
listeners.add(listener);
}
@Override
public void addSelectionListener(String partId, ISelectionListener listener) {
Set<ISelectionListener> listeners = targetedListeners.get(partId);
if (listeners == null) {
listeners = new HashSet<>();
targetedListeners.put(partId, listeners);
}
if (listeners.size() == 0 && selectionService != null) {
selectionService.addSelectionListener(partId, this.targetedListener);
}
listeners.add(listener);
}
@Override
public void addPostSelectionListener(ISelectionListener listener) {
postSelectionListeners.add(listener);
}
@Override
public void addPostSelectionListener(String partId, ISelectionListener listener) {
Set<ISelectionListener> listeners = targetedPostSelectionListeners.get(partId);
if (listeners == null) {
listeners = new HashSet<>();
targetedPostSelectionListeners.put(partId, listeners);
}
if (listeners.size() == 0 && selectionService != null) {
selectionService.addPostSelectionListener(partId, targetedPostListener);
}
listeners.add(listener);
}
@Override
public ISelection getSelection() {
if (activePart != null) {
// get the selection from the active part
ISelectionProvider selectionProvider = activePart.getSite().getSelectionProvider();
return selectionProvider == null ? null : selectionProvider.getSelection();
}
Object selection = selectionService.getSelection();
if (selection == null || selection instanceof ISelection) {
return (ISelection) selection;
}
return new StructuredSelection(selection);
}
@Override
public ISelection getSelection(String partId) {
Object selection = selectionService.getSelection(partId);
if (selection == null || selection instanceof ISelection) {
return (ISelection) selection;
}
return new StructuredSelection(selection);
}
@Override
public void removeSelectionListener(ISelectionListener listener) {
listeners.remove(listener);
}
@Override
public void removeSelectionListener(String partId, ISelectionListener listener) {
Set<ISelectionListener> listeners = targetedListeners.get(partId);
if (listeners != null) {
listeners.remove(listener);
if (listeners.size() == 0 && selectionService != null) {
selectionService.removeSelectionListener(partId, this.targetedListener);
}
}
}
@Override
public void removePostSelectionListener(ISelectionListener listener) {
postSelectionListeners.remove(listener);
}
@Override
public void removePostSelectionListener(String partId, ISelectionListener listener) {
Set<ISelectionListener> listeners = targetedPostSelectionListeners.get(partId);
if (listeners != null) {
listeners.remove(listener);
if (listeners.size() == 0 && selectionService != null) {
selectionService.removePostSelectionListener(partId, targetedPostListener);
}
}
}
@Override
public void selectionChanged(SelectionChangedEvent e) {
MPart part = page.findPart(activePart);
ESelectionService selectionService = part.getContext().get(ESelectionService.class);
selectionService.setSelection(e.getSelection());
}
}