Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorGradientAdjustingCanvas.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.utils.ui.color;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.List;\r
16 \r
17 import org.eclipse.jface.viewers.ISelection;\r
18 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
19 import org.eclipse.jface.viewers.ISelectionProvider;\r
20 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
21 import org.eclipse.jface.viewers.StructuredSelection;\r
22 import org.eclipse.swt.SWT;\r
23 import org.eclipse.swt.events.MouseEvent;\r
24 import org.eclipse.swt.events.MouseListener;\r
25 import org.eclipse.swt.events.MouseMoveListener;\r
26 import org.eclipse.swt.graphics.Color;\r
27 import org.eclipse.swt.graphics.GC;\r
28 import org.eclipse.swt.graphics.Image;\r
29 import org.eclipse.swt.graphics.Rectangle;\r
30 import org.eclipse.swt.widgets.Composite;\r
31 import org.eclipse.swt.widgets.Display;\r
32 \r
33 /**\r
34  * \r
35  * Canvas that shows color gradients and color positions.\r
36  * Without READ_ONLY style the canvas allows user to drag color positions.\r
37  * \r
38  * @author Marko Luukkainen\r
39  *\r
40  */\r
41 public class ColorGradientAdjustingCanvas extends ColorGradientCanvas implements ISelectionProvider{\r
42         \r
43         ColorValue[] values;\r
44         int last;\r
45         int coords[];\r
46         int size = 8;\r
47         int sized2 = 4;\r
48         int width;\r
49         int height;\r
50         \r
51         int selectedValueIndex = -1;\r
52         \r
53         public ColorGradientAdjustingCanvas(Composite parent, int style) {\r
54                 super(parent,style|SWT.DOUBLE_BUFFERED|SWT.NO_BACKGROUND);\r
55                 addMouseListener(new MouseListener() {\r
56                         \r
57                         @Override\r
58                         public void mouseUp(MouseEvent e) {\r
59                                 \r
60                         }\r
61                         \r
62                         @Override\r
63                         public void mouseDown(MouseEvent e) {\r
64                                 // store and reset selection\r
65                                 int prev = selectedValueIndex;\r
66                                 selectedValueIndex = -1;\r
67                                 \r
68                                 // locate closest ColorValue, and select it.\r
69                                 int d = Integer.MAX_VALUE;\r
70                                 for (int i = 0; i <= last; i++) {\r
71                                         int x = coords[i*2];\r
72                                 int y = coords[i*2+1];\r
73                                 int dx = Math.abs(x - e.x);\r
74                                 int dy = Math.abs(y - e.y);\r
75                                 if ((dx < size) &&\r
76                                         (dy < size)) {\r
77                                         int dd = dx+dy;\r
78                                         if (dd < d) {\r
79                                                 selectedValueIndex = i;\r
80                                                 d = dd;\r
81                                         }\r
82                                 }\r
83                                 }\r
84                                 // if selection was changed, update it.\r
85                                 if (prev != selectedValueIndex) {\r
86                                         updateSelection();\r
87                                         redraw();\r
88                                 }\r
89                         }\r
90                         \r
91                         @Override\r
92                         public void mouseDoubleClick(MouseEvent e) {\r
93                                 \r
94                         }\r
95                 });\r
96                 if ((style&SWT.READ_ONLY) == 0) {\r
97                         addMouseMoveListener(new MouseMoveListener() {\r
98                                 \r
99                                 @Override\r
100                                 public void mouseMove(MouseEvent e) {\r
101                                         if ((e.stateMask & SWT.BUTTON1)>0) {\r
102                                                 if (selectedValueIndex > 0 && selectedValueIndex < last) {\r
103                                                         double d;\r
104                                                         if ((ColorGradientAdjustingCanvas.this.style | SWT.HORIZONTAL) > 0) {\r
105                                                                 d = (double)e.x/(double)width;\r
106                                                         } else {\r
107                                                                 d = (double)e.y/(double)height;\r
108                                                         }\r
109                                                         double r = max-min;\r
110                                                         d *= r;\r
111                                                         d += min;\r
112                                                         double offset = r*0.015;\r
113                                                         if (d <= values[selectedValueIndex-1].getValue()+offset)\r
114                                                                 d = values[selectedValueIndex-1].getValue()+offset;\r
115                                                         else if (d >= values[selectedValueIndex+1].getValue()-offset)\r
116                                                                 d = values[selectedValueIndex+1].getValue()-offset;\r
117                                                         values[selectedValueIndex]._setValue(d);\r
118                                                         calculateCoords(width, height);\r
119                                                         redraw();\r
120                                                 }\r
121                                         }\r
122                                         \r
123                                 }\r
124                         });\r
125                 }\r
126 \r
127         }\r
128         \r
129         public void setGradient(ColorGradient gradient) {\r
130                 int prevSize = 0;\r
131                 if (values != null)\r
132                         prevSize = values.length;\r
133                 \r
134                 values = gradient.getColorValueArray();\r
135                 last = values.length-1;\r
136                 coords = new int[values.length*2];\r
137                 super.setGradient(gradient);\r
138                 if (selectedValueIndex >= 0 && prevSize != values.length) {\r
139                         selectedValueIndex = -1;\r
140                         updateSelection();\r
141                 } else {\r
142                         updateSelection();\r
143                 }\r
144         }\r
145         \r
146         double min;\r
147         double max;\r
148         \r
149         private void calculateCoords(int width, int height) {\r
150                 this.width = width;\r
151                 this.height = height;\r
152                 \r
153                 min = values[0].getValue();\r
154                 max = values[last].getValue();\r
155                 \r
156                 if ((ColorGradientAdjustingCanvas.this.style & SWT.HORIZONTAL) > 0) {\r
157                         for (int i = 0; i <= last ; i++) {\r
158                                 int y = height / 2;\r
159                                 double d =  values[i].getValue();\r
160                                 int x = (int)(((d-min)/(max-min))*(double)width);\r
161                                 coords[i*2] = x;\r
162                                 coords[i*2+1] = y;\r
163                         }\r
164                 } else {\r
165                         for (int i = 0; i <= last ; i++) {\r
166                                 int x = width / 2;\r
167                                 double d =  values[i].getValue();\r
168                                 int y = (int)(((d-min)/(max-min))*(double)height);\r
169                                 coords[i*2] = x;\r
170                                 coords[i*2+1] = y;\r
171                         }\r
172                 }\r
173         }\r
174 \r
175         \r
176         @Override\r
177         protected void paintGradient(GC gc, Rectangle clip) {\r
178                 if (values != null && values.length > 0) {\r
179                         Image image = gradient.getGradientImage(clip.width,clip.height,ColorGradientAdjustingCanvas.this.style);\r
180                         gc.drawImage(image, 0, 0);\r
181                         image.dispose();        \r
182                         calculateCoords(clip.width, clip.height);\r
183 \r
184                         Color white = new Color(gc.getDevice(), 255,255,255);\r
185                         Color yellow = new Color(gc.getDevice(), 255,230,0);\r
186                         Color black = new Color(gc.getDevice(), 0, 0, 0);\r
187                         for (int i = 0; i <= last ; i++) {\r
188                                 int x = coords[i*2];\r
189                                 int y = coords[i*2+1];\r
190                                 gc.setForeground(black);\r
191                                 if (selectedValueIndex == i)\r
192                                         gc.setBackground(yellow);\r
193                                 else\r
194                                         gc.setBackground(white);\r
195                                 if (i == 0 || i == last ) {\r
196                                         gc.fillRectangle(x-sized2, y-sized2, size, size);\r
197                                         gc.drawRectangle(x-sized2, y-sized2, size, size);\r
198                                 } else {\r
199                                         gc.fillOval(x-sized2, y-sized2, size, size);\r
200                                         gc.drawOval(x-sized2, y-sized2, size, size);\r
201                                 }\r
202                         }\r
203                         \r
204                         white.dispose();\r
205                         black.dispose();\r
206                         yellow.dispose();\r
207                 } else {\r
208                         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
209                         gc.fillRectangle(clip);\r
210                 }\r
211         }\r
212         \r
213         private ISelection selection = new StructuredSelection();\r
214         private List<ISelectionChangedListener> listeners = new ArrayList<>();\r
215 \r
216         @Override\r
217         public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
218                 listeners.add(listener);\r
219         }\r
220 \r
221         @Override\r
222         public ISelection getSelection() {\r
223         return selection;\r
224         }\r
225 \r
226         @Override\r
227         public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
228                 listeners.remove(listener);\r
229         }\r
230 \r
231         @Override\r
232         public void setSelection(ISelection selection) {\r
233                 ColorValue value = (ColorValue)((StructuredSelection)selection).getFirstElement();\r
234                 selectedValueIndex = gradient.getColorValues().indexOf(value);\r
235         }\r
236         \r
237         private void updateSelection() {\r
238                 if (selectedValueIndex < 0)\r
239                         selection = new StructuredSelection();\r
240                 else\r
241                         selection = new StructuredSelection(values[selectedValueIndex]);\r
242                 \r
243                 for (ISelectionChangedListener l : listeners) {\r
244                         l.selectionChanged(new SelectionChangedEvent(this, selection));\r
245                 }\r
246         }\r
247         \r
248         public int getPointSize() {\r
249                 return size;\r
250         }\r
251         \r
252         public void setPointSize(int size) {\r
253                 this.size = size;\r
254                 this.sized2 = size/2;\r
255         }\r
256         \r
257 \r
258 }\r