1 /*******************************************************************************
2 * Copyright (c) 2020 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Semantum Oy - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.participant;
14 import org.simantics.Simantics;
15 import org.simantics.db.ReadGraph;
16 import org.simantics.db.Resource;
17 import org.simantics.db.common.request.UnaryRead;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.procedure.Listener;
20 import org.simantics.diagram.connection.rendering.ConnectionCrossings;
21 import org.simantics.diagram.stubs.DiagramResource;
22 import org.simantics.g2d.canvas.ICanvasContext;
23 import org.simantics.g2d.canvas.SGDesignation;
24 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
25 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
26 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
27 import org.simantics.scenegraph.g2d.G2DParentNode;
28 import org.simantics.scenegraph.g2d.nodes.ConnectionCrossingsNode;
29 import org.simantics.utils.datastructures.Pair;
30 import org.simantics.utils.ui.ErrorLogger;
32 public class ConnectionCrossingsParticipant extends AbstractDiagramParticipant {
33 private static final String CONNECTION_CROSSINGS_NODE_KEY = "connection-crossings";
35 private ConnectionCrossingsNode ccNode;
36 private final ConnectionCrossings crossings = new ConnectionCrossings();
37 private ConnectionCrossingStyleListener listener;
38 private Resource diagram;
40 public ConnectionCrossingsParticipant(Resource diagram) {
41 this.diagram = diagram;
43 public ConnectionCrossingsParticipant(double width, ConnectionCrossings.Type type) {
44 crossings.setWidth(width);
45 crossings.setType(type);
48 public ConnectionCrossingsParticipant(double width, ConnectionCrossings.Type type, boolean keepLines) {
49 crossings.setWidth(width);
50 crossings.setType(type);
51 crossings.setKeepLines(keepLines);
54 @SGInit(designation = SGDesignation.CONTROL)
55 public void initSG(G2DParentNode parent) {
56 ccNode = parent.addNode(CONNECTION_CROSSINGS_NODE_KEY, ConnectionCrossingsNode.class);
57 ccNode.setCrossings(crossings);
58 ccNode.setZIndex(Integer.MIN_VALUE / 4);
62 public void cleanupSG() {
70 public void addedToContext(ICanvasContext ctx) {
71 super.addedToContext(ctx);
73 if (diagram != null) {
74 listener = new ConnectionCrossingStyleListener(ctx);
75 Simantics.getSession().async(new UnaryRead<Resource, Pair<Double, ConnectionCrossings.Type>>(diagram){
78 public Pair<Double, ConnectionCrossings.Type> perform(ReadGraph graph) throws DatabaseException {
79 DiagramResource DIA = DiagramResource.getInstance(graph);
80 Double gap = graph.getPossibleRelatedValue(diagram, DIA.ConnectionCrossingStyle_Width);
81 Resource typeRes = graph.getPossibleObject(diagram, DIA.ConnectionCrossingStyle_HasType);
82 ConnectionCrossings.Type type;
83 if (DIA.ConnectionCrossingStyle_Type_Gap.equals(typeRes)) {
84 type = ConnectionCrossings.Type.GAP;
85 } else if (DIA.ConnectionCrossingStyle_Type_Arc.equals(typeRes)) {
86 type = ConnectionCrossings.Type.ARC;
87 } else if (DIA.ConnectionCrossingStyle_Type_Square.equals(typeRes)) {
88 type = ConnectionCrossings.Type.SQUARE;
90 type = ConnectionCrossings.Type.NONE;
92 return new Pair<>(gap, type);
100 public void removedFromContext(ICanvasContext ctx) {
101 if (listener != null) {
105 super.removedFromContext(ctx);
108 class ConnectionCrossingStyleListener implements Listener<Pair<Double, ConnectionCrossings.Type>> {
109 ICanvasContext context;
110 public ConnectionCrossingStyleListener(ICanvasContext context) {
111 this.context = context;
114 public void execute(final Pair<Double, ConnectionCrossings.Type> result) {
115 context.getThreadAccess().asyncExec(new Runnable() {
118 ICanvasContext ctx = context;
121 if (ctx.isDisposed())
123 crossings.setWidth(result.first != null ? result.first : 0.0);
124 crossings.setType(result.second);
129 public void dispose() {
133 public boolean isDisposed() {
134 return context == null || context.isDisposed();
137 public void exception(Throwable t) {
138 ErrorLogger.defaultLogError(t);
142 public ConnectionCrossings getCrossings() {