From: Antti Villberg Date: Sat, 27 May 2017 06:29:23 +0000 (+0300) Subject: Support for dynamic transforms for both elements and terminals X-Git-Tag: v1.29.0~17 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=2b0fe692f116091f8d65da664174c92591a077b8;p=simantics%2Fplatform.git Support for dynamic transforms for both elements and terminals Includes also minor code warning/logging cleanup. refs #7119 Change-Id: I2df8f0f0707e8adf1569679ab41a74f605ae1268 --- diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java index 1905cfe2b..feaefeb69 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java @@ -45,6 +45,13 @@ public class RouteGraph implements Serializable { boolean isSimpleConnection; boolean needsUpdate = false; + public void updateTerminals() { + boolean changed = false; + for(RouteTerminal terminal : terminals) + changed |= terminal.updateDynamicPosition(); + if(changed) update(); + } + /** * Adds a route line to the graph. * @param isHorizontal true, if the line is horizontal @@ -78,21 +85,31 @@ public class RouteGraph implements Serializable { * * @param style Tells what kind of line end is drawn * to the connection. + * @param position a provider for a dynamic position for the terminal or + * null if terminal position is not dynamic * @return The new terminal. */ + public RouteTerminal addTerminal(double x, double y, + double minX, double minY, + double maxX, double maxY, + int allowedDirections, + ILineEndStyle style, RouteTerminalPosition position) { + return addTerminal(x, y, minX, minY, maxX, maxY, allowedDirections, style, null, position); + } + public RouteTerminal addTerminal(double x, double y, double minX, double minY, double maxX, double maxY, int allowedDirections, ILineEndStyle style) { - return addTerminal(x, y, minX, minY, maxX, maxY, allowedDirections, style, null); - + return addTerminal(x, y, minX, minY, maxX, maxY, allowedDirections, style, null, null); } + public RouteTerminal addTerminal(double x, double y, double minX, double minY, double maxX, double maxY, int allowedDirections, - ILineEndStyle style, ILineEndStyle dynamicStyle) { + ILineEndStyle style, ILineEndStyle dynamicStyle, RouteTerminalPosition position) { if(CHECK_PARAMERS) { if(allowedDirections > 0x1f) throw new IllegalArgumentException("Illegal allowedDirection flags."); @@ -102,7 +119,7 @@ public class RouteGraph implements Serializable { if(style == null) style = PlainLineEndStyle.INSTANCE; RouteTerminal terminal = new RouteTerminal(x, y, minX, minY, - maxX, maxY, allowedDirections, false, style); + maxX, maxY, allowedDirections, false, style, position); terminal.setDynamicStyle(dynamicStyle); terminals.add(terminal); return terminal; @@ -124,7 +141,7 @@ public class RouteGraph implements Serializable { 0.5*(minX+maxX), 0.5*(minY+maxY), minX, minY, maxX, maxY, - 0xf, true, style); + 0xf, true, style, null); terminal.setDynamicStyle(dynamicStyle); terminals.add(terminal); @@ -142,7 +159,7 @@ public class RouteGraph implements Serializable { ILineEndStyle style) { return addTerminal(x, y, bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY(), - allowedDirections, style); + allowedDirections, style, null); } /** @@ -152,7 +169,7 @@ public class RouteGraph implements Serializable { RouteTerminal newTerminal = addTerminal(terminal.x, terminal.y, terminal.getMinX(), terminal.getMinY(), terminal.getMaxX(), terminal.getMaxY(), - terminal.getAllowedDirections(), terminal.getStyle(), terminal.getDynamicStyle()); + terminal.getAllowedDirections(), terminal.getStyle(), terminal.getDynamicStyle(), terminal.getDynamicPosition()); newTerminal.setData(terminal.getData()); return terminal; } @@ -166,7 +183,7 @@ public class RouteGraph implements Serializable { double maxX, double maxY, int allowedDirections) { return addTerminal(x, y, minX, minY, maxX, maxY, allowedDirections, - PlainLineEndStyle.INSTANCE); + PlainLineEndStyle.INSTANCE, null); } /** diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java index 2f3fc9f86..c43c7de1c 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java @@ -13,6 +13,7 @@ package org.simantics.diagram.connection; import gnu.trove.map.hash.THashMap; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.PrintStream; import java.io.Serializable; @@ -39,13 +40,14 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable private ILineEndStyle style; private ILineEndStyle dynamicStyle; private boolean routeToBounds; + private RouteTerminalPosition dynamicPosition; RouteLine line; RouteTerminal(double x, double y, double minX, double minY, double maxX, double maxY, int allowedDirections, boolean routeToBounds, - ILineEndStyle style) { + ILineEndStyle style, RouteTerminalPosition dynamicPosition) { super(x, y); this.minX = minX; this.minY = minY; @@ -54,8 +56,9 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable this.allowedDirections = allowedDirections; this.routeToBounds = routeToBounds; this.style = style; + this.dynamicPosition = dynamicPosition; } - + @Override public void setData(Object data) { this.data = data; @@ -378,7 +381,7 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable RouteTerminal copy = (RouteTerminal)map.get(this); if(copy == null) { copy = new RouteTerminal(x, y, minX, minY, maxX, maxY, - allowedDirections, routeToBounds, style); + allowedDirections, routeToBounds, style, dynamicPosition); copy.setDynamicStyle(dynamicStyle); map.put(this, copy); copy.data = data; @@ -449,4 +452,25 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable public void setDynamicStyle(ILineEndStyle dynamicStyle) { this.dynamicStyle = dynamicStyle; } + + public RouteTerminalPosition getDynamicPosition() { + return dynamicPosition; + } + + public boolean updateDynamicPosition() { + boolean changed = false; + if (dynamicPosition != null) { + AffineTransform tr = dynamicPosition.getTransform(); + if (tr != null) { + double nx = tr.getTranslateX(); + changed |= x != nx; + x = nx; + double ny = tr.getTranslateY(); + changed |= y != ny; + y = ny; + } + } + return changed; + } + } diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminalPosition.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminalPosition.java new file mode 100644 index 000000000..13ca043b8 --- /dev/null +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminalPosition.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2017 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.diagram.connection; + +import java.awt.geom.AffineTransform; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public interface RouteTerminalPosition { + + public AffineTransform getTransform(); + +} diff --git a/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph b/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph index 9e006381d..7b7bb6b2e 100644 --- a/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph +++ b/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph @@ -113,7 +113,9 @@ DIA.Functions.activeProfileModifier : L0.Function DIA.Functions.diagramElementIssuePath : L0.Function DIA.DefinedElement - >-- DIA.symbolCode ==> "[String]" "[String]" but DIA.symbolCode now returns either "[String]" or "[G2DNodeModification]" directly + >-- DIA.symbolCode -- DIA.symbolDropHandler ==> "[WorkbenchSelectionElement] -> ()" () { @Override public void exception(AsyncReadGraph graph, Throwable t) { - // Nowhere to log properly. - t.printStackTrace(); + LOGGER.error("Error reading transform from " + resource + " into element " + e, t); } }); } public static void readTransform(AsyncReadGraph graph, final Resource resource, final IElement e, final AsyncProcedure procedure) { - G2DResource G2D = graph.getService(G2DResource.class); - graph.forPossibleRelatedValue(resource, G2D.HasTransform, Bindings.DOUBLE_ARRAY, new AsyncProcedure() { - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - procedure.exception(graph, throwable); - } - - @Override - public void execute(AsyncReadGraph graph, double[] mat) { - mat = DiagramGraphUtil.validateAffineTransform(resource, mat); - AffineTransform tr = mat != null ? new AffineTransform(mat) : new AffineTransform(); - ElementUtils.setTransform(e, tr); - procedure.execute(graph, e); - } - }); + DiagramResource DIA = graph.getService(DiagramResource.class); + try { + AffineTransform tr = DiagramGraphUtil.getDynamicAffineTransform((ReadGraph)graph, null, resource, DIA.HasDynamicTransform, true); + ElementUtils.setTransform(e, tr); + } catch (DatabaseException e1) { + ElementUtils.setTransform(e, new AffineTransform()); + } + procedure.execute(graph, e); } public static ISynchronizationContext getContext(IDiagram diagram) { diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/NodeRequest.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/NodeRequest.java index fba5de506..a6f2e0a77 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/NodeRequest.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/NodeRequest.java @@ -22,12 +22,16 @@ import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.diagram.IDiagram; import org.simantics.g2d.element.ElementClass; import org.simantics.g2d.element.IElement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Antti Villberg */ public class NodeRequest extends BaseRequest2 { + private static final Logger LOGGER = LoggerFactory.getLogger(NodeRequest.class); + final IDiagram diagram; final Listener loadListener; @@ -101,7 +105,7 @@ public class NodeRequest extends BaseRequest2 { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { - throwable.printStackTrace(); + LOGGER.error("Unexpected error in GetElementClassRequest", throwable); procedure.execute(graph, null); } @@ -112,7 +116,7 @@ public class NodeRequest extends BaseRequest2 { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { - throwable.printStackTrace(); + LOGGER.error("Unexpected error in SpawnRequest", throwable); procedure.execute(graph, null); } @@ -128,8 +132,7 @@ public class NodeRequest extends BaseRequest2 { factory.load(graph, canvas, diagram, data, element, new AsyncProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { - // TODO: proper logging - throwable.printStackTrace(); + LOGGER.error("Unexpected error in ElementFactory.load (factory=" + factory + ")", throwable); } @Override public void execute(AsyncReadGraph graph, IElement result) { diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphConnectionClassFactory.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphConnectionClassFactory.java index c00820ba3..fd1603d39 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphConnectionClassFactory.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphConnectionClassFactory.java @@ -97,7 +97,7 @@ public class RouteGraphConnectionClassFactory extends SyncElementFactory { Resource diagramRuntime = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE); Set backendConnections = new THashSet<>(); - RouteGraph rg = RouteGraphUtils.load(graph, diagramRuntime, connection, canvas, diagram, modelingRules, backendConnections); + RouteGraph rg = RouteGraphUtils.load(graph, diagramRuntime, connection, canvas, diagram, element, modelingRules, backendConnections); // Load connection line style. ConnectionStyle style = RouteGraphUtils.readConnectionStyle(graph, modelingRules, connection, STR); diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java index 60f7a09db..3127b431c 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java @@ -39,6 +39,7 @@ import org.simantics.diagram.connection.RouteGraphConnectionClass; import org.simantics.diagram.connection.RouteLine; import org.simantics.diagram.connection.RouteNode; import org.simantics.diagram.connection.RouteTerminal; +import org.simantics.diagram.connection.RouteTerminalPosition; import org.simantics.diagram.connection.rendering.BasicConnectionStyle; import org.simantics.diagram.connection.rendering.ConnectionStyle; import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer; @@ -46,6 +47,7 @@ import org.simantics.diagram.connection.rendering.arrows.ArrowLineEndStyle; import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle; import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle; import org.simantics.diagram.content.EdgeResource; +import org.simantics.diagram.content.ResourceTerminal; import org.simantics.diagram.content.TerminalMap; import org.simantics.diagram.query.DiagramRequests; import org.simantics.diagram.stubs.DiagramResource; @@ -55,11 +57,14 @@ import org.simantics.diagram.synchronization.graph.RouteGraphConnection; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.CanvasContext; import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.DataElementMap; import org.simantics.g2d.diagram.handler.Topology.Connection; +import org.simantics.g2d.diagram.handler.Topology.Terminal; import org.simantics.g2d.diagram.impl.ElementDiagram; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; +import org.simantics.g2d.element.handler.TerminalLayout; import org.simantics.g2d.elementclass.FlagClass.Type; import org.simantics.layer0.Layer0; import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphChangeEvent; @@ -93,10 +98,10 @@ public class RouteGraphUtils { Layer0 L0 = Layer0.getInstance(graph); Resource diagramResource = graph.getPossibleObject(connection, L0.PartOf); IModelingRules modelingRules = graph.syncRequest(DiagramRequests.getModelingRules(diagramResource, null), TransientCacheListener.instance()); - return load(graph, diagramRuntime, connection, canvas, diagram, modelingRules, null); + return load(graph, diagramRuntime, connection, canvas, diagram, null, modelingRules, null); } - public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection, ICanvasContext canvas, IDiagram diagram, IModelingRules modelingRules, Set backendConnections) throws DatabaseException { + public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection, ICanvasContext canvas, IDiagram diagram, IElement element, IModelingRules modelingRules, Set backendConnections) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); StructuralResource2 STR = StructuralResource2.getInstance(graph); @@ -171,7 +176,7 @@ public class RouteGraphUtils { connectorToModeledAttachment = new THashMap(toConnectorStatements.size()); connectorToModeledAttachment.put(connector, attachment); if (DEBUG) - System.out.println("modeling rules decided attachment: " + NameUtils.getSafeName(graph, attachment, true) + " for (" + NameUtils.toString(graph, toConnector, true) + ") & (" + NameUtils.toString(graph, terminalStm, true) + ")"); + LOGGER.debug("modeling rules decided attachment: " + NameUtils.getSafeName(graph, attachment, true) + " for (" + NameUtils.toString(graph, toConnector, true) + ") & (" + NameUtils.toString(graph, terminalStm, true) + ")"); } else if (graph.isInstanceOf(terminalElement, DIA.Flag)) { // Secondary: believe flag type attachment = resolveFlagAttachment(graph, connection, terminalElement, modelingRules, DIA); @@ -180,7 +185,7 @@ public class RouteGraphUtils { connectorToModeledAttachment = new THashMap(toConnectorStatements.size()); connectorToModeledAttachment.put(connector, attachment); if (DEBUG) - System.out.println("flag type decided attachment: " + NameUtils.getSafeName(graph, attachment, true) + " for (" + NameUtils.toString(graph, toConnector, true) + ") & (" + NameUtils.toString(graph, terminalStm, true) + ")"); + LOGGER.debug("flag type decided attachment: " + NameUtils.getSafeName(graph, attachment, true) + " for (" + NameUtils.toString(graph, toConnector, true) + ") & (" + NameUtils.toString(graph, terminalStm, true) + ")"); } } } @@ -193,17 +198,18 @@ public class RouteGraphUtils { if (terminalCount == 2 && connectorToModeledAttachment.size() == 1) { forcedAttachmentRelation = getInverseAttachment(graph, connectorToModeledAttachment.values().iterator().next(), DIA); if (DEBUG) - System.out.println("set forced attachment: " + NameUtils.getSafeLabel(graph, forcedAttachmentRelation)); + LOGGER.debug("set forced attachment: " + NameUtils.getSafeLabel(graph, forcedAttachmentRelation)); } Resource connectionType = graph.getPossibleObject(connection, STR.HasConnectionType); + DataElementMap diagramDataElementMap = diagram.getDiagramClass().getSingleItem(DataElementMap.class); // Load all node terminal connections as RouteTerminals for (Statement toConnector : toConnectorStatements) { Resource connector = toConnector.getObject(); Resource attachmentRelation = toConnector.getPredicate(); if (DEBUG) - System.out.println("original attachment relation: " + NameUtils.getSafeLabel(graph, attachmentRelation)); + LOGGER.debug("original attachment relation: " + NameUtils.getSafeLabel(graph, attachmentRelation)); Statement terminalStm = findTerminalStatement(graph, connection, connector, STR); if (terminalStm == null) @@ -237,19 +243,18 @@ public class RouteGraphUtils { if (position.length != 2) position = new double[] { 0, 0 }; + AffineTransform terminalTr = DiagramGraphUtil.getDynamicWorldTransform(graph, diagramRuntime, terminalElement); + final AffineTransform terminalElementTransform = new AffineTransform(terminalTr); + if (DEBUG) { - System.out.println("terminalStm: " + NameUtils.toString(graph, terminalStm)); - System.out.println("terminal: " + graph.getURI(terminalStm.getPredicate())); + LOGGER.debug("terminalStm: " + NameUtils.toString(graph, terminalStm)); + LOGGER.debug("terminal: " + NameUtils.getURIOrSafeNameInternal(graph, terminalStm.getPredicate())); + LOGGER.debug("terminalElement: " + NameUtils.getURIOrSafeNameInternal(graph, terminalElement) + " : " + NameUtils.getURIOrSafeNameInternal(graph, terminalElementType)); + LOGGER.debug("terminalElementTr: " + terminalTr); } - AffineTransform terminalElementTr = diagramRuntime != null ? - DiagramGraphUtil.getDynamicWorldTransform(graph, diagramRuntime, terminalElement) : - DiagramGraphUtil.getWorldTransform(graph, terminalElement); - - if (DEBUG) - System.out.println("terminalElementTr: " + terminalElementTr); - double x = terminalElementTr.getTranslateX(); - double y = terminalElementTr.getTranslateY(); + double x = terminalTr.getTranslateX(); + double y = terminalTr.getTranslateY(); double minx = x-1, miny = y-1, maxx = x+1, maxy = y+1; int direction = 0x0; @@ -259,20 +264,20 @@ public class RouteGraphUtils { if (att != null) { attachmentRelation = att; if (DEBUG) - System.out.println("modeling rules attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); + LOGGER.debug("modeling rules attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); } else if (forcedAttachmentRelation != null) { attachmentRelation = forcedAttachmentRelation; if (DEBUG) - System.out.println("forced rules attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); + LOGGER.debug("forced rules attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); } if (DEBUG) - System.out.println("decided attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); + LOGGER.debug("decided attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation)); // Get element bounds to decide allowed terminal direction(s) IElement te = graph.syncRequest(DiagramRequests.getElement(canvas, diagram, terminalElement, null)); ElementUtils.getElementBounds(te, bounds); { - Shape shp = org.simantics.g2d.utils.GeometryUtils.transformShape(bounds, terminalElementTr); + Shape shp = org.simantics.g2d.utils.GeometryUtils.transformShape(bounds, terminalTr); bounds.setFrame(shp.getBounds2D()); } @@ -285,28 +290,26 @@ public class RouteGraphUtils { maxx = bounds.getMaxX(); maxy = bounds.getMaxY(); - AffineTransform terminalPos = DiagramGraphUtil.getDynamicAffineTransform(graph, terminalElement, terminal); - //AffineTransform terminalPos2 = DiagramGraphUtil.getAffineTransform(graph, terminal); + final ResourceTerminal rt = new ResourceTerminal(terminal); + final TerminalLayout tl = te.getElementClass().getSingleItem(TerminalLayout.class); + AffineTransform terminalPos = tl.getTerminalPosition(element, rt); + if (terminalPos != null) { - if (DEBUG) { - System.out.println("terminalPos: " + terminalPos); - //System.out.println("terminalPos2: " + terminalPos2); - } - terminalElementTr.concatenate(terminalPos); + terminalTr.concatenate(terminalPos); + x = terminalTr.getTranslateX(); + y = terminalTr.getTranslateY(); if (DEBUG) - System.out.println("terminalElementTr: " + terminalElementTr); - x = terminalElementTr.getTranslateX(); - y = terminalElementTr.getTranslateY(); + LOGGER.debug("terminalPos/Tr: " + terminalPos + ", " + terminalTr); } Integer allowedDirections = graph.getPossibleRelatedValue(terminal, DIA.Terminal_AllowedDirections, Bindings.INTEGER); if (allowedDirections != null) { direction |= allowedDirections; - direction = rotateDirection(direction, terminalElementTr); + direction = rotateDirection(direction, terminalTr); } else { direction |= RouteGraphConnectionClass.shortestDirectionOutOfBounds(x, y, bounds); } - //System.out.println("DIR(" + x + ", " + y + ", " + bounds + "): " + Integer.toHexString(direction)); + //LOGGER.debug("DIR(" + x + ", " + y + ", " + bounds + "): " + Integer.toHexString(direction)); if (backendConnections != null) { backendConnections.add( @@ -326,10 +329,11 @@ public class RouteGraphUtils { // FIXME: routegraph crashes if this is done for all terminals regardless of the amount of terminals. if (DEBUG) - System.out.println("load line style: " + NameUtils.getSafeLabel(graph, attachmentRelation)); + LOGGER.debug("load line style: " + NameUtils.getSafeLabel(graph, attachmentRelation)); ILineEndStyle endStyle = loadLineEndStyle(graph, attachmentRelation, connectionType, TAIL); - RouteTerminal routeTerminal = rg.addTerminal(x, y, minx, miny, maxx, maxy, direction, endStyle); + RouteTerminal routeTerminal = rg.addTerminal(x, y, minx, miny, maxx, maxy, direction, endStyle, + new RouteTerminalPositionImpl(diagram, diagramDataElementMap, terminalElement, terminalElementTransform, tl, rt)); routeTerminal.setData( RouteGraphConnection.serialize(graph, connector) ); nodeByData.put( connector, routeTerminal ); @@ -705,4 +709,50 @@ public class RouteGraphUtils { } } + private static class RouteTerminalPositionImpl implements RouteTerminalPosition { + + private IDiagram diagram; + private DataElementMap dataElementMap; + private Resource element; + private AffineTransform elementTransform; + private TerminalLayout terminalLayout; + private Terminal elementTerminal; + + private transient AffineTransform lastTerminalTr; + private transient AffineTransform transform; + + public RouteTerminalPositionImpl(IDiagram diagram, DataElementMap dem, Resource element, AffineTransform elementTransform, TerminalLayout terminalLayout, Terminal terminal) { + this.diagram = diagram; + this.dataElementMap = dem; + this.element = element; + this.elementTransform = elementTransform; + this.terminalLayout = terminalLayout; + this.elementTerminal = terminal; + } + + @Override + public AffineTransform getTransform() { + IElement actualElement = dataElementMap.getElement(diagram, element); + AffineTransform terminalTr = actualElement != null ? terminalLayout.getTerminalPosition(actualElement, elementTerminal) : null; + if (terminalTr == null) + return elementTransform; + + // Return cached transform if terminal transform has not changed. + AffineTransform result = this.transform; + AffineTransform lastTerminalTr = this.lastTerminalTr; + if (lastTerminalTr != null) { + if (terminalTr.equals(lastTerminalTr)) + return result; + lastTerminalTr.setTransform(terminalTr); + } else { + lastTerminalTr = this.lastTerminalTr = new AffineTransform(terminalTr); + result = this.transform = new AffineTransform(); + } + + result.setTransform(elementTransform); + result.concatenate(terminalTr); + return result; + } + + } } diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/SVGElementClassFactory.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/SVGElementClassFactory.java index 65df67acb..94d783f2d 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/SVGElementClassFactory.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/SVGElementClassFactory.java @@ -21,7 +21,6 @@ import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.procedure.guarded.GuardedAsyncProcedureWrapper; -import org.simantics.db.common.request.BinaryAsyncRead; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.UnaryAsyncRead; import org.simantics.db.common.utils.NameUtils; diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java index 2c6c9961a..4cccea938 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java @@ -94,7 +94,6 @@ import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode; import org.simantics.scenegraph.g2d.snap.ISnapAdvisor; import org.simantics.scenegraph.utils.GeometryUtils; import org.simantics.structural2.modelingRules.ConnectionJudgement; -import org.simantics.utils.datastructures.Callback; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.Triple; import org.simantics.utils.logging.TimeLogger; @@ -765,12 +764,9 @@ public class RouteGraphConnectTool extends AbstractMode { Resource attachToLine = RouteGraphConnection.deserialize(graph, attachedToRouteLine.getData()); builder.attachToRouteGraph(graph, judgment, connection, attachToLine, controlPoints, endTerminal, FlagClass.Type.Out); } - }, new Callback() { - @Override - public void run(DatabaseException parameter) { - if (parameter != null) - ExceptionUtils.logAndShowError(parameter); - } + }, e -> { + if (e != null) + ExceptionUtils.logAndShowError(e); }); } diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/pointertool/TerminalUtil.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/pointertool/TerminalUtil.java index 85f75a066..677c97f0f 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/pointertool/TerminalUtil.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/pointertool/TerminalUtil.java @@ -44,7 +44,7 @@ public class TerminalUtil { private static final ThreadLocal> TERMINALS = new ThreadLocal>() { @Override protected ArrayList initialValue() { - return new ArrayList(); + return new ArrayList<>(); } }; @@ -54,7 +54,7 @@ public class TerminalUtil { private static final ThreadLocal> ELEMENTS = new ThreadLocal>() { @Override protected ArrayList initialValue() { - return new ArrayList(); + return new ArrayList<>(); } }; @@ -144,7 +144,7 @@ public class TerminalUtil { pickCenterY = bounds.getCenterY(); } - List result = new ArrayList(); + List result = new ArrayList<>(); ArrayList terminals = TERMINALS.get(); for (IElement e : elements) { @@ -160,8 +160,10 @@ public class TerminalUtil { { Shape terminalShape = getTerminalShape(tls, e, t); if ( terminalShape==null /* point terminal */ && !pickPointTerminals ) continue; - if ( terminalShape!=null /* are terminal */ && !pickAreaTerminals ) continue; - AffineTransform terminalToDiagram = getTerminalPosOnDiagram(e, t); + if ( terminalShape!=null /* area terminal */ && !pickAreaTerminals ) continue; + + AffineTransform terminalToElement = getTerminalPosOnElement0(e, t); + AffineTransform terminalToDiagram = concatenate(ElementUtils.getTransform(e), terminalToElement); // Pick distance will is set to 0 if there was no pick shape, // i.e. everything is picked. @@ -175,11 +177,10 @@ public class TerminalUtil { pickDist = Point2D.distance(pickCenterX, pickCenterY, terminalToDiagram.getTranslateX(), terminalToDiagram.getTranslateY()); } - AffineTransform terminalToElement = getTerminalPosOnElement(e, t); TerminalInfo ti = new TerminalInfo(); ti.e = e; ti.posDia = terminalToDiagram; - ti.posElem = terminalToElement; + ti.posElem = terminalToElement != null ? new AffineTransform(terminalToElement) : new AffineTransform(); ti.t = t; ti.shape = terminalShape; ti.distance = pickDist; @@ -224,8 +225,10 @@ public class TerminalUtil { tt.getTerminals(e, terminals); for (Terminal t : terminals) { + AffineTransform terminalToElement = getTerminalPosOnElement0(e, t); + AffineTransform terminalToDiagram = concatenate(ElementUtils.getTransform(e), terminalToElement); + Shape terminalShape = getTerminalShape(e, t); - AffineTransform terminalToDiagram = getTerminalPosOnDiagram(e, t); Shape pickTargetShape = terminalShape != null ? terminalShape : POINT_PICK_SHAPE; pickTargetShape = GeometryUtils.transformShape(pickTargetShape, terminalToDiagram); if (!GeometryUtils.intersects(pickShape, pickTargetShape)) continue; @@ -235,7 +238,7 @@ public class TerminalUtil { result.e = e; result.posDia = terminalToDiagram; - result.posElem = getTerminalPosOnElement(e, t); + result.posElem = terminalToElement != null ? new AffineTransform(terminalToElement) : new AffineTransform(); result.t = t; result.shape = terminalShape; result.distance = Math.sqrt(pickDist); @@ -300,11 +303,8 @@ public class TerminalUtil { */ public static AffineTransform getTerminalPosOnDiagram(IElement e, Terminal t) { - AffineTransform pos = getTerminalPosOnElement(e, t); - AffineTransform at = ElementUtils.getTransform(e); - AffineTransform result = new AffineTransform(at); - result.concatenate(pos); - return result; + AffineTransform pos = getTerminalPosOnElement0(e, t); + return concatenate(ElementUtils.getTransform(e), pos); } /** @@ -314,6 +314,18 @@ public class TerminalUtil { * @return Transform of a terminal */ public static AffineTransform getTerminalPosOnElement(IElement e, Terminal t) + { + AffineTransform tr = getTerminalPosOnElement0(e, t); + return tr != null ? new AffineTransform(tr) : null; + } + + /** + * Get position of a terminal in element + * @param e element + * @param t terminal + * @return Transform of a terminal + */ + private static AffineTransform getTerminalPosOnElement0(IElement e, Terminal t) { List tls = e.getElementClass().getItemsByClass(TerminalLayout.class); AffineTransform result = null; @@ -363,7 +375,7 @@ public class TerminalUtil { PickRequest req = new PickRequest(pickShape); DiagramUtils.pick(diagram, req, elements); - ArrayList bends = new ArrayList(); + ArrayList bends = new ArrayList<>(); Point2D bendPos = new Point2D.Double(); for (IElement e : diagram.getElements()) { @@ -430,7 +442,7 @@ public class TerminalUtil { } } - ArrayList result = new ArrayList(len); + ArrayList result = new ArrayList<>(len); for (int i = 0; i < len; ++i) { TerminalInfo ti = tis.get(i); if (ti.distance == nearest.distance @@ -444,4 +456,11 @@ public class TerminalUtil { return result; } + private static AffineTransform concatenate(AffineTransform a, AffineTransform b) { + AffineTransform result = new AffineTransform(a); + if (b != null) + result.concatenate(b); + return result; + } + } diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/TerminalLayout.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/TerminalLayout.java index 038e68dc2..8d6f9ab58 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/TerminalLayout.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/TerminalLayout.java @@ -28,10 +28,14 @@ import org.simantics.g2d.utils.geom.DirectionSet; public interface TerminalLayout extends ElementHandler { /** - * Get a copy of terminal transformation (on element) + * Get specified terminal transformation on specified element + * * @param node * @param t - * @return position of a terminal or null + * @return position of a terminal or null if specified terminal does not + * belong to the specified element. The returned AffineTransform + * must be treated as if it were immutable since the implementation + * is allowed to returned singleton/cached values. */ AffineTransform getTerminalPosition(IElement node, Terminal t); diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java index f38e0a6c5..786e07e0a 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java @@ -48,7 +48,7 @@ public class Terminals implements TerminalLayout, TerminalTopology { ObjectTerminal ti = terminalMap.get(t); if (ti == null) return null; - return new AffineTransform(ti.getTransform()); + return ti.getTransform(); } @Override diff --git a/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl b/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl index 5e0e83075..927384697 100644 --- a/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl +++ b/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl @@ -95,3 +95,26 @@ getNodeCount diagram = do provider = getICanvasSceneGraphProvider model composite diagramRVI context = getCanvasContext provider getCount context + +importJava "org.simantics.scenegraph.g2d.G2DNodeModification" where + data G2DNodeModification + @JavaName "" + createG2DNodeModification :: [SVGNodeAssignment] -> [TransformationAssignment] -> G2DNodeModification + +importJava "org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment" where + data SVGNodeAssignment + +importJava "org.simantics.scenegraph.g2d.nodes.TransformationAssignment" where + data TransformationAssignment + @JavaName "" + createTransformationAssignment :: a -> AffineTransform -> TransformationAssignment + +importJava "java.awt.geom.AffineTransform" where + data AffineTransform + @JavaName "" + createAffineTransform :: Double -> Double -> Double -> Double -> Double -> Double -> AffineTransform + +importJava "org.simantics.scenegraph.g2d.AffineTransformFunctions" where + transform :: AffineTransform -> (Double,Double) -> (Double,Double) + inverseTransform :: AffineTransform -> (Double,Double) -> (Double,Double) + \ No newline at end of file diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/SymbolCodeStyle.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/SymbolCodeStyle.java index fb584331e..edc7aa9e1 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/SymbolCodeStyle.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/SymbolCodeStyle.java @@ -11,8 +11,12 @@ *******************************************************************************/ package org.simantics.modeling.adapters; +import java.awt.geom.AffineTransform; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; @@ -22,8 +26,12 @@ import org.simantics.db.layer0.variable.Variables; import org.simantics.diagram.profile.StyleBase; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.G2DNodeModification; +import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.nodes.SVGNode; -import org.simantics.scenegraph.g2d.nodes.SVGNode.SVGNodeAssignment; +import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment; +import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.g2d.nodes.TransformationAssignment; import org.simantics.scenegraph.profile.EvaluationContext; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.utils.datastructures.Pair; @@ -32,39 +40,63 @@ import org.simantics.utils.datastructures.Pair; * @author Antti Villberg * @since 1.29.0 */ -public class SymbolCodeStyle extends StyleBase, Object>> { +public class SymbolCodeStyle extends StyleBase> { @Override - public Pair, Object> calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException { + public Pair calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); // Find a component for the element Variable elementVariable = Variables.getPossibleVariable(graph, element); if (elementVariable == null) return null; - List styles = elementVariable.getPossiblePropertyValue(graph, DIA.symbolCode); - if (styles == null) + Object modi = elementVariable.getPossiblePropertyValue(graph, DIA.symbolCode); + if (modi == null) return null; // If element is moved, recalculate style Object transform = graph.getPossibleRelatedValue(element, DIA.HasTransform); - return Pair.make(styles, transform); + if (modi instanceof G2DNodeModification) { + return Pair.make((G2DNodeModification)modi, transform); + } else if (modi instanceof List) { + @SuppressWarnings("unchecked") + List styles = (List)modi; + List assignments = new ArrayList<>(styles.size()/3); + for (int i = 0; i < styles.size()/3; i++) + assignments.add(new SVGNodeAssignment(styles.get(3*i), styles.get(3*i+1), styles.get(3*i+2))); + return Pair.make(new G2DNodeModification(assignments, Collections.emptyList()), transform); + } else { + throw new DatabaseException("Invalid symbolCode value: " + modi); + } } @Override - public void applyStyleForNode(EvaluationContext evaluationContext, INode node, Pair, Object> result) { - if (result == null || result.first == null || result.first.isEmpty()) + public void applyStyleForNode(EvaluationContext evaluationContext, INode node, Pair result) { + if (result == null || result.first == null) return; - List styles = result.first; - List assignments = new ArrayList<>(styles.size()/3); - for (int i = 0; i < styles.size()/3; i++) - assignments.add(new SVGNodeAssignment(styles.get(3*i), styles.get(3*i+1), styles.get(3*i+2))); - - for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) { - p.setAssignments(assignments); - p.cleanDiagramCache(); + G2DNodeModification modification = result.first; + if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) { + for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) { + p.setAssignments(modification.svgAssignments); + p.cleanDiagramCache(); + } + } + if (modification.transformAssignments != null) { + Map trs = new HashMap<>(); + for (TransformationAssignment ass : modification.transformAssignments) + trs.put(ass.key, ass.transform); + NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> { + Object key = n.getKey(); + AffineTransform tr = trs.get(key); + if (tr != null) { + IG2DNode[] children = n.getSortedNodes(); + if (children.length > 0) + children[0].setTransform(tr); + } + return null; + }); } } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/AffineTransformFunctions.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/AffineTransformFunctions.java new file mode 100644 index 000000000..40e58e949 --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/AffineTransformFunctions.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2017 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d; + +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; + +import org.simantics.scl.runtime.tuple.Tuple2; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public class AffineTransformFunctions { + + public static Tuple2 transform(AffineTransform transform, Tuple2 point) { + Point2D result = new Point2D.Double((Double) point.c0, (Double) point.c1); + transform.transform(result, result); + return new Tuple2(result.getX(), result.getY()); + } + + public static Tuple2 inverseTransform(AffineTransform transform, Tuple2 point) throws NoninvertibleTransformException { + Point2D result = new Point2D.Double((Double)point.c0, (Double)point.c1); + transform.inverseTransform(result, result); + return new Tuple2(result.getX(), result.getY()); + } + +} diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNodeModification.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNodeModification.java new file mode 100644 index 000000000..4b68e1798 --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNodeModification.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d; + +import java.util.List; + +import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment; +import org.simantics.scenegraph.g2d.nodes.TransformationAssignment; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public class G2DNodeModification { + public List svgAssignments; + public List transformAssignments; + public G2DNodeModification(List svgAssignments, List transformAssignments) { + this.svgAssignments = svgAssignments; + this.transformAssignments = transformAssignments; + } +} diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java index 2dd285fd8..2fc37b7d5 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java @@ -56,53 +56,7 @@ import com.kitfox.svg.animation.AnimationElement; @RasterOutputWidget public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { - public static class SVGNodeAssignment { - public String elementId; - public String attributeNameOrId; - public String value; - public SVGNodeAssignment(String elementId, String attributeNameOrId, String value) { - this.elementId = elementId; - this.attributeNameOrId = attributeNameOrId; - this.value = value; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((attributeNameOrId == null) ? 0 : attributeNameOrId.hashCode()); - result = prime * result + ((elementId == null) ? 0 : elementId.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SVGNodeAssignment other = (SVGNodeAssignment) obj; - if (attributeNameOrId == null) { - if (other.attributeNameOrId != null) - return false; - } else if (!attributeNameOrId.equals(other.attributeNameOrId)) - return false; - if (elementId == null) { - if (other.elementId != null) - return false; - } else if (!elementId.equals(other.elementId)) - return false; - if (value == null) { - if (other.value != null) - return false; - } else if (!value.equals(other.value)) - return false; - return true; - } - } - - private static final long serialVersionUID = 8508750881358776559L; + private static final long serialVersionUID = 8508750881358776559L; protected String data = null; protected String defaultData = null; diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNodeAssignment.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNodeAssignment.java new file mode 100644 index 000000000..ac292bc4a --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNodeAssignment.java @@ -0,0 +1,51 @@ +package org.simantics.scenegraph.g2d.nodes; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public class SVGNodeAssignment { + public String elementId; + public String attributeNameOrId; + public String value; + public SVGNodeAssignment(String elementId, String attributeNameOrId, String value) { + this.elementId = elementId; + this.attributeNameOrId = attributeNameOrId; + this.value = value; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((attributeNameOrId == null) ? 0 : attributeNameOrId.hashCode()); + result = prime * result + ((elementId == null) ? 0 : elementId.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SVGNodeAssignment other = (SVGNodeAssignment) obj; + if (attributeNameOrId == null) { + if (other.attributeNameOrId != null) + return false; + } else if (!attributeNameOrId.equals(other.attributeNameOrId)) + return false; + if (elementId == null) { + if (other.elementId != null) + return false; + } else if (!elementId.equals(other.elementId)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } +} \ No newline at end of file diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformationAssignment.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformationAssignment.java new file mode 100644 index 000000000..ce39db5b8 --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformationAssignment.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2017 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d.nodes; + +import java.awt.geom.AffineTransform; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public class TransformationAssignment { + public Object key; + public AffineTransform transform; + public TransformationAssignment(Object key, AffineTransform transform) { + this.key = key; + this.transform = transform; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((transform == null) ? 0 : transform.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TransformationAssignment other = (TransformationAssignment) obj; + if (key == null) { + if (other.key != null) + return false; + } else if (!key.equals(other.key)) + return false; + if (transform == null) { + if (other.transform != null) + return false; + } else if (!transform.equals(other.transform)) + return false; + return true; + } +} \ No newline at end of file diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java index 084c0d658..69268bad0 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java @@ -349,6 +349,8 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In boolean selected = NodeUtil.isSelected(this, 1); + rg.updateTerminals(); + if (currentAction != null) { currentAction.render(g, renderer, mouseX, mouseY); } else {