this.updateSchedules = new ArrayList[CLUSTER_THREADS];
for(int i=0;i<clusterUpdateThreads.length;i++) {
clusterUpdateThreads[i] = Executors.newSingleThreadExecutor(new ClusterThreadFactory("Cluster Updater " + (i+1), false));
- updateSchedules[i] = new ArrayList<ClusterUpdateOperation>();
+ updateSchedules[i] = new ArrayList<>();
}
}
try {
+ TreeMap<ClusterUID, List<ClusterUpdateOperation>> updates = new TreeMap<>(clusterComparator);
+
main:
while(alive) {
- TreeMap<ClusterUID, List<ClusterUpdateOperation>> updates = new TreeMap<ClusterUID, List<ClusterUpdateOperation>>(clusterComparator);
-
+ if (!updates.isEmpty())
+ updates.clear();
operationQueue.pumpUpdates(updates);
if(updates.isEmpty()) {
for(int i=0;i<CLUSTER_THREADS;i++)
updateSchedules[i].clear();
+ if (updates.isEmpty())
+ return;
+
final Semaphore s = new Semaphore(0);
for(Map.Entry<ClusterUID, List<ClusterUpdateOperation>> entry : updates.entrySet()) {
import org.simantics.db.ExternalValueSupport;
import org.simantics.db.ReadGraph;
import org.simantics.db.RelationContext;
+import org.simantics.db.RelationInfo;
import org.simantics.db.Resource;
import org.simantics.db.Session;
import org.simantics.db.Statement;
try {
- Collection<Resource> objects = getObjects(subject, relation);
- return !objects.isEmpty();
+ SyncReadProcedure<RelationInfo> procedure = new SyncReadProcedure<RelationInfo>();
+ processor.forRelationInfo(this, relation, procedure);
+ Collection<Resource> predicates = getPredicates(subject);
+
+ if(procedure.result.isFinal) {
+
+ return predicates.contains(relation);
+
+ } else if (procedure.result.isFunctional) {
+
+ try {
+ int result = processor.getSingleObject(this, subject, relation);
+ return result != 0;
+ } catch (ManyObjectsForFunctionalRelationException e) {
+ return true;
+ } catch (DatabaseException e) {
+ throw new ServiceException(e);
+ }
+
+ } else {
+
+ for(Resource predicate : getPredicates(subject)) {
+ if(isSubrelationOf(predicate, relation))
+ return true;
+ }
+
+ }
+
+ return false;
} catch (ServiceException e) {
QueryControl qc = graph.getService(QueryControl.class);
ClusterControl cc = graph.getService(ClusterControl.class);
_monitor.beginTask("Collect clusters", IProgressMonitor.UNKNOWN);
- cc.gc(graph, clusterTarget);
+ //cc.gc(graph, clusterTarget);
+ if(clusterTarget == -1) {
+ int used = cc.used();
+ //System.err.println("session gc, cluster use = " + used);
+ int baseline = 32*(1<<20);
+ if(used > baseline) {
+ int dynamicTarget = (int)(0.95 * (used-baseline)) + baseline;
+ cc.gc(graph, dynamicTarget);
+ }
+ } else {
+ cc.gc(graph, clusterTarget);
+ }
_monitor.beginTask("Collect queries", IProgressMonitor.UNKNOWN);
qc.gc(graph, allowedTimeInMs);
}
ArrayList<CollectorCluster> toRelease = new ArrayList<CollectorCluster>();
for (CollectorCluster cluster : support.getResidentClusters()) {
- target -= support.getClusterSize(cluster);
- if (target > 0) {
- toRelease.add(cluster);
- } else {
+ toRelease.add(cluster);
+ long clusterSize = support.getClusterSize(cluster);
+ //System.err.println("release cluster with " + (clusterSize/1024) + " kiB - " + cluster);
+ target -= clusterSize;
+ if (target <= 0) {
break;
}
}
NamedNodeMap attr = n.getAttributes();
IDynamicAdapter2 da = null;
if(n.getNodeName().equals("this"))
- da = new ThisResource2();
+ da = ThisResource2.INSTANCE;
else if(n.getNodeName().equals("graph"))
- da = new GraphObject2();
+ da = GraphObject2.INSTANCE;
else if(n.getNodeName().equals("bundle")) {
String bundleId = null;
Node fc = n.getFirstChild();
public class GraphObject2 implements IDynamicAdapter2 {
+ public static final IDynamicAdapter2 INSTANCE = new GraphObject2();
+
@Override
public Class<?> getType() {
return ReadGraph.class;
public class ThisResource2 implements IDynamicAdapter2 {
+ public static IDynamicAdapter2 INSTANCE = new ThisResource2();
+
@Override
public Class<?> getType() {
return Resource.class;
</with>
</activeWhen>
</handler>
+ <handler
+ class="org.simantics.diagram.handler.CanvasCommandDelegate"
+ commandId="copyAsSVG">
+ <activeWhen>
+ <reference definitionId="org.simantics.modeling.ui.diagram.active" />
+ </activeWhen>
+ </handler>
<handler
class="org.simantics.diagram.handler.CanvasCommandDelegate"
commandId="org.eclipse.ui.edit.rename">
import org.simantics.utils.ui.ErrorLogger;
public class ConnectionCrossingsParticipant extends AbstractDiagramParticipant {
- private static final String CONNECTION_CROSSINGS_NODE_KEY = "connection-crossings";
+ public static final String CONNECTION_CROSSINGS_NODE_KEY = "connection-crossings";
private ConnectionCrossingsNode ccNode;
private final ConnectionCrossings crossings = new ConnectionCrossings();
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
+ * 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.Font;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGeneratorContext.GraphicContextDefaults;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.simantics.diagram.elements.TextNode;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
+import org.simantics.g2d.diagram.participant.Selection;
+import org.simantics.g2d.element.ElementHints;
+import org.simantics.g2d.element.ElementUtils;
+import org.simantics.g2d.element.IElement;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.G2DNode;
+import org.simantics.scenegraph.g2d.G2DSceneGraph;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
+import org.simantics.scenegraph.g2d.events.command.CommandEvent;
+import org.simantics.scenegraph.g2d.events.command.Commands;
+import org.simantics.scenegraph.g2d.nodes.LinkNode;
+import org.simantics.scenegraph.g2d.nodes.SelectionNode;
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
+import org.simantics.scenegraph.utils.NodeMapper;
+import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.utils.ui.ErrorLogger;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class CopyAsSVGParticipant extends AbstractDiagramParticipant {
+
+ @Dependency
+ protected Selection sel;
+
+ @EventHandler(priority = 0)
+ public boolean handleCommand(CommandEvent e) {
+ if (e.command.equals(Commands.COPY_AS_SVG)) {
+ Set<IElement> ss = sel.getSelection(0);
+ copyAsSVG(getContext(), ss);
+ return true;
+ }
+ return false;
+ }
+
+ private static void copyAsSVG(ICanvasContext canvasContext, Set<IElement> elements) {
+ G2DSceneGraph sg = canvasContext.getSceneGraph();
+ NodeMapper clipboardNodeMapper = new NodeMapper();
+ List<G2DNode> selectionRenderingDisabledNodes = new ArrayList<G2DNode>();
+ SingleElementNode clipboardNode = sg.addNode("svg-clipboard-temp", SingleElementNode.class);
+
+ try {
+ for (IElement e : elements) {
+ INode node = e.getHint(ElementHints.KEY_SG_NODE);
+ if (node != null) {
+ // Don't render selection. Selection rendering could be a global rendering hint that is adhered by nodes!
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setIgnoreSelection(true);
+ selectionRenderingDisabledNodes.add(n);
+ }
+ for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
+ n.setIgnore(true);
+ selectionRenderingDisabledNodes.add(n);
+ }
+ for(TextNode n : NodeUtil.collectNodes(node, TextNode.class)) {
+ n.setShowSelection(false);
+ selectionRenderingDisabledNodes.add(n);
+ }
+
+ String nodeId = clipboardNodeMapper.add(node);
+ LinkNode delegate = clipboardNode.addNode(ElementUtils.generateNodeId(e), LinkNode.class);
+ delegate.setDelegateId( nodeId );
+ }
+ }
+
+ DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+
+ String svgNS = "http://www.w3.org/2000/svg";
+ Document document = domImpl.createDocument(svgNS, "svg", null);
+
+ GraphicContextDefaults gcDefaults = new GraphicContextDefaults();
+ SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
+ Map<java.awt.RenderingHints.Key, Object> hintMap = new HashMap<java.awt.RenderingHints.Key, Object>();
+
+ hintMap.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ hintMap.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ hintMap.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ hintMap.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
+ hintMap.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+
+ gcDefaults.setRenderingHints(new RenderingHints(hintMap));
+ gcDefaults.setFont(Font.decode(null));
+ ctx.setGraphicContextDefaults(gcDefaults);
+
+ SVGGraphics2D svgG2D = new SVGGraphics2D(ctx, false);
+
+ StringWriter writer = new StringWriter();
+
+ // Track connection crossings manually since we will render only the clipboard node.
+ sg.getNode(ConnectionCrossingsParticipant.CONNECTION_CROSSINGS_NODE_KEY).render(svgG2D);
+ clipboardNode.render(svgG2D);
+
+ Element root = svgG2D.getRoot();
+
+ Rectangle2D bounds = clipboardNode.getBoundsInLocal(true);
+ if (bounds != null) {
+ root.setAttributeNS(null, "viewBox", bounds.getMinX() + " " + bounds.getMinY() + " " + bounds.getWidth() + " " + bounds.getHeight());
+ root.setAttributeNS(null, "height", Double.toString(bounds.getHeight()));
+ root.setAttributeNS(null, "width", Double.toString(bounds.getWidth()));
+ }
+
+ try {
+ svgG2D.stream(root, writer, false, false);
+ } catch (SVGGraphics2DIOException e1) {
+ ErrorLogger.defaultLogError("Failed to copy the diagram selection as SVG." , e1);
+ }
+
+ byte[] svgContent = writer.toString().getBytes(StandardCharsets.UTF_8);
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ Clipboard cb = new Clipboard(Display.getCurrent());
+ cb.setContents(new byte[][] {svgContent},
+ new Transfer[] {
+ SVGTransfer.getInstance()
+ }
+ );
+ }
+ });
+
+ } finally {
+ clipboardNode.removeNodes();
+ clipboardNodeMapper.clear();
+ clipboardNode.remove();
+
+ // Restore the selection rendering state for changed nodes.
+ for (G2DNode n : selectionRenderingDisabledNodes) {
+ if (n instanceof RouteGraphNode) {
+ ((RouteGraphNode) n).setIgnoreSelection(false);
+ } else if (n instanceof SelectionNode) {
+ ((SelectionNode)n).setIgnore(false);
+ } else if (n instanceof TextNode) {
+ ((TextNode)n).setShowSelection(true);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2020 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.participant;
+
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+
+public class SVGTransfer extends ByteArrayTransfer {
+ private static SVGTransfer instance = new SVGTransfer();
+ private static final String TYPE_NAME = "image/svg+xml";
+ private static final int TYPE_ID = registerType(TYPE_NAME);
+
+ public static byte[] formatContent(String svg) {
+ return svg.getBytes(StandardCharsets.UTF_8);
+ }
+
+ public static SVGTransfer getInstance () {
+ return instance;
+ }
+
+ @Override
+ protected int[] getTypeIds(){
+ return new int[] {TYPE_ID};
+ }
+
+ @Override
+ protected String[] getTypeNames(){
+ return new String[] {TYPE_NAME};
+ }
+}
\ No newline at end of file
import org.simantics.diagram.layer.ILayersViewPage;
import org.simantics.diagram.participant.ConnectionCrossingsParticipant;
import org.simantics.diagram.participant.ContextUtil;
+import org.simantics.diagram.participant.CopyAsSVGParticipant;
import org.simantics.diagram.participant.PointerInteractor2;
import org.simantics.diagram.participant.SGFocusParticipant;
import org.simantics.diagram.query.DiagramRequests;
//ctx.add(new TooltipParticipant());
ctx.add(new TerminalTooltipParticipant());
ctx.add(new ConnectionCrossingsParticipant(getInputResource()));
+ ctx.add(new CopyAsSVGParticipant());
}
protected void addPainterParticipants(ICanvasContext ctx) {
});
END(task);
} catch (Throwable t) {
- viewer = null;
LOGGER.error("Failed to complete loading of diagram {} in the canvas thread", viewer.diagramResource, t);
+ viewer = null;
}
}
});
Rectangle2D bounds = null;
while(it.hasNext()) {
IG2DNode node = it.next();
- Rectangle2D b = node.getBounds();
+ Rectangle2D b = node.getBoundsInLocal(ignoreNulls);
if(b == null && !ignoreNulls)
return null;
if(b != null) {
if(!GeometryUtils.isUndefinedRectangle(b)) {
+ b = node.localToParent(b);
if(bounds == null) {
bounds = b.getFrame();
} else {
public static final Command FOCUS_TOOLTIP = new Command("focusTooltip");
+ public static final Command COPY_AS_SVG = new Command("copyAsSVG");
public static Command showPopup(Point2D atControlPosition) {
return new ShowPopup(atControlPosition);
@Override
public Rectangle2D getBoundsInLocal() {
+ return getBoundsInLocal(false);
+ }
+
+ @Override
+ public Rectangle2D getBoundsInLocal(boolean ignoreNulls) {
// Safety against cyclic cases.
if (hasFlags(IN_GET_BOUNDS))
return new Rectangle2D.Double();
setFlags(IN_GET_BOUNDS);
try {
- Rectangle2D bounds = n.getBoundsInLocal();
+ Rectangle2D bounds = n.getBoundsInLocal(ignoreNulls);
if (transform != null && !transform.isIdentity())
bounds = transform.createTransformedShape(bounds).getBounds2D();
return bounds;
*/
public static HistoryImportResult importHistoryArchive(HistoryManager history, Path path) throws IOException, HistoryException {
HistoryImportResult result = new HistoryImportResult();
- try (RandomAccessBinary rab = new BinaryFile(path.toFile())) {
+ try (RandomAccessBinary rab = new BinaryFile(path.toFile(), "r")) {
importHistoryArchive(history, rab, result);
return result;
} catch (IOException e) {
@Override
public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-
- Resource type = context.getPossibleType(graph);
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+ Resource type = context.getPossibleType(graph, STR.Component);
if(type == null) return null;
StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
}
return map;
} else if (StructuralComponentClass.DEFINED.equals(clazz)) {
- StructuralResource2 STR = StructuralResource2.getInstance(graph);
Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(def), TransientCacheListener.instance());
return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
importJava "org.simantics.tests.modelled.ui.TestsUIUtils" where
runSTSTestAction :: Resource -> <Proc> ()
- ignoreSTSTestAction :: [Resource] -> <Proc> ()
+ ignoreSTSTestAction :: Resource -> <Proc> ()
createSTSSuiteAction :: Resource -> <Proc> ()
createSTSSuiteAction res = do
package org.simantics.tests.modelled.ui;
import java.io.IOException;
-import java.util.List;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.simantics.Simantics;
view.execute();
}
- public static void ignoreSTSTestAction(List<Resource> tests) throws DatabaseException {
+ public static void ignoreSTSTestAction(Resource test) throws DatabaseException {
Simantics.getSession().syncRequest(new Write() {
@Override
public void perform(WriteGraph graph) throws DatabaseException {
TestsResource TESTS = TestsResource.getInstance(graph);
- for (Resource test : tests) {
- graph.claimLiteral(test, TESTS.ignore, true, Bindings.BOOLEAN);
- }
+ graph.claimLiteral(test, TESTS.ignore, true, Bindings.BOOLEAN);
}
});
}