coolmap.canvas.datarenderer.renderer.impl.NumberToBoxPlot.java Source code

Java tutorial

Introduction

Here is the source code for coolmap.canvas.datarenderer.renderer.impl.NumberToBoxPlot.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package coolmap.canvas.datarenderer.renderer.impl;

import com.google.common.collect.Range;
import coolmap.canvas.datarenderer.renderer.model.ViewRenderer;
import coolmap.data.CoolMapObject;
import coolmap.data.cmatrix.model.CMatrix;
import coolmap.data.cmatrixview.model.VNode;
import coolmap.data.contology.model.COntology;
import coolmap.utils.graphics.UI;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.commons.math3.stat.descriptive.rank.Percentile;

/**
 *
 * @author sugang
 */
public class NumberToBoxPlot extends ViewRenderer<Double> {

    private JTextField minValueField = new JTextField();
    private JTextField maxValueField = new JTextField();
    private JTextField disectField = new JTextField();

    private Color normalBG = Color.WHITE;
    private Color errorBG = UI.colorRedWarning;
    private JComboBox presetRangeComboBox;

    public NumberToBoxPlot() {
        setName("Number to BoxPlot");
        setDescription("Use bar height to represent numeric values");

        //initialize UI
        configUI.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 0;
        c.ipadx = 5;
        c.ipady = 5;
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;

        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;
        //        JButton button = new JButton("Apply");
        //        configUI.add(button, c);
        //        button.setToolTipText("Apply preset data ranges");
        //        button.addActionListener(new ActionListener() {
        //
        //            @Override
        //            public void actionPerformed(ActionEvent e) {
        //                try {
        //                    MinMaxItem item = (MinMaxItem) (presetRangeComboBox.getSelectedItem());
        //                    minValueField.setText(item.getMinMax().lowerEndpoint().toString());
        //                    maxValueField.setText(item.getMinMax().upperEndpoint().toString());
        //                } catch (Exception ex) {
        //                    minValueField.setText("-1");
        //                    maxValueField.setText("1");
        //                }
        //
        //                updateRenderer();
        //            }
        //        });
        configUI.add(new JLabel("Preset range:"), c);

        c.gridx = 1;
        c.gridwidth = 1;
        presetRangeComboBox = new JComboBox();
        configUI.add(presetRangeComboBox, c);
        presetRangeComboBox.addItem(new DataMinMaxItem());
        presetRangeComboBox.addItem(new DefinedMinMaxItem(-1, 1));
        presetRangeComboBox.addItem(new DefinedMinMaxItem(0, 1));
        presetRangeComboBox.addItem(new DefinedMinMaxItem(-1, 0));
        presetRangeComboBox.addItem(new DefinedMinMaxItem(0, 100));

        presetRangeComboBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                try {
                    MinMaxItem item = (MinMaxItem) (presetRangeComboBox.getSelectedItem());
                    minValueField.setText(item.getMinMax().lowerEndpoint().toString());
                    maxValueField.setText(item.getMinMax().upperEndpoint().toString());
                } catch (Exception ex) {
                    minValueField.setText("-1");
                    maxValueField.setText("1");
                }
            }
        });
        ////////////////////////////////////////////////////////////////////////////////
        //        c.weightx = 0.2;
        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;
        configUI.add(new JLabel("Min value: "), c);
        c.gridx = 1;
        //        c.weightx = 0.3;
        configUI.add(minValueField, c);

        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;
        configUI.add(new JLabel("Max value: "), c);
        c.gridx = 1;
        configUI.add(maxValueField, c);

        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;
        configUI.add(new JLabel("Disect boundary: "), c);
        c.gridx = 1;
        configUI.add(disectField, c);
        disectField.setText("0");

        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 3;

        JButton button = new JButton("Update", UI.getImageIcon("refresh"));
        configUI.add(button, c);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //hit button, redraw!

                updateRenderer();
            }
        });

    }

    private double disectBound = 0;

    @Override
    public void updateRendererChanges() {

        if (getCoolMapObject() == null) {
            return;
        }

        //update min max
        try {
            _minValue = Double.parseDouble(minValueField.getText());
            minValueField.setBackground(normalBG);
        } catch (Exception e) {

            minValueField.setBackground(errorBG);
        }

        try {
            _maxValue = Double.parseDouble(maxValueField.getText());
            maxValueField.setBackground(normalBG);
        } catch (Exception e) {

            maxValueField.setBackground(errorBG);
        }

        try {
            disectBound = Double.parseDouble(disectField.getText());
            disectField.setBackground(normalBG);
        } catch (Exception e) {
            disectField.setBackground(errorBG);
        }

        updateLegend();

    }

    private void updateLegend() {

        int width = DEFAULT_LEGEND_WIDTH;
        int height = DEFAULT_LEGENT_HEIGHT;
        legend = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
                .getDefaultConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        Graphics2D g = (Graphics2D) legend.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.setPaint(UI.colorBlack2);
        g.fillRoundRect(0, 0, width, height - 12, 5, 5);

        g.setColor(barColorBelow);
        int boxNum = 10;
        g.setStroke(UI.stroke1_5);

        double value;
        for (int i = 0; i < boxNum; i++) {
            value = _minValue + (_maxValue - _minValue) / boxNum * i;

            if (value > disectBound) {
                g.setColor(barColorNormal);
            }

            int h = (height - 12) / boxNum * i;
            g.drawLine(i * width / boxNum, height - 12 - h, (i + 1) * width / boxNum, height - 12 - h);

        }

        g.setColor(Color.BLACK);
        g.setFont(UI.fontMono.deriveFont(10f));
        DecimalFormat format = new DecimalFormat("#.##");
        g.drawString(format.format(_minValue), 2, 23);

        g.setColor(Color.BLACK);
        String maxString = format.format(_maxValue);
        int swidth = g.getFontMetrics().stringWidth(maxString);
        g.drawString(maxString, width - 2 - swidth, 23);
        g.dispose();
    }

    private BufferedImage legend;

    @Override
    public Image getLegend() {
        return legend;
    }

    private double _minValue = 0;
    private double _maxValue = 1;

    @Override
    protected void initialize() {
        CoolMapObject obj = getCoolMapObject();
        if (!canRender(obj.getViewClass())) {
            return;
        }

        double minValue = Double.MAX_VALUE;
        double maxValue = -Double.MAX_VALUE;

        for (int i = 0; i < obj.getViewNumRows(); i++) {
            for (int j = 0; j < obj.getViewNumColumns(); j++) {
                try {
                    Double v = (Double) obj.getViewValue(i, j);
                    if (v == null || v.isNaN()) {
                        continue;
                    } else {
                        if (v < minValue) {
                            minValue = v;
                        }
                        if (v > maxValue) {
                            maxValue = v;
                        }
                    }
                } catch (Exception e) {

                }
            }
        }

        minValueField.setText(minValue + "");
        maxValueField.setText(maxValue + "");
        updateRenderer();
    }

    @Override
    public boolean canRender(Class<?> viewClass) {
        try {
            return Double.class.isAssignableFrom(viewClass);
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void preRender(int fromRow, int toRow, int fromCol, int toCol, float zoomX, float zoomY) {
    }

    @Override
    public void prepareGraphics(Graphics2D g2D) {
        //        g2D.setFont(UI.fontMono.deriveFont(12f));
        //        g2D.setColor(UI.colorLightYellow);
    }

    @Override
    public void renderCellLD(Double v, VNode rowNode, VNode columnNode, Graphics2D g2D, int anchorX, int anchorY,
            int cellWidth, int cellHeight) {
        if (v == null || v.isNaN()) {
            //System.out.println(v);
            _markNull(v, rowNode, columnNode, g2D, anchorX, anchorY, cellWidth, cellHeight);
        } else {
            try {
                g2D.setColor(UI.colorBlack2);
                g2D.fillRect((int) anchorX, (int) anchorY, (int) cellWidth, (int) cellHeight);
                g2D.setColor(barColorNormal);
                g2D.setStroke(UI.stroke1_5);

                //This is the 
                //int height = (int)Math.round(cellHeight * (v - _minValue)/(_maxValue - _minValue));
                //g2D.fillRect(Math.round(anchorX), Math.round(anchorY + cellHeight - height), Math.round(cellWidth), Math.round(cellHeight));
                if (rowNode.isSingleNode() && columnNode.isSingleNode()) {

                    double value = (v - _minValue) / (_maxValue - _minValue);

                    if (v >= disectBound) {
                        g2D.setColor(barColorNormal);
                    } else {
                        g2D.setColor(barColorBelow);
                    }

                    g2D.drawLine((int) (anchorX + 1), (int) (anchorY + cellHeight - cellHeight * value),
                            (int) (anchorX + cellWidth - 1), (int) (anchorY + cellHeight - cellHeight * value));
                } else {

                    //                    double min = percentile.evaluate(valueArray, 0);
                    //                    double max = percentile.evaluate(valueArray, 100)
                    double fiveVal[] = boxPlotValues(getCoolMapObject(), rowNode, columnNode);
                    if (fiveVal == null) {
                        g2D.setColor(UI.colorBlack1);
                        g2D.drawRect(Math.round(anchorX), Math.round(anchorY), Math.round(cellWidth),
                                Math.round(cellHeight));
                    }

                    double range = _maxValue - _minValue;
                    double minP = (fiveVal[0] - _minValue) / range;
                    double maxP = (fiveVal[4] - _minValue) / range;
                    double medianP = (fiveVal[2] - _minValue) / range;
                    double q1P = (fiveVal[1] - _minValue) / range;
                    double q3P = (fiveVal[3] - _minValue) / range;

                    try {
                        //                        if (cellWidth >= 2 && cellHeight >= 2) {
                        g2D.drawLine((int) (anchorX + cellWidth / 2),
                                (int) (anchorY + cellHeight - cellHeight * maxP), (int) (anchorX + cellWidth / 2),
                                (int) (anchorY + cellHeight - cellHeight * minP));

                        if (fiveVal[2] >= disectBound) {
                            g2D.setColor(UI.colorLightGreen4);
                        } else {
                            g2D.setColor(UI.colorOrange2);
                        }

                        g2D.fillRect((int) (anchorX), (int) (anchorY + cellHeight - cellHeight * q3P),
                                (int) (cellWidth), (int) (cellHeight * (q3P - q1P)));

                        if (fiveVal[2] >= disectBound) {
                            g2D.setColor(barColorNormal);
                        } else {
                            g2D.setColor(barColorBelow);
                        }

                        //                        g2D.setColor(barColorNormal);
                        //g2D.drawRect((int) (anchorX), (int) (anchorY + cellHeight - cellHeight * q3P), (int) (cellWidth), (int) (cellHeight * (q3P - q1P)));
                        g2D.drawLine((int) (anchorX), (int) (anchorY + cellHeight - cellHeight * medianP),
                                (int) (anchorX + cellWidth), (int) (anchorY + cellHeight - cellHeight * medianP));
                        //                        } else {
                        //
                        //                            if (fiveVal[2] >= medianP) {
                        //                                g2D.setColor(barColorNormal);
                        //                            } else {
                        //                                g2D.setColor(barColorBelow);
                        //                            }
                        //
                        ////                            System.out.println("painted rect");
                        ////                            System.out.println((int) cellWidth + " " + ((int) cellHeight));
                        //                            g2D.fillRect((int) anchorX, (int) anchorY, (int) cellWidth, (int) cellHeight);
                        //                        }

                    } catch (Exception e) {
                        System.err.println("Boxplot render exception");
                    }
                }

                //                if(cellWidth>=4 && cellHeight >=){
                //                    g2D.setColor(UI.colorBlack1);
                //                    g2D.drawRect(Math.round(anchorX), Math.round(anchorY), Math.round(cellWidth), Math.round(cellHeight));
                //                }
            } catch (Exception e) {
            }
        }
    }

    @Override
    public Image getSubTip(CoolMapObject object, VNode rowNode, VNode columnNode, float percentX, float PercentY,
            int cellWidth, int cellHeight) {

        try {
            if (rowNode == lastRowNode && columnNode == lastColumnNode) {
                return subTip; //Still in the same cell
            } else {
                updateSubTip(object, rowNode, columnNode);
            }
        } catch (Exception e) {
            updateSubTip(object, rowNode, columnNode);
        }

        return subTip;
    }

    DecimalFormat df = new DecimalFormat("#.##");

    private void updateSubTip(CoolMapObject object, VNode rowNode, VNode columnNode) {
        //must get all the values
        double[] fiveNum = boxPlotValues(object, rowNode, columnNode);
        if (fiveNum == null) {
            subTip = null;
            return;
        }

        String tip = "Five Numbers:\n";
        tip += "[" + df.format(fiveNum[0]) + "," + df.format(fiveNum[1]) + "," + df.format(fiveNum[2]) + ","
                + df.format(fiveNum[3]) + "," + df.format(fiveNum[4]) + "]";

        subTip = ViewRenderer.createToolTipFromString(tip, UI.fontMono.deriveFont(12f).deriveFont(Font.BOLD));

    }

    //    private MatrixCell lastActivreCell = null;
    private VNode lastRowNode = null;
    private VNode lastColumnNode = null;

    private BufferedImage subTip = null;

    private Color barColorNormal = UI.colorLightGreen0;
    private Color barColorBelow = UI.colorOrange0;

    //need to extract the function to find the 5 points
    private double[] boxPlotValues(CoolMapObject object, VNode rowNode, VNode columnNode) {
        if (rowNode == null || columnNode == null || rowNode.isSingleNode() && columnNode.isSingleNode()) {
            return null;
        } else {

            Integer[] rowIndices;
            Integer[] colIndices;
            if (rowNode.isGroupNode()) {
                rowIndices = rowNode.getBaseIndicesFromCOntology((CMatrix) object.getBaseCMatrices().get(0),
                        COntology.ROW);
            } else {
                rowIndices = new Integer[] {
                        ((CMatrix) object.getBaseCMatrices().get(0)).getIndexOfRowName(rowNode.getName()) };
            }
            if (columnNode.isGroupNode()) {
                colIndices = columnNode.getBaseIndicesFromCOntology((CMatrix) object.getBaseCMatrices().get(0),
                        COntology.COLUMN);
            } else {
                colIndices = new Integer[] {
                        ((CMatrix) object.getBaseCMatrices().get(0)).getIndexOfColName(columnNode.getName()) };
            }

            //A box plot across all matrices
            List<CMatrix> matrices = object.getBaseCMatrices();
            Double value;
            ArrayList<Double> values = new ArrayList<Double>();

            //add values
            for (Integer i : rowIndices) {
                if (i == null || i < 0) {
                    continue;
                }

                for (Integer j : colIndices) {

                    if (j == null || j < 0) {
                        continue;
                    }
                    //Double value = (Double) getCoolMapObject().getViewValue(i, j);
                    //This is wrong. it should eb the base matrix value, not the view values
                    for (CMatrix<Double> matrix : matrices) {

                        value = matrix.getValue(i, j);

                        if (value == null || value.isNaN()) {
                            continue;
                        } else {
                            //System.out.println(i + " " + j + " " + v);
                            values.add(value);
                        }
                    }

                }
            }

            if (values.isEmpty()) {
                return null;
            }

            Collections.sort(values);
            int size = values.size();
            double min = values.get(0);
            double max = values.get(values.size() - 1);

            double median;
            if (size % 2 == 0) {
                median = (values.get(size / 2) + values.get(size / 2 - 1)) / 2;
            } else {
                median = (values.get(size / 2));
            }
            double[] valueArray = new double[values.size()];
            int c = 0;
            for (Double d : values) {
                valueArray[c++] = d.doubleValue();
            }

            Arrays.sort(valueArray);

            Percentile percentile = new Percentile();
            double q1 = percentile.evaluate(valueArray, 25);
            double q3 = percentile.evaluate(valueArray, 75);
            //            double median = percentile.evaluate(valueArray, 50);
            return new double[] { min, q1, median, q3, max };

        }
    }

    @Override
    public void renderCellSD(Double v, VNode rowNode, VNode columnNode, Graphics2D g2D, int anchorX, int anchorY,
            int cellWidth, int cellHeight) {
        if (v == null || v.isNaN()) {
            //System.out.println(v);
            _markNull(v, rowNode, columnNode, g2D, anchorX, anchorY, cellWidth, cellHeight);
        } else {
            try {
                g2D.setColor(UI.colorBlack2);
                g2D.fillRect((int) anchorX, (int) anchorY, (int) cellWidth, (int) cellHeight);
                g2D.setColor(barColorNormal);

                //                g2D.setStroke(null);
                g2D.setStroke(UI.stroke1_5);

                //This is the 
                //int height = (int)Math.round(cellHeight * (v - _minValue)/(_maxValue - _minValue));
                //g2D.fillRect(Math.round(anchorX), Math.round(anchorY + cellHeight - height), Math.round(cellWidth), Math.round(cellHeight));
                if (rowNode.isSingleNode() && columnNode.isSingleNode()) {

                    double medianP = (v - _minValue) / (_maxValue - _minValue);
                    if (v >= disectBound) {
                        g2D.setColor(barColorNormal);
                    } else {
                        g2D.setColor(barColorBelow);

                    }

                    g2D.drawLine((int) (anchorX + 1), (int) (anchorY + cellHeight - cellHeight * medianP),
                            (int) (anchorX + cellWidth - 1), (int) (anchorY + cellHeight - cellHeight * medianP));
                } else {

                    //                    double min = percentile.evaluate(valueArray, 0);
                    //                    double max = percentile.evaluate(valueArray, 100)
                    double fiveVal[] = boxPlotValues(getCoolMapObject(), rowNode, columnNode);
                    if (fiveVal == null) {
                        g2D.setColor(UI.colorBlack1);
                        g2D.drawRect(Math.round(anchorX), Math.round(anchorY), Math.round(cellWidth),
                                Math.round(cellHeight));
                    }

                    double range = _maxValue - _minValue;
                    double minP = (fiveVal[0] - _minValue) / range;
                    double maxP = (fiveVal[4] - _minValue) / range;
                    double medianP = (fiveVal[2] - _minValue) / range;
                    double q1P = (fiveVal[1] - _minValue) / range;
                    double q3P = (fiveVal[3] - _minValue) / range;

                    try {
                        g2D.drawLine((int) (anchorX + cellWidth / 2),
                                (int) (anchorY + cellHeight - cellHeight * maxP), (int) (anchorX + cellWidth / 2),
                                (int) (anchorY + cellHeight - cellHeight * minP));

                        if (fiveVal[2] >= disectBound) {
                            g2D.setColor(UI.colorLightGreen4);
                        } else {
                            g2D.setColor(UI.colorOrange2);
                        }

                        g2D.fillRect((int) (anchorX + cellWidth / 4),
                                (int) (anchorY + cellHeight - cellHeight * q3P), (int) (cellWidth / 2),
                                (int) (cellHeight * (q3P - q1P)));

                        if (fiveVal[2] >= disectBound) {
                            g2D.setColor(barColorNormal);
                        } else {
                            g2D.setColor(barColorBelow);
                        }

                        //                        g2D.setColor(barColorNormal);
                        g2D.drawRect((int) (anchorX + cellWidth / 4),
                                (int) (anchorY + cellHeight - cellHeight * q3P), (int) (cellWidth / 2),
                                (int) (cellHeight * (q3P - q1P)));

                        g2D.drawLine((int) (anchorX + 1), (int) (anchorY + cellHeight - cellHeight * medianP),
                                (int) (anchorX + cellWidth - 1),
                                (int) (anchorY + cellHeight - cellHeight * medianP));
                    } catch (Exception e) {
                        System.err.println("Boxplot render exception");
                    }
                }

                g2D.setColor(UI.colorBlack1);
                g2D.drawRect(Math.round(anchorX), Math.round(anchorY), Math.round(cellWidth),
                        Math.round(cellHeight));
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void renderCellHD(Double v, VNode rowNode, VNode columnNode, Graphics2D g2D, int anchorX, int anchorY,
            int cellWidth, int cellHeight) {
        renderCellSD(v, rowNode, columnNode, g2D, anchorX, anchorY, cellWidth, cellHeight);

        //        g2D.setColor(Color.BLACK);
        //        g2D.drawString(df.format(v), anchorX, anchorY + cellHeight);
    }

    //    DecimalFormat df = new DecimalFormat("#.##");
    @Override
    public void postRender(int fromRow, int toRow, int fromCol, int toCol, float zoomX, float zoomY) {
    }

    private JPanel configUI = new JPanel();

    @Override
    public JComponent getConfigUI() {
        return configUI;
    }

    private class DataMinMaxItem extends MinMaxItem {

        @Override
        public Range<Double> getMinMax() {

            CoolMapObject obj = getCoolMapObject();
            if (!canRender(obj.getViewClass())) {
                return null;
            }

            double minValue = Double.MAX_VALUE;
            double maxValue = -Double.MAX_VALUE;

            try {
                for (int i = 0; i < obj.getViewNumRows(); i++) {
                    for (int j = 0; j < obj.getViewNumColumns(); j++) {
                        try {
                            Double v = (Double) obj.getViewValue(i, j);
                            if (v == null || v.isNaN()) {
                                continue;
                            } else {
                                if (v < minValue) {
                                    minValue = v;
                                }
                                if (v > maxValue) {
                                    maxValue = v;
                                }
                            }
                        } catch (Exception e) {

                        }
                    }
                }
                return Range.closed(minValue, maxValue);
            } catch (Exception e) {
                return null;
            }
        }

        @Override
        public String toString() {
            return "View min - max";
        }

    }

    private class DefinedMinMaxItem extends MinMaxItem {

        private double min;
        private double max;

        public DefinedMinMaxItem(double min, double max) {
            this.min = min;
            this.max = max;
        }

        @Override
        public Range<Double> getMinMax() {
            return Range.closed(min, max);
        }

    }

    private abstract class MinMaxItem {

        public abstract Range<Double> getMinMax();

        @Override
        public String toString() {
            Range<Double> range = getMinMax();
            return range.lowerEndpoint() + " - " + range.upperEndpoint();
        }
    }

    private class GradientItem {

        private final Color[] c;
        private final float[] pos;
        private final BufferedImage preview;
        private final String name;

        public GradientItem(Color[] c, float[] pos, String name) {
            this.c = c;
            this.pos = pos;

            //update preview
            preview = new BufferedImage(100, 16, BufferedImage.TYPE_INT_ARGB);
            this.name = name;

            LinearGradientPaint paint = new LinearGradientPaint(0, 0, 100, 0, pos, c);
            Graphics2D g2D = preview.createGraphics();
            g2D.setPaint(paint);
            g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2D.fillRoundRect(2, 2, 90, 12, 4, 4);

            g2D.dispose();

        }

        public Image getPreview() {
            return preview;
        }

        @Override
        public String toString() {
            return name;//To change body of generated methods, choose Tools | Templates.
        }

        public Color[] getColors() {
            return c;
        }

        public float[] getPositions() {
            return pos;

        }

    }

    private class GradientComboItemRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
                boolean cellHasFocus) {

            JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            l.setIcon(new ImageIcon(((GradientItem) value).getPreview()));
            l.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            return l;
        }

    }
}