Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diagram layout improvements #1206

Merged
merged 8 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion oomph/LinguaFranca.setup
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@
<repository
url="https://download.eclipse.org/modeling/tmf/xtext/updates/releases/2.26.0/"/>
<repository
url="http://download.eclipse.org/elk/updates/releases/0.7.1/"/>
url="http://download.eclipse.org/elk/updates/releases/0.8.1/"/>
<repository
url="https://kieler.github.io/KLighD/v2.1.0/"/>
<repository
Expand Down
4 changes: 2 additions & 2 deletions org.lflang.diagram/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Require-Bundle: de.cau.cs.kieler.klighd;bundle-version="2.0.0",
com.google.guava,
org.eclipse.xtext,
org.eclipse.xtext.xbase.lib,
org.eclipse.elk.core;bundle-version="0.7.0",
org.eclipse.elk.alg.layered;bundle-version="0.7.0",
org.eclipse.elk.core;bundle-version="0.8.1",
org.eclipse.elk.alg.layered;bundle-version="0.8.1",
org.eclipse.core.resources;bundle-version="3.13.900",
org.lflang;bundle-version="0.1.0",
org.lflang.ide;bundle-version="0.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ public abstract class AbstractSynthesisExtensions {
public boolean getBooleanValue(SynthesisOption option) {
return delegate.getBooleanValue(option);
}

public float getFloatValue(SynthesisOption option) {
return delegate.getFloatValue(option);
}

public Object getObjectValue(final SynthesisOption option) {
return delegate.getObjectValue(option);
}

