]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorAlphaGradient.java
1 package org.simantics.utils.ui.color;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6
7 import org.eclipse.swt.SWT;
8 import org.eclipse.swt.graphics.Color;
9 import org.eclipse.swt.graphics.GC;
10 import org.eclipse.swt.graphics.Image;
11 import org.eclipse.swt.widgets.Display;
12
13 public class ColorAlphaGradient extends ColorGradient {
14         
15         List<Integer> alphaValues;
16         
17         
18         public ColorAlphaGradient() {
19                 super();
20                 this.alphaValues = new ArrayList<>();
21         }
22         
23         public ColorAlphaGradient(ColorAlphaGradient copyFrom) {
24                 super(copyFrom);
25                 this.alphaValues = copyFrom.alphaValues;
26     }
27         
28         public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {
29                 super(array);
30                 if (array.length != alphaArray.length)
31                         throw new IllegalArgumentException("Array lenghts do not match.");
32                 this.alphaValues = new ArrayList<>(alphaArray.length);
33                 for (int a : alphaArray) {
34             alphaValues.add(a);
35         }
36         }
37         
38         public ColorAlphaGradient(ColorValue array[], int alphaArray[], int type) {
39                 super(array, type);
40                 if (array.length != alphaArray.length)
41                         throw new IllegalArgumentException("Array lenghts do not match.");
42                 this.alphaValues = new ArrayList<>(alphaArray.length);
43                 for (int a : alphaArray) {
44             alphaValues.add(a);
45         }
46         }
47         
48         public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {
49                 super(values);
50                 if (values.size() != alphaValues.size())
51                         throw new IllegalArgumentException("Array lenghts do not match.");
52                 this.alphaValues = new ArrayList<>(alphaValues);
53         }
54         
55         public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues, int type) {
56                 super(values, type);
57                 if (values.size() != alphaValues.size())
58                         throw new IllegalArgumentException("Array lenghts do not match.");
59                 this.alphaValues = new ArrayList<>(alphaValues);
60         }
61         
62          /**
63      * Interpolates color in RGB space
64      * 
65      * @param value
66      * @return
67      */
68     private byte[] getRGBColor(double value) {
69         int index = 1;
70         while (values.get(index).getValue() <= value && index < values.size()-1)
71             index++;
72
73         value -= values.get(index - 1).getValue();
74         value /= (values.get(index).getValue() - values.get(index - 1).getValue());
75         double valuei = 1.0 - value;
76         byte color[] = new byte[] {
77                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getR() + valuei * values.get(index - 1).getColor().getR())),
78                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getG() + valuei * values.get(index - 1).getColor().getG())),
79                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getB() + valuei * values.get(index - 1).getColor().getB())),
80                 (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};
81         return color;
82
83     }
84
85     /**
86      * Interpolates color in HSV space
87      * 
88      * @param value
89      * @return
90      */
91     private byte[] getHSVColor(double value) {
92         int index = 1;
93         while (values.get(index).getValue() <= value && index < values.size()-1)
94             index++;
95
96         value -= values.get(index - 1).getValue();
97         value /= (values.get(index).getValue() - values.get(index - 1).getValue());
98         double valuei = 1.0 - value;
99         double h;
100         if (Float.isNaN(values.get(index).getColor().getH())) {
101             h = values.get(index-1).getColor().getH();
102         } else if (Float.isNaN(values.get(index-1).getColor().getH())) {
103             h = values.get(index).getColor().getH();
104         } else {
105             // selecting shortest direction between hues
106             float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();
107             if (angle > 180.f)
108                 angle -= 360.f;
109             else if (angle < -180.f)
110                 angle += 360.f;
111             h = values.get(index - 1).getColor().getH() + value * angle;
112             if (h > 360.f)
113                 h -= 360.f;
114             else if (h < 0.f)
115                 h+= 360.f;
116         }
117         org.simantics.utils.ui.color.Color interpolated = new org.simantics.utils.ui.color.Color(h, value * values.get(index).getColor().getS() + valuei * values.get(index - 1).getColor().getS(),
118                 value * values.get(index).getColor().getV() + valuei * values.get(index - 1).getColor().getV());
119         byte color[] = new byte[] { (byte) interpolated.getR(), (byte) interpolated.getG(), (byte) interpolated.getB(), (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};
120
121         return color;
122
123     }
124
125     /**
126      * <p>
127      * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.
128      * </p>
129      * <p>
130      * If gradient contains only one color array is filled with that color
131      * </p>
132      * <p>
133      * if gradient has no colors array is filled with white
134      * </p>
135      * @param size number of pixels
136      * @return gradient in array of bytes
137      */
138     public byte[] getGradientArray(int size) {
139         byte array[] = new byte[size * 4];
140         if (values.size() > 1) {
141             for (int i = 0; i < size; i++) {
142                 int index = i * 4;
143                 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;
144                 byte color[];
145                 if (type == RGB)
146                     color = getRGBColor(value);
147                 else
148                     color = getHSVColor(value);
149                 array[index] = color[0];
150                 array[index + 1] = color[1];
151                 array[index + 2] = color[2];
152                 array[index + 3] = color[3];
153             }
154         } else if (values.size() == 1) {
155             byte color[] = new byte[3];
156             color[0] = (byte)values.get(0).getColor().getR();
157             color[1] = (byte)values.get(0).getColor().getG();
158             color[2] = (byte)values.get(0).getColor().getB();
159             color[3] = (byte)(int)alphaValues.get(0);
160             for (int i = 0; i < size; i++) {
161                 int index = i * 3;
162                 array[index] = color[0];
163                 array[index + 1] = color[1];
164                 array[index + 2] = color[2];
165                 array[index + 3] = color[3];
166             }
167         } else {
168             for (int i = 0; i < size; i++) {
169                 int index = i * 4;
170                 array[index] = (byte)255;
171                 array[index + 1] = (byte)255;
172                 array[index + 2] = (byte)255;
173                 array[index + 3] = (byte)255;
174             }
175         }
176         return array;
177     }
178
179     /**
180      * <p>
181      * Returns gradient in image.
182      * </p>
183      * <p>
184      * If gradient contains only one color image is filled with that color
185      * </p>
186      * <p>
187      * if gradient has no colors image is filled with white
188      * </p>
189      * <p>
190      * Style must be set to  <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>
191      * </p>
192      * @param size number of pixels
193      * @return gradient in array of bytes
194      */
195     
196     public Image getGradientImage(int width, int height, int style) {
197         Image image = new Image(Display.getCurrent(), width, height);
198         GC gc = new GC(image);
199         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
200         gc.fillRectangle(0, 0, width, height);
201         if (values.size() > 1) {
202             if (SWT.HORIZONTAL == (style | SWT.HORIZONTAL)) {
203                 for (int x = 0; x < width; x++) {
204                     double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) x / (double) (width - 1);
205                     byte byteColor[];
206                     if (type == RGB)
207                         byteColor = getRGBColor(value);
208                     else
209                         byteColor = getHSVColor(value);
210                     Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);
211                     gc.setForeground(color);
212                     gc.drawLine(x, 0, x, height);
213                     color.dispose();
214                 }
215             } else if (SWT.VERTICAL == (style | SWT.VERTICAL)){
216                 for (int y = 0; y < height; y++) {
217                     double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) y
218                             / (double) (height - 1);
219                     byte byteColor[];
220                     if (type == RGB)
221                         byteColor = getRGBColor(value);
222                     else
223                         byteColor = getHSVColor(value);
224                     Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);
225                     gc.setForeground(color);
226                     gc.drawLine(0, y, width, y);
227                     color.dispose();
228                 }
229             } else {
230                 gc.dispose();
231                 image.dispose();
232                 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
233             }
234         } else if (values.size() == 1) {
235             Color color = new Color(Display.getCurrent(), values.get(0).getColor().getR(), values.get(0).getColor().getG(), values.get(0).getColor().getB(), alphaValues.get(0));      
236             gc.setBackground(color);
237             gc.fillRectangle(0, 0, width, height);
238             color.dispose();
239         } else {
240             gc.fillRectangle(0, 0, width, height);
241         }
242         gc.dispose();
243         return image;
244     }
245     
246     @Override
247     public boolean equals(Object obj) {
248         if (super.equals(obj)) {
249                 ColorAlphaGradient cg = (ColorAlphaGradient)obj;
250                 return alphaValues.containsAll(cg.alphaValues);
251         } else {
252                 return false;
253         }
254     }
255
256 }