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.behaviour;
016:
017: import java.awt.Shape;
018: import java.awt.geom.AffineTransform;
019: import java.awt.geom.GeneralPath;
020: import java.awt.geom.PathIterator;
021:
022: import net.refractions.udig.project.command.UndoableComposite;
023: import net.refractions.udig.project.command.UndoableMapCommand;
024: import net.refractions.udig.project.ui.internal.commands.draw.DrawShapeCommand;
025: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
026: import net.refractions.udig.tools.edit.EditPlugin;
027: import net.refractions.udig.tools.edit.EditState;
028: import net.refractions.udig.tools.edit.EditToolHandler;
029: import net.refractions.udig.tools.edit.EventBehaviour;
030: import net.refractions.udig.tools.edit.EventType;
031: import net.refractions.udig.tools.edit.LockingBehaviour;
032: import net.refractions.udig.tools.edit.MouseTracker;
033: import net.refractions.udig.tools.edit.commands.CreateEditGeomCommand;
034: import net.refractions.udig.tools.edit.commands.RemoveEditGeomCommand;
035: import net.refractions.udig.tools.edit.commands.SetCurrentGeomCommand;
036: import net.refractions.udig.tools.edit.commands.SetEditStateCommand;
037: import net.refractions.udig.tools.edit.preferences.PreferenceUtil;
038: import net.refractions.udig.tools.edit.support.EditBlackboard;
039: import net.refractions.udig.tools.edit.support.EditUtils;
040: import net.refractions.udig.tools.edit.support.ShapeType;
041:
042: import com.vividsolutions.jts.geom.LineString;
043: import com.vividsolutions.jts.geom.LinearRing;
044: import com.vividsolutions.jts.geom.MultiLineString;
045:
046: /**
047: * <p>Requirements:
048: * <ul>
049: * <li>Mouse Dragged</li>
050: * <li>CurrentState == NONE</li>
051: * <li>Mouse button 1 down</li>
052: * </ul>
053: * </p>
054: * <p>Action:
055: * <ul>
056: * <li>draws a shape as the mouse is dragged</li>
057: * <li>creates a feature on the current layer when mouse is released</li>
058: * </ul>
059: * </p>
060: * @author jones
061: * @since 1.1.0
062: */
063: public class ShapeCreationBehaviour implements EventBehaviour,
064: LockingBehaviour {
065:
066: /**
067: * creates a shape upon request.
068: *
069: * @author jones
070: * @since 1.1.0
071: */
072: public static abstract class ShapeFactory {
073: /**
074: * Creates a GeneralPath with the top left corner at 0,0 and
075: * a total width and height as indicated
076: *
077: * @param width width of path created
078: * @param height height of path created
079: * @return a GeneralPath with the top left corner at 0,0 and
080: * a total width and height as indicated
081: */
082: public abstract GeneralPath create(int width, int height);
083: }
084:
085: private ShapeFactory factory;
086: private GeneralPath path;
087: private DrawShapeCommand drawCommand;
088:
089: /**
090: * @param factory
091: */
092: public ShapeCreationBehaviour(ShapeFactory factory) {
093: this .factory = factory;
094: }
095:
096: public boolean isValid(EditToolHandler handler, MapMouseEvent e,
097: EventType eventType) {
098: if (handler.isLocked() && handler.isLockOwner(this )
099: && eventType == EventType.DRAGGED)
100: return true;
101:
102: boolean legalState = handler.getCurrentState() == EditState.NONE;
103:
104: return !e.modifiersDown() && legalState
105: && e.buttons == MapMouseEvent.BUTTON1
106: && eventType == EventType.DRAGGED;
107: }
108:
109: public UndoableMapCommand getCommand(EditToolHandler handler,
110: MapMouseEvent e, EventType eventType) {
111: if (path == null) {
112: path = factory.create(1, 1);
113: handler.getBehaviours().add(new Creator());
114: handler.lock(this );
115: }
116: MouseTracker tracker = handler.getMouseTracker();
117: int translationX = Math.min(tracker.getDragStarted().getX(),
118: e.x);
119: int translationY = Math.min(tracker.getDragStarted().getY(),
120: e.y);
121: int scaleX = Math.abs(tracker.getDragStarted().getX() - e.x);
122: int scaleY = Math.abs(tracker.getDragStarted().getY() - e.y);
123:
124: AffineTransform transform = AffineTransform
125: .getTranslateInstance(translationX, translationY);
126: transform.scale(scaleX, scaleY);
127: Shape transformedShape = path.createTransformedShape(transform);
128: if (drawCommand == null) {
129: drawCommand = new DrawShapeCommand();
130: drawCommand.setPaint(PreferenceUtil.instance()
131: .getDrawGeomsLine());
132: handler.getContext().sendSyncCommand(drawCommand);
133: }
134: drawCommand.setShape(transformedShape);
135: handler.repaint();
136:
137: return null;
138: }
139:
140: public void handleError(EditToolHandler handler, Throwable error,
141: UndoableMapCommand command) {
142: EditPlugin.log("", error); //$NON-NLS-1$
143: }
144:
145: public Object getKey(EditToolHandler handler) {
146: return this ;
147: }
148:
149: private class Creator implements LockingBehaviour {
150:
151: public Object getKey(EditToolHandler handler) {
152: return ShapeCreationBehaviour.this ;
153: }
154:
155: public boolean isValid(EditToolHandler handler,
156: MapMouseEvent e, EventType eventType) {
157: return handler.isLockOwner(this )
158: && eventType == EventType.RELEASED
159: && e.button == MapMouseEvent.BUTTON1;
160: }
161:
162: public UndoableMapCommand getCommand(EditToolHandler handler,
163: MapMouseEvent e, EventType eventType) {
164: try {
165: PathIterator iter = drawCommand.getShape()
166: .getPathIterator(
167: AffineTransform.getTranslateInstance(0,
168: 0), 1.0);
169: UndoableComposite commands = new UndoableComposite();
170: commands.getCommands().add(
171: handler.getContext().getEditFactory()
172: .createNullEditFeatureCommand());
173: EditBlackboard bb = handler.getEditBlackboard(handler
174: .getEditLayer());
175: commands.getCommands().add(
176: new RemoveEditGeomCommand(handler, bb
177: .getGeoms()));
178: ShapeType shapeType = determineLayerType(handler);
179:
180: CreateEditGeomCommand createEditGeomCommand = new CreateEditGeomCommand(
181: bb, "newShape", shapeType); //$NON-NLS-1$
182: commands.getCommands().add(createEditGeomCommand);
183: commands.getCommands().add(
184: EditUtils.instance.appendPathToShape(iter,
185: shapeType, handler, bb,
186: createEditGeomCommand
187: .getShapeProvider()));
188: commands.getCommands().add(
189: new SetCurrentGeomCommand(handler,
190: createEditGeomCommand
191: .getShapeProvider()));
192: commands.getCommands().add(
193: handler.getCommand(handler
194: .getAcceptBehaviours()));
195:
196: commands.getFinalizerCommands()
197: .add(
198: new SetEditStateCommand(handler,
199: EditState.NONE));
200: return commands;
201: } finally {
202: drawCommand.setValid(false);
203: drawCommand = null;
204: path = null;
205: handler.unlock(this );
206: }
207: }
208:
209: private ShapeType determineLayerType(EditToolHandler handler) {
210: Class type = handler.getEditLayer().getSchema()
211: .getDefaultGeometry().getType();
212:
213: if (LineString.class.isAssignableFrom(type)
214: || LinearRing.class.isAssignableFrom(type)
215: || MultiLineString.class.isAssignableFrom(type))
216: return ShapeType.LINE;
217:
218: return ShapeType.POLYGON;
219: }
220:
221: public void handleError(EditToolHandler handler,
222: Throwable error, UndoableMapCommand command) {
223: EditPlugin.log("", error); //$NON-NLS-1$
224: }
225:
226: }
227:
228: }
|