]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorGradientComposite.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 \r
15 import java.util.ArrayList;\r
16 import java.util.Collections;\r
17 import java.util.HashMap;\r
18 \r
19 import org.eclipse.jface.util.IPropertyChangeListener;\r
20 import org.eclipse.jface.util.PropertyChangeEvent;\r
21 import org.eclipse.jface.viewers.CellEditor;\r
22 import org.eclipse.jface.viewers.ColorCellEditor;\r
23 import org.eclipse.jface.viewers.ICellEditorListener;\r
24 import org.eclipse.jface.viewers.ICellModifier;\r
25 import org.eclipse.jface.viewers.ILabelProviderListener;\r
26 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
27 import org.eclipse.jface.viewers.IStructuredContentProvider;\r
28 import org.eclipse.jface.viewers.IStructuredSelection;\r
29 import org.eclipse.jface.viewers.ITableLabelProvider;\r
30 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
31 import org.eclipse.jface.viewers.TableViewer;\r
32 import org.eclipse.jface.viewers.TextCellEditor;\r
33 import org.eclipse.jface.viewers.Viewer;\r
34 import org.eclipse.swt.SWT;\r
35 import org.eclipse.swt.events.SelectionEvent;\r
36 import org.eclipse.swt.events.SelectionListener;\r
37 import org.eclipse.swt.graphics.Image;\r
38 import org.eclipse.swt.graphics.RGB;\r
39 import org.eclipse.swt.layout.FillLayout;\r
40 import org.eclipse.swt.layout.FormAttachment;\r
41 import org.eclipse.swt.layout.FormData;\r
42 import org.eclipse.swt.layout.FormLayout;\r
43 import org.eclipse.swt.widgets.Button;\r
44 import org.eclipse.swt.widgets.ColorDialog;\r
45 import org.eclipse.swt.widgets.Composite;\r
46 import org.eclipse.swt.widgets.Group;\r
47 import org.eclipse.swt.widgets.Label;\r
48 import org.eclipse.swt.widgets.Table;\r
49 import org.eclipse.swt.widgets.TableColumn;\r
50 import org.eclipse.swt.widgets.TableItem;\r
51 \r
52 /**\r
53  * Widget to create and edit color gradients\r
54  * \r
55  * @author Marko Luukkainen\r
56  *\r
57  */\r
58 public class ColorGradientComposite extends Composite implements ISelectionChangedListener, ICellEditorListener, IPropertyChangeListener{\r
59         private static int ICON_WIDTH = 36;\r
60         private static int ICON_HEIGHT = 14;\r
61         \r
62         private static final String COLOR_ID = "Color";\r
63         private static final String VALUE_ID = "Value";\r
64         \r
65         \r
66         private ColorGradientCanvas gradientComposite;\r
67         //private Table table;\r
68         private TableViewer viewer;\r
69         private Button addButton;\r
70         private Button editButton;\r
71         private Button removeButton;\r
72         private Button rgbButton;\r
73         private Button hsvButton;\r
74         private int type = ColorGradient.RGB;\r
75         \r
76         private ArrayList<ColorValue> values = new ArrayList<ColorValue>();\r
77         //private ArrayList<Image> images = new ArrayList<Image>();\r
78         //private HashMap<TableItem,ColorValue> items = new HashMap<TableItem,ColorValue>();\r
79         private HashMap<ColorValue,Image> images = new HashMap<ColorValue,Image>();\r
80         \r
81         \r
82         \r
83         public ColorGradientComposite(Composite parent, int style) {\r
84                 super(parent,style);\r
85             FormLayout layout = new FormLayout();\r
86             this.setLayout(layout);\r
87             gradientComposite = new ColorGradientCanvas(this,SWT.HORIZONTAL);\r
88             \r
89             Group typeComposite = new Group(this,SWT.NONE);\r
90             typeComposite.setText("Color interpolation type");\r
91             \r
92             typeComposite.setLayout(new FillLayout(SWT.HORIZONTAL));\r
93             Label rgbLabel = new Label(typeComposite,SWT.NONE);\r
94             rgbLabel.setText("RGB");\r
95             rgbButton = new Button(typeComposite,SWT.RADIO);\r
96             rgbButton.setSelection(true);\r
97             rgbButton.addSelectionListener(new SelectionListener() {\r
98                 public void widgetDefaultSelected(SelectionEvent e) {\r
99                         widgetSelected(e);\r
100                 }\r
101                 public void widgetSelected(SelectionEvent e) {\r
102                         rgbButton.setSelection(true);\r
103                         hsvButton.setSelection(false);\r
104                         type = ColorGradient.RGB;\r
105                         gradientComposite.setGradient(new ColorGradient(values,type));\r
106                 }\r
107             });\r
108             Label hsvLabel = new Label(typeComposite,SWT.NONE);\r
109             hsvLabel.setText("HSV");\r
110             hsvButton = new Button(typeComposite,SWT.RADIO);\r
111             hsvButton.addSelectionListener(new SelectionListener() {\r
112                 public void widgetDefaultSelected(SelectionEvent e) {\r
113                         widgetSelected(e);\r
114                 }\r
115                 public void widgetSelected(SelectionEvent e) {\r
116                         hsvButton.setSelection(true);\r
117                         rgbButton.setSelection(false);\r
118                         type = ColorGradient.HSV;\r
119                         gradientComposite.setGradient(new ColorGradient(values,type));\r
120                 }\r
121             });\r
122             viewer = new TableViewer(this,SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);\r
123             //table = new Table(this,SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);\r
124             final Table table = viewer.getTable();\r
125             table.setLinesVisible(true);\r
126             table.setHeaderVisible(true);\r
127             \r
128             viewer.addSelectionChangedListener(this);\r
129             viewer.addPostSelectionChangedListener(this);\r
130             \r
131             TableColumn column = new TableColumn(table,SWT.RIGHT);\r
132             column.setText("Color");\r
133             column.setWidth(40);\r
134             column.setMoveable(false);\r
135             column.setResizable(false);\r
136             column = new TableColumn(table,SWT.LEFT);\r
137             column.setText("Value");\r
138             column.setWidth(300);\r
139             column.setMoveable(false);\r
140             \r
141             viewer.setColumnProperties(new String[]{COLOR_ID,VALUE_ID});\r
142             \r
143             viewer.setLabelProvider(new TableLabelProvider());\r
144             viewer.setContentProvider(new TableContentProvider());\r
145             viewer.setInput(values);\r
146             \r
147             final ColorCellEditor colorEditor = new ColorCellEditor(table);\r
148             final TextCellEditor valueEditor = new TextCellEditor(table);\r
149             colorEditor.addListener(this);\r
150             valueEditor.addListener(this);\r
151             valueEditor.addPropertyChangeListener(this);\r
152             viewer.setCellEditors(new CellEditor[]{colorEditor,valueEditor});\r
153             \r
154             viewer.setCellModifier(new TableCellEditorModifier());    \r
155             \r
156             \r
157             Composite buttonComposite = new Composite(this,SWT.NONE);\r
158             \r
159             \r
160             buttonComposite.setLayout(new FillLayout(SWT.HORIZONTAL));\r
161             \r
162             addButton = new Button(buttonComposite,SWT.PUSH);\r
163             addButton.setText("Add new color");\r
164             addButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
165                 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
166                         ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);\r
167                 \r
168                 RGB rgb = dialog.open();\r
169                 if (rgb != null) {\r
170                     Color c = new Color(rgb.red,rgb.green,rgb.blue);\r
171                     Double value;\r
172                     if (values.size() == 0) {\r
173                         value = 0.0;\r
174                     } else if (values.size() == 1) {\r
175                         value = 100.0;\r
176                     } else {\r
177                         // FIXME : insert some logic here\r
178                         value = 100.0 * Math.random();\r
179                     }\r
180                     \r
181                     addColor(c,value);\r
182                 }\r
183             }\r
184         });\r
185             editButton = new Button(buttonComposite,SWT.PUSH);\r
186             editButton.setText("Edit color");\r
187             editButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
188                 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
189                         TableItem selection[] = table.getSelection();\r
190                         if (selection.length > 0) {\r
191                                 TableItem selected = selection[0];\r
192                                 Object obj = selected.getData();\r
193                                 if (obj instanceof ColorValue) {\r
194                                         ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);\r
195                                         dialog.setRGB(getRGB(((ColorValue)obj).getColor()));\r
196                                         RGB rgb = dialog.open();\r
197                         if (rgb != null) {\r
198                                 modifyColorValueColor((ColorValue)obj,rgb);\r
199                         }\r
200                                 }                       \r
201                         }\r
202                 }\r
203         });\r
204             editButton.setEnabled(false);\r
205             removeButton = new Button(buttonComposite,SWT.PUSH);\r
206             removeButton.setText("Remove color");\r
207             removeButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
208                 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
209                         TableItem selection[] = table.getSelection();\r
210                         if (selection.length > 0) {\r
211                                 TableItem selected = selection[0];\r
212                                 Object o = selected.getData();\r
213                                 if (o instanceof ColorValue) {\r
214                                         Image i = images.get(o);\r
215                                         i.dispose();\r
216                                         images.remove(o);\r
217                                         values.remove(o);\r
218                                         updateWidgets();\r
219                                 }                       \r
220                         }\r
221                 }\r
222         });\r
223             removeButton.setEnabled(false);\r
224             \r
225             FormData gradientData = new FormData();\r
226             gradientData.top = new FormAttachment(0,0);\r
227             gradientData.left = new FormAttachment(0,0);\r
228             gradientData.right = new FormAttachment(100,0);\r
229             gradientData.height = 40;\r
230             gradientComposite.setLayoutData(gradientData);\r
231                \r
232             FormData typeData = new FormData();     \r
233             typeData.left = new FormAttachment(0,0);\r
234             typeData.right = new FormAttachment(100,0);\r
235             typeData.top = new FormAttachment(gradientComposite,0,SWT.BOTTOM);\r
236             typeData.height = 20;\r
237             typeComposite.setLayoutData(typeData);\r
238             \r
239             FormData buttonData = new FormData();           \r
240             buttonData.left = new FormAttachment(0,0);\r
241             buttonData.right = new FormAttachment(100,0);\r
242             buttonData.bottom = new FormAttachment(100,0);\r
243             buttonData.height = 30;\r
244             buttonComposite.setLayoutData(buttonData);\r
245             \r
246             FormData viewerData = new FormData();           \r
247             viewerData.top = new FormAttachment(typeComposite,0,SWT.BOTTOM);\r
248             viewerData.left = new FormAttachment(0,0);\r
249             viewerData.right = new FormAttachment(100,0);\r
250             viewerData.bottom = new FormAttachment(buttonComposite,0,SWT.TOP);\r
251             table.setLayoutData(viewerData);\r
252             \r
253             \r
254         }\r
255         /*\r
256         private void addColorValueToTable(ColorValue value) {\r
257                 TableItem item = new TableItem(table,SWT.NONE);\r
258                 item.setText(Double.toString(value.getValue()));\r
259                 Image image = ColorIconCreator.createImage(value.getColor(), 14);\r
260                 item.setImage(image);\r
261                 images.add(image);\r
262                 items.put(item,value);\r
263         }\r
264         */\r
265         /*\r
266         private void sortItems() {\r
267                 for (Image i : images)\r
268                         i.dispose();\r
269                 for (TableItem item : table.getItems())\r
270                         if(!item.isDisposed())\r
271                                 item.dispose();\r
272                 items.clear();\r
273                 Collections.sort(values,new ColorValueComparator());\r
274                 for (ColorValue value : values) {\r
275                         addColorValueToTable(value);\r
276                 }\r
277         }\r
278         */\r
279         public void addColor(Color color, double value) {\r
280                 addColor(new ColorValue(color,value));\r
281         }\r
282         \r
283         public void addColor(ColorValue value) {\r
284                 values.add(value);\r
285                 Image image = ColorIconCreator.createImage(value.getColor(), ICON_WIDTH, ICON_HEIGHT);\r
286                 images.put(value,image);\r
287                 updateWidgets();\r
288                 //viewer.refresh(true);\r
289         }\r
290         \r
291         private void updateWidgets() {\r
292                 Collections.sort(values,new ColorValueComparator());    \r
293                 gradientComposite.setGradient(new ColorGradient(values,type));\r
294                 viewer.refresh();\r
295                 \r
296         }\r
297         /*\r
298         public void addColor(ColorValue value) {\r
299                 values.add(value);\r
300                 sortItems();\r
301                 // sortItem creates new menuitems, which makes selectedItem disposed\r
302                 for (TableItem item : items.keySet() ) {\r
303                         if (items.get(item) == value) {\r
304                                 gradientComposite.setGradient(new ColorGradient(values,type));\r
305                                 return;\r
306                         }\r
307                         \r
308                 }\r
309                 gradientComposite.setGradient(new ColorGradient(values,type));\r
310         }\r
311         */\r
312         public ColorGradient getGradient() {\r
313                 return new ColorGradient(values,type);\r
314         }\r
315         /*\r
316         public void dispose() {\r
317                 for (Image i : images)\r
318                         i.dispose();\r
319                 if (!table.isDisposed()) {\r
320                         for (TableItem item : table.getItems())\r
321                                 if(!item.isDisposed())\r
322                                         item.dispose();\r
323                         table.dispose();\r
324                 }\r
325         }\r
326         */\r
327         public void dispose() {\r
328                 for (Image i : images.values())\r
329                         i.dispose();\r
330                 \r
331         }\r
332         \r
333         public void setGradient(ColorGradient gradient) {\r
334                 for (Image i : images.values())\r
335                         i.dispose();\r
336                 values.clear();\r
337                 images.clear();\r
338                 type = gradient.getType();\r
339                 for (ColorValue value : gradient.getColorValues())\r
340                         addColor(value);\r
341                 \r
342         }\r
343         \r
344         \r
345 //      private org.eclipse.swt.graphics.Color getSWTColor(Color color){\r
346 //              org.eclipse.swt.graphics.Color swtColor = new org.eclipse.swt.graphics.Color(Display.getCurrent(), color.getR(), color.getG(), color.getB());   \r
347 //              return swtColor;\r
348 //      }\r
349         \r
350         private RGB getRGB(Color color) {\r
351                 RGB rgb = new RGB(color.getR(),color.getG(),color.getB());\r
352                 return rgb;\r
353         }\r
354         \r
355         private void modifyColorValueValue(ColorValue cValue, String string) {\r
356                 try {\r
357                         double d = Double.parseDouble(string);\r
358                         values.remove(cValue);\r
359                         Image image = images.get(cValue);\r
360                         images.remove(cValue);\r
361                         ColorValue newCValue = new ColorValue(cValue.getColor(),d);\r
362                         values.add(newCValue);\r
363                         images.put(newCValue,image);\r
364                         updateWidgets();\r
365                         \r
366                 } catch (NumberFormatException e) {\r
367                         return;\r
368                 }\r
369         }\r
370         \r
371         private void modifyColorValueColor(ColorValue cValue, RGB rgb) {\r
372                 values.remove(cValue);\r
373                 Image oldImage = images.get(cValue);\r
374                 oldImage.dispose();\r
375                 images.remove(cValue);\r
376                 \r
377                 Color newColor = new Color(rgb.red,rgb.green,rgb.blue);\r
378                 ColorValue newCValue = new ColorValue(newColor,cValue.getValue());\r
379                 values.add(newCValue);\r
380                 Image newImage = ColorIconCreator.createImage(newColor, ICON_WIDTH, ICON_HEIGHT);\r
381                 images.put(newCValue,newImage);\r
382                 updateWidgets();\r
383         }\r
384         \r
385         /**\r
386          * Enables and disables "Edit color" and "Remove color" buttons depending on selected item\r
387          */\r
388         public void selectionChanged(SelectionChangedEvent event) {\r
389                 Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();\r
390                 if (obj == null) {\r
391                         editButton.setEnabled(false);\r
392                         removeButton.setEnabled(false);\r
393                 } else {\r
394                         editButton.setEnabled(true);\r
395                         removeButton.setEnabled(true);\r
396                 }\r
397         }\r
398         \r
399         /*\r
400          * FIXME :\r
401          * If item is opened for editing selectionChanged won't get null selection and\r
402          * "Edit" & "Remove" buttons are enabled when there's no valid selection\r
403          * \r
404          * There seems to be no way to get event when cellEditor is activated...\r
405          */\r
406         \r
407         public void applyEditorValue() {\r
408                 // TODO Auto-generated method stub\r
409                 editButton.setEnabled(false);\r
410                 removeButton.setEnabled(false); \r
411         }\r
412         \r
413         public void cancelEditor() {\r
414                 // TODO Auto-generated method stub\r
415                 editButton.setEnabled(false);\r
416                 removeButton.setEnabled(false); \r
417         }\r
418         \r
419         public void editorValueChanged(boolean oldValidState, boolean newValidState) {\r
420                 // TODO Auto-generated method stub\r
421                 editButton.setEnabled(false);\r
422                 removeButton.setEnabled(false); \r
423         }\r
424         \r
425         public void propertyChange(PropertyChangeEvent event) {\r
426                 editButton.setEnabled(false);\r
427                 removeButton.setEnabled(false); \r
428                 \r
429         }\r
430         /**\r
431          * @author Marko Luukkainen\r
432          *\r
433          */\r
434         private class TableLabelProvider implements ITableLabelProvider {\r
435                 private ArrayList<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();\r
436                                 \r
437                 /* (non-Javadoc)\r
438                  * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()\r
439                  */\r
440                 public void dispose() {\r
441                                                 \r
442                 }\r
443                 /* (non-Javadoc)\r
444                  * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)\r
445                  */\r
446                 public Image getColumnImage(Object element, int columnIndex) {\r
447                         //System.out.println("TableLabelProvider.getColumnImage() " + element + " , " + columnIndex);\r
448                         ColorValue value = (ColorValue)element;\r
449                         if (columnIndex == 0)\r
450                                 return images.get(value);\r
451                         return null;\r
452                 }\r
453                 /* (non-Javadoc)\r
454                  * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)\r
455                  */\r
456                 public String getColumnText(Object element, int columnIndex) {\r
457                         //System.out.println("TableLabelProvider.getColumnText() " + element + " , " + columnIndex);\r
458                         ColorValue value = (ColorValue)element;\r
459                         if (columnIndex == 1)\r
460                                 return Double.toString(value.getValue());\r
461                         return null;\r
462                 }\r
463                 /* (non-Javadoc)\r
464                  * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)\r
465                  */\r
466                 public boolean isLabelProperty(Object element, String property) {\r
467                         return true;\r
468                 }\r
469                 /* (non-Javadoc)\r
470                  * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
471                  */\r
472                 public void addListener(ILabelProviderListener listener) {\r
473                         if(!listeners.contains(listener))\r
474                                 listeners.add(listener);                        \r
475                 }\r
476                 /* (non-Javadoc)\r
477                  * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
478                  */\r
479                 public void removeListener(ILabelProviderListener listener) {\r
480                         listeners.remove(listener);\r
481                 }\r
482                 \r
483                 \r
484         }\r
485         \r
486         /**\r
487          * @author Marko Luukkainen\r
488          *\r
489          */\r
490         private class TableContentProvider implements IStructuredContentProvider {\r
491                 public void dispose() {\r
492                         \r
493                 }\r
494                 public Object[] getElements(Object inputElement) {\r
495                         ColorValue valueArray[] = new ColorValue[values.size()];\r
496                         // values.toArray(valueArray);\r
497             // to get correct ordering (smallest last)\r
498             // we must reverse the order of the list\r
499             for (int i = 0; i < values.size(); i++) {\r
500                             valueArray[i] = values.get(values.size() - 1 -i);\r
501             }\r
502             //System.out.println("TableContentProvider.getElements() : array size " + valueArray.length);\r
503                         return valueArray;\r
504                 }\r
505                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
506                         //System.out.println("TableContentProvider.inputChanged()");\r
507                         \r
508                 }\r
509         }\r
510         \r
511         /**\r
512          * @author Marko Luukkainen\r
513          *\r
514          */\r
515         private class TableCellEditorModifier implements ICellModifier {\r
516                 public boolean canModify(Object element, String property) {\r
517                         //System.out.println("TableCellEditorModifier.canModify()" + element + " , " + property);\r
518                         if (property == VALUE_ID)\r
519                                 return true;\r
520                         // this is commented out because it's hard so select the row when both rows have editors\r
521                         // now the color can be changed with "Edit Color" button\r
522                         //if (property == COLOR_ID)\r
523                         //      return true;\r
524                         return false;\r
525                 }\r
526                 public Object getValue(Object element, String property) {\r
527                         //System.out.println("TableCellEditorModifier.getValue()" + element + " , " + property);\r
528                         if (property == VALUE_ID)\r
529                                 return Double.toString(((ColorValue)element).getValue());\r
530                         if (property == COLOR_ID) \r
531                                 return getRGB(((ColorValue)element).getColor());\r
532                         return null;\r
533                         \r
534                 }\r
535                 public void modify(Object element, String property, Object value) {\r
536                         TableItem item = (TableItem)element;\r
537                         Object obj = item.getData();\r
538                         //System.out.println("TableCellEditorModifier.modify()" + element + " , " + property + " , " + value);\r
539                         if (property == VALUE_ID)\r
540                                 modifyColorValueValue((ColorValue)obj,(String)value);\r
541                         if (property == COLOR_ID)\r
542                                 modifyColorValueColor((ColorValue)obj,(RGB)value);\r
543                 }\r
544                 \r
545         }\r
546 }\r
547 \r
548         \r