blob: 590614482b85921927f0ac1c0fab502d3bbca5e0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.ui.internal;
import java.util.Hashtable;
import org.eclipse.core.runtime.ListenerList;
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.SelectionChangedEvent;
import org.eclipse.ui.INullSelectionListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPart;
/**
* Abstract selection service.
*/
public abstract class AbstractSelectionService implements ISelectionService {
/**
* The list of selection listeners (not per-part).
*/
private ListenerList listeners = new ListenerList();
/**
* The list of post selection listeners (not per-part).
*/
private ListenerList postListeners = new ListenerList();
/**
* The currently active part.
*/
private IWorkbenchPart activePart;
/**
* The active part's selection provider, remembered in case the part
* replaces its selection provider after we hooked a listener.
*/
private ISelectionProvider activeProvider;
/**
* Map from part id (String) to per-part tracker (AbstractPartSelectionTracker).
*/
private Hashtable perPartTrackers;
/**
* The JFace selection listener to hook on the active part's selection provider.
*/
private ISelectionChangedListener selListener = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
fireSelection(activePart, event.getSelection());
}
};
/**
* The JFace post selection listener to hook on the active part's selection provider.
*/
private ISelectionChangedListener postSelListener = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
firePostSelection(activePart, event.getSelection());
}
};
/**
* Creates a new SelectionService.
*/
protected AbstractSelectionService() {
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void addSelectionListener(ISelectionListener l) {
listeners.add(l);
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void addSelectionListener(String partId, ISelectionListener listener) {
getPerPartTracker(partId).addSelectionListener(listener);
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void addPostSelectionListener(ISelectionListener l) {
postListeners.add(l);
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void addPostSelectionListener(String partId,
ISelectionListener listener) {
getPerPartTracker(partId).addPostSelectionListener(listener);
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void removeSelectionListener(ISelectionListener l) {
listeners.remove(l);
}
/*
* (non-Javadoc)
* Method declared on ISelectionListener.
*/
public void removePostSelectionListener(String partId,
ISelectionListener listener) {
getPerPartTracker(partId).removePostSelectionListener(listener);
}
/* (non-Javadoc)
* Method declared on ISelectionService.
*/
public void removePostSelectionListener(ISelectionListener l) {
postListeners.remove(l);
}
/*
* (non-Javadoc)
* Method declared on ISelectionListener.
*/
public void removeSelectionListener(String partId,
ISelectionListener listener) {
getPerPartTracker(partId).removeSelectionListener(listener);
}
/**
* Fires a selection event to the given listeners.
*
* @param part the part or <code>null</code> if no active part
* @param sel the selection or <code>null</code> if no active selection
*/
protected void fireSelection(final IWorkbenchPart part, final ISelection sel) {
Object[] array = listeners.getListeners();
for (int i = 0; i < array.length; i++) {
final ISelectionListener l = (ISelectionListener) array[i];
if ((part != null && sel != null)
|| l instanceof INullSelectionListener) {
try {
l.selectionChanged(part, sel);
} catch (Exception e) {
WorkbenchPlugin.log(e);
}
}
}
}
/**
* Fires a selection event to the given listeners.
*
* @param part the part or <code>null</code> if no active part
* @param sel the selection or <code>null</code> if no active selection
*/
protected void firePostSelection(final IWorkbenchPart part,
final ISelection sel) {
Object[] array = postListeners.getListeners();
for (int i = 0; i < array.length; i++) {
final ISelectionListener l = (ISelectionListener) array[i];
if ((part != null && sel != null)
|| l instanceof INullSelectionListener) {
try {
l.selectionChanged(part, sel);
} catch (Exception e) {
WorkbenchPlugin.log(e);
}
}
}
}
/**
* Returns the per-part selection tracker for the given part id.
*
* @param partId part identifier
* @return per-part selection tracker
*/
protected AbstractPartSelectionTracker getPerPartTracker(String partId) {
if (perPartTrackers == null) {
perPartTrackers = new Hashtable(4);
}
AbstractPartSelectionTracker tracker = (AbstractPartSelectionTracker) perPartTrackers
.get(partId);
if (tracker == null) {
tracker = createPartTracker(partId);
perPartTrackers.put(partId, tracker);
}
return tracker;
}
/**
* Creates a new per-part selection tracker for the given part id.
*
* @param partId part identifier
* @return per-part selection tracker
*/
protected abstract AbstractPartSelectionTracker createPartTracker(
String partId);
/**
* Returns the selection.
*/
public ISelection getSelection() {
if (activeProvider != null) {
return activeProvider.getSelection();
} else {
return null;
}
}
/*
* @see ISelectionService#getSelection(String)
*/
public ISelection getSelection(String partId) {
return getPerPartTracker(partId).getSelection();
}
/**
* Sets the current-active part (or null if none)
*
* @since 3.1
*
* @param newPart the new active part (or null if none)
*/
public void setActivePart(IWorkbenchPart newPart) {
// Optimize.
if (newPart == activePart) {
return;
}
ISelectionProvider selectionProvider = null;
if (newPart != null) {
selectionProvider = newPart.getSite().getSelectionProvider();
if (selectionProvider == null) {
newPart = null;
}
}
if (newPart == activePart) {
return;
}
if (activePart != null) {
if (activeProvider != null) {
activeProvider.removeSelectionChangedListener(selListener);
if (activeProvider instanceof IPostSelectionProvider) {
((IPostSelectionProvider) activeProvider)
.removePostSelectionChangedListener(postSelListener);
} else {
activeProvider
.removeSelectionChangedListener(postSelListener);
}
activeProvider = null;
}
activePart = null;
}
activePart = newPart;
if (newPart != null) {
activeProvider = selectionProvider;
// Fire an event if there's an active provider
activeProvider.addSelectionChangedListener(selListener);
ISelection sel = activeProvider.getSelection();
fireSelection(newPart, sel);
if (activeProvider instanceof IPostSelectionProvider) {
((IPostSelectionProvider) activeProvider)
.addPostSelectionChangedListener(postSelListener);
} else {
activeProvider.addSelectionChangedListener(postSelListener);
}
firePostSelection(newPart, sel);
} else {
fireSelection(null, null);
firePostSelection(null, null);
}
}
// /**
// * Notifies the listener that a part has been activated.
// */
// public void partActivated(IWorkbenchPart newPart) {
// // Optimize.
// if (newPart == activePart)
// return;
//
// // Unhook selection from the old part.
// reset();
//
// // Update active part.
// activePart = newPart;
//
// // Hook selection on the new part.
// if (activePart != null) {
// activeProvider = activePart.getSite().getSelectionProvider();
// if (activeProvider != null) {
// // Fire an event if there's an active provider
// activeProvider.addSelectionChangedListener(selListener);
// ISelection sel = activeProvider.getSelection();
// fireSelection(newPart, sel);
// if (activeProvider instanceof IPostSelectionProvider)
// ((IPostSelectionProvider) activeProvider)
// .addPostSelectionChangedListener(postSelListener);
// else
// activeProvider.addSelectionChangedListener(postSelListener);
// firePostSelection(newPart, sel);
// } else {
// //Reset active part. activeProvider may not be null next time this method is called.
// activePart = null;
// }
// }
// // No need to fire an event if no active provider, since this was done in reset()
// }
//
// /**
// * Notifies the listener that a part has been brought to the front.
// */
// public void partBroughtToTop(IWorkbenchPart newPart) {
// // do nothing, the active part has not changed,
// // so the selection is unaffected
// }
//
// /**
// * Notifies the listener that a part has been closed
// */
// public void partClosed(IWorkbenchPart part) {
// // Unhook selection from the part.
// if (part == activePart) {
// reset();
// }
// }
//
// /**
// * Notifies the listener that a part has been deactivated.
// */
// public void partDeactivated(IWorkbenchPart part) {
// // Unhook selection from the part.
// if (part == activePart) {
// reset();
// }
// }
//
// /**
// * Notifies the listener that a part has been opened.
// */
// public void partOpened(IWorkbenchPart part) {
// // Wait for activation.
// }
//
// /**
// * Notifies the listener that a part has been opened.
// */
// public void partInputChanged(IWorkbenchPart part) {
// // 36501 - only process if part is active
// if (activePart == part) {
// reset();
// partActivated(part);
// }
// }
//
// /**
// * Resets the service. The active part and selection provider are
// * dereferenced.
// */
// public void reset() {
// if (activePart != null) {
// fireSelection(null, null);
// firePostSelection(null, null);
// if (activeProvider != null) {
// activeProvider.removeSelectionChangedListener(selListener);
// if (activeProvider instanceof IPostSelectionProvider)
// ((IPostSelectionProvider) activeProvider)
// .removePostSelectionChangedListener(postSelListener);
// else
// activeProvider
// .removeSelectionChangedListener(postSelListener);
// activeProvider = null;
// }
// activePart = null;
// }
// }
}