Skip to content

Commit

Permalink
Merge pull request #203 from kieler/nre/client-only-layout
Browse files Browse the repository at this point in the history
copy properties to the SModel already during initial SModel generation
  • Loading branch information
NiklasRentzCAU authored Nov 8, 2024
2 parents b3a2d9c + fe13113 commit 9dd279c
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 41 deletions.
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-2024 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
Expand Down Expand Up @@ -40,6 +40,7 @@ import de.cau.cs.kieler.klighd.lsp.model.SKLabel
import de.cau.cs.kieler.klighd.lsp.model.SKNode
import de.cau.cs.kieler.klighd.lsp.model.SKPort
import de.cau.cs.kieler.klighd.lsp.utils.KGraphElementIdGenerator
import de.cau.cs.kieler.klighd.lsp.utils.KGraphMappingUtil
import de.cau.cs.kieler.klighd.lsp.utils.SprottyProperties
import de.cau.cs.kieler.klighd.util.KlighdPredicates
import de.cau.cs.kieler.klighd.util.KlighdProperties
Expand Down Expand Up @@ -259,6 +260,7 @@ class KGraphDiagramGenerator implements IDiagramGenerator {
nodeElement.data = node.data.filter[KRenderingLibrary.isAssignableFrom(it.class)].toList

setProperties(nodeElement, node)
KGraphMappingUtil.mapProperties(node, nodeElement)
findSpecialRenderings(filteredData)

val renderingContextData = RenderingContextData.get(node)
Expand Down Expand Up @@ -311,6 +313,7 @@ class KGraphDiagramGenerator implements IDiagramGenerator {

val renderings = edge.data.filter[KRendering.isAssignableFrom(it.class)].toList

KGraphMappingUtil.mapProperties(edge, edgeElement)
findSpecialRenderings(renderings)
edgeElement.children.addAll(createLabels(edge.labels))
edgeElement.junctionPoints = edge.getProperty(CoreOptions.JUNCTION_POINTS)
Expand All @@ -332,6 +335,7 @@ class KGraphDiagramGenerator implements IDiagramGenerator {

val renderings = port.data.filter [ KRendering.isAssignableFrom(it.class)].toList

KGraphMappingUtil.mapProperties(port, portElement)
findSpecialRenderings(renderings)
portElement.children.addAll(createLabels(port.labels))

Expand All @@ -353,6 +357,7 @@ class KGraphDiagramGenerator implements IDiagramGenerator {

val renderings = label.data.filter[KRendering.isAssignableFrom(it.class)].toList

KGraphMappingUtil.mapProperties(label, labelElement)
findSpecialRenderings(renderings)
// activate the element by default if it does not have an active/inactive status yet.
val renderingContextData = RenderingContextData.get(label)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class KGraphDiagramServer extends LanguageAwareDiagramServer {
* Tells the server that the diagram should be refreshed.
*/
protected def handle(RefreshDiagramAction action) {
getOptions().putAll(action.options)
updateDiagram()
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import de.cau.cs.kieler.klighd.lsp.launch.AbstractLanguageServer
import de.cau.cs.kieler.klighd.lsp.model.RequestDiagramPieceAction
import de.cau.cs.kieler.klighd.lsp.model.SKGraph
import de.cau.cs.kieler.klighd.lsp.utils.KGraphMappingUtil
import de.cau.cs.kieler.klighd.lsp.utils.RenderingPreparer
import de.cau.cs.kieler.klighd.util.KlighdSynthesisProperties
import java.util.HashSet
import java.util.List
Expand Down Expand Up @@ -316,6 +317,7 @@ class KGraphDiagramUpdater extends DiagramUpdater {
var SGraph sGraph = null;
synchronized (diagramState) {
sGraph = diagramGenerator.toSGraph(viewContext.viewModel, uri, cancelIndicator)
RenderingPreparer.prepareRenderingIDs(viewContext.viewModel, diagramGenerator.getKGraphToSModelElementMap)
}
if (incrementalDiagramGenerator) {
val requestManager = new KGraphDiagramPieceRequestManager(diagramGenerator as KGraphIncrementalDiagramGenerator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class KGraphLayoutEngine extends ElkLayoutEngine {

synchronized (kGraphContext.viewModel) {
lightDiagramLayoutConfig.performLayout
RenderingPreparer.prepareRendering(kGraphContext.viewModel, diagramState.getKGraphToSModelElementMap(uri))
RenderingPreparer.prepareRenderingLayout(kGraphContext.viewModel, diagramState.getKGraphToSModelElementMap(uri))
}
}

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-2022 by
* Copyright 2018-2024 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
Expand All @@ -18,6 +18,7 @@ package de.cau.cs.kieler.klighd.lsp.model

import de.cau.cs.kieler.klighd.krendering.KImage
import java.util.List
import java.util.Map
import java.util.Set
import java.util.function.Consumer
import org.eclipse.sprotty.Action
Expand Down Expand Up @@ -213,6 +214,8 @@ class RefreshDiagramAction implements Action {
public static val KIND = 'refreshDiagram'
String kind = KIND

Map<String, String> options

new() {}
new(Consumer<RefreshDiagramAction> initializer) {
initializer.accept(this)
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-2022 by
* Copyright 2018-2024 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
Expand Down Expand Up @@ -39,6 +39,7 @@ abstract interface SKElement {
def List<KGraphData> getData()
def void setData(List<KGraphData> data)
def HashMap<String, Object> getProperties()
def void setProperties(HashMap<String, Object> theProperties)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import de.cau.cs.kieler.klighd.kgraph.KLabel
import de.cau.cs.kieler.klighd.kgraph.KNode
import de.cau.cs.kieler.klighd.kgraph.KPort
import de.cau.cs.kieler.klighd.kgraph.KShapeLayout
import de.cau.cs.kieler.klighd.kgraph.util.KGraphUtil
import de.cau.cs.kieler.klighd.lsp.model.SKEdge
import de.cau.cs.kieler.klighd.lsp.model.SKElement
import de.cau.cs.kieler.klighd.lsp.model.SKLabel
Expand All @@ -39,7 +40,6 @@ import org.eclipse.sprotty.Dimension
import org.eclipse.sprotty.Point
import org.eclipse.sprotty.SModelElement
import org.eclipse.sprotty.SShapeElement
import de.cau.cs.kieler.klighd.kgraph.util.KGraphUtil

/**
* A helper class containing static methods for mapping of KGraph and SGraph bounds.
Expand Down Expand Up @@ -108,15 +108,7 @@ class KGraphMappingUtil {
skEdge.junctionPoints.addAllAsCopies(0, kEdge.getProperty(CoreOptions.JUNCTION_POINTS))
skEdge.junctionPoints.offset(new KVector(leftInset, topInset))

// map all properties excepts those that are blacklisted
// also include external whitelisted properties
var properties = kEdge.allProperties;

for (propertyKVPair : properties.entrySet()) {
if (keepProperty(propertyKVPair.key)) {
skEdge.properties.put(propertyKVPair.key.id, propertyKVPair.value)
}
}
mapProperties(kEdge, skEdge)
}

/**
Expand All @@ -138,11 +130,19 @@ class KGraphMappingUtil {
skNode.position = new Point(kNode.xpos + leftInset, kNode.ypos + topInset)
skNode.size = new Dimension(kNode.width, kNode.height)

var properties = kNode.allProperties;
mapProperties(kNode, skNode)
}

/**
* Maps the properties of the KGraphElement to the corresponding SModelElement.
* Excepts those that are blacklisted, but also include whitelisted external properties.
*/
static def mapProperties(KGraphElement kElement, SKElement sElement) {
val properties = kElement.allProperties

for (propertyKVPair : properties.entrySet()) {
if (keepProperty(propertyKVPair.key)) {
skNode.properties.put(propertyKVPair.key.id, propertyKVPair.value)
sElement.properties.put(propertyKVPair.key.id, propertyKVPair.value)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,93 @@ import static extension de.cau.cs.kieler.klighd.lsp.utils.SprottyProperties.*
* @author nre
*/
final class RenderingPreparer {

/**
* Prepares the rendering IDs of a KGraph to be generated for an external viewer.
*
*
* @param element The parent element containing the graph to calculate all rendering IDs for.
* @param kGraphToSGraph A map for identifying the SGraph element for each KGraph element in this graph.
*/
static def void prepareRenderingIDs(KGraphElement element, Map<KGraphElement, SModelElement> kGraphToSGraph) {
// calculate the IDs of all renderings:
for (var int i = 0; i < element.data.size; i++) {
val data = element.data.get(i)
switch(data) {
KRenderingLibrary: {
// The library needs to generate ids for all later KRenderingRefs to refer to.
for (var int j = 0; j < data.renderings.size; j++) {
val rendering = data.renderings.get(j)
if (rendering instanceof KRendering) {
KRenderingIdGenerator.generateIdsRecursive(rendering, "$$lib$$", j)
}
}
}
KRenderingRef: {
// rendering refs refer to the referred ID
data.renderingId = kGraphToSGraph.get(element)?.id + data.rendering.renderingId
}
KRendering: {
// every rendering needs an ID, generate it here
KRenderingIdGenerator.generateIdsRecursive(data, kGraphToSGraph.get(element)?.id + "$$", i)
}
}
}

// Recursively call this method for every child KGraphElement of this.
// (all labels, child nodes, outgoing edges and ports)

if (element instanceof KLabeledGraphElement) {
for (label : element.labels) {
prepareRenderingIDs(label, kGraphToSGraph)
}
}
if (element instanceof KNode) {
// Do not recurse generating IDs if the element is not expanded, as there won't be any SGraph generated for
// it.
var boolean isExpanded
val renderingContextData = RenderingContextData.get(element)
if (renderingContextData.hasProperty(SprottyProperties.EXPANDED)) {
isExpanded = renderingContextData.getProperty(SprottyProperties.EXPANDED)
} else {
// If the expanded property does not exist yet, use the initial expansion.
isExpanded = element.getProperty(KlighdProperties.EXPAND)
}

if (isExpanded) {
for (node : element.children) {
prepareRenderingIDs(node, kGraphToSGraph)
}
}
for (edge : element.outgoingEdges) {
// not expanded => edge must not have the target node inside the non-expanded
if (isExpanded || !KGraphUtil.isDescendant(edge.target, element)) {
prepareRenderingIDs(edge, kGraphToSGraph)
}
}
for (port : element.ports) {
prepareRenderingIDs(port, kGraphToSGraph)
}
}

// Also prepare the IDs of all proxy-renderings
val proxyRendering = element.getProperty(KlighdProperties.PROXY_VIEW_PROXY_RENDERING)
if (element.getProperty(KlighdProperties.PROXY_VIEW_RENDER_NODE_AS_PROXY) && proxyRendering !== null) {
for (var int i = 0; i < proxyRendering.size; i++) {
val data = proxyRendering.get(i)
switch(data) {
KRenderingRef: {
// rendering refs refer to the referred ID
data.renderingId = kGraphToSGraph.get(element)?.id + data.rendering.renderingId
}
KRendering: {
// every rendering needs an ID, generate it here
KRenderingIdGenerator.generateIdsRecursive(data, kGraphToSGraph.get(element)?.id + "$$", i)
}
}
}
}
}

/**
* Prepares a KGraphElement to be rendered in an external viewer.
Expand All @@ -74,29 +161,18 @@ final class RenderingPreparer {
* In case of a {@link KRenderingRef} the bounds and decoration are persisted for every referenced rendering as a map
* inside the properties of the reference.
* For example: &lt;id of the rendering in the library: bounds in this instance&gt;
* Furthermore, for every rendering a unique ID is generated.
* Finally, modifiable styles defined by the synthesis are processed for the rendering.
*
* @param element The parent element containing the graph to calculate all rendering bounds for.
* @param kGraphToSGraph A map for identifying the SGraph element for each KGraph element in this graph.
*/
static def void prepareRendering(KGraphElement element, Map<KGraphElement, SModelElement> kGraphToSGraph) {
static def void prepareRenderingLayout(KGraphElement element, Map<KGraphElement, SModelElement> kGraphToSGraph) {
// calculate the sizes of all renderings:
for (var int i = 0; i < element.data.size; i++) {
val data = element.data.get(i)
switch(data) {
KRenderingLibrary: {
// The library needs to generate ids for all later KRenderingRefs to refer to, but no own bounds,
// since these are generic renderings.
for (var int j = 0; j < data.renderings.size; j++) {
val rendering = data.renderings.get(j)
if (rendering instanceof KRendering) {
KRenderingIdGenerator.generateIdsRecursive(rendering, "$$lib$$", j)
}
}
}
KRenderingRef: {
// all references to KRenderings need to place a map with the ids of the renderings and their
// all references to KRenderings need to place a map with their
// sizes and their decoration in this case in the properties of the reference.
var boundsMap = new HashMap<String, Bounds>
var decorationMap = new HashMap<String, Decoration>
Expand All @@ -105,12 +181,8 @@ final class RenderingPreparer {
data.properties.put(CALCULATED_BOUNDS_MAP, boundsMap)
// and the decorationMap
data.properties.put(CALCULATED_DECORATION_MAP, decorationMap)
// remember the id of the rendering in the reference
data.renderingId = kGraphToSGraph.get(element)?.id + data.rendering.renderingId
}
KRendering: {
// every rendering needs an ID, generate it here
KRenderingIdGenerator.generateIdsRecursive(data, kGraphToSGraph.get(element)?.id + "$$", i)
handleKRendering(element, data, null, null)
}
}
Expand All @@ -121,7 +193,7 @@ final class RenderingPreparer {

if (element instanceof KLabeledGraphElement) {
for (label : element.labels) {
prepareRendering(label, kGraphToSGraph)
prepareRenderingLayout(label, kGraphToSGraph)
}
}
if (element instanceof KNode) {
Expand All @@ -138,17 +210,17 @@ final class RenderingPreparer {

if (isExpanded) {
for (node : element.children) {
prepareRendering(node, kGraphToSGraph)
prepareRenderingLayout(node, kGraphToSGraph)
}
}
for (edge : element.outgoingEdges) {
// not expanded => edge must not have the target node inside the non-expanded
if (isExpanded || !KGraphUtil.isDescendant(edge.target, element)) {
prepareRendering(edge, kGraphToSGraph)
prepareRenderingLayout(edge, kGraphToSGraph)
}
}
for (port : element.ports) {
prepareRendering(port, kGraphToSGraph)
prepareRenderingLayout(port, kGraphToSGraph)
}
}

Expand All @@ -168,13 +240,9 @@ final class RenderingPreparer {
data.properties.put(CALCULATED_BOUNDS_MAP, boundsMap)
// and the decorationMap
data.properties.put(CALCULATED_DECORATION_MAP, decorationMap)
// remember the id of the rendering in the reference
data.renderingId = kGraphToSGraph.get(element)?.id + data.rendering.renderingId

}
KRendering: {
// every rendering needs an ID, generate it here
KRenderingIdGenerator.generateIdsRecursive(data, kGraphToSGraph.get(element)?.id + "$$", i)
if (data.eContainer instanceof KNode) {
// Calculate the size and layout of the proxy first.
val parent = data.eContainer as KNode
Expand Down

0 comments on commit 9dd279c

Please sign in to comment.