public <T extends EObject> T associateWith(T derived, Object source) {
return delegate.associateWith(derived, source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.eclipse.elk.core.options.CoreOptions;
import org.eclipse.elk.core.options.Direction;
import org.eclipse.elk.core.options.PortConstraints;
import org.eclipse.elk.core.options.PortLabelPlacement;
import org.eclipse.elk.core.options.PortSide;
import org.eclipse.elk.core.options.SizeConstraint;
import org.eclipse.elk.graph.properties.Property;
Expand All @@ -77,6 +78,7 @@
import org.lflang.diagram.synthesis.styles.ReactorFigureComponents;
import org.lflang.diagram.synthesis.util.CycleVisualization;
import org.lflang.diagram.synthesis.util.InterfaceDependenciesVisualization;
import org.lflang.diagram.synthesis.util.LayoutPostProcessing;
import org.lflang.diagram.synthesis.util.ModeDiagrams;
import org.lflang.diagram.synthesis.util.NamedInstanceUtil;
import org.lflang.diagram.synthesis.util.ReactorIcons;
Expand Down Expand Up @@ -154,6 +156,7 @@ public class LinguaFrancaSynthesis extends AbstractDiagramSynthesis<Model> {
@Inject @Extension private FilterCycleAction _filterCycleAction;
@Inject @Extension private ReactorIcons _reactorIcons;
@Inject @Extension private ModeDiagrams _modeDiagrams;
@Inject @Extension private LayoutPostProcessing _layoutPostProcessing;

// -------------------------------------------------------------------------

Expand Down Expand Up @@ -235,7 +238,9 @@ public List<SynthesisOption> getDisplayedSynthesisOptions() {
SHOW_INSTANCE_NAMES,
REACTOR_PARAMETER_MODE,
SHOW_STATE_VARIABLES,
REACTOR_BODY_TABLE_COLS
REACTOR_BODY_TABLE_COLS,
LayoutPostProcessing.LAYOUT_CATEGORY,
LayoutPostProcessing.MODEL_ORDER
);
}

Expand Down Expand Up @@ -292,6 +297,7 @@ public KNode transform(final Model model) {
_kRenderingExtensions.addInvisibleContainerRendering(child);
setLayoutOption(child, CoreOptions.ALGORITHM, LayeredOptions.ALGORITHM_ID);
setLayoutOption(child, CoreOptions.PADDING, new ElkPadding(0));
// Legacy ordering option.
setLayoutOption(child, CoreOptions.PRIORITY, reactorNodes.size() - index); // Order!
rootNode.getChildren().add(child);
index++;
Expand Down Expand Up @@ -402,6 +408,7 @@ private Collection<KNode> createReactorNode(
setLayoutOption(node, CoreOptions.PADDING, new ElkPadding(-1, 6, 6, 6));
setLayoutOption(node, LayeredOptions.SPACING_COMPONENT_COMPONENT, LayeredOptions.SPACING_COMPONENT_COMPONENT.getDefault() * 0.5f);
}
_layoutPostProcessing.configureMainReactor(node);
} else {
ReactorInstance instance = reactorInstance;

Expand Down Expand Up @@ -521,7 +528,11 @@ private Collection<KNode> createReactorNode(
// Create ports
Map<PortInstance, KPort> inputPorts = new HashMap<>();
Map<PortInstance, KPort> outputPorts = new HashMap<>();
for (PortInstance input : ListExtensions.reverseView(instance.inputs)) {
List<PortInstance> inputs = instance.inputs;
if (LayoutPostProcessing.LEGACY.equals((String) getObjectValue(LayoutPostProcessing.MODEL_ORDER))) {
inputs = ListExtensions.reverseView(instance.inputs);
}
for (PortInstance input : inputs) {
inputPorts.put(input, addIOPort(node, input, true, input.isMultiport(), reactorInstance.isBank()));
}
for (PortInstance output : instance.outputs) {
Expand Down Expand Up @@ -571,6 +582,7 @@ private Collection<KNode> createReactorNode(
Iterables.addAll(nodes, createUserComments(reactor, node));
}
configureReactorNodeLayout(node);
_layoutPostProcessing.configureReactor(node);
}

// Find and annotate cycles
Expand All @@ -594,15 +606,12 @@ private KNode configureReactorNodeLayout(KNode node) {
setLayoutOption(node, CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.minimumSizeWithPorts());
// Allows to freely shuffle ports on each side
setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
// Adjust port label spacing to be closer to edge but not overlap with port figure
setLayoutOption(node, CoreOptions.PORT_LABELS_PLACEMENT, EnumSet.of(PortLabelPlacement.ALWAYS_OTHER_SAME_SIDE, PortLabelPlacement.OUTSIDE, PortLabelPlacement.NEXT_TO_PORT_IF_POSSIBLE));
setLayoutOption(node, CoreOptions.SPACING_LABEL_PORT_HORIZONTAL, 2.0);
setLayoutOption(node, CoreOptions.SPACING_LABEL_PORT_VERTICAL, -3.0);
// Balanced placement with straight long edges.
setLayoutOption(node, LayeredOptions.NODE_PLACEMENT_STRATEGY, NodePlacementStrategy.NETWORK_SIMPLEX);
// Otherwise nodes are not sorted if they are not connected
setLayoutOption(node, CoreOptions.SEPARATE_CONNECTED_COMPONENTS, false);
// Needed to enforce node positions.
setLayoutOption(node, LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE, true);
// Costs a little more time but layout is quick, therefore, we can do that.
setLayoutOption(node, LayeredOptions.THOROUGHNESS, 100);
setLayoutOption(node, LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE, GreedySwitchType.TWO_SIDED);
if (!getBooleanValue(SHOW_HYPERLINKS)) {
setLayoutOption(node, CoreOptions.PADDING, new ElkPadding(2, 6, 6, 6));
setLayoutOption(node, LayeredOptions.SPACING_NODE_NODE, LayeredOptions.SPACING_NODE_NODE.getDefault() * 0.75f);
Expand Down Expand Up @@ -739,11 +748,11 @@ private Collection<KNode> transformReactorNetwork(
Multimap<ActionInstance, KPort> actionSources = HashMultimap.create();
Map<TimerInstance, KNode> timerNodes = new HashMap<>();
KNode startupNode = _kNodeExtensions.createNode();
boolean startupUsed = false;
TriggerInstance<?> startup = null;
KNode shutdownNode = _kNodeExtensions.createNode();
boolean shutdownUsed = false;
TriggerInstance<?> shutdown = null;
KNode resetNode = _kNodeExtensions.createNode();
boolean resetUsed = false;
TriggerInstance<?> reset = null;

// Transform instances
int index = 0;
Expand All @@ -768,6 +777,7 @@ private Collection<KNode> transformReactorNetwork(
Iterables.addAll(nodes, createUserComments(timer.getDefinition(), node));
timerNodes.put(timer, node);
_linguaFrancaShapeExtensions.addTimerFigure(node, timer);
_layoutPostProcessing.configureTimer(node);
}

// Create reactions
Expand All @@ -781,6 +791,7 @@ private Collection<KNode> transformReactorNetwork(
reactionNodes.put(reaction, node);

setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
_layoutPostProcessing.configureReaction(node);
setLayoutOption(node, LayeredOptions.POSITION, new KVector(0, idx + 1)); // try order reactions vertically if in one layer (+1 to account for startup)

var figure = _linguaFrancaShapeExtensions.addReactionFigure(node, reaction);
Expand Down Expand Up @@ -812,17 +823,17 @@ private Collection<KNode> transformReactorNetwork(
connect(createDependencyEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition),
startupNode,
port);
startupUsed = true;
startup = trigger;
} else if (trigger.isShutdown()) {
connect(createDelayEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition),
shutdownNode,
port);
shutdownUsed = true;
shutdown = trigger;
} else if (trigger.isReset()) {
connect(createDependencyEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition),
resetNode,
port);
resetUsed = true;
reset = trigger;
} else if (trigger instanceof ActionInstance) {
actionDestinations.put(((ActionInstance) trigger), port);
} else if (trigger instanceof PortInstance) {
Expand Down Expand Up @@ -913,6 +924,7 @@ private Collection<KNode> transformReactorNetwork(
nodes.add(node);
Iterables.addAll(nodes, createUserComments(action.getDefinition(), node));
setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
_layoutPostProcessing.configureAction(node);
Pair<KPort, KPort> ports = _linguaFrancaShapeExtensions.addActionFigureAndPorts(
node,
action.isPhysical() ? "P" : "L");
Expand Down Expand Up @@ -1010,14 +1022,16 @@ private Collection<KNode> transformReactorNetwork(
}

// Add startup/shutdown
if (startupUsed) {
if (startup != null) {
_linguaFrancaShapeExtensions.addStartupFigure(startupNode);
_utilityExtensions.setID(startupNode, reactorInstance.uniqueID() + "_startup");
NamedInstanceUtil.linkInstance(startupNode, startup);
startupNode.setProperty(REACTION_SPECIAL_TRIGGER, true);
nodes.add(0, startupNode); // add at the start (ordered first)
// try to order with reactions vertically if in one layer
setLayoutOption(startupNode, LayeredOptions.POSITION, new KVector(0, 0));
setLayoutOption(startupNode, LayeredOptions.LAYERING_LAYER_CONSTRAINT, LayerConstraint.FIRST);
_layoutPostProcessing.configureAction(startupNode);

if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
KPort port = addInvisiblePort(startupNode);
Expand All @@ -1026,12 +1040,14 @@ private Collection<KNode> transformReactorNetwork(
});
}
}
if (shutdownUsed) {
if (shutdown != null) {
_linguaFrancaShapeExtensions.addShutdownFigure(shutdownNode);
_utilityExtensions.setID(shutdownNode, reactorInstance.uniqueID() + "_shutdown");
NamedInstanceUtil.linkInstance(shutdownNode, shutdown);
shutdownNode.setProperty(REACTION_SPECIAL_TRIGGER, true);
nodes.add(shutdownNode); // add at the end (ordered last)
// try to order with reactions vertically if in one layer
_layoutPostProcessing.configureShutDown(shutdownNode);
setLayoutOption(shutdownNode, LayeredOptions.POSITION, new KVector(0, reactorInstance.reactions.size() + 1));

if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) { // connect all edges to one port
Expand All @@ -1041,11 +1057,12 @@ private Collection<KNode> transformReactorNetwork(
});
}
}
if (resetUsed) {
if (reset != null) {
_linguaFrancaShapeExtensions.addResetFigure(resetNode);
_utilityExtensions.setID(resetNode, reactorInstance.uniqueID() + "_reset");
NamedInstanceUtil.linkInstance(resetNode, reset);
resetNode.setProperty(REACTION_SPECIAL_TRIGGER, true);
nodes.add(startupUsed ? 1 : 0, resetNode); // after startup
nodes.add(startup != null ? 1 : 0, resetNode); // after startup
// try to order with reactions vertically if in one layer
setLayoutOption(resetNode, LayeredOptions.POSITION, new KVector(0, 0.5));
setLayoutOption(resetNode, LayeredOptions.LAYERING_LAYER_CONSTRAINT, LayerConstraint.FIRST);
Expand Down Expand Up @@ -1090,7 +1107,8 @@ private Collection<KNode> transformReactorNetwork(
prevNode = node;
}
}


_layoutPostProcessing.orderChildren(nodes);
_modeDiagrams.handleModes(nodes, reactorInstance);

return nodes;
Expand Down
Loading