001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.tools.edit.support;
016:
017: import java.awt.Rectangle;
018: import java.awt.Shape;
019: import java.awt.geom.GeneralPath;
020: import java.awt.geom.PathIterator;
021: import java.util.Iterator;
022: import java.util.NoSuchElementException;
023:
024: import net.refractions.udig.ui.graphics.SWTGraphics;
025:
026: import org.eclipse.swt.graphics.Device;
027: import org.eclipse.swt.graphics.Path;
028:
029: /**
030: * An abstract class for drawing {@link net.refractions.udig.tools.edit.support.EditGeom} objects
031: *
032: * @author jones
033: * @since 1.1.0
034: */
035: public abstract class AbstractPathIterator implements PathIterator {
036:
037: protected final EditGeom geom;
038: private Iterator<PrimitiveShape> shapes;
039: protected Iterator<Point> points;
040: protected Point currentPoint, nextPoint;
041:
042: protected PrimitiveShape currentShape;
043:
044: protected AbstractPathIterator(EditGeom shape) {
045: this .geom = shape;
046: }
047:
048: /**
049: * Returns a shape that can be draw.
050: * <p>It is recommended to call getShape() every time a draw is needed because the shape does not update if
051: * the EditGeom is updated between draws. getShape is guaranteed to get a shape that is representative of
052: * the current state of geom.</p>
053: *
054: * @return
055: */
056: public Shape toShape() {
057: prepareToPath();
058:
059: if (geom.getShell().getNumPoints() == 1) {
060: Shape createPoint = createPoint();
061: if (createPoint != null)
062: return createPoint;
063: }
064: GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
065:
066: path.append(this , false);
067:
068: return path;
069: }
070:
071: public Path toPath(Device device) {
072: prepareToPath();
073:
074: if (geom.getShell().getNumPoints() == 1) {
075: Path createPoint = createPointPath(device);
076: if (createPoint != null)
077: return createPoint;
078: }
079:
080: return SWTGraphics.createPath(this , device);
081: }
082:
083: private void prepareToPath() {
084: currentPoint = null;
085: points = null;
086: nextPoint = null;
087: currentShape = null;
088: shapes = geom.iterator();
089: }
090:
091: /**
092: * Called if there is only a single point in the geom. Default behaviour
093: * is to return a small square. If null is returned then this PathIterator
094: * will be used to create a geometry.
095: *
096: * @return a shape to draw or null if PathIterator should be used to create a shape.
097: */
098: protected Shape createPoint() {
099: Point point = geom.getShell().getPoint(0);
100: return new Rectangle(point.getX() - 2, point.getY() - 2, 4, 4);
101: }
102:
103: protected Path createPointPath(Device device) {
104: Point point = geom.getShell().getPoint(0);
105: Path path = new Path(device);
106: path.addRectangle(point.getX() - 2, point.getY() - 2, 4, 4);
107: return path;
108: }
109:
110: public int getWindingRule() {
111: return WIND_EVEN_ODD;
112: }
113:
114: public boolean isDone() {
115: return isDoneInternal();
116: }
117:
118: private boolean isDoneInternal() {
119: if (nextPoint != null)
120: return false;
121:
122: if (points != null && points.hasNext()) {
123: nextPoint = points.next();
124: return false;
125: }
126:
127: // points is null or is done so get next shape
128: while (shapes.hasNext()) {
129: currentShape = shapes.next();
130:
131: points = currentShape.iterator();
132:
133: if (points.hasNext()) {
134: nextPoint = points.next();
135: break;
136: }
137: }
138:
139: return nextPoint == null;
140: }
141:
142: public void next() {
143: try {
144: nextPoint = null;
145: if (points.hasNext()) {
146: if (isDone()) {
147: return;
148: }
149: currentPoint = nextPoint;
150: } else {
151: isDone();
152: currentPoint = null;
153: }
154: } catch (NoSuchElementException e) {
155: throw new NoSuchElementException(
156: "Shape is done, make sure to check isDone before calling next()"); //$NON-NLS-1$
157: }
158:
159: }
160:
161: public int currentSegment(float[] coords) {
162:
163: int result = SEG_LINETO;
164:
165: if (currentPoint == null) {
166: coords[0] = nextPoint.getX();
167: coords[1] = nextPoint.getY();
168: return SEG_MOVETO;
169: }
170:
171: coords[0] = currentPoint.getX();
172: coords[1] = currentPoint.getY();
173:
174: return result;
175:
176: }
177:
178: public int currentSegment(double[] coords) {
179: float[] floats = new float[coords.length];
180: int result = currentSegment(floats);
181: System.arraycopy(floats, 0, coords, 0, coords.length);
182: return result;
183: }
184:
185: }
|