/*******************************************************************************
* Copyright (c) 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.gef;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.widgets.Control;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
/**
* Manages a viewer's selection model. Selection management includes representing a form
* of selection which is available to clients of a viewer as an ISelection. It also
* includes managing the notion of focus, which is closely tied to the current selection.
* The selection manager provides the mechanism for modifying the selection and any
* validation.
* <P>
* WARNING: Subclassing this class is considered experimental at this point.
* @since 3.2
*/
public class SelectionManager {
private EditPart focusPart;
private Runnable notifier;
private List selection;
private EditPartViewer viewer;
/**
* Default Constructor
* @since 3.2
*/
protected SelectionManager() { }
/**
* Creates the default implementation for a selection manager.
* @return the default selection manager
* @since 3.2
*/
public static SelectionManager createDefault() {
return new SelectionManager();
}
/**
* Appends the <code>EditPart</code> to the current selection. The EditPart becomes the
* new primary selection. Fires selection changed to all{@link
* org.eclipse.jface.viewers.ISelectionChangedListener}s.
* @param editpart the EditPart to append
* @since 3.2
*/
public void appendSelection(EditPart editpart) {
if (editpart != getFocus())
viewer.setFocus(null);
if (!selection.isEmpty()) {
EditPart primary = (EditPart)selection.get(selection.size() - 1);
primary.setSelected(EditPart.SELECTED);
}
// if the editpart is already in the list, re-order it to be the last one
selection.remove(editpart);
selection.add(editpart);
editpart.setSelected(EditPart.SELECTED_PRIMARY);
fireSelectionChanged();
}
/**
* Removes the <code>EditPart</code> from the current selection.
* @param editpart the editpart
* @since 3.2
*/
public void deselect(EditPart editpart) {
editpart.setSelected(EditPart.SELECTED_NONE);
selection.remove(editpart);
if (!selection.isEmpty()) {
EditPart primary = (EditPart)selection.get(selection.size() - 1);
primary.setSelected(EditPart.SELECTED_PRIMARY);
}
fireSelectionChanged();
}
/**
* Deselects everything.
* @since 3.2
*/
public void deselectAll() {
EditPart part;
setFocus(null);
for (int i = 0; i < selection.size(); i++) {
part = (EditPart)selection.get(i);
part.setSelected(EditPart.SELECTED_NONE);
}
selection.clear();
fireSelectionChanged();
}
/**
* Causes the viewer to fire selection changed notification to all listeners.
* @since 3.2
*/
protected final void fireSelectionChanged() {
notifier.run();
}
/**
* Returns the focus editpart.
* @return the focus editpart
* @since 3.2
*/
protected EditPart getFocus() {
return focusPart;
}
/**
* Returns the current selection.
* @return the selection
* @since 3.2
*/
public ISelection getSelection() {
if (selection.isEmpty() && viewer.getContents() != null)
return new StructuredSelection(viewer.getContents());
return new StructuredSelection(selection);
}
/**
* Returns <code>null</code> or the viewer whose selection is managed.
* @return <code>null</code> or the viewer
* @since 3.2
*/
protected EditPartViewer getViewer() {
return viewer;
}
/**
* For internal use only. This API is subject to change.
* @param control the control
* @since 3.2
*/
public void internalHookControl(Control control) { }
/**
* For internal use only. This API is subject to change.
* @since 3.2
*/
public void internalUninstall() { }
/**
* Provides a hook for when the viewer has been set.
* @param viewer the viewer.
* @since 3.2
*/
protected void hookViewer(EditPartViewer viewer) { }
/**
* For internal use only.
* @param viewer viewer
* @param selection selection
* @param notifier notifier
* @since 3.2
*/
public void internalInitialize(EditPartViewer viewer, List selection, Runnable notifier) {
this.viewer = viewer;
this.selection = selection;
this.notifier = notifier;
hookViewer(viewer);
}
/**
* Sets the focus part.
* @param part the focus part
* @since 3.2
*/
public void setFocus(EditPart part) {
if (focusPart == part)
return;
if (focusPart != null)
focusPart.setFocus(false);
focusPart = part;
if (focusPart != null)
focusPart.setFocus(true);
}
/**
* Sets the selection.
* @param newSelection the new selection
* @since 3.2
*/
public void setSelection(ISelection newSelection) {
if (!(newSelection instanceof IStructuredSelection))
return;
List orderedSelection = ((IStructuredSelection)newSelection).toList();
// Convert to HashSet to optimize performance.
Collection hashset = new HashSet(orderedSelection);
setFocus(null);
for (int i = 0; i < selection.size(); i++) {
EditPart part = (EditPart)selection.get(i);
if (!hashset.contains(part))
part.setSelected(EditPart.SELECTED_NONE);
}
selection.clear();
if (!orderedSelection.isEmpty()) {
Iterator itr = orderedSelection.iterator();
while (true) {
EditPart part = (EditPart)itr.next();
selection.add(part);
if (!itr.hasNext()) {
part.setSelected(EditPart.SELECTED_PRIMARY);
break;
}
part.setSelected(EditPart.SELECTED);
}
}
fireSelectionChanged();
}
}