001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for 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
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program 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
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui.renderer;
034:
035: import java.awt.BasicStroke;
036: import java.awt.Color;
037: import java.awt.Graphics2D;
038: import java.awt.Shape;
039: import java.awt.Stroke;
040: import java.awt.geom.NoninvertibleTransformException;
041: import java.awt.geom.Point2D;
042: import java.awt.geom.Rectangle2D;
043: import java.util.*;
044:
045: import javax.swing.Icon;
046:
047: import com.vividsolutions.jts.geom.Coordinate;
048: import com.vividsolutions.jts.geom.Envelope;
049: import com.vividsolutions.jts.geom.Geometry;
050: import com.vividsolutions.jts.util.Assert;
051: import com.vividsolutions.jump.feature.Feature;
052: import com.vividsolutions.jump.util.CollectionMap;
053: import com.vividsolutions.jump.workbench.model.Layer;
054: import com.vividsolutions.jump.workbench.ui.GUIUtil;
055: import com.vividsolutions.jump.workbench.ui.LayerViewPanel;
056: import com.vividsolutions.jump.workbench.ui.Viewport;
057: import com.vividsolutions.jump.workbench.ui.renderer.style.Style;
058: import com.vividsolutions.jump.workbench.ui.renderer.style.StyleUtil;
059:
060: public abstract class AbstractSelectionRenderer extends
061: FeatureCollectionRenderer implements Style {
062: public final static int HANDLE_WIDTH = 5;
063: private boolean enabled = true;
064: private Stroke handleStroke = new BasicStroke(1);
065: private Color handleFillColor;
066: private Color handleLineColor = Color.black;
067: private Stroke lineStroke = new BasicStroke(2);
068: private Color lineColor;
069: private Stroke fillStroke = new BasicStroke(1);
070: private Color fillColor;
071: private boolean filling = true;
072: protected LayerViewPanel panel;
073:
074: public AbstractSelectionRenderer(Object contentID,
075: LayerViewPanel panel, Color color, boolean paintingHandles,
076: boolean filling) {
077: super (contentID, panel);
078: this .panel = panel;
079: handleFillColor = color;
080: lineColor = color;
081: fillColor = GUIUtil.alphaColor(Color.white, 75);
082: this .paintingHandles = paintingHandles;
083: this .filling = filling;
084: }
085:
086: public String getName() {
087: throw new UnsupportedOperationException();
088: }
089:
090: public Icon getIcon() {
091: throw new UnsupportedOperationException();
092: }
093:
094: public void setEnabled(boolean enabled) {
095: this .enabled = enabled;
096: }
097:
098: public boolean isEnabled() {
099: return enabled;
100: }
101:
102: public Object clone() {
103: Assert.shouldNeverReachHere();
104: return null;
105: }
106:
107: public void initialize(Layer layer) {
108: }
109:
110: private CollectionMap featureToSelectedItemsMap;
111:
112: private boolean paintingHandles;
113:
114: public void paint(Feature f, Graphics2D g, Viewport viewport)
115: throws NoninvertibleTransformException {
116: for (Iterator i = featureToSelectedItemsMap.getItems(f)
117: .iterator(); i.hasNext();) {
118: Geometry geometry = (Geometry) i.next();
119: paint(geometry, g, viewport);
120: }
121: }
122:
123: public void paint(Geometry geometry, Graphics2D g, Viewport viewport)
124: throws NoninvertibleTransformException {
125: Coordinate[] modelCoordinates = geometry.getCoordinates();
126: StyleUtil.paint(geometry, g, viewport, filling, fillStroke,
127: fillColor, true, lineStroke, lineColor);
128: if (paintingHandles) {
129: //paintHandles(g, coordinates, handleStroke, handleFillColor, handleLineColor, panel.getViewport());
130: // LDB: the above method is very slow. The following code is aproximately equivalent
131: // although it draws a different style of handle (overlapping vs. hollow)
132: Rectangle2D viewRectangle = viewport
133: .toViewRectangle(viewport
134: .getEnvelopeInModelCoordinates());
135: Coordinate[] viewCoordinates = viewport
136: .getJava2DConverter().toViewCoordinates(
137: modelCoordinates);
138: Rectangle2D.Double handle = new Rectangle2D.Double(0, 0,
139: HANDLE_WIDTH, HANDLE_WIDTH);
140: for (int i = 0; i < viewCoordinates.length; i++) {
141: Coordinate p = viewCoordinates[i];
142: double x = p.x;
143: double y = p.y;
144: if (!viewRectangle.contains(x, y)) { //<<JOKE:handle with care>>
145: //Otherwise get "sun.dc.pr.PRException: endPath: bad path" exception [Jon Aquino 10/22/2003]
146: continue;
147: }
148: handle.x = x - (HANDLE_WIDTH / 2);
149: handle.y = y - (HANDLE_WIDTH / 2);
150: g.setStroke(handleStroke);
151: g.setColor(handleFillColor);
152: g.fill(handle);
153: g.setColor(handleLineColor);
154: g.draw(handle);
155: }
156: }
157: }
158:
159: protected Collection styles() {
160: return Collections.singleton(this );
161: }
162:
163: protected Map layerToFeaturesMap() {
164: featureToSelectedItemsMap = new CollectionMap();
165: HashMap layerToFeaturesMap = new HashMap();
166: for (Iterator i = panel.getLayerManager().iterator(); i
167: .hasNext();) {
168: Layer layer = (Layer) i.next();
169: Map featureToSelectedItemsMapForLayer = featureToSelectedItemsMap(layer);
170: featureToSelectedItemsMap
171: .putAll(featureToSelectedItemsMapForLayer);
172: layerToFeaturesMap.put(layer,
173: featureToSelectedItemsMapForLayer.keySet());
174: }
175: return layerToFeaturesMap;
176: }
177:
178: protected abstract CollectionMap featureToSelectedItemsMap(
179: Layer layer);
180:
181: private static Shape handle(Point2D point) {
182: Rectangle2D.Double handle = new Rectangle2D.Double(0.0, 0.0,
183: HANDLE_WIDTH, HANDLE_WIDTH);
184: handle.x = point.getX() - (HANDLE_WIDTH / 2);
185: handle.y = point.getY() - (HANDLE_WIDTH / 2);
186:
187: return handle;
188: }
189:
190: public static void paintHandles(Graphics2D g,
191: Coordinate[] coordinates, Stroke stroke, Color fillColor,
192: Color lineColor, Viewport viewport)
193: throws NoninvertibleTransformException {
194: g.setStroke(stroke);
195: g.setColor(fillColor);
196:
197: for (int i = 0; i < coordinates.length; i++) {
198: if (!viewport.getEnvelopeInModelCoordinates().contains(
199: coordinates[i])) {
200: //Otherwise get "sun.dc.pr.PRException: endPath: bad path" exception [Jon Aquino 10/22/2003]
201: continue;
202: }
203: g.fill(handle(viewport.toViewPoint(new Point2D.Double(
204: coordinates[i].x, coordinates[i].y))));
205: }
206:
207: g.setColor(lineColor);
208:
209: for (int i = 0; i < coordinates.length; i++) {
210: if (!viewport.getEnvelopeInModelCoordinates().contains(
211: coordinates[i])) {
212: //Otherwise get "sun.dc.pr.PRException: endPath: bad path" exception [Jon Aquino 10/22/2003]
213: continue;
214: }
215: g.draw(handle(viewport.toViewPoint(new Point2D.Double(
216: coordinates[i].x, coordinates[i].y))));
217: }
218: }
219:
220: protected boolean useImageCaching(Map layerToFeaturesMap) {
221: return true;
222: }
223:
224: }
|