From 8bf500e16447b97e7b597fb50c115dac437523e7 Mon Sep 17 00:00:00 2001 From: Martin Fleck Date: Tue, 14 Nov 2023 10:09:42 +0100 Subject: [PATCH] Add ghost elements to tool palette items through trigger actions Relates to https://github.com/eclipse-glsp/glsp/issues/1159 --- .../CreateWorkflowNodeOperationHandler.java | 6 ++ .../server/emf/EMFCreateOperationHandler.java | 29 +++++++++ .../glsp/server/actions/GhostElement.java | 63 +++++++++++++++++++ .../actions/TriggerNodeCreationAction.java | 16 +++++ .../GModelCreateNodeOperationHandler.java | 24 +++++++ 5 files changed, 138 insertions(+) create mode 100644 plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/GhostElement.java diff --git a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/handler/CreateWorkflowNodeOperationHandler.java b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/handler/CreateWorkflowNodeOperationHandler.java index e51b86fa..fbf14f0c 100644 --- a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/handler/CreateWorkflowNodeOperationHandler.java +++ b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/handler/CreateWorkflowNodeOperationHandler.java @@ -15,6 +15,7 @@ ********************************************************************************/ package org.eclipse.glsp.example.workflow.handler; +import java.util.HashMap; import java.util.Optional; import org.eclipse.glsp.example.workflow.utils.ModelTypes; @@ -22,6 +23,7 @@ import org.eclipse.glsp.graph.GCompartment; import org.eclipse.glsp.graph.GModelElement; import org.eclipse.glsp.graph.GPoint; +import org.eclipse.glsp.server.actions.GhostElement; import org.eclipse.glsp.server.gmodel.GModelCreateNodeOperationHandler; import org.eclipse.glsp.server.operations.CreateNodeOperation; @@ -50,4 +52,8 @@ protected Optional getCategoryCompartment(final Category category) .filter(comp -> ModelTypes.STRUCTURE.equals(comp.getType())).findFirst(); } + @Override + protected GhostElement createTriggerGhostElement(final String elementTypeId) { + return new GhostElement(createNode(Optional.empty(), new HashMap<>()), true); + } } diff --git a/plugins/org.eclipse.glsp.server.emf/src/org/eclipse/glsp/server/emf/EMFCreateOperationHandler.java b/plugins/org.eclipse.glsp.server.emf/src/org/eclipse/glsp/server/emf/EMFCreateOperationHandler.java index 0c29f35e..c036c60a 100644 --- a/plugins/org.eclipse.glsp.server.emf/src/org/eclipse/glsp/server/emf/EMFCreateOperationHandler.java +++ b/plugins/org.eclipse.glsp.server.emf/src/org/eclipse/glsp/server/emf/EMFCreateOperationHandler.java @@ -16,8 +16,14 @@ package org.eclipse.glsp.server.emf; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.glsp.server.actions.ActionDispatcher; +import org.eclipse.glsp.server.actions.GhostElement; +import org.eclipse.glsp.server.actions.TriggerElementCreationAction; +import org.eclipse.glsp.server.actions.TriggerNodeCreationAction; +import org.eclipse.glsp.server.operations.CreateNodeOperation; import org.eclipse.glsp.server.operations.CreateOperation; import org.eclipse.glsp.server.operations.CreateOperationHandler; @@ -46,4 +52,27 @@ public EMFCreateOperationHandler(final List handledElementTypeIds) { public void setHandledElementTypeIds(final List handledElementTypeIds) { this.handledElementTypeIds = handledElementTypeIds; } + + @Override + public List getTriggerActions() { + if (CreateNodeOperation.class.isAssignableFrom(getHandledOperationType())) { + return getHandledElementTypeIds().stream().map(this::createTriggerNodeCreationAction) + .collect(Collectors.toList()); + } + return CreateOperationHandler.super.getTriggerActions(); + } + + protected TriggerNodeCreationAction createTriggerNodeCreationAction(final String elementTypeId) { + return new TriggerNodeCreationAction(elementTypeId, + createTriggerArgs(elementTypeId), + createTriggerGhostElement(elementTypeId)); + } + + protected GhostElement createTriggerGhostElement(final String elementTypeId) { + return null; + } + + protected Map createTriggerArgs(final String elementTypeId) { + return null; + } } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/GhostElement.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/GhostElement.java new file mode 100644 index 00000000..041602ea --- /dev/null +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/GhostElement.java @@ -0,0 +1,63 @@ +/******************************************************************************** + * 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 java.util.Optional; + +import org.eclipse.glsp.graph.GModelElement; + +/** + * A ghost element describes an element that may be rendered as a schematic visualization of an element that may be + * inserted during creation. + */ +public class GhostElement { + private Object template; + private Boolean dynamic; + + public GhostElement(final String templateElementId) { + this.template = templateElementId; + } + + public GhostElement(final String templateElementId, final boolean dynamic) { + this.template = templateElementId; + this.dynamic = dynamic; + } + + public GhostElement(final GModelElement element) { + this.template = element; + } + + public GhostElement(final GModelElement element, final boolean dynamic) { + this.template = element; + this.dynamic = dynamic; + } + + public Optional getTemplateElementId() { + return template instanceof String templateElementId ? Optional.of(templateElementId) : Optional.empty(); + } + + public void setTemplateElementId(final String templateElementId) { this.template = templateElementId; } + + public Optional getTemplateElement() { + return template instanceof GModelElement templateElement ? Optional.of(templateElement) : Optional.empty(); + } + + public void setTemplateElement(final GModelElement templateElement) { this.template = templateElement; } + + public Boolean getDynamic() { return dynamic; } + + public void setDynamic(final boolean dynamic) { this.dynamic = dynamic; } +} diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/TriggerNodeCreationAction.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/TriggerNodeCreationAction.java index 34b06402..0f802354 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/TriggerNodeCreationAction.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/TriggerNodeCreationAction.java @@ -25,6 +25,8 @@ public class TriggerNodeCreationAction extends TriggerElementCreationAction { public static final String KIND = "triggerNodeCreation"; + private GhostElement ghostElement; + public TriggerNodeCreationAction() { this(null); } @@ -33,9 +35,23 @@ public TriggerNodeCreationAction(final String elementTypeId) { this(elementTypeId, new HashMap<>()); } + public TriggerNodeCreationAction(final String elementTypeId, final GhostElement ghostElement) { + this(elementTypeId, new HashMap<>(), ghostElement); + } + public TriggerNodeCreationAction(final String elementTypeId, final Map args) { super(KIND, elementTypeId, args); } + public TriggerNodeCreationAction(final String elementTypeId, + final Map args, final GhostElement ghostElement) { + super(KIND, elementTypeId, args); + this.ghostElement = ghostElement; + } + + public GhostElement getGhostElement() { return ghostElement; } + + public void setGhostElement(final GhostElement ghostElement) { this.ghostElement = ghostElement; } + } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/gmodel/GModelCreateNodeOperationHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/gmodel/GModelCreateNodeOperationHandler.java index d4ae5ba1..46a1f67d 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/gmodel/GModelCreateNodeOperationHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/gmodel/GModelCreateNodeOperationHandler.java @@ -18,13 +18,17 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import org.eclipse.emf.common.command.Command; import org.eclipse.glsp.graph.GModelElement; import org.eclipse.glsp.graph.GNode; import org.eclipse.glsp.graph.GPoint; import org.eclipse.glsp.server.actions.ActionDispatcher; +import org.eclipse.glsp.server.actions.GhostElement; import org.eclipse.glsp.server.actions.SelectAction; +import org.eclipse.glsp.server.actions.TriggerElementCreationAction; +import org.eclipse.glsp.server.actions.TriggerNodeCreationAction; import org.eclipse.glsp.server.operations.CreateEdgeOperation; import org.eclipse.glsp.server.operations.CreateNodeOperation; import org.eclipse.glsp.server.utils.LayoutUtil; @@ -86,6 +90,26 @@ protected Optional getContainer(final CreateNodeOperation operati return modelState.getIndex().get(operation.getContainerId()); } + @Override + public List getTriggerActions() { + return getHandledElementTypeIds().stream().map(this::createTriggerNodeCreationAction) + .collect(Collectors.toList()); + } + + protected TriggerNodeCreationAction createTriggerNodeCreationAction(final String elementTypeId) { + return new TriggerNodeCreationAction(elementTypeId, + createTriggerArgs(elementTypeId), + createTriggerGhostElement(elementTypeId)); + } + + protected GhostElement createTriggerGhostElement(final String elementTypeId) { + return null; + } + + protected Map createTriggerArgs(final String elementTypeId) { + return null; + } + /** * Create and return the new Node at the specified (optional) location. The location * is given in coordinates relative to the