Skip to content

Commit

Permalink
#197, #196: Improve dirty state handling (#101)
Browse files Browse the repository at this point in the history
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 eclipse-glsp/glsp#197
Fixes eclipse-glsp/glsp#196
  • Loading branch information
tortmayr authored Mar 23, 2021
1 parent 398772b commit 38004fd
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -51,7 +51,7 @@ public List<Action> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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);
Expand All @@ -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";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ default ShapeTypeHint createDefaultNodeTypeHint(final String elementId) {
default boolean needsClientLayout() {
return true;
}

default boolean animatedUpdate() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -15,6 +15,7 @@
********************************************************************************/
package org.eclipse.glsp.server.features.core.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

Expand Down Expand Up @@ -55,28 +56,32 @@ public class ModelSubmissionHandler {
* </p>
*
* @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<Action> submitModel(final GModelState modelState) {
public List<Action> 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<Action> 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.
* <p>
* 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}.
* </p>
Expand All @@ -87,15 +92,30 @@ public List<Action> submitModel(final GModelState modelState) {
* </p>
*
* @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<Action> submitModelDirectly(final GModelState modelState) {
public List<Action> 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<Action> result = new ArrayList<>();
result.add(modelAction);
if (!diagramConfiguration.needsClientLayout()) {
result.add(new SetDirtyStateAction(modelState.isDirty(), reason));
}
return result;
}
}

public List<Action> submitModelDirectly(final GModelState modelState) {
return submitModelDirectly(modelState, null);
}

public synchronized Object getModelLock() { return modelLock; }
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;

Expand All @@ -36,10 +37,10 @@ public class UndoRedoActionHandler implements ActionHandler {
public List<Action> 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -57,7 +58,7 @@ protected List<Action> 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,
Expand Down

0 comments on commit 38004fd

Please sign in to comment.