/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI for * visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * 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., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions Suite #1A 2328 Government Street Victoria BC V8T 5G5 Canada * * (250)385-6040 www.vividsolutions.com */ package com.vividsolutions.jump.workbench.ui.renderer.style; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Stroke; import java.util.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.Icon; import com.vividsolutions.jts.util.Assert; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.util.LangUtil; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.ui.GUIUtil; import com.vividsolutions.jump.workbench.ui.Viewport; public class ColorThemingStyle implements Style { public ColorThemingStyle() { //Parameterless constructor for Java2XML. [Jon Aquino] } /** * Call this method after calling #setAttributeValueToBasicStyleMap rather * than before. */ public void setAlpha(int alpha) { defaultStyle.setAlpha(alpha); for (Iterator i = attributeValueToBasicStyleMap.values().iterator(); i .hasNext();) { BasicStyle style = (BasicStyle) i.next(); style.setAlpha(alpha); } } /** * Call this method after calling #setAttributeValueToBasicStyleMap rather * than before. */ public void setLineWidth(int lineWidth) { defaultStyle.setLineWidth(lineWidth); for (Iterator i = attributeValueToBasicStyleMap.values().iterator(); i .hasNext();) { BasicStyle style = (BasicStyle) i.next(); style.setLineWidth(lineWidth); } } /** * @param defaultStyle * <code>null</code> to prevent drawing features with a null * attribute value */ public ColorThemingStyle(String attributeName, Map attributeValueToBasicStyleMap, BasicStyle defaultStyle) { this(attributeName, attributeValueToBasicStyleMap, attributeValueToLabelMap(attributeValueToBasicStyleMap), defaultStyle); // [sstein: 2.Dec.06] i guess this constructor comes from Erwan to // allow different types of classing } public ColorThemingStyle(String attributeName, Map attributeValueToBasicStyleMap, Map attributeValueToLabelMap, BasicStyle defaultStyle) { setAttributeName(attributeName); setAttributeValueToBasicStyleMap(attributeValueToBasicStyleMap); setAttributeValueToLabelMap(attributeValueToLabelMap); setDefaultStyle(defaultStyle); } private static Map attributeValueToLabelMap(Map attributeValueToBasicStyleMap) { // Be sure to use the same Map class -- it may be a RangeTreeMap [Jon Aquino 2005-07-30] Map attributeValueToLabelMap = (Map) LangUtil.newInstance(attributeValueToBasicStyleMap.getClass()); for (Iterator i = attributeValueToBasicStyleMap.keySet().iterator(); i.hasNext(); ) { Object value = i.next(); attributeValueToLabelMap.put(value, value.toString()); } return attributeValueToLabelMap; } private BasicStyle defaultStyle; public void paint(Feature f, Graphics2D g, Viewport viewport) throws Exception { getStyle(f).paint(f, g, viewport); } private BasicStyle getStyle(Feature feature) { //Attribute name will be null if a layer has only a spatial attribute. // [Jon Aquino] //If we can't find an attribute with this name, just use the //defaultStyle. The attribute may have been deleted. [Jon Aquino] // If the attribute data type for color theming has been changed - // throws multiple exceptions and the layer dissappears due to the // fact that it can't find the style in the valuetobasicstyle map. // Solved here by catching the exception and returning the default style // (just like when the attribute name has been changed). [Ed Deen] BasicStyle style = null; try { style = attributeName != null && feature.getSchema().hasAttribute(attributeName) && feature.getAttribute(attributeName) != null ? (BasicStyle) attributeValueToBasicStyleMap .get(trimIfString(feature.getAttribute(attributeName))) : defaultStyle; } catch (ClassCastException e) { // Do Nothing }; /*try*/ return style == null ? defaultStyle : style; } public static Object trimIfString(Object object) { return object != null && object instanceof String ? ((String) object) .trim() : object; } private Layer layer; private Map attributeValueToBasicStyleMap = new HashMap(); //[sstein 2.Dec.06] added = new Hashmap private Map attributeValueToLabelMap; private String attributeName; //[sstein 2.Dec.06] note: some things here are different. I am not sure if the changes // come from changes by VividSolution or preparations for different classing by Erwan public Object clone() { try { ColorThemingStyle clone = (ColorThemingStyle) super.clone(); //Deep-copy the map, to facilitate undo. [Jon Aquino] clone.attributeValueToBasicStyleMap = (Map) attributeValueToBasicStyleMap.getClass() .newInstance(); for (Iterator i = attributeValueToBasicStyleMap.keySet().iterator(); i .hasNext();) { Object attribute = (Object) i.next(); clone.attributeValueToBasicStyleMap.put(attribute, ((BasicStyle) attributeValueToBasicStyleMap .get(attribute)).clone()); } clone.attributeValueToLabelMap = (Map) attributeValueToLabelMap.getClass().newInstance(); clone.attributeValueToLabelMap.putAll(attributeValueToLabelMap); return clone; } catch (InstantiationException e) { Assert.shouldNeverReachHere(); return null; } catch (IllegalAccessException e) { Assert.shouldNeverReachHere(); return null; } catch (CloneNotSupportedException e) { Assert.shouldNeverReachHere(); return null; } } /** * @return null if the layer has no non-spatial attributes */ public String getAttributeName() { return attributeName; } /** * You can set the keys to Ranges if the Map is a Range.RangeTreeMap. But * don't mix Ranges and non-Ranges -- the UI expects homogeneity in this * regard (i.e. to test whether or not there are ranges, only the first * attribute value is tested). */ public void setAttributeValueToBasicStyleMap(Map attributeValueToBasicStyleMap) { this.attributeValueToBasicStyleMap = attributeValueToBasicStyleMap; } /** * You can set the keys to Ranges if the Map is a Range.RangeTreeMap. But * don't mix Ranges and non-Ranges -- the UI expects homogeneity in this * regard (i.e. to test whether or not there are ranges, only the first * attribute value is tested). */ public void setAttributeValueToLabelMap(Map attributeValueToLabelMap) { this.attributeValueToLabelMap = attributeValueToLabelMap; } public void setAttributeName(String attributeName) { this.attributeName = attributeName; } public Map getAttributeValueToBasicStyleMap() { return attributeValueToBasicStyleMap; } public Map getAttributeValueToLabelMap() { return attributeValueToLabelMap; } private boolean enabled = false; public void initialize(Layer layer) { this.layer = layer; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return enabled; } public static ColorThemingStyle get(Layer layer) { if ((ColorThemingStyle) layer.getStyle(ColorThemingStyle.class) == null) { ColorThemingStyle colorThemingStyle = new ColorThemingStyle( pickNonSpatialAttributeName(layer .getFeatureCollectionWrapper().getFeatureSchema()), new HashMap(), new BasicStyle(Color.lightGray)); layer.addStyle(colorThemingStyle); } return (ColorThemingStyle) layer.getStyle(ColorThemingStyle.class); } private static String pickNonSpatialAttributeName(FeatureSchema schema) { for (int i = 0; i < schema.getAttributeCount(); i++) { if (schema.getGeometryIndex() != i) { return schema.getAttributeName(i); } } return null; } public BasicStyle getDefaultStyle() { return defaultStyle; } public void setDefaultStyle(BasicStyle defaultStyle) { this.defaultStyle = defaultStyle; } }