Skip to content

Commit

Permalink
Merge pull request #145 from kieler/sdo/interactiveMrTree
Browse files Browse the repository at this point in the history
Adds language server interaction possibilities for interactive layout for ELK's MrTree. Cleans up and restructures features related to interactive.
  • Loading branch information
NiklasRentzCAU authored Mar 14, 2024
2 parents 408ed02 + b0c908c commit 0ee929a
Show file tree
Hide file tree
Showing 34 changed files with 1,669 additions and 389 deletions.
2 changes: 2 additions & 0 deletions plugins/de.cau.cs.kieler.klighd.lsp/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Export-Package: de.cau.cs.kieler.klighd.lsp,
de.cau.cs.kieler.klighd.lsp.gson_utils,
de.cau.cs.kieler.klighd.lsp.interactive,
de.cau.cs.kieler.klighd.lsp.interactive.layered,
de.cau.cs.kieler.klighd.lsp.interactive.mrtree,
de.cau.cs.kieler.klighd.lsp.interactive.rectpacking,
de.cau.cs.kieler.klighd.lsp.launch,
de.cau.cs.kieler.klighd.lsp.model,
Expand All @@ -25,6 +26,7 @@ Require-Bundle: de.cau.cs.kieler.kgraph.text,
com.google.inject;bundle-version="3.0.0",
org.apache.log4j;bundle-version="1.2.15",
org.eclipse.elk.alg.layered,
org.eclipse.elk.alg.mrtree,
org.eclipse.elk.alg.rectpacking,
org.eclipse.elk.core,
org.eclipse.elk.graph,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
de.cau.cs.kieler.klighd.lsp.interactive.layered.LayeredInteractiveActionHandler
de.cau.cs.kieler.klighd.lsp.interactive.rectpacking.RectpackingInteractiveActionHandler
de.cau.cs.kieler.klighd.lsp.interactive.mrtree.MrTreeActionHandler
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
de.cau.cs.kieler.klighd.lsp.interactive.ElkGraphConstraintSerializer
5 changes: 5 additions & 0 deletions plugins/de.cau.cs.kieler.klighd.lsp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
<artifactId>org.eclipse.elk.alg.layered</artifactId>
<version>${elk-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.elk</groupId>
<artifactId>org.eclipse.elk.alg.mrtree</artifactId>
<version>${elk-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.elk</groupId>
<artifactId>org.eclipse.elk.alg.rectpacking</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,25 @@
*/
package de.cau.cs.kieler.klighd.lsp

import java.util.HashMap
import org.eclipse.xtend.lib.annotations.Accessors
import java.util.Map
import org.eclipse.sprotty.Action

/**
* Abstract class to handle Sprotty actions.
*
* @author sdo
*/
abstract class AbstractActionHandler implements IActionHandler {
abstract class AbstractActionHandler implements ISprottyActionHandler {

@Accessors(PUBLIC_GETTER, PROTECTED_SETTER)
HashMap<String, Class<?>> supportedMessages = newHashMap
Map<String, Class<? extends Action>> supportedMessages

override Map<String, Class<? extends Action>> getSupportedMessages() {
return supportedMessages
}

def setSupportedMessages(Map<String, Class<? extends Action>> messages) {
this.supportedMessages = messages
}

override canHandleAction(String kind) {
return supportedMessages.containsKey(kind)

}
return supportedMessages.containsKey(kind)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
package de.cau.cs.kieler.klighd.lsp

import org.eclipse.sprotty.Action
import java.util.Map

/**
* Service Interface for ActionHandler.
*
* @author sdo
* Service interface for Sprotty action handlers.
*/
interface IActionHandler {
interface ISprottyActionHandler {


def Map<String, Class<? extends Action>> getSupportedMessages();

/**
* Checks and returns true if this ActionHandler can handle this action.
* @param kind String identifier of action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import java.util.HashSet
import java.util.List
import org.apache.log4j.Logger
import org.eclipse.elk.alg.layered.options.LayeredOptions
import org.eclipse.elk.alg.rectpacking.options.RectPackingOptions
import org.eclipse.elk.core.options.CoreOptions
import org.eclipse.emf.ecore.EObject
import org.eclipse.sprotty.Dimension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ package de.cau.cs.kieler.klighd.lsp
import com.google.common.base.Throwables
import com.google.common.io.ByteStreams
import com.google.inject.Inject
import com.google.inject.Injector
import de.cau.cs.kieler.klighd.IAction
import de.cau.cs.kieler.klighd.IAction.ActionContext
import de.cau.cs.kieler.klighd.Klighd
import de.cau.cs.kieler.klighd.KlighdDataManager
import de.cau.cs.kieler.klighd.ViewContext
import de.cau.cs.kieler.klighd.kgraph.KNode
import de.cau.cs.kieler.klighd.lsp.interactive.layered.LayeredInteractiveActionHandler
import de.cau.cs.kieler.klighd.lsp.interactive.rectpacking.RectpackingInteractiveActionHandler
import de.cau.cs.kieler.klighd.lsp.model.CheckImagesAction
import de.cau.cs.kieler.klighd.lsp.model.CheckedImagesAction
import de.cau.cs.kieler.klighd.lsp.model.DisplayedActionUIData
Expand All @@ -47,8 +46,13 @@ import java.io.InputStream
import java.util.ArrayList
import java.util.Base64
import java.util.Collection
import java.util.HashMap
import java.util.List
import java.util.Map
import java.util.ServiceLoader
import java.util.Set
import java.util.concurrent.CompletableFuture
import org.apache.log4j.Logger
import org.eclipse.core.runtime.Platform
import org.eclipse.elk.core.data.LayoutMetaDataService
import org.eclipse.elk.core.data.LayoutOptionData
Expand All @@ -74,11 +78,9 @@ import org.eclipse.xtend.lib.annotations.Accessors
*/
class KGraphDiagramServer extends LanguageAwareDiagramServer {

@Inject
protected LayeredInteractiveActionHandler constraintActionHandler
@Inject protected Injector injector

@Inject
protected RectpackingInteractiveActionHandler rectpackingActionHandler
Map<String, ISprottyActionHandler> handlers = new HashMap

@Inject
protected KGraphDiagramState diagramState
Expand All @@ -105,6 +107,22 @@ class KGraphDiagramServer extends LanguageAwareDiagramServer {
@Accessors(PUBLIC_GETTER)
protected Object modelLock = new Object

/**
* Needed for KeithUpdateModelAction
*
* FIXME Remove this if UpdateModelAction has a cause.
*/
new() {
super()
// Create map of registered action kinds and handlers.
ServiceLoader.load(ISprottyActionHandler, KlighdDataManager.getClassLoader()).forEach[handler |
val Set<String> kindsSupported = handler.supportedMessages.keySet
for (kind : kindsSupported) {
handlers.put(kind, handler);
}
]
}

/**
* Prepares the client side update of the model by processing the potentially needed images on the client. Checks
* for client-side cached images with the {@link CheckImagesAction}. If the corresponding response to the
Expand Down Expand Up @@ -215,12 +233,16 @@ class KGraphDiagramServer extends LanguageAwareDiagramServer {
handle(action as RefreshLayoutAction)
} else if (action.getKind === RequestDiagramPieceAction.KIND) {
handle(action as RequestDiagramPieceAction)
} else if (constraintActionHandler.canHandleAction(action.getKind)) {
constraintActionHandler.handle(action, clientId, this)
} else if (rectpackingActionHandler.canHandleAction(action.getKind)) {
rectpackingActionHandler.handle(action, clientId, this)
} else {
super.accept(message)
val handlerInstance = handlers.get(action.kind)
if (handlerInstance !== null) {
// Even though we have an instance, it is not yet populated with all injected things.
val handler = injector.getInstance(handlerInstance.class)
handler.handle(action, clientId, this)
} else {
// If no handler is registered for this message. Let the default super class handle it.
super.accept(message)
}
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* http://rtsys.informatik.uni-kiel.de/kieler
*
* Copyright 2018-2021 by
* Copyright 2018-2022 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
Expand All @@ -17,33 +17,28 @@
package de.cau.cs.kieler.klighd.lsp.gson_utils

import com.google.gson.GsonBuilder
import com.google.inject.Injector
import de.cau.cs.kieler.klighd.KlighdDataManager
import de.cau.cs.kieler.klighd.SynthesisOption
import de.cau.cs.kieler.klighd.lsp.interactive.layered.DeleteLayerConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.layered.DeletePositionConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.layered.DeleteStaticConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.layered.SetLayerConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.layered.SetPositionConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.layered.SetStaticConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.rectpacking.RectpackingDeletePositionConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.rectpacking.RectpackingSetPositionConstraintAction
import de.cau.cs.kieler.klighd.lsp.interactive.rectpacking.SetAspectRatioAction
import de.cau.cs.kieler.klighd.lsp.ISprottyActionHandler
import de.cau.cs.kieler.klighd.lsp.model.CheckedImagesAction
import de.cau.cs.kieler.klighd.lsp.model.PerformActionAction
import de.cau.cs.kieler.klighd.lsp.model.RefreshDiagramAction
import de.cau.cs.kieler.klighd.lsp.model.RefreshLayoutAction
import de.cau.cs.kieler.klighd.lsp.model.RequestDiagramPieceAction
import de.cau.cs.kieler.klighd.lsp.model.SetSynthesisAction
import java.awt.geom.Point2D
import java.util.ServiceLoader
import org.eclipse.emf.ecore.EObject
import org.eclipse.sprotty.server.json.ActionTypeAdapter

/**
* Static util class to configure needed gson type adapters for KGraph serialization.
*
* @author nre
* @author nre, sdo
*/
class KGraphTypeAdapterUtil {
def static GsonBuilder configureGson(GsonBuilder gsonBuilder) {
def static GsonBuilder configureGson(GsonBuilder gsonBuilder, Injector injector) {
gsonBuilder
.registerTypeAdapterFactory(
new ActionTypeAdapter.Factory => [
Expand All @@ -54,21 +49,18 @@ class KGraphTypeAdapterUtil {
addActionKind(RefreshDiagramAction.KIND, RefreshDiagramAction)
addActionKind(RefreshLayoutAction.KIND, RefreshLayoutAction)

// Interactive layered actions
addActionKind(SetStaticConstraintAction.KIND, SetStaticConstraintAction)
addActionKind(SetPositionConstraintAction.KIND, SetPositionConstraintAction)
addActionKind(SetLayerConstraintAction.KIND, SetLayerConstraintAction)
addActionKind(DeleteStaticConstraintAction.KIND, DeleteStaticConstraintAction)
addActionKind(DeletePositionConstraintAction.KIND, DeletePositionConstraintAction)
addActionKind(DeleteLayerConstraintAction.KIND, DeleteLayerConstraintAction)

// Interactive rectpacking actions
addActionKind(RectpackingSetPositionConstraintAction.KIND, RectpackingSetPositionConstraintAction)
addActionKind(RectpackingDeletePositionConstraintAction.KIND, RectpackingDeletePositionConstraintAction)
addActionKind(SetAspectRatioAction.KIND, SetAspectRatioAction)
// Load all registered action handlers and add their actions.
ServiceLoader.load(ISprottyActionHandler, KlighdDataManager.getClassLoader()).forEach[handler |
val handlerInstance = injector.getInstance(handler.class)
handlerInstance.supportedMessages.keySet.forEach[kind |
addActionKind(kind, handlerInstance.supportedMessages.get(kind))
]
]

// Incremental topdown actions
addActionKind(RequestDiagramPieceAction.KIND, RequestDiagramPieceAction)


]
)
.registerTypeAdapter(Point2D, new Point2DTypeAdapter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import de.cau.cs.kieler.klighd.kgraph.KNode
* @author sdo
*/
@Data
class ConstraintProperty {
class ConstraintProperty<T> {
KNode kNode
IProperty<Integer> property
IProperty<T> property
T value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
*
* http://rtsys.informatik.uni-kiel.de/kieler
*
* Copyright 2022 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*/
package de.cau.cs.kieler.klighd.lsp.interactive

import de.cau.cs.kieler.klighd.internal.util.KlighdInternalProperties
import java.util.List
import org.eclipse.elk.graph.ElkNode
import org.eclipse.emf.ecore.resource.Resource

/**
* Serializes constraint for an ELK graph by just adding the corresponding properties.
*
* @author sdo
*
*/
class ElkGraphConstraintSerializer implements IConstraintSerializer {

override canHandle(Object graph) {
return graph instanceof ElkNode
}

override serializeConstraints(
List<ConstraintProperty<Object>> changedNodes,
Object graph,
Resource resource
) {
val codeBefore = InteractiveUtil.serializeResource(resource)
changedNodes.forEach [ c |
val ElkNode elkNode = c.KNode.getProperty(KlighdInternalProperties.MODEL_ELEMENT) as ElkNode
elkNode.setProperty(c.property, c.value)
]

val codeAfter = InteractiveUtil.serializeResource(resource)

return InteractiveUtil.calculateTextEdit(codeBefore, codeAfter)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
*
* http://rtsys.informatik.uni-kiel.de/kieler
*
* Copyright 2022 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*/
package de.cau.cs.kieler.klighd.lsp.interactive

import java.util.List
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.lsp4j.TextEdit

/**
* Service interface for implementations that serialize a set constraint in the model.
* E.g. for ElkGraphs a property is added and the graph serialized,
* for SCCharts an Annotation with a layout constraint is added and the graph serialized.
*
* @author sdo
*
*/
interface IConstraintSerializer {
/**
* Checks whether this serializer can handle a graph type
*
* @param graph The graph to serialize
* @return true if the graph can be serialized
*/
def boolean canHandle(Object graph);

/**
* @param changedNodes The added constraints.
* @param graph The model, e.g. SCChart or ElkGraph.
* @param resource The resource to change
* @return The TextEdit to send to the client consisting of the new text and a range.
*/
def TextEdit serializeConstraints(List<ConstraintProperty<Object>> changedNodes, Object graph, Resource resource);
}
Loading

0 comments on commit 0ee929a

Please sign in to comment.