001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI for
003: * visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or modify it under
008: * the terms of the GNU General Public License as published by the Free Software
009: * Foundation; either version 2 of the License, or (at your option) any later
010: * version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
014: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
015: * details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
019: * Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions Suite #1A 2328 Government Street Victoria BC V8T 5G5 Canada
024: *
025: * (250)385-6040 www.vividsolutions.com
026: */
027: package de.latlon.deejump.plugin.style;
028:
029: import java.awt.Color;
030: import java.awt.Graphics2D;
031: import java.util.HashMap;
032: import java.util.Iterator;
033: import java.util.Map;
034:
035: import com.vividsolutions.jts.util.Assert;
036: import com.vividsolutions.jump.feature.Feature;
037: import com.vividsolutions.jump.feature.FeatureSchema;
038: import com.vividsolutions.jump.util.LangUtil;
039: import com.vividsolutions.jump.workbench.model.Layer;
040: import com.vividsolutions.jump.workbench.ui.Viewport;
041: import com.vividsolutions.jump.workbench.ui.renderer.style.BasicStyle;
042: import com.vividsolutions.jump.workbench.ui.renderer.style.SquareVertexStyle;
043: import com.vividsolutions.jump.workbench.ui.renderer.style.Style;
044: import com.vividsolutions.jump.workbench.ui.renderer.style.VertexStyle;
045:
046: public class DeeColorThemingStyle implements Style {
047: public DeeColorThemingStyle() {
048: //Parameterless constructor for Java2XML. [Jon Aquino]
049: //UT
050: this ("", new HashMap(), new HashMap(), new HashMap(),
051: new BasicStyle());
052: }
053:
054: /**
055: * Call this method after calling #setAttributeValueToBasicStyleMap rather
056: * than before.
057: */
058: public void setAlpha(int alpha) {
059: defaultStyle.setAlpha(alpha);
060: for (Iterator i = attributeValueToBasicStyleMap.values()
061: .iterator(); i.hasNext();) {
062: BasicStyle style = (BasicStyle) i.next();
063: style.setAlpha(alpha);
064: }
065: }
066:
067: /**
068: * Call this method after calling #setAttributeValueToBasicStyleMap rather
069: * than before.
070: */
071: public void setLineWidth(int lineWidth) {
072: defaultStyle.setLineWidth(lineWidth);
073: for (Iterator i = attributeValueToBasicStyleMap.values()
074: .iterator(); i.hasNext();) {
075: BasicStyle style = (BasicStyle) i.next();
076: style.setLineWidth(lineWidth);
077: }
078: }
079:
080: /**
081: * @param defaultStyle
082: * <code>null</code> to prevent drawing features with a null
083: * attribute value
084: */
085: public DeeColorThemingStyle(String attributeName,
086: Map attributeValueToBasicStyleMap, BasicStyle defaultStyle) {
087: this (
088: attributeName,
089: attributeValueToBasicStyleMap,
090: attributeValueToLabelMap(attributeValueToBasicStyleMap),
091: defaultStyle);
092:
093: }
094:
095: public DeeColorThemingStyle(String attributeName,
096: Map attributeValueToBasicStyleMap,
097: Map attributeValueToLabelMap, BasicStyle defaultStyle) {
098: this (
099: attributeName,
100: attributeValueToBasicStyleMap,
101: attributeValueToLabelMap(attributeValueToBasicStyleMap),
102: attributeValueToVertexStyleMap(attributeValueToBasicStyleMap),
103: defaultStyle);
104:
105: }
106:
107: public DeeColorThemingStyle(String attributeName,
108: Map attributeValueToBasicStyleMap,
109: Map attributeValueToLabelMap,
110: Map attributeValueToVertexStyleMap, BasicStyle defaultStyle) {
111: setAttributeName(attributeName);
112: setAttributeValueToBasicStyleMap(attributeValueToBasicStyleMap);
113: setAttributeValueToLabelMap(attributeValueToLabelMap);
114: setAttributeValueToVertexStyleMap(attributeValueToVertexStyleMap);
115: setDefaultStyle(defaultStyle);
116:
117: }
118:
119: /**
120: * @param attributeValueToVertexStyleMap2
121: */
122: public void setAttributeValueToVertexStyleMap(
123: Map attributeValueToVertexStyleMap) {
124: this .attributeValueToVertexStyleMap = attributeValueToVertexStyleMap;
125:
126: }
127:
128: private static Map attributeValueToLabelMap(
129: Map attributeValueToBasicStyleMap) {
130: // Be sure to use the same Map class -- it may be a RangeTreeMap [Jon Aquino 2005-07-30]
131: Map attributeValueToLabelMap = (Map) LangUtil
132: .newInstance(attributeValueToBasicStyleMap.getClass());
133: for (Iterator i = attributeValueToBasicStyleMap.keySet()
134: .iterator(); i.hasNext();) {
135: Object value = i.next();
136: attributeValueToLabelMap.put(value, value.toString());
137: }
138: return attributeValueToLabelMap;
139: }
140:
141: private static Map attributeValueToVertexStyleMap(
142: Map attributeValueToBasicStyleMap) {
143: Map attributeValueToVertexStyleMap = (Map) LangUtil
144: .newInstance(attributeValueToBasicStyleMap.getClass());
145: for (Iterator i = attributeValueToBasicStyleMap.keySet()
146: .iterator(); i.hasNext();) {
147: Object value = i.next();
148: attributeValueToVertexStyleMap.put(value, value.toString());
149: }
150: return attributeValueToVertexStyleMap;
151: }
152:
153: private BasicStyle defaultStyle;
154:
155: public void paint(Feature f, Graphics2D g, Viewport viewport)
156: throws Exception {
157: getStyle(f).paint(f, g, viewport);
158: getVertexStyle(f).paint(f, g, viewport);
159: }
160:
161: /**
162: * @param f
163: * @return
164: */
165: private VertexStyle getVertexStyle(Feature feature) {
166: //TODO why star vertex style as default?!??!?!?
167: VertexStyle style = attributeName != null
168: && feature.getSchema().hasAttribute(attributeName)
169: && feature.getAttribute(attributeName) != null ? (VertexStyle) attributeValueToVertexStyleMap
170: .get(trimIfString(feature.getAttribute(attributeName)))
171: : new SquareVertexStyle();
172: return style == null ? new SquareVertexStyle() : style;
173:
174: }
175:
176: private BasicStyle getStyle(Feature feature) {
177: //Attribute name will be null if a layer has only a spatial attribute.
178: // [Jon Aquino]
179: //If we can't find an attribute with this name, just use the
180: //defaultStyle. The attribute may have been deleted. [Jon Aquino]
181: BasicStyle style = attributeName != null
182: && feature.getSchema().hasAttribute(attributeName)
183: && feature.getAttribute(attributeName) != null ? (BasicStyle) attributeValueToBasicStyleMap
184: .get(trimIfString(feature.getAttribute(attributeName)))
185: : defaultStyle;
186: return style == null ? defaultStyle : style;
187: }
188:
189: public static Object trimIfString(Object object) {
190: return object != null && object instanceof String ? ((String) object)
191: .trim()
192: : object;
193: }
194:
195: private Layer layer;
196: private Map attributeValueToBasicStyleMap;
197: private Map attributeValueToLabelMap;
198: private Map attributeValueToVertexStyleMap;
199: private String attributeName;
200:
201: public Object clone() {
202: try {
203: DeeColorThemingStyle clone = (DeeColorThemingStyle) super
204: .clone();
205: //Deep-copy the map, to facilitate undo. [Jon Aquino]
206: clone.attributeValueToBasicStyleMap = (Map) attributeValueToBasicStyleMap
207: .getClass().newInstance();
208:
209: clone.attributeValueToVertexStyleMap = (Map) attributeValueToVertexStyleMap
210: .getClass().newInstance();
211:
212: for (Iterator i = attributeValueToBasicStyleMap.keySet()
213: .iterator(); i.hasNext();) {
214: Object attribute = (Object) i.next();
215:
216: BasicStyle bs = (BasicStyle) ((BasicStyle) attributeValueToBasicStyleMap
217: .get(attribute)).clone();
218:
219: VertexStyle vs = (VertexStyle) ((VertexStyle) attributeValueToVertexStyleMap
220: .get(attribute)).clone();
221:
222: clone.attributeValueToBasicStyleMap.put(attribute,
223: new PointSymbolizerBasicStyle(bs, vs));
224:
225: clone.attributeValueToVertexStyleMap.put(attribute, vs);
226: }
227: clone.attributeValueToLabelMap = (Map) attributeValueToLabelMap
228: .getClass().newInstance();
229: clone.attributeValueToLabelMap
230: .putAll(attributeValueToLabelMap);
231:
232: return clone;
233: } catch (InstantiationException e) {
234: Assert.shouldNeverReachHere();
235: return null;
236: } catch (IllegalAccessException e) {
237: Assert.shouldNeverReachHere();
238: return null;
239: } catch (CloneNotSupportedException e) {
240: Assert.shouldNeverReachHere();
241: return null;
242: }
243: }
244:
245: /**
246: * @return null if the layer has no non-spatial attributes
247: */
248: public String getAttributeName() {
249: return attributeName;
250: }
251:
252: /**
253: * You can set the keys to Ranges if the Map is a Range.RangeTreeMap. But
254: * don't mix Ranges and non-Ranges -- the UI expects homogeneity in this
255: * regard (i.e. to test whether or not there are ranges, only the first
256: * attribute value is tested).
257: */
258: public void setAttributeValueToBasicStyleMap(
259: Map attributeValueToBasicStyleMap) {
260: this .attributeValueToBasicStyleMap = attributeValueToBasicStyleMap;
261: }
262:
263: /**
264: * You can set the keys to Ranges if the Map is a Range.RangeTreeMap. But
265: * don't mix Ranges and non-Ranges -- the UI expects homogeneity in this
266: * regard (i.e. to test whether or not there are ranges, only the first
267: * attribute value is tested).
268: */
269: public void setAttributeValueToLabelMap(Map attributeValueToLabelMap) {
270: this .attributeValueToLabelMap = attributeValueToLabelMap;
271: }
272:
273: public void setAttributeName(String attributeName) {
274: this .attributeName = attributeName;
275: }
276:
277: public Map getAttributeValueToBasicStyleMap() {
278: return attributeValueToBasicStyleMap;
279: }
280:
281: public Map getAttributeValueToLabelMap() {
282: return attributeValueToLabelMap;
283: }
284:
285: public Map getAttributeValueToVertexStyleMap() {
286: return attributeValueToVertexStyleMap;
287: }
288:
289: private boolean enabled = false;
290:
291: public void initialize(Layer layer) {
292: this .layer = layer;
293: }
294:
295: public void setEnabled(boolean enabled) {
296: this .enabled = enabled;
297: }
298:
299: public boolean isEnabled() {
300: return enabled;
301: }
302:
303: public static DeeColorThemingStyle get(Layer layer) {
304: if ((DeeColorThemingStyle) layer
305: .getStyle(DeeColorThemingStyle.class) == null) {
306: DeeColorThemingStyle colorThemingStyle = new DeeColorThemingStyle(
307: pickNonSpatialAttributeName(layer
308: .getFeatureCollectionWrapper()
309: .getFeatureSchema()), new HashMap(),
310: new BasicStyle(Color.lightGray));
311: layer.addStyle(colorThemingStyle);
312: }
313: return (DeeColorThemingStyle) layer
314: .getStyle(DeeColorThemingStyle.class);
315: }
316:
317: private static String pickNonSpatialAttributeName(
318: FeatureSchema schema) {
319: for (int i = 0; i < schema.getAttributeCount(); i++) {
320: if (schema.getGeometryIndex() != i) {
321: return schema.getAttributeName(i);
322: }
323: }
324: return null;
325: }
326:
327: public BasicStyle getDefaultStyle() {
328: return defaultStyle;
329: }
330:
331: public void setDefaultStyle(BasicStyle defaultStyle) {
332: this.defaultStyle = defaultStyle;
333: }
334:
335: }
|