| /******************************************************************************* |
| * Copyright (c) 2000, 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.ui.parts; |
| |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DragSource; |
| import org.eclipse.swt.dnd.DropTarget; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.resource.LocalResourceManager; |
| import org.eclipse.jface.resource.ResourceManager; |
| import org.eclipse.jface.util.TransferDragSourceListener; |
| import org.eclipse.jface.util.TransferDropTargetListener; |
| 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.draw2d.geometry.Point; |
| |
| import org.eclipse.gef.AccessibleEditPart; |
| import org.eclipse.gef.EditDomain; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.EditPartFactory; |
| import org.eclipse.gef.EditPartViewer; |
| import org.eclipse.gef.KeyHandler; |
| import org.eclipse.gef.RootEditPart; |
| import org.eclipse.gef.SelectionManager; |
| |
| /** |
| * The base implementation for EditPartViewer. |
| * |
| * @author hudsonr |
| */ |
| public abstract class AbstractEditPartViewer implements EditPartViewer { |
| |
| private DisposeListener disposeListener; |
| |
| private SelectionManager selectionModel; |
| |
| /** |
| * The raw list of selected editparts. |
| */ |
| protected final List selection = new ArrayList(); |
| |
| /** |
| * The unmodifiable list of selected editparts. |
| */ |
| protected final List constantSelection = Collections |
| .unmodifiableList(selection); |
| |
| /** |
| * The list of selection listeners. |
| * |
| * @deprecated |
| */ |
| protected List selectionListeners = new ArrayList(1); |
| |
| /** |
| * The editpart specifically set to have focus. Note that if this value is |
| * <code>null</code>, the focus editpart is still implied to be the part |
| * with primary selection. Subclasses should call the accessor: |
| * {@link #getFocusEditPart()} whenever possible. |
| * |
| * @deprecated |
| */ |
| protected EditPart focusPart; |
| |
| private EditPartFactory factory; |
| private Map mapIDToEditPart = new HashMap(); |
| private Map mapVisualToEditPart = new HashMap(); |
| private Map properties; |
| private Control control; |
| private ResourceManager resources; |
| private EditDomain domain; |
| private RootEditPart rootEditPart; |
| private MenuManager contextMenu; |
| |
| private DragSource dragSource; |
| private org.eclipse.gef.dnd.DelegatingDragAdapter dragAdapter = new org.eclipse.gef.dnd.DelegatingDragAdapter(); |
| |
| private DropTarget dropTarget; |
| private org.eclipse.gef.dnd.DelegatingDropAdapter dropAdapter = new org.eclipse.gef.dnd.DelegatingDropAdapter(); |
| |
| private KeyHandler keyHandler; |
| private PropertyChangeSupport changeSupport; |
| |
| /** |
| * Constructs the viewer and calls {@link #init()}. |
| */ |
| public AbstractEditPartViewer() { |
| setSelectionManager(SelectionManager.createDefault()); |
| init(); |
| } |
| |
| /** |
| * @see EditPartViewer#setSelectionManager(SelectionManager) |
| */ |
| public void setSelectionManager(SelectionManager model) { |
| Assert.isNotNull(model); |
| if (selectionModel != null) |
| selectionModel.internalUninstall(); |
| selectionModel = model; |
| model.internalInitialize(this, selection, new Runnable() { |
| public void run() { |
| fireSelectionChanged(); |
| } |
| }); |
| if (getControl() != null) |
| model.internalHookControl(getControl()); |
| } |
| |
| /** |
| * @see EditPartViewer#addDragSourceListener(org.eclipse.gef.dnd.TransferDragSourceListener) |
| */ |
| public void addDragSourceListener( |
| org.eclipse.gef.dnd.TransferDragSourceListener listener) { |
| addDragSourceListener((TransferDragSourceListener) listener); |
| } |
| |
| /** |
| * @see EditPartViewer#addDragSourceListener(TransferDragSourceListener) |
| */ |
| public void addDragSourceListener(TransferDragSourceListener listener) { |
| getDelegatingDragAdapter().addDragSourceListener(listener); |
| refreshDragSourceAdapter(); |
| } |
| |
| /** |
| * @see EditPartViewer#addDropTargetListener(org.eclipse.gef.dnd.TransferDropTargetListener) |
| */ |
| public void addDropTargetListener( |
| org.eclipse.gef.dnd.TransferDropTargetListener listener) { |
| addDropTargetListener((TransferDropTargetListener) listener); |
| } |
| |
| /** |
| * @see EditPartViewer#addDropTargetListener(TransferDropTargetListener) |
| */ |
| public void addDropTargetListener(TransferDropTargetListener listener) { |
| getDelegatingDropAdapter().addDropTargetListener(listener); |
| refreshDropTargetAdapter(); |
| } |
| |
| /** |
| * @see EditPartViewer#addPropertyChangeListener(PropertyChangeListener) |
| */ |
| public void addPropertyChangeListener(PropertyChangeListener listener) { |
| if (changeSupport == null) |
| changeSupport = new PropertyChangeSupport(this); |
| changeSupport.addPropertyChangeListener(listener); |
| } |
| |
| /** |
| * @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener) |
| */ |
| public void addSelectionChangedListener(ISelectionChangedListener listener) { |
| selectionListeners.add(listener); |
| } |
| |
| /** |
| * @see EditPartViewer#appendSelection(EditPart) |
| */ |
| public void appendSelection(EditPart editpart) { |
| selectionModel.appendSelection(editpart); |
| } |
| |
| /** |
| * @see EditPartViewer#createControl(Composite) |
| */ |
| public abstract Control createControl(Composite parent); |
| |
| /** |
| * @see EditPartViewer#deselect(EditPart) |
| */ |
| public void deselect(EditPart editpart) { |
| selectionModel.deselect(editpart); |
| } |
| |
| /** |
| * @see EditPartViewer#deselectAll() |
| */ |
| public void deselectAll() { |
| selectionModel.deselectAll(); |
| } |
| |
| /** |
| * Called if and when the <code>Control</code> is disposed. Subclasses may |
| * extend this method to perform additional cleanup. |
| * |
| * @param e |
| * the disposeevent |
| */ |
| protected void handleDispose(DisposeEvent e) { |
| if (resources != null) |
| resources.dispose(); |
| setControl(null); |
| } |
| |
| /** |
| * @see EditPartViewer#findObjectAt(Point) |
| */ |
| public final EditPart findObjectAt(Point pt) { |
| return findObjectAtExcluding(pt, Collections.EMPTY_SET); |
| } |
| |
| /** |
| * @see EditPartViewer#findObjectAtExcluding(Point, Collection) |
| */ |
| public final EditPart findObjectAtExcluding(Point pt, Collection exclude) { |
| return findObjectAtExcluding(pt, exclude, null); |
| } |
| |
| /** |
| * Fires selection changed to the registered listeners at the time called. |
| */ |
| protected void fireSelectionChanged() { |
| Object listeners[] = selectionListeners.toArray(); |
| SelectionChangedEvent event = new SelectionChangedEvent(this, |
| getSelection()); |
| for (int i = 0; i < listeners.length; i++) |
| ((ISelectionChangedListener) listeners[i]).selectionChanged(event); |
| } |
| |
| /** |
| * @see EditPartViewer#flush() |
| */ |
| public void flush() { |
| } |
| |
| /** |
| * @see EditPartViewer#getContextMenu() |
| */ |
| public MenuManager getContextMenu() { |
| return contextMenu; |
| } |
| |
| /** |
| * @see EditPartViewer#getContents() |
| */ |
| public EditPart getContents() { |
| return getRootEditPart().getContents(); |
| } |
| |
| /** |
| * @see EditPartViewer#getControl() |
| */ |
| public Control getControl() { |
| return control; |
| } |
| |
| /** |
| * Returns <code>null</code> or the DelegatingDragAdapater. The adapter is |
| * created automatically when |
| * {@link #addDragSourceListener(TransferDragSourceListener)} is called. |
| * |
| * @return <code>null</code> or the adapter |
| */ |
| protected org.eclipse.gef.dnd.DelegatingDragAdapter getDelegatingDragAdapter() { |
| return dragAdapter; |
| } |
| |
| /** |
| * Returns <code>null</code> or the DelegatingDropAdapater. The adapter is |
| * created automatically when |
| * {@link #addDropTargetListener(TransferDropTargetListener)} is called. |
| * |
| * @return <code>null</code> or the adapter |
| */ |
| protected org.eclipse.gef.dnd.DelegatingDropAdapter getDelegatingDropAdapter() { |
| return dropAdapter; |
| } |
| |
| /** |
| * Returns <code>null</code> or the DragSource. The drag source is created |
| * automatically when |
| * {@link #addDragSourceListener(TransferDragSourceListener)} is called. |
| * |
| * @return <code>null</code> or the drag source |
| */ |
| protected DragSource getDragSource() { |
| return dragSource; |
| } |
| |
| /** |
| * Returns <code>null</code> or the DropTarget. The drop target is created |
| * automatically when |
| * {@link #addDropTargetListener(TransferDropTargetListener)} is called. |
| * |
| * @return <code>null</code> or the drop target |
| */ |
| protected DropTarget getDropTarget() { |
| return dropTarget; |
| } |
| |
| /** |
| * @see EditPartViewer#getEditDomain() |
| */ |
| public EditDomain getEditDomain() { |
| return domain; |
| } |
| |
| /** |
| * @see EditPartViewer#getEditPartFactory() |
| */ |
| public EditPartFactory getEditPartFactory() { |
| return factory; |
| } |
| |
| /** |
| * @see EditPartViewer#getEditPartRegistry() |
| */ |
| public Map getEditPartRegistry() { |
| return mapIDToEditPart; |
| } |
| |
| /** |
| * @see EditPartViewer#getFocusEditPart() |
| */ |
| public EditPart getFocusEditPart() { |
| if (focusPart != null) |
| return focusPart; |
| if (getSelectedEditParts().isEmpty()) { |
| if (getContents() != null) |
| return getContents(); |
| else |
| return getRootEditPart(); |
| } |
| List selection = getSelectedEditParts(); |
| return (EditPart) selection.get(selection.size() - 1); |
| } |
| |
| /** |
| * @see EditPartViewer#getKeyHandler() |
| */ |
| public KeyHandler getKeyHandler() { |
| return keyHandler; |
| } |
| |
| /** |
| * @see EditPartViewer#getProperty(String) |
| */ |
| public Object getProperty(String key) { |
| if (properties != null) |
| return properties.get(key); |
| return null; |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPartViewer#getResourceManager() |
| */ |
| public ResourceManager getResourceManager() { |
| if (resources != null) |
| return resources; |
| Assert.isNotNull(getControl()); |
| resources = new LocalResourceManager(JFaceResources.getResources()); |
| return resources; |
| } |
| |
| /** |
| * @see EditPartViewer#getRootEditPart() |
| */ |
| public RootEditPart getRootEditPart() { |
| return rootEditPart; |
| } |
| |
| /** |
| * @see EditPartViewer#getSelectedEditParts() |
| */ |
| public List getSelectedEditParts() { |
| return constantSelection; |
| } |
| |
| /** |
| * Returns an ISelection containing a list of one or more EditPart. Whenever |
| * {@link #getSelectedEditParts()} returns an empty list, the |
| * <i>contents</i> editpart ({@link #getContents()}) is returned as the |
| * current selection. |
| * |
| * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() |
| */ |
| public ISelection getSelection() { |
| return selectionModel.getSelection(); |
| } |
| |
| /** |
| * @see EditPartViewer#getSelectionManager() |
| */ |
| public SelectionManager getSelectionManager() { |
| return selectionModel; |
| } |
| |
| /** |
| * @see EditPartViewer#getVisualPartMap() |
| */ |
| public Map getVisualPartMap() { |
| return mapVisualToEditPart; |
| } |
| |
| /** |
| * Called once the control has been set. |
| * |
| * @see #unhookControl() |
| */ |
| protected void hookControl() { |
| Control control = getControl(); |
| Assert.isTrue(control != null); |
| getSelectionManager().internalHookControl(control); |
| control.addDisposeListener(disposeListener = new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| handleDispose(e); |
| } |
| }); |
| if (getRootEditPart() != null) |
| getRootEditPart().activate(); |
| refreshDragSourceAdapter(); |
| refreshDropTargetAdapter(); |
| if (contextMenu != null) |
| control.setMenu(contextMenu.createContextMenu(getControl())); |
| } |
| |
| /** |
| * Called whenever the {@link #getDragSource() drag source} is automatically |
| * created. |
| */ |
| protected void hookDragSource() { |
| dragSource.addDragListener(getDelegatingDragAdapter()); |
| } |
| |
| /** |
| * Called whenever the {@link #getDropTarget() drop target} is automatically |
| * created. |
| */ |
| protected void hookDropTarget() { |
| getDropTarget().addDropListener(getDelegatingDropAdapter()); |
| } |
| |
| /** |
| * Called from the constructor. Subclasses may extend this method. |
| */ |
| protected void init() { |
| } |
| |
| private void primDeselectAll() { |
| EditPart part; |
| List list = primGetSelectedEditParts(); |
| for (int i = 0; i < list.size(); i++) { |
| part = (EditPart) list.get(i); |
| part.setSelected(EditPart.SELECTED_NONE); |
| } |
| list.clear(); |
| } |
| |
| /** |
| * Returns the modifiable List of selected EditParts. |
| * |
| * @return the internal list of selected editparts |
| */ |
| protected List primGetSelectedEditParts() { |
| return selection; |
| } |
| |
| /** |
| * Creates or disposes a DragSource as needed, and sets the supported |
| * transfer types. Clients should not need to call or override this method. |
| */ |
| protected void refreshDragSourceAdapter() { |
| if (getControl() == null) |
| return; |
| if (getDelegatingDragAdapter().isEmpty()) |
| setDragSource(null); |
| else { |
| if (getDragSource() == null) |
| setDragSource(new DragSource(getControl(), DND.DROP_MOVE |
| | DND.DROP_COPY | DND.DROP_LINK)); |
| getDragSource().setTransfer( |
| getDelegatingDragAdapter().getTransfers()); |
| } |
| } |
| |
| /** |
| * Creates or disposes a DropTarget as needed, and sets the supported |
| * transfer types. Clients should not need to call or override this method. |
| */ |
| protected void refreshDropTargetAdapter() { |
| if (getControl() == null) |
| return; |
| if (getDelegatingDropAdapter().isEmpty()) |
| setDropTarget(null); |
| else { |
| if (getDropTarget() == null) |
| setDropTarget(new DropTarget(getControl(), DND.DROP_MOVE |
| | DND.DROP_COPY | DND.DROP_LINK)); |
| getDropTarget().setTransfer( |
| getDelegatingDropAdapter().getTransfers()); |
| } |
| } |
| |
| /** |
| * @see EditPartViewer#registerAccessibleEditPart(AccessibleEditPart) |
| */ |
| public void registerAccessibleEditPart(AccessibleEditPart acc) { |
| } |
| |
| /** |
| * @see EditPartViewer#removeDragSourceListener(org.eclipse.gef.dnd.TransferDragSourceListener) |
| * @deprecated |
| */ |
| public void removeDragSourceListener( |
| org.eclipse.gef.dnd.TransferDragSourceListener listener) { |
| removeDragSourceListener((TransferDragSourceListener) listener); |
| } |
| |
| /** |
| * @see EditPartViewer#removeDragSourceListener(TransferDragSourceListener) |
| */ |
| public void removeDragSourceListener(TransferDragSourceListener listener) { |
| getDelegatingDragAdapter().removeDragSourceListener(listener); |
| if (getDelegatingDragAdapter().isEmpty()) |
| refreshDragSourceAdapter(); |
| } |
| |
| /** |
| * @see EditPartViewer#removeDropTargetListener(org.eclipse.gef.dnd.TransferDropTargetListener) |
| * @deprecated |
| */ |
| public void removeDropTargetListener( |
| org.eclipse.gef.dnd.TransferDropTargetListener listener) { |
| removeDropTargetListener((TransferDropTargetListener) listener); |
| } |
| |
| /** |
| * @see EditPartViewer#removeDropTargetListener(TransferDropTargetListener) |
| */ |
| public void removeDropTargetListener(TransferDropTargetListener listener) { |
| getDelegatingDropAdapter().removeDropTargetListener(listener); |
| if (getDelegatingDropAdapter().isEmpty()) |
| refreshDropTargetAdapter(); |
| } |
| |
| /** |
| * @see EditPartViewer#removePropertyChangeListener(PropertyChangeListener) |
| */ |
| public void removePropertyChangeListener(PropertyChangeListener listener) { |
| if (changeSupport != null) { |
| changeSupport.removePropertyChangeListener(listener); |
| if (changeSupport.getPropertyChangeListeners().length == 0) |
| changeSupport = null; |
| } |
| } |
| |
| /** |
| * @see ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener) |
| */ |
| public void removeSelectionChangedListener(ISelectionChangedListener l) { |
| selectionListeners.remove(l); |
| } |
| |
| /** |
| * @see EditPartViewer#reveal(EditPart) |
| */ |
| public void reveal(EditPart part) { |
| } |
| |
| /** |
| * @see EditPartViewer#select(EditPart) |
| */ |
| public void select(EditPart editpart) { |
| // If selection isn't changing, do nothing. |
| if ((getSelectedEditParts().size() == 1) |
| && (getSelectedEditParts().get(0) == editpart)) |
| return; |
| primDeselectAll(); |
| appendSelection(editpart); // fireSelectionChanged() is called here |
| } |
| |
| /** |
| * @see EditPartViewer#setContextMenu(MenuManager) |
| */ |
| public void setContextMenu(MenuManager manager) { |
| if (contextMenu != null) |
| contextMenu.dispose(); |
| contextMenu = manager; |
| if (getControl() != null && !getControl().isDisposed()) |
| getControl().setMenu(contextMenu.createContextMenu(getControl())); |
| } |
| |
| /** |
| * @see EditPartViewer#setContents(EditPart) |
| */ |
| public void setContents(EditPart editpart) { |
| getRootEditPart().setContents(editpart); |
| } |
| |
| /** |
| * @see EditPartViewer#setContents(Object) |
| */ |
| public void setContents(Object contents) { |
| Assert.isTrue(getEditPartFactory() != null, |
| "An EditPartFactory is required to call setContents(Object)");//$NON-NLS-1$ |
| setContents(getEditPartFactory().createEditPart(null, contents)); |
| } |
| |
| /** |
| * @see EditPartViewer#setControl(Control) |
| */ |
| public void setControl(Control control) { |
| if (this.control != null) |
| unhookControl(); |
| this.control = control; |
| if (control != null) |
| hookControl(); |
| } |
| |
| /** |
| * @see EditPartViewer#setCursor(Cursor) |
| */ |
| public void setCursor(Cursor cursor) { |
| if (getControl() == null || getControl().isDisposed()) |
| return; |
| getControl().setCursor(cursor); |
| } |
| |
| /** |
| * Sets the drag source. Called from {@link #refreshDragSourceAdapter()}. |
| * |
| * @param source |
| * <code>null</code> or a drag source |
| */ |
| protected void setDragSource(DragSource source) { |
| if (dragSource != null) |
| dragSource.dispose(); |
| dragSource = source; |
| if (dragSource != null) |
| hookDragSource(); |
| } |
| |
| /** |
| * Sets the drop target. Called from {@link #refreshDropTargetAdapter()}. |
| * |
| * @param target |
| * dropTarget <code>null</code> or a drop target |
| */ |
| protected void setDropTarget(DropTarget target) { |
| if (dropTarget != null) |
| dropTarget.dispose(); |
| dropTarget = target; |
| if (dropTarget != null) |
| hookDropTarget(); |
| } |
| |
| /** |
| * @see EditPartViewer#setEditDomain(EditDomain) |
| */ |
| public void setEditDomain(EditDomain editdomain) { |
| this.domain = editdomain; |
| } |
| |
| /** |
| * @see EditPartViewer#setEditPartFactory(org.eclipse.gef.EditPartFactory) |
| */ |
| public void setEditPartFactory(EditPartFactory factory) { |
| this.factory = factory; |
| } |
| |
| /** |
| * @see EditPartViewer#setFocus(EditPart) |
| */ |
| public void setFocus(EditPart part) { |
| getSelectionManager().setFocus(part); |
| focusPart = part; |
| } |
| |
| /** |
| * @see EditPartViewer#setKeyHandler(KeyHandler) |
| */ |
| public void setKeyHandler(KeyHandler handler) { |
| keyHandler = handler; |
| } |
| |
| /** |
| * @see EditPartViewer#setProperty(String, Object) |
| */ |
| public void setProperty(String key, Object value) { |
| if (properties == null) |
| properties = new HashMap(); |
| Object old; |
| if (value == null) |
| old = properties.remove(key); |
| else |
| old = properties.put(key, value); |
| |
| if (changeSupport != null) |
| changeSupport.firePropertyChange(key, old, value); |
| } |
| |
| /** |
| * @see EditPartViewer#setRootEditPart(RootEditPart) |
| */ |
| public void setRootEditPart(RootEditPart editpart) { |
| if (rootEditPart != null) { |
| if (rootEditPart.isActive()) |
| rootEditPart.deactivate(); |
| rootEditPart.setViewer(null); |
| } |
| rootEditPart = editpart; |
| rootEditPart.setViewer(this); |
| if (getControl() != null) |
| rootEditPart.activate(); |
| } |
| |
| /** |
| * @see EditPartViewer#setRouteEventsToEditDomain(boolean) |
| */ |
| public void setRouteEventsToEditDomain(boolean value) { |
| } |
| |
| /** |
| * Sets the selection to the given selection and fires selection changed. |
| * The ISelection should be an {@link IStructuredSelection} or it will be |
| * ignored. |
| * |
| * @see ISelectionProvider#setSelection(ISelection) |
| */ |
| public void setSelection(ISelection newSelection) { |
| selectionModel.setSelection(newSelection); |
| } |
| |
| /** |
| * Called when the control is being set to <code>null</code>, but before it |
| * is null. |
| */ |
| protected void unhookControl() { |
| Assert.isTrue(getControl() != null); |
| |
| if (disposeListener != null) { |
| getControl().removeDisposeListener(disposeListener); |
| disposeListener = null; |
| } |
| if (getContextMenu() != null) |
| getContextMenu().dispose(); |
| if (getRootEditPart() != null) |
| getRootEditPart().deactivate(); |
| } |
| |
| /** |
| * Does nothing by default. Subclasses needing to add accessibility support |
| * should override this method. |
| * |
| * @see EditPartViewer#unregisterAccessibleEditPart(AccessibleEditPart) |
| */ |
| public void unregisterAccessibleEditPart(AccessibleEditPart acc) { |
| } |
| |
| } |