/* * DiscreteColourDecorator.java * * Copyright (C) 2006-2014 Andrew Rambaut * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package figtree.treeviewer.decorators; import jebl.util.Attributable; import java.awt.*; import java.awt.geom.Point2D; import java.util.*; import java.util.List; /** * This decorator takes an attribute name and a set of attibutable Objects. * Colours are given to each individual value. * * If the data take more values than colors, then they will wrap around * * @author Andrew Rambaut * @version $Id$ * * $HeadURL$ * * $LastChangedBy$ * $LastChangedDate$ * $LastChangedRevision$ */ public class DiscreteColourDecorator extends ColourDecorator { public static Color[] DEFAULT_PAINTS = new Color[] { new Color(64,35,225), new Color(229,35,60), new Color(255,174,34), new Color(86,255,34), new Color(35,141,148), new Color(146,35,142), new Color(255,90,34), new Color(239,255,34), Color.DARK_GRAY, new Color(160,146,241), new Color(243,146,158), new Color(255,215,145), new Color(171,255,145), new Color(146,199,202), new Color(201,146,199), new Color(255,173,145), new Color(248,255,145), Color.LIGHT_GRAY, new Color(32,18,113), new Color(115,18,30), new Color(128,87,17), new Color(43,128,17), new Color(18,71,74), new Color(73,18,71), new Color(128,45,17), new Color(120,128,17) }; public DiscreteColourDecorator() { super(null); colours = DEFAULT_PAINTS; } public DiscreteColourDecorator(String attributeName) { super(attributeName); } public DiscreteColourDecorator(String attributeName, Set<? extends Attributable> items) { super(attributeName, items); } @Override public void setup(String settings) { throw new UnsupportedOperationException("setup from string not implemented"); } public void setAttributes(String attributeName, Set<? extends Attributable> items) { super.setAttributes(attributeName, items); // First collect the set of all attribute values Set<Object> sortedValues = new TreeSet<Object>(); Set<Object> unsortedValues = new HashSet<Object>(); for (Attributable item : items) { Object value = item.getAttribute(attributeName); if (value != null) { if (value instanceof Comparable) { sortedValues.add(value); } else { unsortedValues.add(value); } } } if (values == null) { values = new ArrayList<Object>(sortedValues); values.addAll(unsortedValues); } else { // if there is already a values array, only add the new values // to maintain the order that may have been edited by the user. for (Object value : sortedValues) { if (!values.contains(value)) { values.add(value); } } for (Object value : unsortedValues) { if (!values.contains(value)) { values.add(value); } } } setupColours(); } public List<Object> getValues() { return values; } public void setValues(Collection<Object> values) { this.values = new ArrayList<Object>(values); setupColours(); } protected void setupColours() { setColourMap(values, DEFAULT_PAINTS); } public Color getColor(Object value) { return (Color)colours[orderMap.get(value)]; } protected void setColourMap(Collection<Object> values, Color[] colours) { if (values == null) { return; } orderMap = new TreeMap<Object, Integer>(); this.colours = colours; this.values = new ArrayList<Object>(values); // now create a paint map for these values int i = 0; for (Object value : this.values) { orderMap.put(value, i); i = (i + 1) % colours.length; } } protected Color getColourForValue(Object value) { int index = -1; if (value != null) { if (orderMap != null && orderMap.size() > 0) { index = orderMap.get(value); } else if (value instanceof Number) { index = ((Number)value).intValue() % colours.length; } } if (index == -1) { return null; } return colours[index]; } public void setValuesOrder(List<Object> discreteValues) { values = discreteValues; hasReorderedValues = true; } public boolean hasReorderedValues() { return hasReorderedValues; } public String getOrderString() { StringBuilder sb = new StringBuilder(); boolean first = true; for (Object value : values) { if (!first) { sb.append(","); } else { first = false; } sb.append(value); } return sb.toString(); } private List<Object> values; private Map<Object, Integer> orderMap; private Color[] colours; private boolean hasReorderedValues = false; }