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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.utils.ui.color;
\r
15 import java.util.ArrayList;
\r
16 import java.util.Collections;
\r
17 import java.util.HashMap;
\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
53 * Widget to create and edit color gradients
\r
55 * @author Marko Luukkainen
\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
62 private static final String COLOR_ID = "Color";
\r
63 private static final String VALUE_ID = "Value";
\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
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
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
89 Group typeComposite = new Group(this,SWT.NONE);
\r
90 typeComposite.setText("Color interpolation type");
\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
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
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
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
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
128 viewer.addSelectionChangedListener(this);
\r
129 viewer.addPostSelectionChangedListener(this);
\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
141 viewer.setColumnProperties(new String[]{COLOR_ID,VALUE_ID});
\r
143 viewer.setLabelProvider(new TableLabelProvider());
\r
144 viewer.setContentProvider(new TableContentProvider());
\r
145 viewer.setInput(values);
\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
154 viewer.setCellModifier(new TableCellEditorModifier());
\r
157 Composite buttonComposite = new Composite(this,SWT.NONE);
\r
160 buttonComposite.setLayout(new FillLayout(SWT.HORIZONTAL));
\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
168 RGB rgb = dialog.open();
\r
170 Color c = new Color(rgb.red,rgb.green,rgb.blue);
\r
172 if (values.size() == 0) {
\r
174 } else if (values.size() == 1) {
\r
177 // FIXME : insert some logic here
\r
178 value = 100.0 * Math.random();
\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
198 modifyColorValueColor((ColorValue)obj,rgb);
\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
223 removeButton.setEnabled(false);
\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
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
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
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
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
262 items.put(item,value);
\r
266 private void sortItems() {
\r
267 for (Image i : images)
\r
269 for (TableItem item : table.getItems())
\r
270 if(!item.isDisposed())
\r
273 Collections.sort(values,new ColorValueComparator());
\r
274 for (ColorValue value : values) {
\r
275 addColorValueToTable(value);
\r
279 public void addColor(Color color, double value) {
\r
280 addColor(new ColorValue(color,value));
\r
283 public void addColor(ColorValue value) {
\r
285 Image image = ColorIconCreator.createImage(value.getColor(), ICON_WIDTH, ICON_HEIGHT);
\r
286 images.put(value,image);
\r
288 //viewer.refresh(true);
\r
291 private void updateWidgets() {
\r
292 Collections.sort(values,new ColorValueComparator());
\r
293 gradientComposite.setGradient(new ColorGradient(values,type));
\r
298 public void addColor(ColorValue value) {
\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
309 gradientComposite.setGradient(new ColorGradient(values,type));
\r
312 public ColorGradient getGradient() {
\r
313 return new ColorGradient(values,type);
\r
316 public void dispose() {
\r
317 for (Image i : images)
\r
319 if (!table.isDisposed()) {
\r
320 for (TableItem item : table.getItems())
\r
321 if(!item.isDisposed())
\r
327 public void dispose() {
\r
328 for (Image i : images.values())
\r
333 public void setGradient(ColorGradient gradient) {
\r
334 for (Image i : images.values())
\r
338 type = gradient.getType();
\r
339 for (ColorValue value : gradient.getColorValues())
\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
350 private RGB getRGB(Color color) {
\r
351 RGB rgb = new RGB(color.getR(),color.getG(),color.getB());
\r
355 private void modifyColorValueValue(ColorValue cValue, String string) {
\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
366 } catch (NumberFormatException e) {
\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
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
386 * Enables and disables "Edit color" and "Remove color" buttons depending on selected item
\r
388 public void selectionChanged(SelectionChangedEvent event) {
\r
389 Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();
\r
391 editButton.setEnabled(false);
\r
392 removeButton.setEnabled(false);
\r
394 editButton.setEnabled(true);
\r
395 removeButton.setEnabled(true);
\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
404 * There seems to be no way to get event when cellEditor is activated...
\r
407 public void applyEditorValue() {
\r
408 // TODO Auto-generated method stub
\r
409 editButton.setEnabled(false);
\r
410 removeButton.setEnabled(false);
\r
413 public void cancelEditor() {
\r
414 // TODO Auto-generated method stub
\r
415 editButton.setEnabled(false);
\r
416 removeButton.setEnabled(false);
\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
425 public void propertyChange(PropertyChangeEvent event) {
\r
426 editButton.setEnabled(false);
\r
427 removeButton.setEnabled(false);
\r
431 * @author Marko Luukkainen
\r
434 private class TableLabelProvider implements ITableLabelProvider {
\r
435 private ArrayList<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
\r
438 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
\r
440 public void dispose() {
\r
444 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
\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
454 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
\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
464 * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
\r
466 public boolean isLabelProperty(Object element, String property) {
\r
470 * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
\r
472 public void addListener(ILabelProviderListener listener) {
\r
473 if(!listeners.contains(listener))
\r
474 listeners.add(listener);
\r
477 * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
\r
479 public void removeListener(ILabelProviderListener listener) {
\r
480 listeners.remove(listener);
\r
487 * @author Marko Luukkainen
\r
490 private class TableContentProvider implements IStructuredContentProvider {
\r
491 public void dispose() {
\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
502 //System.out.println("TableContentProvider.getElements() : array size " + valueArray.length);
\r
505 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
\r
506 //System.out.println("TableContentProvider.inputChanged()");
\r
512 * @author Marko Luukkainen
\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
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
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
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