blob: d95c1863ce6b6a6d6f6c1b8037cfe0977ed69627 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2021 THALES GLOBAL SERVICES and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.ui.tools.internal.editor;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.ui.URIEditorInput;
import org.eclipse.emf.common.ui.viewer.IViewerProvider;
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.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.sirius.business.api.dialect.command.RefreshRepresentationsCommand;
import org.eclipse.sirius.business.api.query.DRepresentationQuery;
import org.eclipse.sirius.business.api.query.URIQuery;
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.business.api.session.SessionStatus;
import org.eclipse.sirius.common.ui.SiriusTransPlugin;
import org.eclipse.sirius.common.ui.tools.api.util.EclipseUIUtil;
import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor;
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.tools.api.command.ICommandFactory;
import org.eclipse.sirius.tools.api.permission.DRepresentationPermissionStatusListener;
import org.eclipse.sirius.tools.api.permission.DRepresentationPermissionStatusQuery;
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.session.IEditingSession;
import org.eclipse.sirius.ui.business.api.session.SessionEditorInput;
import org.eclipse.sirius.ui.business.api.session.SessionUIManager;
import org.eclipse.sirius.ui.business.internal.dialect.TreeEditorDialogFactory;
import org.eclipse.sirius.ui.tools.api.properties.DTablePropertySheetpage;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.DRepresentationDescriptor;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
import org.eclipse.sirius.viewpoint.provider.Messages;
import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
/**
* Provides generic support for DTable and DTree editors. <BR>
* Clients may extend this class.
*
* @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
*/
public abstract class AbstractDTreeEditor extends EditorPart
implements DialectEditor, IViewerProvider, ITabbedPropertySheetPageContributor, IEditingDomainProvider, IReusableEditor, SessionListener, ISaveablesSource, IPageListener {
/**
* This class has the responsibility to open the editing session corresponding to a session added to the session
* manager and attaching to it the current editor so it can be handled correctly.
*
* @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
*
*/
private static final class SessionHandlingForEditor extends SessionManagerListener.Stub {
private AbstractDTreeEditor editor;
SessionHandlingForEditor(AbstractDTreeEditor editor) {
this.editor = editor;
}
@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(editor);
// important to remove the reference to the editor because this
// listener is still referenced by Eclipse ContextService when
// the editor is closed causing a leak.
editor = null;
/* remove this listener */
SessionManager.INSTANCE.removeSessionsListener(this);
}
}
}
/** The PERMISSION_GRANTED_TO_CURRENT_USER_EXCLUSIVELY icon descriptor. */
private static final ImageDescriptor LOCK_BY_ME_IMAGE_DESCRIPTOR = SiriusEditPlugin.Implementation
.getBundledImageDescriptor("icons/full/decorator/permission_granted_to_current_user_exclusively.gif"); //$NON-NLS-1$
/** The PERMISSION_GRANTED_TO_CURRENT_USER_EXCLUSIVELY icon descriptor. */
private static final ImageDescriptor LOCK_BY_OTHER_IMAGE_DESCRIPTOR = SiriusEditPlugin.Implementation.getBundledImageDescriptor("icons/full/decorator/permission_denied.gif"); //$NON-NLS-1$
private static final ImageDescriptor NO_WRITE_PERMISSION_IMAGE_DESCRIPTOR = SiriusEditPlugin.Implementation.getBundledImageDescriptor("icons/full/decorator/permission_no_write.gif");; //$NON-NLS-1$
/**
* This is the one adapter factory used for providing views of the model.
*/
protected AdapterFactory adapterFactory;
/**
* Model accessor.
*/
protected ModelAccessor accessor;
/**
* The tree viewer manager.
*/
protected AbstractDTableViewerManager treeViewerManager;
/** The control of this editor. */
protected Control control;
/**
* The session.
*/
protected Session session;
/**
* To increase performance we stop the update of the corresponding propertySheetPage during the refresh of the
* DTable.
*/
protected boolean propertiesUpdateEnabled;
/**
* .
*/
protected boolean isClosing;
/**
* Property sheet page.
*/
protected DTablePropertySheetpage currentPropertySheetpage;
/** the EMF command factory provider. */
protected ICommandFactory emfCommandFactory;
/**
* SessionManagerListener.
*/
protected final SessionManagerListener sessionManagerListener = new SessionHandlingForEditor(this);
/**
* The DialectEditorDialogFactory.
*/
protected DialectEditorDialogFactory myDialogFactory = new TreeEditorDialogFactory(this);
/**
* The {@link UndoRedoActionHandler} used to provide appropriate undo and redo Action Handlers to this editor.
*/
protected UndoRedoActionHandler undoRedoActionHandler;
/** Singleton instance of the initial Image for the NO_LOCK status. */
protected Image initialTitleImage;
/** Singleton instance of the Image for the REPRESENTATION_FROZEN status. */
protected Image frozenRepresentationImage;
/**
* To know if the last representation refresh succeeded in this editor.
*/
protected Optional<Boolean> isLastRefreshSucceeded = Optional.empty();
/** The {@link IAuthorityListener}. */
private IAuthorityListener dRepresentationLockStatusListener;
/** Singleton instance of the Image for the LOCK_BY_ME status */
private Image lockByMeImage;
/** Singleton instance of the Image for the LOCK_BY_OTHER status */
private Image lockByOtherImage;
/**
* Singleton instance of the image when DRepresentation has no write permission
*/
private Image noWritePermissionImage;
private int choice = ISaveablePart2.DEFAULT;
/**
* Default constructor.
*/
public AbstractDTreeEditor() {
super();
emfCommandFactory = null;
}
@Override
public Optional<Boolean> isLastRepresentationRefreshSucceeded() {
return isLastRefreshSucceeded;
}
/**
* Editor picture.
*
* @return initial image editor
*/
public abstract Image getInitialImage();
/**
* Get lazily the Image for the LOCK_BY_ME status.
*
* @return the Image for the LOCK_BY_ME status
*/
protected Image getLockByMeImage() {
if (lockByMeImage == null || lockByMeImage.isDisposed()) {
lockByMeImage = SiriusEditPlugin.getPlugin().getImage(LOCK_BY_ME_IMAGE_DESCRIPTOR);
}
return lockByMeImage;
}
/**
* Get lazily the Image for the LOCK_BY_OTHER status.
*
* @return the Image for the LOCK_BY_OTHER status
*/
protected Image getLockByOtherImage() {
if (lockByOtherImage == null || lockByOtherImage.isDisposed()) {
lockByOtherImage = SiriusEditPlugin.getPlugin().getImage(LOCK_BY_OTHER_IMAGE_DESCRIPTOR);
}
return lockByOtherImage;
}
/**
* Lazily gets the image when there is no write permission of the DRepresentation.
*
* @return the image when there is no write permission of the DRepresentation.
*/
protected Image getNoWritePermissionImage() {
if (noWritePermissionImage == null || noWritePermissionImage.isDisposed()) {
noWritePermissionImage = SiriusEditPlugin.getPlugin().getImage(NO_WRITE_PERMISSION_IMAGE_DESCRIPTOR);
}
return noWritePermissionImage;
}
/**
* Get lazily the Image for the REPRESENTATION_FROZEN state.
*
* @return the Image for the REPRESENTATION_FROZEN state
*/
public abstract Image getFrozenRepresentationImage();
@Override
public TransactionalEditingDomain getEditingDomain() {
return session != null ? session.getTransactionalEditingDomain() : null;
}
public IActionBars getActionBars() {
return ((EditingDomainActionBarContributor) getEditorSite().getActionBarContributor()).getActionBars();
}
/**
* Performs the save and handles errors appropriately.
*
* @param overwrite
* indicates whether or not overwriting is allowed
* @param progressMonitor
* the monitor in which to run the operation
*
*/
protected void performSave(final boolean overwrite, final IProgressMonitor progressMonitor) {
session.save(progressMonitor);
}
/**
* Tells if the aird {@link Resource} associated to the specified <code>editorInput</code> exists or not.
*
* @param editorInput
* the specifed {@link IEditorInput}
* @return false if the aird {@link Resource} associated to the specified <code>editorInput</code> exists, true else
*/
protected boolean isAirdResourceDeleted(final IEditorInput editorInput) {
boolean isDeleted = false;
DRepresentation representation = getRepresentation();
if (representation != null) {
DRepresentationQuery dRepresentationQuery = new DRepresentationQuery(representation);
DRepresentationDescriptor descriptor = dRepresentationQuery.getRepresentationDescriptor();
final Resource sessionResource = descriptor != null ? descriptor.eResource() : representation.eResource();
if (sessionResource != null) {
URI sessionResourceURI = sessionResource.getURI();
boolean sessionResourceExists = sessionResource.getResourceSet().getURIConverter().exists(sessionResourceURI, Collections.emptyMap());
// WORKAROUND with collab plugins
if (!sessionResourceExists && new URIQuery(sessionResourceURI).isInMemoryURI()) {
isDeleted = false;
} else {
isDeleted = !sessionResourceExists;
}
}
}
return isDeleted;
}
/**
* We have to take care of the case when Eclipse starts up with a session and diagram already open. see bug #1217
*
* {@inheritDoc}
*/
@Override
public void init(final IEditorSite site, final IEditorInput input) throws PartInitException {
setSite(site);
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;
if (input instanceof SessionEditorInput) {
SessionEditorInput sessionEditorInput = (SessionEditorInput) input;
final URI uri = sessionEditorInput.getURI();
this.session = sessionEditorInput.getSession();
URI uriToUse = Optional.ofNullable(sessionEditorInput.getRepDescUri()).orElse(uri);
if (session != null) {
setRepresentation(uriToUse, false);
}
} else if (input instanceof URIEditorInput) {
/* This happens when Eclipse is launched with an open tree editor */
final URI uri = ((URIEditorInput) input).getURI();
setRepresentation(uri, true);
}
setInput(input);
if (session != null) {
session.addListener(this);
configureCommandFactoryProviders();
IEditingSession uiSession = SessionUIManager.INSTANCE.getOrCreateUISession(this.session);
uiSession.open();
uiSession.attachEditor(this);
setAccessor(SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(getRepresentation()));
}
DRepresentation representation = getRepresentation();
if (representation != null) {
/* Update title. Semantic table could have been renamed */
notify(PROP_TITLE);
initialTitleImage = getTitleImage();
}
}
/**
* Configure and set the command factory.
*/
protected abstract void configureCommandFactoryProviders();
/**
* Initialize {@link IPermissionAuthority} and the title image if the Table is already locked by the current user
* before opening.
*
* @param representation
* the {@link DSemanticDecorator} that is opening.
*/
protected void initPermissionAuthority(DSemanticDecorator representation) {
// This IPermissionAuthority is added only on shared
// representations.
IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(representation.getTarget());
dRepresentationLockStatusListener = new DRepresentationPermissionStatusListener(representation, this);
permissionAuthority.addAuthorityListener(dRepresentationLockStatusListener);
if (!permissionAuthority.canEditInstance(this.getRepresentation())) {
notify(SessionListener.REPRESENTATION_EDITION_PERMISSION_DENIED);
} else if (LockStatus.LOCKED_BY_ME.equals(permissionAuthority.getLockStatus(representation))) {
notify(SessionListener.REPRESENTATION_EDITION_PERMISSION_GRANTED_TO_CURRENT_USER_EXCLUSIVELY);
}
}
/**
* Open the session.
*
* @param rootElement
* the representation
*/
protected void getSession(final DSemanticDecorator rootElement) {
session = SessionManager.INSTANCE.getSession(rootElement.getTarget());
if (session == null) {
SiriusTransPlugin.getPlugin().error(MessageFormat.format(Messages.AbstractDTreeEditor_noSessionError, rootElement), null);
}
}
@Override
public boolean isDirty() {
return session != null && session.getStatus() == SessionStatus.DIRTY;
}
@Override
public boolean isSaveAsAllowed() {
return false;
}
@Override
public void setFocus() {
if (treeViewerManager != null) {
// Resolve proxy model after aird reload.
DRepresentation representation = getRepresentation();
boolean representationProxyDetected = false;
if (representation != null && representation.eIsProxy() && session != null) {
representationProxyDetected = true;
IEditorInput editorInput = getEditorInput();
if (editorInput instanceof URIEditorInput) {
URIEditorInput sessionEditorInput = (URIEditorInput) editorInput;
final URI uri = sessionEditorInput.getURI();
setRepresentation(uri, false);
IEditingSession uiSession = SessionUIManager.INSTANCE.getUISession(session);
// Get the new representation
representation = getRepresentation();
if (uiSession != null && representation != null) {
// Reinit dialect editor closer and other
// IEditingSession mechanisms.
uiSession.detachEditor(this);
uiSession.attachEditor(this);
}
// Reinit the lock status listener.
IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(representation);
if (representation instanceof DSemanticDecorator && permissionAuthority != null && dRepresentationLockStatusListener != null) {
permissionAuthority.removeAuthorityListener(dRepresentationLockStatusListener);
initPermissionAuthority((DSemanticDecorator) representation);
}
}
}
checkSemanticAssociation();
if (representationProxyDetected) {
updateEditorAfterAirdResourceReload();
}
/*
* A regression in Kepler can cause an NPE inside the treeViewerManager.getControl().setFocus() below. The
* guard condition is a workaround, which seems to fix the problem (or at least the symptom) in our tests.
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=378846#c16
*/
AbstractDTreeViewer viewer = treeViewerManager.getTreeViewer();
if (viewer != null && viewer.getTree() != null && viewer.getTree().getTopItem() != null) {
treeViewerManager.getControl().setFocus();
}
setEclipseWindowTitle();
} else if (control != null) {
control.setFocus();
}
}
/**
* Update all needed editor elements after an Aird resource reload like {@link Tree} or
* {@link AbstractDTableViewerManager} referencing previous Aird elements as proxies.
*/
protected abstract void updateEditorAfterAirdResourceReload();
/**
* Retrieve and set the representation from the given {@link DRepresentationDescriptor} URI.
*
* @param uri
* the URI of the {@link DRepresentationDescriptor} to resolve.
* @param loadOnDemand
* whether to create and load the resource, if it doesn't already exists.
*/
protected abstract void setRepresentation(URI uri, boolean loadOnDemand);
/**
* Close this editor if root element has been removed.
*/
protected void checkSemanticAssociation() {
DRepresentation representation = getRepresentation();
boolean shouldClose = representation == null || representation.eResource() == null;
if (!shouldClose && representation instanceof DSemanticDecorator) {
EObject semanticTarget = ((DSemanticDecorator) representation).getTarget();
shouldClose = semanticTarget == null || semanticTarget.eResource() == null;
}
if (shouldClose) {
/*
* The element has been deleted, we should close the editor
*/
myDialogFactory.editorWillBeClosedInformationDialog(getSite().getShell());
DialectUIManager.INSTANCE.closeEditor(this, false);
}
}
/**
* Updates the title of the eclipse window.
*/
protected 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$
if (end > -1) {
title = MessageFormat.format(Messages.AbstractDTreeEditor_eclipseWindowTitle, title.substring(0, end + 6) + this.getPartName());
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setText(title);
}
}
/**
* Retrieves the descriptor for this editor.
*
* @return the editor descriptor
*/
protected final IEditorDescriptor getEditorDescriptor() {
final IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
final IEditorDescriptor editorDesc = editorRegistry.findEditor(getSite().getId());
return editorDesc;
}
@Override
public boolean needsRefresh(int propId) {
boolean result = false;
if (propId == DialectEditor.PROP_REFRESH) {
if (session.getSiriusPreferences().isAutoRefresh()) {
result = true;
}
} else if (propId == DialectEditor.PROP_FORCE_REFRESH) {
result = true;
}
return result;
}
/**
* Launch refresh on representation.
*/
protected abstract void launchRefresh();
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") final Class type) {
Object result = super.getAdapter(type);
if (result == null) {
if (type == IPropertySheetPage.class) {
IPropertySheetPage contributedPage = SiriusEditPlugin.getPlugin().getPropertySheetPage(this, getContributorId());
if (contributedPage != null) {
currentPropertySheetpage = null;
result = contributedPage;
} else {
currentPropertySheetpage = new DTablePropertySheetpage(this);
result = currentPropertySheetpage;
}
} else if (type == EditingDomain.class) {
result = getEditingDomain();
}
}
return result;
}
/**
* Do a refresh of the properties view if it's activated.
*/
public void forceRefreshProperties() {
if (currentPropertySheetpage != null && currentPropertySheetpage.getControl() != null && !currentPropertySheetpage.getControl().isDisposed()) {
currentPropertySheetpage.refresh();
}
}
@Override
public Viewer getViewer() {
Viewer viewer = null;
if (treeViewerManager != null) {
viewer = treeViewerManager.getTreeViewer();
}
return viewer;
}
public AbstractDTableViewerManager getTableViewer() {
return treeViewerManager;
}
/**
* return accessor.
*
* @return the accessor
*/
public ModelAccessor getAccessor() {
return accessor;
}
@Override
public void dispose() {
if (control != null) {
control.dispose();
control = null;
}
if (dRepresentationLockStatusListener != null) {
IPermissionAuthority permissionAuthority = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(getRepresentation());
permissionAuthority.removeAuthorityListener(dRepresentationLockStatusListener);
dRepresentationLockStatusListener = null;
}
isClosing = true;
SessionManager.INSTANCE.removeSessionsListener(sessionManagerListener);
// Disposing the UndoredoActionHandler
if (this.undoRedoActionHandler != null) {
this.undoRedoActionHandler.dispose();
}
undoRedoActionHandler = null;
super.dispose();
if (getTableViewer() != null) {
getTableViewer().dispose();
}
treeViewerManager = null;
// We need to perform the detachEditor after having disposed the viewer
// and the editor input to avoid a refresh. A refresh can occurs in the
// case where the detach triggers the reload of the modified resources
// (if choice == ISaveablePart2.NO)
if (session != null) {
session.removeListener(this);
final IEditingSession sess = SessionUIManager.INSTANCE.getUISession(session);
if (sess != null) {
sess.detachEditor(this, choice == ISaveablePart2.NO);
}
session = null;
}
adapterFactory = null;
accessor = null;
currentPropertySheetpage = null;
emfCommandFactory = null;
myDialogFactory = null;
}
@Override
public void setInput(final IEditorInput input) {
super.setInput(input);
// Set the context for the command stack (See
// org.eclipse.gmf.runtime.diagram.ui.partsDiagramEditor.setInput for
// details)
// configureTableEditDomain();
Viewer viewer = getViewer();
if (viewer != null) {
viewer.refresh();
}
// 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 = PermissionAuthorityRegistry.getDefault().getPermissionAuthority(dSemanticDecorator);
LockStatus lockStatus = LockStatus.NOT_LOCKED;
LockStatus dSemanticDecoratorLockStatus = permissionAuthority.getLockStatus(dSemanticDecorator);
if (dSemanticDecoratorLockStatus != LockStatus.NOT_LOCKED) {
lockStatus = dSemanticDecoratorLockStatus;
}
int associatedSessionListenerEvent = dRepresentationPermissionStatusQuery.getAssociatedSessionListenerEvent(lockStatus);
notify(associatedSessionListenerEvent);
}
}
public AdapterFactory getAdapterFactory() {
return adapterFactory;
}
/**
* Set the update status.
*
* @param enabled
* the updateEnabled to set
*/
public void enablePropertiesUpdate(final boolean enabled) {
propertiesUpdateEnabled = enabled;
}
/**
* Get the update status.
*
* @return the update status
*/
public boolean isPropertiesUpdateEnabled() {
return propertiesUpdateEnabled;
}
@Override
public void notify(final int changeKind) {
AbstractDTreeEditorSessionListenerDelegate abstractDTreeEditorSessionListenerDelegate = new AbstractDTreeEditorSessionListenerDelegate(this, changeKind);
if (Display.getCurrent() == null) {
EclipseUIUtil.displayAsyncExec(abstractDTreeEditorSessionListenerDelegate);
} else {
abstractDTreeEditorSessionListenerDelegate.run();
}
}
/**
* Overridden to change the visibility of the inherited method.
*
* {@inheritDoc}
*/
@Override
public void setTitleImage(Image titleImage) {
if (!getTitleImage().equals(titleImage)) {
super.setTitleImage(titleImage);
}
}
/**
* Update a property.
*
* @param notificationKind
* the kind of property changed
*/
protected void firePropertyChangeInUIThread(final int notificationKind) {
if (notificationKind == PROP_TITLE) {
setPartName(getRepresentation().getName());
}
firePropertyChange(notificationKind);
}
protected IEditingSession getUISession() {
return SessionUIManager.INSTANCE.getUISession(session);
}
@Override
public boolean isSaveOnCloseNeeded() {
/*
* No call to editingSession.needToBeSavedOnClose(this) here to allow close all detection.
*/
return isDirty();
}
@Override
public void setDialogFactory(DialectEditorDialogFactory dialogFactory) {
myDialogFactory = dialogFactory;
}
@Override
public Saveable[] getSaveables() {
if (session != null && session.isOpen()) {
IEditingSession uiSession = getUISession();
if (uiSession instanceof ISaveablesSource) {
return ((ISaveablesSource) uiSession).getSaveables();
}
}
return new Saveable[0];
}
@Override
public Saveable[] getActiveSaveables() {
return getSaveables();
}
@Override
public int promptToSaveOnClose() {
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;
}
@Override
public void createPartControl(Composite parent) {
// setting up a UndoActionHandler
// and a RedoActionHandler to avoid
// issues with Undo and Redo
setUpUndoRedoActionHandler();
}
@Override
public void pageOpened(IWorkbenchPage page) {
}
@Override
public void pageActivated(IWorkbenchPage page) {
// As the page has been activated, we now can create the
// UndoRedoActionHandler
setUpUndoRedoActionHandler();
}
@Override
public void pageClosed(IWorkbenchPage page) {
}
/**
* Initializes an UndoRedoActionHandler, which purpose is to provide appropriate undo and redo Action Handlers to
* this editor.
*/
protected void setUpUndoRedoActionHandler() {
// Undo/Redo Issues with Trees and Tables
IWorkbenchWindow workbenchWindow = getEditorSite().getWorkbenchWindow();
if (workbenchWindow != null) {
IWorkbenchPage part = workbenchWindow.getActivePage();
if (part != null) {
undoRedoActionHandler = new UndoRedoActionHandler(this.getEditingDomain(), getEditorSite());
}
}
// If the UndoRedoActionHandler was not create
if (undoRedoActionHandler == null) {
// We register the current editor as listening the page opening
// The UndoRedoActionHandler will be created whenever the page will
// open
getEditorSite().getWorkbenchWindow().addPageListener(this);
}
}
/**
* Indicates if the given TreeItem list contains (at any level) the given element. If it's the case, returns the
* TreeItem containing this element.
*
* @param items
* the TreeItems to look into
* @param element
* the searched element
* @return the TreeItem containing the searched element if one found, null otherwise
*/
protected TreeItem contains(TreeItem[] items, Object element) {
TreeItem searchedTreeItem = null;
for (int i = 0; i < items.length && (searchedTreeItem == null); i++) {
if ((items[i].getData() != null) && items[i].getData().equals(element)) {
searchedTreeItem = items[i];
}
if (searchedTreeItem == null) {
searchedTreeItem = contains(items[i].getItems(), element);
}
}
return searchedTreeItem;
}
@Override
public DialectEditorDialogFactory getDialogFactory() {
return myDialogFactory;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.sirius.business.api.componentization.ViewpointRegistryListener2#modelerDesciptionFilesLoaded()
*/
protected void modelerDescriptionFilesLoaded() {
if (session.getSiriusPreferences().isAutoRefresh()) {
Job refreshJob = new Job(Messages.AbstractDTreeEditor_modelerDescriptionFilesLoadedJob) {
@Override
protected IStatus run(IProgressMonitor monitor) {
getEditingDomain().getCommandStack().execute(new RefreshRepresentationsCommand(getEditingDomain(), monitor, getRepresentation()));
return Status.OK_STATUS;
}
};
refreshJob.schedule();
}
}
/**
* Set the accessor.
*
* @param accessor
* the accessor to set
*/
protected void setAccessor(ModelAccessor accessor) {
this.accessor = accessor;
}
}