diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/CheckEdgeTargetResultAction.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/CheckEdgeTargetResultAction.java new file mode 100644 index 00000000..f4a2668f --- /dev/null +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/CheckEdgeTargetResultAction.java @@ -0,0 +1,40 @@ +/******************************************************************************** + * Copyright (c) 2023 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 + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.server.actions; + +/** + * {@link ResponseAction} for a {@link RequestCheckEdgeTargetAction}. + */ +public class CheckEdgeTargetResultAction extends ResponseAction { + + public static final String KIND = "setTargetTypeHints"; + + private boolean isValid; + + public CheckEdgeTargetResultAction() { + this(false); + } + + public CheckEdgeTargetResultAction(final boolean isValid) { + super(KIND); + this.setValid(isValid); + } + + public boolean isValid() { return isValid; } + + public void setValid(final boolean isValid) { this.isValid = isValid; } + +} diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/RequestCheckEdgeTargetAction.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/RequestCheckEdgeTargetAction.java new file mode 100644 index 00000000..8de3cc8e --- /dev/null +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/RequestCheckEdgeTargetAction.java @@ -0,0 +1,69 @@ +/******************************************************************************** + * Copyright (c) 2023 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 + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.server.actions; + +import org.eclipse.glsp.server.types.EdgeTypeHint; + +/** + * A {@link RequestAction} used to check the validity of an edge being created. This is used + * to update creation feedback on the client side, for edges configured with a dynamic {@link EdgeTypeHint}. + * + * @see EdgeTypeHint#isDynamic() + * @see CheckEdgeTargetResultAction + */ +public class RequestCheckEdgeTargetAction extends RequestAction { + + public static final String KIND = "requestCheckEdgeTarget"; + + private String edgeTypeId; + + private String sourceElementId; + + private String targetElementId; + + public RequestCheckEdgeTargetAction() { + super(KIND); + } + + /** + * The element type id of the Edge. + * + * @return + * the element type id of the Edge. + */ + public String getEdgeTypeId() { return edgeTypeId; } + + public void setEdgeTypeId(final String edgeTypeId) { this.edgeTypeId = edgeTypeId; } + + /** + * The ID of the source element of the edge being created. + * + * @return the ID of the source element of the edge being created. + */ + public String getSourceElementId() { return sourceElementId; } + + public void setSourceElementId(final String sourceElementId) { this.sourceElementId = sourceElementId; } + + /** + * The ID of the target element of the edge being created. + * + * @return the ID of the target element of the edge being created. + */ + public String getTargetElementId() { return targetElementId; } + + public void setTargetElementId(final String targetElementId) { this.targetElementId = targetElementId; } + +} diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DiagramModule.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DiagramModule.java index bf402cdc..be8198c9 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DiagramModule.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DiagramModule.java @@ -35,6 +35,7 @@ import org.eclipse.glsp.server.actions.SetDirtyStateAction; import org.eclipse.glsp.server.actions.SetEditModeAction; import org.eclipse.glsp.server.actions.SetEditModeActionHandler; +import org.eclipse.glsp.server.actions.CheckEdgeTargetResultAction; import org.eclipse.glsp.server.actions.SetViewportAction; import org.eclipse.glsp.server.actions.StartProgressAction; import org.eclipse.glsp.server.actions.TriggerEdgeCreationAction; @@ -43,6 +44,7 @@ import org.eclipse.glsp.server.di.scope.DiagramGlobalScope; import org.eclipse.glsp.server.di.scope.DiagramGlobalSingleton; import org.eclipse.glsp.server.diagram.DiagramConfiguration; +import org.eclipse.glsp.server.diagram.DefaultRequestTargetTypeHintsActionHandler; import org.eclipse.glsp.server.diagram.RequestTypeHintsActionHandler; import org.eclipse.glsp.server.diagram.ServerConfigurationContribution; import org.eclipse.glsp.server.diagram.SetTypeHintsAction; @@ -320,6 +322,7 @@ protected void configureClientActions(final MultiBinding binding) { binding.add(TriggerNodeCreationAction.class); binding.add(UpdateModelAction.class); binding.add(UpdateProgressAction.class); + binding.add(CheckEdgeTargetResultAction.class); } protected void configureActionHandlers(final MultiBinding binding) { @@ -338,6 +341,7 @@ protected void configureActionHandlers(final MultiBinding binding binding.add(ComputedBoundsActionHandler.class); binding.add(SaveModelActionHandler.class); binding.add(UndoRedoActionHandler.class); + binding.add(DefaultRequestTargetTypeHintsActionHandler.class); } protected Class bindActionHandlerRegistry() { diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DefaultRequestTargetTypeHintsActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DefaultRequestTargetTypeHintsActionHandler.java new file mode 100644 index 00000000..4147e6ca --- /dev/null +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/diagram/DefaultRequestTargetTypeHintsActionHandler.java @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2023 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 + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.server.diagram; + +import java.util.List; + +import org.eclipse.glsp.server.actions.AbstractActionHandler; +import org.eclipse.glsp.server.actions.Action; +import org.eclipse.glsp.server.actions.CheckEdgeTargetResultAction; +import org.eclipse.glsp.server.actions.RequestCheckEdgeTargetAction; + +import com.google.inject.Inject; + +/** + * Default handler implementation for {@link RequestCheckEdgeTargetAction}. + * This handler always rejects creation of dynamic Edges. Client applications + * should replace this default implementation with their own logic to + * conditionally accept creation of new edges configured with a Dynamic type. + */ +public class DefaultRequestTargetTypeHintsActionHandler extends AbstractActionHandler { + + @Inject + protected DiagramConfiguration diagramConfiguration; + + @Override + protected List executeAction(final RequestCheckEdgeTargetAction actualAction) { + return List.of(new CheckEdgeTargetResultAction()); + } + +} 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 0fffbc20..82009c41 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 @@ -71,7 +71,7 @@ public interface DiagramConfiguration { Optional getGraphExtension(); default EdgeTypeHint createDefaultEdgeTypeHint(final String elementId) { - return new EdgeTypeHint(elementId, true, true, true, null, null); + return new EdgeTypeHint(elementId, true, true, true, false, null, null); } default ShapeTypeHint createDefaultShapeTypeHint(final String elementId) { diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/types/EdgeTypeHint.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/types/EdgeTypeHint.java index 5d9b6a34..72595c96 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/types/EdgeTypeHint.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/types/EdgeTypeHint.java @@ -17,6 +17,8 @@ import java.util.List; +import org.eclipse.glsp.server.actions.RequestCheckEdgeTargetAction; + /** * {@link ElementTypeHint Element type hints} for edges. */ @@ -25,12 +27,19 @@ public class EdgeTypeHint extends ElementTypeHint { private boolean routable; private List sourceElementTypeIds; private List targetElementTypeIds; + private boolean dynamic = false; public EdgeTypeHint() {} public EdgeTypeHint(final String elementTypeId, final boolean repositionable, final boolean deletable, final boolean routable, final List sourceElementTypeIds, final List targetElementTypeIds) { + this(elementTypeId, repositionable, deletable, routable, false, sourceElementTypeIds, targetElementTypeIds); + } + + public EdgeTypeHint(final String elementTypeId, final boolean repositionable, final boolean deletable, + final boolean routable, final boolean dynamic, + final List sourceElementTypeIds, final List targetElementTypeIds) { super(elementTypeId, repositionable, deletable); this.routable = routable; this.sourceElementTypeIds = sourceElementTypeIds; @@ -53,4 +62,15 @@ public void setTargetElementTypeIds(final List targetElementTypeIds) { this.targetElementTypeIds = targetElementTypeIds; } + /** + * Indicates whether this type hint is dynamic or not. Dynamic edge type hints + * require an additional runtime check before creating an edge, when checking + * source and target element types is not sufficient. + * + * @see RequestCheckEdgeTargetAction + */ + public boolean isDynamic() { return dynamic; } + + public void setDynamic(final boolean isDynamic) { this.dynamic = isDynamic; } + }