blob: 5ec55d0944ca329a28de6816a45597e897feddd4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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
*******************************************************************************/
package org.eclipse.bpel.common.ui.tray;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
/**
* @author IBM, Original Contribution.
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date Jun 5, 2007
*
*/
public class MultiViewerSelectionProvider implements ISelectionProvider, IPostSelectionProvider {
static ISelectionChangedListener[] EMPTY_LISTENERS = {};
protected List<EditPartViewer> viewers = new ArrayList<EditPartViewer>();
protected List<ISelectionChangedListener> listeners = new ArrayList<ISelectionChangedListener>();
protected List<ISelectionChangedListener> postListeners = new ArrayList<ISelectionChangedListener>();
protected boolean changingSelection = false;
protected boolean broadcastingSelectionChange = false;
protected IStructuredSelection cachedSelection;
/**
* Brand new shiny MultiViewerSelectionProvider
*/
public MultiViewerSelectionProvider() {
// Empty constructor
}
/**
* Brand new shiny MultiViewerSelectionProvider
*
* @param viewer
*/
public MultiViewerSelectionProvider(EditPartViewer viewer) {
addViewer(viewer);
}
/**
* @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addSelectionChangedListener(ISelectionChangedListener listener) {
listeners.add(listener);
}
/**
* @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
listeners.remove(listener);
}
/**
* @see org.eclipse.jface.viewers.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
postListeners.add(listener);
}
/**
* @see org.eclipse.jface.viewers.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
postListeners.remove(listener);
}
/**
* Add the viewer to the list of viewers that are listening for selection changes.
*
* @param viewer
*/
public void addViewer(EditPartViewer viewer) {
viewers.add(viewer);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
if (changingSelection) {
return;
}
setSelection(event.getSelection());
}
});
}
/**
* Get the current selection
*
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
if (cachedSelection == null) {
List<EditPartViewer> result = new ArrayList<EditPartViewer>();
for (EditPartViewer next : viewers) {
result.addAll(next.getSelectedEditParts());
}
cachedSelection = calculateSelection(new StructuredSelection(result));
}
return cachedSelection;
}
/**
* @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
*/
public void setSelection(ISelection selection) {
if (selection instanceof IStructuredSelection == false) {
return;
}
cachedSelection = calculateSelection((IStructuredSelection) selection);
internalSetSelection(cachedSelection);
fireSelectionChanged(this, cachedSelection);
}
protected void fireSelectionChanged(ISelectionProvider provider, ISelection selection) {
SelectionChangedEvent event = new SelectionChangedEvent(provider, selection);
try {
broadcastingSelectionChange = true;
for (ISelectionChangedListener listener : this.listeners.toArray(EMPTY_LISTENERS)) {
listener.selectionChanged(event);
}
for (ISelectionChangedListener listener : this.postListeners.toArray(EMPTY_LISTENERS)) {
listener.selectionChanged(event);
}
} finally {
broadcastingSelectionChange = false;
}
}
protected IStructuredSelection calculateSelection(IStructuredSelection baseSelection) {
List<EditPart> result = new ArrayList<EditPart>();
for (EditPartViewer viewer : viewers) {
Map<Object, EditPart> registry = viewer.getEditPartRegistry();
for (Object n : baseSelection.toArray()) {
EditPart part = (EditPart) n;
Object model = part.getModel();
EditPart viewerEditPart = registry.get(model);
if (viewerEditPart != null) {
result.add(viewerEditPart);
}
}
}
if (result.isEmpty()) {
return StructuredSelection.EMPTY;
}
return new StructuredSelection(result);
}
// TODO: try getting rid of the isEmpty() check here and in the same
// place in AdaptingSelectionProvider.
// Set selection to each of the viewers and make sure we ignore callbacks
protected void internalSetSelection(IStructuredSelection selection) {
if (selection == null || selection.isEmpty()) {
return;
}
try {
changingSelection = true;
for (EditPartViewer viewer : viewers) {
Map<Object, EditPart> registry = viewer.getEditPartRegistry();
List<EditPart> newList = new ArrayList<EditPart>();
Set<EditPart> newSet = new HashSet<EditPart>();
for (Object n : selection.toArray()) {
EditPart part = (EditPart) n;
Object model = part.getModel();
EditPart viewerEditPart = registry.get(model);
if (viewerEditPart != null && newSet.add(viewerEditPart)) {
newList.add(viewerEditPart);
}
}
viewer.setSelection(new StructuredSelection(newList));
}
} finally {
changingSelection = false;
}
}
/**
* Answer true if we are broadcasting a selection change.
*
* @return answer true if we are broadcasting selection change.
*/
public boolean isBroadcastingSelectionChange() {
return broadcastingSelectionChange;
}
}