1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.utils.ui.color;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
19 import org.eclipse.jface.layout.GridDataFactory;
20 import org.eclipse.jface.util.IPropertyChangeListener;
21 import org.eclipse.jface.util.PropertyChangeEvent;
22 import org.eclipse.jface.viewers.CellEditor;
23 import org.eclipse.jface.viewers.ColorCellEditor;
24 import org.eclipse.jface.viewers.ICellEditorListener;
25 import org.eclipse.jface.viewers.ICellModifier;
26 import org.eclipse.jface.viewers.ILabelProviderListener;
27 import org.eclipse.jface.viewers.ISelectionChangedListener;
28 import org.eclipse.jface.viewers.IStructuredContentProvider;
29 import org.eclipse.jface.viewers.IStructuredSelection;
30 import org.eclipse.jface.viewers.ITableLabelProvider;
31 import org.eclipse.jface.viewers.SelectionChangedEvent;
32 import org.eclipse.jface.viewers.StructuredSelection;
33 import org.eclipse.jface.viewers.TableViewer;
34 import org.eclipse.jface.viewers.TextCellEditor;
35 import org.eclipse.jface.viewers.Viewer;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.graphics.RGB;
41 import org.eclipse.swt.layout.FillLayout;
42 import org.eclipse.swt.layout.GridLayout;
43 import org.eclipse.swt.widgets.Button;
44 import org.eclipse.swt.widgets.ColorDialog;
45 import org.eclipse.swt.widgets.Composite;
46 import org.eclipse.swt.widgets.Table;
47 import org.eclipse.swt.widgets.TableColumn;
48 import org.eclipse.swt.widgets.TableItem;
51 * Widget to create and edit color gradients
53 * @author Marko Luukkainen
56 public class ColorGradientComposite extends Composite implements ISelectionChangedListener, ICellEditorListener, IPropertyChangeListener{
57 private static int ICON_WIDTH = 36;
58 private static int ICON_HEIGHT = 14;
60 private static final String COLOR_ID = "Color";
61 private static final String VALUE_ID = "Value";
64 private ColorGradientCanvas gradientComposite;
65 private TableViewer viewer;
66 private Button addButton;
67 private Button editButton;
68 private Button removeButton;
69 private Button rgbButton;
70 private Button hsvButton;
71 private int type = ColorGradient.RGB;
73 private ArrayList<ColorValue> values = new ArrayList<ColorValue>();
74 private HashMap<ColorValue,Image> images = new HashMap<ColorValue,Image>();
76 public ColorGradientComposite(Composite parent, int style) {
78 GridLayout layout = new GridLayout(2,false);
79 this.setLayout(layout);
80 gradientComposite = new ColorGradientCanvas(this,SWT.HORIZONTAL);
84 // Group typeComposite = new Group(this,SWT.NONE);
85 // typeComposite.setText("Interpolation");
86 Composite typeComposite = new Composite(this, SWT.NONE);
88 typeComposite.setLayout(new GridLayout(1,false));
89 rgbButton = new Button(typeComposite,SWT.RADIO);
90 rgbButton.setSelection(true);
91 rgbButton.addSelectionListener(new SelectionListener() {
92 public void widgetDefaultSelected(SelectionEvent e) {
95 public void widgetSelected(SelectionEvent e) {
96 rgbButton.setSelection(true);
97 hsvButton.setSelection(false);
98 type = ColorGradient.RGB;
99 gradientComposite.setGradient(new ColorGradient(values,type));
102 rgbButton.setText("RGB");
103 hsvButton = new Button(typeComposite,SWT.RADIO);
104 hsvButton.addSelectionListener(new SelectionListener() {
105 public void widgetDefaultSelected(SelectionEvent e) {
108 public void widgetSelected(SelectionEvent e) {
109 hsvButton.setSelection(true);
110 rgbButton.setSelection(false);
111 type = ColorGradient.HSV;
112 gradientComposite.setGradient(new ColorGradient(values,type));
115 hsvButton.setText("HSV");
117 viewer = new TableViewer(this,SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
118 final Table table = viewer.getTable();
120 table.setLinesVisible(true);
121 table.setHeaderVisible(true);
123 viewer.addSelectionChangedListener(this);
124 viewer.addPostSelectionChangedListener(this);
126 TableColumn column = new TableColumn(table,SWT.RIGHT);
127 column.setText("Color");
129 column.setMoveable(false);
130 column.setResizable(false);
131 column = new TableColumn(table,SWT.LEFT);
132 column.setText("Value");
133 column.setWidth(300);
134 column.setMoveable(false);
136 viewer.setColumnProperties(new String[]{COLOR_ID,VALUE_ID});
138 viewer.setLabelProvider(new TableLabelProvider());
139 viewer.setContentProvider(new TableContentProvider());
140 viewer.setInput(values);
142 final ColorCellEditor colorEditor = new ColorCellEditor(table);
143 final TextCellEditor valueEditor = new TextCellEditor(table);
144 colorEditor.addListener(this);
145 valueEditor.addListener(this);
146 valueEditor.addPropertyChangeListener(this);
147 viewer.setCellEditors(new CellEditor[]{colorEditor,valueEditor});
149 viewer.setCellModifier(new TableCellEditorModifier());
151 Composite buttonComposite = new Composite(this,SWT.NONE);
153 buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));
155 addButton = new Button(buttonComposite,SWT.PUSH);
156 addButton.setText("Add new color");
157 addButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
158 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
159 ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);
161 RGB rgb = dialog.open();
163 Color c = new Color(rgb.red,rgb.green,rgb.blue);
165 if (values.size() == 0) {
167 } else if (values.size() == 1) {
170 StructuredSelection selection = (StructuredSelection)viewer.getSelection();
171 if (selection.size() == 1) {
172 // add new color next to the selection
173 ColorValue v = (ColorValue)selection.getFirstElement();
174 int index = values.indexOf(v);
175 if (index == values.size() -1) {
178 value = (values.get(index+1).getValue()-values.get(index).getValue())*0.5;
179 value += values.get(index).getValue();
181 // add new color to largest gap
184 for (int i = 0; i < values.size() -1; i++) {
185 double v1 = values.get(i).getValue();
186 double v2 = values.get(i+1).getValue();
193 value = values.get(index).getValue() + r *0.5;
200 editButton = new Button(buttonComposite,SWT.PUSH);
201 editButton.setText("Edit color");
202 editButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
203 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
204 TableItem selection[] = table.getSelection();
205 if (selection.length > 0) {
206 TableItem selected = selection[0];
207 Object obj = selected.getData();
208 if (obj instanceof ColorValue) {
209 ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);
210 dialog.setRGB(getRGB(((ColorValue)obj).getColor()));
211 RGB rgb = dialog.open();
213 modifyColorValueColor((ColorValue)obj,rgb);
219 editButton.setEnabled(false);
220 removeButton = new Button(buttonComposite,SWT.PUSH);
221 removeButton.setText("Remove color");
222 removeButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
223 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
224 TableItem selection[] = table.getSelection();
225 if (selection.length > 0) {
226 TableItem selected = selection[0];
227 Object o = selected.getData();
228 if (o instanceof ColorValue) {
229 Image i = images.get(o);
238 removeButton.setEnabled(false);
240 GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 32).applyTo(gradientComposite);
241 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 100).applyTo(table);
242 GridDataFactory.fillDefaults().grab(false, true).align(SWT.LEFT, SWT.FILL).applyTo(typeComposite);
243 GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite);
248 public void addColor(Color color, double value) {
249 addColor(new ColorValue(color,value));
252 public void addColor(ColorValue value) {
254 Image image = ColorIconCreator.createImage(value.getColor(), ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);
255 images.put(value,image);
257 //viewer.refresh(true);
260 private void updateWidgets() {
261 Collections.sort(values,new ColorValueComparator());
262 gradientComposite.setGradient(new ColorGradient(values,type));
267 public ColorGradient getGradient() {
268 return new ColorGradient(values,type);
271 public void dispose() {
272 for (Image i : images.values())
277 public void setGradient(ColorGradient gradient) {
278 for (Image i : images.values())
282 type = gradient.getType();
283 for (ColorValue value : gradient.getColorValues())
285 if (type == ColorGradient.HSV) {
286 rgbButton.setSelection(false);
287 hsvButton.setSelection(true);
288 } else if (type == ColorGradient.RGB) {
289 hsvButton.setSelection(false);
290 rgbButton.setSelection(true);
295 private RGB getRGB(Color color) {
296 RGB rgb = new RGB(color.getR(),color.getG(),color.getB());
300 private void modifyColorValueValue(ColorValue cValue, String string) {
302 double d = Double.parseDouble(string);
303 values.remove(cValue);
304 Image image = images.get(cValue);
305 images.remove(cValue);
306 ColorValue newCValue = new ColorValue(cValue.getColor(),d);
307 values.add(newCValue);
308 images.put(newCValue,image);
311 } catch (NumberFormatException e) {
316 private void modifyColorValueColor(ColorValue cValue, RGB rgb) {
317 values.remove(cValue);
318 Image oldImage = images.get(cValue);
320 images.remove(cValue);
322 Color newColor = new Color(rgb.red,rgb.green,rgb.blue);
323 ColorValue newCValue = new ColorValue(newColor,cValue.getValue());
324 values.add(newCValue);
325 Image newImage = ColorIconCreator.createImage(newColor, ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);
326 images.put(newCValue,newImage);
331 * Enables and disables "Edit color" and "Remove color" buttons depending on selected item
333 public void selectionChanged(SelectionChangedEvent event) {
334 Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();
336 editButton.setEnabled(false);
337 removeButton.setEnabled(false);
339 editButton.setEnabled(true);
340 removeButton.setEnabled(true);
346 * If item is opened for editing selectionChanged won't get null selection and
347 * "Edit" & "Remove" buttons are enabled when there's no valid selection
349 * There seems to be no way to get event when cellEditor is activated...
352 public void applyEditorValue() {
353 // TODO Auto-generated method stub
354 editButton.setEnabled(false);
355 removeButton.setEnabled(false);
358 public void cancelEditor() {
359 // TODO Auto-generated method stub
360 editButton.setEnabled(false);
361 removeButton.setEnabled(false);
364 public void editorValueChanged(boolean oldValidState, boolean newValidState) {
365 // TODO Auto-generated method stub
366 editButton.setEnabled(false);
367 removeButton.setEnabled(false);
370 public void propertyChange(PropertyChangeEvent event) {
371 editButton.setEnabled(false);
372 removeButton.setEnabled(false);
376 * @author Marko Luukkainen
379 private class TableLabelProvider implements ITableLabelProvider {
380 private ArrayList<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
383 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
385 public void dispose() {
389 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
391 public Image getColumnImage(Object element, int columnIndex) {
392 //System.out.println("TableLabelProvider.getColumnImage() " + element + " , " + columnIndex);
393 ColorValue value = (ColorValue)element;
394 if (columnIndex == 0)
395 return images.get(value);
399 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
401 public String getColumnText(Object element, int columnIndex) {
402 //System.out.println("TableLabelProvider.getColumnText() " + element + " , " + columnIndex);
403 ColorValue value = (ColorValue)element;
404 if (columnIndex == 1)
405 return Double.toString(value.getValue());
409 * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
411 public boolean isLabelProperty(Object element, String property) {
415 * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
417 public void addListener(ILabelProviderListener listener) {
418 if(!listeners.contains(listener))
419 listeners.add(listener);
422 * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
424 public void removeListener(ILabelProviderListener listener) {
425 listeners.remove(listener);
432 * @author Marko Luukkainen
435 private class TableContentProvider implements IStructuredContentProvider {
436 public void dispose() {
439 public Object[] getElements(Object inputElement) {
440 ColorValue valueArray[] = new ColorValue[values.size()];
441 // values.toArray(valueArray);
442 // to get correct ordering (smallest last)
443 // we must reverse the order of the list
444 for (int i = 0; i < values.size(); i++) {
445 valueArray[i] = values.get(values.size() - 1 -i);
447 //System.out.println("TableContentProvider.getElements() : array size " + valueArray.length);
450 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
451 //System.out.println("TableContentProvider.inputChanged()");
457 * @author Marko Luukkainen
460 private class TableCellEditorModifier implements ICellModifier {
461 public boolean canModify(Object element, String property) {
462 //System.out.println("TableCellEditorModifier.canModify()" + element + " , " + property);
463 if (property == VALUE_ID)
465 // this is commented out because it's hard so select the row when both rows have editors
466 // now the color can be changed with "Edit Color" button
467 //if (property == COLOR_ID)
471 public Object getValue(Object element, String property) {
472 //System.out.println("TableCellEditorModifier.getValue()" + element + " , " + property);
473 if (property == VALUE_ID)
474 return Double.toString(((ColorValue)element).getValue());
475 if (property == COLOR_ID)
476 return getRGB(((ColorValue)element).getColor());
480 public void modify(Object element, String property, Object value) {
481 TableItem item = (TableItem)element;
482 Object obj = item.getData();
483 //System.out.println("TableCellEditorModifier.modify()" + element + " , " + property + " , " + value);
484 if (property == VALUE_ID)
485 modifyColorValueValue((ColorValue)obj,(String)value);
486 if (property == COLOR_ID)
487 modifyColorValueColor((ColorValue)obj,(RGB)value);