001: package net.refractions.udig.project.internal.render;
002:
003: import java.awt.Color;
004: import java.io.IOException;
005: import java.net.URL;
006:
007: import net.refractions.udig.catalog.IGeoResource;
008: import net.refractions.udig.project.StyleContent;
009: import net.refractions.udig.project.internal.Layer;
010: import net.refractions.udig.project.internal.ProjectPlugin;
011: import net.refractions.udig.project.preferences.PreferenceConstants;
012:
013: import org.eclipse.core.runtime.IProgressMonitor;
014: import org.eclipse.jface.preference.IPreferenceStore;
015: import org.eclipse.jface.preference.PreferenceConverter;
016: import org.eclipse.swt.graphics.RGB;
017: import org.eclipse.ui.IMemento;
018: import org.geotools.feature.FeatureType;
019: import org.geotools.feature.GeometryAttributeType;
020: import org.geotools.filter.CompareFilter;
021: import org.geotools.filter.Expression;
022: import org.geotools.filter.FilterFactory;
023: import org.geotools.filter.FilterFactoryFinder;
024: import org.geotools.filter.FilterType;
025: import org.geotools.filter.IllegalFilterException;
026: import org.geotools.filter.function.FilterFunction_geometryType;
027: import org.geotools.styling.FeatureTypeStyle;
028: import org.geotools.styling.Fill;
029: import org.geotools.styling.LineSymbolizer;
030: import org.geotools.styling.Mark;
031: import org.geotools.styling.PointSymbolizer;
032: import org.geotools.styling.PolygonSymbolizer;
033: import org.geotools.styling.Rule;
034: import org.geotools.styling.Stroke;
035: import org.geotools.styling.Style;
036: import org.geotools.styling.StyleBuilder;
037: import org.geotools.styling.StyleFactory;
038: import org.geotools.styling.StyleFactoryFinder;
039: import org.geotools.styling.StyledLayerDescriptor;
040: import org.geotools.styling.Symbolizer;
041: import org.geotools.styling.UserLayer;
042:
043: import com.vividsolutions.jts.geom.LineString;
044: import com.vividsolutions.jts.geom.LinearRing;
045: import com.vividsolutions.jts.geom.MultiLineString;
046: import com.vividsolutions.jts.geom.MultiPoint;
047: import com.vividsolutions.jts.geom.MultiPolygon;
048: import com.vividsolutions.jts.geom.Point;
049: import com.vividsolutions.jts.geom.Polygon;
050:
051: /**
052: * The style used for Selection
053: *
054: * @author jeichar
055: * @since 0.6.0
056: */
057: public class SelectionStyleContent extends StyleContent {
058:
059: /** <code>ID</code> field */
060: public static final String ID = "net.refractions.udig.project.selectionStyle"; //$NON-NLS-1$
061:
062: private static final StyleBuilder builder = new StyleBuilder();
063: private static final StyleFactory styleFactory = StyleFactoryFinder
064: .createStyleFactory();
065:
066: private static final String fTypeName = "fTypeName"; //$NON-NLS-1$
067:
068: static Color getColor() {
069: IPreferenceStore store = ProjectPlugin.getPlugin()
070: .getPreferenceStore();
071: RGB rgb = PreferenceConverter.getColor(store,
072: PreferenceConstants.P_SELECTION_COLOR);
073: return new Color(rgb.red, rgb.green, rgb.blue);
074: }
075:
076: private StyleBuilder styleBuilder = new StyleBuilder();
077:
078: /**
079: * Construct <code>SelectionStyleContent</code>.
080: */
081: public SelectionStyleContent() {
082: super (ID);
083: }
084:
085: /**
086: * Returns a geotools style object.
087: */
088: public Class getStyleClass() {
089: return Style.class;
090: }
091:
092: /**
093: * Does nothing.
094: */
095: public void save(IMemento momento, Object value) {
096: Style style = (Style) value;
097:
098: // store the feature type name
099: momento.putString(fTypeName, style.getFeatureTypeStyles()[0]
100: .getFeatureTypeName());
101: }
102:
103: public Object load(IMemento momento) {
104: // Style style = createDefaultStyle(null);
105: // style.getFeatureTypeStyles()[0].setFeatureTypeName(momento.getString(fTypeName));
106: // //nest the style in an SLD
107: // createDefaultStyledLayerDescriptor(style);
108: // return style;
109: return null;
110: }
111:
112: /*
113: * (non-Javadoc)
114: *
115: * @see net.refractions.udig.project.StyleContent#createDefaultStyle(net.refractions.udig.catalog.IGeoResource)
116: */
117: public Object createDefaultStyle(IGeoResource resource,
118: Color colour, IProgressMonitor monitor) {
119: return null;
120: }
121:
122: public static Style createDefaultStyle(Layer layer) {
123: Style style = builder.createStyle();
124:
125: SelectionStyleContent ssc = new SelectionStyleContent();
126: FeatureType schema = layer.getSchema();
127: if (schema == null)
128: return null;
129: GeometryAttributeType geom = schema.getDefaultGeometry();
130: if (isLine(geom)) {
131: ssc.getDefaultRule(style).setSymbolizers(
132: new Symbolizer[] { ssc
133: .createLineSymbolizer(getColor()) });
134: } else if (isPoint(geom)) {
135: ssc.getDefaultRule(style).setSymbolizers(
136: new Symbolizer[] { ssc
137: .createPointSymbolizer(getColor()) });
138: } else if (isPolygon(geom)) {
139: ssc.getDefaultRule(style).setSymbolizers(
140: new Symbolizer[] { ssc
141: .createPolygonSymbolizer(getColor()) });
142: } else {
143: try {
144: ssc.createGeometrySLD(getColor(), schema
145: .getDefaultGeometry().getName(), style);
146: } catch (Exception e) {
147: ProjectPlugin.log("", e); //$NON-NLS-1$
148: ssc.getDefaultRule(style).setSymbolizers(
149: new Symbolizer[] { ssc
150: .createLineSymbolizer(getColor()) });
151: }
152: }
153:
154: // nest the style in an SLD
155: createDefaultStyledLayerDescriptor(style);
156: return style;
157: }
158:
159: private CompareFilter createGeometryFunctionFilter(
160: String geomXPath, Object geometryClassSimpleName)
161: throws IllegalFilterException {
162: FilterFactory factory = FilterFactoryFinder
163: .createFilterFactory();
164: FilterFunction_geometryType geomTypeExpr = new FilterFunction_geometryType();
165: geomTypeExpr.setArgs(new Expression[] { factory
166: .createAttributeExpression(geomXPath) });
167:
168: CompareFilter filter = factory
169: .createCompareFilter(FilterType.COMPARE_EQUALS);
170: filter.addLeftValue(geomTypeExpr);
171: filter.addRightValue(factory
172: .createLiteralExpression(geometryClassSimpleName));
173: return filter;
174: }
175:
176: private void createGeometrySLD(Color colour, String geomXPath,
177: Style style) throws IllegalFilterException {
178: // create Point rule
179: Rule rule = getDefaultRule(style);
180: CompareFilter filter = createGeometryFunctionFilter(geomXPath,
181: Point.class.getSimpleName());
182: rule.setFilter(filter);
183: rule
184: .setSymbolizers(new Symbolizer[] { createPointSymbolizer(colour) });
185: getDefaultFeatureTypeStyle(style).addRule(rule);
186:
187: // create MultiPoint rule
188: rule = styleBuilder.createRule(new Symbolizer[] {});
189: filter = createGeometryFunctionFilter(geomXPath,
190: MultiPoint.class.getSimpleName());
191: rule.setFilter(filter);
192: rule
193: .setSymbolizers(new Symbolizer[] { createPointSymbolizer(colour) });
194: getDefaultFeatureTypeStyle(style).addRule(rule);
195:
196: // create LineString rule
197: rule = styleBuilder.createRule(new Symbolizer[] {});
198: filter = createGeometryFunctionFilter(geomXPath,
199: LineString.class.getSimpleName());
200: rule.setFilter(filter);
201: rule
202: .setSymbolizers(new Symbolizer[] { createLineSymbolizer(colour) });
203: getDefaultFeatureTypeStyle(style).addRule(rule);
204:
205: // create LinearRing rule
206: rule = styleBuilder.createRule(new Symbolizer[] {});
207: filter = createGeometryFunctionFilter(geomXPath,
208: LinearRing.class.getSimpleName());
209: rule.setFilter(filter);
210: rule
211: .setSymbolizers(new Symbolizer[] { createLineSymbolizer(colour) });
212: getDefaultFeatureTypeStyle(style).addRule(rule);
213:
214: // create MultiLineString rule
215: rule = styleBuilder.createRule(new Symbolizer[] {});
216: filter = createGeometryFunctionFilter(geomXPath,
217: MultiLineString.class.getSimpleName());
218: rule.setFilter(filter);
219: rule
220: .setSymbolizers(new Symbolizer[] { createLineSymbolizer(colour) });
221: getDefaultFeatureTypeStyle(style).addRule(rule);
222:
223: // create Polygon rule
224: rule = styleBuilder.createRule(new Symbolizer[] {});
225: filter = createGeometryFunctionFilter(geomXPath, Polygon.class
226: .getSimpleName());
227: rule.setFilter(filter);
228: rule
229: .setSymbolizers(new Symbolizer[] { createPolygonSymbolizer(colour) });
230: getDefaultFeatureTypeStyle(style).addRule(rule);
231:
232: // create MultiPolygon rule
233: rule = styleBuilder.createRule(new Symbolizer[] {});
234: filter = createGeometryFunctionFilter(geomXPath,
235: MultiPolygon.class.getSimpleName());
236: rule.setFilter(filter);
237: rule
238: .setSymbolizers(new Symbolizer[] { createPolygonSymbolizer(colour) });
239: getDefaultFeatureTypeStyle(style).addRule(rule);
240:
241: }
242:
243: /**
244: * @return the first rule in the default feature type style.
245: */
246: public Rule getDefaultRule(Style style) {
247: FeatureTypeStyle ftStyle = getDefaultFeatureTypeStyle(style);
248: if (ftStyle.getRules() == null
249: || ftStyle.getRules().length == 0) {
250: // create an empty rule
251: Rule rule = styleBuilder.createRule(new Symbolizer[] {});
252: ftStyle.addRule(rule);
253: return rule;
254: }
255:
256: return ftStyle.getRules()[0];
257: }
258:
259: /**
260: * Returns the the first feature type style for the SLD style. The feature type style is created
261: * if it does not exist.
262: *
263: * @return The default (first) feature type style.
264: */
265: public FeatureTypeStyle getDefaultFeatureTypeStyle(Style style) {
266: FeatureTypeStyle[] styles = style.getFeatureTypeStyles();
267: if (styles == null || styles.length == 0
268: || styles[0].getRules().length == 0) {
269: // create a feature type style
270: FeatureTypeStyle ftStyle = styleBuilder
271: .createFeatureTypeStyle("default", new Rule[] {}); //$NON-NLS-1$
272: style.addFeatureTypeStyle(ftStyle);
273: return ftStyle;
274: }
275:
276: return styles[0];
277: }
278:
279: protected PointSymbolizer createPointSymbolizer(Color colour) {
280: PointSymbolizer symb = styleBuilder.createPointSymbolizer();
281: Fill fill = styleBuilder.createFill(Color.YELLOW, 0.0);
282:
283: Stroke stroke = builder.createStroke(getColor(), 2);
284: symb.getGraphic().setMarks(
285: new Mark[] { styleBuilder.createMark(
286: "square", fill, stroke) }); //$NON-NLS-1$
287:
288: return symb;
289: }
290:
291: protected LineSymbolizer createLineSymbolizer(Color colour) {
292: LineSymbolizer symbolizer = styleBuilder.createLineSymbolizer();
293:
294: Stroke stroke = builder.createStroke(getColor(), 2);
295: stroke.setDashArray(new float[] { 4, 4 });
296: symbolizer.setStroke(stroke);
297:
298: return symbolizer;
299: }
300:
301: protected PolygonSymbolizer createPolygonSymbolizer(Color colour) {
302: PolygonSymbolizer symbolizer = styleBuilder
303: .createPolygonSymbolizer();
304:
305: Stroke stroke = builder.createStroke(getColor(), 2);
306: stroke.setDashArray(new float[] { 4, 4 });
307: symbolizer.setStroke(stroke);
308:
309: Fill fill = styleBuilder.createFill();
310: fill.setColor(styleBuilder.colorExpression(colour));
311: fill.setOpacity(styleBuilder.literalExpression(.5));
312: symbolizer.setFill(fill);
313:
314: return symbolizer;
315: }
316:
317: /*
318: * @see net.refractions.udig.project.StyleContent#load(java.net.URL)
319: */
320: public Object load(URL url, IProgressMonitor monitor)
321: throws IOException {
322: return null;
323: }
324:
325: /**
326: * Creates an SLD and UserLayer, and nests the style (SLD-->UserLayer-->Style). This method is a
327: * copy of the one in SLDContent to avoid a cyclic dependency.
328: *
329: * @see net.refractions.style.sld.SLDContent#createDefaultStyledLayerDescriptor
330: * @param style
331: * @return SLD
332: */
333: private static StyledLayerDescriptor createDefaultStyledLayerDescriptor(
334: Style style) {
335: StyledLayerDescriptor sld = styleFactory
336: .createStyledLayerDescriptor();
337: UserLayer layer = styleFactory.createUserLayer();
338: sld.addStyledLayer(layer);
339: layer.addUserStyle(style);
340: return sld;
341: }
342:
343: public static final boolean isPolygon(FeatureType featureType) {
344: if (featureType == null)
345: return false;
346: return isPolygon(featureType.getDefaultGeometry());
347: }
348:
349: /* This needed to be a function as it was being writen poorly everywhere */
350: public static final boolean isPolygon(
351: GeometryAttributeType geometryType) {
352: if (geometryType == null)
353: return false;
354: Class type = geometryType.getType();
355: return Polygon.class.isAssignableFrom(type)
356: || MultiPolygon.class.isAssignableFrom(type);
357: }
358:
359: public static final boolean isLine(FeatureType featureType) {
360: if (featureType == null)
361: return false;
362: return isLine(featureType.getDefaultGeometry());
363: }
364:
365: /* This needed to be a function as it was being writen poorly everywhere */
366: public static final boolean isLine(
367: GeometryAttributeType geometryType) {
368: if (geometryType == null)
369: return false;
370: Class type = geometryType.getType();
371: return LineString.class.isAssignableFrom(type)
372: || MultiLineString.class.isAssignableFrom(type);
373: }
374:
375: public static final boolean isPoint(FeatureType featureType) {
376: if (featureType == null)
377: return false;
378: return isPoint(featureType.getDefaultGeometry());
379: }
380:
381: /* This needed to be a function as it was being writen poorly everywhere */
382: public static final boolean isPoint(
383: GeometryAttributeType geometryType) {
384: if (geometryType == null)
385: return false;
386: Class type = geometryType.getType();
387: return Point.class.isAssignableFrom(type)
388: || MultiPoint.class.isAssignableFrom(type);
389: }
390: }
|