blob: 3734452bcd224104163b6679f16b823a03c42b4d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 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();
}
}