Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Barbin2015-02-23 10:55:04 +0000
committerFlorian Barbin2015-03-06 08:31:40 +0000
commit91745f8dc183dd48b47775fe52bc7ad1bb17607f (patch)
tree745248bfb648d983b9ce2cf750694fb589355bea
parent94b51052cdab27eb399b7c7655c66fecb50a3648 (diff)
downloadorg.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>
-rw-r--r--plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/EditingSession.java49
-rw-r--r--plugins/org.eclipse.sirius.ui/src/org/eclipse/sirius/ui/business/internal/session/RestoreToLastSavePointListener.java223
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());
+ }
+}

Back to the top