X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=org.simantics.district.network.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fnetwork%2Fui%2Fparticipants%2FDynamicVisualisationContributionsParticipant.java;h=36eaaf619f618e8e0bd9d572018e8ce7a251e2c2;hb=10cc983e56eaadd88e66aca478918a4bd841fdfd;hp=690860620059dc9c7802b2bf7bfa0468c840692b;hpb=fb4e5f02481e918807be83e87239a4d91b4343f2;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java index 69086062..36eaaf61 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java @@ -1,27 +1,54 @@ package org.simantics.district.network.ui.participants; import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; import java.util.Map; +import java.util.Set; +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.DeferredRenderingNode; +import org.simantics.district.network.ui.nodes.DistrictNetworkEdgeArrayNode; +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.scenegraph.INode; 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.Pair; 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(); @@ -31,10 +58,12 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas } } }; - + private DynamicVisualisationContributionsNode node; private AffineTransform transform; - + private DistrictNetworkHoverInfoNode hoverInfoNode; + private DeferredRenderingNode deferredEdgeArrowRendererNode; + public DynamicVisualisationContributionsParticipant(AffineTransform tr) { this.transform = tr; } @@ -47,9 +76,14 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas 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) { + // Ensure hover polling is stopped + if (hoverUpdateSchedule != null && !hoverUpdateSchedule.isDone()) { + hoverUpdateSchedule.cancel(false); + } + 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); @@ -63,8 +97,16 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas 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); + + Pair> dearn = DistrictNetworkEdgeArrayNode.renderer(); + deferredEdgeArrowRendererNode = parent.addNode(dearn.first, dearn.second); } - + @EventHandler(priority = 0) protected boolean handleKeyEvent(CommandEvent e) { if (e.command.equals(DistrictDiagramViewer.MAP_COLOR_BAR_OPTIONS_CHANGE)) { @@ -73,20 +115,7 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas } 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()); @@ -94,23 +123,102 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas node.setSizeBarOptions(getSizeBarOptions()); } - private Map getDynamicColoringObjects() { - Map objects = getHint(DistrictDiagramViewer.KEY_MAP_COLORING_OBJECTS); - return objects; + private Map getDynamicColoringObjects() { + return getHint(DistrictDiagramViewer.KEY_MAP_COLORING_OBJECTS); } private ColorBarOptions getColorBarOptions() { - ColorBarOptions options = getHint(DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS); - return options; + return getHint(DistrictDiagramViewer.KEY_MAP_COLOR_BAR_OPTIONS); } private Map getDynamicSizingObjects() { - Map objects = getHint(DistrictDiagramViewer.KEY_MAP_SIZING_OBJECTS); - return objects; + return getHint(DistrictDiagramViewer.KEY_MAP_SIZING_OBJECTS); } private SizeBarOptions getSizeBarOptions() { - SizeBarOptions options = getHint(DistrictDiagramViewer.KEY_MAP_SIZE_BAR_OPTIONS); - return options; + return getHint(DistrictDiagramViewer.KEY_MAP_SIZE_BAR_OPTIONS); + } + + private ScheduledFuture hoverUpdateSchedule; + private static final Object COMPLETE = new Object(); + + public void hoverNode(Resource runtimeDiagram, Resource mapElement, INode hoveredNode, int zoomLevel) { + 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; + cancelCurrentHoverUpdate(); + hoverUpdateSchedule = ThreadUtils.getNonBlockingWorkExecutor().scheduleWithFixedDelay( + () -> updateHoverInfo(runtimeDiagram, mapElement, hoveredNode, zoomLevel, visualisation, thread), + 0, + visualisation.getInterval(), + TimeUnit.MILLISECONDS); + } + }); } + + private void updateHoverInfo(Resource runtimeDiagram, Resource mapElement, INode hoveredNode, int zoomLevel, DynamicVisualisation visualisation, IThreadWorkQueue thread) { + CompletableFuture future = new CompletableFuture<>(); + try { + Simantics.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Set mapElementTypes = graph.getTypes(mapElement); + if (mapElementTypes.isEmpty()) { + future.complete(COMPLETE); + return; + } + + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + + boolean doHover = + (mapElementTypes.contains(DN.Vertex) && visualisation.isKeyVariablesVertexHover()) + || (mapElementTypes.contains(DN.Edge) && visualisation.isKeyVariablesEdgesHover()); + + StyleResult results = DistrictNetworkHoverInfoStyle.doCalculateStyleResult(graph, runtimeDiagram, mapElement); + if (results != null) { + Point2D location = DistrictNetworkHoverInfoStyle.calculatePoint(hoveredNode, zoomLevel, null); + thread.asyncExec(() -> { + if (isRemoved()) + return; + if (doHover) { + hoverInfoNode.setLabels(results.getLabels()); + hoverInfoNode.setOrigin(results.getOrigin()); + hoverInfoNode.setMousePosition(location); + hoverInfoNode.setHoveredNode(hoveredNode); + } else { + hoverInfoNode.setHoveredNode(null); + } + future.complete(COMPLETE); + }); + } else { + future.complete(COMPLETE); + } + } + }); + } catch (DatabaseException e) { + future.completeExceptionally(e); + } + // this waits until everything is done + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + LOGGER.debug("Interrupted hovering", e); + } + } + + public boolean doHover(boolean hover, boolean isConnectionTool) { + if (!hover) + cancelCurrentHoverUpdate(); + return hoverInfoNode.hover(hover, isConnectionTool); + } + + private void cancelCurrentHoverUpdate() { + if (hoverUpdateSchedule != null && !hoverUpdateSchedule.isDone()) + hoverUpdateSchedule.cancel(false); + } + }