X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fprofile%2FShowRelatedElements.java;h=a18191a671e9497151ad3c105e6f10da37821912;hb=48135dcd03588783f9c1b688aaa53cdaacba6ef2;hp=a4e003c5f579d5d2532e10b9de5d758df8fb4a84;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/ShowRelatedElements.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/ShowRelatedElements.java index a4e003c5f..a18191a67 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/ShowRelatedElements.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/ShowRelatedElements.java @@ -1,286 +1,286 @@ -/******************************************************************************* - * Copyright (c) 2011 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.diagram.profile; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Statement; -import org.simantics.db.common.utils.OrderedSetUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.diagram.content.ConnectionUtil; -import org.simantics.diagram.flag.FlagUtil; -import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; -import org.simantics.g2d.connection.handler.ConnectionHandler; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.diagram.handler.DataElementMap; -import org.simantics.g2d.diagram.handler.PickRequest.PickFilter; -import org.simantics.g2d.diagram.handler.Relationship; -import org.simantics.g2d.diagram.handler.Topology.Connection; -import org.simantics.g2d.element.ElementUtils; -import org.simantics.g2d.element.IElement; -import org.simantics.g2d.element.handler.BendsHandler; -import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; -import org.simantics.g2d.utils.GeometryUtils; -import org.simantics.modeling.ModelingResources; -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.nodes.RelationshipNode2; -import org.simantics.scenegraph.profile.DataNodeMap; -import org.simantics.scenegraph.profile.EvaluationContext; -import org.simantics.scenegraph.profile.common.ProfileVariables; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.datastructures.map.Tuple; - -/** - * @author Tuukka Lehtonen - */ -public class ShowRelatedElements extends StyleBase { - - protected Collection terminalConnections = new ArrayList(4); - - protected final BasicStroke highlightStroke = new BasicStroke(1.0f, - BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, - new float[] { 4.0f, 6.0f }, 0); - - protected Line2D line = new Line2D.Double(); - - /** - * One possible result of - * {@link ShowRelatedElements#calculateStyle(ReadGraph, Resource, Resource, Variable)} - */ - public static class Relation extends Tuple { - public Relation(String relation, - Resource element, AffineTransform elementTransform, - Resource otherElement, AffineTransform otherElementTransform) - { - super(relation, element, elementTransform, otherElement, otherElementTransform); - } - public String getRelation() { - return (String) getField(0); - } - public Resource getElement() { - return (Resource) getField(1); - } - public AffineTransform getTransform() { - return (AffineTransform) getField(2); - } - public Resource getOtherElement() { - return (Resource) getField(3); - } - public AffineTransform getOtherTransform() { - return (AffineTransform) getField(4); - } - } - - /** - * Calculates a result that is contains the styled element, its parent and - * transforms of both. This takes care of the style updating the visuals - * properly every time the related components move. - */ - @Override - public Object calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) - throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - - if (graph.isInstanceOf(element, DIA.Monitor)) { - return calculateFromComponent(graph, runtimeDiagram, element, DIA.HasMonitorComponent); - } - if (graph.isInstanceOf(element, DIA.Flag)) { - return calculateFromFlag(graph, element); - } - - // Just return anything, no relationship to visualize. - return Boolean.TRUE; - } - - protected Object calculateFromFlag(ReadGraph graph, Resource flag) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - - Resource relatedFlag = FlagUtil.getPossibleCounterpart(graph, flag); - if (relatedFlag != null) { - Collection flagDiagrams = OrderedSetUtils.getOwnerLists(graph, flag, DIA.Diagram); - Collection relatedDiagrams = OrderedSetUtils.getOwnerLists(graph, relatedFlag, DIA.Diagram); - if (!Collections.disjoint(flagDiagrams, relatedDiagrams)) { - AffineTransform flagAt = DiagramGraphUtil.getTransform(graph, flag); - AffineTransform relatedFlagAt = DiagramGraphUtil.getTransform(graph, relatedFlag); - return new Relation(Relationship.RELATED_TO.toString(), flag, flagAt, relatedFlag, relatedFlagAt); - } - } - - return Boolean.TRUE; - } - - protected Object calculateFromComponent(ReadGraph graph, Resource runtime, Resource element, Resource elementToComponentRelation) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - ModelingResources MOD = ModelingResources.getInstance(graph); - - Resource parentComponent = graph.getPossibleObject(element, elementToComponentRelation); - if (parentComponent != null) { - Resource parentElement = graph.getPossibleObject(parentComponent, MOD.ComponentToElement); - if (parentElement != null) { - AffineTransform at = DiagramGraphUtil.getTransform(graph, element); - if (graph.isInstanceOf(parentElement, DIA.Connection)) - return new Relation(Relationship.CHILD_OF.toString(), element, at, parentElement, - getConnectionOutputNodePosition(graph, runtime, parentElement)); - - AffineTransform parentAt = DiagramGraphUtil.getTransform(graph, parentElement); - return new Relation(Relationship.CHILD_OF.toString(), element, at, parentElement, parentAt); - } - } - - return Boolean.TRUE; - } - - protected AffineTransform getConnectionOutputNodePosition(ReadGraph graph, Resource runtime, Resource connection) throws DatabaseException { - Statement toTail = ConnectionUtil.getConnectionTailNodeStatement(graph, connection); - if (toTail == null) - return null; - - AffineTransform at = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, toTail.getObject()); - - Resource connectionPoint = graph.getPossibleInverse(toTail.getPredicate()); - if (connectionPoint == null) - return at; - - DiagramResource DIA = DiagramResource.getInstance(graph); - for (Resource terminal : graph.getObjects(connectionPoint, DIA.HasConnectionPoint_Inverse)) { - AffineTransform terminalAt = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, terminal); - at.concatenate(terminalAt); - } - - return at; - } - - @Override - public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, Object value) { - INode node = map.getNode(item); - if (node == null) { - evaluationContext.update(); - return; - } - - if (!(value instanceof Relation)) { - cleanupStyleForNode(node); - return; - } - - IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); - - Relation r = (Relation) value; - - DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class); - IElement element = emap.getElement(diagram, item); - IElement otherElement = emap.getElement(diagram, r.getOtherElement()); - if (otherElement != null) - addCorrespondence(r, (G2DParentNode) node, r.getRelation(), element, otherElement, highlightStroke, Color.GRAY); - } - - protected void addCorrespondence(Relation r, G2DParentNode p, String id, IElement from, IElement to, Stroke lineStroke, Color lineColor) { - Pair p1 = toPoint(r.getTransform(), from); - Pair p2 = toPoint(r.getOtherTransform(), to); - if (p1 != null && p2 != null) - addCorrespondence(p, id, p1, p2, lineStroke, lineColor); - } - - /** - * @param parentTransform - * @param e - * @return origin and bounding box of the specified element in canvas - * coordinate system - */ - protected Pair toPoint(AffineTransform parentTransform, IElement e) { - if (PickFilter.FILTER_CONNECTIONS.accept(e)) { - // For connections select the first found output terminal position as - // the correspondence visualization point. - - ConnectionHandler ch = e.getElementClass().getSingleItem(ConnectionHandler.class); - terminalConnections.clear(); - ch.getTerminalConnections(e, terminalConnections); - for (Connection c : terminalConnections) { - if (c.end != EdgeEnd.Begin) - continue; - - BendsHandler bh = c.edge.getElementClass().getAtMostOneItemOfClass(BendsHandler.class); - if (bh != null) { - List points = new ArrayList(); - GeometryUtils.getPoints(bh.getPath(c.edge), points); - if (!points.isEmpty()) - return Pair.make(points.get(0), null); - } else { - AffineTransform at = parentTransform; - Point2D point = new Point2D.Double(at.getTranslateX(), at.getTranslateY()); - return Pair.make(point, null); - } - } - - // Fall back to the default logic if connection output terminal - // search fails. - } - - // Using element origin prevents the relationship rubber band target - // from changing every time the content of the node changes, e.g. the - // text of a monitor. - AffineTransform at = ElementUtils.getTransform(e); - Point2D p = new Point2D.Double(at.getTranslateX(), at.getTranslateY()); - Rectangle2D r = ElementUtils.getElementBoundsOnDiagram(e).getBounds2D(); - return Pair.make(p, r); - } - - protected void addCorrespondence(G2DParentNode p, String id, - Pair p1, - Pair p2, - Stroke lineStroke, Color lineColor) - { - RelationshipNode2 node = p.getOrCreateNode(id, RelationshipNode2.class); - node.setZIndex(-10); - - if (p1.second != null) { - line.setLine(p1.first, p2.first); - if (LineUtilities.clipLine(line, p1.second)) - p1.first.setLocation(line.getX2(), line.getY2()); - } - if (p2.second != null) { - line.setLine(p1.first, p2.first); - if (LineUtilities.clipLine(line, p2.second)) - p2.first.setLocation(line.getX1(), line.getY1()); - } - - node.init(lineStroke, lineColor, p1.first, p2.first); - } - - @Override - protected void cleanupStyleForNode(INode node) { - ProfileVariables.denyChild(node, "", Relationship.CHILD_OF.toString()); - //ProfileVariables.denyChild(node, "", Relationship.PARENT_OF.toString()); - ProfileVariables.denyChild(node, "", Relationship.RELATED_TO.toString()); - } - - @Override - public String toString() { - return "show related elements"; - } - -} +/******************************************************************************* + * Copyright (c) 2011 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.diagram.profile; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.diagram.content.ConnectionUtil; +import org.simantics.diagram.flag.FlagUtil; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; +import org.simantics.g2d.connection.handler.ConnectionHandler; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.DataElementMap; +import org.simantics.g2d.diagram.handler.PickRequest.PickFilter; +import org.simantics.g2d.diagram.handler.Relationship; +import org.simantics.g2d.diagram.handler.Topology.Connection; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.BendsHandler; +import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; +import org.simantics.g2d.utils.GeometryUtils; +import org.simantics.modeling.ModelingResources; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.nodes.RelationshipNode2; +import org.simantics.scenegraph.profile.DataNodeMap; +import org.simantics.scenegraph.profile.EvaluationContext; +import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.datastructures.map.Tuple; + +/** + * @author Tuukka Lehtonen + */ +public class ShowRelatedElements extends StyleBase { + + protected Collection terminalConnections = new ArrayList(4); + + protected final BasicStroke highlightStroke = new BasicStroke(1.0f, + BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, + new float[] { 4.0f, 6.0f }, 0); + + protected Line2D line = new Line2D.Double(); + + /** + * One possible result of + * {@link ShowRelatedElements#calculateStyle(ReadGraph, Resource, Resource, Variable)} + */ + public static class Relation extends Tuple { + public Relation(String relation, + Resource element, AffineTransform elementTransform, + Resource otherElement, AffineTransform otherElementTransform) + { + super(relation, element, elementTransform, otherElement, otherElementTransform); + } + public String getRelation() { + return (String) getField(0); + } + public Resource getElement() { + return (Resource) getField(1); + } + public AffineTransform getTransform() { + return (AffineTransform) getField(2); + } + public Resource getOtherElement() { + return (Resource) getField(3); + } + public AffineTransform getOtherTransform() { + return (AffineTransform) getField(4); + } + } + + /** + * Calculates a result that is contains the styled element, its parent and + * transforms of both. This takes care of the style updating the visuals + * properly every time the related components move. + */ + @Override + public Object calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) + throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + + if (graph.isInstanceOf(element, DIA.Monitor)) { + return calculateFromComponent(graph, runtimeDiagram, element, DIA.HasMonitorComponent); + } + if (graph.isInstanceOf(element, DIA.Flag)) { + return calculateFromFlag(graph, element); + } + + // Just return anything, no relationship to visualize. + return Boolean.TRUE; + } + + protected Object calculateFromFlag(ReadGraph graph, Resource flag) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + + Resource relatedFlag = FlagUtil.getPossibleCounterpart(graph, flag); + if (relatedFlag != null) { + Collection flagDiagrams = OrderedSetUtils.getOwnerLists(graph, flag, DIA.Diagram); + Collection relatedDiagrams = OrderedSetUtils.getOwnerLists(graph, relatedFlag, DIA.Diagram); + if (!Collections.disjoint(flagDiagrams, relatedDiagrams)) { + AffineTransform flagAt = DiagramGraphUtil.getTransform(graph, flag); + AffineTransform relatedFlagAt = DiagramGraphUtil.getTransform(graph, relatedFlag); + return new Relation(Relationship.RELATED_TO.toString(), flag, flagAt, relatedFlag, relatedFlagAt); + } + } + + return Boolean.TRUE; + } + + protected Object calculateFromComponent(ReadGraph graph, Resource runtime, Resource element, Resource elementToComponentRelation) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + + Resource parentComponent = graph.getPossibleObject(element, elementToComponentRelation); + if (parentComponent != null) { + Resource parentElement = graph.getPossibleObject(parentComponent, MOD.ComponentToElement); + if (parentElement != null) { + AffineTransform at = DiagramGraphUtil.getTransform(graph, element); + if (graph.isInstanceOf(parentElement, DIA.Connection)) + return new Relation(Relationship.CHILD_OF.toString(), element, at, parentElement, + getConnectionOutputNodePosition(graph, runtime, parentElement)); + + AffineTransform parentAt = DiagramGraphUtil.getTransform(graph, parentElement); + return new Relation(Relationship.CHILD_OF.toString(), element, at, parentElement, parentAt); + } + } + + return Boolean.TRUE; + } + + protected AffineTransform getConnectionOutputNodePosition(ReadGraph graph, Resource runtime, Resource connection) throws DatabaseException { + Statement toTail = ConnectionUtil.getConnectionTailNodeStatement(graph, connection); + if (toTail == null) + return null; + + AffineTransform at = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, toTail.getObject()); + + Resource connectionPoint = graph.getPossibleInverse(toTail.getPredicate()); + if (connectionPoint == null) + return at; + + DiagramResource DIA = DiagramResource.getInstance(graph); + for (Resource terminal : graph.getObjects(connectionPoint, DIA.HasConnectionPoint_Inverse)) { + AffineTransform terminalAt = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, terminal); + at.concatenate(terminalAt); + } + + return at; + } + + @Override + public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, Object value) { + INode node = map.getNode(item); + if (node == null) { + evaluationContext.update(); + return; + } + + if (!(value instanceof Relation)) { + cleanupStyleForNode(node); + return; + } + + IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); + + Relation r = (Relation) value; + + DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class); + IElement element = emap.getElement(diagram, item); + IElement otherElement = emap.getElement(diagram, r.getOtherElement()); + if (otherElement != null) + addCorrespondence(r, (G2DParentNode) node, r.getRelation(), element, otherElement, highlightStroke, Color.GRAY); + } + + protected void addCorrespondence(Relation r, G2DParentNode p, String id, IElement from, IElement to, Stroke lineStroke, Color lineColor) { + Pair p1 = toPoint(r.getTransform(), from); + Pair p2 = toPoint(r.getOtherTransform(), to); + if (p1 != null && p2 != null) + addCorrespondence(p, id, p1, p2, lineStroke, lineColor); + } + + /** + * @param parentTransform + * @param e + * @return origin and bounding box of the specified element in canvas + * coordinate system + */ + protected Pair toPoint(AffineTransform parentTransform, IElement e) { + if (PickFilter.FILTER_CONNECTIONS.accept(e)) { + // For connections select the first found output terminal position as + // the correspondence visualization point. + + ConnectionHandler ch = e.getElementClass().getSingleItem(ConnectionHandler.class); + terminalConnections.clear(); + ch.getTerminalConnections(e, terminalConnections); + for (Connection c : terminalConnections) { + if (c.end != EdgeEnd.Begin) + continue; + + BendsHandler bh = c.edge.getElementClass().getAtMostOneItemOfClass(BendsHandler.class); + if (bh != null) { + List points = new ArrayList(); + GeometryUtils.getPoints(bh.getPath(c.edge), points); + if (!points.isEmpty()) + return Pair.make(points.get(0), null); + } else { + AffineTransform at = parentTransform; + Point2D point = new Point2D.Double(at.getTranslateX(), at.getTranslateY()); + return Pair.make(point, null); + } + } + + // Fall back to the default logic if connection output terminal + // search fails. + } + + // Using element origin prevents the relationship rubber band target + // from changing every time the content of the node changes, e.g. the + // text of a monitor. + AffineTransform at = ElementUtils.getTransform(e); + Point2D p = new Point2D.Double(at.getTranslateX(), at.getTranslateY()); + Rectangle2D r = ElementUtils.getElementBoundsOnDiagram(e).getBounds2D(); + return Pair.make(p, r); + } + + protected void addCorrespondence(G2DParentNode p, String id, + Pair p1, + Pair p2, + Stroke lineStroke, Color lineColor) + { + RelationshipNode2 node = p.getOrCreateNode(id, RelationshipNode2.class); + node.setZIndex(-10); + + if (p1.second != null) { + line.setLine(p1.first, p2.first); + if (LineUtilities.clipLine(line, p1.second)) + p1.first.setLocation(line.getX2(), line.getY2()); + } + if (p2.second != null) { + line.setLine(p1.first, p2.first); + if (LineUtilities.clipLine(line, p2.second)) + p2.first.setLocation(line.getX1(), line.getY1()); + } + + node.init(lineStroke, lineColor, p1.first, p2.first); + } + + @Override + protected void cleanupStyleForNode(INode node) { + ProfileVariables.denyChild(node, "", Relationship.CHILD_OF.toString()); + //ProfileVariables.denyChild(node, "", Relationship.PARENT_OF.toString()); + ProfileVariables.denyChild(node, "", Relationship.RELATED_TO.toString()); + } + + @Override + public String toString() { + return "show related elements"; + } + +}