diff options
| author | Florian Barbin | 2015-02-23 10:55:04 +0000 |
|---|---|---|
| committer | Florian Barbin | 2015-03-06 08:31:40 +0000 |
| commit | 91745f8dc183dd48b47775fe52bc7ad1bb17607f (patch) | |
| tree | 745248bfb648d983b9ce2cf750694fb589355bea | |
| parent | 94b51052cdab27eb399b7c7655c66fecb50a3648 (diff) | |
| download | org.eclipse.sirius-91745f8dc183dd48b47775fe52bc7ad1bb17607f.tar.gz org.eclipse.sirius-91745f8dc183dd48b47775fe52bc7ad1bb17607f.tar.xz org.eclipse.sirius-91745f8dc183dd48b47775fe52bc7ad1bb17607f.zip | |
[444261] Use the Operation History as far as possible.
This commit aims to use a more pragmatic solution than reloading
impacted resources systematically. If the operation history limit is not
reached, we privilege the revert by performing undos instead of reload
the entire resource.
Bug: 444261
Change-Id: Ia68d62f4297e2800eb26ce55958208a0359f09ef
Signed-off-by: Florian Barbin <florian.barbin@obeo.fr>
2 files changed, 232 insertions, 40 deletions
diff --git a/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/EditingSession.java b/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/EditingSession.java index 3e21de73d2..76baddcd3e 100644 --- a/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/EditingSession.java +++ b/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/EditingSession.java @@ -28,16 +28,12 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.business.api.session.danalysis.DAnalysisSession; import org.eclipse.sirius.business.internal.session.ReloadingPolicyImpl; -import org.eclipse.sirius.common.tools.api.resource.ResourceSetSync.ResourceStatus; -import org.eclipse.sirius.common.tools.api.resource.ResourceSyncClient; -import org.eclipse.sirius.common.tools.api.resource.ResourceSyncClient.ResourceStatusChange; import org.eclipse.sirius.common.ui.tools.api.util.EclipseUIUtil; import org.eclipse.sirius.common.ui.tools.api.util.SWTUtil; import org.eclipse.sirius.tools.api.command.ui.RefreshFilter; import org.eclipse.sirius.tools.api.command.ui.RefreshFilterManager; import org.eclipse.sirius.ui.business.api.dialect.DialectEditor; import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager; -import org.eclipse.sirius.ui.business.api.preferences.SiriusUIPreferencesKeys; import org.eclipse.sirius.ui.business.api.session.EditingSessionEvent; import org.eclipse.sirius.ui.business.api.session.EditorNameAdapter; import org.eclipse.sirius.ui.business.api.session.IEditingSession; @@ -90,6 +86,8 @@ public class EditingSession implements IEditingSession, ISaveablesSource, Refres */ private EditorNameAdapter editorNameAdapter; + private RestoreToLastSavePointListener restoreToSavePointListener; + private SaveSessionWhenNoDialectEditorsListener saveSessionListener; /** @@ -106,11 +104,16 @@ public class EditingSession implements IEditingSession, ISaveablesSource, Refres } private void initListeners() { + this.restoreToSavePointListener = new RestoreToLastSavePointListener(session); this.saveSessionListener = new SaveSessionWhenNoDialectEditorsListener(session); this.saveSessionListener.register(); } private void removeListeners() { + if (restoreToSavePointListener != null) { + restoreToSavePointListener.dispose(); + restoreToSavePointListener = null; + } if (this.saveSessionListener != null) { this.saveSessionListener.unregister(); @@ -195,7 +198,7 @@ public class EditingSession implements IEditingSession, ISaveablesSource, Refres boolean returnToSyncState = revertChanges && (getEditors().size() == 1 || closeAllDetected()); detachEditor(dialectEditor); if (returnToSyncState) { - returnToSyncState(); + restoreToSavePointListener.returnToSyncState(); } } @@ -246,7 +249,7 @@ public class EditingSession implements IEditingSession, ISaveablesSource, Refres int choice = ISaveablePart2.DEFAULT; if (saveable != null) { boolean stillOpenElsewhere = getEditors().size() > 1 && !closeAllDetected(); - boolean promptStandardDialog = !isAllowedToReturnToSyncState(); + boolean promptStandardDialog = !restoreToSavePointListener.isAllowedToReturnToSyncState(); choice = SWTUtil.showSaveDialog(session, saveable.getName(), true, stillOpenElsewhere, promptStandardDialog); @@ -257,40 +260,6 @@ public class EditingSession implements IEditingSession, ISaveablesSource, Refres return choice; } - /** - * Notifies the session that the changes have been canceled by user. That - * will cause the reloading of "changed" resources. - */ - private void returnToSyncState() { - if (isAllowedToReturnToSyncState()) { - List<ResourceStatusChange> changes = new ArrayList<ResourceStatusChange>(); - for (Resource currentResource : session.getAllSessionResources()) { - if (currentResource.isModified()) { - changes.add(new ResourceStatusChange(currentResource, ResourceStatus.CHANGES_CANCELED, ResourceStatus.CHANGED)); - } - } - for (Resource currentResource : session.getSemanticResources()) { - if (currentResource.isModified()) { - changes.add(new ResourceStatusChange(currentResource, ResourceStatus.CHANGES_CANCELED, ResourceStatus.CHANGED)); - } - } - if (session instanceof ResourceSyncClient) { - ((ResourceSyncClient) session).statusesChanged(changes); - } - } - } - - /** - * Check the DesignerUIPreferencesKeys.PREF_RELOAD_ON_LAST_EDITOR_CLOSE - * preference state. - * - * @return the preference value. - */ - private boolean isAllowedToReturnToSyncState() { - IPreferenceStore preferenceStore = SiriusEditPlugin.getPlugin().getPreferenceStore(); - return preferenceStore != null && preferenceStore.getBoolean(SiriusUIPreferencesKeys.PREF_RELOAD_ON_LAST_EDITOR_CLOSE.name()); - } - private boolean closeAllDetected() { return needSaveOnCloseDetec.closeAllDetected(); } diff --git a/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/RestoreToLastSavePointListener.java b/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/RestoreToLastSavePointListener.java new file mode 100644 index 0000000000..acf447359d --- /dev/null +++ b/plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/RestoreToLastSavePointListener.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2011, 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.ui.business.internal.session; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.operations.IOperationHistory; +import org.eclipse.core.commands.operations.IOperationHistoryListener; +import org.eclipse.core.commands.operations.IUndoContext; +import org.eclipse.core.commands.operations.IUndoableOperation; +import org.eclipse.core.commands.operations.ObjectUndoContext; +import org.eclipse.core.commands.operations.OperationHistoryEvent; +import org.eclipse.core.commands.operations.OperationHistoryFactory; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.workspace.IWorkspaceCommandStack; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.sirius.business.api.session.Session; +import org.eclipse.sirius.business.api.session.SessionStatus; +import org.eclipse.sirius.common.tools.api.resource.ResourceSetSync; +import org.eclipse.sirius.common.tools.api.resource.ResourceSetSync.ResourceStatus; +import org.eclipse.sirius.common.tools.api.resource.ResourceSyncClient; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.tools.api.command.EditingDomainUndoContext; +import org.eclipse.sirius.ui.business.api.preferences.SiriusUIPreferencesKeys; +import org.eclipse.sirius.viewpoint.DAnalysisSessionEObject; +import org.eclipse.sirius.viewpoint.SiriusPlugin; +import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin; +import org.eclipse.ui.PlatformUI; + +/** + * Marker able to restore the command stack to the last save point. + * + * @author mporhel + */ +public class RestoreToLastSavePointListener implements ResourceSyncClient, IOperationHistoryListener { + + private IUndoableOperation marker; + + private Session session; + + /** + * Create a new instance. + * + * @param session + * the session to listen + */ + public RestoreToLastSavePointListener(Session session) { + this.session = session; + OperationHistoryFactory.getOperationHistory().addOperationHistoryListener(this); + ResourceSetSync.getOrInstallResourceSetSync(session.getTransactionalEditingDomain()).registerClient(this); + } + + /** + * Return to the last save point. + */ + public void returnToSyncState() { + // If the user is closing the workbench, we do not need to reset the + // changes. + if (PlatformUI.getWorkbench().isClosing()) { + return; + } + if (isAllowedToReturnToSyncState()) { + if (canPerformTheRevertFromOperationHistory()) { + returnToSyncStateFromOperationHistory(); + } else { + reloadTheResources(); + } + } + } + + private void reloadTheResources() { + List<ResourceStatusChange> changes = new ArrayList<ResourceStatusChange>(); + for (Resource currentResource : getModifiedResources()) { + changes.add(new ResourceStatusChange(currentResource, ResourceStatus.CHANGES_CANCELED, ResourceStatus.CHANGED)); + } + if (session instanceof ResourceSyncClient) { + ((ResourceSyncClient) session).statusesChanged(changes); + } + } + + private Collection<Resource> getModifiedResources() { + List<Resource> changed = new ArrayList<Resource>(); + for (Resource currentResource : session.getAllSessionResources()) { + if (currentResource.isModified()) { + changed.add(currentResource); + } + } + for (Resource currentResource : session.getSemanticResources()) { + if (currentResource.isModified()) { + changed.add(currentResource); + } + } + if (session instanceof DAnalysisSessionEObject) { + for (Resource currentResource : ((DAnalysisSessionEObject) session).getControlledResources()) { + if (currentResource.isModified()) { + changed.add(currentResource); + } + } + } + return changed; + } + + private void returnToSyncStateFromOperationHistory() { + try { + IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); + IUndoContext undoCtx = getUndoContext(); + while (operationHistory != null && operationHistory.canUndo(undoCtx) && session.getStatus() != SessionStatus.SYNC) { + IUndoableOperation toUndo = operationHistory.getUndoOperation(undoCtx); + + operationHistory.undoOperation(toUndo, new NullProgressMonitor(), null); + + if (marker == toUndo) { + break; + } + } + setResourcesBackToSync(); + } catch (ExecutionException e) { + // If something went wrong, we reload the changed resources: + reloadTheResources(); + String sessionLabel = SiriusEditPlugin.getPlugin().getUiCallback().getSessionNameToDisplayWhileSaving(session); + SiriusPlugin.getDefault().warning(sessionLabel + " modified resources were reloaded. An error occurs while attempting to cancel all modifications.", e); + } + } + + private void setResourcesBackToSync() { + if (session instanceof ResourceSyncClient) { + for (Resource currentResource : getModifiedResources()) { + currentResource.setModified(false); + } + } + } + + private IUndoContext getUndoContext() { + IUndoContext undoCtx; + if (session.getTransactionalEditingDomain() != null) { + if (session.getTransactionalEditingDomain().getCommandStack() instanceof IWorkspaceCommandStack) { + undoCtx = ((IWorkspaceCommandStack) session.getTransactionalEditingDomain().getCommandStack()).getDefaultUndoContext(); + } else { + undoCtx = new EditingDomainUndoContext(session.getTransactionalEditingDomain()); + } + } else { + undoCtx = new ObjectUndoContext(this); + } + return undoCtx; + } + + /** + * Dispose this listener. + */ + public void dispose() { + OperationHistoryFactory.getOperationHistory().removeOperationHistoryListener(this); + // Do not call ResourceSetSync.getOrInstallResourceSetSync as the + // ResourceSetSync could already have been removed. + Option<ResourceSetSync> resourceSetSync = ResourceSetSync.getResourceSetSync(session.getTransactionalEditingDomain()); + if (resourceSetSync.some()) { + resourceSetSync.get().unregisterClient(this); + } + session = null; + marker = null; + } + + @Override + public void statusChanged(Resource resource, ResourceStatus oldStatus, ResourceStatus newStatus) { + // Do nothing while processing, + // see statusesChanged(Collection<ReResourceStatusChange>) + } + + @Override + public void statusesChanged(Collection<ResourceStatusChange> changes) { + /* this may be call in a async thread */ + if (session != null) { + if (SessionStatus.SYNC == session.getStatus()) { + marker = null; + } + } + } + + @Override + public void historyNotification(OperationHistoryEvent event) { + if (session != null && SessionStatus.DIRTY == session.getStatus()) { + if (marker == null) { + marker = event.getOperation(); + } + } + } + + /** + * Returns whether we can perform the entire revert by undoing all + * operations. In other words, if the undo history is strictly lower to the + * max limit. + * + * @return true if we can perform the undo, false otherwise. + */ + private boolean canPerformTheRevertFromOperationHistory() { + IUndoContext undoContext = getUndoContext(); + IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); + IUndoableOperation[] iUndoableOperations = operationHistory.getUndoHistory(undoContext); + return iUndoableOperations.length < operationHistory.getLimit(undoContext); + } + + /** + * Check the DesignerUIPreferencesKeys.PREF_RELOAD_ON_LAST_EDITOR_CLOSE + * preference state. + * + * @return the preference value. + */ + public boolean isAllowedToReturnToSyncState() { + IPreferenceStore preferenceStore = SiriusEditPlugin.getPlugin().getPreferenceStore(); + return preferenceStore != null && preferenceStore.getBoolean(SiriusUIPreferencesKeys.PREF_RELOAD_ON_LAST_EDITOR_CLOSE.name()); + } +} |
