-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.diagram.participant;\r
-\r
-import java.awt.Color;\r
-import java.awt.Font;\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.PossibleIndexRoot;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.adapter.Instances;\r
-import org.simantics.db.layer0.request.IsActive;\r
-import org.simantics.db.layer0.util.Layer0Utils;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.diagram.elements.TextNode;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.ICanvasContext;\r
-import org.simantics.g2d.canvas.SGDesignation;\r
-import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
-import org.simantics.g2d.canvas.impl.HintReflection.HintListener;\r
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;\r
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
-import org.simantics.g2d.utils.Alignment;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.utils.datastructures.hints.IHintContext;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
-import org.simantics.utils.ui.ErrorLogger;\r
-\r
-/**\r
- * DiagramModelActivityTracker tracks whether or not the specified input\r
- * resource is part of the diagram model or not and modifies the canvas\r
- * background color accordingly. If the diagram is not in an active model, an\r
- * <b>INACTIVE MODEL</b> banner is also shown in the background using\r
- * {@link TextNode}.\r
- * \r
- * @author Tuukka Lehtonen\r
- */\r
-public class DiagramModelActivityTracker extends AbstractCanvasParticipant {\r
-\r
- public static final Key KEY_IN_ACTIVE_MODEL = new KeyOf(String.class, "IN_ACTIVE_MODEL");\r
- public static final Key KEY_ACTIVE_BACKGROUND = new KeyOf(Color.class, "ACTIVE_BACKGROUND");\r
- public static final Key KEY_INACTIVE_BACKGROUND = new KeyOf(Color.class, "INACTIVE_BACKGROUND");\r
-\r
- private static final Color DEFAULT_ACTIVE_BACKGROUND = Color.WHITE;\r
- private static final Color DEFAULT_INACTIVE_BACKGROUND = new Color(242, 242, 242);\r
-\r
- Resource input;\r
- IsInActiveModelListener listener;\r
- TextNode bannerNode;\r
-\r
- public DiagramModelActivityTracker(Resource input) {\r
- if (input == null)\r
- throw new NullPointerException("null input");\r
- this.input = input;\r
- }\r
-\r
- @HintListener(Class=Hints.class, Field="KEY_CONTROL_BOUNDS")\r
- public void controlBoundsChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
- if (bannerNode == null)\r
- return;\r
- if (newValue != null) {\r
- Rectangle2D bounds = (Rectangle2D) newValue;\r
- AffineTransform at = new AffineTransform();\r
- at.translate(5,5);\r
-// at.translate(bounds.getWidth() / 2, bounds.getHeight() / 2);\r
-// at.scale(2, 2);\r
-// at.rotate(-Math.PI/6);\r
-// at.translate(bounds.getWidth() - 150, bounds.getHeight() - 30);\r
-// at.scale(1, 1);\r
- bannerNode.setTransform(at);\r
- } else {\r
- // Disable rendering\r
- bannerNode.setColor(null);\r
- }\r
- }\r
-\r
- @HintListener(Class=DiagramModelActivityTracker.class, Field="KEY_IN_ACTIVE_MODEL")\r
- public void containingModelActivityChanged(IHintObservable sender, Key key, Object oldValue, Object _newValue) {\r
- String newValue = (String)_newValue;\r
- if (bannerNode == null)\r
- return;\r
- if (newValue == null) {\r
- bannerNode.setText("");\r
- } else {\r
- bannerNode.setText(newValue);\r
- //bannerNode.setColor(new Color(192, 32, 32, 128));\r
- //bannerNode.setColor(new Color(192, 32, 32, 32));\r
- }\r
- }\r
-\r
- @Override\r
- public void addedToContext(ICanvasContext ctx) {\r
- super.addedToContext(ctx);\r
-\r
- listener = new IsInActiveModelListener(ctx);\r
- Simantics.getSession().async(new IsActiveDiagram(input), listener);\r
-\r
- if (!ctx.getHintStack().containsHint(KEY_ACTIVE_BACKGROUND))\r
- ctx.getDefaultHintContext().setHint(KEY_ACTIVE_BACKGROUND, DEFAULT_ACTIVE_BACKGROUND);\r
- if (!ctx.getHintStack().containsHint(KEY_INACTIVE_BACKGROUND))\r
- ctx.getDefaultHintContext().setHint(KEY_INACTIVE_BACKGROUND, DEFAULT_INACTIVE_BACKGROUND);\r
- }\r
-\r
- @Override\r
- public void removedFromContext(ICanvasContext ctx) {\r
- if (listener != null) {\r
- listener.dispose();\r
- listener = null;\r
- }\r
- super.removedFromContext(ctx);\r
- }\r
-\r
- @SGInit(designation = SGDesignation.CONTROL)\r
- public void initSG(G2DParentNode parent) {\r
- bannerNode = parent.addNode("inactivity-banner", TextNode.class);\r
- bannerNode.setZIndex(Integer.MIN_VALUE / 4);\r
- //bannerNode.setZIndex(Integer.MAX_VALUE / 4);\r
- bannerNode.setHorizontalAlignment((byte) Alignment.LEADING.ordinal());\r
- bannerNode.setVerticalAlignment((byte) Alignment.LEADING.ordinal());\r
- //bannerNode.setText("Model is not active.");\r
- bannerNode.setText("");\r
- bannerNode.setFont(Font.decode("Arial 16"));\r
- //bannerNode.setBackgroundColor(new Color(192, 192, 192, 128));\r
- bannerNode.setPadding(10, 10);\r
- bannerNode.setBorderColor(Color.GRAY);\r
- bannerNode.setBorderWidth(0);\r
- bannerNode.setEditable(false);\r
- }\r
-\r
- @SGCleanup\r
- public void cleanupSG() {\r
- if (bannerNode != null) {\r
- bannerNode.remove();\r
- bannerNode = null;\r
- }\r
- }\r
-\r
- static class IsActiveDiagram extends UnaryRead<Resource, String> {\r
- public IsActiveDiagram(Resource parameter) {\r
- super(parameter);\r
- }\r
- @Override\r
- public String perform(ReadGraph graph) throws DatabaseException {\r
- \r
- Resource indexRoot = graph.syncRequest( new PossibleIndexRoot(parameter) );\r
- if (indexRoot == null) {\r
- return "This diagram is not part of any model or shared library";\r
- }\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
- ModelingResources MOD = ModelingResources.getInstance(graph);\r
- Resource composite = graph.getPossibleObject(parameter, MOD.DiagramToComposite);\r
- if(composite == null)\r
- return "This diagram does not have a corresponding configuration";\r
- \r
- Resource componentType = graph.getPossibleObject(composite, STR.Defines);\r
- if(componentType != null) {\r
- // This is a component type\r
- boolean published = Layer0Utils.isPublished(graph, componentType);\r
- if(published)\r
- return "This diagram defines a published (read-only) user component";\r
- }\r
- \r
- if(graph.isInstanceOf(indexRoot, L0.SharedOntology)) {\r
- return "";\r
- }\r
- \r
- boolean activeModel = graph.syncRequest( new IsActive(indexRoot) );\r
- if(!activeModel)\r
- return "The model of this diagram is not active";\r
- \r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- Instances query = graph.adapt(DIA.DiagramActivityCondition, Instances.class);\r
-\r
- for(Resource condition : query.find(graph, indexRoot)) {\r
- String value = Simantics.tryInvokeSCL(graph, condition, DIA.DiagramActivityCondition_test, parameter);\r
- if(value != null && !value.isEmpty()) return value;\r
- }\r
- \r
- return "";\r
- \r
- }\r
- }\r
-\r
- static class IsInActiveModelListener implements Listener<String> {\r
- ICanvasContext context;\r
- public IsInActiveModelListener(ICanvasContext context) {\r
- this.context = context;\r
- }\r
- @Override\r
- public void execute(final String result) {\r
- final Color color = (result.isEmpty())\r
- ? context.getHintStack().<Color>getHint(KEY_ACTIVE_BACKGROUND)\r
- : context.getHintStack().<Color>getHint(KEY_INACTIVE_BACKGROUND);\r
-\r
- context.getThreadAccess().asyncExec(new Runnable() {\r
- @Override\r
- public void run() {\r
- ICanvasContext ctx = context;\r
- if (ctx == null)\r
- return;\r
- if (ctx.isDisposed())\r
- return;\r
- IHintContext hints = ctx.getDefaultHintContext();\r
- if (color != null)\r
- hints.setHint(Hints.KEY_BACKGROUND_COLOR, color);\r
- hints.setHint(KEY_IN_ACTIVE_MODEL, result);\r
- }\r
- });\r
- }\r
- public void dispose() {\r
- context = null;\r
- }\r
- @Override\r
- public boolean isDisposed() {\r
- ICanvasContext context = this.context;\r
- return context == null || context.isDisposed();\r
- }\r
- @Override\r
- public void exception(Throwable t) {\r
- ErrorLogger.defaultLogError(t);\r
- }\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2018 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.participant;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.adapter.Instances;
+import org.simantics.db.layer0.request.IsActive;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.procedure.Listener;
+import org.simantics.diagram.elements.TextNode;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.SGDesignation;
+import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
+import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
+import org.simantics.g2d.participant.RulerPainter;
+import org.simantics.g2d.utils.Alignment;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.utils.DPIUtil;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.utils.datastructures.hints.IHintContext;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.ui.ErrorLogger;
+
+/**
+ * DiagramModelActivityTracker tracks whether or not the specified input
+ * resource is part of the diagram model or not and modifies the canvas
+ * background color accordingly. If the diagram is not in an active model, an
+ * <b>INACTIVE MODEL</b> banner is also shown in the background using
+ * {@link TextNode}.
+ *
+ * @author Tuukka Lehtonen
+ */
+public class DiagramModelActivityTracker extends AbstractCanvasParticipant {
+
+ public static final Key KEY_IN_ACTIVE_MODEL = new KeyOf(String.class, "IN_ACTIVE_MODEL");
+ public static final Key KEY_ACTIVE_BACKGROUND = new KeyOf(Color.class, "ACTIVE_BACKGROUND");
+ public static final Key KEY_INACTIVE_BACKGROUND = new KeyOf(Color.class, "INACTIVE_BACKGROUND");
+
+ private static final Color DEFAULT_ACTIVE_BACKGROUND = Color.WHITE;
+ private static final Color DEFAULT_INACTIVE_BACKGROUND = new Color(242, 242, 242);
+
+ Resource input;
+ IsInActiveModelListener listener;
+ TextNode bannerNode;
+ Rectangle2D bounds;
+ boolean rulerVisible = false;
+ double rulerSize = 0;
+
+ public DiagramModelActivityTracker(Resource input) {
+ if (input == null)
+ throw new NullPointerException("null input");
+ this.input = input;
+ }
+
+ @HintListener(Class=Hints.class, Field="KEY_CONTROL_BOUNDS")
+ public void controlBoundsChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ bounds = (Rectangle2D) newValue;
+ resetBannerNode(bounds, rulerVisible, rulerSize);
+ }
+
+ @HintListener(Class=RulerPainter.class, Field="KEY_RULER_ENABLED")
+ public void rulerToggled(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ rulerVisible = Boolean.TRUE.equals(newValue);
+ resetBannerNode(bounds, rulerVisible, rulerSize);
+ }
+
+ @HintListener(Class=RulerPainter.class, Field="KEY_RULER_SIZE")
+ public void rulerSizeChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ rulerSize = newValue != null ? (Double) newValue : 0.0;
+ resetBannerNode(bounds, rulerVisible, rulerSize);
+ }
+
+ private void resetBannerNode(Rectangle2D bounds, boolean rulerVisible, double rulerSize) {
+ if (bannerNode == null)
+ return;
+ if (bounds != null) {
+ AffineTransform at = new AffineTransform();
+ at.translate(5,5);
+ if (rulerVisible) {
+ double s = DPIUtil.upscale(rulerSize);
+ at.translate(s, s);
+ }
+ bannerNode.setTransform(at);
+ bannerNode.setColor(Color.BLACK);
+ } else {
+ // Disable rendering
+ bannerNode.setColor(null);
+ }
+ }
+
+ @HintListener(Class=DiagramModelActivityTracker.class, Field="KEY_IN_ACTIVE_MODEL")
+ public void containingModelActivityChanged(IHintObservable sender, Key key, Object oldValue, Object _newValue) {
+ String newValue = (String)_newValue;
+ if (bannerNode == null)
+ return;
+ if (newValue == null) {
+ bannerNode.setText("");
+ } else {
+ bannerNode.setText(newValue);
+ //bannerNode.setColor(new Color(192, 32, 32, 128));
+ //bannerNode.setColor(new Color(192, 32, 32, 32));
+ }
+ }
+
+ @Override
+ public void addedToContext(ICanvasContext ctx) {
+ super.addedToContext(ctx);
+
+ rulerVisible = Boolean.TRUE.equals(getHint(RulerPainter.KEY_RULER_ENABLED));
+ Double rs = getHint(RulerPainter.KEY_RULER_SIZE);
+ rulerSize = rs != null ? rs : 0;
+
+ listener = new IsInActiveModelListener(ctx);
+ Simantics.getSession().async(new IsActiveDiagram(input), listener);
+
+ if (!ctx.getHintStack().containsHint(KEY_ACTIVE_BACKGROUND))
+ ctx.getDefaultHintContext().setHint(KEY_ACTIVE_BACKGROUND, DEFAULT_ACTIVE_BACKGROUND);
+ if (!ctx.getHintStack().containsHint(KEY_INACTIVE_BACKGROUND))
+ ctx.getDefaultHintContext().setHint(KEY_INACTIVE_BACKGROUND, DEFAULT_INACTIVE_BACKGROUND);
+ }
+
+ @Override
+ public void removedFromContext(ICanvasContext ctx) {
+ if (listener != null) {
+ listener.dispose();
+ listener = null;
+ }
+ super.removedFromContext(ctx);
+ }
+
+ @SGInit(designation = SGDesignation.CONTROL)
+ public void initSG(G2DParentNode parent) {
+ bannerNode = parent.addNode("inactivity-banner", TextNode.class);
+ bannerNode.setZIndex(Integer.MIN_VALUE / 4);
+ //bannerNode.setZIndex(Integer.MAX_VALUE / 4);
+ bannerNode.setHorizontalAlignment((byte) Alignment.LEADING.ordinal());
+ bannerNode.setVerticalAlignment((byte) Alignment.LEADING.ordinal());
+ //bannerNode.setText("Model is not active.");
+ bannerNode.setText("");
+ int fontSize = DPIUtil.upscale(16);
+ bannerNode.setFont(new Font("Tahoma", Font.PLAIN, fontSize));
+ //bannerNode.setBackgroundColor(new Color(192, 192, 192, 128));
+ bannerNode.setPadding(10, 10);
+ bannerNode.setBorderColor(Color.GRAY);
+ bannerNode.setBorderWidth(0);
+ bannerNode.setEditable(false);
+ bannerNode.setColor(Color.BLACK);
+ }
+
+ @SGCleanup
+ public void cleanupSG() {
+ if (bannerNode != null) {
+ bannerNode.remove();
+ bannerNode = null;
+ }
+ }
+
+ static class IsActiveDiagram extends UnaryRead<Resource, String> {
+ public IsActiveDiagram(Resource parameter) {
+ super(parameter);
+ }
+ @Override
+ public String perform(ReadGraph graph) throws DatabaseException {
+
+ Resource indexRoot = graph.syncRequest( new PossibleIndexRoot(parameter) );
+ if (indexRoot == null) {
+ return "This diagram is not part of any model or shared library";
+ }
+ Layer0 L0 = Layer0.getInstance(graph);
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ Resource composite = graph.getPossibleObject(parameter, MOD.DiagramToComposite);
+ if(composite == null)
+ return "This diagram does not have a corresponding configuration";
+
+ Resource componentType = graph.getPossibleObject(composite, STR.Defines);
+ if(componentType != null) {
+ // This is a component type
+ boolean published = Layer0Utils.isPublished(graph, componentType);
+ if(published)
+ return "This diagram defines a published (read-only) user component";
+ }
+
+ if(graph.isInstanceOf(indexRoot, L0.SharedOntology)) {
+ return "";
+ }
+
+ boolean activeModel = graph.syncRequest( new IsActive(indexRoot) );
+ if(!activeModel)
+ return "The model of this diagram is not active";
+
+ DiagramResource DIA = DiagramResource.getInstance(graph);
+ Instances query = graph.adapt(DIA.DiagramActivityCondition, Instances.class);
+
+ for(Resource condition : query.find(graph, indexRoot)) {
+ String value = Simantics.tryInvokeSCL(graph, condition, DIA.DiagramActivityCondition_test, parameter);
+ if(value != null && !value.isEmpty()) return value;
+ }
+
+ return "";
+
+ }
+ }
+
+ static class IsInActiveModelListener implements Listener<String> {
+ ICanvasContext context;
+ public IsInActiveModelListener(ICanvasContext context) {
+ this.context = context;
+ }
+ @Override
+ public void execute(final String result) {
+ final Color color = (result.isEmpty())
+ ? context.getHintStack().<Color>getHint(KEY_ACTIVE_BACKGROUND)
+ : context.getHintStack().<Color>getHint(KEY_INACTIVE_BACKGROUND);
+
+ context.getThreadAccess().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ ICanvasContext ctx = context;
+ if (ctx == null)
+ return;
+ if (ctx.isDisposed())
+ return;
+ IHintContext hints = ctx.getDefaultHintContext();
+ if (color != null)
+ hints.setHint(Hints.KEY_BACKGROUND_COLOR, color);
+ hints.setHint(KEY_IN_ACTIVE_MODEL, result);
+ }
+ });
+ }
+ public void dispose() {
+ context = null;
+ }
+ @Override
+ public boolean isDisposed() {
+ ICanvasContext context = this.context;
+ return context == null || context.isDisposed();
+ }
+ @Override
+ public void exception(Throwable t) {
+ ErrorLogger.defaultLogError(t);
+ }
+ }
+
+}