| /******************************************************************************* |
| * <copyright> |
| * |
| * Copyright (c) 2005, 2014 SAP AG. |
| * 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: |
| * SAP AG - initial API, implementation and documentation |
| * mwenz - Bug 331715: Support for rectangular grids in diagrams |
| * mwenz - Bug 332964: Enable setting selection for non-EMF domain models and |
| * when embedded into a multi-page editor |
| * mwenz - Bug 336075 - DiagramEditor accepts URIEditorInput |
| * mwenz - Bug 329523 - Add notification of DiagramTypeProvider after saving a diagram |
| * jpasch - Bug 323025 ActionBarContributor cleanup |
| * mwenz - Bug 345347 - There should be a way to not allow other plugins to contribute to the diagram context menu |
| * mwenz - Bug 346932 - Navigation history broken |
| * mwenz - Bug 356828 - Escaped diagram name is used as editor title |
| * mwenz - Bug 356218 - Added hasDoneChanges updates to update diagram feature |
| * and called features via editor command stack to check it |
| * Felix Velasco (mwenz) - Bug 323351 - Enable to suppress/reactivate the speed buttons |
| * Bug 336488 - DiagramEditor API |
| * mwenz - Bug 367204 - Correctly return the added PE inAbstractFeatureProvider's addIfPossible method |
| * mwenz - Bug 324556 - Prevent invisible shapes to be selected to avoid IllegalArgumentException |
| * mwenz - Bug 372753 - save shouldn't (necessarily) flush the command stack |
| * mwenz - Bug 376008 - Iterating through navigation history causes exceptions |
| * Felix Velasco - mwenz - Bug 379788 - Memory leak in DefaultMarkerBehavior |
| * mwenz - Bug 387971 - Features cant't be invoked from contextMenu |
| * fvelasco - Bug 323349 - Enable external invocation of features |
| * mwenz - Bug 393113 - Auto-focus does not work for connections |
| * mwenz - Bug 396893 - Enable the registration of the drop target listeners configurable |
| * pjpaulin - Bug 352120 - Main implementation of DiagramEditor - API BREAKAGE HERE |
| * pjpaulin - Bug 352120 - Renamed from DiagramEditorImpl so that classes extending DiagramEditor do not break |
| * mwenz - Bug 394315 - Enable injecting behavior objects in DiagramEditor |
| * pjpaulin - Bug 405314 - Should be able to override DefaultBehavior implementation without configuration |
| * mwenz - Bug 430687 - UpdateBehaviour createEditingDomain should be able to access diagram input (sphinx compatibility) |
| * |
| * </copyright> |
| * |
| *******************************************************************************/ |
| package org.eclipse.graphiti.ui.editor; |
| |
| import java.util.ArrayList; |
| import java.util.EventObject; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.emf.common.ui.URIEditorInput; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.edit.domain.IEditingDomainProvider; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.gef.DefaultEditDomain; |
| import org.eclipse.gef.GraphicalViewer; |
| import org.eclipse.gef.palette.PaletteRoot; |
| import org.eclipse.gef.ui.actions.ActionRegistry; |
| import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences; |
| import org.eclipse.gef.ui.palette.PaletteViewerProvider; |
| import org.eclipse.gef.ui.parts.GraphicalEditor; |
| import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette; |
| import org.eclipse.gef.ui.parts.SelectionSynchronizer; |
| import org.eclipse.graphiti.dt.IDiagramTypeProvider; |
| import org.eclipse.graphiti.mm.pictograms.PictogramElement; |
| import org.eclipse.graphiti.services.Graphiti; |
| import org.eclipse.graphiti.tb.IToolBehaviorProvider; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorSite; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.contexts.IContextService; |
| import org.eclipse.ui.navigator.CommonNavigator; |
| import org.eclipse.ui.part.MultiPageEditorPart; |
| import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; |
| |
| /** |
| * This is the main class for the Graphiti diagram editor. It represents the |
| * editor to Eclipse and therefore implements {@link IEditorPart}. The |
| * implementation is based upon a GEF editor implementation ( |
| * {@link GraphicalEditorWithFlyoutPalette}) and enhances it with |
| * Graphiti-specific stuff.<br> |
| * This editor is registered as an Eclipse editor using the extension point |
| * org.eclipse.ui.editors. Therefore the Eclipse standard methods can be used to |
| * open a new diagram editor. The associated {@link IEditorInput} object is a |
| * subclass of {@link DiagramEditorInput}, but using another type of input is |
| * also ok as long as it can be adapted to an IFile that can be reolved within |
| * the workspace of is a {@link URIEditorInput}. These types of input objects |
| * will be converted to a corresponding {@link DiagramEditorInput} when the |
| * editor is initialized (see {@link #init(IEditorSite, IEditorInput)}).<br> |
| * Any clients extending this class should also contribute their editor to the |
| * Eclipse editor extension point to gain full advantage of the Eclipse editor |
| * integration of Graphiti.<br> |
| * There are a lot of aspects this class needs to deal with; the larger aspects |
| * are separated into other classes which share the lifecycle with the |
| * {@link DiagramEditor} instance. This means they are instantiated when a |
| * new diagram editor is created and exist until the editor is closed again. |
| * There are default implementations for all of these aspects, see the |
| * Default*Behavior classes in this package. The following aspects are |
| * separated: |
| * <ul> |
| * <li>Markers: Handles everything about markers in the editor. See |
| * {@link DefaultMarkerBehavior} for the default implementation. Override |
| * {@link #createMarkerBehavior()} to change the default behavior.</li> |
| * <li>Palette: Handles everything about the palette in the editor. See |
| * {@link DefaultPaletteBehavior} for the default implementation. Override |
| * {@link #createPaletteBehaviour()} to change the default behavior.</li> |
| * <li>Persistence: Handles everything about loading, saving and the dirty state |
| * in the editor. See {@link DefaultPersistencyBehavior} for the default |
| * implementation. Override {@link #createPersistencyBehavior()} to change the |
| * default behavior.</li> |
| * <li>Refreshing: Handles everything about refreshing the editor (refreshing |
| * means that the editor shows what's defined in the pictogram model). See |
| * {@link DefaultRefreshBehavior} for the default implementation. Override |
| * {@link #createRefreshBehavior()} to change the default behavior.</li> |
| * <li>Update: Handles everything about updating the editor (updating means that |
| * the pictogram model is updated to reflect any changes done to the domain |
| * model - your business objects - or to the way objects shall be visualized). |
| * See {@link DefaultMarkerBehavior} for the default implementation. Override |
| * {@link #createMarkerBehavior()} to change the default behavior.</li> |
| * </ul> |
| * All the other aspects are dealt with directly within this class. One of the |
| * larger aspects implemented here is selection handling, which would have been |
| * awkward if separated out. |
| * |
| * @since 0.10 |
| * |
| */ |
| public class DiagramEditor extends GraphicalEditorWithFlyoutPalette implements IDiagramContainerUI, |
| ITabbedPropertySheetPageContributor, IEditingDomainProvider { |
| |
| private String contributorId; |
| private DiagramBehavior diagramBehavior; |
| |
| /** |
| * The ID of the {@link DiagramEditor} as it is registered with the |
| * org.eclipse.ui.editors extension point. |
| */ |
| public static final String DIAGRAM_EDITOR_ID = "org.eclipse.graphiti.ui.editor.DiagramEditor"; //$NON-NLS-1$ |
| |
| /** |
| * Creates a new diagram editor and cares about the creation of the |
| * different behavior extensions by delegating to the various |
| * create*Behavior() methods. |
| */ |
| public DiagramEditor() { |
| super(); |
| } |
| |
| /** |
| * Returns the associated {@link DiagramSupport} instance to this editor. |
| * |
| * @return The associated {@link DiagramSupport} instance |
| * |
| * @since 0.10 |
| */ |
| public DiagramBehavior getDiagramBehavior() { |
| return diagramBehavior; |
| } |
| |
| // ------------------ Initializazion --------------------------------------- |
| |
| /** |
| * Does the initialization of the editor. The default implementation cares |
| * about: |
| * <ol> |
| * <li>converting the passed {@link IEditorInput} to a |
| * {@link DiagramEditorInput}. In case this fails, a |
| * {@link PartInitException} is thrown.</li> |
| * <li>creating the editing domain by delegating to the update behavior |
| * extension, see |
| * {@link DefaultUpdateBehavior#createEditingDomain(IDiagramEditorInput)} |
| * for details</li> |
| * <li>initializing the underlying GEF editor by delegating to super</li> |
| * <li>initializing the update behavior extension (the order is important |
| * here as this must happen after initializing the GEF editor!)</li> |
| * <li>triggering the migration of diagram data if necessary</li> |
| * </ol> |
| * Any clients overriding this method have to make sure that they they |
| * always call <code>super.init(site, input)</code>. |
| * |
| * @see org.eclipse.ui.IEditorPart#init(IEditorSite, IEditorInput) |
| * @param site |
| * the Eclipse {@link IEditorSite} that will host this editor |
| * @param input |
| * the editor input that shall be used. Note that this method |
| * will exchange the input instance in case it is no |
| * {@link DiagramEditorInput}. |
| * |
| */ |
| public void init(IEditorSite site, IEditorInput input) throws PartInitException { |
| diagramBehavior = createDiagramBehavior(); |
| diagramBehavior.setParentPart(this); |
| diagramBehavior.initDefaultBehaviors(); |
| |
| IDiagramEditorInput diagramEditorInput; |
| if (input instanceof IDiagramEditorInput) { |
| diagramEditorInput = (IDiagramEditorInput) input; |
| } else { |
| // Eclipse may call us with other inputs when a file is to be |
| // opened. Try to convert this to a valid diagram input. |
| diagramEditorInput = convertToDiagramEditorInput(input); |
| if (diagramEditorInput == null) { |
| throw new PartInitException( |
| "No DiagramEditorInput instance is available but it is required. The method convertToDiagramEditorInput illegally returned null."); //$NON-NLS-1$ |
| } |
| } |
| |
| diagramBehavior.getUpdateBehavior().createEditingDomain(diagramEditorInput); |
| |
| // The GEF GraphicalEditor init(...) functionality, adapted to provide a |
| // nice error message to the user in case of an error when opening an |
| // editor with e.g. an invalid diagram, see Bug 376008 |
| setSite(site); |
| setInput((IEditorInput) diagramEditorInput); |
| if (diagramBehavior.getEditorInitializationError() != null) { |
| // In case of error simply show an primitive editor with a label |
| return; |
| } |
| getCommandStack().addCommandStackListener(this); |
| getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this); |
| initializeActionRegistry(); |
| // ... End of GEF functionality taken over |
| |
| diagramBehavior.getUpdateBehavior().init(); |
| |
| diagramBehavior.migrateDiagramModelIfNecessary(); |
| IContextService contextService = (IContextService) getSite().getService(IContextService.class); |
| contextService.activateContext(getDiagramTypeProvider().getContextId()); |
| } |
| |
| /** |
| * Creates the behavior object that cares about the common (behavioral) |
| * coding shared between editors, views and other composites. See |
| * {@link DiagramBehavior} for details and the default implementation. |
| * Override to change the behavior. |
| * |
| * @return a new instance of {@link DiagramBehavior} |
| * @since 0.10 |
| */ |
| protected DiagramBehavior createDiagramBehavior() { |
| return new DiagramBehavior(this); |
| } |
| |
| /** |
| * Is called by the {@link #init(IEditorSite, IEditorInput)} method in case |
| * the {@link IEditorInput} instance passed is no {@link DiagramEditorInput} |
| * . This method should try to convert the passed input object to a |
| * {@link DiagramEditorInput} or throw an {@link PartInitException} in case |
| * the conversion can (or should) not be done for any reason. The default |
| * implementation uses the |
| * {@link EditorInputAdapter#adaptToDiagramEditorInput(IEditorInput)} method |
| * to do the conversion. Clients may adapt to do additional conversions or |
| * to prohibit any conversion by simply throwing a {@link PartInitException} |
| * . |
| * |
| * @param input |
| * the original input |
| * @return a {@link DiagramEditorInput} corresponding to the passed input |
| * instance in case a conversion is possible. This method must not |
| * return <code>null</code>, otherwise the editor initialization |
| * will fail. |
| * @throws PartInitException |
| * in case the passed input object cannot or should not be |
| * converted to a {@link DiagramEditorInput} instance. |
| * |
| * @since 0.9 |
| */ |
| protected DiagramEditorInput convertToDiagramEditorInput(IEditorInput input) throws PartInitException { |
| IEditorInput newInput = EditorInputAdapter.adaptToDiagramEditorInput(input); |
| if (!(newInput instanceof IDiagramEditorInput)) { |
| throw new PartInitException("Unknown editor input: " + input); //$NON-NLS-1$ |
| } |
| return (DiagramEditorInput) newInput; |
| } |
| |
| /** |
| * Sets the given {@link IEditorInput} object as the input for this editor. |
| * It must be of type {@link DiagramEditorInput} otherwise an |
| * {@link IllegalArgumentException} is thrown.<br> |
| * The default implementation here cares about loading the diagram from the |
| * EMF {@link Resource} the input points to, sets the ID of the |
| * {@link IDiagramTypeProvider} for the diagram given in the input, |
| * registers listeners (by delegating to |
| * {@link #registerDiagramResourceSetListener()} and |
| * {@link #registerBusinessObjectsListener()}) and does the refreshing of |
| * the editor UI. |
| * |
| * @param input |
| * the {@link DiagramEditorInput} instance to use within this |
| * editor. |
| */ |
| protected void setInput(IEditorInput input) { |
| super.setInput(input); |
| if (!(input instanceof IDiagramEditorInput)) { |
| throw new IllegalArgumentException("The IEditorInput has the wrong type: " + input.getClass()); //$NON-NLS-1$ |
| } |
| diagramBehavior.setInput((IDiagramEditorInput) input); |
| } |
| |
| /** |
| * Creates the UI of the editor by delegating to the |
| * <code>super.createPartControl</code> method. The default implementation |
| * here also registers the command stack listener to correctly reflect the |
| * dirty state of the editor. |
| */ |
| public void createPartControl(Composite parent) { |
| if (diagramBehavior.getEditorInitializationError() != null) { |
| diagramBehavior.createErrorPartControl(parent); |
| } else { |
| super.createPartControl(parent); |
| diagramBehavior.addGefListeners(); |
| } |
| } |
| |
| /** |
| * Creates the GraphicalViewer on the specified {@link Composite} and |
| * initializes it. This method needs to be implemented here to fulfill the |
| * interface of the underlying GEF editor but only delegates to |
| * {@link DiagramSupport#createGraphicalViewer(Composite)}. |
| * |
| * @param parent |
| * The parent composite |
| */ |
| protected void createGraphicalViewer(Composite parent) { |
| diagramBehavior.createGraphicalViewer(parent); |
| } |
| |
| /** |
| * Called to initialize the editor with its content. Here everything is |
| * done, which is dependent of the IConfigurationProviderInternal. |
| * |
| * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#initializeGraphicalViewer() |
| * @since 0.10 |
| */ |
| public void initializeGraphicalViewer() { |
| |
| super.initializeGraphicalViewer(); |
| diagramBehavior.initializeGraphicalViewer(); |
| |
| // this will cause the ActionBarContributor to refresh with the |
| // new actions (there is no specific refresh-action). |
| if (getEditorSite().getActionBarContributor() != null) |
| getEditorSite().getActionBarContributor().setActiveEditor(this); |
| } |
| |
| /** |
| * Called to configure the editor, before it receives its content. The |
| * default-implementation is for example doing the following: configure the |
| * ZoomManager, registering Actions... Here everything is done, which is |
| * independent of the IConfigurationProviderInternal. |
| * |
| * @see org.eclipse.gef.ui.parts.GraphicalEditor#configureGraphicalViewer() |
| */ |
| protected void configureGraphicalViewer() { |
| super.configureGraphicalViewer(); |
| diagramBehavior.configureGraphicalViewer(); |
| } |
| |
| // ------------------- Dirty state ----------------------------------------- |
| |
| /** |
| * Updates the UI to correctly reflect the dirty state of the editor. The |
| * default implementation does this by firing a |
| * {@link IEditorPart#PROP_DIRTY} property change. |
| * |
| * @since 0.9 |
| */ |
| public void updateDirtyState() { |
| firePropertyChange(IEditorPart.PROP_DIRTY); |
| } |
| |
| /** |
| * Called to perform the saving of the editor. The default implementation |
| * delegates via {@link DiagramSupport} to |
| * {@link DefaultPersistencyBehavior#saveDiagram(IProgressMonitor)}. |
| * |
| * @param monitor |
| * the Eclipse progress monitor to report progress with. |
| */ |
| public void doSave(IProgressMonitor monitor) { |
| diagramBehavior.getPersistencyBehavior().saveDiagram(monitor); |
| } |
| |
| /** |
| * Returns if the editor is currently dirty and needs to be saved or not. |
| * The default implementation delegates to {@link DiagramSupport#isDirty()}. |
| * |
| * @return <code>true</code> in case the editor is dirty, <code>false</code> |
| * otherwise. |
| */ |
| public boolean isDirty() { |
| return diagramBehavior.isDirty(); |
| } |
| |
| // ---------------------- Palette --------------------------------------- // |
| |
| /** |
| * Delegates to the method (or the method in a subclass of) |
| * {@link DefaultPaletteBehavior#createPaletteViewerProvider() |
| * #createPaletteViewerProvider()} to create the |
| * {@link PaletteViewerProvider} used inside the GEF editor. |
| * |
| * @return the {@link PaletteViewerProvider} to use |
| */ |
| protected final PaletteViewerProvider createPaletteViewerProvider() { |
| return diagramBehavior.createPaletteViewerProvider(); |
| } |
| |
| /** |
| * Delegates to the method (or the method in a subclass of) |
| * {@link DefaultPaletteBehavior#getPalettePreferences()}. To change the |
| * palette override the behavior there. |
| * |
| * @return the {@link PaletteViewerProvider} preferences to use. |
| */ |
| protected final FlyoutPreferences getPalettePreferences() { |
| return diagramBehavior.getPalettePreferences(); |
| } |
| |
| /** |
| * Returns the {@link PaletteRoot} to use in the GEF editor by delegating to |
| * {@link DefaultPaletteBehavior#getPaletteRoot()}. |
| * |
| * @return the {@link PaletteRoot} to use |
| */ |
| protected final PaletteRoot getPaletteRoot() { |
| return diagramBehavior.getPaletteRoot(); |
| } |
| |
| // ---------------------- Refresh --------------------------------------- // |
| |
| /** |
| * Refreshes the editor title to show the name of the diagram |
| * |
| * @since 0.9 |
| */ |
| public void refreshTitle() { |
| String name = getDiagramTypeProvider().getDiagramTitle(); |
| if (name == null || name.length() == 0) { |
| name = getConfigurationElement().getAttribute("name"); //$NON-NLS-1$ |
| } |
| if (name == null || name.length() == 0) { |
| name = URI.decode(getDiagramTypeProvider().getDiagram().eResource().getURI().lastSegment()); |
| } |
| setPartName(name); |
| } |
| |
| /** |
| * Refreshes the tooltip displayed for the editor title tab according to |
| * what is returned in {@link #getTitleToolTip()}. |
| * |
| * @since 0.9 |
| */ |
| public void refreshTitleToolTip() { |
| setTitleToolTip(getTitleToolTip()); |
| } |
| |
| // ====================== standard behavior ============================== |
| |
| /** |
| * Implements the Eclipse {@link IAdaptable} interface. This implementation |
| * first delegates to the {@link IToolBehaviorProvider#getAdapter(Class)} |
| * method and checks if something is returned. In case the return value is |
| * <code>null</code> it returns adapters for ZoomManager, |
| * IPropertySheetPage, Diagram, KeyHandler, SelectionSynchronizer and |
| * IContextButtonManager. It also delegates to the super implementation in |
| * {@link GraphicalEditorWithFlyoutPalette#getAdapter(Class)}. |
| * |
| * @param type |
| * the type to which shall be adapted |
| * @return the adapter instance |
| */ |
| public Object getAdapter(@SuppressWarnings("rawtypes") Class type) { |
| Object returnObj = diagramBehavior.getAdapter(type); |
| if (returnObj != null) { |
| return returnObj; |
| } |
| if (type == SelectionSynchronizer.class) { |
| return getSelectionSynchronizer(); |
| } |
| return super.getAdapter(type); |
| } |
| |
| /** |
| * Disposes this {@link DiagramEditor} instance and frees all used resources |
| * and clears all references. Also delegates to all the behavior extensions |
| * to also free their resources (e.g. and most important is the |
| * {@link TransactionalEditingDomain} held by the |
| * {@link DefaultPersistencyBehavior}. Always delegate to |
| * <code>super.dispose()</code> in case you override this method! |
| */ |
| public void dispose() { |
| if (diagramBehavior != null) { |
| diagramBehavior.disposeBeforeGefDispose(); |
| } |
| |
| RuntimeException exc = null; |
| if (getEditDomain() != null) { |
| // Avoid exception in case an error during editor initialization |
| // happened |
| try { |
| super.dispose(); |
| } catch (RuntimeException e) { |
| exc = e; |
| } |
| } |
| |
| if (diagramBehavior != null) { |
| diagramBehavior.disposeAfterGefDispose(); |
| } |
| |
| if (exc != null) { |
| throw exc; |
| } |
| } |
| |
| /** |
| * Sets the focus by delegating to the super class implementation in the GEF |
| * editor and additionally triggers a update of the diagram by delegating to |
| * {@link DefaultUpdateBehavior#handleActivate()}. |
| */ |
| public void setFocus() { |
| if (getGraphicalViewer() == null) { |
| return; |
| } |
| |
| super.setFocus(); |
| diagramBehavior.getUpdateBehavior().handleActivate(); |
| } |
| |
| // ---------------------- Selection ------------------------------------- // |
| |
| /** |
| * Returns the {@link PictogramElement}s that are currently selected in the |
| * diagram editor. |
| * |
| * @return an array of {@link PictogramElement}s. |
| * |
| * @since 0.9 |
| */ |
| public PictogramElement[] getSelectedPictogramElements() { |
| return diagramBehavior.getSelectedPictogramElements(); |
| } |
| |
| /** |
| * Handles a selection changed event that is triggered by any selection |
| * source, e.g. a browser with "Link to Editor" enabled.<br> |
| * Checks if the currently active editor is a {@link MultiPageEditorPart} |
| * with an opened diagram editor inside, tries to find any |
| * {@link PictogramElement} for the objects in the selection and selects |
| * them in the diagram.<br> |
| * Note that in case of the {@link CommonNavigator} as event source, its |
| * editor linking mechanism must be enabled. |
| * |
| * @param part |
| * the source {@link IWorkbenchPart} that triggered the event |
| * @param selection |
| * the new selection (mostly a {@link IStructuredSelection} |
| * instance. |
| * |
| * @since 0.9 |
| */ |
| public void selectionChanged(IWorkbenchPart part, ISelection selection) { |
| // If not the active editor, ignore selection changed. |
| boolean editorIsActive = getSite().getPage().isPartVisible(this); |
| if (!editorIsActive) { |
| // Check if we are a page of the active multi page editor |
| IEditorPart activeEditor = getSite().getPage().getActiveEditor(); |
| if (activeEditor != null) { |
| if (activeEditor instanceof MultiPageEditorPart) { |
| Object selectedPage = ((MultiPageEditorPart) activeEditor).getAdapter(getClass()); |
| if (selectedPage instanceof DiagramEditor) { |
| // Editor is active and diagram sub editor is its active |
| // page |
| editorIsActive = true; |
| } |
| } |
| } |
| } |
| if (editorIsActive) { |
| // long start = System.nanoTime(); |
| // this is where we should check the selection source (part) |
| // * for CNF view the link flag must be obeyed |
| // this would however require a dependency to |
| // org.eclipse.ui.navigator |
| if (part instanceof CommonNavigator) { |
| if (!((CommonNavigator) part).isLinkingEnabled()) { |
| return; |
| } |
| } |
| // useful selection ?? |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection) selection; |
| List<PictogramElement> peList = new ArrayList<PictogramElement>(); |
| // Collect all Pictogram Elements for all selected domain |
| // objects into one list |
| for (Iterator<?> iterator = structuredSelection.iterator(); iterator.hasNext();) { |
| Object object = iterator.next(); |
| if (object instanceof EObject) { |
| // Find the Pictogram Elements for the given domain |
| // object via the standard link service |
| List<PictogramElement> referencingPes = Graphiti.getLinkService().getPictogramElements( |
| getDiagramTypeProvider().getDiagram(), (EObject) object); |
| if (referencingPes.size() > 0) { |
| peList.addAll(referencingPes); |
| } |
| } else { |
| // For non-EMF domain objects use the registered |
| // notification service for finding |
| PictogramElement[] relatedPictogramElements = getDiagramTypeProvider().getNotificationService() |
| .calculateRelatedPictogramElements(new Object[] { object }); |
| for (int i = 0; i < relatedPictogramElements.length; i++) { |
| peList.add(relatedPictogramElements[i]); |
| } |
| } |
| } |
| |
| // Do the selection in the diagram (in case there is something |
| // to select) |
| PictogramElement[] pes = null; |
| if (peList.size() > 0) { |
| pes = peList.toArray(new PictogramElement[peList.size()]); |
| } |
| if (pes != null && pes.length > 0) { |
| selectPictogramElements(pes); |
| } |
| } |
| /* |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=387971: When |
| * embedding a diagram editor inside a multi page editor the |
| * registered actions were not updated. The fix was simply not to |
| * delegate to super.selectionChange where a check for the editor |
| * being active only checks for the main editor (GEF editor is not |
| * embeddable inside another editor) but to trigger the action |
| * update ourself when our checks say the diagram editor is active. |
| */ |
| updateActions(getSelectionActions()); |
| } |
| |
| } |
| |
| /** |
| * Selects the given {@link PictogramElement}s in the diagram. |
| * |
| * @param pictogramElements |
| * an array of {@link PictogramElement}s to select. |
| * @since 0.9 |
| */ |
| public void selectPictogramElements(PictogramElement[] pictogramElements) { |
| diagramBehavior.selectPictogramElements(pictogramElements); |
| } |
| |
| /** |
| * Sets one {@link PictogramElement} for later selection. |
| * <p> |
| * The methods {@link #getPictogramElementsForSelection()}, |
| * {@link #setPictogramElementForSelection(PictogramElement)}, |
| * {@link #setPictogramElementsForSelection(PictogramElement[])} and |
| * {@link DiagramSupport#selectBufferedPictogramElements()} offer the |
| * possibility to use a deferred selection mechanism: via the setters, |
| * {@link PictogramElement}s can be stored for a selection operation that is |
| * triggered lateron during a general refresh via the method |
| * {@link DiagramSupport#selectBufferedPictogramElements()}. This mechanism |
| * is used e.g. in the Graphiti framework in direct editing to restore the |
| * previous selection, but can also be used by clients. |
| * |
| * @param pictogramElement |
| * the {@link PictogramElement} that shall be stored for later |
| * selection |
| * @since 0.9 |
| */ |
| public void setPictogramElementForSelection(PictogramElement pictogramElement) { |
| diagramBehavior.setPictogramElementForSelection(pictogramElement); |
| } |
| |
| /** |
| * Sets {@link PictogramElement}s for later selection. |
| * <p> |
| * The methods {@link #getPictogramElementsForSelection()}, |
| * {@link #setPictogramElementForSelection(PictogramElement)}, |
| * {@link #setPictogramElementsForSelection(PictogramElement[])} and |
| * {@link DiagramSupport#selectBufferedPictogramElements()} offer the |
| * possibility to use a deferred selection mechanism: via the setters, |
| * {@link PictogramElement}s can be stored for a selection operation that is |
| * triggered lateron during a general refresh via the method |
| * {@link DiagramSupport#selectBufferedPictogramElements()}. This mechanism |
| * is used e.g. in the Graphiti framework in direct editing to restore the |
| * previous selection, but can also be used by clients. |
| * |
| * @param pictogramElements |
| * the {@link PictogramElement}s that shall be stored for later |
| * selection |
| * @since 0.9 |
| */ |
| public void setPictogramElementsForSelection(PictogramElement pictogramElements[]) { |
| diagramBehavior.setPictogramElementsForSelection(pictogramElements); |
| } |
| |
| // ---------------------- Other ----------------------------------------- // |
| |
| /** |
| * Returns the ID for contributions in the tabbed property sheets by |
| * delegating to the method {@link IToolBehaviorProvider#getContributorId()} |
| * . |
| * |
| * @return the contributor id as a {@link String} |
| * @since 0.9 |
| */ |
| public String getContributorId() { |
| |
| if (contributorId == null) { |
| IToolBehaviorProvider tbp = getToolBehaviorProvider(); |
| if (tbp != null) { |
| contributorId = tbp.getContributorId(); |
| } |
| } |
| return contributorId; |
| } |
| |
| /** |
| * Returns the {@link IDiagramTypeProvider} instance associated with this |
| * {@link DiagramEditor}. There is always a 1:1 relation between the editor |
| * and the provider. |
| * <p> |
| * Note that this is a pure delegation method. Overrides should happen in |
| * {@link DiagramBehavior}. |
| * |
| * @return the associated {@link IDiagramTypeProvider} instance. |
| * |
| * @since 0.9 |
| */ |
| public IDiagramTypeProvider getDiagramTypeProvider() { |
| return diagramBehavior.getDiagramTypeProvider(); |
| } |
| |
| /** |
| * Returns the GEF edit domain as needed for some of the feature |
| * functionality in Graphiti; simply a public rewrite of the GEF editor |
| * super method. |
| * |
| * @return the {@link DefaultEditDomain} used in this editor |
| * @see GraphicalEditor#getEditDomain() |
| * |
| * @since 0.9 |
| */ |
| public DefaultEditDomain getEditDomain() { |
| return super.getEditDomain(); |
| } |
| |
| /** |
| * Returns the GEF {@link GraphicalViewer} as it is needed in some Graphiti |
| * feature implementations. This is simply a public rewrite of the according |
| * super method. |
| * |
| * @return the {@link GraphicalViewer} used within this editor instance |
| * @see GraphicalEditor#getGraphicalViewer() |
| */ |
| public GraphicalViewer getGraphicalViewer() { |
| return super.getGraphicalViewer(); |
| } |
| |
| /** |
| * Returns the tooltip that shall be displayed when hovering over the editor |
| * title tab. |
| * |
| * @return the tooltip as a {@link String} |
| */ |
| public String getTitleToolTip() { |
| if (getDiagramTypeProvider() != null && getDiagramTypeProvider().getCurrentToolBehaviorProvider() != null) { |
| IToolBehaviorProvider tbp = getDiagramTypeProvider().getCurrentToolBehaviorProvider(); |
| String titleToolTip = tbp.getTitleToolTip(); |
| if (titleToolTip != null) { |
| return titleToolTip; |
| } |
| } |
| return super.getTitleToolTip(); |
| } |
| |
| private IToolBehaviorProvider getToolBehaviorProvider() { |
| IDiagramTypeProvider dtp = getDiagramTypeProvider(); |
| if (dtp != null) { |
| return dtp.getCurrentToolBehaviorProvider(); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the EMF {@link TransactionalEditingDomain} used within this |
| * editor by delegating to the update behavior extension, by default |
| * {@link DefaultUpdateBehavior#getEditingDomain()}. |
| * |
| * @return the {@link TransactionalEditingDomain} instance used in the |
| * editor |
| * |
| * @since 0.9 |
| */ |
| public TransactionalEditingDomain getEditingDomain() { |
| return diagramBehavior.getEditingDomain(); |
| } |
| |
| /** |
| * @since 0.10 |
| */ |
| public IDiagramEditorInput getDiagramEditorInput() { |
| return diagramBehavior.getInput(); |
| } |
| |
| /** |
| * Returns the {@link IWorkbenchPart} for this container. Since this editor |
| * itself is already a part the default implementation simply returns this. |
| * |
| * @return This part |
| * @since 0.10 |
| */ |
| public IWorkbenchPart getWorkbenchPart() { |
| return this; |
| } |
| |
| /** |
| * @since 0.10 |
| */ |
| public void close() { |
| getSite().getPage().closeEditor(this, false); |
| } |
| |
| /* GEF methods that need to be part of the IGEFDiagramContainer interface. */ |
| |
| /** |
| * @since 0.10 |
| */ |
| public void setEditDomain(DefaultEditDomain editDomain) { |
| super.setEditDomain(editDomain); |
| } |
| |
| public ActionRegistry getActionRegistry() { |
| return super.getActionRegistry(); |
| } |
| |
| @SuppressWarnings("rawtypes") |
| public List getSelectionActions() { |
| return super.getSelectionActions(); |
| } |
| |
| public void commandStackChanged(EventObject event) { |
| super.commandStackChanged(event); |
| } |
| |
| public void setGraphicalViewer(GraphicalViewer viewer) { |
| super.setGraphicalViewer(viewer); |
| } |
| |
| public void hookGraphicalViewer() { |
| super.hookGraphicalViewer(); |
| } |
| } |