package org.simantics.district.network.ui.participants; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.network.profile.RuntimeDynamicVisualisationsRequest; import org.simantics.district.network.ui.DistrictDiagramViewer; import org.simantics.district.network.ui.nodes.DistrictNetworkHoverInfoNode; import org.simantics.district.network.ui.nodes.DynamicVisualisationContributionsNode; import org.simantics.district.network.ui.styles.DistrictNetworkHoverInfoStyle; import org.simantics.district.network.ui.styles.DistrictNetworkHoverInfoStyle.StyleResult; import org.simantics.district.network.visualisations.model.ColorBarOptions; import org.simantics.district.network.visualisations.model.DynamicColorContribution; import org.simantics.district.network.visualisations.model.DynamicSizeContribution; import org.simantics.district.network.visualisations.model.DynamicVisualisation; import org.simantics.district.network.visualisations.model.SizeBarOptions; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; import org.simantics.layer0.Layer0; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.command.CommandEvent; import org.simantics.utils.datastructures.hints.HintListenerAdapter; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintListener; import org.simantics.utils.datastructures.hints.IHintObservable; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.threads.ThreadUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DynamicVisualisationContributionsParticipant extends AbstractCanvasParticipant { private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationContributionsParticipant.class); IHintListener hintListener = new HintListenerAdapter() { public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { ICanvasContext cc = getContext(); if (cc != null) { updateNode(); cc.getContentContext().setDirty(); } } }; private DynamicVisualisationContributionsNode node; private AffineTransform transform; private DistrictNetworkHoverInfoNode hoverInfoNode; public DynamicVisualisationContributionsParticipant(AffineTransform tr) { this.transform = tr; } @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); getHintStack().addKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_COLORING_OBJECTS, hintListener); getHintStack().addKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS, hintListener); getHintStack().addKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_SIZING_OBJECTS, hintListener); getHintStack().addKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_SIZE_BAR_OPTIONS, hintListener); } @Override public void removedFromContext(ICanvasContext ctx) { getHintStack().removeKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_COLORING_OBJECTS, hintListener); getHintStack().removeKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS, hintListener); getHintStack().removeKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_SIZING_OBJECTS, hintListener); getHintStack().removeKeyHintListener(getThread(), DistrictDiagramViewer.KEY_MAP_SIZE_BAR_OPTIONS, hintListener); super.removedFromContext(ctx); } @SGInit public void initSG(G2DParentNode parent) { node = parent.addNode(DynamicVisualisationContributionsNode.ID, DynamicVisualisationContributionsNode.class); node.setTransform(transform); node.setEnabled(true); node.setZIndex(1000); hoverInfoNode = parent.addNode("districtNetworkHoverInfoNode", DistrictNetworkHoverInfoNode.class); hoverInfoNode.setLookupId("districtNetworkHoverInfoNode"); hoverInfoNode.setTransform(transform); hoverInfoNode.setZIndex(Integer.MAX_VALUE - 500); } @EventHandler(priority = 0) protected boolean handleKeyEvent(CommandEvent e) { if (e.command.equals(DistrictDiagramViewer.MAP_COLOR_BAR_OPTIONS_CHANGE)) { System.out.println(e); return true; } return false; } // @Override // protected boolean handleCommand(CommandEvent e) { // if (e.command.equals(DistrictDiagramViewer.MAP_COLOR_BAR_OPTIONS_CHANGE)) { // ICanvasContext context = (ICanvasContext) e.getContext(); // ColorBarOptions options = context.getHintStack().getHint(DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS); // this.colorBarsOptions = options; // repaint(); // return true; // } else { // return super.handleCommand(e); // } // } protected void updateNode() { node.setDynamicColoringObjects(getDynamicColoringObjects()); node.setColorBarOptions(getColorBarOptions()); node.setDynamicSizingObjects(getDynamicSizingObjects()); node.setSizeBarOptions(getSizeBarOptions()); } private Map getDynamicColoringObjects() { Map objects = getHint(DistrictDiagramViewer.KEY_MAP_COLORING_OBJECTS); return objects; } private ColorBarOptions getColorBarOptions() { ColorBarOptions options = getHint(DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS); return options; } private Map getDynamicSizingObjects() { Map objects = getHint(DistrictDiagramViewer.KEY_MAP_SIZING_OBJECTS); return objects; } private SizeBarOptions getSizeBarOptions() { SizeBarOptions options = getHint(DistrictDiagramViewer.KEY_MAP_SIZE_BAR_OPTIONS); return options; } private ScheduledFuture hoverUpdateSchedule; public void hoverNode(Resource runtimeDiagram, Resource mapElement, G2DParentNode hoveredNode) { IThreadWorkQueue thread = getThread(); Simantics.getSession().asyncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { DynamicVisualisation visualisation = graph.syncRequest(new RuntimeDynamicVisualisationsRequest(runtimeDiagram)); if (visualisation == null) return; if (hoverUpdateSchedule != null && !hoverUpdateSchedule.isDone()) { hoverUpdateSchedule.cancel(false); } hoverUpdateSchedule = ThreadUtils.getNonBlockingWorkExecutor().scheduleWithFixedDelay(() -> { CompletableFuture future = new CompletableFuture<>(); try { Simantics.getSession().syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { boolean keyVariablesVertexHover = visualisation.isKeyVariablesVertexHover(); boolean keyVariablesEdgesHover = visualisation.isKeyVariablesEdgesHover(); Resource mapElementInstanceOf = graph.getSingleObject(mapElement, Layer0.getInstance(graph).InstanceOf); DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); boolean doHover = true; if (mapElementInstanceOf.equals(DN.Vertex) && !keyVariablesVertexHover) { doHover = false; } else if (mapElementInstanceOf.equals(DN.Edge) && !keyVariablesEdgesHover) { doHover = false; } final boolean finalDoHover = doHover; StyleResult results = DistrictNetworkHoverInfoStyle.doCalculateStyleResult(graph, runtimeDiagram, mapElement); if (results != null) { Point2D location = DistrictNetworkHoverInfoStyle.calculatePoint(graph, mapElement); thread.asyncExec(() -> { if (isRemoved()) return; if (finalDoHover) { hoverInfoNode.setLabels(results.getLabels()); hoverInfoNode.setOrigin(results.getOrigin()); hoverInfoNode.setMousePosition(location); hoverInfoNode.hover2(hoveredNode); } else { hoverInfoNode.hover2(null); } future.complete(new Object()); }); } else { future.complete(new Object()); } } }); } catch (DatabaseException e) { future.completeExceptionally(e); } // this waits until everything is done try { future.get(); } catch (InterruptedException | ExecutionException e) { LOGGER.debug("Interrupted hovering", e); } }, 0, visualisation.getInterval(), TimeUnit.MILLISECONDS); } }); } public boolean doHover(boolean hover, boolean isConnectionTool) { return hoverInfoNode.hover(hover, isConnectionTool); } }