1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package net.sf.jtreemap.ktreemap.example;
34
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.events.PaintEvent;
37 import org.eclipse.swt.events.PaintListener;
38 import org.eclipse.swt.graphics.Color;
39 import org.eclipse.swt.graphics.GC;
40 import org.eclipse.swt.graphics.Point;
41 import org.eclipse.swt.widgets.Canvas;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Display;
44 import net.sf.jtreemap.ktreemap.ITreeMapColorProvider;
45 import net.sf.jtreemap.ktreemap.ITreeMapProvider;
46 import net.sf.jtreemap.ktreemap.KTreeMap;
47 import net.sf.jtreemap.ktreemap.TreeMapNode;
48
49 /**
50 * An HSB color space color provider for KTreeMap. Uses a specified function to
51 * map the values onto the HSB color space. The default is a linear function,
52 * but in my experience one of the logarithmic ones works best for this color
53 * space.
54 *
55 * @author Andy Adamczak
56 */
57 public class HSBTreeMapColorProvider implements ITreeMapColorProvider {
58 protected KTreeMap m_jTreeMap;
59 protected double m_maxValue = Double.MIN_VALUE;
60 protected double m_minValue = Double.MAX_VALUE;
61 private float m_positiveHue;
62 private float m_negativeHue;
63 private float m_positiveSaturation = 1f;
64 private float m_negativeSaturation = 1f;
65
66 private ColorDistributionTypes m_colorDistribution = ColorDistributionTypes.Linear;
67
68 /**
69 * @param treeMap
70 * @param color
71 */
72 public HSBTreeMapColorProvider(KTreeMap treeMap, Color color) {
73 this(treeMap, ColorDistributionTypes.Linear, color, color);
74 }
75
76 /**
77 * @param treeMap
78 * @param positiveColor
79 * @param negativeColor
80 */
81 public HSBTreeMapColorProvider(KTreeMap treeMap, Color positiveColor,
82 Color negativeColor) {
83 this(treeMap, ColorDistributionTypes.Linear, positiveColor, negativeColor);
84 }
85
86 /**
87 * @param treeMap
88 * @param colorDistribution
89 * @param color
90 */
91 public HSBTreeMapColorProvider(KTreeMap treeMap,
92 ColorDistributionTypes colorDistribution, Color color) {
93 this(treeMap, colorDistribution, color, color);
94 }
95
96 /**
97 * @param treeMap
98 * @param colorDistribution
99 * @param positiveColor
100 * @param negativeColor
101 */
102 public HSBTreeMapColorProvider(KTreeMap treeMap,
103 ColorDistributionTypes colorDistribution, Color positiveColor,
104 Color negativeColor) {
105 super();
106 m_jTreeMap = treeMap;
107 m_colorDistribution = colorDistribution;
108 adjustColor(positiveColor, negativeColor);
109 }
110
111 /**
112 * @param treeMap
113 * @param colorDistribution
114 * @param hue
115 * @param saturation
116 */
117 public HSBTreeMapColorProvider(KTreeMap treeMap,
118 ColorDistributionTypes colorDistribution, float hue, float saturation) {
119 this(treeMap, colorDistribution, hue, saturation, hue, saturation);
120 }
121
122 /**
123 * @param treeMap
124 * @param colorDistribution
125 * @param positiveHue
126 * @param positiveSaturation
127 * @param negativeHue
128 * @param negativeSaturation
129 */
130 public HSBTreeMapColorProvider(KTreeMap treeMap,
131 ColorDistributionTypes colorDistribution, float positiveHue,
132 float positiveSaturation, float negativeHue, float negativeSaturation) {
133 super();
134 m_jTreeMap = treeMap;
135 m_colorDistribution = colorDistribution;
136 adjustColor(positiveHue, positiveSaturation, negativeHue,
137 negativeSaturation);
138 }
139
140 /**
141 * @param treeMap
142 * @param hue
143 * @param saturation
144 */
145 public HSBTreeMapColorProvider(KTreeMap treeMap, float hue, float saturation) {
146 this(treeMap, ColorDistributionTypes.Linear, hue, saturation, hue,
147 saturation);
148 }
149
150 /**
151 * @param treeMap
152 * @param positiveHue
153 * @param positiveSaturation
154 * @param negativeHue
155 * @param negativeSaturation
156 */
157 public HSBTreeMapColorProvider(KTreeMap treeMap, float positiveHue,
158 float positiveSaturation, float negativeHue, float negativeSaturation) {
159 this(treeMap, ColorDistributionTypes.Linear, positiveHue,
160 positiveSaturation, negativeHue, negativeSaturation);
161 }
162
163 /**
164 * @param color
165 */
166 public void adjustColor(Color color) {
167 adjustColor(color, color);
168 }
169
170 /**
171 * @param positiveColor
172 * @param negativeColor
173 */
174 public void adjustColor(Color positiveColor, Color negativeColor) {
175
176
177
178
179 float[] hsbvals = new float[3];
180
181 hsbvals = java.awt.Color.RGBtoHSB(positiveColor.getRed(), positiveColor
182 .getGreen(), positiveColor.getBlue(), hsbvals);
183 m_positiveHue = hsbvals[0];
184 m_positiveSaturation = 1f;
185
186 hsbvals = java.awt.Color.RGBtoHSB(negativeColor.getRed(), negativeColor
187 .getGreen(), negativeColor.getBlue(), hsbvals);
188 m_negativeHue = hsbvals[0];
189 m_negativeSaturation = 1f;
190 }
191
192 /**
193 * @param hue
194 * @param saturation
195 */
196 public void adjustColor(float hue, float saturation) {
197 adjustColor(hue, saturation, hue, saturation);
198 }
199
200 /**
201 * @param positiveHue
202 * @param positiveSaturation
203 * @param negativeHue
204 * @param negativeSaturation
205 */
206 public void adjustColor(float positiveHue, float positiveSaturation,
207 float negativeHue, float negativeSaturation) {
208 m_positiveHue = positiveHue;
209 m_positiveSaturation = positiveSaturation;
210 m_negativeHue = negativeHue;
211 m_negativeSaturation = negativeSaturation;
212 }
213
214 public Color getBackground(Object value) {
215
216
217
218 if (m_maxValue == Double.MIN_VALUE || m_minValue == Double.MAX_VALUE) {
219 setValues(m_jTreeMap.getRoot());
220 }
221 ITreeMapProvider provider = m_jTreeMap.getTreeMapProvider();
222 double val = provider.getDoubleValue(value);
223
224 return getBackground(val);
225 }
226
227 public Color getForeground(Object value) {
228 return Display.getDefault().getSystemColor(SWT.COLOR_WHITE);
229 }
230
231 public Composite getLegend(Composite parent, int style) {
232 return new Legend(parent, style);
233 }
234
235 /**
236 * Set the max and the min values in the tree map
237 *
238 * @param root root of the JTreeMap
239 */
240 void setValues(TreeMapNode root) {
241 if (root.isLeaf()) {
242 Object value = root.getValue();
243 ITreeMapProvider provider = m_jTreeMap.getTreeMapProvider();
244 double rootValue = provider.getDoubleValue(value);
245 if (rootValue >= m_maxValue) {
246 m_maxValue = rootValue;
247 }
248
249 if (rootValue <= m_minValue) {
250 m_minValue = rootValue;
251 }
252 } else {
253 for (TreeMapNode node : root.getChildren()) {
254 setValues(node);
255 }
256 }
257 }
258
259 /**
260 * Given a value, maps that value to a new value using the specified math
261 * function
262 *
263 * @param value the value to convert
264 * @return the converted value
265 */
266 private double adjustValue(double value) {
267 switch (m_colorDistribution) {
268 case Log:
269 return Math.log1p(value);
270 case Exp:
271 return Math.exp(value);
272 case SquareRoot:
273 return Math.sqrt(value);
274 case CubicRoot:
275 return Math.cbrt(value);
276 default:
277
278 return value;
279 }
280 }
281
282 private Color getBackground(double val) {
283 double maxValue = m_maxValue;
284 double minValue = m_minValue;
285 if (val >= 0) {
286
287 double range = maxValue - Math.max(0, minValue);
288 val -= Math.max(0, minValue);
289 range = adjustValue(range);
290 java.awt.Color cc = new java.awt.Color(java.awt.Color.HSBtoRGB(
291 m_positiveHue, m_positiveSaturation,
292 (float)(adjustValue(val) / range)));
293 return ResourceManager.getColor(cc.getRed(), cc.getGreen(), cc.getBlue());
294 }
295
296
297 double range = Math.abs(minValue - Math.min(0, maxValue));
298 val += Math.min(0, maxValue);
299 val = Math.abs(val);
300
301
302 range = adjustValue(range);
303 java.awt.Color cc = new java.awt.Color(java.awt.Color.HSBtoRGB(
304 m_negativeHue, m_negativeSaturation, (float)(adjustValue(val) / range)));
305 return ResourceManager.getColor(cc.getRed(), cc.getGreen(), cc.getBlue());
306 }
307
308 /**
309 * @author Andy Adamczak
310 */
311 public enum ColorDistributionTypes {
312 /**
313 *
314 */
315 Linear,
316 /**
317 *
318 */
319 Log,
320 /**
321 *
322 */
323 Exp,
324 /**
325 *
326 */
327 SquareRoot,
328 /**
329 *
330 */
331 CubicRoot
332 }
333
334 private class Legend extends Canvas {
335
336 /**
337 * Constructor
338 * @param parent parent Composite
339 * @param style style
340 */
341 public Legend(Composite parent, int style) {
342 super(parent, style);
343
344 addPaintListener(new PaintListener() {
345 public void paintControl(PaintEvent e) {
346 Legend.this.paintControl(e);
347 }
348 });
349 }
350
351 @Override
352 public Point computeSize(int wHint, int hHint, boolean changed) {
353 int height = 20;
354 if (hHint != SWT.DEFAULT)
355 height = hHint;
356 return new Point(wHint, height);
357 }
358
359 protected void paintControl(PaintEvent e) {
360 GC gc = e.gc;
361 int width = this.getBounds().width;
362 double step = (m_maxValue - m_minValue) / width;
363 double value = m_minValue;
364 for (int i = 0; i < width; i++) {
365 gc.setBackground(HSBTreeMapColorProvider.this.getBackground(value));
366 gc.fillRectangle(i, 0, 1, this.getBounds().height);
367 value += step;
368 }
369 }
370 }
371 }
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387