Skip to content

Commit

Permalink
Split preparing rendering IDs to happen right after model generation
Browse files Browse the repository at this point in the history
(specifically, before any layout stuff)
  • Loading branch information
NiklasRentzCAU committed Sep 30, 2024
1 parent 5277008 commit 1dc8b7d
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 26 deletions.
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 @@ -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 1dc8b7d

Please sign in to comment.