]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorGradientComposite.java
index 77b7668d1eb3653599af774b96b2f3b1ad8eb68e..ea193f0272c783caabcf9b6feaea61aac35fc6fb 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.utils.ui.color;\r
-\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.util.IPropertyChangeListener;\r
-import org.eclipse.jface.util.PropertyChangeEvent;\r
-import org.eclipse.jface.viewers.CellEditor;\r
-import org.eclipse.jface.viewers.ColorCellEditor;\r
-import org.eclipse.jface.viewers.ICellEditorListener;\r
-import org.eclipse.jface.viewers.ICellModifier;\r
-import org.eclipse.jface.viewers.ILabelProviderListener;\r
-import org.eclipse.jface.viewers.ISelectionChangedListener;\r
-import org.eclipse.jface.viewers.IStructuredContentProvider;\r
-import org.eclipse.jface.viewers.IStructuredSelection;\r
-import org.eclipse.jface.viewers.ITableLabelProvider;\r
-import org.eclipse.jface.viewers.SelectionChangedEvent;\r
-import org.eclipse.jface.viewers.StructuredSelection;\r
-import org.eclipse.jface.viewers.TableViewer;\r
-import org.eclipse.jface.viewers.TextCellEditor;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.events.SelectionListener;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.eclipse.swt.graphics.RGB;\r
-import org.eclipse.swt.layout.FillLayout;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.ColorDialog;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Table;\r
-import org.eclipse.swt.widgets.TableColumn;\r
-import org.eclipse.swt.widgets.TableItem;\r
-\r
-/**\r
- * Widget to create and edit color gradients\r
- * \r
- * @author Marko Luukkainen\r
- *\r
- */\r
-public class ColorGradientComposite extends Composite implements ISelectionChangedListener, ICellEditorListener, IPropertyChangeListener{\r
-       private static int ICON_WIDTH = 36;\r
-       private static int ICON_HEIGHT = 14;\r
-       \r
-       private static final String COLOR_ID = "Color";\r
-       private static final String VALUE_ID = "Value";\r
-       \r
-       \r
-       private ColorGradientCanvas gradientComposite;\r
-       private TableViewer viewer;\r
-       private Button addButton;\r
-       private Button editButton;\r
-       private Button removeButton;\r
-       private Button rgbButton;\r
-       private Button hsvButton;\r
-       private int type = ColorGradient.RGB;\r
-       \r
-       private ArrayList<ColorValue> values = new ArrayList<ColorValue>();\r
-       private HashMap<ColorValue,Image> images = new HashMap<ColorValue,Image>();\r
-       \r
-       public ColorGradientComposite(Composite parent, int style) {\r
-               super(parent,style);\r
-               GridLayout layout = new GridLayout(2,false);\r
-           this.setLayout(layout);\r
-           gradientComposite = new ColorGradientCanvas(this,SWT.HORIZONTAL);\r
-           \r
-          \r
-           \r
-//         Group typeComposite = new Group(this,SWT.NONE);\r
-//         typeComposite.setText("Interpolation");\r
-           Composite typeComposite = new Composite(this, SWT.NONE);\r
-           \r
-           typeComposite.setLayout(new GridLayout(1,false));\r
-           rgbButton = new Button(typeComposite,SWT.RADIO);\r
-           rgbButton.setSelection(true);\r
-           rgbButton.addSelectionListener(new SelectionListener() {\r
-               public void widgetDefaultSelected(SelectionEvent e) {\r
-                       widgetSelected(e);\r
-               }\r
-               public void widgetSelected(SelectionEvent e) {\r
-                       rgbButton.setSelection(true);\r
-                       hsvButton.setSelection(false);\r
-                       type = ColorGradient.RGB;\r
-                       gradientComposite.setGradient(new ColorGradient(values,type));\r
-               }\r
-           });\r
-           rgbButton.setText("RGB");\r
-           hsvButton = new Button(typeComposite,SWT.RADIO);\r
-           hsvButton.addSelectionListener(new SelectionListener() {\r
-               public void widgetDefaultSelected(SelectionEvent e) {\r
-                       widgetSelected(e);\r
-               }\r
-               public void widgetSelected(SelectionEvent e) {\r
-                       hsvButton.setSelection(true);\r
-                       rgbButton.setSelection(false);\r
-                       type = ColorGradient.HSV;\r
-                       gradientComposite.setGradient(new ColorGradient(values,type));\r
-               }\r
-           });\r
-           hsvButton.setText("HSV");\r
-          \r
-           viewer = new TableViewer(this,SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);\r
-           final Table table = viewer.getTable();\r
-           \r
-           table.setLinesVisible(true);\r
-           table.setHeaderVisible(true);\r
-           \r
-           viewer.addSelectionChangedListener(this);\r
-           viewer.addPostSelectionChangedListener(this);\r
-           \r
-           TableColumn column = new TableColumn(table,SWT.RIGHT);\r
-           column.setText("Color");\r
-           column.setWidth(60);\r
-           column.setMoveable(false);\r
-           column.setResizable(false);\r
-           column = new TableColumn(table,SWT.LEFT);\r
-           column.setText("Value");\r
-           column.setWidth(300);\r
-           column.setMoveable(false);\r
-           \r
-           viewer.setColumnProperties(new String[]{COLOR_ID,VALUE_ID});\r
-           \r
-           viewer.setLabelProvider(new TableLabelProvider());\r
-           viewer.setContentProvider(new TableContentProvider());\r
-           viewer.setInput(values);\r
-           \r
-           final ColorCellEditor colorEditor = new ColorCellEditor(table);\r
-           final TextCellEditor valueEditor = new TextCellEditor(table);\r
-           colorEditor.addListener(this);\r
-           valueEditor.addListener(this);\r
-           valueEditor.addPropertyChangeListener(this);\r
-           viewer.setCellEditors(new CellEditor[]{colorEditor,valueEditor});\r
-           \r
-           viewer.setCellModifier(new TableCellEditorModifier());    \r
-           \r
-           Composite buttonComposite = new Composite(this,SWT.NONE);\r
-\r
-           buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));\r
-           \r
-           addButton = new Button(buttonComposite,SWT.PUSH);\r
-           addButton.setText("Add new color");\r
-           addButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
-               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
-                       ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);\r
-                \r
-                RGB rgb = dialog.open();\r
-                if (rgb != null) {\r
-                    Color c = new Color(rgb.red,rgb.green,rgb.blue);\r
-                    Double value;\r
-                    if (values.size() == 0) {\r
-                       value = 0.0;\r
-                    } else if (values.size() == 1) {\r
-                       value = 100.0;\r
-                    } else {\r
-                       StructuredSelection selection = (StructuredSelection)viewer.getSelection();\r
-                       if (selection.size() == 1) {\r
-                               // add new color next to the selection\r
-                               ColorValue v = (ColorValue)selection.getFirstElement();\r
-                               int index = values.indexOf(v);\r
-                               if (index == values.size() -1) {\r
-                                       index--;\r
-                               }\r
-                               value = (values.get(index+1).getValue()-values.get(index).getValue())*0.5;\r
-                               value += values.get(index).getValue();\r
-                       } else {\r
-                               // add new color to largest gap\r
-                               int index = 0;\r
-                               double r = 0.0;\r
-                               for (int i = 0; i < values.size() -1; i++) {\r
-                                       double v1 = values.get(i).getValue();\r
-                                       double v2 = values.get(i+1).getValue();\r
-                                       double vr = v2 -v1;\r
-                                       if (vr > r) {\r
-                                               r=vr;\r
-                                               index = i;\r
-                                       }\r
-                               }\r
-                               value = values.get(index).getValue() + r *0.5;\r
-                       }\r
-                    }\r
-                    addColor(c,value);\r
-                }\r
-            }\r
-        });\r
-           editButton = new Button(buttonComposite,SWT.PUSH);\r
-           editButton.setText("Edit color");\r
-           editButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
-               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
-                       TableItem selection[] = table.getSelection();\r
-                       if (selection.length > 0) {\r
-                               TableItem selected = selection[0];\r
-                               Object obj = selected.getData();\r
-                               if (obj instanceof ColorValue) {\r
-                                       ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);\r
-                                       dialog.setRGB(getRGB(((ColorValue)obj).getColor()));\r
-                                       RGB rgb = dialog.open();\r
-                        if (rgb != null) {\r
-                               modifyColorValueColor((ColorValue)obj,rgb);\r
-                        }\r
-                               }                       \r
-                       }\r
-               }\r
-        });\r
-           editButton.setEnabled(false);\r
-           removeButton = new Button(buttonComposite,SWT.PUSH);\r
-           removeButton.setText("Remove color");\r
-           removeButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
-               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
-                       TableItem selection[] = table.getSelection();\r
-                       if (selection.length > 0) {\r
-                               TableItem selected = selection[0];\r
-                               Object o = selected.getData();\r
-                               if (o instanceof ColorValue) {\r
-                                       Image i = images.get(o);\r
-                                       i.dispose();\r
-                                       images.remove(o);\r
-                                       values.remove(o);\r
-                                       updateWidgets();\r
-                               }                       \r
-                       }\r
-               }\r
-        });\r
-           removeButton.setEnabled(false);\r
-           \r
-           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 32).applyTo(gradientComposite);\r
-           GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 100).applyTo(table);\r
-           GridDataFactory.fillDefaults().grab(false, true).align(SWT.LEFT, SWT.FILL).applyTo(typeComposite);\r
-           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite);\r
-           \r
-           \r
-       }\r
-\r
-       public void addColor(Color color, double value) {\r
-               addColor(new ColorValue(color,value));\r
-       }\r
-       \r
-       public void addColor(ColorValue value) {\r
-               values.add(value);\r
-               Image image = ColorIconCreator.createImage(value.getColor(), ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);\r
-               images.put(value,image);\r
-               updateWidgets();\r
-               //viewer.refresh(true);\r
-       }\r
-       \r
-       private void updateWidgets() {\r
-               Collections.sort(values,new ColorValueComparator());    \r
-               gradientComposite.setGradient(new ColorGradient(values,type));\r
-               viewer.refresh();\r
-               \r
-       }\r
-\r
-       public ColorGradient getGradient() {\r
-               return new ColorGradient(values,type);\r
-       }\r
-\r
-       public void dispose() {\r
-               for (Image i : images.values())\r
-                       i.dispose();\r
-               super.dispose();\r
-       }\r
-       \r
-       public void setGradient(ColorGradient gradient) {\r
-               for (Image i : images.values())\r
-                       i.dispose();\r
-               values.clear();\r
-               images.clear();\r
-               type = gradient.getType();\r
-               for (ColorValue value : gradient.getColorValues())\r
-                       addColor(value);\r
-               if (type == ColorGradient.HSV) {\r
-                       rgbButton.setSelection(false);\r
-                       hsvButton.setSelection(true);\r
-               } else if (type == ColorGradient.RGB) {\r
-                       hsvButton.setSelection(false);\r
-                       rgbButton.setSelection(true);\r
-               }\r
-               \r
-       }\r
-       \r
-       private RGB getRGB(Color color) {\r
-               RGB rgb = new RGB(color.getR(),color.getG(),color.getB());\r
-               return rgb;\r
-       }\r
-       \r
-       private void modifyColorValueValue(ColorValue cValue, String string) {\r
-               try {\r
-                       double d = Double.parseDouble(string);\r
-                       values.remove(cValue);\r
-                       Image image = images.get(cValue);\r
-                       images.remove(cValue);\r
-                       ColorValue newCValue = new ColorValue(cValue.getColor(),d);\r
-                       values.add(newCValue);\r
-                       images.put(newCValue,image);\r
-                       updateWidgets();\r
-                       \r
-               } catch (NumberFormatException e) {\r
-                       return;\r
-               }\r
-       }\r
-       \r
-       private void modifyColorValueColor(ColorValue cValue, RGB rgb) {\r
-               values.remove(cValue);\r
-               Image oldImage = images.get(cValue);\r
-               oldImage.dispose();\r
-               images.remove(cValue);\r
-               \r
-               Color newColor = new Color(rgb.red,rgb.green,rgb.blue);\r
-               ColorValue newCValue = new ColorValue(newColor,cValue.getValue());\r
-               values.add(newCValue);\r
-               Image newImage = ColorIconCreator.createImage(newColor, ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);\r
-               images.put(newCValue,newImage);\r
-               updateWidgets();\r
-       }\r
-       \r
-       /**\r
-        * Enables and disables "Edit color" and "Remove color" buttons depending on selected item\r
-        */\r
-       public void selectionChanged(SelectionChangedEvent event) {\r
-               Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();\r
-               if (obj == null) {\r
-                       editButton.setEnabled(false);\r
-                       removeButton.setEnabled(false);\r
-               } else {\r
-                       editButton.setEnabled(true);\r
-                       removeButton.setEnabled(true);\r
-               }\r
-       }\r
-       \r
-       /*\r
-        * FIXME :\r
-        * If item is opened for editing selectionChanged won't get null selection and\r
-        * "Edit" & "Remove" buttons are enabled when there's no valid selection\r
-        * \r
-        * There seems to be no way to get event when cellEditor is activated...\r
-        */\r
-       \r
-       public void applyEditorValue() {\r
-               // TODO Auto-generated method stub\r
-               editButton.setEnabled(false);\r
-               removeButton.setEnabled(false); \r
-       }\r
-       \r
-       public void cancelEditor() {\r
-               // TODO Auto-generated method stub\r
-               editButton.setEnabled(false);\r
-               removeButton.setEnabled(false); \r
-       }\r
-       \r
-       public void editorValueChanged(boolean oldValidState, boolean newValidState) {\r
-               // TODO Auto-generated method stub\r
-               editButton.setEnabled(false);\r
-               removeButton.setEnabled(false); \r
-       }\r
-       \r
-       public void propertyChange(PropertyChangeEvent event) {\r
-               editButton.setEnabled(false);\r
-               removeButton.setEnabled(false); \r
-               \r
-       }\r
-       /**\r
-        * @author Marko Luukkainen\r
-        *\r
-        */\r
-       private class TableLabelProvider implements ITableLabelProvider {\r
-               private ArrayList<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();\r
-                               \r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()\r
-                */\r
-               public void dispose() {\r
-                                               \r
-               }\r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)\r
-                */\r
-               public Image getColumnImage(Object element, int columnIndex) {\r
-                       //System.out.println("TableLabelProvider.getColumnImage() " + element + " , " + columnIndex);\r
-                       ColorValue value = (ColorValue)element;\r
-                       if (columnIndex == 0)\r
-                               return images.get(value);\r
-                       return null;\r
-               }\r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)\r
-                */\r
-               public String getColumnText(Object element, int columnIndex) {\r
-                       //System.out.println("TableLabelProvider.getColumnText() " + element + " , " + columnIndex);\r
-                       ColorValue value = (ColorValue)element;\r
-                       if (columnIndex == 1)\r
-                               return Double.toString(value.getValue());\r
-                       return null;\r
-               }\r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)\r
-                */\r
-               public boolean isLabelProperty(Object element, String property) {\r
-                       return true;\r
-               }\r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
-                */\r
-               public void addListener(ILabelProviderListener listener) {\r
-                       if(!listeners.contains(listener))\r
-                               listeners.add(listener);                        \r
-               }\r
-               /* (non-Javadoc)\r
-                * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
-                */\r
-               public void removeListener(ILabelProviderListener listener) {\r
-                       listeners.remove(listener);\r
-               }\r
-               \r
-               \r
-       }\r
-       \r
-       /**\r
-        * @author Marko Luukkainen\r
-        *\r
-        */\r
-       private class TableContentProvider implements IStructuredContentProvider {\r
-               public void dispose() {\r
-                       \r
-               }\r
-               public Object[] getElements(Object inputElement) {\r
-                       ColorValue valueArray[] = new ColorValue[values.size()];\r
-                       // values.toArray(valueArray);\r
-            // to get correct ordering (smallest last)\r
-            // we must reverse the order of the list\r
-            for (int i = 0; i < values.size(); i++) {\r
-                           valueArray[i] = values.get(values.size() - 1 -i);\r
-            }\r
-            //System.out.println("TableContentProvider.getElements() : array size " + valueArray.length);\r
-                       return valueArray;\r
-               }\r
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
-                       //System.out.println("TableContentProvider.inputChanged()");\r
-                       \r
-               }\r
-       }\r
-       \r
-       /**\r
-        * @author Marko Luukkainen\r
-        *\r
-        */\r
-       private class TableCellEditorModifier implements ICellModifier {\r
-               public boolean canModify(Object element, String property) {\r
-                       //System.out.println("TableCellEditorModifier.canModify()" + element + " , " + property);\r
-                       if (property == VALUE_ID)\r
-                               return true;\r
-                       // this is commented out because it's hard so select the row when both rows have editors\r
-                       // now the color can be changed with "Edit Color" button\r
-                       //if (property == COLOR_ID)\r
-                       //      return true;\r
-                       return false;\r
-               }\r
-               public Object getValue(Object element, String property) {\r
-                       //System.out.println("TableCellEditorModifier.getValue()" + element + " , " + property);\r
-                       if (property == VALUE_ID)\r
-                               return Double.toString(((ColorValue)element).getValue());\r
-                       if (property == COLOR_ID) \r
-                               return getRGB(((ColorValue)element).getColor());\r
-                       return null;\r
-                       \r
-               }\r
-               public void modify(Object element, String property, Object value) {\r
-                       TableItem item = (TableItem)element;\r
-                       Object obj = item.getData();\r
-                       //System.out.println("TableCellEditorModifier.modify()" + element + " , " + property + " , " + value);\r
-                       if (property == VALUE_ID)\r
-                               modifyColorValueValue((ColorValue)obj,(String)value);\r
-                       if (property == COLOR_ID)\r
-                               modifyColorValueColor((ColorValue)obj,(RGB)value);\r
-               }\r
-               \r
-       }\r
-}\r
-\r
-       \r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.utils.ui.color;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColorCellEditor;
+import org.eclipse.jface.viewers.ICellEditorListener;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+/**
+ * Widget to create and edit color gradients
+ * 
+ * @author Marko Luukkainen
+ *
+ */
+public class ColorGradientComposite extends Composite implements ISelectionChangedListener, ICellEditorListener, IPropertyChangeListener{
+       private static int ICON_WIDTH = 36;
+       private static int ICON_HEIGHT = 14;
+       
+       private static final String COLOR_ID = "Color";
+       private static final String VALUE_ID = "Value";
+       
+       
+       private ColorGradientCanvas gradientComposite;
+       private TableViewer viewer;
+       private Button addButton;
+       private Button editButton;
+       private Button removeButton;
+       private Button rgbButton;
+       private Button hsvButton;
+       private int type = ColorGradient.RGB;
+       
+       private ArrayList<ColorValue> values = new ArrayList<ColorValue>();
+       private HashMap<ColorValue,Image> images = new HashMap<ColorValue,Image>();
+       
+       public ColorGradientComposite(Composite parent, int style) {
+               super(parent,style);
+               GridLayout layout = new GridLayout(2,false);
+           this.setLayout(layout);
+           gradientComposite = new ColorGradientCanvas(this,SWT.HORIZONTAL);
+           
+          
+           
+//         Group typeComposite = new Group(this,SWT.NONE);
+//         typeComposite.setText("Interpolation");
+           Composite typeComposite = new Composite(this, SWT.NONE);
+           
+           typeComposite.setLayout(new GridLayout(1,false));
+           rgbButton = new Button(typeComposite,SWT.RADIO);
+           rgbButton.setSelection(true);
+           rgbButton.addSelectionListener(new SelectionListener() {
+               public void widgetDefaultSelected(SelectionEvent e) {
+                       widgetSelected(e);
+               }
+               public void widgetSelected(SelectionEvent e) {
+                       rgbButton.setSelection(true);
+                       hsvButton.setSelection(false);
+                       type = ColorGradient.RGB;
+                       gradientComposite.setGradient(new ColorGradient(values,type));
+               }
+           });
+           rgbButton.setText("RGB");
+           hsvButton = new Button(typeComposite,SWT.RADIO);
+           hsvButton.addSelectionListener(new SelectionListener() {
+               public void widgetDefaultSelected(SelectionEvent e) {
+                       widgetSelected(e);
+               }
+               public void widgetSelected(SelectionEvent e) {
+                       hsvButton.setSelection(true);
+                       rgbButton.setSelection(false);
+                       type = ColorGradient.HSV;
+                       gradientComposite.setGradient(new ColorGradient(values,type));
+               }
+           });
+           hsvButton.setText("HSV");
+          
+           viewer = new TableViewer(this,SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
+           final Table table = viewer.getTable();
+           
+           table.setLinesVisible(true);
+           table.setHeaderVisible(true);
+           
+           viewer.addSelectionChangedListener(this);
+           viewer.addPostSelectionChangedListener(this);
+           
+           TableColumn column = new TableColumn(table,SWT.RIGHT);
+           column.setText("Color");
+           column.setWidth(60);
+           column.setMoveable(false);
+           column.setResizable(false);
+           column = new TableColumn(table,SWT.LEFT);
+           column.setText("Value");
+           column.setWidth(300);
+           column.setMoveable(false);
+           
+           viewer.setColumnProperties(new String[]{COLOR_ID,VALUE_ID});
+           
+           viewer.setLabelProvider(new TableLabelProvider());
+           viewer.setContentProvider(new TableContentProvider());
+           viewer.setInput(values);
+           
+           final ColorCellEditor colorEditor = new ColorCellEditor(table);
+           final TextCellEditor valueEditor = new TextCellEditor(table);
+           colorEditor.addListener(this);
+           valueEditor.addListener(this);
+           valueEditor.addPropertyChangeListener(this);
+           viewer.setCellEditors(new CellEditor[]{colorEditor,valueEditor});
+           
+           viewer.setCellModifier(new TableCellEditorModifier());    
+           
+           Composite buttonComposite = new Composite(this,SWT.NONE);
+
+           buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));
+           
+           addButton = new Button(buttonComposite,SWT.PUSH);
+           addButton.setText("Add new color");
+           addButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { 
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    
+                       ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);
+                
+                RGB rgb = dialog.open();
+                if (rgb != null) {
+                    Color c = new Color(rgb.red,rgb.green,rgb.blue);
+                    Double value;
+                    if (values.size() == 0) {
+                       value = 0.0;
+                    } else if (values.size() == 1) {
+                       value = 100.0;
+                    } else {
+                       StructuredSelection selection = (StructuredSelection)viewer.getSelection();
+                       if (selection.size() == 1) {
+                               // add new color next to the selection
+                               ColorValue v = (ColorValue)selection.getFirstElement();
+                               int index = values.indexOf(v);
+                               if (index == values.size() -1) {
+                                       index--;
+                               }
+                               value = (values.get(index+1).getValue()-values.get(index).getValue())*0.5;
+                               value += values.get(index).getValue();
+                       } else {
+                               // add new color to largest gap
+                               int index = 0;
+                               double r = 0.0;
+                               for (int i = 0; i < values.size() -1; i++) {
+                                       double v1 = values.get(i).getValue();
+                                       double v2 = values.get(i+1).getValue();
+                                       double vr = v2 -v1;
+                                       if (vr > r) {
+                                               r=vr;
+                                               index = i;
+                                       }
+                               }
+                               value = values.get(index).getValue() + r *0.5;
+                       }
+                    }
+                    addColor(c,value);
+                }
+            }
+        });
+           editButton = new Button(buttonComposite,SWT.PUSH);
+           editButton.setText("Edit color");
+           editButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { 
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    
+                       TableItem selection[] = table.getSelection();
+                       if (selection.length > 0) {
+                               TableItem selected = selection[0];
+                               Object obj = selected.getData();
+                               if (obj instanceof ColorValue) {
+                                       ColorDialog dialog = new ColorDialog(ColorGradientComposite.this.getShell(), SWT.NONE);
+                                       dialog.setRGB(getRGB(((ColorValue)obj).getColor()));
+                                       RGB rgb = dialog.open();
+                        if (rgb != null) {
+                               modifyColorValueColor((ColorValue)obj,rgb);
+                        }
+                               }                       
+                       }
+               }
+        });
+           editButton.setEnabled(false);
+           removeButton = new Button(buttonComposite,SWT.PUSH);
+           removeButton.setText("Remove color");
+           removeButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { 
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    
+                       TableItem selection[] = table.getSelection();
+                       if (selection.length > 0) {
+                               TableItem selected = selection[0];
+                               Object o = selected.getData();
+                               if (o instanceof ColorValue) {
+                                       Image i = images.get(o);
+                                       i.dispose();
+                                       images.remove(o);
+                                       values.remove(o);
+                                       updateWidgets();
+                               }                       
+                       }
+               }
+        });
+           removeButton.setEnabled(false);
+           
+           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 32).applyTo(gradientComposite);
+           GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 100).applyTo(table);
+           GridDataFactory.fillDefaults().grab(false, true).align(SWT.LEFT, SWT.FILL).applyTo(typeComposite);
+           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite);
+           
+           
+       }
+
+       public void addColor(Color color, double value) {
+               addColor(new ColorValue(color,value));
+       }
+       
+       public void addColor(ColorValue value) {
+               values.add(value);
+               Image image = ColorIconCreator.createImage(value.getColor(), ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);
+               images.put(value,image);
+               updateWidgets();
+               //viewer.refresh(true);
+       }
+       
+       private void updateWidgets() {
+               Collections.sort(values,new ColorValueComparator());    
+               gradientComposite.setGradient(new ColorGradient(values,type));
+               viewer.refresh();
+               
+       }
+
+       public ColorGradient getGradient() {
+               return new ColorGradient(values,type);
+       }
+
+       public void dispose() {
+               for (Image i : images.values())
+                       i.dispose();
+               super.dispose();
+       }
+       
+       public void setGradient(ColorGradient gradient) {
+               for (Image i : images.values())
+                       i.dispose();
+               values.clear();
+               images.clear();
+               type = gradient.getType();
+               for (ColorValue value : gradient.getColorValues())
+                       addColor(value);
+               if (type == ColorGradient.HSV) {
+                       rgbButton.setSelection(false);
+                       hsvButton.setSelection(true);
+               } else if (type == ColorGradient.RGB) {
+                       hsvButton.setSelection(false);
+                       rgbButton.setSelection(true);
+               }
+               
+       }
+       
+       private RGB getRGB(Color color) {
+               RGB rgb = new RGB(color.getR(),color.getG(),color.getB());
+               return rgb;
+       }
+       
+       private void modifyColorValueValue(ColorValue cValue, String string) {
+               try {
+                       double d = Double.parseDouble(string);
+                       values.remove(cValue);
+                       Image image = images.get(cValue);
+                       images.remove(cValue);
+                       ColorValue newCValue = new ColorValue(cValue.getColor(),d);
+                       values.add(newCValue);
+                       images.put(newCValue,image);
+                       updateWidgets();
+                       
+               } catch (NumberFormatException e) {
+                       return;
+               }
+       }
+       
+       private void modifyColorValueColor(ColorValue cValue, RGB rgb) {
+               values.remove(cValue);
+               Image oldImage = images.get(cValue);
+               oldImage.dispose();
+               images.remove(cValue);
+               
+               Color newColor = new Color(rgb.red,rgb.green,rgb.blue);
+               ColorValue newCValue = new ColorValue(newColor,cValue.getValue());
+               values.add(newCValue);
+               Image newImage = ColorIconCreator.createImage(newColor, ICON_WIDTH, ICON_HEIGHT, SWT.BORDER);
+               images.put(newCValue,newImage);
+               updateWidgets();
+       }
+       
+       /**
+        * Enables and disables "Edit color" and "Remove color" buttons depending on selected item
+        */
+       public void selectionChanged(SelectionChangedEvent event) {
+               Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();
+               if (obj == null) {
+                       editButton.setEnabled(false);
+                       removeButton.setEnabled(false);
+               } else {
+                       editButton.setEnabled(true);
+                       removeButton.setEnabled(true);
+               }
+       }
+       
+       /*
+        * FIXME :
+        * If item is opened for editing selectionChanged won't get null selection and
+        * "Edit" & "Remove" buttons are enabled when there's no valid selection
+        * 
+        * There seems to be no way to get event when cellEditor is activated...
+        */
+       
+       public void applyEditorValue() {
+               // TODO Auto-generated method stub
+               editButton.setEnabled(false);
+               removeButton.setEnabled(false); 
+       }
+       
+       public void cancelEditor() {
+               // TODO Auto-generated method stub
+               editButton.setEnabled(false);
+               removeButton.setEnabled(false); 
+       }
+       
+       public void editorValueChanged(boolean oldValidState, boolean newValidState) {
+               // TODO Auto-generated method stub
+               editButton.setEnabled(false);
+               removeButton.setEnabled(false); 
+       }
+       
+       public void propertyChange(PropertyChangeEvent event) {
+               editButton.setEnabled(false);
+               removeButton.setEnabled(false); 
+               
+       }
+       /**
+        * @author Marko Luukkainen
+        *
+        */
+       private class TableLabelProvider implements ITableLabelProvider {
+               private ArrayList<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
+                               
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+                */
+               public void dispose() {
+                                               
+               }
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+                */
+               public Image getColumnImage(Object element, int columnIndex) {
+                       //System.out.println("TableLabelProvider.getColumnImage() " + element + " , " + columnIndex);
+                       ColorValue value = (ColorValue)element;
+                       if (columnIndex == 0)
+                               return images.get(value);
+                       return null;
+               }
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+                */
+               public String getColumnText(Object element, int columnIndex) {
+                       //System.out.println("TableLabelProvider.getColumnText() " + element + " , " + columnIndex);
+                       ColorValue value = (ColorValue)element;
+                       if (columnIndex == 1)
+                               return Double.toString(value.getValue());
+                       return null;
+               }
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+                */
+               public boolean isLabelProperty(Object element, String property) {
+                       return true;
+               }
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+                */
+               public void addListener(ILabelProviderListener listener) {
+                       if(!listeners.contains(listener))
+                               listeners.add(listener);                        
+               }
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+                */
+               public void removeListener(ILabelProviderListener listener) {
+                       listeners.remove(listener);
+               }
+               
+               
+       }
+       
+       /**
+        * @author Marko Luukkainen
+        *
+        */
+       private class TableContentProvider implements IStructuredContentProvider {
+               public void dispose() {
+                       
+               }
+               public Object[] getElements(Object inputElement) {
+                       ColorValue valueArray[] = new ColorValue[values.size()];
+                       // values.toArray(valueArray);
+            // to get correct ordering (smallest last)
+            // we must reverse the order of the list
+            for (int i = 0; i < values.size(); i++) {
+                           valueArray[i] = values.get(values.size() - 1 -i);
+            }
+            //System.out.println("TableContentProvider.getElements() : array size " + valueArray.length);
+                       return valueArray;
+               }
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       //System.out.println("TableContentProvider.inputChanged()");
+                       
+               }
+       }
+       
+       /**
+        * @author Marko Luukkainen
+        *
+        */
+       private class TableCellEditorModifier implements ICellModifier {
+               public boolean canModify(Object element, String property) {
+                       //System.out.println("TableCellEditorModifier.canModify()" + element + " , " + property);
+                       if (property == VALUE_ID)
+                               return true;
+                       // this is commented out because it's hard so select the row when both rows have editors
+                       // now the color can be changed with "Edit Color" button
+                       //if (property == COLOR_ID)
+                       //      return true;
+                       return false;
+               }
+               public Object getValue(Object element, String property) {
+                       //System.out.println("TableCellEditorModifier.getValue()" + element + " , " + property);
+                       if (property == VALUE_ID)
+                               return Double.toString(((ColorValue)element).getValue());
+                       if (property == COLOR_ID) 
+                               return getRGB(((ColorValue)element).getColor());
+                       return null;
+                       
+               }
+               public void modify(Object element, String property, Object value) {
+                       TableItem item = (TableItem)element;
+                       Object obj = item.getData();
+                       //System.out.println("TableCellEditorModifier.modify()" + element + " , " + property + " , " + value);
+                       if (property == VALUE_ID)
+                               modifyColorValueValue((ColorValue)obj,(String)value);
+                       if (property == COLOR_ID)
+                               modifyColorValueColor((ColorValue)obj,(RGB)value);
+               }
+               
+       }
+}
+
+