001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.tools.internal;
010:
011: import java.awt.Point;
012:
013: import net.refractions.udig.project.command.Command;
014: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
015: import net.refractions.udig.project.ui.tool.AbstractTool;
016: import net.refractions.udig.project.ui.tool.IToolContext;
017: import net.refractions.udig.ui.PlatformGIS;
018:
019: import org.eclipse.core.runtime.Platform;
020: import org.eclipse.jface.action.ContributionItem;
021: import org.eclipse.jface.action.IStatusLineManager;
022: import org.eclipse.jface.action.StatusLineLayoutData;
023: import org.eclipse.jface.action.StatusLineManager;
024: import org.eclipse.swt.SWT;
025: import org.eclipse.swt.events.FocusEvent;
026: import org.eclipse.swt.events.FocusListener;
027: import org.eclipse.swt.events.KeyEvent;
028: import org.eclipse.swt.events.KeyListener;
029: import org.eclipse.swt.graphics.Font;
030: import org.eclipse.swt.graphics.FontData;
031: import org.eclipse.swt.widgets.Composite;
032: import org.eclipse.swt.widgets.Control;
033: import org.eclipse.swt.widgets.Display;
034: import org.eclipse.swt.widgets.Label;
035: import org.eclipse.swt.widgets.Text;
036: import org.geotools.geometry.jts.JTS;
037: import org.geotools.referencing.CRS;
038: import org.geotools.referencing.crs.DefaultGeographicCRS;
039: import org.opengis.referencing.crs.CoordinateReferenceSystem;
040:
041: import com.vividsolutions.jts.geom.Coordinate;
042:
043: /**
044: * A CursorPosition tool displays the current Cursor position in map coordinates
045: * on the Statusbar
046: *
047: * @author Jesse Eichar
048: * @version $Revision: 1.9 $
049: */
050: public class CursorPosition extends AbstractTool {
051: private static final String ID = "CURSOR_POSITION_LABEL"; //$NON-NLS-1$
052:
053: /**
054: * Creates an new instance of CursorPosition
055: */
056: public CursorPosition() {
057: super (MOTION);
058: }
059:
060: @Override
061: public void setContext(IToolContext tools) {
062: super .setContext(tools);
063: Display d = Display.getDefault();
064:
065: PlatformGIS.syncInDisplayThread(new Runnable() {
066: /**
067: * @see java.lang.Runnable#run()
068: */
069: public void run() {
070: getLabel();
071: }
072: });
073: }
074:
075: public void mouseMoved(final MapMouseEvent e) {
076: final LineItem label = getLabel();
077: if (label == null)
078: return;
079: Point screen = e.getPoint();
080: Coordinate world = getContext()
081: .pixelToWorld(screen.x, screen.y);
082: if (world == null)
083: return;
084: label.setPosition(world);
085: }
086:
087: LineItem getLabel() {
088: if (getContext().getActionBars() == null)
089: return null;
090: IStatusLineManager bar = getContext().getActionBars()
091: .getStatusLineManager();
092: if (bar == null) {
093: return null;
094: }
095: LineItem item = (LineItem) bar.find(ID);
096: if (item == null) {
097: item = new LineItem(ID);
098: bar.appendToGroup(StatusLineManager.END_GROUP, item);
099: bar.update(true);
100: }
101:
102: return item;
103: }
104:
105: public void mouseDragged(MapMouseEvent e) {
106: mouseMoved(e);
107: }
108:
109: private class LineItem extends ContributionItem implements
110: KeyListener, FocusListener {
111: private static final double ACCURACY = 0.0000001;
112:
113: private Text textArea;
114:
115: Coordinate position;
116:
117: LineItem(String id) {
118: super (id);
119: }
120:
121: /**
122: * @see org.eclipse.jface.action.IContributionItem#isDynamic()
123: */
124: public boolean isDynamic() {
125: return true;
126: }
127:
128: public void setPosition(Coordinate coord) {
129: if (position != null
130: && Math.abs(position.x - coord.x) < ACCURACY
131: && Math.abs(position.y - coord.y) < ACCURACY) {
132: return;
133: }
134: position = coord;
135:
136: if (textArea != null && !textArea.isDisposed()) {
137: textArea.setText(getString(coord));
138: }
139: }
140:
141: private String getString(Coordinate coord) {
142: String value = getString(coord.x)
143: + ", " + getString(coord.y); //$NON-NLS-1$
144: return value;
145: }
146:
147: private String getString(double value) {
148: if (Double.isNaN(value)) {
149: return Messages.CursorPosition_not_a_number;
150: }
151:
152: if (Double.isInfinite(value)) {
153: return Messages.CursorPosition_infinity;
154: }
155:
156: String string = String.valueOf(value);
157: string += "00"; //$NON-NLS-1$
158:
159: // calculate number of digits to display based on zoom level
160: Coordinate coordFactor = getContext().getPixelSize();
161: double inverse = (double) 1 / coordFactor.x;
162: String strFactor = String.valueOf(inverse);
163: int factor = strFactor.lastIndexOf('.');
164:
165: int end = Math.max(1, Math.min(string.lastIndexOf('.')
166: + factor, string.length() - 1));
167: string = string.substring(0, end);
168:
169: if (string.endsWith(".")) { //$NON-NLS-1$
170: string = string.substring(0, string.length() - 1);
171: }
172:
173: return string;
174: }
175:
176: @Override
177: public void fill(Composite parent) {
178: Label separator = new Label(parent, SWT.SEPARATOR);
179: StatusLineLayoutData data = new StatusLineLayoutData();
180: data.widthHint = 1;
181: data.heightHint = 15;
182: separator.setLayoutData(data);
183: textArea = new Text(parent, SWT.BORDER | SWT.CENTER);
184: textArea.addKeyListener(this );
185: textArea.addFocusListener(this );
186: if (position != null)
187: textArea.setText(getString(position));
188: textArea.setToolTipText(Messages.CursorPosition_tooltip);
189: setFont(textArea);
190: data = new StatusLineLayoutData();
191: data.widthHint = 150;
192: data.heightHint = 15;
193: textArea.setLayoutData(data);
194: }
195:
196: void setFont(Control textArea2) {
197: Display display = textArea2.getDisplay();
198: FontData[] data = display.getFontList("courier", true); //$NON-NLS-1$
199: if (data.length < 1) {
200: data = textArea2.getFont().getFontData();
201: }
202: for (int i = 0; i < data.length; i++) {
203: if (Platform.OS_MACOSX == Platform.getOS())
204: data[i].setHeight(12);
205: else
206: data[i].setHeight(10);
207: }
208: textArea2.setFont(new Font(textArea2.getDisplay(), data));
209: }
210:
211: public void keyPressed(KeyEvent e) {
212: // do nothing
213: }
214:
215: Coordinate current;
216:
217: public void keyReleased(KeyEvent e) {
218: if (e.character == SWT.Selection) {
219: go();
220: } else if (e.character == SWT.ESC) {
221: textArea.setText(getString(position));
222: }
223:
224: }
225:
226: private void go() {
227: Coordinate newpos = parse(textArea.getText(), getContext()
228: .getCRS());
229: if (Math.abs(newpos.x - position.x) > ACCURACY
230: || Math.abs(newpos.y - position.y) > ACCURACY) {
231: setPosition(newpos);
232: Command c = getContext().getNavigationFactory()
233: .createSetViewportCenterCommand(newpos);
234: getContext().sendASyncCommand(c);
235: }
236: }
237:
238: public void focusGained(FocusEvent e) {
239: int end = textArea.getText().length();
240: textArea.setSelection(0, end);
241: }
242:
243: public void focusLost(FocusEvent e) {
244: // do nada
245: }
246:
247: }
248:
249: public static Coordinate parse(String value,
250: CoordinateReferenceSystem crs) {
251: String modifiedvalue = value.trim();
252: boolean latlong = false;
253: String upperCase = modifiedvalue.toUpperCase();
254: String tmp = modifiedvalue;
255: modifiedvalue = stripCode(modifiedvalue, upperCase);
256: if (tmp.length() != modifiedvalue.length())
257: latlong = true;
258: String[] components = modifiedvalue.split(","); //$NON-NLS-1$
259: if (components.length == 1) {
260: components = modifiedvalue.split(" "); //$NON-NLS-1$
261: }
262:
263: if (components.length == 1)
264: return null;
265: if (components[0].startsWith("(") || components[0].startsWith("[")) { //$NON-NLS-1$ //$NON-NLS-2$
266: components[0] = components[0].substring(1);
267: }
268: if (components[1].endsWith(")") || components[1].endsWith("]")) { //$NON-NLS-1$ //$NON-NLS-2$
269: components[1] = components[1].substring(0, components[1]
270: .length() - 1);
271: }
272: try {
273: double arg1 = Double.parseDouble(components[0]);
274: double arg0 = Double.parseDouble(components[1]);
275: Coordinate coord = new Coordinate(arg1, arg0);
276: if (latlong && crs != null) {
277: try {
278: JTS.transform(coord, coord, CRS.transform(
279: DefaultGeographicCRS.WGS84, crs, true));
280: } catch (Exception e) {
281: ToolsPlugin.log(
282: Messages.CursorPosition_transformError, e);
283: }
284: }
285: return coord;
286: } catch (NumberFormatException e) {
287: return null;
288: }
289: }
290:
291: private static String stripCode(String modifiedvalue,
292: String upperCase) {
293: String code = "LL"; //$NON-NLS-1$
294: if (upperCase.endsWith(code)) {
295: return modifiedvalue.substring(0, modifiedvalue.length()
296: - code.length());
297: }
298: code = "L L"; //$NON-NLS-1$
299: if (upperCase.endsWith(code)) {
300: return modifiedvalue.substring(0, modifiedvalue.length()
301: - code.length());
302: }
303: code = "LATLONG"; //$NON-NLS-1$
304: if (upperCase.endsWith(code)) {
305: return modifiedvalue.substring(0, modifiedvalue.length()
306: - code.length());
307: }
308: code = "LAT LONG"; //$NON-NLS-1$
309: if (upperCase.endsWith(code)) {
310: return modifiedvalue.substring(0, modifiedvalue.length()
311: - code.length());
312: }
313: code = "LAT LON"; //$NON-NLS-1$
314: if (upperCase.endsWith(code)) {
315: return modifiedvalue.substring(0, modifiedvalue.length()
316: - code.length());
317: }
318: return modifiedvalue;
319: }
320:
321: }
|