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 net.refractions.udig.core.IProvider;
018: import net.refractions.udig.project.ILayer;
019: import net.refractions.udig.project.command.UndoableMapCommand;
020: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
021: import net.refractions.udig.tools.edit.EditPlugin;
022: import net.refractions.udig.tools.edit.EditToolHandler;
023: import net.refractions.udig.tools.edit.EventBehaviour;
024: import net.refractions.udig.tools.edit.EventType;
025: import net.refractions.udig.tools.edit.preferences.PreferenceUtil;
026: import net.refractions.udig.tools.edit.support.ClosestEdge;
027: import net.refractions.udig.tools.edit.support.EditGeom;
028: import net.refractions.udig.tools.edit.support.Point;
029: import net.refractions.udig.tools.edit.support.PrimitiveShape;
030: import net.refractions.udig.ui.PlatformGIS;
031:
032: import org.eclipse.swt.graphics.Cursor;
033: import org.eclipse.swt.widgets.Display;
034: import org.eclipse.ui.IActionBars2;
035: import org.eclipse.ui.PlatformUI;
036:
037: import com.vividsolutions.jts.geom.MultiPolygon;
038: import com.vividsolutions.jts.geom.Polygon;
039:
040: /**
041: * Sets the cursor to indicate what action can be done.
042: *
043: * Also adds tips to the status bar.
044: *
045: * @author Jesse
046: * @since 1.1.0
047: */
048: public class CursorControlBehaviour implements EventBehaviour {
049:
050: private IProvider<String> defaultMessage;
051: private IProvider<Cursor> overVertexCursor;
052: private IProvider<Cursor> overEdgeCursor;
053: private IProvider<String> overEdgeMessage;
054: private IProvider<String> overVertexMessage;
055:
056: /**
057: * new instance
058: * @param defaultMessage the message display when not over a vertex or an edge.
059: * @param overVertexCursor a provider that provides the cursor to show when over a vertex. This class
060: * <em>WILL NOT</em> dispose of the cursor.
061: * @param overVertexMessage generates the message to display when over a vertex
062: * @param overEdgeCursor a provider that provides the cursor to show when over an edge. This class
063: * <em>WILL NOT</em> dispose of the cursor.
064: * @param overEdgeMessage generates the message to display when over an edge
065:
066: */
067: public CursorControlBehaviour(EditToolHandler handler,
068: IProvider<String> defaultMessage,
069: IProvider<Cursor> overVertexCursor,
070: IProvider<String> overVertexMessage,
071: IProvider<Cursor> overEdgeCursor,
072: IProvider<String> overEdgeMessage) {
073: this .defaultMessage = defaultMessage;
074: if (overVertexCursor == null)
075: this .overVertexCursor = new DefaultCursorProvider(handler);
076: else
077: this .overVertexCursor = overVertexCursor;
078: if (overEdgeCursor == null)
079: this .overEdgeCursor = new DefaultCursorProvider(handler);
080: else
081: this .overEdgeCursor = overEdgeCursor;
082: if (overVertexMessage == null)
083: this .overVertexMessage = new NullStringProvider();
084: else
085: this .overVertexMessage = overVertexMessage;
086: if (overEdgeMessage == null)
087: this .overEdgeMessage = new NullStringProvider();
088: else
089: this .overEdgeMessage = overEdgeMessage;
090: }
091:
092: public boolean isValid(EditToolHandler handler, MapMouseEvent e,
093: EventType eventType) {
094: boolean isHover = eventType == EventType.HOVERED;
095: boolean isMove = eventType == EventType.MOVED;
096: return isHover || isMove;
097: }
098:
099: public UndoableMapCommand getCommand(EditToolHandler handler,
100: MapMouseEvent e, EventType eventType) {
101: if (overVertex(handler, e)) {
102: setCursorAndMessage(overVertexCursor.get(),
103: overVertexMessage.get(), handler);
104: } else if (eventType == EventType.HOVERED && onEdge(handler, e)) {
105: setCursorAndMessage(overEdgeCursor.get(), overEdgeMessage
106: .get(), handler);
107: } else
108: setCursorAndMessage(handler.editCursor, defaultMessage
109: .get(), handler);
110:
111: return null;
112: }
113:
114: private boolean onEdge(EditToolHandler handler, MapMouseEvent e) {
115: Point point = Point.valueOf(e.x, e.y);
116: EditGeom geom = handler.getCurrentGeom();
117: if (geom == null)
118: return false;
119:
120: ILayer selectedLayer = handler.getEditLayer();
121: Class type = selectedLayer.getSchema().getDefaultGeometry()
122: .getType();
123: boolean polygonLayer = Polygon.class.isAssignableFrom(type)
124: || MultiPolygon.class.isAssignableFrom(type);
125:
126: ClosestEdge closestEdge = geom.getClosestEdge(point,
127: polygonLayer);
128:
129: return closestEdge != null
130: && closestEdge.getDistanceToEdge() < PreferenceUtil
131: .instance().getVertexRadius();
132: }
133:
134: private boolean overVertex(EditToolHandler handler, MapMouseEvent e) {
135: if (handler.getCurrentShape() == null)
136: return false;
137: int radius = PreferenceUtil.instance().getVertexRadius();
138: Point point = Point.valueOf(e.x, e.y);
139: return handler.getCurrentGeom().overVertex(point, radius) != null;
140: }
141:
142: private void setCursorAndMessage(final Cursor cursor,
143: final String string, final EditToolHandler handler) {
144: Runnable runnable = new Runnable() {
145: public void run() {
146: if (PlatformUI.getWorkbench().isClosing())
147: return;
148: IActionBars2 bars = handler.getContext()
149: .getActionBars();
150: if (bars != null) {
151: bars.getStatusLineManager().setErrorMessage(null);
152: bars.getStatusLineManager().setMessage(string);
153: }
154: handler.getContext().getViewportPane()
155: .setCursor(cursor);
156:
157: }
158: };
159: if (Display.getCurrent() != null)
160: runnable.run();
161: else
162: Display.getDefault().asyncExec(runnable);
163: }
164:
165: public void handleError(EditToolHandler handler, Throwable error,
166: UndoableMapCommand command) {
167: EditPlugin.log("", error); //$NON-NLS-1$
168: }
169:
170: public static class SystemCursorProvider implements
171: IProvider<Cursor> {
172: private int id;
173:
174: /**
175: * new instance
176: * @param swtCursorID the id from SWT that indicates the cursor to create.
177: */
178: public SystemCursorProvider(int swtCursorID) {
179: this .id = swtCursorID;
180: }
181:
182: public Cursor get() {
183: final Cursor[] cursor = new Cursor[1];
184: PlatformGIS.syncInDisplayThread(new Runnable() {
185: public void run() {
186: cursor[0] = Display.getDefault()
187: .getSystemCursor(id);
188: }
189: });
190: return cursor[0];
191: }
192:
193: }
194:
195: public static class DefaultCursorProvider implements
196: IProvider<Cursor> {
197:
198: private EditToolHandler handler;
199:
200: public DefaultCursorProvider(EditToolHandler handler) {
201: this .handler = handler;
202: }
203:
204: public Cursor get() {
205: return handler.editCursor;
206: }
207:
208: }
209:
210: public static class NullStringProvider implements IProvider<String> {
211:
212: public String get() {
213: return null;
214: }
215:
216: }
217: }
|