blob: 73a5f95edcc9a20dd8ac475f148176b27ebe3390 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 THALES GLOBAL SERVICES 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.diagram.ui.tools.internal.editor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.operations.IOperationHistoryListener;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.ObjectUndoContext;
import org.eclipse.core.commands.operations.UndoContext;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
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.EValidator;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.workspace.IWorkspaceCommandStack;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.MouseWheelHandler;
import org.eclipse.gef.MouseWheelZoomHandler;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.dnd.AbstractTransferDropTargetListener;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.gef.ui.rulers.RulerComposite;
import org.eclipse.gmf.runtime.common.ui.action.IDisposableAction;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument;
import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocumentProvider;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.sirius.business.api.dialect.command.RefreshRepresentationsCommand;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionListener;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.sirius.business.api.session.SessionManagerListener;
import org.eclipse.sirius.common.tools.DslCommonPlugin;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
import org.eclipse.sirius.common.ui.tools.api.util.IObjectActionDelegateWrapper;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DSemanticDiagram;
import org.eclipse.sirius.diagram.DiagramPlugin;
import org.eclipse.sirius.diagram.business.api.query.DDiagramElementQuery;
import org.eclipse.sirius.diagram.tools.api.command.DiagramCommandFactoryService;
import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory;
import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactoryProvider;
import org.eclipse.sirius.diagram.tools.api.command.view.HideDDiagramElement;
import org.eclipse.sirius.diagram.tools.api.command.view.HideDDiagramElementLabel;
import org.eclipse.sirius.diagram.ui.business.api.provider.AbstractDDiagramElementLabelItemProvider;
import org.eclipse.sirius.diagram.ui.business.api.query.DDiagramGraphicalQuery;
import org.eclipse.sirius.diagram.ui.business.api.view.SiriusGMFHelper;
import org.eclipse.sirius.diagram.ui.business.api.view.refresh.CanonicalSynchronizer;
import org.eclipse.sirius.diagram.ui.business.api.view.refresh.CanonicalSynchronizerFactory;
import org.eclipse.sirius.diagram.ui.business.internal.command.RefreshDiagramOnOpeningCommand;
import org.eclipse.sirius.diagram.ui.business.internal.session.DiagramSessionHelper;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDDiagramEditPart;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramNameEditPart;
import org.eclipse.sirius.diagram.ui.edit.internal.part.listener.DiagramHeaderPostCommitListener;
import org.eclipse.sirius.diagram.ui.edit.internal.part.listener.VisibilityPostCommitListener;
import org.eclipse.sirius.diagram.ui.internal.refresh.SiriusDiagramSessionEventBroker;
import org.eclipse.sirius.diagram.ui.internal.refresh.SynchronizeGMFModelCommand;
import org.eclipse.sirius.diagram.ui.internal.refresh.layout.SiriusCanonicalLayoutHandler;
import org.eclipse.sirius.diagram.ui.internal.refresh.listeners.GMFDiagramUpdater;
import org.eclipse.sirius.diagram.ui.part.SiriusDiagramEditor;
import org.eclipse.sirius.diagram.ui.part.SiriusDiagramEditorUtil;
import org.eclipse.sirius.diagram.ui.part.ValidateAction;
import org.eclipse.sirius.diagram.ui.provider.DiagramUIPlugin;
import org.eclipse.sirius.diagram.ui.tools.api.editor.DDiagramEditor;
import org.eclipse.sirius.diagram.ui.tools.api.graphical.edit.palette.PaletteManager;
import org.eclipse.sirius.diagram.ui.tools.api.graphical.edit.palette.ToolFilter;
import org.eclipse.sirius.diagram.ui.tools.api.preferences.SiriusDiagramUiPreferencesKeys;
import org.eclipse.sirius.diagram.ui.tools.api.properties.PropertiesService;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.delete.DeleteFromModelWithHookAction;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.delete.DeleteWithHookAction;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.visibility.HideDDiagramElementAction;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.visibility.HideDDiagramElementLabelAction;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.visibility.RevealOutlineElementsAction;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.visibility.RevealOutlineLabelsAction;
import org.eclipse.sirius.diagram.ui.tools.internal.commands.emf.EMFCommandFactoryUI;
import org.eclipse.sirius.diagram.ui.tools.internal.dnd.DragAndDropWrapper;
import org.eclipse.sirius.diagram.ui.tools.internal.editor.header.DiagramHeaderComposite;
import org.eclipse.sirius.diagram.ui.tools.internal.editor.tabbar.Tabbar;
import org.eclipse.sirius.diagram.ui.tools.internal.editor.tabbar.TabbarRefresher;
import org.eclipse.sirius.diagram.ui.tools.internal.graphical.edit.part.DDiagramRootEditPart;
import org.eclipse.sirius.diagram.ui.tools.internal.menu.DiagramEditorContextMenuProvider;
import org.eclipse.sirius.diagram.ui.tools.internal.menu.DiagramMenuUpdater;
import org.eclipse.sirius.diagram.ui.tools.internal.outline.QuickOutlineControl;
import org.eclipse.sirius.diagram.ui.tools.internal.outline.SiriusInformationPresenter;
import org.eclipse.sirius.diagram.ui.tools.internal.outline.SiriusQuickOutlineInformationProvider;
import org.eclipse.sirius.diagram.ui.tools.internal.palette.PaletteManagerImpl;
import org.eclipse.sirius.diagram.ui.tools.internal.palette.SiriusPaletteViewer;
import org.eclipse.sirius.diagram.ui.tools.internal.part.SiriusDiagramGraphicalViewer;
import org.eclipse.sirius.diagram.ui.tools.internal.providers.decorators.SubDiagramDecoratorProvider;
import org.eclipse.sirius.diagram.ui.tools.internal.resource.CustomSiriusDocumentProvider;
import org.eclipse.sirius.diagram.ui.tools.internal.views.outlineview.DiagramOutlineWithBookPages;
import org.eclipse.sirius.diagram.ui.tools.internal.views.providers.outline.OutlineComparator;
import org.eclipse.sirius.diagram.ui.tools.internal.views.providers.outline.OutlineContentProvider;
import org.eclipse.sirius.diagram.ui.tools.internal.views.providers.outline.OutlineLabelProvider;
import org.eclipse.sirius.ecore.extender.business.api.permission.IAuthorityListener;
import org.eclipse.sirius.ecore.extender.business.api.permission.IPermissionAuthority;
import org.eclipse.sirius.ecore.extender.business.api.permission.LockStatus;
import org.eclipse.sirius.ecore.extender.business.api.permission.PermissionAuthorityRegistry;
import org.eclipse.sirius.ecore.extender.business.internal.permission.ReadOnlyWrapperPermissionAuthority;
import org.eclipse.sirius.ecore.extender.tool.api.ModelUtils;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.tools.api.command.EditingDomainUndoContext;
import org.eclipse.sirius.tools.api.command.listener.ChangeListenerFactory;
import org.eclipse.sirius.tools.api.command.listener.IChangeListener;
import org.eclipse.sirius.tools.api.interpreter.InterpreterRegistry;
import org.eclipse.sirius.tools.api.permission.DRepresentationPermissionStatusListener;
import org.eclipse.sirius.tools.api.permission.DRepresentationPermissionStatusQuery;
import org.eclipse.sirius.tools.api.profiler.SiriusTasksKey;
import org.eclipse.sirius.tools.api.ui.property.IPropertiesProvider;
import org.eclipse.sirius.ui.business.api.dialect.DialectEditor;
import org.eclipse.sirius.ui.business.api.dialect.DialectEditorDialogFactory;
import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager;
import org.eclipse.sirius.ui.business.api.dialect.marker.TraceabilityMarkerNavigationProvider;
import org.eclipse.sirius.ui.business.api.session.IEditingSession;
import org.eclipse.sirius.ui.business.api.session.SessionEditorInput;
import org.eclipse.sirius.ui.business.api.session.SessionEditorInputFactory;
import org.eclipse.sirius.ui.business.api.session.SessionUIManager;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.DRepresentationElement;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* The diagram editor.
*
* @author mchauvin
* @since 0.9.0
*/
public class DDiagramEditorImpl extends SiriusDiagramEditor implements DDiagramEditor, ISelectionListener, SessionListener {
/**
* The ID of the editor in the Editor Registry.
*/
public static final String ID = DDiagramEditor.EDITOR_ID;
/**
* My undo context.
*/
protected IUndoContext undoContext;
/**
* This is the one adapter factory used for providing views of the model (as
* in EcoreEditor).
*/
protected AdapterFactory adapterFactory;
private Session session;
/** The key handler */
private KeyHandler keyHandler;
private TemplateTransferDragSourceListener paletteTransferDragSourceListener;
private SiriusPaletteToolDropTargetListener paletteTransferDropTargetListener;
/**
* The abstract transfer drop target listener.
*/
private AbstractTransferDropTargetListener transferDropTargetListener;
/** the emf command factory provider */
private IDiagramCommandFactoryProvider emfCommandFactoryProvider;
private DiagramOutlinePage diagramOutline;
private boolean isClosing;
private IPermissionAuthority authority;
private IAuthorityListener dRepresentationLockStatusListener;
private final SessionManagerListener sessionManagerListener = new SessionManagerListener.Stub() {
@Override
public void notifyAddSession(final Session newSession) {
/* we want to be notified only once */
final IEditingSession editingSession = SessionUIManager.INSTANCE.getOrCreateUISession(newSession);
if (!editingSession.isOpen()) {
editingSession.open();
editingSession.attachEditor(DDiagramEditorImpl.this);
/*
* need to reinit command factory provider to take the right
* model accesor
*/
initCommandFactoryProviders();
/* remove this listener */
SessionManager.INSTANCE.removeSessionsListener(this);
}
}
};
private TabbarRefresher tabbarPostCommitListener;
private DiagramHeaderPostCommitListener diagramHeaderPostCommitListener;
private VisibilityPostCommitListener visibilityPostCommitListener;
private GMFDiagramUpdater gmfDiagramUpdater;
/**
* A changeListener to listen changes (if activated).
*/
private IChangeListener changeListener;
private DialectEditorDialogFactory myDialogFactory = new DiagramDialectEditorDialogFactory(this);
private final IOperationHistoryListener operationHistoryListener = new DOperationHistoryListener(this);
private PaletteManager paletteManager;
private Tabbar tabbar;
/**
* A Selection listeners that react to any selection changes by updating the
* "Diagram" Menu.
*/
private DiagramMenuUpdater diagramMenuUpdater;
private ScrollingGraphicalViewer sGViewer;
private DiagramHeaderComposite diagramHeaderComposite;
private ToolFilter toolFilterWhenRepresentationIsLocked = new ToolFilterForLockedDRepresentation();
private Composite parentComposite;
private Job refreshJob;
/**
* Create a new instance.
*/
public DDiagramEditorImpl() {
super();
}
@Override
public void close(boolean save) {
if (refreshJob != null) {
try {
refreshJob.join();
} catch (InterruptedException e) {
DiagramPlugin.getDefault().getLog().log(new Status(IStatus.INFO, DiagramPlugin.ID, "Refresh job got interrupted", e));
}
}
super.close(save);
}
/**
* We have to take care of the case when Eclipse starts up with a session.
* and diagram already open. {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.part.SiriusDiagramEditor#init(org.eclipse.ui.IEditorSite,
* org.eclipse.ui.IEditorInput)
*/
@Override
public void init(final IEditorSite site, IEditorInput input) throws PartInitException {
IEditorInput correctedInput = getCorrectedInput(input);
if (correctedInput instanceof SessionEditorInput) {
this.session = ((SessionEditorInput) correctedInput).getSession();
}
final Collection<Session> sessions = SessionManager.INSTANCE.getSessions();
/*
* we are during eclipse boot, we are not trying to close the editor
*/
if (sessions.isEmpty() && (!isClosing)) {
SessionManager.INSTANCE.addSessionsListener(sessionManagerListener);
}
isClosing = false;
try {
if (getSession() != null) {
// Initialize the undo context
initUndoContext();
// Enable GMF notation model canonical refresh in pre-commit
// called here to be notified before the DiagramEventBroker
SiriusDiagramSessionEventBroker.getInstance(getSession());
}
super.init(site, correctedInput);
if (getSession() != null) {
getSession().addListener(this);
/* checks the SessionUIManager. */
final IEditingSession editingSession = SessionUIManager.INSTANCE.getOrCreateUISession(getSession());
editingSession.open();
editingSession.attachEditor(this);
}
initCommandFactoryProviders();
/* Update title. Semantic diagram could have been renamed */
notify(PROP_TITLE);
initCollaborativeIPermissionAuthority();
} catch (NullPointerException e) {
DiagramPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, DiagramPlugin.ID, "Error while getting the session.", e));
}
}
private void initUndoContext() {
if (undoContext == null) {
final TransactionalEditingDomain domain = getEditingDomain();
if (domain != null) {
if (domain.getCommandStack() instanceof IWorkspaceCommandStack) {
undoContext = ((IWorkspaceCommandStack) domain.getCommandStack()).getDefaultUndoContext();
} else {
undoContext = new EditingDomainUndoContext(domain);
}
} else {
undoContext = new ObjectUndoContext(this);
}
}
}
private IEditorInput getCorrectedInput(IEditorInput input) {
if (input instanceof FileEditorInput) {
IFile file = ((FileEditorInput) input).getFile();
URI analysisURI = URI.createPlatformResourceURI("/" + file.getProject().getName() + "/" + file.getProjectRelativePath(), true);
return new SessionEditorInputFactory().create(analysisURI);
}
return input;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
// Initialize drag'n drop listener from palette
// PaletteViewer paletteViewer =
// getPaletteViewerProvider().getEditDomain().getPaletteViewer();
// paletteTransferDragSourceListener = new
// TemplateTransferDragSourceListener(paletteViewer);
// paletteViewer.addDragSourceListener(paletteTransferDragSourceListener);
//
// paletteTransferDropTargetListener = new
// ViewpointPaletteToolDropTargetListener(getGraphicalViewer());
// getDiagramGraphicalViewer().addDropTargetListener(paletteTransferDropTargetListener);
tabbarPostCommitListener = new TabbarRefresher(getEditingDomain());
visibilityPostCommitListener = new VisibilityPostCommitListener(getDiagramEditPart());
if (isHeaderSectionEnabled()) {
diagramHeaderPostCommitListener = new DiagramHeaderPostCommitListener(getEditingDomain(), getDiagramHeader());
}
// Update palette : should be hidden if diagram is not editable
if (!getPermissionAuthority().canEditInstance(getRepresentation())) {
notify(REPRESENTATION_EDITION_PERMISSION_DENIED);
}
}
/**
* Overridden to instantiate a {@link SiriusPaletteViewer} instead of the
* standard one, to support creation from the palette with drag'n drop.
*
* {@inheritDoc}
*/
protected PaletteViewer constructPaletteViewer() {
// return new ViewpointPaletteViewer();
PaletteViewer pv = new SiriusPaletteViewer();
// Initialize drag'n drop listener from palette
paletteTransferDragSourceListener = new TemplateTransferDragSourceListener(pv);
pv.addDragSourceListener(paletteTransferDragSourceListener);
// Handle the palette view case.
if (paletteManager != null) {
paletteManager.update(getDiagram());
}
return pv;
}
/**
* Overridden to change the visibility of the inherited method.
*
* {@inheritDoc}
*/
@Override
public void setTitleImage(Image titleImage) {
super.setTitleImage(titleImage);
}
/**
* Initialize CDO {@link IPermissionAuthority} and the title image if the
* Diagram is already locked by the current user before opening.
*/
private void initCollaborativeIPermissionAuthority() {
// This IPermissionAuthority is added only on shared
// representations.
IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(getDiagram().getElement());
dRepresentationLockStatusListener = new DRepresentationPermissionStatusListener((DSemanticDiagram) getDiagram().getElement(), this);
permissionAuthority.addAuthorityListener(dRepresentationLockStatusListener);
if (!permissionAuthority.canEditInstance(this.getRepresentation())) {
notify(SessionListener.REPRESENTATION_EDITION_PERMISSION_DENIED);
} else if (permissionAuthority instanceof ReadOnlyWrapperPermissionAuthority) {
// Find the CDOLockBasedPermissionAuthority and investigate by
// introspection if the diagram is "locked by me" in order to
// display the proper title image
ReadOnlyWrapperPermissionAuthority readOnlyWrapperPermissionAuthority = (ReadOnlyWrapperPermissionAuthority) permissionAuthority;
IPermissionAuthority wrappedAuthority = readOnlyWrapperPermissionAuthority.getWrappedAuthority();
if ("CDOLockBasedPermissionAuthority".equals(wrappedAuthority.getClass().getSimpleName())) {
if (LockStatus.LOCKED_BY_ME.equals(wrappedAuthority.getLockStatus(getDiagram().getElement()))) {
notify(SessionListener.REPRESENTATION_EDITION_PERMISSION_GRANTED_TO_CURRENT_USER_EXCLUSIVELY);
}
}
}
}
/**
* {@inheritDoc}
*/
public IDiagramCommandFactoryProvider getEmfCommandFactoryProvider() {
return emfCommandFactoryProvider;
}
/**
* {@inheritDoc}
*/
public void setEmfCommandFactoryProvider(IDiagramCommandFactoryProvider emfCommandFactoryProvider) {
this.emfCommandFactoryProvider = emfCommandFactoryProvider;
configureCommandFactoryProviders();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#getKeyHandler()
*/
@Override
protected KeyHandler getKeyHandler() {
if (keyHandler == null) {
keyHandler = super.getKeyHandler();
/* map our custom delete action */
final ActionRegistry registry = getActionRegistry();
final IDisposableAction deleteFromModelAction = new DeleteFromModelWithHookAction(this);
deleteFromModelAction.init();
registry.registerAction(deleteFromModelAction);
final IAction deleteAction = new DeleteWithHookAction(this);
deleteAction.setText(DiagramUIMessages.DiagramEditor_Delete_from_Diagram);
registry.registerAction(deleteAction);
keyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0), getActionRegistry().getAction(ActionFactory.DELETE.getId()));
keyHandler.put(/* CTRL + D */
KeyStroke.getPressed((char) 0x4, 100, SWT.CTRL), getActionRegistry().getAction(ActionIds.ACTION_DELETE_FROM_MODEL));
}
return keyHandler;
}
/**
* @see org.eclipse.sirius.business.api.componentization.ViewpointRegistryListener2#modelerDesciptionFilesLoaded()
*/
private void modelerDescriptionFilesLoaded() {
if (isAutoRefresh()) {
// reload the palette when a .odesign is reloaded
// already done be DDiagramEditorSessionListenerDelegate.
// Run refresh in a job to avoid taking lock on the Workspace on
// representation change, while the lock is already taken on odesign
// change
refreshJob = new Job("Refresh ") {
@Override
protected IStatus run(IProgressMonitor monitor) {
launchRefresh(false);
return Status.OK_STATUS;
}
};
refreshJob.schedule();
}
}
private void initCommandFactoryProviders() {
/* get IEMFCommandFactories */
emfCommandFactoryProvider = DiagramCommandFactoryService.getInstance().getNewProvider();
configureCommandFactoryProviders();
}
private void configureCommandFactoryProviders() {
/*
* We add a callback for UI stuffs
*/
IDiagramCommandFactory diagramCommandFactory = emfCommandFactoryProvider.getCommandFactory(getEditingDomain());
diagramCommandFactory.setUserInterfaceCallBack(new EMFCommandFactoryUI());
}
/**
* Overridden to not create a new {@link TransactionalEditingDomain} but
* return the {@link Session#getTransactionalEditingDomain()}.
*
* @return the {@link Session#getTransactionalEditingDomain()}
*/
@Override
protected TransactionalEditingDomain createEditingDomain() {
return getSession().getTransactionalEditingDomain();
}
/**
* Called when the diagram is displayed. Updates the Palette.
*
* {@inheritDoc}
*/
@Override
protected void hookGraphicalViewer() {
super.hookGraphicalViewer();
final Diagram gmfDiagram = getDiagram();
/* manage palette. */
paletteManager = new PaletteManagerImpl(getEditDomain());
paletteManager.update(getDiagram());
// Initialize drag'n drop listener from palette
paletteTransferDropTargetListener = new SiriusPaletteToolDropTargetListener(getGraphicalViewer());
getDiagramGraphicalViewer().addDropTargetListener(paletteTransferDropTargetListener);
/* initialize Java Service. */
EObject semantic = ViewUtil.resolveSemanticElement(gmfDiagram);
if (semantic instanceof DSemanticDecorator) {
// Add a ChangeListener to the DDiagram
changeListener = ChangeListenerFactory.INSTANCE.getNewChangeListener();
semantic.eAdapters().add(changeListener);
semantic = ((DSemanticDecorator) semantic).getTarget();
if (semantic != null && semantic.eResource() == null) {
ModelUtils.resolveAll(semantic);
}
}
// Semantic element can be null if the editor has been opened from the
// project explorer (=> a GMF Diagram associated to no semantic element
// is created)
if (semantic != null) {
final IInterpreter interpreter = SiriusPlugin.getDefault().getInterpreterRegistry().getInterpreter(semantic);
InterpreterRegistry.prepareImportsFromSession(interpreter, SessionManager.INSTANCE.getSession(semantic));
}
/* add a listener to selection */
getSite().getPage().addSelectionListener(this);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor#dispose()
*/
@Override
public void dispose() {
isClosing = true;
// Dispose the tabbar (to avoir memory leak)
if (getTabbar() != null) {
getTabbar().dispose();
setTabbar(null);
}
// Dispose post-commit listener
disposePostCommitListener();
if (gmfDiagramUpdater != null) {
gmfDiagramUpdater.dispose();
gmfDiagramUpdater = null;
}
// Remove the change listener ContentAdapter.
if (getDiagram() != null && getDiagram().eResource() != null) {
try {
EObject semantic = ViewUtil.resolveSemanticElement(getDiagram());
if (semantic instanceof DSemanticDecorator) {
// Remove the ChangeListener to the DDiagram
semantic.eAdapters().remove(changeListener);
// Can cause a NPE with CDO
}
} catch (NullPointerException e) {
// nothing to do, rest of dispose steps will be performed
}
if (dRepresentationLockStatusListener != null) {
IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(getDiagram().getElement());
permissionAuthority.removeAuthorityListener(dRepresentationLockStatusListener);
}
}
SessionManager.INSTANCE.removeSessionsListener(sessionManagerListener);
dRepresentationLockStatusListener = null;
if (getSession() != null) {
getSession().removeListener(this);
}
if (getGraphicalViewer() != null) {
getGraphicalViewer().removeDropTargetListener(transferDropTargetListener);
}
/* It is a very good idea to detach the editor from the session */
if (this.getDiagram() != null) {
if (getSession() != null) {
final IEditingSession editingSession = SessionUIManager.INSTANCE.getUISession(getSession());
if (editingSession != null) {
editingSession.detachEditor(this);
}
}
}
if (getSite() != null) {
getSite().getPage().removeSelectionListener(this);
}
getOperationHistory().removeOperationHistoryListener(this.operationHistoryListener);
if (adapterFactory instanceof IDisposable) {
((IDisposable) adapterFactory).dispose();
}
PaletteViewer paletteViewer = getPaletteViewerProvider().getEditDomain().getPaletteViewer();
if (paletteViewer != null) {
paletteViewer.removeDragSourceListener(paletteTransferDragSourceListener);
getGraphicalViewer().removeDropTargetListener(paletteTransferDropTargetListener);
}
/* dispose the palette manager */
if (paletteManager != null) {
paletteManager.dispose();
paletteManager = null;
}
if (sGViewer != null) {
if (sGViewer.getControl() != null) {
sGViewer.getControl().dispose();
}
sGViewer = null;
}
disposeOutline();
// Dispose the session editor input to keep the minimum information to
// be restore from the INavigationHistory and EditorHistory.
if (getEditorInput() instanceof SessionEditorInput) {
((SessionEditorInput) getEditorInput()).dispose();
}
IUndoContext savedUndoContext = getUndoContext();
// to avoid dispose of current session related IUndoeableOperation
setUndoContext(new UndoContext());
super.dispose();
setUndoContext(savedUndoContext);
// If possible, remove the diagram event broker for the listening of the
// transactional editing domain
stopDiagramEventBrokerListener(getEditingDomain());
}
private void disposeOutline() {
if (diagramOutline != null) {
this.diagramOutline = null;
}
}
private void disposePostCommitListener() {
if (tabbarPostCommitListener != null) {
tabbarPostCommitListener.dispose();
tabbarPostCommitListener = null;
}
if (visibilityPostCommitListener != null) {
visibilityPostCommitListener.dispose();
visibilityPostCommitListener = null;
}
if (diagramHeaderPostCommitListener != null) {
diagramHeaderPostCommitListener.dispose();
diagramHeaderPostCommitListener = null;
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.part.SiriusDiagramEditor#configureGraphicalViewer()
*/
@Override
protected void configureGraphicalViewer() {
super.configureGraphicalViewer();
/* register our menu provider to provide our custom delete action */
final DiagramEditorContextMenuProvider provider = new DiagramEditorContextMenuProvider(this, getDiagramGraphicalViewer());
getDiagramGraphicalViewer().setContextMenu(provider);
getSite().registerContextMenu(ActionIds.DIAGRAM_EDITOR_CONTEXT_MENU, provider, getDiagramGraphicalViewer());
getOperationHistory().addOperationHistoryListener(operationHistoryListener);
// add the wheel mouse to zoom
this.getGraphicalViewer().setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.CTRL), MouseWheelZoomHandler.SINGLETON);
}
private void initOutline() {
/** the outline popup menu items and associated actions */
IObjectActionDelegateWrapper[] outlinePopupMenuActions = new IObjectActionDelegateWrapper[] {
new IObjectActionDelegateWrapper(new HideDDiagramElementAction(HideDDiagramElement.HIDE_ELEMENT_LABEL), HideDDiagramElement.HIDE_ELEMENT_LABEL) {
@Override
public ImageDescriptor getImageDescriptor() {
return ((IAction) getWrappedAction()).getImageDescriptor();
}
@Override
public boolean isEnabled() {
if (currentSelection instanceof IStructuredSelection) {
final Object selectedObject = ((IStructuredSelection) currentSelection).getFirstElement();
if (selectedObject instanceof DDiagramElement) {
boolean isHidden = !new DDiagramElementQuery((DDiagramElement) selectedObject).isHidden();
boolean wrappedActionEnabled = ((IAction) getWrappedAction()).isEnabled();
return isHidden && wrappedActionEnabled;
}
}
return false;
}
}, new IObjectActionDelegateWrapper(new HideDDiagramElementLabelAction(HideDDiagramElementLabel.HIDE_LABEL), HideDDiagramElementLabel.HIDE_LABEL) {
@Override
public ImageDescriptor getImageDescriptor() {
return ((IAction) getWrappedAction()).getImageDescriptor();
}
@Override
public boolean isEnabled() {
boolean result = false;
if (currentSelection instanceof IStructuredSelection) {
final Object selectedObject = ((IStructuredSelection) currentSelection).getFirstElement();
if (selectedObject instanceof DDiagramElement) {
DDiagramElementQuery query = new DDiagramElementQuery((DDiagramElement) selectedObject);
result = query.canHideLabel() && !query.isLabelHidden();
} else if (selectedObject instanceof AbstractDDiagramElementLabelItemProvider) {
Option<DDiagramElement> optionTarget = ((AbstractDDiagramElementLabelItemProvider) selectedObject).getDiagramElementTarget();
if (optionTarget.some()) {
DDiagramElementQuery query = new DDiagramElementQuery(optionTarget.get());
result = query.canHideLabel() && !query.isLabelHidden();
}
}
}
return result;
}
}, new IObjectActionDelegateWrapper(new RevealOutlineElementsAction(), RevealOutlineElementsAction.REVEAL_ELEMENT_LABEL) {
@Override
public ImageDescriptor getImageDescriptor() {
return ((IAction) getWrappedAction()).getImageDescriptor();
}
@Override
public boolean isEnabled() {
if (currentSelection instanceof IStructuredSelection) {
final Object selectedObject = ((IStructuredSelection) currentSelection).getFirstElement();
if (selectedObject instanceof DDiagramElement) {
return new DDiagramElementQuery((DDiagramElement) selectedObject).isHidden();
}
}
return false;
}
}, new IObjectActionDelegateWrapper(new RevealOutlineLabelsAction(), RevealOutlineLabelsAction.REVEAL_LABEL_LABEL) {
@Override
public ImageDescriptor getImageDescriptor() {
return ((IAction) getWrappedAction()).getImageDescriptor();
}
@Override
public boolean isEnabled() {
boolean result = false;
if (currentSelection instanceof IStructuredSelection) {
final Object selectedObject = ((IStructuredSelection) currentSelection).getFirstElement();
if (selectedObject instanceof DDiagramElement) {
DDiagramElementQuery query = new DDiagramElementQuery((DDiagramElement) selectedObject);
result = query.isLabelHidden();
} else if (selectedObject instanceof AbstractDDiagramElementLabelItemProvider) {
Option<DDiagramElement> optionTarget = ((AbstractDDiagramElementLabelItemProvider) selectedObject).getDiagramElementTarget();
if (optionTarget.some()) {
DDiagramElementQuery query = new DDiagramElementQuery(optionTarget.get());
result = query.isLabelHidden();
}
}
}
return result;
}
}, };
if (isOldUIEnabled()) {
diagramOutline = new DiagramOutlineWithBookPages(this.getDiagramEditPart().getModel(), getGraphicalViewer(), outlinePopupMenuActions);
} else {
diagramOutline = new DiagramOutlinePage(this.getDiagramEditPart().getModel(), new OutlineLabelProvider(), new OutlineContentProvider(), new OutlineComparator(), getGraphicalViewer(), outlinePopupMenuActions);
}
}
/**
* We hook the set focus in order to refresh the root edit part so that the
* sub diagram decorators will get refreshed.
*/
@Override
public void setFocus() {
super.setFocus();
final Iterator<EditPart> iterParts = getDiagramGraphicalViewer().getRootEditPart().getChildren().iterator();
while (iterParts.hasNext()) {
final EditPart editPart = iterParts.next();
if (editPart instanceof AbstractDDiagramEditPart && ((GraphicalEditPart) editPart).resolveSemanticElement() instanceof DSemanticDiagram) {
final DSemanticDiagram semanticElement = (DSemanticDiagram) ((GraphicalEditPart) editPart).resolveSemanticElement();
if (semanticElement == null || semanticElement.eResource() == null || semanticElement.getTarget() == null || semanticElement.getTarget().eResource() == null) {
// The session may not be accessible if the session is using
// CDOResources and the server is down
if (SessionManager.INSTANCE.getSession(semanticElement.getTarget()) != null) {
/*
* The element has been deleted, we should close the
* editor
*/
myDialogFactory.editorWillBeClosedInformationDialog(getSite().getShell());
close(false);
}
return;
}
}
}
// if (isAutoRefresh()) {
// final Diagram gmfDiagram = this.getDiagram();
// final EObject resolvedSemanticElement =
// ViewUtil.resolveSemanticElement(gmfDiagram);
// if (resolvedSemanticElement instanceof DRepresentation) {
// getEditingDomain().getCommandStack().execute(new
// RefreshRepresentationCommand(getEditingDomain(), (DRepresentation)
// resolvedSemanticElement));
// }
// }
if (getGraphicalViewer() != null) {
if (getGraphicalViewer().getRootEditPart() != null) {
/* Let's refresh the edit parts */
DslCommonPlugin.PROFILER.startWork(SiriusTasksKey.REFRESH_GEF_KEY);
SubDiagramDecoratorProvider.refreshEditParts(getGraphicalViewer().getRootEditPart());
DslCommonPlugin.PROFILER.stopWork(SiriusTasksKey.REFRESH_GEF_KEY);
}
}
if (getOperationHistory() != null) {
// See the javadoc of addOperationHistoryListener. If the listener
// is already registered, the call has no effect.
// so we can safely add the listener here.
getOperationHistory().addOperationHistoryListener(this.operationHistoryListener);
}
setEclipseWindowTitle();
}
private void setEclipseWindowTitle() {
// Updates the title of the eclipse window.
// Removes the xmi id if the selected element and replace it with the
// name of the tab.
String title = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getText();
final int end = title.lastIndexOf(".aird#"); //$NON-NLS-1$
final int end2 = title.lastIndexOf(" - "); //$NON-NLS-1$
if (end > -1) {
title = title.substring(0, end + 5) + this.getPartName() + title.substring(end2);
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setText(title);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#createScrollingGraphicalViewer()
*/
@Override
protected ScrollingGraphicalViewer createScrollingGraphicalViewer() {
return new SiriusDiagramGraphicalViewer();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor#selectionChanged(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
@Override
public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
super.selectionChanged(part, selection);
if (getTabbar() != null) {
getTabbar().selectionChanged(part, selection);
}
// we inform the DiagramMenuUpdater that the selection has changed
if (this.diagramMenuUpdater != null) {
this.diagramMenuUpdater.selectionChanged(part, selection);
}
if (this == part) {
return;
}
if (selection instanceof IStructuredSelection) {
final List<?> selected = ((IStructuredSelection) selection).toList();
final List<IGraphicalEditPart> result = new ArrayList<IGraphicalEditPart>(selected.size());
final IDiagramGraphicalViewer viewer = getDiagramGraphicalViewer();
if (viewer != null) {
for (final Object object : selected) {
if (object instanceof EObject) {
try {
// TODO remove this try/catch once the
// offline mode will be supported
String elementID = EMFCoreUtil.getProxyID((EObject) object);
final List<IGraphicalEditPart> concernedEditParts = viewer.findEditPartsForElement(elementID, IGraphicalEditPart.class);
result.addAll(concernedEditParts);
} catch (IllegalStateException e) {
// An issue has been encountered while connecting to
// remote CDO server
if (DiagramUIPlugin.getPlugin().isDebugging()) {
DiagramUIPlugin.getPlugin().getLog().log(new Status(IStatus.WARNING, DiagramUIPlugin.ID, "Error while connecting to remote CDO server"));
}
}
} else {
if (object instanceof AbstractDDiagramElementLabelItemProvider) {
Option<DDiagramElement> diagramElementTarget = ((AbstractDDiagramElementLabelItemProvider) object).getDiagramElementTarget();
if (diagramElementTarget.some()) {
String elementID = EMFCoreUtil.getProxyID(diagramElementTarget.get());
final List<IGraphicalEditPart> concernedEditParts = viewer.findEditPartsForElement(elementID, IGraphicalEditPart.class);
result.addAll(Sets.newHashSet(Iterables.filter(concernedEditParts, AbstractDiagramNameEditPart.class)));
}
}
}
}
if (!result.isEmpty()) {
try {
getDiagramGraphicalViewer().setSelection(new StructuredSelection(result));
} catch (IllegalArgumentException e) {
// This can happen when selected a CDOObject
// that has been deleted. Simply do not update selection
// in this case
} catch (NullPointerException e) {
// This can happen when selected a CDOObject
// that has been deleted. Simply do not update selection
// in this case
}
}
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.part.EditorPart#isSaveOnCloseNeeded()
*/
@Override
public boolean isSaveOnCloseNeeded() {
/*
* No call to editingSession.needToBeSavedOnClose(this)
*/
return isDirty();
}
/**
* {@inheritDoc}
*/
public Session getSession() {
if (session == null) {
session = getSessionFromDiagramInstance();
}
return session;
}
private Session getSessionFromDiagramInstance() {
if (getDiagram() != null && getDiagram().eResource() != null) {
Session mySession = DiagramSessionHelper.findSession(getDiagram());
if (mySession == null) {
if (getEditorInput() instanceof SessionEditorInput) {
SessionEditorInput sessionEditorInput = (SessionEditorInput) getEditorInput();
mySession = sessionEditorInput.getSession();
}
}
return mySession;
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
protected void setDocumentProvider(final IEditorInput input) {
if (getSession() != null/*
* && (input instanceof IFileEditorInput ||
* input instanceof URIEditorInput)
*/) {
setDocumentProvider(DiagramUIPlugin.getPlugin().getDocumentProvider(getSession().getTransactionalEditingDomain()));
} else {
// super.setDocumentProvider(input);
setDocumentProvider(new CustomSiriusDocumentProvider());
}
}
/**
* {@inheritDoc}
*/
@Override
protected IDocumentProvider getDocumentProvider(final IEditorInput input) {
if (input instanceof IFileEditorInput || input instanceof URIEditorInput) {
return DiagramUIPlugin.getPlugin().getDocumentProvider(getSession().getTransactionalEditingDomain());
}
return super.getDocumentProvider(input);
}
private IEditingSession getUISession() {
return SessionUIManager.INSTANCE.getUISession(getSession());
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.tools.api.editor.DDiagramEditor#getPermissionAuthority()
*/
public IPermissionAuthority getPermissionAuthority() {
if (authority == null) {
authority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(getEditingDomain().getResourceSet());
}
return authority;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.ui.business.api.dialect.DialectEditor#needsRefresh(int)
*/
public boolean needsRefresh(int propId) {
boolean result = false;
if (propId == DialectEditor.PROP_REFRESH) {
if (isAutoRefresh()) {
result = true;
}
} else if (propId == DialectEditor.PROP_FORCE_REFRESH) {
result = true;
}
return result;
}
/**
* {@inheritDoc}
*/
public void validateRepresentation() {
ValidateAction.runValidation(getDiagramEditPart(), getDiagram());
}
/**
* Overridden to delegate {@link SessionListener} events to
* {@link DDiagramEditorSessionListenerDelegate}.
*
* {@inheritDoc}
*
* @since 0.9.0
*/
public void notify(final int changeKind) {
DDiagramEditorSessionListenerDelegate dDiagramEditorSessionListenerDelegate = new DDiagramEditorSessionListenerDelegate(this, toolFilterWhenRepresentationIsLocked, changeKind);
if (Display.getCurrent() == null) {
PlatformUI.getWorkbench().getDisplay().asyncExec(dDiagramEditorSessionListenerDelegate);
} else {
dDiagramEditorSessionListenerDelegate.run();
}
switch (changeKind) {
case VSM_UPDATED:
modelerDescriptionFilesLoaded();
break;
default:
break;
}
}
/**
* Method to update some ui parts according to events.
*
* @param notificationKind
* the event to update ui parts.
*/
public void firePropertyChangeInUIThread(final int notificationKind) {
Runnable runnable = new Runnable() {
public void run() {
if (notificationKind == PROP_TITLE) {
if ((getDiagram() != null) && (getDiagram().getElement() != null) && (getDiagram().getElement() instanceof DSemanticDiagram)) {
final String editorName = DialectUIManager.INSTANCE.getEditorName((DSemanticDiagram) getDiagram().getElement());
setPartName(editorName);
}
}
firePropertyChange(notificationKind);
}
};
if (Display.getCurrent() == null) {
PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
} else {
runnable.run();
}
}
private boolean isAutoRefresh() {
boolean autoRefresh = false;
try {
autoRefresh = PropertiesService.getInstance().getPropertiesProvider().getProperty(IPropertiesProvider.KEY_AUTO_REFRESH);
} catch (final IllegalArgumentException e) {
DiagramPlugin.getDefault().logError(e.getMessage());
}
return autoRefresh;
}
/**
* @param opening
* True if this refresh is launch during the opening of the
* editor, false otherwise.
*/
private void launchRefresh(boolean opening) {
Diagram gmfDiag = getDiagram();
if (gmfDiag != null) {
EObject eObject = gmfDiag.getElement();
Command command = null;
if (eObject instanceof DSemanticDiagram) {
DSemanticDiagram dDiagram = (DSemanticDiagram) eObject;
if (opening) {
CompoundCommand compoundCommand = new CompoundCommand();
Command refreshOnOpeningCmd = new RefreshDiagramOnOpeningCommand(getEditingDomain(), dDiagram);
compoundCommand.append(refreshOnOpeningCmd);
compoundCommand.setLabel(refreshOnOpeningCmd.getLabel());
// We are during the opening, the diagramEditPart is not
// already
// available, but we synchronize the GMF diag
CanonicalSynchronizer canonicalSynchronizer = CanonicalSynchronizerFactory.INSTANCE.createCanonicalSynchronizer(gmfDiag);
Command synchronizeGMFModel = new SynchronizeGMFModelCommand(getEditingDomain(), canonicalSynchronizer);
compoundCommand.append(synchronizeGMFModel);
command = compoundCommand;
} else {
command = new RefreshRepresentationsCommand(getEditingDomain(), new NullProgressMonitor(), dDiagram);
}
getEditingDomain().getCommandStack().execute(command);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.part.SiriusDiagramEditor#handleEditorInputChanged()
*/
@Override
protected void handleEditorInputChanged() {
super.handleEditorInputChanged();
if (isAutoRefresh()) {
launchRefresh(false);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.part.SiriusDiagramEditor#getAdapter(java.lang.Class)
*/
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") final Class type) {
Object adapter = null;
if (type == IDiagramCommandFactoryProvider.class) {
adapter = this.emfCommandFactoryProvider;
} else if (type == IContentOutlinePage.class) {
if (diagramOutline == null) {
initOutline();
}
diagramOutline.setDiagramWorkbenchPart(this);
adapter = diagramOutline;
} else if (type == EditingDomain.class || type == TransactionalEditingDomain.class) {
adapter = this.getEditingDomain();
} else if (type == IDiagramWorkbenchPart.class) {
adapter = this;
}
return adapter != null ? adapter : super.getAdapter(type);
}
/**
* {@inheritDoc}
*/
@Override
public TransactionalEditingDomain getEditingDomain() {
if (getSession() != null) {
return getSession().getTransactionalEditingDomain();
}
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor#getEditingDomainID()
*/
@Override
protected String getEditingDomainID() {
if (getSession() != null) {
return getSession().getTransactionalEditingDomain().getID();
} else {
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#createGraphicalViewer(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void createGraphicalViewer(final Composite parent) {
this.diagramMenuUpdater = new DiagramMenuUpdater(this);
parentComposite = createParentComposite(parent);
if (!isOldUIEnabled()) {
setTabbar(new Tabbar(parentComposite, this));
}
createHeaderSection(parentComposite);
createMainDiagramSection(parentComposite);
}
private boolean isOldUIEnabled() {
return Platform.getPreferencesService().getBoolean(DiagramUIPlugin.ID, SiriusDiagramUiPreferencesKeys.PREF_OLD_UI.name(), false, null);
}
private void createMainDiagramSection(Composite composite) {
Composite mainSection = new Composite(composite, SWT.None);
mainSection.setLayoutData(new GridData(GridData.FILL_BOTH));
mainSection.setLayout(new FillLayout());
createOriginalGraphicalViewer(mainSection);
}
private void createHeaderSection(Composite composite) {
if (isHeaderSectionEnabled()) {
diagramHeaderComposite = new DiagramHeaderComposite(composite, this);
}
}
private Composite createParentComposite(Composite parent) {
this.diagramMenuUpdater = new DiagramMenuUpdater(this);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout(1, true);
layout.verticalSpacing = 0;
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
return composite;
}
/**
* Return true if the header must be enabled, false otherwise.
*
* @return true if the header must be enabled, false otherwise.
*/
public boolean isHeaderSectionEnabled() {
boolean result = false;
DRepresentation representation = getRepresentation();
if (representation instanceof DDiagram) {
result = new DDiagramGraphicalQuery((DDiagram) representation).isHeaderSectionEnabled();
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#getGraphicalControl()
*/
@Override
protected Control getGraphicalControl() {
return parentComposite;
}
/**
* Get the tab bar.
*
* @return Returns the tab bar
*/
public Tabbar getTabbar() {
return tabbar;
}
/**
* Set the tab bar.
*
* @param tabbar
* the tab bar to set .
*/
protected void setTabbar(Tabbar tabbar) {
this.tabbar = tabbar;
}
/**
* Create classic diagram graphical viewer.
*
* @param parent
* the parent composite
*/
protected void createOriginalGraphicalViewer(final Composite parent) {
setRulerComposite(new RulerComposite(parent, SWT.NONE));
sGViewer = createScrollingGraphicalViewer();
sGViewer.createControl(getRulerComposite());
setGraphicalViewer(sGViewer);
hookGraphicalViewer();
configureGraphicalViewer();
initializeGraphicalViewer();
getRulerComposite().setGraphicalViewer((ScrollingGraphicalViewer) getGraphicalViewer());
if (sGViewer.getRootEditPart() instanceof DDiagramRootEditPart) {
DDiagramRootEditPart rootEditPart = (DDiagramRootEditPart) sGViewer.getRootEditPart();
rootEditPart.getZoomManager().setZoomLevelContributions(Arrays.asList(ZoomManager.FIT_ALL, ZoomManager.FIT_HEIGHT, ZoomManager.FIT_WIDTH));
}
}
/**
* {@inheritDoc}
*
* @not-generated : we're making sure the property is set as soon as
* possible.
*/
@Override
protected void setGraphicalViewer(GraphicalViewer viewer) {
viewer.setProperty(EDITOR_ID, this);
super.setGraphicalViewer(viewer);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditorWithFlyOutPalette#initializeGraphicalViewer()
*/
@Override
protected void initializeGraphicalViewer() {
/*
* Refresh diagram if needed. Must be done before that
*/
if (DialectUIManager.INSTANCE.isRefreshActivatedOnRepresentationOpening()) {
launchRefresh(true);
}
super.initializeGraphicalViewer();
// After EditPart instantiation call arrange command on views marked as
// to be arranged
final DiagramEditPart diagramEditPart = getDiagramEditPart();
if (diagramEditPart != null) {
SiriusCanonicalLayoutHandler.launchArrangeCommand(diagramEditPart);
}
transferDropTargetListener = new AbstractTransferDropTargetListener(getGraphicalViewer(), LocalSelectionTransfer.getTransfer()) {
@Override
protected Request createTargetRequest() {
final ChangeBoundsRequest request = new ChangeBoundsRequest(RequestConstants.REQ_DROP);
final List<EditPart> list = new ArrayList<EditPart>(1);
if (getCurrentEvent().data instanceof IStructuredSelection) {
list.add(new DragAndDropWrapper(getCurrentEvent().data));
} else if (getTransfer() instanceof LocalSelectionTransfer) {
final LocalSelectionTransfer localSelectionTransfer = (LocalSelectionTransfer) getTransfer();
if (localSelectionTransfer.getSelection() instanceof IStructuredSelection) {
list.add(new DragAndDropWrapper(localSelectionTransfer.getSelection()));
}
}
request.setEditParts(list);
return request;
}
@Override
protected void updateTargetRequest() {
final Request request = getTargetRequest();
((ChangeBoundsRequest) request).setLocation(getDropLocation());
}
};
getGraphicalViewer().addDropTargetListener(transferDropTargetListener);
// Initialize and rebuild the header composite
if (getDiagramHeader() != null) {
getDiagramHeader().setGraphicalViewer((ScrollingGraphicalViewer) getGraphicalViewer());
getDiagramHeader().rebuildHeaderSection();
}
}
/**
* Configures my diagram edit domain with its command stack.
*/
@Override
protected void configureDiagramEditDomain() {
final DefaultEditDomain editDomain = getEditDomain();
if (editDomain != null) {
final CommandStack stack = editDomain.getCommandStack();
if (stack != null) {
// dispose the old stack
stack.dispose();
}
// create and assign the new stack
final DiagramCommandStack diagramStack = new DDiagramCommandStack(getDiagramEditDomain());
diagramStack.setOperationHistory(getOperationHistory());
// changes made on the stack can be undone from this editor
diagramStack.setUndoContext(getUndoContext());
editDomain.setCommandStack(diagramStack);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.ui.business.api.dialect.DialectEditor#getRepresentation()
*/
public DRepresentation getRepresentation() {
if (getDiagram() != null && getDiagram().eResource() != null && getDiagram().getElement() instanceof DRepresentation) {
return (DRepresentation) getDiagram().getElement();
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Diagram getDiagram() {
if (getDocumentProvider() != null) {
IDiagramDocument document = (IDiagramDocument) getDocumentProvider().getDocument(getEditorInput());
if (document != null) {
return document.getDiagram();
}
}
return super.getDiagram();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#getUndoContext()
*/
@Override
protected IUndoContext getUndoContext() {
return undoContext;
}
/**
* Sets my undo context.
*
* @param context
* the undo context
*/
@Override
protected void setUndoContext(final IUndoContext context) {
this.undoContext = context;
}
/**
* Override to not dispose undo context. We dispose
* {@link org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl#defaultUndoContext}
* only at {@link Session#close(org.eclipse.core.runtime.IProgressMonitor)}
* call.
*/
@Override
protected void stopListening() {
if (getDocumentProvider() != null && getEditingDomain() == null) {
/*
* if editing domain is null, so undo context is not yet activated
* => we should not create one with getUndoContext()
*/
super.stopListening();
} else {
// Stop listening but set the undo context to null before, to avoid
// the dispose of this one. The undo context will be dispose during
// the close of the session.
final IUndoContext savUndoContext = getUndoContext();
setUndoContext(null);
super.stopListening();
setUndoContext(savUndoContext);
}
}
/**
* This will create the quick outline presenter and install it on this
* editor.
*
* @return The quick outline presenter.
*/
public SiriusInformationPresenter getQuickOutlinePresenter() {
SiriusInformationPresenter informationPresenter = new SiriusInformationPresenter(new IInformationControlCreator() {
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
*/
public IInformationControl createInformationControl(Shell parent) {
return new QuickOutlineControl(parent, SWT.RESIZE, DDiagramEditorImpl.this);
}
});
informationPresenter.install(getGraphicalControl());
IInformationProvider provider = new SiriusQuickOutlineInformationProvider(this);
informationPresenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
final int minimalWidth = 50;
final int minimalHeight = 30;
informationPresenter.setSizeConstraints(minimalWidth, minimalHeight, true, false);
informationPresenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
return informationPresenter;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.ui.business.api.dialect.DialectEditor#setDialogFactory(org.eclipse.sirius.ui.business.api.dialect.DialectEditorDialogFactory)
*/
public void setDialogFactory(DialectEditorDialogFactory dialogFactory) {
myDialogFactory = dialogFactory;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.tools.api.editor.DDiagramEditor#getPaletteManager()
*/
public PaletteManager getPaletteManager() {
return paletteManager;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.tools.api.editor.DDiagramEditor#getTabBarManager()
*/
public IToolBarManager getTabBarManager() {
if (getTabbar() != null) {
return getTabbar().getToolBarManager();
}
return null;
}
private void gogo(IMarker marker) {
/* If the marker is a marker supported by the MarkerNavigationService */
if (marker.getAttribute(EValidator.URI_ATTRIBUTE, null) == null) {
super.gotoMarker(marker);
} else {
/*
* Step 1 : getting the view corresponding to the given
* representation element
*/
final View targetView = getTargetView(marker);
if (targetView != null) {
/* Step 2 : getting the edit part from this view */
Map<?, ?> editPartRegistry = this.getDiagramGraphicalViewer().getEditPartRegistry();
EditPart targetEditPart = (EditPart) editPartRegistry.get(targetView);
/* Step 3 : selecting the correct editPart */
if (targetEditPart != null) {
SiriusDiagramEditorUtil.selectElementsInDiagram(this, Arrays.asList(new EditPart[] { targetEditPart }));
}
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(this);
}
}
}
private View getTargetView(IMarker marker) {
final String representationURI = marker.getAttribute(TraceabilityMarkerNavigationProvider.REPRESENTATION_URI, null);
final String representationElementId = marker.getAttribute(TraceabilityMarkerNavigationProvider.REPRESENTATION_ELEMENT_ID, null);
if ((representationElementId != null) && (representationURI != null)) {
final URI markerDDiagramURI = URI.createURI(representationURI);
if (markerDDiagramURI != null) {
EObject semanticDiagram = this.getDiagram().eResource().getResourceSet().getEObject(markerDDiagramURI, true);
if (semanticDiagram != null) {
final DRepresentationElement representationElement = (DRepresentationElement) semanticDiagram.eResource().getEObject(representationElementId);
if (representationElement != null) {
return SiriusGMFHelper.getGmfView((DDiagramElement) representationElement);
}
}
}
}
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.part.SiriusDiagramEditor#gotoMarker(org.eclipse.core.resources.IMarker)
*/
@Override
public void gotoMarker(IMarker marker) {
if (TraceabilityMarkerNavigationProvider.isTraceabilityMarker(marker)) {
new TraceabilityMarkerNavigationProvider(this).gotoMarker(marker);
} else {
gogo(marker);
}
}
/**
* Remove the diagram event broker for the listening of the transactional
* editing domain <B>if possible</B>. GMF never remove its
* DiagramEventBroker ant this can let think to memoryLeak if the
* weakHashMap used bu DiagramEventBroker is not clean.<BR>
* But if there is no more GMF editor, using this transactional editing
* domain, opened when can remove the diagram event broker to be more clear.
*
* @param ted
* The transactional editing domain used by the current editor.
*/
protected void stopDiagramEventBrokerListener(TransactionalEditingDomain ted) {
// Try to remove the diagram event broker if it's no more needed to
// avoir memory leak
int nbGMFDiagramEditorsOfSameTED = 0;
if (getSite() != null && getSite().getPage() != null) {
for (IEditorReference editorRef : getSite().getPage().getEditorReferences()) {
IEditorPart editorPart = editorRef.getEditor(false);
if (editorPart instanceof DiagramEditor && !editorPart.equals(this)) {
// Check that the same ted is used.
if (ted != null && ted.equals(((DiagramEditor) editorPart).getEditingDomain())) {
nbGMFDiagramEditorsOfSameTED++;
}
}
}
}
if (nbGMFDiagramEditorsOfSameTED == 0 && ted != null) {
// Remove the diagram event broker because there is no more opened
// diagram
DiagramEventBroker.stopListening(ted);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.diagram.tools.api.editor.DDiagramEditor#getAdapterFactory()
*/
public AdapterFactory getAdapterFactory() {
if (adapterFactory == null) {
// Create an adapter factory that yields item providers.
adapterFactory = DiagramUIPlugin.getPlugin().getNewAdapterFactory();
}
return adapterFactory;
}
/**
* {@inheritDoc}
*
* Overridden to have the title image stable during super.setInput(input)
* because the title image can change depending if the representation is
* locked (CDO).
*/
@Override
public void setInput(IEditorInput input) {
super.setInput(input);
if (getGraphicalViewer() != null) {
getGraphicalViewer().setSelection(new StructuredSelection());
}
// Update the tab's icon according to LockStatus
DRepresentation representation = getRepresentation();
if (representation instanceof DSemanticDecorator) {
DSemanticDecorator dSemanticDecorator = (DSemanticDecorator) representation;
DRepresentationPermissionStatusQuery dRepresentationPermissionStatusQuery = new DRepresentationPermissionStatusQuery(dSemanticDecorator);
IPermissionAuthority permissionAuthority = getPermissionAuthority();
LockStatus lockStatus = LockStatus.NOT_LOCKED;
LockStatus dSemanticDecoratorLockStatus = permissionAuthority.getLockStatus(dSemanticDecorator);
if (dSemanticDecoratorLockStatus != LockStatus.NOT_LOCKED) {
lockStatus = dSemanticDecoratorLockStatus;
}
int associatedSessionListenerEvent = dRepresentationPermissionStatusQuery.getAssociatedSessionListenerEvent(lockStatus);
notify(associatedSessionListenerEvent);
}
if (diagramHeaderComposite != null && !diagramHeaderComposite.isDisposed()) {
diagramHeaderComposite.rebuildHeaderSection();
}
// The input has changed, replace the existing gmfDiagramUpdater
if (gmfDiagramUpdater != null) {
gmfDiagramUpdater.dispose();
gmfDiagramUpdater = null;
}
if (representation instanceof DDiagram) {
gmfDiagramUpdater = new GMFDiagramUpdater(getSession(), (DDiagram) representation);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.sirius.ui.business.api.dialect.DialectEditor#getDialogFactory()
*/
public DialectEditorDialogFactory getDialogFactory() {
return myDialogFactory;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.ISaveablesSource#getSaveables()
*/
public Saveable[] getSaveables() {
if (session != null && session.isOpen()) {
IEditingSession uiSession = SessionUIManager.INSTANCE.getUISession(session);
if (uiSession instanceof ISaveablesSource) {
return ((ISaveablesSource) uiSession).getSaveables();
}
}
return new Saveable[0];
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.ISaveablesSource#getActiveSaveables()
*/
public Saveable[] getActiveSaveables() {
return getSaveables();
}
/**
* {@inheritDoc}
*
* @see ISaveablePart2#promptToSaveOnClose()
*/
public int promptToSaveOnClose() {
int choice = ISaveablePart2.DEFAULT;
if (session != null && session.isOpen()) {
IEditingSession uiSession = SessionUIManager.INSTANCE.getUISession(session);
// Close all && Still open elsewhere detection.
if (uiSession != null && uiSession.needToBeSavedOnClose(this)) {
choice = uiSession.promptToSaveOnClose();
}
}
return choice;
}
/**
* Return the diagram header composite.
*
* @return the diagram header composite
*/
public DiagramHeaderComposite getDiagramHeader() {
return diagramHeaderComposite;
}
}