package org.esa.snap.rcp.status; import com.bc.ceres.glayer.support.ImageLayer; import com.bc.ceres.glayer.swing.LayerCanvas; import org.esa.snap.core.datamodel.GeoCoding; import org.esa.snap.core.datamodel.GeoPos; import org.esa.snap.core.datamodel.PixelPos; import org.esa.snap.core.datamodel.RasterDataNode; import org.esa.snap.netbeans.docwin.DocumentWindowManager; import org.esa.snap.rcp.SnapApp; import org.esa.snap.ui.PixelPositionListener; import org.esa.snap.ui.product.ProductSceneView; import org.openide.awt.StatusLineElementProvider; import org.openide.util.lookup.ServiceProvider; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.SwingConstants; import java.awt.Component; import java.awt.Dimension; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import static org.esa.snap.rcp.pixelinfo.PixelInfoView.*; /** * Displays current pixel position in the status bar. * * @author Norman Fomferra */ @ServiceProvider(service = StatusLineElementProvider.class, position = 10) public class PixelPosStatusLineElementProvider implements StatusLineElementProvider, DocumentWindowManager.Listener<Object, ProductSceneView>, PixelPositionListener, PreferenceChangeListener { private static final String GEO_POS_FORMAT = "Lat %8s Lon %8s"; private static final String PIXEL_POS_FORMAT = "X %6s Y %6s"; private static final String ZOOM_LEVEL_FORMAT = "Zoom %s Level %s"; private final JLabel zoomLevelLabel; private final JLabel geoPosLabel; private final JLabel pixelPosLabel; private final JPanel panel; private boolean showPixelOffsetDecimals; private boolean showGeoPosOffsetDecimals; public PixelPosStatusLineElementProvider() { DocumentWindowManager.getDefault().addListener(DocumentWindowManager.Predicate.view(ProductSceneView.class), this); SnapApp.getDefault().getPreferences().addPreferenceChangeListener(this); updateSettings(); pixelPosLabel = new JLabel(); pixelPosLabel.setPreferredSize(new Dimension(120, 20)); pixelPosLabel.setHorizontalAlignment(SwingConstants.CENTER); geoPosLabel = new JLabel(); geoPosLabel.setPreferredSize(new Dimension(200, 20)); geoPosLabel.setHorizontalAlignment(SwingConstants.CENTER); zoomLevelLabel = new JLabel(); zoomLevelLabel.setPreferredSize(new Dimension(150, 20)); zoomLevelLabel.setHorizontalAlignment(SwingConstants.CENTER); panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS)); panel.add(Box.createHorizontalGlue()); panel.add(new JSeparator(SwingConstants.VERTICAL)); panel.add(pixelPosLabel); panel.add(new JSeparator(SwingConstants.VERTICAL)); panel.add(geoPosLabel); panel.add(new JSeparator(SwingConstants.VERTICAL)); panel.add(zoomLevelLabel); } @Override public Component getStatusLineElement() { return panel; } @Override public void pixelPosChanged(ImageLayer imageLayer, int pixelX, int pixelY, int currentLevel, boolean pixelPosValid, MouseEvent e) { if (pixelPosValid) { AffineTransform i2mTransform = imageLayer.getImageToModelTransform(currentLevel); Point2D modelP = i2mTransform.transform(new Point2D.Double(pixelX + 0.5, pixelY + 0.5), null); AffineTransform m2iTransform = imageLayer.getModelToImageTransform(); Point2D imageP = m2iTransform.transform(modelP, null); PixelPos pixelPos = new PixelPos(imageP.getX(), imageP.getY()); ProductSceneView productSceneView = SnapApp.getDefault().getSelectedProductSceneView(); if (productSceneView == null) { setDefault(); return; } RasterDataNode rasterDataNode = productSceneView.getRaster(); if (rasterDataNode == null) { setDefault(); return; } GeoCoding geoCoding = rasterDataNode.getGeoCoding(); if (geoCoding == null) { setDefault(); return; } GeoPos geoPos = geoCoding.getGeoPos(pixelPos, null); if (showGeoPosOffsetDecimals) { geoPosLabel.setText(String.format("Lat %.5f Lon %.5f", geoPos.getLat(), geoPos.getLon())); } else { geoPosLabel.setText(String.format(GEO_POS_FORMAT, geoPos.getLatString(), geoPos.getLonString())); } if (showPixelOffsetDecimals) { pixelPosLabel.setText(String.format(PIXEL_POS_FORMAT, imageP.getX(), imageP.getY())); } else { pixelPosLabel.setText(String.format(PIXEL_POS_FORMAT, (int) Math.floor(imageP.getX()), (int) Math.floor(imageP.getY()))); } LayerCanvas layerCanvas = (LayerCanvas) e.getSource(); double zoomFactor = layerCanvas.getViewport().getZoomFactor(); String scaleStr; if (zoomFactor > 1.0) { double v = Math.round(10.0 * zoomFactor) / 10.0; scaleStr = ((int) v == v ? (int) v : v) + ":1"; } else { double v = Math.round(10.0 / zoomFactor) / 10.0; scaleStr = "1:" + ((int) v == v ? (int) v : v); } zoomLevelLabel.setText(String.format(ZOOM_LEVEL_FORMAT, scaleStr, currentLevel)); } else { setDefault(); } } private void setDefault() { geoPosLabel.setText(String.format(GEO_POS_FORMAT, "--", "--")); pixelPosLabel.setText(String.format(PIXEL_POS_FORMAT, "--", "--")); zoomLevelLabel.setText(String.format(ZOOM_LEVEL_FORMAT, "--", "--")); } @Override public void pixelPosNotAvailable() { setDefault(); } @Override public void preferenceChange(PreferenceChangeEvent evt) { // Called if SNAP preferences change, adjust any status bar setting here. final String propertyName = evt.getKey(); if (PREFERENCE_KEY_SHOW_PIXEL_POS_DECIMALS.equals(propertyName) || PREFERENCE_KEY_SHOW_GEO_POS_DECIMALS.equals(propertyName)) { updateSettings(); } } @Override public void windowSelected(DocumentWindowManager.Event<Object, ProductSceneView> e) { ProductSceneView view = e.getWindow().getView(); view.addPixelPositionListener(this); } @Override public void windowDeselected(DocumentWindowManager.Event<Object, ProductSceneView> e) { ProductSceneView view = e.getWindow().getView(); view.removePixelPositionListener(this); } private void updateSettings() { final Preferences preferences = SnapApp.getDefault().getPreferences(); showPixelOffsetDecimals = preferences.getBoolean( PREFERENCE_KEY_SHOW_PIXEL_POS_DECIMALS, PREFERENCE_DEFAULT_SHOW_PIXEL_POS_DECIMALS); showGeoPosOffsetDecimals = preferences.getBoolean( PREFERENCE_KEY_SHOW_GEO_POS_DECIMALS, PREFERENCE_DEFAULT_SHOW_GEO_POS_DECIMALS); } }