From 38004fdda70b083bee7ab0ea0c4de067be617ac3 Mon Sep 17 00:00:00 2001
From: Tobias Ortmayr
Date: Tue, 23 Mar 2021 14:02:13 +0100
Subject: [PATCH] #197, #196: Improve dirty state handling (#101)
The `SetDirtyStateAction` now also declares the reason which caused the dirty state change.
Ensure that the `SetDirtyStateAction` is only sent once during a model update
Part of https://github.com/eclipse-glsp/glsp/issues/197
Fixes https://github.com/eclipse-glsp/glsp/issues/196
---
.../actions/SaveModelActionHandler.java | 4 +-
.../server/actions/SetDirtyStateAction.java | 21 ++++++++-
.../server/diagram/DiagramConfiguration.java | 4 ++
.../core/model/ModelSubmissionHandler.java | 44 ++++++++++++++-----
.../core/model/RequestModelActionHandler.java | 2 +-
.../undoredo/UndoRedoActionHandler.java | 7 +--
.../operations/OperationActionHandler.java | 5 ++-
7 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SaveModelActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SaveModelActionHandler.java
index 73957585..53e1008d 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SaveModelActionHandler.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SaveModelActionHandler.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2019 EclipseSource and others.
+ * Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -51,7 +51,7 @@ public List executeAction(final SaveModelAction action, final GModelStat
} finally {
modelSourceWatcher.continueWatching(modelState);
}
- return listOf(new SetDirtyStateAction(modelState.isDirty()));
+ return listOf(new SetDirtyStateAction(modelState.isDirty(), SetDirtyStateAction.Reason.SAVE));
}
protected void saveModelState(final GModelState modelState) {
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SetDirtyStateAction.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SetDirtyStateAction.java
index 9d45f661..09dad13c 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SetDirtyStateAction.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SetDirtyStateAction.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2020 EclipseSource and others.
+ * Copyright (c) 2020-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -16,10 +16,10 @@
package org.eclipse.glsp.server.actions;
public class SetDirtyStateAction extends Action {
-
public static final String ID = "setDirtyState";
private boolean isDirty;
+ private String reason;
public SetDirtyStateAction() {
super(ID);
@@ -30,8 +30,25 @@ public SetDirtyStateAction(final boolean isDirty) {
this.isDirty = isDirty;
}
+ public SetDirtyStateAction(final boolean isDirty, final String reason) {
+ this(isDirty);
+ this.reason = reason;
+ }
+
public boolean isDirty() { return isDirty; }
public void setDirty(final boolean isDirty) { this.isDirty = isDirty; }
+ public String getReason() { return reason; }
+
+ public void setReason(final String reason) { this.reason = reason; }
+
+ public static class Reason {
+ public static final String OPERATION = "operation";
+ public static final String UNDO = "undo";
+ public static final String REDO = "redo";
+ public static final String SAVE = "save";
+ public static final String EXTERNAL = "external";
+ }
+
}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DiagramConfiguration.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DiagramConfiguration.java
index 2fadf7f5..e00a53cf 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DiagramConfiguration.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DiagramConfiguration.java
@@ -48,4 +48,8 @@ default ShapeTypeHint createDefaultNodeTypeHint(final String elementId) {
default boolean needsClientLayout() {
return true;
}
+
+ default boolean animatedUpdate() {
+ return true;
+ }
}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/ModelSubmissionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/ModelSubmissionHandler.java
index 9ac61d33..88e4642a 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/ModelSubmissionHandler.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/ModelSubmissionHandler.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2019 EclipseSource and others.
+ * Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -15,6 +15,7 @@
********************************************************************************/
package org.eclipse.glsp.server.features.core.model;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -55,28 +56,32 @@ public class ModelSubmissionHandler {
*
*
* @param modelState The model state to submit.
+ * @param reason The optional reason that caused the model update.
* @return A list of actions to be processed in order to submit the model.
*/
- public List submitModel(final GModelState modelState) {
+ public List submitModel(final GModelState modelState, final String reason) {
modelFactory.createGModel(modelState);
modelState.getRoot().setRevision(modelState.getRoot().getRevision() + 1);
DiagramConfiguration diagramConfiguration = diagramConfigurationRegistry.get(modelState);
- if (diagramConfiguration.getLayoutKind() == ServerLayoutKind.AUTOMATIC) {
- layoutEngine.layout(modelState);
- }
- if (diagramConfiguration.needsClientLayout()) {
+ boolean needsClientLayout = diagramConfiguration.needsClientLayout();
+ if (needsClientLayout) {
synchronized (modelLock) {
return Arrays.asList(new RequestBoundsAction(modelState.getRoot()),
- new SetDirtyStateAction(modelState.isDirty()));
+ new SetDirtyStateAction(modelState.isDirty(), reason));
}
}
- return submitModelDirectly(modelState);
+ return submitModelDirectly(modelState, reason);
+ }
+
+ public List submitModel(final GModelState modelState) {
+ return submitModel(modelState, null);
}
/**
* Returns a list of actions to directly update the client-side model without any server- or client-side layouting.
*
- * Typically {@link ActionHandler action handlers} don't invoke this method but use {@link #submitModel(GModelState)}
+ * Typically {@link ActionHandler action handlers} don't invoke this method but use
+ * {@link #submitModel(GModelState,String)}
* instead, as this is only used to eventually submit the model on the client directly after all layouting is already
* performed before. The only foreseen caller of this method is {@link ComputedBoundsActionHandler}.
*
@@ -87,15 +92,30 @@ public List submitModel(final GModelState modelState) {
*
*
* @param modelState The model state to submit.
+ * @param reason The optional reason that caused the model update.
* @return A list of actions to be processed in order to submit the model.
*/
- public List submitModelDirectly(final GModelState modelState) {
+ public List submitModelDirectly(final GModelState modelState, final String reason) {
GModelRoot gModel = modelState.getRoot();
- Action action = gModel.getRevision() == 0 ? new SetModelAction(gModel) : new UpdateModelAction(gModel);
+ DiagramConfiguration diagramConfiguration = diagramConfigurationRegistry.get(modelState);
+ if (diagramConfiguration.getLayoutKind() == ServerLayoutKind.AUTOMATIC) {
+ layoutEngine.layout(modelState);
+ }
+ Action modelAction = gModel.getRevision() == 0 ? new SetModelAction(gModel)
+ : new UpdateModelAction(gModel, diagramConfiguration.animatedUpdate());
synchronized (modelLock) {
- return Arrays.asList(action, new SetDirtyStateAction(modelState.isDirty()));
+ List result = new ArrayList<>();
+ result.add(modelAction);
+ if (!diagramConfiguration.needsClientLayout()) {
+ result.add(new SetDirtyStateAction(modelState.isDirty(), reason));
+ }
+ return result;
}
}
+ public List submitModelDirectly(final GModelState modelState) {
+ return submitModelDirectly(modelState, null);
+ }
+
public synchronized Object getModelLock() { return modelLock; }
}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/RequestModelActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/RequestModelActionHandler.java
index 8a773a33..745fba6d 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/RequestModelActionHandler.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/core/model/RequestModelActionHandler.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2019 EclipseSource and others.
+ * Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/undoredo/UndoRedoActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/undoredo/UndoRedoActionHandler.java
index b247979d..adf739ad 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/undoredo/UndoRedoActionHandler.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/features/undoredo/UndoRedoActionHandler.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2019 EclipseSource and others.
+ * Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -20,6 +20,7 @@
import org.apache.log4j.Logger;
import org.eclipse.glsp.server.actions.Action;
import org.eclipse.glsp.server.actions.ActionHandler;
+import org.eclipse.glsp.server.actions.SetDirtyStateAction;
import org.eclipse.glsp.server.features.core.model.ModelSubmissionHandler;
import org.eclipse.glsp.server.model.GModelState;
@@ -36,10 +37,10 @@ public class UndoRedoActionHandler implements ActionHandler {
public List execute(final Action action, final GModelState modelState) {
if (action instanceof UndoAction && modelState.canUndo()) {
modelState.undo();
- return modelSubmissionHandler.submitModel(modelState);
+ return modelSubmissionHandler.submitModel(modelState, SetDirtyStateAction.Reason.UNDO);
} else if (action instanceof RedoAction && modelState.canRedo()) {
modelState.redo();
- return modelSubmissionHandler.submitModel(modelState);
+ return modelSubmissionHandler.submitModel(modelState, SetDirtyStateAction.Reason.REDO);
}
LOG.warn("Cannot undo or redo");
return none();
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/OperationActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/OperationActionHandler.java
index 6c2669de..657a5e9f 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/OperationActionHandler.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/OperationActionHandler.java
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2019 EclipseSource and others.
+ * Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -20,6 +20,7 @@
import org.eclipse.glsp.server.actions.Action;
import org.eclipse.glsp.server.actions.BasicActionHandler;
+import org.eclipse.glsp.server.actions.SetDirtyStateAction;
import org.eclipse.glsp.server.features.core.model.ModelSubmissionHandler;
import org.eclipse.glsp.server.internal.gmodel.commandstack.GModelRecordingCommand;
import org.eclipse.glsp.server.model.GModelState;
@@ -57,7 +58,7 @@ protected List executeHandler(final Operation operation, final Operation
GModelRecordingCommand command = new GModelRecordingCommand(modelState.getRoot(), handler.getLabel(),
() -> handler.execute(operation, modelState));
modelState.execute(command);
- return modelSubmissionHandler.submitModel(modelState);
+ return modelSubmissionHandler.submitModel(modelState, SetDirtyStateAction.Reason.OPERATION);
}
public static Optional extends OperationHandler> getOperationHandler(final Operation operation,