From dab24824da1b284b8a4734a069cfba72fb1f05de Mon Sep 17 00:00:00 2001 From: jsimomaa Date: Mon, 2 Sep 2019 09:16:30 +0300 Subject: [PATCH] First version of district visualisations TODO: * Saving of visualisation templates * Disabling dynamic updates * "Gappless" color/size values from maps * Show/Hide ticks of color bars * Perfomance tuning gitlab #59 APROS-15038 APROS-15527 APROS-15528 Change-Id: I739d1b677351084c88820579a3a0ef3c985b8886 --- .../graph/DistrictNetwork.pgraph | 56 ++ .../DistrictNetworkDiagramSettings.pgraph | 3 + .../graph/DistrictNetworkProfiles.pgraph | 1 + .../ontology/DistrictNetworkResource.java | 222 +++++ .../META-INF/MANIFEST.MF | 3 +- .../fragment.e4xmi | 2 + org.simantics.district.network.ui/plugin.xml | 16 + .../network/ui/DistrictDiagramViewer.java | 242 +++++- ...DynamicVisualisationContributionsNode.java | 344 ++++++++ ...VisualisationContributionsParticipant.java | 116 +++ .../network/ui/table/ImportCSVHandler.java | 2 +- .../DynamicVisualisationsUI.java | 778 ++++++++++++++++++ .../DynamicVisualisationsView.java | 86 ++ .../META-INF/MANIFEST.MF | 7 +- org.simantics.district.network/adapters.xml | 3 + .../ColorContribution.scl | 21 + .../DynamicVisualisations/ColorMap.scl | 0 .../SizeContribution.scl | 13 + .../DynamicVisualisations/SizeMap.scl | 0 .../district/network/DistrictNetworkUtil.java | 214 +++++ .../network/profile/DNElementColorStyle.java | 77 +- .../network/profile/DNElementSizeStyle.java | 127 +++ .../profile/DynamicVisualisationsRequest.java | 43 + .../RuntimeDynamicVisualisationsRequest.java | 30 + .../DynamicVisualisationsContributions.java | 278 +++++++ .../VisualisationColoringObject.java | 56 ++ .../visualisations/model/ColorBarOptions.java | 67 ++ .../model/DynamicColorContribution.java | 83 ++ .../visualisations/model/DynamicColorMap.java | 70 ++ .../model/DynamicSizeContribution.java | 83 ++ .../visualisations/model/DynamicSizeMap.java | 38 + .../model/DynamicVisualisation.java | 37 + .../visualisations/model/SizeBarOptions.java | 66 ++ 33 files changed, 3174 insertions(+), 10 deletions(-) create mode 100644 org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DynamicVisualisationContributionsNode.java create mode 100644 org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java create mode 100644 org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsUI.java create mode 100644 org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsView.java create mode 100644 org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorContribution.scl create mode 100644 org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorMap.scl create mode 100644 org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeContribution.scl create mode 100644 org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeMap.scl create mode 100644 org.simantics.district.network/src/org/simantics/district/network/profile/DNElementSizeStyle.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/profile/DynamicVisualisationsRequest.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/profile/RuntimeDynamicVisualisationsRequest.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/VisualisationColoringObject.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/ColorBarOptions.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorContribution.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorMap.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeContribution.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeMap.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicVisualisation.java create mode 100644 org.simantics.district.network/src/org/simantics/district/network/visualisations/model/SizeBarOptions.java diff --git a/org.simantics.district.network.ontology/graph/DistrictNetwork.pgraph b/org.simantics.district.network.ontology/graph/DistrictNetwork.pgraph index 2a64b3dc..128904c8 100644 --- a/org.simantics.district.network.ontology/graph/DistrictNetwork.pgraph +++ b/org.simantics.district.network.ontology/graph/DistrictNetwork.pgraph @@ -156,6 +156,10 @@ DN.RightClickDefaultMapping -- DN.Diagram.Visualisations.ShowColorBars + @defProperty "Show Color Bars" L0.Boolean + >-- DN.Diagram.Visualisations.ShowColorBarTicks + @defProperty "Show Color Bar Ticks" L0.Boolean + >-- DN.Diagram.Visualisations.ColorBarLocation + @defProperty "Color Bar Location" L0.String + >-- DN.Diagram.Visualisations.ColorBarSize + @defProperty "Color Bar Size" L0.String + >-- DN.Diagram.Visualisations.ShowSizeBars + @defProperty "Show Size Bars" L0.Boolean + >-- DN.Diagram.Visualisations.ShowSizeBarTicks + @defProperty "Show Size Bar Ticks" L0.Boolean + >-- DN.Diagram.Visualisations.SizeBarLocation + @defProperty "Size Bar Location" L0.String + >-- DN.Diagram.Visualisations.SizeBarSize + @defProperty "Size Bar Size" L0.String + +DN.Diagram.Visualisations.colorContributions -- DN.Diagram.drawMapEnabled ==> "Boolean" -- DN.Diagram.hasVisualisation --> DN.Diagram.Visualisations -- DN.Diagram.profileUpdateInterval ==> "Long" + @@ -48,5 +49,6 @@ + diff --git a/org.simantics.district.network.ui/plugin.xml b/org.simantics.district.network.ui/plugin.xml index 1e596f54..b8a712d8 100644 --- a/org.simantics.district.network.ui/plugin.xml +++ b/org.simantics.district.network.ui/plugin.xml @@ -40,6 +40,22 @@ restorable="true" allowMultiple="false"> + + + + diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java index 68b7aa79..cc5b24e1 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java @@ -2,6 +2,7 @@ package org.simantics.district.network.ui; import java.awt.Color; import java.awt.geom.AffineTransform; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Supplier; @@ -15,8 +16,13 @@ import org.simantics.db.procedure.Listener; import org.simantics.diagram.ui.DiagramModelHints; import org.simantics.district.network.DistrictNetworkUtil; import org.simantics.district.network.ui.participants.DNPointerInteractor; +import org.simantics.district.network.ui.participants.DynamicVisualisationContributionsParticipant; import org.simantics.district.network.ui.participants.ElevationServerParticipant; import org.simantics.district.network.ui.participants.MapRulerPainter; +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.SizeBarOptions; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.CanvasContext; import org.simantics.g2d.diagram.handler.PickRequest.PickFilter; @@ -34,9 +40,12 @@ import org.simantics.maps.MapScalingTransform; import org.simantics.maps.eclipse.MapPainter; import org.simantics.maps.sg.commands.MapCommands; import org.simantics.modeling.ui.diagramEditor.DiagramViewer; +import org.simantics.scenegraph.g2d.events.command.Command; import org.simantics.scenegraph.g2d.events.command.CommandEvent; import org.simantics.scenegraph.g2d.events.command.Commands; 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.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,6 +66,7 @@ public class DistrictDiagramViewer extends DiagramViewer { ctx.add(new NetworkDrawingParticipant(tr)); ctx.add(new ElevationServerParticipant(tr)); + ctx.add(new DynamicVisualisationContributionsParticipant(tr)); } protected String getPopupId() { @@ -105,6 +115,10 @@ public class DistrictDiagramViewer extends DiagramViewer { // super.loadPageSettings() does async-db-operations setupDrawMapEnabled(); setupBackgroundColor(); + setupColoringObjects(); + setupColorBarOptions(); + setupSizingObjects(); + setupSizeBarOptions(); } private void setupDrawMapEnabled() { @@ -118,7 +132,7 @@ public class DistrictDiagramViewer extends DiagramViewer { result -> queueBackgroundColorChangeEvent(result), () -> DistrictDiagramViewer.this.isDisposed())); } - + private void queueBackgroundColorChangeEvent(RGB.Integer result) { if (result != null) { Color backgroundColor = new Color(result.red, result.green, result.blue); @@ -127,6 +141,72 @@ public class DistrictDiagramViewer extends DiagramViewer { } } + private void setupColoringObjects() { + sessionContext.getSession().asyncRequest(new ColoringObjectsRequest(getInputResource()), new ColoringObjectsListener( + result -> queueColoringObjectsChangeEvent(result), + () -> DistrictDiagramViewer.this.isDisposed())); + } + + + private void setupColorBarOptions() { + sessionContext.getSession().asyncRequest(new ColorBarOptionsRequest(getInputResource()), new ColorBarOptionsListener( + result -> queueColorBarOptionsChangeEvent(result), + () -> DistrictDiagramViewer.this.isDisposed())); + } + + private void setupSizingObjects() { + sessionContext.getSession().asyncRequest(new SizingObjectsRequest(getInputResource()), new SizingObjectsListener( + result -> queueSizingObjectsChangeEvent(result), + () -> DistrictDiagramViewer.this.isDisposed())); + } + + + private void setupSizeBarOptions() { + sessionContext.getSession().asyncRequest(new SizeBarOptionsRequest(getInputResource()), new SizeBarOptionsListener( + result -> queueSizeBarOptionsChangeEvent(result), + () -> DistrictDiagramViewer.this.isDisposed())); + } + + public static final Key KEY_MAP_COLOR_BAR_OPTIONS = new KeyOf(ColorBarOptions.class, "colorBarOptions"); + public static final Command MAP_COLOR_BAR_OPTIONS_CHANGE = new Command("colorBarOptionsChange"); + public static final Key KEY_MAP_SIZE_BAR_OPTIONS = new KeyOf(SizeBarOptions.class, "sizeBarOptions"); + public static final Command MAP_SIZE_BAR_OPTIONS_CHANGE = new Command("sizeBarOptionsChange"); + + public static final Key KEY_MAP_COLORING_OBJECTS = new KeyOf(Map.class, "coloringObjects"); + public static final Command MAP_COLORING_OBJECTS_CHANGE = new Command("coloringObjectsChange"); + + public static final Key KEY_MAP_SIZING_OBJECTS = new KeyOf(Map.class, "sizingObjects"); + public static final Command MAP_SIZING_OBJECTS_CHANGE = new Command("sizingObjectsChange"); + + + private void queueColoringObjectsChangeEvent(Map result) { + if (result != null) { + canvasContext.getDefaultHintContext().setHint(KEY_MAP_COLORING_OBJECTS, result); + canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MAP_COLORING_OBJECTS_CHANGE)); + } + } + + private void queueColorBarOptionsChangeEvent(ColorBarOptions result) { + if (result != null) { + canvasContext.getDefaultHintContext().setHint(KEY_MAP_COLOR_BAR_OPTIONS, result); + canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MAP_COLOR_BAR_OPTIONS_CHANGE)); + } + } + + private void queueSizingObjectsChangeEvent(Map result) { + if (result != null) { + canvasContext.getDefaultHintContext().setHint(KEY_MAP_SIZING_OBJECTS, result); + canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MAP_SIZING_OBJECTS_CHANGE)); + } + } + + private void queueSizeBarOptionsChangeEvent(SizeBarOptions result) { + if (result != null) { + canvasContext.getDefaultHintContext().setHint(KEY_MAP_SIZE_BAR_OPTIONS, result); + canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MAP_SIZE_BAR_OPTIONS_CHANGE)); + } + } + private static class DrawMapEnabledRequest extends UnaryRead { public DrawMapEnabledRequest(Resource diagram) { @@ -206,4 +286,164 @@ public class DistrictDiagramViewer extends DiagramViewer { return isDisposed.get(); } } + + private static class ColorBarOptionsRequest extends UnaryRead { + + public ColorBarOptionsRequest(Resource diagram) { + super(diagram); + } + + @Override + public ColorBarOptions perform(ReadGraph graph) throws DatabaseException { + return DistrictNetworkUtil.colorBarOptions(graph, parameter); + } + } + + private static class ColoringObjectsRequest extends UnaryRead> { + + public ColoringObjectsRequest(Resource diagram) { + super(diagram); + } + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + return DistrictNetworkUtil.colorContributions(graph, parameter); + } + } + + private static class ColoringObjectsListener implements Listener> { + + private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); + + private Consumer> callback; + private Supplier isDisposed; + + public ColoringObjectsListener(Consumer> callback, Supplier isDisposed) { + this.callback = callback; + this.isDisposed = isDisposed; + } + + @Override + public void execute(Map result) { + callback.accept(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Could not listen ColorBarOptions", t); + } + + @Override + public boolean isDisposed() { + return isDisposed.get(); + } + } + + private static class ColorBarOptionsListener implements Listener { + + private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); + + private Consumer callback; + private Supplier isDisposed; + + public ColorBarOptionsListener(Consumer callback, Supplier isDisposed) { + this.callback = callback; + this.isDisposed = isDisposed; + } + + @Override + public void execute(ColorBarOptions result) { + callback.accept(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Could not listen ColorBarOptions", t); + } + + @Override + public boolean isDisposed() { + return isDisposed.get(); + } + } + + private static class SizeBarOptionsRequest extends UnaryRead { + + public SizeBarOptionsRequest(Resource diagram) { + super(diagram); + } + + @Override + public SizeBarOptions perform(ReadGraph graph) throws DatabaseException { + return DistrictNetworkUtil.sizeBarOptions(graph, parameter); + } + } + + private static class SizeBarOptionsListener implements Listener { + + private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); + + private Consumer callback; + private Supplier isDisposed; + + public SizeBarOptionsListener(Consumer callback, Supplier isDisposed) { + this.callback = callback; + this.isDisposed = isDisposed; + } + + @Override + public void execute(SizeBarOptions result) { + callback.accept(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Could not listen SizeBarOptions", t); + } + + @Override + public boolean isDisposed() { + return isDisposed.get(); + } + } + + private static class SizingObjectsRequest extends UnaryRead> { + + public SizingObjectsRequest(Resource diagram) { + super(diagram); + } + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + return DistrictNetworkUtil.sizeContributions(graph, parameter); + } + } + + private static class SizingObjectsListener implements Listener> { + + private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); + + private Consumer> callback; + private Supplier isDisposed; + + public SizingObjectsListener(Consumer> callback, Supplier isDisposed) { + this.callback = callback; + this.isDisposed = isDisposed; + } + + @Override + public void execute(Map result) { + callback.accept(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Could not listen ColorBarOptions", t); + } + + @Override + public boolean isDisposed() { + return isDisposed.get(); + } + } } diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DynamicVisualisationContributionsNode.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DynamicVisualisationContributionsNode.java new file mode 100644 index 00000000..53d7862c --- /dev/null +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DynamicVisualisationContributionsNode.java @@ -0,0 +1,344 @@ +package org.simantics.district.network.ui.nodes; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.simantics.district.network.visualisations.model.ColorBarOptions; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsLocation; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsSize; +import org.simantics.district.network.visualisations.model.DynamicColorContribution; +import org.simantics.district.network.visualisations.model.DynamicColorMap; +import org.simantics.district.network.visualisations.model.DynamicColorMap.RGBIntensity; +import org.simantics.district.network.visualisations.model.DynamicSizeContribution; +import org.simantics.district.network.visualisations.model.DynamicSizeMap; +import org.simantics.district.network.visualisations.model.SizeBarOptions; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsLocation; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsSize; +import org.simantics.scenegraph.g2d.G2DNode; +import org.simantics.scenegraph.utils.DPIUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DynamicVisualisationContributionsNode extends G2DNode { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationContributionsNode.class); + + public static final String ID = "dynamicVisualisationContributionsNode"; + + private static final long serialVersionUID = 7400966702826774761L; + + protected boolean enabled = true; + + private Map dynamicColoringContributions; + private Map dynamicSizingContributions; + + private ColorBarOptions colorBarsOptions = ColorBarOptions.useDefault(); + private SizeBarOptions sizeBarsOptions = SizeBarOptions.useDefault(); + + @Override + public void render(Graphics2D g2d) { + if (!enabled) + return; + + AffineTransform ot = g2d.getTransform(); + Color oldColor = g2d.getColor(); + + try { + g2d.transform(transform); + g2d.setTransform(new AffineTransform()); + + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + return; // FIXME + + renderColors(g2d); + renderSizes(g2d); + } finally { + g2d.setColor(oldColor); + g2d.setTransform(ot); + } + } + + private double colorBarBoxWidth = 300; + private double colorBarBoxHeight = 50; + private double colorBarBoxPadding = 20; + + private void renderColors(Graphics2D g2d) { + if (colorBarsOptions == null || !colorBarsOptions.isShowColorBars()) { + return; + } + ColorBarsLocation location = colorBarsOptions.getLocation(); + ColorBarsSize size = colorBarsOptions.getSize(); + double colorBarBoxLeft = getColorBarBoxLeft(g2d, location, size); + double colorBarBoxTopInitial = getColorBarBoxTop(g2d, location, size); + double colorBarBoxWidth = getColorBarBoxWidth(size); + double colorBarBoxHeight = getColorBarBoxHeight(size); + + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + return; // FIXME + + int i = 0; + + if (dynamicColoringContributions != null) { + for (Entry object : dynamicColoringContributions.entrySet()) { + DynamicColorContribution cc = object.getValue(); + + if (!cc.isUsed()) + break; + + double min = cc.getDefaultMin(); + double max = cc.getDefaultMax(); + String unit = cc.getUnit(); + String label = cc.getLabel(); + + DynamicColorMap map = cc.getDefaultColorMap(); + + double colorBarBoxTop = (colorBarBoxTopInitial + (colorBarBoxHeight * i)); + i++; + + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f)); + g2d.setColor(new Color(0.9f, 0.9f, 0.9f, 0.95f)); + + Rectangle2D vertical = new Rectangle2D.Double(colorBarBoxLeft, colorBarBoxTop, colorBarBoxWidth, colorBarBoxHeight); + g2d.fill(vertical); + + double colorVerticalLeft = colorBarBoxLeft + 5; + double colorVerticalTop = colorBarBoxTop + 15; + double colorVerticalHeigth = colorBarBoxHeight - 30; + List intensities = map.getIntensities(); + double colorVerticalWidth = (colorBarBoxWidth - 10) / intensities.size(); + + Font rulerFont = new Font("Tahoma", Font.PLAIN, DPIUtil.upscale(9)); + g2d.setFont(rulerFont); + g2d.setColor(Color.BLACK); + + String str = Double.toString(max); + g2d.drawString(str, (int)(colorBarBoxLeft + colorBarBoxWidth - 30), (int)(colorBarBoxTop + colorBarBoxHeight)); + + str = Double.toString(min); + g2d.drawString(str, (int)colorBarBoxLeft + 1, (int)(colorBarBoxTop + colorBarBoxHeight)); + + + for (RGBIntensity intensity : intensities) { + + g2d.setColor(new Color((float)intensity.getRed(), (float)intensity.getGreen(), (float)intensity.getBlue(), 1f)); + Rectangle2D colorVertical = new Rectangle2D.Double(colorVerticalLeft, colorVerticalTop, colorVerticalWidth, colorVerticalHeigth); + g2d.fill(colorVertical); + colorVerticalLeft = colorVerticalLeft + colorVerticalWidth; + } + g2d.setColor(Color.BLACK); + str = object.getKey() + " - " + label + " [" + unit + "]"; + g2d.drawString(str, (int)colorBarBoxLeft + 5, (int)colorBarBoxTop + 10); + } + } + } + + private double getColorBarBoxTop(Graphics2D g2d, ColorBarsLocation location, ColorBarsSize size) { + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + throw new IllegalStateException(); + switch (location) { + case NORTH: { + return colorBarBoxPadding; + } + case SOUTH: { + return bounds.getMaxY() - colorBarBoxPadding; + } + case EAST: + case WEST: { + return (bounds.getMaxY() / 2) - (getColorBarBoxHeight(size) / 2); + } + default: + return 0; + } + } + + private double getColorBarBoxLeft(Graphics2D g2d, ColorBarsLocation location, ColorBarsSize size) { + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + throw new IllegalStateException(); + switch (location) { + case EAST: { + double right = bounds.getMaxX() - colorBarBoxPadding; + return right - getColorBarBoxWidth(size); + } + case WEST: { + return colorBarBoxPadding; + } + case NORTH: + case SOUTH: { + double left = (bounds.getMaxX() / 2) - (getColorBarBoxWidth(size) / 2); + return left; + } + default: + return 0; + } + } + + private double getColorBarBoxWidth(ColorBarsSize size) { + return size.getSize() * colorBarBoxWidth; + } + + private double getColorBarBoxHeight(ColorBarsSize size) { + return size.getSize() * colorBarBoxHeight; + } + + private void renderSizes(Graphics2D g2d) { + if (sizeBarsOptions == null || !sizeBarsOptions.isShowSizeBars()) { + return; + } + SizeBarsLocation location = sizeBarsOptions.getLocation(); + SizeBarsSize sizeb = sizeBarsOptions.getSize(); + double sizeBarBoxLeft = getSizeBarBoxLeft(g2d, location, sizeb); + double sizeBarBoxTopInitial = getSizeBarBoxTop(g2d, location, sizeb); + double sizeBarBoxWidth = getSizeBarBoxWidth(sizeb); + double sizeBarBoxHeight = getSizeBarBoxHeight(sizeb); + + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + return; // FIXME + + int i = 0; + + for (Entry object : dynamicSizingContributions.entrySet()) { + DynamicSizeContribution cc = object.getValue(); + + double min = cc.getDefaultMin(); + double max = cc.getDefaultMax(); + String unit = cc.getUnit(); + String label = cc.getLabel(); + + DynamicSizeMap map = cc.getDefaultSizeMap(); + + List sizes = map.getSizes(); + + double sizeBarBoxTop = (sizeBarBoxTopInitial + (colorBarBoxHeight * i)); + i++; +// double backgroundBoxPaddingRight = 20; +// double backgroundBoxHeight = 50; +// double backgroundBoxWidth = 300; +// double backgroundBoxRight = bounds.getMaxX() - backgroundBoxPaddingRight; +// double backgroundBoxLeft = backgroundBoxRight - backgroundBoxWidth; +// double backgroundBoxTop = bounds.getMaxY();// + (initialPosition + (position * i)); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f)); + g2d.setColor(new Color(0.9f, 0.9f, 0.9f, 0.95f)); + + Rectangle2D vertical = new Rectangle2D.Double(sizeBarBoxLeft, sizeBarBoxTop, colorBarBoxWidth, colorBarBoxHeight); + g2d.fill(vertical); + + double sizeVerticalLeft = sizeBarBoxLeft + 5; + double sizeVerticalTop = sizeBarBoxTop + 15; + double sizeVerticalHeigth = colorBarBoxHeight - 30; + + double sizeVerticalWidth = (sizeBarBoxWidth - 10) / sizes.size(); + + Font rulerFont = new Font("Tahoma", Font.PLAIN, DPIUtil.upscale(9)); + g2d.setFont(rulerFont); + g2d.setColor(Color.BLACK); + + String str = Double.toString(max); + g2d.drawString(str, (int)(sizeBarBoxLeft + sizeBarBoxWidth - 30), (int)(sizeBarBoxTop + sizeBarBoxHeight)); + + str = Double.toString(min); + g2d.drawString(str, (int)sizeBarBoxLeft + 1, (int)(sizeBarBoxTop + sizeBarBoxHeight)); + + + g2d.setColor(new Color((float)0, (float)0, (float)0.8, 0.8f)); + for (Double size: sizes) { + + Ellipse2D ellipse = new Ellipse2D.Double(sizeVerticalLeft + sizeVerticalWidth / 2, (sizeVerticalTop), size * sizeVerticalHeigth, size * sizeVerticalHeigth); + g2d.fill(ellipse); + + sizeVerticalLeft = sizeVerticalLeft + sizeVerticalWidth; + } + g2d.setColor(Color.BLACK); + str = object.getKey() + " - " + label + " [" + unit + "]"; + g2d.drawString(str, (int)sizeBarBoxLeft + 5, (int)sizeBarBoxTop + 10); + } + } + + private double getSizeBarBoxTop(Graphics2D g2d, SizeBarsLocation location, SizeBarsSize size) { + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + throw new IllegalStateException(); + switch (location) { + case NORTH: { + return colorBarBoxPadding; + } + case SOUTH: { + return bounds.getMaxY() - colorBarBoxPadding; + } + case EAST: + case WEST: { + return (bounds.getMaxY() / 2) - (getSizeBarBoxHeight(size) / 2); + } + default: + return 0; + } + } + + private double getSizeBarBoxLeft(Graphics2D g2d, SizeBarsLocation location, SizeBarsSize size) { + Rectangle2D bounds = g2d.getClipBounds(); + if (bounds == null) + throw new IllegalStateException(); + switch (location) { + case EAST: { + double right = bounds.getMaxX() - colorBarBoxPadding; + return right - getSizeBarBoxWidth(size); + } + case WEST: { + return colorBarBoxPadding; + } + case NORTH: + case SOUTH: { + double left = (bounds.getMaxX() / 2) - (getSizeBarBoxWidth(size) / 2); + return left; + } + default: + return 0; + } + } + + private double getSizeBarBoxWidth(SizeBarsSize size) { + return size.getSize() * colorBarBoxWidth; + } + + private double getSizeBarBoxHeight(SizeBarsSize size) { + return size.getSize() * colorBarBoxHeight; + } + + @Override + public Rectangle2D getBoundsInLocal() { + return null; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setDynamicColoringObjects(Map dynamicColoringObjects) { + this.dynamicColoringContributions = dynamicColoringObjects; + } + + public void setColorBarOptions(ColorBarOptions colorBarsOptions) { + this.colorBarsOptions = colorBarsOptions; + } + + public void setDynamicSizingObjects(Map dynamicSizingObjects) { + this.dynamicSizingContributions = dynamicSizingObjects; + } + + public void setSizeBarOptions(SizeBarOptions sizeBarOptions) { + this.sizeBarsOptions = sizeBarOptions; + } + +} 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 new file mode 100644 index 00000000..69086062 --- /dev/null +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java @@ -0,0 +1,116 @@ +package org.simantics.district.network.ui.participants; + +import java.awt.geom.AffineTransform; +import java.util.Map; + +import org.simantics.district.network.ui.DistrictDiagramViewer; +import org.simantics.district.network.ui.nodes.DynamicVisualisationContributionsNode; +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.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.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; + +public class DynamicVisualisationContributionsParticipant extends AbstractCanvasParticipant { + + 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; + + 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); + } + + @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; + } +} diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/table/ImportCSVHandler.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/table/ImportCSVHandler.java index a94d56a1..d484e1b1 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/table/ImportCSVHandler.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/table/ImportCSVHandler.java @@ -79,7 +79,7 @@ public class ImportCSVHandler { if (sourceEPSGCRS != null && !sourceEPSGCRS.isEmpty()) { CoordinateReferenceSystem sourceCRS = CRS.decode(sourceEPSGCRS); CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326"); - transform = CRS.findMathTransform(sourceCRS, targetCRS, true); + transform = CRS.findMathTransform(sourceCRS, targetCRS, false); doTransform = true; } diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsUI.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsUI.java new file mode 100644 index 00000000..4fe3d591 --- /dev/null +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsUI.java @@ -0,0 +1,778 @@ +package org.simantics.district.network.ui.visualisations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorPart; +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.Listener; +import org.simantics.district.network.DistrictNetworkUtil; +import org.simantics.district.network.profile.DynamicVisualisationsRequest; +import org.simantics.district.network.visualisations.DynamicVisualisationsContributions; +import org.simantics.district.network.visualisations.DynamicVisualisationsContributions.DynamicColoringObject; +import org.simantics.district.network.visualisations.DynamicVisualisationsContributions.DynamicSizingObject; +import org.simantics.district.network.visualisations.model.ColorBarOptions; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsLocation; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsSize; +import org.simantics.district.network.visualisations.model.DynamicColorContribution; +import org.simantics.district.network.visualisations.model.DynamicColorMap; +import org.simantics.district.network.visualisations.model.DynamicSizeContribution; +import org.simantics.district.network.visualisations.model.DynamicSizeMap; +import org.simantics.district.network.visualisations.model.DynamicVisualisation; +import org.simantics.district.network.visualisations.model.SizeBarOptions; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsLocation; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsSize; +import org.simantics.ui.workbench.IResourceEditorPart; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.ui.workbench.WorkbenchUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DynamicVisualisationsUI extends Composite { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationsUI.class); + + private Resource diagramResource; + private VisualisationListener listener; + private DynamicVisualisation visualisation; + + private Button showSizeButton; + private Button sizeTicksButton; + private Combo sizeLocationCombo; + private Combo sizeSizeCombo; + private Button showColorButton; + private Button colorTicksButton; + private Combo colorLocationCombo; + private Combo colorSizeCombo; + + public DynamicVisualisationsUI(Composite parent, int style) { + super(parent, style); + + defaultInitializeUI(); + } + + private void defaultInitializeUI() { + GridDataFactory.fillDefaults().grab(true, true).applyTo(this); + GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(this); + + Composite coloringObjectsComposite = new Composite(this, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(coloringObjectsComposite); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(coloringObjectsComposite); + initializeColoringObjects(coloringObjectsComposite); + + Composite colorBarsComposite = new Composite(this, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(colorBarsComposite); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(colorBarsComposite); + initializeColorBars(colorBarsComposite); + + Composite objectSizesComposite = new Composite(this, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(objectSizesComposite); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(objectSizesComposite); + initializeObjectSizes(objectSizesComposite); + + Composite sizeBarsComposite = new Composite(this, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(sizeBarsComposite); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(sizeBarsComposite); + initializeSizeBars(sizeBarsComposite); + + } + + private void initializeColoringObjects(Composite parent) { + Group group = new Group(parent, SWT.NONE); + group.setText("Coloring Objects"); + GridDataFactory.fillDefaults().grab(true, false).applyTo(group); + GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group); + + { + createColoringObjectHeaderRow(group); + } + List>> suppliers = new ArrayList<>(); + { + try { + Collection result = Simantics.getSession().syncRequest(new UniqueRead>() { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return DynamicVisualisationsContributions.dynamicColoringObjects(graph); + } + }); + + for (DynamicColoringObject object : result) { + suppliers.add(createColoringObjectRow(group, object)); + } + + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + { + Button applyButton = new Button(group, SWT.NONE); + applyButton.setText("Apply"); + applyButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + List> collect = suppliers.stream().map(s -> s.get()).filter(Objects::nonNull).collect(Collectors.toList()); + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + DistrictNetworkUtil.setColorContributions(graph, DynamicVisualisationsUI.this.diagramResource, collect); + } + }); + } + }); + } + } + + private void createColoringObjectHeaderRow(Composite parent) { + + Label label = new Label(parent, SWT.NONE); + label.setText("Label"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Used"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Variable"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Min"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Max"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Unit"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("ColorMap"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Default"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + } + + private Map coloringRows = new HashMap<>(); + private Map sizingRows = new HashMap<>(); + + private static class ColoringObjectRow { + + private final Label label; + private final Button usedButton; + private final Combo variableCombo; + private final Text minText; + private final Text maxText; + private final Label unit; + private final Combo colorMapCombo; + private final Button defaultButton; + + public ColoringObjectRow(Label label, Button usedButton, Combo variableCombo, Text minText, Text maxText, Label unit, + Combo colorMapCombo, Button defaultButton) { + super(); + this.label = label; + this.usedButton = usedButton; + this.variableCombo = variableCombo; + this.minText = minText; + this.maxText = maxText; + this.unit = unit; + this.colorMapCombo = colorMapCombo; + this.defaultButton = defaultButton; + } + + public void update(DynamicColorContribution colorContribution) { + String[] items = variableCombo.getItems(); + for (int i = 0; i < items.length; i++) { + if (colorContribution.getLabel().equals(items[i])) { + variableCombo.select(i); + break; + } + } + minText.setText(Double.toString(colorContribution.getDefaultMin())); + maxText.setText(Double.toString(colorContribution.getDefaultMax())); + unit.setText(colorContribution.getUnit()); + + // color map only supports single for now + colorMapCombo.setItems(colorContribution.getDefaultColorMap().getLabel()); + colorMapCombo.select(0); +// String[] colorItems = colorMapCombo.getItems(); +// for (int i = 0; i < colorItems.length; i++) { +// +// if (colorContribution.getDefaultColorMap().getLabel().equals(colorItems[i])) { +// colorMapCombo.select(i); +// break; +// } +// } + } + } + + private static class SizingObjectRow { + + private final Label label; + private final Button usedButton; + private final Combo variableCombo; + private final Text minText; + private final Text maxText; + private final Label unit; + private final Combo sizeMapCombo; + private final Button defaultButton; + + public SizingObjectRow(Label label, Button usedButton, Combo variableCombo, Text minText, Text maxText, Label unit, + Combo sizeMapCombo, Button defaultButton) { + super(); + this.label = label; + this.usedButton = usedButton; + this.variableCombo = variableCombo; + this.minText = minText; + this.maxText = maxText; + this.unit = unit; + this.sizeMapCombo = sizeMapCombo; + this.defaultButton = defaultButton; + } + + public void update(DynamicSizeContribution sizeContribution) { + String[] items = variableCombo.getItems(); + for (int i = 0; i < items.length; i++) { + if (sizeContribution.getLabel().equals(items[i])) { + variableCombo.select(i); + break; + } + } + minText.setText(Double.toString(sizeContribution.getDefaultMin())); + maxText.setText(Double.toString(sizeContribution.getDefaultMax())); + unit.setText(sizeContribution.getUnit()); + + // color map only supports single for now + sizeMapCombo.setItems(sizeContribution.getDefaultSizeMap().getLabel()); + sizeMapCombo.select(0); +// String[] colorItems = colorMapCombo.getItems(); +// for (int i = 0; i < colorItems.length; i++) { +// +// if (colorContribution.getDefaultColorMap().getLabel().equals(colorItems[i])) { +// colorMapCombo.select(i); +// break; +// } +// } + } + } + + private Supplier> createColoringObjectRow(Composite parent, DynamicColoringObject object) { + Label label = new Label(parent, SWT.NONE); + label.setText(object.getColoringObject().getName()); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(label); + + Map colorContributions = object.getColorContributions(); + + Button usedButton = new Button(parent, SWT.CHECK); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(usedButton); + + Combo variableCombo = new Combo(parent, SWT.READ_ONLY); + variableCombo.setItems(colorContributions.keySet().toArray(new String[colorContributions.size()])); + + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(variableCombo); + + Text minText = new Text(parent, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).align(SWT.CENTER, SWT.CENTER).applyTo(minText); + + Text maxText = new Text(parent, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).align(SWT.CENTER, SWT.CENTER).applyTo(maxText); + + Label unit = new Label(parent, SWT.NONE); + unit.setText(""); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(unit); + + Combo colorMapCombo = new Combo(parent, SWT.READ_ONLY); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(colorMapCombo); + + Button defaultButton = new Button(parent, SWT.CHECK); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(defaultButton); + + variableCombo.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // handle update for others + + DynamicColorContribution cont = colorContributions.get(variableCombo.getText()); + + if (minText.getText().isEmpty()) { + minText.setText(Double.toString(cont.getDefaultMin())); + } + if (maxText.getText().isEmpty()) { + maxText.setText(Double.toString(cont.getDefaultMax())); + } + unit.setText(cont.getUnit()); + + colorMapCombo.setItems(cont.getDefaultColorMap().getLabel()); + colorMapCombo.select(0); + + defaultButton.setSelection(true); + } + }); + + coloringRows.put(object.getColoringObject().getName(), new ColoringObjectRow(label, usedButton, variableCombo, minText, maxText, unit, colorMapCombo, defaultButton)); + + return new Supplier>() { + + @Override + public Pair get() { + DynamicColorContribution cont = colorContributions.get(variableCombo.getText()); + if (cont != null) { + String colorMap = colorMapCombo.getItem(colorMapCombo.getSelectionIndex()); + try { + Map colorMaps = Simantics.getSession().syncRequest(new UniqueRead>() { + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + return DynamicVisualisationsContributions.dynamicColorMaps(graph); + } + }); + DynamicColorMap dColorMap = colorMaps.get(colorMap); + String label = variableCombo.getItem(variableCombo.getSelectionIndex()); + + DynamicColorContribution dcc = new DynamicColorContribution(label, cont.getModuleName(), cont.getAttributeName(), unit.getText(), cont.getVariableGain(), cont.getVariableBias(), dColorMap, Double.parseDouble(minText.getText()), Double.parseDouble(maxText.getText())); + dcc.setUsed(usedButton.getSelection()); + dcc.setUseDefault(defaultButton.getSelection()); + + return Pair.make(object.getColoringObject().getName(), dcc); + } catch (DatabaseException e) { + LOGGER.error("Could not get DynamicColorContribution", e); + } + } + return null; + } + }; + } + + private void createSizingObjectHeaderRow(Composite parent) { + + Label label = new Label(parent, SWT.NONE); + label.setText("Label"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Used"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Variable"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Min"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Max"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Unit"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("SizeMap"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + + label = new Label(parent, SWT.NONE); + label.setText("Default"); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label); + } + + private Supplier> createSizingObjectRow(Composite parent, DynamicSizingObject object) { + Label label = new Label(parent, SWT.NONE); + label.setText(object.getSizingObject().getName()); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(label); + + Map sizeContributions = object.getSizeContributions(); + + Button usedButton = new Button(parent, SWT.CHECK); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(usedButton); + + Combo variableCombo = new Combo(parent, SWT.READ_ONLY); + variableCombo.setItems(sizeContributions.keySet().toArray(new String[sizeContributions.size()])); + + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(variableCombo); + + Text minText = new Text(parent, SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(minText); + + Text maxText = new Text(parent, SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(maxText); + + Label unit = new Label(parent, SWT.NONE); + unit.setText(""); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(unit); + + Combo sizeMapCombo = new Combo(parent, SWT.READ_ONLY); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(sizeMapCombo); + + Button defaultButton = new Button(parent, SWT.CHECK); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(defaultButton); + + variableCombo.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // handle update for others + + DynamicSizeContribution cont = sizeContributions.get(variableCombo.getText()); + + if (minText.getText().isEmpty()) { + minText.setText(Double.toString(cont.getDefaultMin())); + } + if (maxText.getText().isEmpty()) { + maxText.setText(Double.toString(cont.getDefaultMax())); + } + unit.setText(cont.getUnit()); + + sizeMapCombo.setItems(cont.getDefaultSizeMap().getLabel()); + sizeMapCombo.select(0); + + defaultButton.setSelection(true); + } + }); + + sizingRows.put(object.getSizingObject().getName(), new SizingObjectRow(label, usedButton, variableCombo, minText, maxText, unit, sizeMapCombo, defaultButton)); + + return new Supplier>() { + + @Override + public Pair get() { + DynamicSizeContribution cont = sizeContributions.get(variableCombo.getText()); + if (cont != null) { + String sizeMap = sizeMapCombo.getItem(sizeMapCombo.getSelectionIndex()); + try { + Map sizeMaps = Simantics.getSession().syncRequest(new UniqueRead>() { + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + return DynamicVisualisationsContributions.dynamicSizeMaps(graph); + } + }); + DynamicSizeMap dColorMap = sizeMaps.get(sizeMap); + String label = variableCombo.getItem(variableCombo.getSelectionIndex()); + + DynamicSizeContribution dsc = new DynamicSizeContribution(label, cont.getModuleName(), cont.getAttributeName(), unit.getText(), cont.getVariableGain(), cont.getVariableBias(), dColorMap, Double.parseDouble(minText.getText()), Double.parseDouble(maxText.getText())); + dsc.setUsed(usedButton.getSelection()); + dsc.setUseDefault(defaultButton.getSelection()); + + return Pair.make(object.getSizingObject().getName(), dsc); + } catch (DatabaseException e) { + LOGGER.error("Could not get DynamicColorContribution", e); + } + } + return null; + } + }; + } + + private void initializeColorBars(Composite parent) { + Group group = new Group(parent, SWT.NONE); + group.setText("Color Bars"); + GridDataFactory.fillDefaults().grab(true, false).applyTo(group); + GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(group); + + createColorBars(group); + } + + private void createColorBars(Composite parent) { + + showColorButton = new Button(parent, SWT.CHECK); + showColorButton.setText("Show"); + + colorTicksButton = new Button(parent, SWT.CHECK); + colorTicksButton.setText("Ticks"); + + Label label = new Label(parent, SWT.NONE); + label.setText("Location"); + colorLocationCombo = new Combo(parent, SWT.READ_ONLY); + colorLocationCombo.setItems(Stream.of(ColorBarsLocation.values()).map(size -> size.toString()).toArray(String[]::new)); + + label = new Label(parent, SWT.NONE); + label.setText("Size"); + colorSizeCombo = new Combo(parent, SWT.READ_ONLY); + colorSizeCombo.setItems(Stream.of(ColorBarsSize.values()).map(size -> size.toString()).toArray(String[]::new)); + + Button applyButton = new Button(parent, SWT.NONE); + applyButton.setText("Apply"); + + applyButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // persist changes + IEditorPart activeEditor = WorkbenchUtils.getActiveEditor(); + if (activeEditor instanceof IResourceEditorPart) { + Resource diagram = ((IResourceEditorPart) activeEditor).getResourceInput().getResource(); + ColorBarOptions options = new ColorBarOptions() + .showColorBars(showColorButton.getSelection()) + .showColorBarsTicks(colorTicksButton.getSelection()) + .withLocation(ColorBarsLocation.valueOf(colorLocationCombo.getText().toUpperCase())) + .withSize(ColorBarsSize.valueOf(colorSizeCombo.getText().toUpperCase())); + + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + DistrictNetworkUtil.setColorBarOptions(graph, diagram, options); + } + }); + } + } + }); + } + + private void initializeObjectSizes(Composite parent) { + Group group = new Group(parent, SWT.NONE); + group.setText("Object Sizes"); + GridDataFactory.fillDefaults().grab(true, false).applyTo(group); + GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group); + + { + createSizingObjectHeaderRow(group); + createObjectSizes(group); + } + } + + private void createObjectSizes(Composite parent) { + + List>> suppliers = new ArrayList<>(); + try { + Collection resultSizing = Simantics.getSession().syncRequest(new UniqueRead>() { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return DynamicVisualisationsContributions.dynamicSizingObjects(graph); + } + }); + + for (DynamicSizingObject object : resultSizing) { + suppliers.add(createSizingObjectRow(parent, object)); + } + } catch (DatabaseException e) { + e.printStackTrace(); + } + + { + Button applyButton = new Button(parent, SWT.NONE); + applyButton.setText("Apply"); + applyButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + List> collect = suppliers.stream().map(s -> s.get()).filter(Objects::nonNull).collect(Collectors.toList()); + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + DistrictNetworkUtil.setSizeContributions(graph, DynamicVisualisationsUI.this.diagramResource, collect); + } + }); + } + }); + } + } + + private void initializeSizeBars(Composite parent) { + Group group = new Group(parent, SWT.NONE); + group.setText("Size Bars"); + GridDataFactory.fillDefaults().grab(true, false).applyTo(group); + GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(group); + + createSizeBars(group); + } + + private void createSizeBars(Composite parent) { + showSizeButton = new Button(parent, SWT.CHECK); + showSizeButton.setText("Show"); + + sizeTicksButton = new Button(parent, SWT.CHECK); + sizeTicksButton.setText("Ticks"); + + Label label = new Label(parent, SWT.NONE); + label.setText("Location"); + sizeLocationCombo = new Combo(parent, SWT.READ_ONLY); + sizeLocationCombo.setItems(Stream.of(SizeBarsLocation.values()).map(size -> size.toString()).toArray(String[]::new)); + + label = new Label(parent, SWT.NONE); + label.setText("Size"); + sizeSizeCombo = new Combo(parent, SWT.NONE); + sizeSizeCombo.setItems(Stream.of(SizeBarsSize.values()).map(size -> size.toString()).toArray(String[]::new)); + + Button applyButton = new Button(parent, SWT.READ_ONLY); + applyButton.setText("Apply"); + + applyButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // persist changes + IEditorPart activeEditor = WorkbenchUtils.getActiveEditor(); + if (activeEditor instanceof IResourceEditorPart) { + Resource diagram = ((IResourceEditorPart) activeEditor).getResourceInput().getResource(); + SizeBarOptions options = new SizeBarOptions() + .showSizeBars(showSizeButton.getSelection()) + .showSizeBarsTicks(sizeTicksButton.getSelection()) + .withLocation(SizeBarsLocation.valueOf(sizeLocationCombo.getText().toUpperCase())) + .withSize(SizeBarsSize.valueOf(sizeSizeCombo.getText().toUpperCase())); + + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + DistrictNetworkUtil.setSizeBarOptions(graph, diagram, options); + } + }); + } + } + }); + } + + public void setDiagramResource(Resource diagramResource) { + if (this.diagramResource != diagramResource) { + this.diagramResource = diagramResource; + updateListening(); + } + } + + private void updateListening() { + if (listener != null) { + listener.dispose(); + } + listener = new VisualisationListener(this); + Simantics.getSession().asyncRequest(new DynamicVisualisationsRequest(diagramResource), listener); + } + + private static class VisualisationListener implements Listener { + + private static final Logger LOGGER = LoggerFactory.getLogger(VisualisationListener.class); + + private boolean disposed; + private DynamicVisualisationsUI ui; + + public VisualisationListener(DynamicVisualisationsUI ui) { + this.ui = ui; + } + + @Override + public void execute(DynamicVisualisation result) { + ui.updateVisualisation(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Could not listen visualisation", t); + } + + @Override + public boolean isDisposed() { + return disposed || ui.isDisposed(); + } + + public void dispose() { + this.disposed = true; + } + } + + public void updateVisualisation(DynamicVisualisation result) { + this.visualisation = result; + Display.getDefault().asyncExec(() -> { + if (getParent().isDisposed()) + return; + + Map colorContributions = visualisation.getColorContributions(); + for (Entry entry : colorContributions.entrySet()) { + + ColoringObjectRow coloringObjectRow = coloringRows.get(entry.getKey()); + if (coloringObjectRow != null) { + + coloringObjectRow.update(entry.getValue()); + + } else { + LOGGER.info("No coloring object visualisation row for key {}", entry.getKey()); + } + } + ColorBarOptions colorOptions = visualisation.getColorBarOptions(); + showColorButton.setSelection(colorOptions.isShowColorBars()); + colorTicksButton.setSelection(colorOptions.isShowColorBarsTicks()); + for (int i = 0; i < colorLocationCombo.getItems().length; i++) { + String item = colorLocationCombo.getItem(i); + if (item.equals(colorOptions.getLocation().toString())) { + colorLocationCombo.select(i); + break; + } + } + for (int i = 0; i < colorSizeCombo.getItems().length; i++) { + String item = colorSizeCombo.getItem(i); + if (item.equals(colorOptions.getSize().toString())) { + colorSizeCombo.select(i); + break; + } + } + + Map sizeContributions = visualisation.getSizeContributions(); + for (Entry entry : sizeContributions.entrySet()) { + + SizingObjectRow sizingObjectRow = sizingRows.get(entry.getKey()); + if (sizingObjectRow != null) { + + sizingObjectRow.update(entry.getValue()); + + } else { + LOGGER.info("No sizing object visualisation row for key {}", entry.getKey()); + } + } + SizeBarOptions sizeOptions = visualisation.getSizeBarOptions(); + showSizeButton.setSelection(sizeOptions.isShowSizeBars()); + sizeTicksButton.setSelection(sizeOptions.isShowSizeBarsTicks()); + for (int i = 0; i < sizeLocationCombo.getItems().length; i++) { + String item = sizeLocationCombo.getItem(i); + if (item.equals(sizeOptions.getLocation().toString())) { + sizeLocationCombo.select(i); + break; + } + } + for (int i = 0; i < sizeSizeCombo.getItems().length; i++) { + String item = sizeSizeCombo.getItem(i); + if (item.equals(sizeOptions.getSize().toString())) { + sizeSizeCombo.select(i); + break; + } + } + }); + } +} diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsView.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsView.java new file mode 100644 index 00000000..d98a3787 --- /dev/null +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/visualisations/DynamicVisualisationsView.java @@ -0,0 +1,86 @@ +package org.simantics.district.network.ui.visualisations; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; + +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.workbench.modeling.EPartService; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; +import org.eclipse.e4.ui.workbench.modeling.IPartListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; +import org.simantics.district.network.ui.DistrictDiagramEditor; +import org.simantics.ui.workbench.IResourceEditorInput; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + +public class DynamicVisualisationsView { + + @Inject + ESelectionService selectionService; + + @Inject + EPartService partService; + + private DynamicVisualisationsUI ui; + + @PostConstruct + public void postConstruct(Composite parent) { + ui = new DynamicVisualisationsUI(parent, 0); + + IEditorPart editor = WorkbenchUtils.getActiveEditor(); + if (editor instanceof DistrictDiagramEditor) + setDiagramResource(editor.getEditorInput()); + + partService.addPartListener(partListener); + } + + @PreDestroy + public void dispose() { + partService.removePartListener(partListener); + ui.dispose(); + ui = null; + } + + private void setDiagramResourceFromCompatibilityEditor(MPart part) { + if (part.getObject() instanceof CompatibilityEditor) { + CompatibilityEditor editor = (CompatibilityEditor) part.getObject(); + IEditorPart editorPart = editor.getEditor(); + setDiagramResource(editorPart.getEditorInput()); + } + } + + private void setDiagramResource(IEditorInput input) { + if (input instanceof IResourceEditorInput) { + ui.setDiagramResource(((IResourceEditorInput) input).getResource()); + } + } + + private IPartListener partListener = new IPartListener() { + + @Override + public void partVisible(MPart part) { + setDiagramResourceFromCompatibilityEditor(part); + } + + @Override + public void partHidden(MPart part) { + } + + @Override + public void partDeactivated(MPart part) { + } + + @Override + public void partBroughtToTop(MPart part) { + setDiagramResourceFromCompatibilityEditor(part); + } + + @Override + public void partActivated(MPart part) { + setDiagramResourceFromCompatibilityEditor(part); + } + }; +} diff --git a/org.simantics.district.network/META-INF/MANIFEST.MF b/org.simantics.district.network/META-INF/MANIFEST.MF index ddf8bb90..77e7c464 100644 --- a/org.simantics.district.network/META-INF/MANIFEST.MF +++ b/org.simantics.district.network/META-INF/MANIFEST.MF @@ -18,7 +18,10 @@ Require-Bundle: org.simantics.db, org.slf4j.api, org.simantics.maps.elevation.server;bundle-version="1.0.0", org.simantics.modeling, - org.simantics.db.indexing + org.simantics.db.indexing, + org.simantics.scl.osgi Export-Package: org.simantics.district.network, org.simantics.district.network.changeset, - org.simantics.district.network.profile + org.simantics.district.network.profile, + org.simantics.district.network.visualisations, + org.simantics.district.network.visualisations.model diff --git a/org.simantics.district.network/adapters.xml b/org.simantics.district.network/adapters.xml index fddb3b74..dc464c88 100644 --- a/org.simantics.district.network/adapters.xml +++ b/org.simantics.district.network/adapters.xml @@ -12,6 +12,9 @@ + + diff --git a/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorContribution.scl b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorContribution.scl new file mode 100644 index 00000000..800aa2b8 --- /dev/null +++ b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorContribution.scl @@ -0,0 +1,21 @@ +// Example: (�p supply�, �S_PC�, �PO11_PRESSURE�, �bar(g)�, 0.1, 1.0, �summer�, 50.0, 120.0) +// Above �p supply� is label and there may be several UC types contributing to the same label. Default colorMap �summer�. + +importJava "org.simantics.district.network.visualisations.model.DynamicColorMap" where + data DynamicColorMap + + @JavaName "" + dynamicColorMap :: String -> [RGBIntensity] -> DynamicColorMap + +importJava "org.simantics.district.network.visualisations.model.DynamicColorMap$RGBIntensity" where + data RGBIntensity + + @JavaName "" + rgbIntensity :: Double -> Double -> Double -> RGBIntensity + +importJava "org.simantics.district.network.visualisations.model.DynamicColorContribution" where + data DynamicColorContribution + + @JavaName "" + dynamicColorContribution :: String -> String -> String -> String -> Double -> Double -> DynamicColorMap -> Double -> Double -> DynamicColorContribution + diff --git a/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorMap.scl b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/ColorMap.scl new file mode 100644 index 00000000..e69de29b diff --git a/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeContribution.scl b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeContribution.scl new file mode 100644 index 00000000..e6b2ed38 --- /dev/null +++ b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeContribution.scl @@ -0,0 +1,13 @@ +// Example: (�supply flow�, �S_FLOW�, �SP_VALUE�, �kg/s�, 1.0, 0.0, �linearSizesMedium�, 10.0, 1500.0) + +importJava "org.simantics.district.network.visualisations.model.DynamicSizeMap" where + data DynamicSizeMap + + @JavaName "" + dynamicSizeMap :: String -> [Double] -> DynamicSizeMap + +importJava "org.simantics.district.network.visualisations.model.DynamicSizeContribution" where + data DynamicSizeContribution + + @JavaName "" + dynamicSizeContribution :: String -> String -> String -> String -> Double -> Double -> DynamicSizeMap -> Double -> Double -> DynamicSizeContribution diff --git a/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeMap.scl b/org.simantics.district.network/scl/Simantics/District/DynamicVisualisations/SizeMap.scl new file mode 100644 index 00000000..e69de29b diff --git a/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java b/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java index ae73e56b..22aa7266 100644 --- a/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java +++ b/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java @@ -3,8 +3,11 @@ package org.simantics.district.network; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -30,12 +33,24 @@ import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; import org.simantics.diagram.synchronization.graph.layer.GraphLayer; import org.simantics.diagram.synchronization.graph.layer.IGraphLayerUtil; import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.visualisations.DynamicVisualisationsContributions; +import org.simantics.district.network.visualisations.model.ColorBarOptions; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsLocation; +import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsSize; +import org.simantics.district.network.visualisations.model.DynamicColorContribution; +import org.simantics.district.network.visualisations.model.DynamicColorMap; +import org.simantics.district.network.visualisations.model.DynamicSizeContribution; +import org.simantics.district.network.visualisations.model.DynamicSizeMap; +import org.simantics.district.network.visualisations.model.SizeBarOptions; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsLocation; +import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsSize; import org.simantics.layer0.Layer0; import org.simantics.maps.elevation.server.SingletonTiffTileInterface; import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences; import org.simantics.modeling.ModelingResources; import org.simantics.modeling.adapters.NewCompositeActionFactory; import org.simantics.operation.Layer0X; +import org.simantics.utils.datastructures.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -386,4 +401,203 @@ public class DistrictNetworkUtil { } return results; } + + public static ColorBarOptions colorBarOptions(ReadGraph graph, Resource diagram) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation != null) { + String colorBarLocation = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ColorBarLocation, Bindings.STRING); + String colorBarSize = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ColorBarSize, Bindings.STRING); + Boolean show = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ShowColorBars, Bindings.BOOLEAN); + Boolean showTicks = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ShowColorBarTicks, Bindings.BOOLEAN); + if (colorBarLocation != null) { + return new ColorBarOptions() + .showColorBars(show != null ? show : false) + .showColorBarsTicks(showTicks != null ? showTicks : false) + .withLocation(ColorBarsLocation.valueOf(colorBarLocation)) + .withSize(ColorBarsSize.valueOf(colorBarSize)); + } + } + return ColorBarOptions.useDefault(); + } + + public static void setColorBarOptions(WriteGraph graph, Resource diagram, ColorBarOptions options) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + Layer0 L0 = Layer0.getInstance(graph); + visualisation = graph.newResource(); + graph.claim(visualisation, L0.InstanceOf, DN.Diagram_Visualisations); + graph.claimLiteral(visualisation, L0.HasName, "Visualisation"); + graph.claim(diagram, DN.Diagram_hasVisualisation, visualisation); + } + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ColorBarLocation, options.getLocation().toString(), Bindings.STRING); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ColorBarSize, options.getSize().toString(), Bindings.STRING); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ShowColorBars, options.isShowColorBars(), Bindings.BOOLEAN); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ShowColorBarTicks, options.isShowColorBarsTicks(), Bindings.BOOLEAN); + } + + public static SizeBarOptions sizeBarOptions(ReadGraph graph, Resource diagram) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation != null) { + String sizeBarLocation = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_SizeBarLocation, Bindings.STRING); + String sizeBarSize = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_SizeBarSize, Bindings.STRING); + Boolean show = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ShowSizeBars, Bindings.BOOLEAN); + Boolean showTicks = graph.getPossibleRelatedValue(visualisation, DN.Diagram_Visualisations_ShowSizeBarTicks, Bindings.BOOLEAN); + if (sizeBarLocation != null) { + return new SizeBarOptions() + .showSizeBars(show != null ? show : false) + .showSizeBarsTicks(showTicks != null ? showTicks : false) + .withLocation(SizeBarsLocation.valueOf(sizeBarLocation)) + .withSize(SizeBarsSize.valueOf(sizeBarSize)); + } + } + return SizeBarOptions.useDefault(); + } + + public static void setSizeBarOptions(WriteGraph graph, Resource diagram, SizeBarOptions options) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + Layer0 L0 = Layer0.getInstance(graph); + visualisation = graph.newResource(); + graph.claim(visualisation, L0.InstanceOf, DN.Diagram_Visualisations); + graph.claimLiteral(visualisation, L0.HasName, "Visualisation"); + graph.claim(diagram, DN.Diagram_hasVisualisation, visualisation); + } + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_SizeBarLocation, options.getLocation().toString(), Bindings.STRING); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_SizeBarSize, options.getSize().toString(), Bindings.STRING); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ShowSizeBars, options.isShowSizeBars(), Bindings.BOOLEAN); + graph.claimLiteral(visualisation, DN.Diagram_Visualisations_ShowSizeBarTicks, options.isShowSizeBarsTicks(), Bindings.BOOLEAN); + } + + public static Map colorContributions(ReadGraph graph, Resource diagram) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + return Collections.emptyMap(); + } + Map contributions = new HashMap<>(); + + Map colorMaps = DynamicVisualisationsContributions.dynamicColorMaps(graph); + + Collection colorContributions = graph.getObjects(visualisation, DN.Diagram_Visualisations_colorContributions); + for (Resource colorContribution : colorContributions) { + String ucName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionContributorName, Bindings.STRING); + String label = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionLabel, Bindings.STRING); + String moduleName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionModuleName, Bindings.STRING); + String attributeName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionModuleAttribute, Bindings.STRING); + String unit = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionUnit, Bindings.STRING); + Double variableGain = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionVariableGain, Bindings.DOUBLE); + Double variableBias = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionVariableBias, Bindings.DOUBLE); + String dynamicColorMap = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultColorMap, Bindings.STRING); + Double defaultMin = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultMin, Bindings.DOUBLE); + Double defaultMax = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultMax, Bindings.DOUBLE); + Boolean used = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionUsed, Bindings.BOOLEAN); + Boolean useDefault = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_colorContributionUseDefault, Bindings.BOOLEAN); + DynamicColorContribution dynamicColorContribution = new DynamicColorContribution(label, moduleName, attributeName, unit, variableGain, variableBias, colorMaps.get(dynamicColorMap), defaultMin, defaultMax); + dynamicColorContribution.setUsed(used != null ? used : false); + dynamicColorContribution.setUseDefault(useDefault != null ? useDefault : false); + contributions.put(ucName, dynamicColorContribution); + } + return contributions; + } + + public static void setColorContributions(WriteGraph graph, Resource diagram, List> collect) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + Layer0 L0 = Layer0.getInstance(graph); + visualisation = graph.newResource(); + graph.claim(visualisation, L0.InstanceOf, DN.Diagram_Visualisations); + graph.claimLiteral(visualisation, L0.HasName, "Visualisation"); + graph.claim(diagram, DN.Diagram_hasVisualisation, visualisation); + } + graph.deny(visualisation, DN.Diagram_Visualisations_colorContributions); + for (Pair coll : collect) { + Resource colorContribution = graph.newResource(); + + DynamicColorContribution contr = coll.second; + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionContributorName, coll.first); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionLabel, contr.getLabel()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionModuleName, contr.getModuleName()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionModuleAttribute, contr.getAttributeName()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionUnit, contr.getUnit()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionVariableGain, contr.getVariableGain()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionVariableBias, contr.getVariableBias()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultColorMap, contr.getDefaultColorMap().getLabel()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultMin, contr.getDefaultMin()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionDefaultMax, contr.getDefaultMax()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionUsed, contr.isUsed()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_colorContributionUseDefault, contr.isUseDefault()); + + graph.claim(visualisation, DN.Diagram_Visualisations_colorContributions, colorContribution); + } + } + + public static Map sizeContributions(ReadGraph graph, Resource diagram) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + return Collections.emptyMap(); + } + Map contributions = new HashMap<>(); + + Map sizeMaps = DynamicVisualisationsContributions.dynamicSizeMaps(graph); + + Collection colorContributions = graph.getObjects(visualisation, DN.Diagram_Visualisations_sizeContributions); + for (Resource colorContribution : colorContributions) { + String ucName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionContributorName, Bindings.STRING); + String label = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionLabel, Bindings.STRING); + String moduleName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionModuleName, Bindings.STRING); + String attributeName = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionModuleAttribute, Bindings.STRING); + String unit = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionUnit, Bindings.STRING); + Double variableGain = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionVariableGain, Bindings.DOUBLE); + Double variableBias = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionVariableBias, Bindings.DOUBLE); + String dynamicSizeMap = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultSizeMap, Bindings.STRING); + Double defaultMin = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultMin, Bindings.DOUBLE); + Double defaultMax = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultMax, Bindings.DOUBLE); + Boolean used = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionUsed, Bindings.BOOLEAN); + Boolean useDefault = graph.getRelatedValue(colorContribution, DN.Diagram_Visualisations_sizeContributionUseDefault, Bindings.BOOLEAN); + DynamicSizeContribution dsc = new DynamicSizeContribution(label, moduleName, attributeName, unit, variableGain, variableBias, sizeMaps.get(dynamicSizeMap), defaultMin, defaultMax); + dsc.setUsed(used != null ? used : false); + dsc.setUseDefault(useDefault != null ? useDefault : false); + contributions.put(ucName, dsc); + } + return contributions; + } + + public static void setSizeContributions(WriteGraph graph, Resource diagram, List> collect) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisation = graph.getPossibleObject(diagram, DN.Diagram_hasVisualisation); + if (visualisation == null) { + Layer0 L0 = Layer0.getInstance(graph); + visualisation = graph.newResource(); + graph.claim(visualisation, L0.InstanceOf, DN.Diagram_Visualisations); + graph.claimLiteral(visualisation, L0.HasName, "Visualisation"); + graph.claim(diagram, DN.Diagram_hasVisualisation, visualisation); + } + graph.deny(visualisation, DN.Diagram_Visualisations_sizeContributions); + for (Pair coll : collect) { + Resource colorContribution = graph.newResource(); + + DynamicSizeContribution contr = coll.second; + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionContributorName, coll.first); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionLabel, contr.getLabel()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionModuleName, contr.getModuleName()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionModuleAttribute, contr.getAttributeName()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionUnit, contr.getUnit()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionVariableGain, contr.getVariableGain()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionVariableBias, contr.getVariableBias()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultSizeMap, contr.getDefaultSizeMap().getLabel()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultMin, contr.getDefaultMin()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionDefaultMax, contr.getDefaultMax()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionUsed, contr.isUsed()); + graph.claimLiteral(colorContribution, DN.Diagram_Visualisations_sizeContributionUseDefault, contr.isUseDefault()); + + graph.claim(visualisation, DN.Diagram_Visualisations_sizeContributions, colorContribution); + } + } + } diff --git a/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementColorStyle.java b/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementColorStyle.java index 859faa67..fe0a1fe7 100644 --- a/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementColorStyle.java +++ b/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementColorStyle.java @@ -1,16 +1,28 @@ package org.simantics.district.network.profile; import java.awt.Color; +import java.util.Map; import org.simantics.Simantics; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.visualisations.model.DynamicColorContribution; +import org.simantics.district.network.visualisations.model.DynamicColorMap; +import org.simantics.district.network.visualisations.model.DynamicVisualisation; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; import org.simantics.scenegraph.INode; import org.simantics.scenegraph.g2d.nodes.SingleElementNode; import org.simantics.scenegraph.profile.EvaluationContext; import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen @@ -18,14 +30,69 @@ import org.simantics.scenegraph.profile.common.ProfileVariables; */ public class DNElementColorStyle extends ThrottledStyleBase { - private static final boolean DEBUG = false; + private static final Logger LOGGER = LoggerFactory.getLogger(DNElementColorStyle.class); + + private static final boolean DEBUG = false; @Override public Color calculateThrottledStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource groupItem) throws DatabaseException { - DiagramSettings ds = graph.syncRequest(new DiagramSettingsRequest(runtimeDiagram), TransientCacheAsyncListener.instance()); - // Prevent PendingVariableExceptions from coming through - boolean wasSynchronous = graph.setSynchronous(true); - try { + + DynamicVisualisation dv = graph.syncRequest(new RuntimeDynamicVisualisationsRequest(runtimeDiagram), + TransientCacheAsyncListener.instance()); + + DiagramSettings ds = graph.syncRequest(new DiagramSettingsRequest(runtimeDiagram), TransientCacheAsyncListener.instance()); + // Prevent PendingVariableExceptions from coming through + boolean wasSynchronous = graph.setSynchronous(true); + try { + if (dv != null) { + Layer0 L0 = Layer0.getInstance(graph); + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + Resource mapping = graph.getSingleObject(groupItem, DN.HasMapping); + + Map colorContributions = dv.getColorContributions(); + String mappingName = graph.getRelatedValue(mapping, L0.HasName); + DynamicColorContribution dcc = colorContributions.get(mappingName); + if (dcc != null && dcc.isUsed()) { + + Resource mappedComponent = graph.getPossibleObject(groupItem, DN.MappedComponent); + if (mappedComponent != null) { + + Resource component = graph.getSingleObject(mappedComponent, MOD.ElementToComponent); + Variable variable = Variables.getVariable(graph, component); + Variable possibleActiveVariable = Variables.possibleActiveVariable(graph, variable); + if (possibleActiveVariable != null) { + + Variable module = possibleActiveVariable.getPossibleChild(graph, dcc.getModuleName()); + if (module != null) { + Variable attribute = module.getPossibleProperty(graph, dcc.getAttributeName()); + if (attribute != null) { + Double possibleValue = attribute.getPossibleValue(graph, Bindings.DOUBLE); + if (possibleValue != null) { + // here we do the adjusting according to spec in #15038 + double adjustedValue = possibleValue.doubleValue() * dcc.getVariableGain() + dcc.getVariableBias(); + DynamicColorMap defaultColorMap = dcc.getDefaultColorMap(); + Color color = defaultColorMap.getColor(adjustedValue, dcc.getDefaultMin(), dcc.getDefaultMax()); + return color; + } else { + LOGGER.warn("No value for {}", attribute.getURI(graph)); + } + } else { + LOGGER.warn("Wrong attribute name {} for {} !!", dcc.getAttributeName(), module.getURI(graph)); + } + } else { + LOGGER.warn("Wrong modulename {} for {} !!", dcc.getModuleName(), possibleActiveVariable.getURI(graph)); + } + } else { + LOGGER.debug("No active experiment for {}", variable.getURI(graph)); + } + } else { + LOGGER.debug("No mapped component for {} to calculate dynamic color style", groupItem); + } + } + } + + // the old implementation here if (ds.elementColoringFunction.isPresent()) { if (DEBUG) System.out.print("elementColoringFunction: " + ds.elementColoringFunction + "(" + groupItem + "): "); diff --git a/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementSizeStyle.java b/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementSizeStyle.java new file mode 100644 index 00000000..990aa4d2 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/profile/DNElementSizeStyle.java @@ -0,0 +1,127 @@ +package org.simantics.district.network.profile; + +import java.util.Map; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.visualisations.model.DynamicSizeContribution; +import org.simantics.district.network.visualisations.model.DynamicSizeMap; +import org.simantics.district.network.visualisations.model.DynamicVisualisation; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.G2DSceneGraph; +import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.profile.EvaluationContext; +import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Jani Simomaa + */ +public class DNElementSizeStyle extends ThrottledStyleBase { + + private static final Logger LOGGER = LoggerFactory.getLogger(DNElementSizeStyle.class); + private static final boolean DEBUG = false; + + private static final Double PENDING = Double.NaN; + private static final Double ONE = 1.0; + + @Override + public Double calculateThrottledStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource groupItem) throws DatabaseException { + + DynamicVisualisation dv = graph.syncRequest(new RuntimeDynamicVisualisationsRequest(runtimeDiagram), + TransientCacheAsyncListener.instance()); + + // Prevent PendingVariableExceptions from coming through + boolean wasSynchronous = graph.setSynchronous(true); + try { + if (dv != null) { + Layer0 L0 = Layer0.getInstance(graph); + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + Resource mapping = graph.getSingleObject(groupItem, DN.HasMapping); + + Map sizeContributions = dv.getSizeContributions(); + String mappingName = graph.getRelatedValue(mapping, L0.HasName); + DynamicSizeContribution dsc = sizeContributions.get(mappingName); + if (dsc != null && dsc.isUsed()) { + + Resource mappedComponent = graph.getPossibleObject(groupItem, DN.MappedComponent); + if (mappedComponent != null) { + + Resource component = graph.getSingleObject(mappedComponent, MOD.ElementToComponent); + Variable variable = Variables.getVariable(graph, component); + Variable possibleActiveVariable = Variables.possibleActiveVariable(graph, variable); + if (possibleActiveVariable != null) { + + Variable module = possibleActiveVariable.getPossibleChild(graph, dsc.getModuleName()); + if (module != null) { + Variable attribute = module.getPossibleProperty(graph, dsc.getAttributeName()); + if (attribute != null) { + Double possibleValue = attribute.getPossibleValue(graph, Bindings.DOUBLE); + if (possibleValue != null) { + // here we do the adjusting according to spec in #15038 + double adjustedValue = possibleValue.doubleValue() * dsc.getVariableGain() + dsc.getVariableBias(); + DynamicSizeMap defaultSizeMap = dsc.getDefaultSizeMap(); + double size = defaultSizeMap.getSize(adjustedValue, dsc.getDefaultMin(), dsc.getDefaultMax()); + return size; + } else { + LOGGER.warn("No value for {}", attribute.getURI(graph)); + } + } else { + LOGGER.warn("Wrong attribute name {} for {} !!", dsc.getAttributeName(), module.getURI(graph)); + } + } else { + LOGGER.warn("Wrong modulename {} for {} !!", dsc.getModuleName(), possibleActiveVariable.getURI(graph)); + } + } else { + LOGGER.debug("No active experiment for {}", variable.getURI(graph)); + } + } else { + LOGGER.debug("No mapped component for {} to calculate dynamic size style", groupItem); + } + } + } + } + finally { + graph.setSynchronous(wasSynchronous); + } + return null; + } + + @Override + public void applyThrottledStyleForNode(EvaluationContext observer, INode node, Double value) { + //System.out.println("apply: " + node + " : " + value); + SingleElementNode n = (SingleElementNode) node; + if (value == PENDING) { + ((G2DSceneGraph)node.getRootNode()).setPending(node); + } else { + ((G2DSceneGraph)node.getRootNode()).clearPending(node); + } + if (value == null) + value = ONE; + for (INode nn : n.getNodes()) { + ProfileVariables.claimNodeProperty(nn, "size", value, observer); + ProfileVariables.claimNodeProperty(nn, "stroke", value, observer); + } + } + + @Override + protected void cleanupStyleForNode(EvaluationContext evaluationContext, INode node) { + ((G2DSceneGraph)node.getRootNode()).clearPending(node); + SingleElementNode n = (SingleElementNode) node; + for (INode nn : n.getNodes()) { + ProfileVariables.claimNodeProperty(nn, "size", ONE, evaluationContext); + ProfileVariables.claimNodeProperty(nn, "stroke", ONE, evaluationContext); + } + } + +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/profile/DynamicVisualisationsRequest.java b/org.simantics.district.network/src/org/simantics/district/network/profile/DynamicVisualisationsRequest.java new file mode 100644 index 00000000..c4d9d209 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/profile/DynamicVisualisationsRequest.java @@ -0,0 +1,43 @@ +package org.simantics.district.network.profile; + +import java.util.Map; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.district.network.DistrictNetworkUtil; +import org.simantics.district.network.ontology.DistrictNetworkResource; +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.layer0.Layer0; + +/** + * @author Jani Simomaa + */ +public class DynamicVisualisationsRequest extends ResourceRead { + + public DynamicVisualisationsRequest(Resource diagram) { + super(diagram); + } + + @Override + public DynamicVisualisation perform(ReadGraph graph) throws DatabaseException { + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + Resource visualisationResource = graph.getPossibleObject(resource, DN.Diagram_hasVisualisation); + if (visualisationResource != null) { + String name = graph.getRelatedValue(visualisationResource, Layer0.getInstance(graph).HasName); + Map colorContributions = DistrictNetworkUtil.colorContributions(graph, resource); + ColorBarOptions colorBarOptions = DistrictNetworkUtil.colorBarOptions(graph, resource); + Map sizeContributions = DistrictNetworkUtil.sizeContributions(graph, resource); + SizeBarOptions sizeBarOptions = DistrictNetworkUtil.sizeBarOptions(graph, resource); + DynamicVisualisation visualisation = new DynamicVisualisation(name, colorContributions, colorBarOptions, sizeContributions, sizeBarOptions); + return visualisation; + } + return null; + } + +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/profile/RuntimeDynamicVisualisationsRequest.java b/org.simantics.district.network/src/org/simantics/district/network/profile/RuntimeDynamicVisualisationsRequest.java new file mode 100644 index 00000000..a29b311e --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/profile/RuntimeDynamicVisualisationsRequest.java @@ -0,0 +1,30 @@ +package org.simantics.district.network.profile; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.district.network.visualisations.model.DynamicVisualisation; + +/** + * @author Jani Simomaa + */ +public class RuntimeDynamicVisualisationsRequest extends ResourceRead { + + public RuntimeDynamicVisualisationsRequest(Resource runtimeDiagram) { + super(runtimeDiagram); + } + + @Override + public DynamicVisualisation perform(ReadGraph graph) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + Resource diagram = graph.getPossibleObject(resource, DIA.RuntimeDiagram_HasConfiguration); + if (diagram != null) { + return graph.syncRequest(new DynamicVisualisationsRequest(diagram), TransientCacheAsyncListener.instance()); + } + return null; + } + +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java new file mode 100644 index 00000000..45e52fb5 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java @@ -0,0 +1,278 @@ +package org.simantics.district.network.visualisations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.simantics.NameLabelUtil; +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.NamedResource; +import org.simantics.db.common.request.ObjectsWithSupertype; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.district.network.visualisations.model.DynamicColorContribution; +import org.simantics.district.network.visualisations.model.DynamicColorMap; +import org.simantics.district.network.visualisations.model.DynamicSizeContribution; +import org.simantics.district.network.visualisations.model.DynamicSizeMap; +import org.simantics.layer0.Layer0; +import org.simantics.scl.compiler.top.ValueNotFound; +import org.simantics.scl.osgi.SCLOsgi; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.tuple.Tuple0; +import org.simantics.structural.stubs.StructuralResource2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DynamicVisualisationsContributions { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationsContributions.class); + + private static final String COMMON_DYNAMIC_VISUALISATIONS_MODULE = "CommonDynamicVisualisations"; + private static final String COLOR_MAP_CONTRIBUTION = "colorMapContribution"; + private static final String SIZE_MAP_CONTRIBUTION = "sizeMapContribution"; + + private static final String DYNAMIC_VISUALISATIONS_CONTRIBUTION_MODULE = "DynamicVisualisationsContribution"; + private static final String COLOR_CONTRIBUTION = "colorContribution"; + private static final String SIZE_CONTRIBUTION = "sizeContribution"; + + public static Map dynamicColorMaps(ReadGraph graph) throws DatabaseException { + List sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + + Map results = new HashMap<>(); + Layer0 L0 = Layer0.getInstance(graph); + for (Resource sharedOntology : sharedOntologies) { + Resource sclModule = Layer0Utils.getPossibleChild(graph, sharedOntology, L0.SCLModule, COMMON_DYNAMIC_VISUALISATIONS_MODULE); + if (sclModule != null) { + String moduleURI = graph.getURI(sclModule); + Object oldGraph = SCLContext.getCurrent().get("graph"); + try { + // let's put the graph to SCLContext for resolving the color maps + SCLContext.getCurrent().put("graph", graph); + @SuppressWarnings("unchecked") + List result = (List) SCLOsgi.MODULE_REPOSITORY.getValue(moduleURI, COLOR_MAP_CONTRIBUTION); + + for (DynamicColorMap colorMap : result) { + results.put(colorMap.getLabel(), colorMap); + } + } catch (ValueNotFound e) { + e.printStackTrace(); + } finally { + SCLContext.getCurrent().put("graph", oldGraph); + } + } + } + return results; + } + + public static Map dynamicSizeMaps(ReadGraph graph) throws DatabaseException { + List sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + + Map results = new HashMap<>(); + Layer0 L0 = Layer0.getInstance(graph); + for (Resource sharedOntology : sharedOntologies) { + Resource sclModule = Layer0Utils.getPossibleChild(graph, sharedOntology, L0.SCLModule, COMMON_DYNAMIC_VISUALISATIONS_MODULE); + if (sclModule != null) { + String moduleURI = graph.getURI(sclModule); + Object oldGraph = SCLContext.getCurrent().get("graph"); + try { + // let's put the graph to SCLContext for resolving the color maps + SCLContext.getCurrent().put("graph", graph); + @SuppressWarnings("unchecked") + List result = (List) SCLOsgi.MODULE_REPOSITORY.getValue(moduleURI, SIZE_MAP_CONTRIBUTION); + + for (DynamicSizeMap sizeMap : result) { + results.put(sizeMap.getLabel(), sizeMap); + } + } catch (ValueNotFound e) { + e.printStackTrace(); + } finally { + SCLContext.getCurrent().put("graph", oldGraph); + } + } + } + return results; + } + + public static Collection dynamicColoringObjects(ReadGraph graph) throws DatabaseException { + + List sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + + List results = new ArrayList<>(); + + for (Resource sharedOntology : sharedOntologies) { + Collection findByType = graph.syncRequest(new ObjectsWithSupertype(sharedOntology, Layer0.getInstance(graph).ConsistsOf, StructuralResource2.getInstance(graph).Component)); + //Collection findByType = QueryIndexUtils.searchByType(graph, sharedOntology, ); + for (Resource find : findByType) { + NamedResource moduleType = new NamedResource(NameLabelUtil.modalName(graph, find), find); + DynamicColoringObject dynamicColoringObject = dynamicColoringObject(graph, moduleType); + if (dynamicColoringObject != null) + results.add(dynamicColoringObject); + } + } + return results; + } + + public static Collection dynamicSizingObjects(ReadGraph graph) throws DatabaseException { + + List sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + + List results = new ArrayList<>(); + + for (Resource sharedOntology : sharedOntologies) { + Collection findByType = graph.syncRequest(new ObjectsWithSupertype(sharedOntology, Layer0.getInstance(graph).ConsistsOf, StructuralResource2.getInstance(graph).Component)); + //Collection findByType = QueryIndexUtils.searchByType(graph, sharedOntology, ); + for (Resource find : findByType) { + NamedResource moduleType = new NamedResource(NameLabelUtil.modalName(graph, find), find); + DynamicSizingObject dynamicSizingObject = dynamicSizingObject(graph, moduleType); + if (dynamicSizingObject != null) + results.add(dynamicSizingObject); + } + } + return results; + } + + private static DynamicColoringObject dynamicColoringObject(ReadGraph graph, NamedResource moduleType) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Resource sclModule = Layer0Utils.getPossibleChild(graph, moduleType.getResource(), L0.SCLModule, DYNAMIC_VISUALISATIONS_CONTRIBUTION_MODULE); + if (sclModule != null) { + String moduleURI = graph.getURI(sclModule); + return new DynamicColoringObject(moduleType, getDynamicColorContributionSupplier(moduleURI, COLOR_CONTRIBUTION)); + } + return null; + } + +// private static DynamicColoringMap dynamicColoringMap(ReadGraph graph, NamedResource moduleType) throws DatabaseException { +// Layer0 L0 = Layer0.getInstance(graph); +// Resource sclModule = Layer0Utils.getPossibleChild(graph, moduleType.getResource(), L0.SCLModule, DYNAMIC_VISUALISATIONS_CONTRIBUTION_MODULE); +// if (sclModule != null) { +// String moduleURI = graph.getURI(sclModule); +// return new DynamicColoringMap(moduleType, getDynamicColoringMapSupplier(moduleURI, COLOR_CONTRIBUTION)); +// } +// return null; +// } + + private static DynamicSizingObject dynamicSizingObject(ReadGraph graph, NamedResource moduleType) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Resource sclModule = Layer0Utils.getPossibleChild(graph, moduleType.getResource(), L0.SCLModule, DYNAMIC_VISUALISATIONS_CONTRIBUTION_MODULE); + if (sclModule != null) { + String moduleURI = graph.getURI(sclModule); + return new DynamicSizingObject(moduleType, getDynamicSizeContributionSupplier(moduleURI, SIZE_CONTRIBUTION)); + } + return null; + } + + private static Supplier> getDynamicColorMapSupplier(String uri, String expressionText) { + return () -> { + try { + @SuppressWarnings("unchecked") + List result = (List) SCLOsgi.MODULE_REPOSITORY.getValue(uri, expressionText); + return result.stream();//result.stream().map(DynamicColorContribution::fromTuple9); + } catch (ValueNotFound e) { + LOGGER.error("Could not find contributions", e); + //throw new RuntimeException(e); + return Stream.empty(); + } + }; + } + + private static Supplier> getDynamicColorContributionSupplier(String uri, String expressionText) { + return () -> { + try { + @SuppressWarnings("unchecked") + List result = (List) SCLOsgi.MODULE_REPOSITORY.getValue(uri, expressionText); + return result.stream();//result.stream().map(DynamicColorContribution::fromTuple9); + } catch (ValueNotFound e) { + LOGGER.error("Could not find contributions", e); + //throw new RuntimeException(e); + return Stream.empty(); + } + }; + } + + private static Supplier> getDynamicSizeContributionSupplier(String uri, String expressionText) { + return () -> { + try { + @SuppressWarnings("unchecked") + List result = (List) SCLOsgi.MODULE_REPOSITORY.getValue(uri, expressionText); + return result.stream();//result.stream().map(DynamicColorContribution::fromTuple9); + } catch (ValueNotFound e) { + LOGGER.error("Could not find contributions", e); + //throw new RuntimeException(e); + return Stream.empty(); + } + }; + } + + public static class DynamicColoringObject { + + private final NamedResource coloringObject; + private final Supplier> colorContributionSupplier; + private Map colorContributions; + + public DynamicColoringObject(NamedResource coloringObject, Supplier> colorContributionSupplier) { + this.coloringObject = coloringObject; + this.colorContributionSupplier = colorContributionSupplier; + } + + public NamedResource getColoringObject() { + return coloringObject; + } + + public Map getColorContributions() { + if (colorContributions == null) + colorContributions = colorContributionSupplier.get().collect(Collectors.toMap(c -> c.getLabel(), c -> c)); + return colorContributions; + } + } + + public static class DynamicColoringMap { + + private final NamedResource coloringObject; + private final Supplier> colorContributionSupplier; + private Map colorContributions; + + public DynamicColoringMap(NamedResource coloringObject, Supplier> colorContributionSupplier) { + this.coloringObject = coloringObject; + this.colorContributionSupplier = colorContributionSupplier; + } + + public NamedResource getColoringObject() { + return coloringObject; + } + + public Map getColorContributions() { + if (colorContributions == null) + colorContributions = colorContributionSupplier.get().collect(Collectors.toMap(c -> c.getLabel(), c -> c)); + return colorContributions; + } + } + + public static class DynamicSizingObject { + + private final NamedResource sizingObject; + private final Supplier> sizeContributionSupplier; + private Map sizeContributions; + + public DynamicSizingObject(NamedResource coloringObject, Supplier> sizeContributionSupplier) { + this.sizingObject = coloringObject; + this.sizeContributionSupplier = sizeContributionSupplier; + } + + public NamedResource getSizingObject() { + return sizingObject; + } + + public Map getSizeContributions() { + if (sizeContributions == null) + sizeContributions = sizeContributionSupplier.get().collect(Collectors.toMap(c -> c.getLabel(), c -> c)); + return sizeContributions; + } + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/VisualisationColoringObject.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/VisualisationColoringObject.java new file mode 100644 index 00000000..c13bcd41 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/VisualisationColoringObject.java @@ -0,0 +1,56 @@ +package org.simantics.district.network.visualisations; + +public class VisualisationColoringObject { + + private String label; + private boolean used; + private String variable; + private double min; + private double max; + private String unit; + private String colorMap; + private boolean isDefault; + + public VisualisationColoringObject(String label, boolean used, String variable, double min, double max, String unit, String colorMap, boolean isDefault) { + this.label = label; + this.used = used; + this.variable = variable; + this.min = min; + this.max = max; + this.unit = unit; + this.colorMap = colorMap; + this.isDefault = isDefault; + } + + public String getLabel() { + return label; + } + + public boolean isUsed() { + return used; + } + + public String getVariable() { + return variable; + } + + public double getMin() { + return min; + } + + public double getMax() { + return max; + } + + public String getUnit() { + return unit; + } + + public String getColorMap() { + return colorMap; + } + + public boolean isDefault() { + return isDefault; + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/ColorBarOptions.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/ColorBarOptions.java new file mode 100644 index 00000000..a57ad913 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/ColorBarOptions.java @@ -0,0 +1,67 @@ +package org.simantics.district.network.visualisations.model; + +public class ColorBarOptions { + + private boolean showColorBars; + private boolean showColorBarsTicks; + private ColorBarsLocation location; + private ColorBarsSize size; + + public boolean isShowColorBars() { + return showColorBars; + } + + public ColorBarOptions showColorBars(boolean show) { + this.showColorBars = show; + return this; + } + + public boolean isShowColorBarsTicks() { + return showColorBarsTicks; + } + + public ColorBarOptions showColorBarsTicks(boolean show) { + this.showColorBarsTicks = show; + return this; + } + + public ColorBarsLocation getLocation() { + return location; + } + + public ColorBarOptions withLocation(ColorBarsLocation location) { + this.location = location; + return this; + } + + public ColorBarsSize getSize() { + return size; + } + + public ColorBarOptions withSize(ColorBarsSize size) { + this.size = size; + return this; + } + + public enum ColorBarsLocation { + NORTH, EAST, SOUTH, WEST + } + + public enum ColorBarsSize { + SMALL(1), MEDIUM(2), LARGE(3); + + int size; + + ColorBarsSize(int size) { + this.size = size; + } + + public int getSize() { + return size; + } + } + + public static ColorBarOptions useDefault() { + return new ColorBarOptions().showColorBars(true).withLocation(ColorBarsLocation.EAST).withSize(ColorBarsSize.SMALL); + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorContribution.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorContribution.java new file mode 100644 index 00000000..2839bcc3 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorContribution.java @@ -0,0 +1,83 @@ +package org.simantics.district.network.visualisations.model; + +public class DynamicColorContribution { + + private String label; + private String moduleName; + private String attributeName; + private String unit; + private double variableGain; + private double variableBias; + private DynamicColorMap defaultColorMap; + private double defaultMin; + private double defaultMax; + + // for graph persistence only + private boolean used; + private boolean useDefault; + + public DynamicColorContribution(String label, String moduleName, String attributeName, String unit, + double variableGain, double variableBias, DynamicColorMap defaultColorMap, double defaultMin, double defaultMax) { + this.label = label; + this.moduleName = moduleName; + this.attributeName = attributeName; + this.unit = unit; + this.variableGain = variableGain; + this.variableBias = variableBias; + this.defaultColorMap = defaultColorMap; + this.defaultMin = defaultMin; + this.defaultMax = defaultMax; + } + + public String getLabel() { + return label; + } + + public String getModuleName() { + return moduleName; + } + + public String getAttributeName() { + return attributeName; + } + + public String getUnit() { + return unit; + } + + public double getVariableGain() { + return variableGain; + } + + public double getVariableBias() { + return variableBias; + } + + public DynamicColorMap getDefaultColorMap() { + return defaultColorMap; + } + + public double getDefaultMin() { + return defaultMin; + } + + public double getDefaultMax() { + return defaultMax; + } + + public void setUsed(boolean used) { + this.used = used; + } + + public boolean isUsed() { + return used; + } + + public void setUseDefault(boolean useDefault) { + this.useDefault = useDefault; + } + + public boolean isUseDefault() { + return useDefault; + } +} \ No newline at end of file diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorMap.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorMap.java new file mode 100644 index 00000000..09cb5794 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicColorMap.java @@ -0,0 +1,70 @@ +package org.simantics.district.network.visualisations.model; + +import java.awt.Color; +import java.util.Arrays; +import java.util.List; + +public class DynamicColorMap { + + static List blues = Arrays.asList(new RGBIntensity(0, 0, 0.1), new RGBIntensity(0, 0, 0.5), new RGBIntensity(0, 0, 0.9)); + + public static final DynamicColorMap DEFAULT = new DynamicColorMap("default", blues); + + private String label; + private List intensities; + + public DynamicColorMap(String label, List intensities) { + this.label = label; + this.intensities = intensities; + } + + public String getLabel() { + return label; + } + + public List getIntensities() { + return intensities; + } + + public static class RGBIntensity { + + private double red; + private double green; + private double blue; + + public RGBIntensity(double red, double green, double blue) { + this.red = red; + this.green = green; + this.blue = blue; + } + + public double getRed() { + return red; + } + + public double getGreen() { + return green; + } + + public double getBlue() { + return blue; + } + } + + public Color getColor(double value, double defaultMin, double defaultMax) { + + double gap = defaultMax - defaultMin; + double singleGap = gap / getIntensities().size(); + + int i = 0; + while (i < getIntensities().size() - 1) { + if (value <= defaultMin + (i * singleGap)) { + break; + } + i++; + } + + RGBIntensity intensity = getIntensities().get(i); + return new Color((float)intensity.getRed(), (float)intensity.getGreen(), (float)intensity.getBlue()); + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeContribution.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeContribution.java new file mode 100644 index 00000000..009c8c43 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeContribution.java @@ -0,0 +1,83 @@ +package org.simantics.district.network.visualisations.model; + +public class DynamicSizeContribution { + + private String label; + private String moduleName; + private String attributeName; + private String unit; + private double variableGain; + private double variableBias; + private DynamicSizeMap defaultSizeMap; + private double defaultMin; + private double defaultMax; + + // for graph persistence only + private boolean used; + private boolean useDefault; + + public DynamicSizeContribution(String label, String moduleName, String attributeName, String unit, + double variableGain, double variableBias, DynamicSizeMap defaultSizeMap, double defaultMin, double defaultMax) { + this.label = label; + this.moduleName = moduleName; + this.attributeName = attributeName; + this.unit = unit; + this.variableGain = variableGain; + this.variableBias = variableBias; + this.defaultSizeMap = defaultSizeMap; + this.defaultMin = defaultMin; + this.defaultMax = defaultMax; + } + + public String getLabel() { + return label; + } + + public String getModuleName() { + return moduleName; + } + + public String getAttributeName() { + return attributeName; + } + + public String getUnit() { + return unit; + } + + public double getVariableGain() { + return variableGain; + } + + public double getVariableBias() { + return variableBias; + } + + public DynamicSizeMap getDefaultSizeMap() { + return defaultSizeMap; + } + + public double getDefaultMin() { + return defaultMin; + } + + public double getDefaultMax() { + return defaultMax; + } + + public boolean isUsed() { + return used; + } + + public void setUsed(boolean used) { + this.used = used; + } + + public boolean isUseDefault() { + return useDefault; + } + + public void setUseDefault(boolean useDefault) { + this.useDefault = useDefault; + } +} \ No newline at end of file diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeMap.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeMap.java new file mode 100644 index 00000000..7edb12b9 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicSizeMap.java @@ -0,0 +1,38 @@ +package org.simantics.district.network.visualisations.model; + +import java.util.List; + +public class DynamicSizeMap { + + private String label; + private List sizes; + + public DynamicSizeMap(String label, List sizes) { + this.label = label; + this.sizes = sizes; + } + + public String getLabel() { + return label; + } + + public List getSizes() { + return sizes; + } + + public double getSize(double value, double defaultMin, double defaultMax) { + + double gap = defaultMax - defaultMin; + double singleGap = gap / getSizes().size(); + + int i = 0; + while (i < getSizes().size() - 1) { + if (value <= defaultMin + (i * singleGap)) { + break; + } + i++; + } + + return getSizes().get(i); + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicVisualisation.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicVisualisation.java new file mode 100644 index 00000000..ea88e9de --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/DynamicVisualisation.java @@ -0,0 +1,37 @@ +package org.simantics.district.network.visualisations.model; + +import java.util.Map; + +public class DynamicVisualisation { + + private String name; + + private Map colorContributions; + private ColorBarOptions colorBarOptions; + private Map sizeContributions; + private SizeBarOptions sizeBarOptions; + + public DynamicVisualisation(String name, Map colorContributions, ColorBarOptions colorBarOptions, Map sizeContributions, SizeBarOptions sizeBarOptions) { + this.name = name; + this.colorContributions = colorContributions; + this.colorBarOptions = colorBarOptions; + this.sizeContributions = sizeContributions; + this.sizeBarOptions = sizeBarOptions; + } + + public Map getColorContributions() { + return colorContributions; + } + + public ColorBarOptions getColorBarOptions() { + return colorBarOptions; + } + + public Map getSizeContributions() { + return sizeContributions; + } + + public SizeBarOptions getSizeBarOptions() { + return sizeBarOptions; + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/SizeBarOptions.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/SizeBarOptions.java new file mode 100644 index 00000000..14e9f47f --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/model/SizeBarOptions.java @@ -0,0 +1,66 @@ +package org.simantics.district.network.visualisations.model; + +public class SizeBarOptions { + + private boolean showColorBars; + private boolean showColorBarsTicks; + private SizeBarsLocation location; + private SizeBarsSize size; + + public boolean isShowSizeBars() { + return showColorBars; + } + + public SizeBarOptions showSizeBars(boolean show) { + this.showColorBars = show; + return this; + } + + public boolean isShowSizeBarsTicks() { + return showColorBarsTicks; + } + + public SizeBarOptions showSizeBarsTicks(boolean show) { + this.showColorBarsTicks = show; + return this; + } + + public SizeBarsLocation getLocation() { + return location; + } + + public SizeBarOptions withLocation(SizeBarsLocation location) { + this.location = location; + return this; + } + + public SizeBarsSize getSize() { + return size; + } + + public SizeBarOptions withSize(SizeBarsSize size) { + this.size = size; + return this; + } + public enum SizeBarsLocation { + NORTH, EAST, SOUTH, WEST + } + + public enum SizeBarsSize { + SMALL(1), MEDIUM(2), LARGE(3); + + int size; + + SizeBarsSize(int size) { + this.size = size; + } + + public double getSize() { + return size; + } + } + + public static SizeBarOptions useDefault() { + return new SizeBarOptions().showSizeBars(true).withLocation(SizeBarsLocation.EAST).withSize(SizeBarsSize.SMALL); + } +} -- 2.45.2