001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2002, Centre for Computational Geography
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.styling;
018:
019: import org.geotools.event.AbstractGTComponent;
020: import org.geotools.event.GTList;
021: import org.geotools.factory.CommonFactoryFinder;
022: import org.geotools.factory.GeoTools;
023: import org.geotools.resources.Utilities;
024: import org.opengis.filter.FilterFactory;
025: import org.opengis.filter.expression.Expression;
026: import org.opengis.util.Cloneable;
027:
028: // OpenGIS dependencies
029: import java.util.Arrays;
030: import java.util.HashMap;
031: import java.util.List;
032: import java.util.Map;
033:
034: /**
035: * Provides a Java representation of an SLD TextSymbolizer that defines how
036: * text symbols should be rendered.
037: *
038: * @author Ian Turton, CCG
039: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/styling/TextSymbolizerImpl.java $
040: * @version $Id: TextSymbolizerImpl.java 25459 2007-05-08 05:19:25Z jgarnett $
041: */
042: public class TextSymbolizerImpl extends AbstractGTComponent implements
043: TextSymbolizer2, Cloneable {
044: private final FilterFactory filterFactory;
045: private Fill fill;
046: private java.util.List fonts = new GTList(this , "fonts");
047: private Halo halo;
048: private LabelPlacement placement;
049: private String geometryPropertyName = null;
050: private Expression label = null;
051: private Graphic graphic = null;
052: private Expression priority = null;
053: private HashMap optionsMap = null; //null=nothing in it
054:
055: protected TextSymbolizerImpl() {
056: this (CommonFactoryFinder.getFilterFactory(GeoTools
057: .getDefaultHints()));
058: }
059:
060: /**
061: * Creates a new instance of DefaultTextSymbolizer
062: */
063: protected TextSymbolizerImpl(FilterFactory factory) {
064: this .filterFactory = factory;
065: fill = new FillImpl();
066: fill.setColor(filterFactory.literal("#000000")); // default text fill is black
067: halo = null;
068: placement = new PointPlacementImpl();
069: }
070:
071: /**
072: * This property defines the geometry to be used for styling.<br>
073: * The property is optional and if it is absent (null) then the "default"
074: * geometry property of the feature should be used. Geometry types other
075: * than inherently point types can be used. The geometryPropertyName is
076: * the name of a geometry property in the Feature being styled.
077: * Typically, features only have one geometry so, in general, the need to
078: * select one is not required. Note: this moves a little away from the SLD
079: * spec which provides an XPath reference to a Geometry object, but does
080: * follow it in spirit.
081: *
082: * @return String The name of the attribute in the feature being styled
083: * that should be used. If null then the default geometry should
084: * be used.
085: */
086: public String geometryPropertyName() {
087: return geometryPropertyName;
088: }
089:
090: /**
091: * Returns the fill to be used to fill the text when rendered.
092: *
093: * @return The fill to be used.
094: */
095: public Fill getFill() {
096: return fill;
097: }
098:
099: /**
100: * Setter for property fill.
101: *
102: * @param fill New value of property fill.
103: */
104: public void setFill(Fill fill) {
105: if (this .fill == fill) {
106: return;
107: }
108:
109: Fill old = this .fill;
110: this .fill = fill;
111: fireChildChanged("fill", fill, old);
112: }
113:
114: /**
115: * Returns a device independent Font object that is to be used to render
116: * the label.
117: *
118: * @return Device independent Font object to be used to render the label.
119: */
120: public Font[] getFonts() {
121: if (fonts.size() == 0) {
122: fonts.add(new FontImpl());
123: }
124:
125: return (Font[]) fonts.toArray(new Font[] {});
126: }
127:
128: /**
129: * Setter for property font.
130: *
131: * @param font New value of property font.
132: */
133: public void addFont(org.geotools.styling.Font font) {
134: this .fonts.add(font);
135: }
136:
137: /**
138: * Sets the list of fonts in the TextSymbolizer to the provided array of
139: * Fonts.
140: *
141: * @param fonts The array of fonts to use in the symbolizer.
142: */
143: public void setFonts(Font[] fonts) {
144: List newFonts = Arrays.asList(fonts);
145: this .fonts.clear();
146: this .fonts.addAll(newFonts);
147: }
148:
149: /**
150: * A halo fills an extended area outside the glyphs of a rendered text
151: * label to make the label easier to read over a background.
152: *
153: * @return DOCUMENT ME!
154: */
155: public Halo getHalo() {
156: return halo;
157: }
158:
159: /**
160: * Setter for property halo.
161: *
162: * @param halo New value of property halo.
163: */
164: public void setHalo(Halo halo) {
165: if (this .halo == halo) {
166: return;
167: }
168:
169: Halo old = this .halo;
170: this .halo = halo;
171: fireChildChanged("halo", halo, old);
172: }
173:
174: /**
175: * Returns the label expression.
176: *
177: * @return Label expression.
178: */
179: public Expression getLabel() {
180: return label;
181: }
182:
183: /**
184: * Setter for property label.
185: *
186: * @param label New value of property label.
187: */
188: public void setLabel(Expression label) {
189: Expression old = this .label;
190: this .label = label;
191: fireChildChanged("label", label, old);
192: }
193:
194: /**
195: * A pointPlacement specifies how a text element should be rendered
196: * relative to its geometric point.
197: *
198: * @return Value of property labelPlacement.
199: */
200: public LabelPlacement getPlacement() {
201: return placement;
202: }
203:
204: /**
205: * Setter for property labelPlacement.
206: *
207: * @param labelPlacement New value of property labelPlacement.
208: */
209: public void setPlacement(LabelPlacement labelPlacement) {
210: if (this .placement == labelPlacement) {
211: return;
212: }
213:
214: LabelPlacement old = this .placement;
215: this .placement = labelPlacement;
216: fireChildChanged("placement", labelPlacement, old);
217: }
218:
219: /**
220: * A pointPlacement specifies how a text element should be rendered
221: * relative to its geometric point.
222: *
223: * @return Value of property labelPlacement.
224: *
225: * @deprecated use getPlacement()
226: */
227: public LabelPlacement getLabelPlacement() {
228: return getPlacement();
229: }
230:
231: /**
232: * Setter for property labelPlacement.
233: *
234: * @param labelPlacement New value of property labelPlacement.
235: *
236: * @deprecated use setPlacement(LabelPlacement)
237: */
238: public void setLabelPlacement(
239: org.geotools.styling.LabelPlacement labelPlacement) {
240: setPlacement(labelPlacement);
241: }
242:
243: /**
244: * Getter for property geometryPropertyName.
245: *
246: * @return Value of property geometryPropertyName.
247: */
248: public java.lang.String getGeometryPropertyName() {
249: return geometryPropertyName;
250: }
251:
252: /**
253: * Setter for property geometryPropertyName.
254: *
255: * @param geometryPropertyName New value of property geometryPropertyName.
256: */
257: public void setGeometryPropertyName(
258: java.lang.String geometryPropertyName) {
259: this .geometryPropertyName = geometryPropertyName;
260: fireChanged();
261: }
262:
263: /**
264: * Accept a StyleVisitor to perform an operation on this symbolizer.
265: *
266: * @param visitor The StyleVisitor to accept.
267: */
268: public void accept(StyleVisitor visitor) {
269: visitor.visit(this );
270: }
271:
272: /**
273: * Creates a deep copy clone. TODO: Need to complete the deep copy,
274: * currently only shallow copy.
275: *
276: * @return The deep copy clone.
277: *
278: * @throws AssertionError DOCUMENT ME!
279: */
280: public Object clone() {
281: try {
282: return super .clone();
283: } catch (CloneNotSupportedException e) {
284: throw new AssertionError(e); // this should never happen.
285: }
286: }
287:
288: public int hashCode() {
289: final int PRIME = 1000003;
290: int result = 0;
291:
292: if (fill != null) {
293: result = (PRIME * result) + fill.hashCode();
294: }
295:
296: if (fonts != null) {
297: result = (PRIME * result) + fonts.hashCode();
298: }
299:
300: if (halo != null) {
301: result = (PRIME * result) + halo.hashCode();
302: }
303:
304: if (placement != null) {
305: result = (PRIME * result) + placement.hashCode();
306: }
307:
308: if (geometryPropertyName != null) {
309: result = (PRIME * result) + geometryPropertyName.hashCode();
310: }
311:
312: if (label != null) {
313: result = (PRIME * result) + label.hashCode();
314: }
315:
316: return result;
317: }
318:
319: public boolean equals(Object oth) {
320: if (this == oth) {
321: return true;
322: }
323:
324: if (oth == null) {
325: return false;
326: }
327:
328: if (oth instanceof TextSymbolizerImpl) {
329: TextSymbolizerImpl other = (TextSymbolizerImpl) oth;
330:
331: return Utilities.equals(this .geometryPropertyName,
332: other.geometryPropertyName)
333: && Utilities.equals(this .label, other.label)
334: && Utilities.equals(this .halo, other.halo)
335: && Utilities.equals(this .fonts, other.fonts)
336: && Utilities
337: .equals(this .placement, other.placement)
338: && Utilities.equals(this .fill, other.fill);
339: }
340:
341: return false;
342: }
343:
344: /* (non-Javadoc)
345: * @see org.geotools.styling.TextSymbolizer#setPriority(org.geotools.filter.Expression)
346: */
347: public void setPriority(Expression priority) {
348: if (this .priority == priority) {
349: return;
350: }
351:
352: Expression old = this .priority;
353: this .priority = priority;
354: fireChildChanged("priority", priority, old);
355: }
356:
357: /* (non-Javadoc)
358: * @see org.geotools.styling.TextSymbolizer#getPriority()
359: * null = "default"
360: * should evaluate to a Number.
361: */
362: public Expression getPriority() {
363: return priority;
364: }
365:
366: /* (non-Javadoc)
367: * @see org.geotools.styling.TextSymbolizer#addToOptions(java.lang.String, java.lang.String)
368: */
369: public void addToOptions(String key, String value) {
370: if (optionsMap == null) {
371: optionsMap = new HashMap();
372: }
373:
374: optionsMap.put(key, value.trim());
375: fireChanged(); // TODO: Handle Options Map?
376: }
377:
378: /* (non-Javadoc)
379: * @see org.geotools.styling.TextSymbolizer#getOption(java.lang.String)
380: */
381: public String getOption(String key) {
382: if (optionsMap == null) {
383: return null;
384: }
385:
386: return (String) optionsMap.get(key);
387: }
388:
389: /* (non-Javadoc)
390: * @see org.geotools.styling.TextSymbolizer#getOptions()
391: */
392: public Map getOptions() {
393: return optionsMap;
394: }
395:
396: public Graphic getGraphic() {
397: return graphic;
398: }
399:
400: public void setGraphic(Graphic graphic) {
401: if (this .graphic == graphic) {
402: return;
403: }
404:
405: Graphic old = this .graphic;
406: this .graphic = graphic;
407: fireChildChanged("graphic", graphic, old);
408: }
409: }
|