X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Fdiagram%2Fstyle%2FIssueDecorationStyle.java;h=68210f9e263f5c48e51eb10bbbc30f0324b85244;hp=f0384d115f659b097b4e94cc02b134da706f8f4f;hb=46cdf23c4ea4733a3acbfd5c9895ec9e65965c7d;hpb=0b471805f017da83d715a0d8409f53bdd009d31e diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/IssueDecorationStyle.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/IssueDecorationStyle.java index f0384d115..68210f9e2 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/IssueDecorationStyle.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/IssueDecorationStyle.java @@ -1,161 +1,211 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.modeling.ui.diagram.style; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.procedure.adapter.TransientCacheListener; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.diagram.profile.StyleBase; -import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; -import org.simantics.issues.Severity; -import org.simantics.issues.common.IssueResourcesContexts; -import org.simantics.issues.common.ListModelIssuesBySeverity; -import org.simantics.modeling.ModelingResources; -import org.simantics.modeling.ui.Activator; -import org.simantics.modeling.ui.diagram.style.IssueDecorationStyle.IssueResult; -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.g2d.nodes.Decoration; -import org.simantics.scenegraph.g2d.nodes.DecorationSVGNode; -import org.simantics.scenegraph.g2d.nodes.SVGNode; -import org.simantics.scenegraph.profile.EvaluationContext; -import org.simantics.scenegraph.profile.common.ProfileVariables; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.utils.datastructures.map.Tuple; - - -/** - * @author Tuukka Lehtonen - */ -public class IssueDecorationStyle extends StyleBase { - - private static final String DECORATION_NODE_NAME = "issueDecorations"; - - private List getContexts(ReadGraph graph, Resource element) throws DatabaseException { - - ModelingResources MOD = ModelingResources.getInstance(graph); - List result = new ArrayList(3); - result.add(element); - Resource config = graph.getPossibleObject(element, MOD.ElementToComponent); - if (config != null && result.indexOf(config) == -1) result.add(config); - config = graph.getPossibleObject(element, MOD.DiagramConnectionToConnection); - if (config != null && result.indexOf(config) == -1) result.add(config); - // For diagram reference element support - config = graph.getPossibleObject(element, MOD.HasParentComponent); - if (config != null && result.indexOf(config) == -1) result.add(config); - return result; - - } - - @Override - public IssueResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException { - - Resource model = Variables.getModel(graph, configuration); - if (model == null) - return null; - - List contexts = getContexts(graph, element); - AffineTransform transform = DiagramGraphUtil.getAffineTransform(graph, element); - Map> issuesBySeverity = graph.syncRequest(new ListModelIssuesBySeverity(model, true, true, Severity.NOTE), - TransientCacheListener.>>instance()); - - for (Severity severity : Severity.values()) { - List issues = issuesBySeverity.get(severity); - if (issues != null) { - Set issueContexts = graph.syncRequest(new IssueResourcesContexts(issues)); - if (!Collections.disjoint(issueContexts, contexts)) - return new IssueResult(severity, transform); - } - } - - return null; - } - - @Override - public void applyStyleForNode(EvaluationContext observer, INode node, IssueResult result) { - if (result == null) { - ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); - return; - } - - SVGNode svgNode = ProfileVariables.claimChild(node, "", DECORATION_NODE_NAME, DecorationSVGNode.class, observer); - - svgNode.setZIndex( Integer.MAX_VALUE ); - svgNode.setTransform(getDecorationPosition(node)); - - String svgData = svgDataForSeverity(result.getSeverity()); - if (svgData != null) - svgNode.setData(svgData); - } - - /** - * Returns position of the decoration. - * By default decoration is placed to the top left corner. Override this method to change the position. - * - * @param node - * @return - */ - protected AffineTransform getDecorationPosition(INode node) { - Rectangle2D bounds = NodeUtil.getLocalBounds(node, Decoration.class); - - double tx = bounds.getX(); - double ty = bounds.getY(); - return AffineTransform.getTranslateInstance(tx, ty); - } - - protected String svgDataForSeverity(Severity s) { - switch (s) { - case FATAL: return Activator.FATAL_SVG_TEXT; - case ERROR: return Activator.ERROR_SVG_TEXT; - case WARNING: return Activator.WARNING_SVG_TEXT; - case INFO: return Activator.INFO_SVG_TEXT; - case NOTE: return Activator.NOTE_SVG_TEXT; - default: return null; - } - } - - @Override - protected void cleanupStyleForNode(INode node) { - ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); - } - - @Override - public String toString() { - return "Issue decoration"; - } - - /** - * This is needed to keep the issue decoration up-to-date when its parent - * element moves. - */ - public static class IssueResult extends Tuple { - public IssueResult(Severity severity, AffineTransform transform) { - super(severity, transform); - } - public Severity getSeverity() { - return (Severity) getField(0); - } - } - -} - - +/******************************************************************************* + * Copyright (c) 2007, 2010 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.modeling.ui.diagram.style; + +import java.awt.geom.AffineTransform; +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.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.diagram.connection.RouteGraph; +import org.simantics.diagram.elements.DecorationSVGNode; +import org.simantics.diagram.elements.SVGNode; +import org.simantics.diagram.handler.Paster; +import org.simantics.diagram.handler.Paster.RouteLine; +import org.simantics.diagram.profile.StyleBase; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; +import org.simantics.issues.Severity; +import org.simantics.issues.common.IssueResourcesContexts; +import org.simantics.issues.common.ListModelIssuesBySeverity; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.ui.Activator; +import org.simantics.modeling.ui.diagram.style.IssueDecorationStyle.IssueResult; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.nodes.ConnectionNode; +import org.simantics.scenegraph.g2d.nodes.Decoration; +import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode; +import org.simantics.scenegraph.profile.EvaluationContext; +import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.utils.datastructures.map.Tuple; + + +/** + * @author Tuukka Lehtonen + */ +public class IssueDecorationStyle extends StyleBase { + + private static final String DECORATION_NODE_NAME = "issueDecorations"; //$NON-NLS-1$ + + private List getContexts(ReadGraph graph, Resource element) throws DatabaseException { + + ModelingResources MOD = ModelingResources.getInstance(graph); + List result = new ArrayList(3); + result.add(element); + Resource config = graph.getPossibleObject(element, MOD.ElementToComponent); + if (config != null && result.indexOf(config) == -1) result.add(config); + config = graph.getPossibleObject(element, MOD.DiagramConnectionToConnection); + if (config != null && result.indexOf(config) == -1) result.add(config); + // For diagram reference element support + config = graph.getPossibleObject(element, MOD.HasParentComponent); + if (config != null && result.indexOf(config) == -1) result.add(config); + return result; + + } + + @Override + public IssueResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException { + + Resource model = Variables.getModel(graph, configuration); + if (model == null) + return null; + + List contexts = getContexts(graph, element); + Map> issuesBySeverity = graph.syncRequest(new ListModelIssuesBySeverity(model, true, true, Severity.NOTE), + TransientCacheListener.>>instance()); + + for (Severity severity : Severity.values()) { + List issues = issuesBySeverity.get(severity); + if (issues != null) { + Set issueContexts = graph.syncRequest(new IssueResourcesContexts(issues)); + if (!Collections.disjoint(issueContexts, contexts)) { + return new IssueResult(severity, getIdentifier(graph, runtimeDiagram, element)); + } + } + } + + return null; + } + + private static Object getIdentifier(ReadGraph graph, Resource runtimeDiagram, Resource element) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + if (graph.isInstanceOf(element, DIA.RouteGraphConnection)) { + Collection connectors = graph.getObjects(element, DIA.HasConnector); + Collection routeNodes = graph.getObjects(element, DIA.HasInteriorRouteNode); + + // This is needed to make this query result change every time the underlying element changes visually. + Set identifier = new HashSet(connectors.size() + routeNodes.size()); + + for (Resource connector : connectors) { + for (Resource connectedTo : graph.getObjects(connector, STR.Connects)) { + if (!connectedTo.equals(element)) { + AffineTransform at = DiagramGraphUtil.getDynamicAffineTransform(graph, runtimeDiagram, connectedTo, DIA.HasDynamicTransform, false); + identifier.add(at); + } + } + } + for (Resource routeLine : routeNodes) { + RouteLine rl = Paster.readRouteLine(graph, routeLine); + identifier.add(rl); + } + return identifier; + } else { + return DiagramGraphUtil.getAffineTransform(graph, element); + } + } + + @Override + public void applyStyleForNode(EvaluationContext observer, INode node, IssueResult result) { + if (result == null) { + ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); //$NON-NLS-1$ + return; + } + + SVGNode svgNode = ProfileVariables.claimChild(node, "", DECORATION_NODE_NAME, DecorationSVGNode.class, observer); //$NON-NLS-1$ + + svgNode.setZIndex( Integer.MAX_VALUE ); + svgNode.setTransform(getDecorationPosition(node)); + + String svgData = svgDataForSeverity(result.getSeverity()); + if (svgData != null) + svgNode.setData(svgData); + } + + /** + * Returns position of the decoration. + * By default decoration is placed to the top left corner. Override this method to change the position. + * + * @param node + * @return + */ + protected AffineTransform getDecorationPosition(INode node) { + Rectangle2D bounds = NodeUtil.getLocalBounds(node, Decoration.class); + + if (node instanceof ConnectionNode) { + for (INode child : ((ConnectionNode)node).getSortedNodes()) { + if (child instanceof RouteGraphNode) { + RouteGraphNode rgn = (RouteGraphNode) child; + RouteGraph rg = rgn.getRouteGraph(); + Point2D nearest = rg.findNearestPoint(bounds.getCenterX(), bounds.getCenterY()); + if (nearest != null) { + return AffineTransform.getTranslateInstance(nearest.getX(), nearest.getY()); + } + } + } + } + double tx = bounds.getX(); + double ty = bounds.getY(); + return AffineTransform.getTranslateInstance(tx, ty); + } + + protected String svgDataForSeverity(Severity s) { + switch (s) { + case FATAL: return Activator.FATAL_SVG_TEXT; + case ERROR: return Activator.ERROR_SVG_TEXT; + case WARNING: return Activator.WARNING_SVG_TEXT; + case INFO: return Activator.INFO_SVG_TEXT; + case NOTE: return Activator.NOTE_SVG_TEXT; + default: return null; + } + } + + @Override + protected void cleanupStyleForNode(INode node) { + ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); //$NON-NLS-1$ + } + + @Override + public String toString() { + return "Issue decoration"; //$NON-NLS-1$ + } + + /** + * This is needed to keep the issue decoration up-to-date when its parent + * element moves. + */ + public static class IssueResult extends Tuple { + public IssueResult(Severity severity, Object identifier) { + super(severity, identifier); + } + public Severity getSeverity() { + return (Severity) getField(0); + } + } + +} + +