]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DynamicVisualisationContributionsNode.java
Add support for gradients in dynamic visualisations
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / nodes / DynamicVisualisationContributionsNode.java
1 package org.simantics.district.network.ui.nodes;
2
3 import java.awt.AlphaComposite;
4 import java.awt.Color;
5 import java.awt.Font;
6 import java.awt.Graphics2D;
7 import java.awt.geom.AffineTransform;
8 import java.awt.geom.Rectangle2D;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Map.Entry;
12
13 import org.simantics.district.network.visualisations.model.ColorBarOptions;
14 import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsLocation;
15 import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsSize;
16 import org.simantics.district.network.visualisations.model.DynamicColorContribution;
17 import org.simantics.district.network.visualisations.model.DynamicColorMap;
18 import org.simantics.district.network.visualisations.model.DynamicColorMap.RGBIntensity;
19 import org.simantics.district.network.visualisations.model.DynamicSizeContribution;
20 import org.simantics.district.network.visualisations.model.DynamicSizeMap;
21 import org.simantics.district.network.visualisations.model.SizeBarOptions;
22 import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsLocation;
23 import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsSize;
24 import org.simantics.scenegraph.g2d.G2DNode;
25 import org.simantics.scenegraph.utils.DPIUtil;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public class DynamicVisualisationContributionsNode extends G2DNode {
30
31     private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationContributionsNode.class);
32
33     public static final String ID = "dynamicVisualisationContributionsNode";
34     
35     private static final long serialVersionUID = 7400966702826774761L;
36
37     protected boolean enabled = true;
38
39     private Map<String, DynamicColorContribution> dynamicColoringContributions;
40     private Map<String, DynamicSizeContribution> dynamicSizingContributions;
41     
42     private ColorBarOptions colorBarsOptions = ColorBarOptions.useDefault();
43     private SizeBarOptions sizeBarsOptions = SizeBarOptions.useDefault();
44
45     @Override
46     public void render(Graphics2D g2d) {
47         if (!enabled)
48             return;
49         
50         AffineTransform ot = g2d.getTransform();
51         Color oldColor = g2d.getColor();
52         
53         try {
54             g2d.transform(transform);
55             g2d.setTransform(new AffineTransform());
56             
57             Rectangle2D bounds = g2d.getClipBounds();
58             if (bounds == null)
59                 return; // FIXME
60             
61             renderColors(g2d);
62             renderSizes(g2d);
63         } finally {
64             g2d.setColor(oldColor);
65             g2d.setTransform(ot);
66         }
67     }
68
69     private double colorBarBoxWidth = 300;
70     private double colorBarBoxHeight = 50;
71     private double colorBarBoxPadding = 20;
72
73     private void renderColors(Graphics2D g2d) {
74         if (colorBarsOptions == null || !colorBarsOptions.isShowColorBars()) {
75             return;
76         }
77         ColorBarsLocation location = colorBarsOptions.getLocation();
78         ColorBarsSize size = colorBarsOptions.getSize();
79         double colorBarBoxLeft = getColorBarBoxLeft(g2d, location, size);
80         double colorBarBoxTopInitial = getColorBarBoxTop(g2d, location, size);
81         double colorBarBoxWidth = getColorBarBoxWidth(size);
82         double colorBarBoxHeight = getColorBarBoxHeight(size);
83         
84         Rectangle2D bounds = g2d.getClipBounds();
85         if (bounds == null)
86             return; // FIXME
87         
88         int i = 0;
89         
90         if (dynamicColoringContributions != null) {
91             for (Entry<String, DynamicColorContribution> object : dynamicColoringContributions.entrySet()) {
92                 DynamicColorContribution cc = object.getValue();
93                 
94                 if (!cc.isUsed())
95                     break;
96                 
97                 double min = cc.getDefaultMin();
98                 double max = cc.getDefaultMax();
99                 String unit = cc.getUnit();
100                 String label = cc.getLabel();
101                 
102                 DynamicColorMap map = cc.getDefaultColorMap();
103                 
104                 double colorBarBoxTop = (colorBarBoxTopInitial + (colorBarBoxHeight * i));
105                 i++;
106
107                 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
108                 g2d.setColor(new Color(0.9f, 0.9f, 0.9f, 0.95f));
109                 
110                 Rectangle2D vertical = new Rectangle2D.Double(colorBarBoxLeft, colorBarBoxTop, colorBarBoxWidth, colorBarBoxHeight);
111                 g2d.fill(vertical);
112                 
113                 double colorVerticalLeft = colorBarBoxLeft + 5;
114                 double colorVerticalTop = colorBarBoxTop + 15;
115                 double colorVerticalHeigth = colorBarBoxHeight - 30;
116                 List<RGBIntensity> intensities = map.getIntensities();
117                 double colorVerticalWidth = (colorBarBoxWidth - 10) / intensities.size();
118                 
119                 Font rulerFont = new Font("Tahoma", Font.PLAIN, DPIUtil.upscale(9));
120                 g2d.setFont(rulerFont);
121                 
122                 double interval = (max - min) / intensities.size();
123                 
124                 for (int j = 0; j < intensities.size(); j++) {
125                     
126                     RGBIntensity intensity = intensities.get(j);
127                     
128                     if (colorBarsOptions.isUseGradients()) {
129                         
130                         RGBIntensity upperLimitIntensity;
131                         if (j + 1 != intensities.size())
132                             upperLimitIntensity = intensities.get(j + 1);
133                         else
134                             upperLimitIntensity = intensity;
135                         
136                         double minRed = intensity.getRed();
137                         double minGreen = intensity.getGreen();
138                         double minBlue = intensity.getBlue();
139                         
140                         double maxRed = upperLimitIntensity.getRed();
141                         double maxGreen = upperLimitIntensity.getGreen();
142                         double maxBlue = upperLimitIntensity.getBlue();
143                         
144                         double redDelta = (maxRed - minRed) / colorVerticalWidth;
145                         double greenDelta = (maxGreen - minGreen) / colorVerticalWidth;
146                         double blueDelta = (maxBlue - minBlue) / colorVerticalWidth;
147                         
148                         for (int k = 0; k < colorVerticalWidth; k++) {
149                             
150                             
151                             g2d.setColor(new Color((float)(minRed + (k * redDelta)), (float)(minGreen + (k * greenDelta)), (float)(minBlue + (k * blueDelta)), 1f));
152                             Rectangle2D colorVertical = new Rectangle2D.Double(colorVerticalLeft + k, colorVerticalTop, 1, colorVerticalHeigth);
153                             g2d.fill(colorVertical);
154                         }
155                         
156                     } else {
157                         g2d.setColor(new Color((float)intensity.getRed(), (float)intensity.getGreen(), (float)intensity.getBlue(), 1f));
158                         Rectangle2D colorVertical = new Rectangle2D.Double(colorVerticalLeft, colorVerticalTop, colorVerticalWidth, colorVerticalHeigth);
159                         g2d.fill(colorVertical);
160                     }
161                     
162
163                     
164                     double value = min + j * interval;
165                     String str = Double.toString(value);
166                     if (str.length() > 4) {
167                         str = str.substring(0, 3);
168                     }
169                     g2d.setColor(Color.BLACK);
170                     g2d.drawString(str, (float)(colorVerticalLeft - 8), (float)(colorBarBoxTop + colorBarBoxHeight));
171                     colorVerticalLeft = colorVerticalLeft + colorVerticalWidth;
172                 }
173                 g2d.setColor(Color.BLACK);
174                 
175                 String str = Double.toString(max);
176                 g2d.drawString(str, (float)(colorVerticalLeft - 8), (float)(colorBarBoxTop  + colorBarBoxHeight));
177                 
178                 str = object.getKey() + " - " + label + " [" + unit + "]";
179                 g2d.drawString(str, (float)colorBarBoxLeft + 5, (float)colorBarBoxTop + 10);
180             }
181         }
182     }
183
184     private double getColorBarBoxTop(Graphics2D g2d, ColorBarsLocation location, ColorBarsSize size) {
185         Rectangle2D bounds = g2d.getClipBounds();
186         if (bounds == null)
187             throw new IllegalStateException();
188         switch (location) {
189             case NORTH: {
190                 return colorBarBoxPadding;
191             }
192             case SOUTH: {
193                 return bounds.getMaxY() - colorBarBoxPadding;
194             }
195             case EAST:
196             case WEST: {
197                 return (bounds.getMaxY() / 2) - (getColorBarBoxHeight(size) / 2);
198             }
199             default:
200                 return 0;
201         }
202     }
203     
204     private double getColorBarBoxLeft(Graphics2D g2d, ColorBarsLocation location, ColorBarsSize size) {
205         Rectangle2D bounds = g2d.getClipBounds();
206         if (bounds == null)
207             throw new IllegalStateException();
208         switch (location) {
209             case EAST: {
210                 double right = bounds.getMaxX() - colorBarBoxPadding;
211                 return right - getColorBarBoxWidth(size);
212             }
213             case WEST: {
214                 return colorBarBoxPadding;
215             }
216             case NORTH:
217             case SOUTH: {
218                 double left = (bounds.getMaxX() / 2) - (getColorBarBoxWidth(size) / 2);
219                 return left;
220             }
221             default:
222                 return 0;
223         }
224     }
225
226     private double getColorBarBoxWidth(ColorBarsSize size) {
227         return size.getSize() * colorBarBoxWidth;
228     }
229
230     private double getColorBarBoxHeight(ColorBarsSize size) {
231         return size.getSize() * colorBarBoxHeight;
232     }
233
234     private void renderSizes(Graphics2D g2d) {
235         if (sizeBarsOptions == null || !sizeBarsOptions.isShowSizeBars()) {
236             return;
237         }
238         SizeBarsLocation location = sizeBarsOptions.getLocation();
239         SizeBarsSize sizeb = sizeBarsOptions.getSize();
240         double sizeBarBoxLeft = getSizeBarBoxLeft(g2d, location, sizeb);
241         double sizeBarBoxTopInitial = getSizeBarBoxTop(g2d, location, sizeb);
242         double sizeBarBoxWidth = getSizeBarBoxWidth(sizeb);
243         double sizeBarBoxHeight = getSizeBarBoxHeight(sizeb);
244         
245         Rectangle2D bounds = g2d.getClipBounds();
246         if (bounds == null)
247             return; // FIXME
248         
249         int i = 0;
250         
251         if (dynamicSizingContributions != null) {
252             for (Entry<String, DynamicSizeContribution> object : dynamicSizingContributions.entrySet()) {
253                 DynamicSizeContribution cc = object.getValue();
254                 
255                 if (!cc.isUsed())
256                     continue;
257                 
258                 double min = cc.getDefaultMin();
259                 double max = cc.getDefaultMax();
260                 String unit = cc.getUnit();
261                 String label = cc.getLabel();
262                 
263                 DynamicSizeMap map = cc.getDefaultSizeMap();
264                 
265                 List<Double> sizes = map.getSizes();
266                 
267                 double sizeBarBoxTop = (sizeBarBoxTopInitial + (colorBarBoxHeight * i));
268                 i++;
269     
270                 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
271                 g2d.setColor(new Color(0.9f, 0.9f, 0.9f, 0.95f));
272                 
273                 Rectangle2D vertical = new Rectangle2D.Double(sizeBarBoxLeft, sizeBarBoxTop, colorBarBoxWidth, colorBarBoxHeight);
274                 g2d.fill(vertical);
275                 
276                 double sizeVerticalLeft = sizeBarBoxLeft + 5;
277                 double sizeVerticalTop = sizeBarBoxTop + 15;
278                 double sizeVerticalHeigth = colorBarBoxHeight - 30;
279     
280                 double sizeVerticalWidth = (sizeBarBoxWidth - 10) / sizes.size();
281                 
282                 Font rulerFont = new Font("Tahoma", Font.PLAIN, DPIUtil.upscale(9));
283                 g2d.setFont(rulerFont);
284     
285                 double interval = (max - min) / sizes.size();
286                 
287                 for (int j = 0; j < sizes.size(); j++) {
288                     
289                     Double size = sizes.get(j);
290                     
291                     g2d.setColor(new Color((float)0, (float)0, (float)0.8, 0.8f));
292                     double sizedWidth = (size / 5) * sizeVerticalHeigth;
293                     Rectangle2D rect = new Rectangle2D.Double(sizeVerticalLeft, (sizeVerticalTop), sizedWidth, sizeVerticalHeigth);
294                     g2d.fill(rect);
295                     
296                     double value = min + j * interval;
297                     String str = Double.toString(value);
298                     if (str.length() > 4) {
299                         str = str.substring(0, 3);
300                     }
301                     g2d.setColor(Color.BLACK);
302                     g2d.drawString(str, (float)(sizeVerticalLeft - 8), (float)(sizeBarBoxTop + sizeBarBoxHeight));
303                     
304                     sizeVerticalLeft = sizeVerticalLeft + sizeVerticalWidth;
305                 }
306                 g2d.setColor(Color.BLACK);
307                 
308                 String str = Double.toString(max);
309                 g2d.drawString(str, (int)(sizeBarBoxLeft + sizeBarBoxWidth - 30), (int)(sizeBarBoxTop + sizeBarBoxHeight));
310                 
311                 str = object.getKey() + " - " + label + " [" + unit + "]";
312                 g2d.drawString(str, (int)sizeBarBoxLeft + 5, (int)sizeBarBoxTop + 10);
313             }
314         }
315     }
316     
317     private double getSizeBarBoxTop(Graphics2D g2d, SizeBarsLocation location, SizeBarsSize size) {
318         Rectangle2D bounds = g2d.getClipBounds();
319         if (bounds == null)
320             throw new IllegalStateException();
321         switch (location) {
322             case NORTH: {
323                 return colorBarBoxPadding;
324             }
325             case SOUTH: {
326                 return bounds.getMaxY() - colorBarBoxPadding;
327             }
328             case EAST:
329             case WEST: {
330                 return (bounds.getMaxY() / 2) - (getSizeBarBoxHeight(size) / 2);
331             }
332             default:
333                 return 0;
334         }
335     }
336     
337     private double getSizeBarBoxLeft(Graphics2D g2d, SizeBarsLocation location, SizeBarsSize size) {
338         Rectangle2D bounds = g2d.getClipBounds();
339         if (bounds == null)
340             throw new IllegalStateException();
341         switch (location) {
342             case EAST: {
343                 double right = bounds.getMaxX() - colorBarBoxPadding;
344                 return right - getSizeBarBoxWidth(size);
345             }
346             case WEST: {
347                 return colorBarBoxPadding;
348             }
349             case NORTH:
350             case SOUTH: {
351                 double left = (bounds.getMaxX() / 2) - (getSizeBarBoxWidth(size) / 2);
352                 return left;
353             }
354             default:
355                 return 0;
356         }
357     }
358
359     private double getSizeBarBoxWidth(SizeBarsSize size) {
360         return size.getSize() * colorBarBoxWidth;
361     }
362
363     private double getSizeBarBoxHeight(SizeBarsSize size) {
364         return size.getSize() * colorBarBoxHeight;
365     }
366
367     @Override
368     public Rectangle2D getBoundsInLocal() {
369         return null;
370     }
371
372     public void setEnabled(boolean enabled) {
373         this.enabled = enabled;
374     }
375
376     public void setDynamicColoringObjects(Map<String,DynamicColorContribution> dynamicColoringObjects) {
377         this.dynamicColoringContributions = dynamicColoringObjects;
378     }
379
380     public void setColorBarOptions(ColorBarOptions colorBarsOptions) {
381         this.colorBarsOptions = colorBarsOptions;
382     }
383
384     public void setDynamicSizingObjects(Map<String, DynamicSizeContribution> dynamicSizingObjects) {
385         this.dynamicSizingContributions = dynamicSizingObjects;
386     }
387
388     public void setSizeBarOptions(SizeBarOptions sizeBarOptions) {
389         this.sizeBarsOptions = sizeBarOptions;
390     }
391
392 }