/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package org.jgrasstools.nww.gui;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.event.PositionEvent;
import gov.nasa.worldwind.event.PositionListener;
import gov.nasa.worldwind.event.RenderingEvent;
import gov.nasa.worldwind.event.RenderingListener;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.NetworkCheckThread;
import gov.nasa.worldwind.util.NetworkStatus;
import gov.nasa.worldwind.util.WWMath;
/**
* @author tag
* @version $Id: StatusBar.java 1945 2014-04-18 17:08:43Z tgaskins $
*/
public class StatusBar extends JPanel implements PositionListener, RenderingListener {
// Units constants TODO: Replace with UnitsFormat
public final static String UNIT_METRIC = "gov.nasa.worldwind.StatusBar.Metric";
public final static String UNIT_IMPERIAL = "gov.nasa.worldwind.StatusBar.Imperial";
protected static final int MAX_ALPHA = 254;
private WorldWindow eventSource;
private String elevationUnit = UNIT_METRIC;
private String angleFormat = Angle.ANGLE_FORMAT_DD;
protected final JLabel latDisplay = new JLabel("");
protected final JLabel lonDisplay = new JLabel(Logging.getMessage("term.OffGlobe"));
protected final JLabel altDisplay = new JLabel("");
protected final JLabel eleDisplay = new JLabel("");
protected AtomicBoolean showNetworkStatus = new AtomicBoolean(true);
protected AtomicBoolean isNetworkAvailable = new AtomicBoolean(true);
protected Thread netCheckThread;
public StatusBar() {
super(new GridLayout(1, 0));
final JLabel heartBeat = new JLabel(Logging.getMessage("term.Downloading"));
altDisplay.setHorizontalAlignment(SwingConstants.CENTER);
latDisplay.setHorizontalAlignment(SwingConstants.CENTER);
lonDisplay.setHorizontalAlignment(SwingConstants.CENTER);
eleDisplay.setHorizontalAlignment(SwingConstants.CENTER);
this.add(altDisplay);
this.add(latDisplay);
this.add(lonDisplay);
this.add(eleDisplay);
this.add(heartBeat);
heartBeat.setHorizontalAlignment(SwingConstants.CENTER);
heartBeat.setForeground(new java.awt.Color(255, 0, 0, 0));
Timer downloadTimer = new Timer(100, new ActionListener(){
public void actionPerformed( java.awt.event.ActionEvent actionEvent ) {
if (!showNetworkStatus.get()) {
if (heartBeat.getText().length() > 0)
heartBeat.setText("");
return;
}
if (!isNetworkAvailable.get()) {
heartBeat.setText(Logging.getMessage("term.NoNetwork"));
heartBeat.setForeground(new Color(255, 0, 0, MAX_ALPHA));
return;
}
Color color = heartBeat.getForeground();
int alpha = color.getAlpha();
if (isNetworkAvailable.get() && WorldWind.getRetrievalService().hasActiveTasks()) {
heartBeat.setText(Logging.getMessage("term.Downloading"));
if (alpha >= MAX_ALPHA)
alpha = MAX_ALPHA;
else
alpha = alpha < 16 ? 16 : Math.min(MAX_ALPHA, alpha + 20);
} else {
alpha = Math.max(0, alpha - 20);
}
heartBeat.setForeground(new Color(255, 0, 0, alpha));
}
});
downloadTimer.start();
this.netCheckThread = this.startNetCheckThread();
WorldWind.getNetworkStatus().addPropertyChangeListener(NetworkStatus.HOST_UNAVAILABLE, new PropertyChangeListener(){
public void propertyChange( PropertyChangeEvent evt ) {
Object nv = evt.getNewValue();
String message = Logging.getMessage("NetworkStatus.UnavailableHost",
nv != null && nv instanceof URL ? ((URL) nv).getHost() : "Unknown");
Logging.logger().info(message);
}
});
WorldWind.getNetworkStatus().addPropertyChangeListener(NetworkStatus.HOST_AVAILABLE, new PropertyChangeListener(){
public void propertyChange( PropertyChangeEvent evt ) {
Object nv = evt.getNewValue();
String message = Logging.getMessage("NetworkStatus.HostNowAvailable",
nv != null && nv instanceof URL ? ((URL) nv).getHost() : "Unknown");
Logging.logger().info(message);
}
});
}
protected NetworkCheckThread startNetCheckThread() {
NetworkCheckThread nct = new NetworkCheckThread(this.showNetworkStatus, this.isNetworkAvailable, null);
nct.setDaemon(true);
nct.start();
return nct;
}
public void setEventSource( WorldWindow newEventSource ) {
if (this.eventSource != null) {
this.eventSource.removePositionListener(this);
this.eventSource.removeRenderingListener(this);
}
if (newEventSource != null) {
newEventSource.addPositionListener(this);
newEventSource.addRenderingListener(this);
}
this.eventSource = newEventSource;
}
public boolean isShowNetworkStatus() {
return showNetworkStatus.get();
}
public void setShowNetworkStatus( boolean showNetworkStatus ) {
this.showNetworkStatus.set(showNetworkStatus);
if (showNetworkStatus) {
if (this.netCheckThread != null)
this.netCheckThread.interrupt();
this.netCheckThread = this.startNetCheckThread();
} else {
if (this.netCheckThread != null)
this.netCheckThread.interrupt();
this.netCheckThread = null;
}
}
public void moved( PositionEvent event ) {
this.handleCursorPositionChange(event);
}
public WorldWindow getEventSource() {
return this.eventSource;
}
public String getElevationUnit() {
return this.elevationUnit;
}
public void setElevationUnit( String unit ) {
if (unit == null) {
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.elevationUnit = unit;
}
public String getAngleFormat() {
return this.angleFormat;
}
public void setAngleFormat( String format ) {
if (format == null) {
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.angleFormat = format;
}
protected String makeCursorElevationDescription( double metersElevation ) {
String s;
String elev = Logging.getMessage("term.Elev");
if (UNIT_IMPERIAL.equals(elevationUnit))
s = String.format(elev + " %,7d feet", (int) (WWMath.convertMetersToFeet(metersElevation)));
else // Default to metric units.
s = String.format(elev + " %,7d meters", (int) metersElevation);
return s;
}
protected String makeEyeAltitudeDescription( double metersAltitude ) {
String s;
String altitude = Logging.getMessage("term.Altitude");
if (UNIT_IMPERIAL.equals(elevationUnit)) {
double miles = WWMath.convertMetersToMiles(metersAltitude);
if (Math.abs(miles) >= 1)
s = String.format(altitude + " %,7d mi", (int) Math.round(miles));
else
s = String.format(altitude + " %,7d ft", (int) Math.round(WWMath.convertMetersToFeet(metersAltitude)));
} else if (Math.abs(metersAltitude) >= 1000) // Default to metric units.
s = String.format(altitude + " %,7d km", (int) Math.round(metersAltitude / 1e3));
else
s = String.format(altitude + " %,7d m", (int) Math.round(metersAltitude));
return s;
}
protected String makeAngleDescription( String label, Angle angle ) {
String s;
if (Angle.ANGLE_FORMAT_DMS.equals(angleFormat))
s = String.format("%s %s", label, angle.toDMSString());
else
s = String.format("%s %7.4f\u00B0", label, angle.degrees);
return s;
}
protected void handleCursorPositionChange( PositionEvent event ) {
Position newPos = event.getPosition();
if (newPos != null) {
String las = makeAngleDescription("Lat", newPos.getLatitude());
String los = makeAngleDescription("Lon", newPos.getLongitude());
String els = makeCursorElevationDescription(
eventSource.getModel().getGlobe().getElevation(newPos.getLatitude(), newPos.getLongitude()));
latDisplay.setText(las);
lonDisplay.setText(los);
eleDisplay.setText(els);
} else {
latDisplay.setText("");
lonDisplay.setText(Logging.getMessage("term.OffGlobe"));
eleDisplay.setText("");
}
}
public void stageChanged( RenderingEvent event ) {
if (!event.getStage().equals(RenderingEvent.BEFORE_BUFFER_SWAP))
return;
EventQueue.invokeLater(new Runnable(){
public void run() {
if (eventSource.getView() != null && eventSource.getView().getEyePosition() != null)
altDisplay.setText(makeEyeAltitudeDescription(eventSource.getView().getEyePosition().getElevation()));
else
altDisplay.setText(Logging.getMessage("term.Altitude"));
}
});
}
}