svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / project / documents / view / toolListeners / StatusBarListener.java @ 45732
History | View | Annotate | Download (13.3 KB)
1 | 40558 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40558 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | 40435 | jjdelcerro | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | 40558 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40435 | jjdelcerro | * of the License, or (at your option) any later version.
|
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | 40558 | jjdelcerro | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 40435 | jjdelcerro | *
|
21 | 40558 | jjdelcerro | * For any additional information, do not hesitate to contact us
|
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40435 | jjdelcerro | */
|
24 | package org.gvsig.app.project.documents.view.toolListeners; |
||
25 | |||
26 | import java.awt.Image; |
||
27 | import java.awt.geom.Point2D; |
||
28 | import java.text.NumberFormat; |
||
29 | |||
30 | import org.cresques.cts.IProjection; |
||
31 | 41000 | jldominguez | import org.slf4j.Logger; |
32 | import org.slf4j.LoggerFactory; |
||
33 | |||
34 | 40435 | jjdelcerro | import org.gvsig.andami.PluginServices; |
35 | import org.gvsig.andami.ui.mdiFrame.MainFrame; |
||
36 | 45732 | jjdelcerro | import org.gvsig.fmap.geom.GeometryUtils; |
37 | 40435 | jjdelcerro | import org.gvsig.fmap.mapcontext.MapContext; |
38 | import org.gvsig.fmap.mapcontrol.MapControl; |
||
39 | import org.gvsig.fmap.mapcontrol.tools.BehaviorException; |
||
40 | import org.gvsig.fmap.mapcontrol.tools.Events.PointEvent; |
||
41 | import org.gvsig.fmap.mapcontrol.tools.Listeners.PointListener; |
||
42 | |||
43 | |||
44 | |||
45 | /**
|
||
46 | * <p>Listener that displays at the status bar of the application's main frame, the value of the point coordinates of the mouse's
|
||
47 | * cursor on the associated <code>MapControl</code>, just as is received a <code>PointEvent</code> event.</p>
|
||
48 | *
|
||
49 | * <p>Calculates the coordinates equivalent to the point according this rules:
|
||
50 | * <ul>
|
||
51 | * <li>uses <i><code>formatDegrees(p.get{X or Y}()</code></i> if the associated <code>MapControl</code> object isn't projected.</li>
|
||
52 | * <li>uses <i><code>formatDegrees({MapControl's projection}.toGeo(p.get{X or Y}())</code></i> if the associated
|
||
53 | * <code>MapControl</code> object is projected and its <code>ViewPort</code>'s distance units are in degrees.</li>
|
||
54 | * <li>uses <i><code>{NumberFormat according to {@link #setFractionDigits(Point2D) #setFractionDigits(Point2D)}}.format((p.get{X or Y}()/MapContext.CHANGEM[mapControl.getViewPort().getDistanceUnits()])*MapContext.CHANGEM[mapControl.getViewPort().getMapUnits()])</code></i>
|
||
55 | * otherwise.</li>
|
||
56 | * </ul>
|
||
57 | * </p>
|
||
58 | *
|
||
59 | * <p>The <u>prefix</u> of the coordinate expressions will be:
|
||
60 | * <ul>
|
||
61 | * <li>Longitude "<i>Long =</i>" and latitude "<i>Lat =</i>", if the associated <i>MapControl</i> object isn't projected, or the current distance unit
|
||
62 | * of the <code>MapControl</code>'s view port is in degrees.</li>
|
||
63 | * <li>X "<i>X =</i>" and Y "<i>Y =</i>", otherwise.</li>
|
||
64 | * </ul>
|
||
65 | * </p>
|
||
66 | *
|
||
67 | * <p>And the <u>sufix</u> value:
|
||
68 | * <ul>
|
||
69 | * <li>If the associated <i>MapControl</i> object isn't projected, or the current distance unit
|
||
70 | * of the <code>MapControl</code>'s view port is in degrees(expected latitude or longitude), according this pattern:<br>
|
||
71 | * <code><b><i>S?G? M' S''</i></b></code>, having:<br>
|
||
72 | * <ul>
|
||
73 | * <li><i>S?</i> : optionally, if the value is negative, sets a "-" symbol.</li>
|
||
74 | * <li><i>G</i> : equivalent grades.</li>
|
||
75 | * <li><i>M</i> : equivalent minutes.</li>
|
||
76 | * <li><i>S</i> : equivalent seconds.</li>
|
||
77 | * </ul>
|
||
78 | * </li>
|
||
79 | * <li>Otherwise a decimal number according this rules:
|
||
80 | * <ul>
|
||
81 | * <li><i>8 decimals</i>, if is using any of the following geographic coordinate systems:
|
||
82 | * <ul>
|
||
83 | * <li><i>EPSG:4230 (known as <a href="http://en.wikipedia.org/wiki/ED50">ED50</a>)</i>.</li>
|
||
84 | * <li><i>EPSG:4326 (known as <a href="http://en.wikipedia.org/wiki/WGS84">WGS84</a>)</i>.</li>
|
||
85 | * </ul>
|
||
86 | * <li><i>2 decimals</i>, otherwise.</li>
|
||
87 | * </ul>
|
||
88 | * </li>
|
||
89 | * </ul>
|
||
90 | * </p>
|
||
91 | *
|
||
92 | * @author Vicente Caballero Navarro
|
||
93 | */
|
||
94 | public class StatusBarListener implements PointListener { |
||
95 | 41000 | jldominguez | |
96 | 45732 | jjdelcerro | private static Logger logger = LoggerFactory.getLogger(StatusBarListener.class); |
97 | |||
98 | private static final String DEGRESS_FORMAT = "%-%d? %m' %.0s''"; |
||
99 | |||
100 | /**
|
||
101 | 40435 | jjdelcerro | * Reference to the <code>MapControl</code> object that uses.
|
102 | */
|
||
103 | private MapControl mapControl = null; |
||
104 | |||
105 | /**
|
||
106 | * Format of the coordinates. Is used to set the number of decimals.
|
||
107 | */
|
||
108 | private NumberFormat nf = null; |
||
109 | 41000 | jldominguez | |
110 | private static long lastLogTime = 0; |
||
111 | 40435 | jjdelcerro | |
112 | /**
|
||
113 | * <p>Creates a new <code>StatusBarListener</code> object.</p>
|
||
114 | *
|
||
115 | * @param mc the <code>MapControl</code> where will be applied the changes
|
||
116 | */
|
||
117 | public StatusBarListener(MapControl mc) {
|
||
118 | mapControl = mc; |
||
119 | nf = NumberFormat.getInstance();
|
||
120 | nf.setMaximumFractionDigits(2);
|
||
121 | } |
||
122 | |||
123 | /*
|
||
124 | * (non-Javadoc)
|
||
125 | * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getImageCursor()
|
||
126 | */
|
||
127 | public Image getImageCursor() { |
||
128 | return null; |
||
129 | } |
||
130 | |||
131 | /*
|
||
132 | * (non-Javadoc)
|
||
133 | * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
|
||
134 | */
|
||
135 | public boolean cancelDrawing() { |
||
136 | return false; |
||
137 | } |
||
138 | |||
139 | /*
|
||
140 | * 050211, jmorell: M?todo modificado para mejorar la manera de mostrar las
|
||
141 | * coordenadas geod?sicas en la barra de estado. Muestra Lat y Lon y aumenta
|
||
142 | * el n?mero de decimales para cuando trabajemos en coordenadas geod?sicas.
|
||
143 | *
|
||
144 | * (non-Javadoc)
|
||
145 | * @see com.iver.cit.gvsig.fmap.tools.Listeners.PointListener#point(com.iver.cit.gvsig.fmap.tools.Events.PointEvent)
|
||
146 | */
|
||
147 | public void point(PointEvent event) throws BehaviorException { |
||
148 | String[] axisText = new String[2]; |
||
149 | axisText[0] = "X = "; |
||
150 | axisText[1] = "Y = "; |
||
151 | Point2D p = mapControl.getMapContext().getViewPort().toMapPoint(event.getPoint());
|
||
152 | setFractionDigits(p); |
||
153 | axisText = setCoorDisplayText(axisText); |
||
154 | MainFrame mF = PluginServices.getMainFrame(); |
||
155 | |||
156 | if (mF != null){ |
||
157 | |||
158 | mF.getStatusBar().setMessage("units",
|
||
159 | PluginServices.getText(this, MapContext.getDistanceNames()[mapControl.getMapContext().getViewPort().getDistanceUnits()]));
|
||
160 | |||
161 | 43439 | jjdelcerro | // No se debe llamar a setControlValue desde aqu?, porque
|
162 | 40435 | jjdelcerro | // cambia la escala, y con ella el viewPort (adem?s, de
|
163 | // la vista que no es).
|
||
164 | // mF.getStatusBar().setControlValue("scale",String.valueOf(mapControl.getMapContext().getScaleView()));
|
||
165 | // Fin
|
||
166 | 43439 | jjdelcerro | IProjection proj = mapControl.getViewPort().getProjection(); |
167 | mF.getStatusBar().setMessage("projection",
|
||
168 | proj==null? "":proj.getAbrev() |
||
169 | ); |
||
170 | 40435 | jjdelcerro | |
171 | String[] coords=getCoords(p); |
||
172 | mF.getStatusBar().setMessage("x", axisText[0] + coords[0]); |
||
173 | mF.getStatusBar().setMessage("y", axisText[1] + coords[1]); |
||
174 | } |
||
175 | } |
||
176 | |||
177 | /**
|
||
178 | * <p>Sets the number of decimals of the coordinates that will be displayed, according the current projection
|
||
179 | * of the associated <code>MapControl</code>:
|
||
180 | * <ul>
|
||
181 | * <li><i>8 decimals</i>, if is using geographical coordinates:
|
||
182 | * <ul>
|
||
183 | * <li><i>EPSG:4230 (known as <a href="http://en.wikipedia.org/wiki/ED50">ED50</a>)</i>.</li>
|
||
184 | * <li><i>EPSG:4326 (known as <a href="http://en.wikipedia.org/wiki/WGS84">WGS84</a>)</i>.</li>
|
||
185 | * </ul>
|
||
186 | * <li><i>2 decimals</i>, otherwise.</li>
|
||
187 | * </ul>
|
||
188 | * </p>
|
||
189 | *
|
||
190 | * @param p unused parameter
|
||
191 | *
|
||
192 | * @version 050211
|
||
193 | * @author jmorell.
|
||
194 | */
|
||
195 | public void setFractionDigits(Point2D p) { |
||
196 | IProjection iProj = mapControl.getMapContext().getProjection(); |
||
197 | 43439 | jjdelcerro | if (iProj!=null && !iProj.isProjected()) { |
198 | 40435 | jjdelcerro | nf.setMaximumFractionDigits(8);
|
199 | } else {
|
||
200 | nf.setMaximumFractionDigits(2);
|
||
201 | } |
||
202 | } |
||
203 | |||
204 | /**
|
||
205 | * <p>Gets the name of the coordinates:
|
||
206 | * <ul>
|
||
207 | * <li><i>Longitude</i> and <i>Latitude</i>, if the associated <i>MapControl</i> object isn't projected, or the current distance unit
|
||
208 | * of the <code>MapControl</code>'s view port is in degrees.</li>
|
||
209 | * <li><i>X</i> and <i>Y</i>, otherwise.</li>
|
||
210 | * </ul>
|
||
211 | * </p>
|
||
212 | *
|
||
213 | * @param p array of at least two <code>String</code>, where text will be stored and returned
|
||
214 | *
|
||
215 | * @return text describing the coordinate value:
|
||
216 | * <ul>
|
||
217 | * <li>If isn't projected:
|
||
218 | * <ul>
|
||
219 | * <li><code>String[0]</code> : "Long = "</li>
|
||
220 | * <li><code>String[1]</code> : "Lat = "</li>
|
||
221 | * </ul>
|
||
222 | * </li>
|
||
223 | * <li>Otherwise:
|
||
224 | * <ul>
|
||
225 | * <li><code>String[0]</code> : "X = "</li>
|
||
226 | * <li><code>String[1]</code> : "Y = "</li>
|
||
227 | * </ul>
|
||
228 | * </li>
|
||
229 | * </ul>
|
||
230 | *
|
||
231 | * @version 050211
|
||
232 | * @author jmorell
|
||
233 | */
|
||
234 | public String[] setCoorDisplayText(String[] axisText) { |
||
235 | IProjection iProj = mapControl.getMapContext().getProjection(); |
||
236 | 43439 | jjdelcerro | if( iProj == null ) { |
237 | axisText[0] = ""; |
||
238 | axisText[1] = ""; |
||
239 | } else {
|
||
240 | if (!iProj.isProjected() || MapContext.getDistanceNames()[mapControl.getMapContext().getViewPort().getDistanceUnits()].equals("Grados")) { |
||
241 | axisText[0] = "Lon = "; |
||
242 | axisText[1] = "Lat = "; |
||
243 | } else {
|
||
244 | axisText[0] = "X = "; |
||
245 | axisText[1] = "Y = "; |
||
246 | } |
||
247 | } |
||
248 | 40435 | jjdelcerro | return axisText;
|
249 | } |
||
250 | |||
251 | 45732 | jjdelcerro | // /**
|
252 | // * <p>Converts a decimal value (expected latitude or longitude) in degrees, and formats it according this pattern:<br>
|
||
253 | // * <code><b><i>S?G? M' S''</i></b></code>, having:<br>
|
||
254 | // * <ul>
|
||
255 | // * <li><i>S?</i> : optionally, if the value is negative, sets a "-" symbol.</li>
|
||
256 | // * <li><i>G</i> : equivalent grades.</li>
|
||
257 | // * <li><i>M</i> : equivalent minutes.</li>
|
||
258 | // * <li><i>S</i> : equivalent seconds.</li>
|
||
259 | // * </ul>
|
||
260 | // * </p>
|
||
261 | // *
|
||
262 | // * @param d the latitude or longitude value to convert
|
||
263 | // *
|
||
264 | // * @return value formatted in degrees
|
||
265 | // */
|
||
266 | // private String formatDegrees(double d) {
|
||
267 | //// String signo = d<0 ? "-" : "";
|
||
268 | //// d = Math.abs(d);
|
||
269 | //// long grado = 0;
|
||
270 | //// double minuto = 0;
|
||
271 | //// double segundo = 0;
|
||
272 | ////
|
||
273 | //// grado = (long)(d);
|
||
274 | //// minuto = (d - grado) * 60;
|
||
275 | //// segundo = (minuto - (long) minuto)*60;
|
||
276 | ////// System.out.println("Grados: " + grado);
|
||
277 | ////// System.out.println("Minutos: " + minuto);
|
||
278 | ////// System.out.println("Segundos: " + segundo);
|
||
279 | //// return signo+grado+"? "+(long) minuto+"' "+(long)segundo+"''";
|
||
280 | // return GeometryUtils.formatCoordinate("%-%d? %m' %s''", d);
|
||
281 | // }
|
||
282 | 40435 | jjdelcerro | |
283 | /**
|
||
284 | * <p>Returns the coordinates equivalent to <code>p</code>:
|
||
285 | * <ul>
|
||
286 | * <li>Uses <i><code>formatDegrees(p.get{X or Y}()</code></i> if the associated <code>MapControl</code> object isn't projected.</li>
|
||
287 | * <li>Uses <i><code>formatDegrees({MapControl's projection}.toGeo(p.get{X or Y}())</code></i> if the associated
|
||
288 | * <code>MapControl</code> object is projected and its <code>ViewPort</code>'s distance units are in degrees.</li>
|
||
289 | * <li>Uses <i><code>{NumberFormat according to {@link #setFractionDigits(Point2D) #setFractionDigits(Point2D)}}.format((p.get{X or Y}()/MapContext.CHANGEM[mapControl.getViewPort().getDistanceUnits()])*MapContext.CHANGEM[mapControl.getViewPort().getMapUnits()])</code></i>
|
||
290 | * otherwise.</li>
|
||
291 | * </ul>
|
||
292 | * </p>
|
||
293 | *
|
||
294 | * @param p point 2D to convert in text coordinates according the projection of the associated <code>MapControl</code> and the
|
||
295 | * distance units of its <code>ViewPort</code>.
|
||
296 | *
|
||
297 | * @return coordinates equivalent to <code>p</code>, according to the algorithm explained up
|
||
298 | */
|
||
299 | public String[] getCoords(Point2D p) { |
||
300 | String[] coords=new String[2]; |
||
301 | IProjection iProj = mapControl.getMapContext().getProjection(); |
||
302 | if (!iProj.isProjected()) {
|
||
303 | 45732 | jjdelcerro | coords[0]=String.valueOf(GeometryUtils.formatCoordinate(DEGRESS_FORMAT, p.getX())); |
304 | coords[1]=String.valueOf(GeometryUtils.formatCoordinate(DEGRESS_FORMAT, p.getY())); |
||
305 | 40435 | jjdelcerro | } else {
|
306 | double[] trans2Meter=MapContext.getDistanceTrans2Meter(); |
||
307 | if (PluginServices.getText(this,MapContext.getDistanceNames()[mapControl.getViewPort().getDistanceUnits()]).equals(PluginServices.getText(this,"Grados"))) { |
||
308 | 41000 | jldominguez | |
309 | Point2D pgeo = null; |
||
310 | try {
|
||
311 | pgeo = iProj.toGeo(p); |
||
312 | 45732 | jjdelcerro | coords[0]=String.valueOf(GeometryUtils.formatCoordinate(DEGRESS_FORMAT, pgeo.getX())); |
313 | coords[1]=String.valueOf(GeometryUtils.formatCoordinate(DEGRESS_FORMAT, pgeo.getY())); |
||
314 | 41000 | jldominguez | } catch (Exception exc) { |
315 | |||
316 | if ((System.currentTimeMillis() - lastLogTime) > 5000) { |
||
317 | /*
|
||
318 | * Prevent too many log lines
|
||
319 | */
|
||
320 | lastLogTime = System.currentTimeMillis();
|
||
321 | logger.info("Error: Unable to unproject coordinates: " + p);
|
||
322 | } |
||
323 | |||
324 | /*
|
||
325 | * Unable to "unproject". This is not necessarily a bug
|
||
326 | * (example: UTM coordinates very far from fuse)
|
||
327 | */
|
||
328 | coords[0]= "-"; |
||
329 | coords[1]= "-"; |
||
330 | } |
||
331 | |||
332 | 40435 | jjdelcerro | }else {
|
333 | if (PluginServices.getText(this,MapContext.getDistanceNames()[mapControl.getViewPort().getMapUnits()]).equals(PluginServices.getText(this,"Grados"))) { |
||
334 | mapControl.getViewPort().setMapUnits(1);
|
||
335 | } |
||
336 | |||
337 | coords[0]=String.valueOf(nf.format((p.getX()/trans2Meter[mapControl.getViewPort().getDistanceUnits()])*trans2Meter[mapControl.getViewPort().getMapUnits()])); |
||
338 | coords[1]=String.valueOf(nf.format((p.getY()/trans2Meter[mapControl.getViewPort().getDistanceUnits()])*trans2Meter[mapControl.getViewPort().getMapUnits()])); |
||
339 | } |
||
340 | } |
||
341 | return coords;
|
||
342 | } |
||
343 | |||
344 | /*
|
||
345 | * (non-Javadoc)
|
||
346 | * @see com.iver.cit.gvsig.fmap.tools.Listeners.PointListener#pointDoubleClick(com.iver.cit.gvsig.fmap.tools.Events.PointEvent)
|
||
347 | */
|
||
348 | public void pointDoubleClick(PointEvent event) throws BehaviorException { |
||
349 | // TODO Auto-generated method stub
|
||
350 | } |
||
351 | } |