| /****************************************************************************** |
| * Copyright (c) 2002, 2009 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.gmf.runtime.diagram.ui.parts; |
| |
| import java.util.List; |
| |
| import org.eclipse.draw2d.DeferredUpdateManager; |
| import org.eclipse.draw2d.LightweightSystem; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer; |
| import org.eclipse.gmf.runtime.common.ui.util.DisplayUtils; |
| import org.eclipse.gmf.runtime.diagram.ui.internal.parts.ElementToEditPartsMap; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| 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.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.swt.widgets.Display; |
| |
| /** |
| * @author melaasar |
| * |
| * Implementation of a diagram graphical viewer |
| */ |
| public class DiagramGraphicalViewer |
| extends ScrollingGraphicalViewer |
| implements IDiagramGraphicalViewer { |
| |
| /** |
| * Resource manager to remember the resources allocated for this graphical |
| * viewer. |
| */ |
| private ResourceManager resourceManager; |
| |
| /** |
| * Constructor |
| */ |
| public DiagramGraphicalViewer() { |
| super(); |
| } |
| |
| /** |
| * @param enable |
| * <code>boolean</code> <code>true</code> if client wishes to |
| * disable updates on the figure canvas, <code>false</code> |
| * indicates normal updates are to take place. |
| */ |
| public void enableUpdates(boolean enable) { |
| if (enable) |
| getLightweightSystemWithUpdateToggle().enableUpdates(); |
| else |
| getLightweightSystemWithUpdateToggle().disableUpdates(); |
| } |
| |
| /** |
| * @return |
| */ |
| public boolean areUpdatesDisabled() { |
| return getLightweightSystemWithUpdateToggle().getToggleUpdateManager().shouldDisableUpdates(); |
| } |
| |
| private class ToggleUpdateManager |
| extends DeferredUpdateManager { |
| |
| private boolean disableUpdates = false; |
| |
| /** |
| * @return the disableUpdates |
| */ |
| public boolean shouldDisableUpdates() { |
| return disableUpdates; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.draw2d.DeferredUpdateManager#sendUpdateRequest() |
| */ |
| protected void sendUpdateRequest() { |
| DisplayUtils.getDisplay().asyncExec(new UpdateRequest()); |
| } |
| |
| /** |
| * @param disableUpdates |
| * the disableUpdates to set |
| */ |
| public synchronized void setDisableUpdates(boolean disableUpdates) { |
| boolean prevDisableUpdates = this.disableUpdates; |
| this.disableUpdates = disableUpdates; |
| if (!disableUpdates && prevDisableUpdates != disableUpdates) { |
| sendUpdateRequest(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.draw2d.DeferredUpdateManager#performUpdate() |
| */ |
| public synchronized void performUpdate() { |
| if (!shouldDisableUpdates()) |
| super.performUpdate(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.draw2d.DeferredUpdateManager#performValidation() |
| */ |
| public void performValidation() { |
| if (!shouldDisableUpdates()) |
| super.performValidation(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.draw2d.DeferredUpdateManager#queueWork() |
| */ |
| public void queueWork() { |
| if (!shouldDisableUpdates()) |
| super.queueWork(); |
| } |
| } |
| |
| private class LightweightSystemWithUpdateToggle |
| extends LightweightSystem { |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.draw2d.LightweightSystem#getUpdateManager() |
| */ |
| public ToggleUpdateManager getToggleUpdateManager() { |
| return (ToggleUpdateManager) getUpdateManager(); |
| } |
| |
| /** |
| * disable updates on the figure canvas |
| */ |
| public void disableUpdates() { |
| getToggleUpdateManager().setDisableUpdates(true); |
| } |
| |
| /** |
| * allow updates on the figure canvas to occcur |
| */ |
| public void enableUpdates() { |
| getToggleUpdateManager().setDisableUpdates(false); |
| } |
| } |
| |
| private LightweightSystemWithUpdateToggle getLightweightSystemWithUpdateToggle() { |
| return (LightweightSystemWithUpdateToggle) getLightweightSystem(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#createLightweightSystem() |
| */ |
| protected LightweightSystem createLightweightSystem() { |
| LightweightSystem lws = new LightweightSystemWithUpdateToggle(); |
| lws.setUpdateManager(new ToggleUpdateManager()); |
| return lws; |
| } |
| |
| /** |
| * A selection event pending flag (for asynchronous firing) |
| */ |
| private boolean selectionEventPending = false; |
| |
| /** |
| * A registry of editparts on the diagram, mapping an element's id string to |
| * a list of <code>EditParts</code>. |
| */ |
| private ElementToEditPartsMap elementToEditPartsMap = new ElementToEditPartsMap(); |
| |
| /** |
| * Hook a zoom enabled graphics source |
| * |
| * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#hookControl() |
| */ |
| protected void hookControl() { |
| super.hookControl(); |
| |
| if (resourceManager == null) { |
| resourceManager = new LocalResourceManager(JFaceResources |
| .getResources()); |
| } |
| } |
| |
| /** |
| * Refresh drag source adapters regardless if the adapter list is empty |
| * |
| * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#removeDragSourceListener(TransferDragSourceListener) |
| */ |
| public void removeDragSourceListener(TransferDragSourceListener listener) { |
| getDelegatingDragAdapter().removeDragSourceListener(listener); |
| refreshDragSourceAdapter(); |
| } |
| |
| /** |
| * Refresh drag target adapters regardless if the adapter list is empty |
| * |
| * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#removeDropTargetListener(TransferDropTargetListener) |
| */ |
| public void removeDropTargetListener(TransferDropTargetListener listener) { |
| getDelegatingDropAdapter().removeDropTargetListener(listener); |
| refreshDropTargetAdapter(); |
| } |
| |
| /** |
| * Overriden to also flush pending selection events to account for OS |
| * diffences, since we are firing selection change events asynchronously. |
| */ |
| public void flush() { |
| super.flush(); |
| if (selectionEventPending) { |
| flushSelectionEvents(getSelection()); |
| } |
| |
| } |
| |
| /** |
| * For performance reasons, we fire the event asynchronously |
| */ |
| protected void fireSelectionChanged() { |
| if (selectionEventPending) |
| return; |
| selectionEventPending = true; |
| Display display = DisplayUtils.getDisplay(); |
| if (display != null) { |
| display.asyncExec(new Runnable() { |
| |
| public void run() { |
| flushSelectionEvents(getSelection()); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * flush the selection events |
| * |
| * @param sel |
| */ |
| protected void flushSelectionEvents(ISelection sel) { |
| selectionEventPending = false; |
| SelectionChangedEvent event = new SelectionChangedEvent(this, sel); |
| |
| // avoid exceptions caused by selectionChanged |
| // modifiying selectionListeners |
| Object[] array = selectionListeners.toArray(); |
| |
| for (int i = 0; i < array.length; i++) { |
| ISelectionChangedListener l = (ISelectionChangedListener) array[i]; |
| if (selectionListeners.contains(l)) |
| l.selectionChanged(event); |
| } |
| } |
| |
| private void fireEmptySelection() { |
| if (selectionEventPending) |
| return; |
| selectionEventPending = true; |
| Display display = getControl().getDisplay(); |
| if (display != null) { |
| display.asyncExec(new Runnable() { |
| |
| public void run() { |
| flushSelectionEvents(getSelection()); |
| flushSelectionEvents(StructuredSelection.EMPTY); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer#getDiagramEditDomain() |
| */ |
| public IDiagramEditDomain getDiagramEditDomain() { |
| return (IDiagramEditDomain) getEditDomain(); |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer#findEditPartsForElement(java.lang.String, |
| * java.lang.Class) |
| */ |
| public List findEditPartsForElement(String elementIdStr, Class editPartClass) { |
| return elementToEditPartsMap.findEditPartsForElement(elementIdStr, |
| editPartClass); |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer#registerEditPartForElement(java.lang.String, |
| * org.eclipse.gef.EditPart) |
| */ |
| public void registerEditPartForElement(String elementIdStr, EditPart ep) { |
| elementToEditPartsMap.registerEditPartForElement(elementIdStr, ep); |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer#unregisterEditPartForElement(java.lang.String, |
| * org.eclipse.gef.EditPart) |
| */ |
| public void unregisterEditPartForElement(String elementIdStr, EditPart ep) { |
| elementToEditPartsMap.unregisterEditPartForElement(elementIdStr, ep); |
| } |
| |
| /** The work space preference store */ |
| private IPreferenceStore workspacePreferenceStore; |
| |
| private boolean initializing; |
| |
| /** |
| * The editor manages the workspaces preferences store. So viewers not using |
| * a editor do not need to create a preference store. This method provides a |
| * hook for clients requiring access to the preference store. |
| * |
| * @param store |
| */ |
| public void hookWorkspacePreferenceStore(IPreferenceStore store) { |
| this.workspacePreferenceStore = store; |
| } |
| |
| /** |
| * Returns the workspace preference store managed by the |
| * <code>DiagramEditor</code>, if one is being used. May return null. |
| * |
| * @return the work space preference store |
| */ |
| public IPreferenceStore getWorkspaceViewerPreferenceStore() { |
| return workspacePreferenceStore; |
| } |
| |
| /** |
| * Gets the resource manager to remember the resources allocated for this |
| * graphical viewer. All resources will be disposed when the graphical |
| * viewer is closed if they have not already been disposed. |
| */ |
| public final ResourceManager getResourceManager() { |
| return resourceManager; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#unhookControl() |
| */ |
| protected void unhookControl() { |
| fireEmptySelection(); |
| super.unhookControl(); |
| |
| if (resourceManager != null) { |
| resourceManager.dispose(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#setContents(org.eclipse.gef.EditPart) |
| */ |
| public void setContents(EditPart editpart) { |
| initializing = true; |
| try { |
| super.setContents(editpart); |
| } finally { |
| initializing = false; |
| } |
| } |
| |
| /** |
| * checks if the viewer is still in the process of initializing itself |
| * |
| * @return true if initializing; false if the initializing process is |
| * finished |
| */ |
| public boolean isInitializing() { |
| return initializing; |
| } |
| } |