/*
Copyright (C) 2001, 2007 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.applications.sar;
import gov.nasa.worldwind.geom.Position;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
/**
* @author tag
* @version $Id: TrackViewPanel.java 5064 2008-04-16 15:41:01Z dcollins $
*/
public class TrackViewPanel extends JPanel
{
// SAR logical components.
private SARTrack sarTrack;
private String elevationUnit;
// "View" panel components
private JCheckBox subsurfaceButton;
private JRadioButton examineButton;
private JRadioButton followButton;
private JRadioButton freeButton;
private JCheckBox overrideClipDistanceButton;
private JSlider clipDistanceSlider;
// "Position" panel components
private JLabel latLabel;
private JLabel lonLabel;
private JLabel altLabel;
private JLabel latReadout;
private JLabel lonReadout;
private JLabel altReadout;
private JSpinner positionSpinner;
private JSlider positionSlider;
private JButton fastReverseButton;
private JButton reverseButton;
private JButton stopButton;
private JButton forwardButton;
private JButton fastForwardButton;
private JLabel speedLabel;
private JSlider speedSlider;
// "Player" logical components.
private static final int PLAY_FORWARD = 1;
private static final int PLAY_BACKWARD = -1;
private static final int PLAY_STOP = 0;
private int playMode = PLAY_STOP;
private Timer player;
public static final String POSITION_CHANGE = "TrackViewPanel.PositionChange";
public static final String VIEW_CHANGE = "TrackViewPanel.ViewChange";
public TrackViewPanel()
{
initComponents();
this.updateEnabledState();
}
public void setCurrentTrack(SARTrack sarTrack)
{
this.sarTrack = sarTrack;
if (this.sarTrack != null)
{
this.sarTrack.addPropertyChangeListener(new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
updatePositionList(false);
}
});
}
this.updatePositionList(true);
this.updateEnabledState();
}
public String getElevationUnit()
{
return this.elevationUnit;
}
public void setElevationUnit(String elevationUnit)
{
this.elevationUnit = elevationUnit;
}
private void updatePositionList(boolean resetPosition)
{
String[] strings = new String[this.sarTrack != null ? this.sarTrack.size() : 0];
for (int i = 0; i < strings.length; i++)
strings[i] = String.format("%,4d", i);
if (strings.length == 0)
strings = new String[] {" 0"};
Object currentSpinnerValue = this.positionSpinner.getValue();
int currentSliderValue = this.positionSlider.getValue();
this.positionSpinner.setModel(new SpinnerListModel(strings));
this.positionSpinner.setValue(resetPosition ? strings[0] : currentSpinnerValue);
this.positionSlider.setValue(resetPosition ? 0 : currentSliderValue);
}
private void setPositionSpinnerNumber(int n)
{
this.positionSpinner.setValue(String.format("%,4d", n));
}
private void updateEnabledState()
{
boolean state = this.sarTrack != null;
this.examineButton.setEnabled(state);
this.followButton.setEnabled(state);
this.positionSpinner.setEnabled(state);
this.positionSlider.setEnabled(state);
this.speedLabel.setEnabled(state);
this.latLabel.setEnabled(state);
this.lonLabel.setEnabled(state);
this.altLabel.setEnabled(state);
this.fastReverseButton.setEnabled(state);
this.reverseButton.setEnabled(state);
// this.stopButton.setEnabled(state);
this.forwardButton.setEnabled(state);
this.fastForwardButton.setEnabled(state);
this.speedLabel.setEnabled(state);
this.speedSlider.setEnabled(state);
this.updateReadout(this.sarTrack != null && sarTrack.size() > 0 ? sarTrack.get(0) : null);
}
private void positionSpinnerStateChanged()
{
this.positionSlider.setValue(0);
this.firePropertyChange(POSITION_CHANGE, -1, 0);
}
private void positionSliderStateChanged()
{
this.firePropertyChange(POSITION_CHANGE, -1, 0);
}
private void examineButtonItemStateChanged()
{
this.subsurfaceButton.setSelected(false);
this.firePropertyChange(VIEW_CHANGE, -1, 0);
}
private void followButtonItemStateChanged()
{
this.subsurfaceButton.setSelected(true);
this.firePropertyChange(VIEW_CHANGE, -1, 0);
}
private void freeButtonItemStateChanged()
{
this.subsurfaceButton.setSelected(false);
this.firePropertyChange(VIEW_CHANGE, -1, 0);
}
private void subsurfaceButtonItemStateChanged()
{
this.firePropertyChange(VIEW_CHANGE, -1, 0);
}
private void overrideClipDistanceButtonStateChanged()
{
this.subsurfaceButton.setEnabled(!this.overrideClipDistanceButton.isSelected());
this.firePropertyChange(POSITION_CHANGE, -1, 0);
}
private void clipDistanceStateChanged()
{
this.firePropertyChange(POSITION_CHANGE, -1, 0);
}
public int getCurrentPositionNumber()
{
Object o = this.positionSpinner.getValue();
if (o == null)
return -1;
return Integer.parseInt(o.toString().trim().replaceAll(",", ""));
}
private boolean isLastPosition(int n)
{
return n >= this.sarTrack.size() - 1;
}
public double getPositionDelta()
{
int i = this.positionSlider.getValue();
int min = this.positionSlider.getMinimum();
int max = this.positionSlider.getMaximum();
return (double) i / ((double) max - (double) min);
}
public boolean isSubsurfaceOkay()
{
return this.subsurfaceButton.isSelected();
}
public boolean isExamineViewMode()
{
return this.examineButton.isSelected();
}
public boolean isFollowViewMode()
{
return this.followButton.isSelected();
}
public boolean isFreeViewMode()
{
return this.freeButton.isSelected();
}
public boolean isOverrideClipDistance()
{
return this.overrideClipDistanceButton.isSelected();
}
public double getClipDistance()
{
return this.clipDistanceSlider.getValue();
}
public void updateReadout(Position pos)
{
this.latReadout.setText(pos == null ? "" : String.format("% 7.4f\u00B0", pos.getLatitude().getDegrees()));
this.lonReadout.setText(pos == null ? "" : String.format("% 7.4f\u00B0", pos.getLongitude().getDegrees()));
if (SAR2.UNIT_IMPERIAL.equals(this.elevationUnit))
this.altReadout.setText(pos == null ? "" : String.format("% 8.0f ft", SAR2.metersToFeet(pos.getElevation())));
else // Default to metric units.
this.altReadout.setText(pos == null ? "" : String.format("% 8.0f m", pos.getElevation()));
}
// Player Controls
private void fastReverseButtonActionPerformed()
{
if (this.getCurrentPositionNumber() > 0)
setPositionSpinnerNumber(this.getCurrentPositionNumber() - 1);
}
private void reverseButtonActionPerformed()
{
setPlayMode(PLAY_BACKWARD);
}
private void stopButtonActionPerformed()
{
setPlayMode(PLAY_STOP);
}
private void forwardButtonActionPerformed()
{
setPlayMode(PLAY_FORWARD);
}
private void fastForwardButtonActionPerformed()
{
if (!isLastPosition(this.getCurrentPositionNumber()))
setPositionSpinnerNumber(this.getCurrentPositionNumber() + 1);
}
public boolean isPlayerActive()
{
return this.playMode != PLAY_STOP;
}
private void setPlayMode(int mode)
{
this.playMode = mode;
if (player == null)
initPlayer();
player.start();
}
private void initPlayer()
{
if (player != null)
return;
player = new Timer(50, new ActionListener()
{
// Animate the view motion by controlling the positionSpinner and segmentSlider
public void actionPerformed(ActionEvent actionEvent)
{
runPlayer();
}
});
}
private void runPlayer()
{
int curPosition = getCurrentPositionNumber();
int curValue = this.positionSlider.getValue();
int valueSpeed = this.speedSlider.getValue() / 10;
if (this.playMode == PLAY_STOP)
{
this.stopButton.setEnabled(false);
this.player.stop();
}
else if (this.playMode == PLAY_FORWARD)
{
this.stopButton.setEnabled(true);
if (curPosition >= (this.sarTrack.size() - 1))
{
this.playMode = PLAY_STOP;
setPositionSpinnerNumber(this.sarTrack.size() - 1);
}
else
{
int nextValue = curValue + valueSpeed;
if (nextValue > this.positionSlider.getMaximum())
{
int nextPosition = curPosition + 1;
if (nextPosition >= (this.sarTrack.size() - 1))
{
this.playMode = PLAY_STOP;
setPositionSpinnerNumber(this.sarTrack.size() - 1);
}
else
{
setPositionSpinnerNumber(nextPosition);
}
}
else
{
this.positionSlider.setValue(nextValue);
}
}
}
else if (this.playMode == PLAY_BACKWARD)
{
this.stopButton.setEnabled(true);
if (curPosition >= (this.sarTrack.size() - 1))
{
setPositionSpinnerNumber(curPosition - 1);
this.positionSlider.setValue(this.positionSlider.getMaximum());
}
else
{
int nextValue = curValue - valueSpeed;
if (nextValue < this.positionSlider.getMinimum())
{
int nextPosition = curPosition - 1;
if (nextPosition < 0)
{
this.playMode = PLAY_STOP;
setPositionSpinnerNumber(0);
this.positionSlider.setValue(0);
}
else
{
setPositionSpinnerNumber(nextPosition);
this.positionSlider.setValue(this.positionSlider.getMaximum());
}
}
else
{
this.positionSlider.setValue(nextValue);
}
}
}
}
private void initComponents()
{
//======== this ========
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
//======== "View" Section ========
Box viewPanel = Box.createVerticalBox();
{
//viewBox.setBorder(new EmptyBorder(5, 10, 12, 5));
viewPanel.setBorder(new CompoundBorder(
new TitledBorder(BorderFactory.createMatteBorder(1, 5, 1, 1, Color.GRAY), "View"),
new EmptyBorder(5, 5, 5, 5)));
//======== View Mode Panel ========
Box modePanel = Box.createHorizontalBox();
modePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
{
//---- "Subsurface" Button ----
this.subsurfaceButton = new JCheckBox();
this.subsurfaceButton.setText("Subsurface");
this.subsurfaceButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
subsurfaceButtonItemStateChanged();
}
});
modePanel.add(this.subsurfaceButton);
modePanel.add(Box.createHorizontalStrut(20));
//---- "EXAMINE" Button ----
this.examineButton = new JRadioButton();
this.examineButton.setText("EXAMINE");
this.examineButton.setHorizontalAlignment(SwingConstants.CENTER);
this.examineButton.setEnabled(false);
this.examineButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
examineButtonItemStateChanged();
}
});
modePanel.add(this.examineButton);
modePanel.add(Box.createHorizontalStrut(20));
//---- "FLY-IT" Button ----
this.followButton = new JRadioButton();
this.followButton.setText("FLY-IT");
this.followButton.setHorizontalAlignment(SwingConstants.CENTER);
this.followButton.setEnabled(false);
this.followButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
followButtonItemStateChanged();
}
});
modePanel.add(this.followButton);
modePanel.add(Box.createHorizontalStrut(20));
//---- "FREE" Button ----
this.freeButton = new JRadioButton();
this.freeButton.setText("FREE");
this.freeButton.setSelected(true);
this.freeButton.setHorizontalAlignment(SwingConstants.CENTER);
this.freeButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
freeButtonItemStateChanged();
}
});
modePanel.add(this.freeButton);
//--------
modePanel.add(Box.createHorizontalGlue());
//---- View Mode ButtonGroup ----
ButtonGroup viewModeButtonGroup = new ButtonGroup();
viewModeButtonGroup.add(this.examineButton);
viewModeButtonGroup.add(this.followButton);
viewModeButtonGroup.add(this.freeButton);
}
viewPanel.add(modePanel);
viewPanel.add(Box.createVerticalStrut(10));
//======== Clip Control Panel ========
Box clipPanel = Box.createHorizontalBox();
clipPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
{
//---- "Override Clip Distance" Button ----
this.overrideClipDistanceButton = new JCheckBox();
this.overrideClipDistanceButton.setText("Override Clip Distance:");
this.overrideClipDistanceButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
overrideClipDistanceButtonStateChanged();
}
});
clipPanel.add(this.overrideClipDistanceButton);
clipPanel.add(Box.createHorizontalStrut(3));
int minDistance = 10;
int maxDistance = 100000;
this.clipDistanceSlider = new JSlider();
this.clipDistanceSlider.setMinimum(minDistance);
this.clipDistanceSlider.setMaximum(maxDistance);
this.clipDistanceSlider.setValue(minDistance + (maxDistance - minDistance) / 2);
this.clipDistanceSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent event) {
clipDistanceStateChanged();
}
});
clipPanel.add(this.clipDistanceSlider);
}
viewPanel.add(clipPanel);
}
add(viewPanel);
//======== "Position" Section ========
Box positionPanel = Box.createVerticalBox();
positionPanel.setBorder(new CompoundBorder(
new TitledBorder(BorderFactory.createMatteBorder(1, 5, 1, 1, Color.GRAY), "Position"),
new EmptyBorder(5, 5, 5, 5)));
{
//======== Position Readout ========
JPanel readoutPanel = new JPanel();
readoutPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
readoutPanel.setLayout(new GridLayout(1, 3));
{
//======== Latitude ========
Box lat = Box.createHorizontalBox();
{
this.latLabel = new JLabel();
this.latLabel.setText("Lat:");
lat.add(this.latLabel);
lat.add(Box.createHorizontalStrut(3));
this.latReadout = new JLabel();
this.latReadout.setText("-90.0000");
lat.add(this.latReadout);
lat.add(Box.createHorizontalGlue());
}
readoutPanel.add(lat);
//======== Longitude ========
Box lon = Box.createHorizontalBox();
{
this.lonLabel = new JLabel();
this.lonLabel.setText("Lon:");
lon.add(this.lonLabel);
lon.add(Box.createHorizontalStrut(3));
//---- lonReadout ----
this.lonReadout = new JLabel();
this.lonReadout.setText("-180.0000");
lon.add(this.lonReadout);
lon.add(Box.createHorizontalGlue());
}
readoutPanel.add(lon);
//======== Altitude ========
Box alt = Box.createHorizontalBox();
{
this.altLabel = new JLabel();
this.altLabel.setText("Alt:");
alt.add(this.altLabel);
alt.add(Box.createHorizontalStrut(3));
this.altReadout = new JLabel();
this.altReadout.setText("50,000.000");
alt.add(this.altReadout);
alt.add(Box.createHorizontalGlue());
}
readoutPanel.add(alt);
}
positionPanel.add(readoutPanel);
positionPanel.add(Box.createVerticalStrut(5));
//======== Position Spinner, Slider ========
JPanel positionControlPanel = new JPanel();
positionControlPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
positionControlPanel.setLayout(new BorderLayout(5, 0));
{
//---- Position Spinner ----
this.positionSpinner = new JSpinner();
this.positionSpinner.setModel(new SpinnerListModel(new String[] {" 0"}));
this.positionSpinner.setEnabled(false);
this.positionSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
positionSpinnerStateChanged();
}
});
positionControlPanel.add(this.positionSpinner, BorderLayout.WEST);
//---- Position Slider ----
this.positionSlider = new JSlider();
this.positionSlider.setMaximum(1000);
this.positionSlider.setValue(0);
this.positionSlider.setEnabled(false);
this.positionSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
positionSliderStateChanged();
}
});
positionControlPanel.add(this.positionSlider, BorderLayout.CENTER);
}
positionPanel.add(positionControlPanel);
positionPanel.add(Box.createVerticalStrut(10));
//======== "VCR" Panel ========
Box vcrPanel = Box.createHorizontalBox();
vcrPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
{
//---- "<<" Button ----
this.fastReverseButton = new JButton();
this.fastReverseButton.setText("<<");
this.fastReverseButton.setEnabled(false);
this.fastReverseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fastReverseButtonActionPerformed();
}
});
vcrPanel.add(this.fastReverseButton);
vcrPanel.add(Box.createHorizontalStrut(3));
//---- "<" Button----
this.reverseButton = new JButton();
this.reverseButton.setText("<");
this.reverseButton.setEnabled(false);
this.reverseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
reverseButtonActionPerformed();
}
});
vcrPanel.add(this.reverseButton);
vcrPanel.add(Box.createHorizontalStrut(3));
//---- "Stop" Button ----
this.stopButton = new JButton();
this.stopButton.setText("Stop");
this.stopButton.setEnabled(false);
this.stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopButtonActionPerformed();
}
});
vcrPanel.add(this.stopButton);
vcrPanel.add(Box.createHorizontalStrut(3));
//---- ">" Button ----
this.forwardButton = new JButton();
this.forwardButton.setText(">");
this.forwardButton.setBorder(UIManager.getBorder("Button.border"));
this.forwardButton.setEnabled(false);
this.forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
forwardButtonActionPerformed();
}
});
vcrPanel.add(this.forwardButton);
vcrPanel.add(Box.createHorizontalStrut(3));
//---- ">>" Button ----
this.fastForwardButton = new JButton();
this.fastForwardButton.setText(">>");
this.fastForwardButton.setEnabled(false);
this.fastForwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fastForwardButtonActionPerformed();
}
});
vcrPanel.add(this.fastForwardButton);
//--------
vcrPanel.add(Box.createHorizontalGlue());
}
positionPanel.add(vcrPanel);
positionPanel.add(Box.createVerticalStrut(5));
//======== "Speed" Panel ========
Box speedPanel = Box.createHorizontalBox();
speedPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
{
//---- "Speed:" Label ----
this.speedLabel = new JLabel();
this.speedLabel.setText("Speed:");
speedPanel.add(this.speedLabel);
speedPanel.add(Box.createHorizontalStrut(5));
//---- Speed Slider ----
this.speedSlider = new JSlider();
this.speedSlider.setMaximum(200);
this.speedSlider.setMajorTickSpacing(50);
this.speedSlider.setPaintLabels(true);
this.speedSlider.setValue(20);
this.speedSlider.setEnabled(false);
speedPanel.add(this.speedSlider);
}
positionPanel.add(speedPanel);
}
add(positionPanel);
}
}