package com.aerodynelabs.habtk;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import org.noos.xing.mydoggy.Content;
import org.noos.xing.mydoggy.ContentManager;
import org.noos.xing.mydoggy.ToolWindow;
import org.noos.xing.mydoggy.ToolWindowAnchor;
import org.noos.xing.mydoggy.ToolWindowType;
import org.noos.xing.mydoggy.plaf.MyDoggyToolWindowManager;
import org.noos.xing.mydoggy.plaf.ui.content.MyDoggyMultiSplitContentManagerUI;
//import org.pushingpixels.substance.api.DecorationAreaType;
//import org.pushingpixels.substance.api.SubstanceColorScheme;
//import org.pushingpixels.substance.api.SubstanceLookAndFeel;
//import org.pushingpixels.substance.api.skin.SubstanceTwilightLookAndFeel;
import com.aerodynelabs.habtk.help.HelpWindow;
import com.aerodynelabs.habtk.logging.DebugLog;
import com.aerodynelabs.habtk.prediction.Predictor;
import com.aerodynelabs.habtk.tracking.PositionEvent;
import com.aerodynelabs.habtk.tracking.PositionListener;
import com.aerodynelabs.habtk.tracking.TrackingService;
import com.aerodynelabs.habtk.ui.AboutDialog;
import com.aerodynelabs.habtk.ui.MessageDialog;
import com.aerodynelabs.habtk.ui.PredictionPanel;
import com.aerodynelabs.habtk.ui.LogPanel;
import com.aerodynelabs.habtk.ui.TrackingConfigDialog;
import com.aerodynelabs.habtk.ui.TrackingPanel;
import com.aerodynelabs.map.MapOverlay;
import com.aerodynelabs.map.MapPath;
import com.aerodynelabs.map.MapPoint;
import com.aerodynelabs.map.MappingPanel;
/**
* The main class of HABtk
* @author Ethan Harstad
*
*/
public class HABtk implements PositionListener {
private static final String VERSION = "0.01 Alpha";
private static final Logger debugLog = Logger.getLogger("Debug");
private static HABtk habtk;
private static JFrame window;
private static MyDoggyToolWindowManager windowManager;
private static ContentManager contentManager;
private static JCheckBoxMenuItem flightTrackItem;
private static TrackingPanel trackingPanel;
private static MappingPanel trackingMap;
private static boolean tracking = false;
private static BalloonFlight flight;
private static TrackingService trackingService;
private static MapPoint prevPoint = null;
private static int descendingPkts = 0;
/**
* Create GUI Components
*/
private static void setup() {
// Configure window
window = new JFrame("HABtk - " + VERSION);
window.setMinimumSize(new Dimension(800, 600));
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
windowManager = new MyDoggyToolWindowManager();
contentManager = windowManager.getContentManager();
contentManager.setContentManagerUI(new MyDoggyMultiSplitContentManagerUI());
// Create components
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenu flightMenu = new JMenu("Tracking");
JMenu helpMenu = new JMenu("Help");
menuBar.add(fileMenu);
menuBar.add(flightMenu);
menuBar.add(helpMenu);
window.setJMenuBar(menuBar);
JMenuItem fileNewFlightItem = new JMenuItem("New Flight");
fileNewFlightItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Predictor flightPredictor = Predictor.create();
if(flightPredictor != null) flight.setPredictor(flightPredictor);
}
});
fileMenu.add(fileNewFlightItem);
JMenuItem fileLoadFlightItem = new JMenuItem("Load Flight");
fileLoadFlightItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Predictor flightPredictor = Predictor.load();
flight.setPredictor(flightPredictor);
}
});
fileMenu.add(fileLoadFlightItem);
JMenuItem fileSaveFlightItem = new JMenuItem("Save Flight");
fileSaveFlightItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(flight.getPredictor() != null) flight.getPredictor().save();
}
});
fileMenu.add(fileSaveFlightItem);
fileMenu.add(new JSeparator());
JMenuItem fileExitItem = new JMenuItem("Exit");
fileExitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
window.setVisible(false);
exit();
}
});
fileMenu.add(fileExitItem);
JMenuItem flightConfigItem = new JMenuItem("Configure Tracking");
flightConfigItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
TrackingConfigDialog config = new TrackingConfigDialog(trackingService);
if(config.wasAccepted()) {
trackingService.setPrimary(config.getPrimary());
trackingService.setSecondary(config.getSecondary());
trackingService.setRecovery(config.getRecovery());
}
}
});
flightMenu.add(flightConfigItem);
flightTrackItem = new JCheckBoxMenuItem("Enable Tracking");
flightTrackItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(flightTrackItem.getState() == true) {
if(trackingService.getPrimary() == null) {
JOptionPane.showMessageDialog(window, "Primary tracker is not configured.\nDisabling tracking service.", "Configuration Error", JOptionPane.ERROR_MESSAGE, null);
flightTrackItem.setState(false);
return;
}
if(flight.getPredictor() == null) {
JOptionPane.showMessageDialog(window, "Flight is not defined, cannot run predictions.", "Undefined Flight", JOptionPane.WARNING_MESSAGE, null);
flightTrackItem.setState(false);
return;
}
Content mapContent = contentManager.getContent("Tracking Map");
if(mapContent == null) {
contentManager.removeAllContents();
trackingMap = new MappingPanel();
trackingMap.setCenter(
flight.getPredictor().getStart().getLatitude(),
flight.getPredictor().getStart().getLongitude());
MapOverlay trackOverlay = new MapOverlay("Track");
trackOverlay.addPath("Track", flight.getTrack());
trackingMap.addOverlay(trackOverlay);
MapOverlay predOverlay = new MapOverlay("Prediction");
predOverlay.addPath("Prediction", flight.getLatestPrediction());
trackingMap.addOverlay(predOverlay);
contentManager.addContent("Tracking Map", "Tracking Map",
null, trackingMap);
}
}
tracking = flightTrackItem.getState();
trackingService.setEnabled(tracking);
if(tracking == true) {
}
}
});
flightMenu.add(flightTrackItem);
JMenuItem helpHelpItem = new JMenuItem("Help Contents");
helpHelpItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
HelpWindow.showHelp();
}
});
helpMenu.add(helpHelpItem);
JMenuItem helpUpdateItem = new JMenuItem("Check for Updates");
helpUpdateItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//TODO help update action
new Updater();
}
});
helpMenu.add(helpUpdateItem);
JMenuItem helpAboutItem = new JMenuItem("About");
helpAboutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new AboutDialog(window);
}
});
helpMenu.add(helpAboutItem);
trackingPanel = new TrackingPanel();
trackingService.addListener(trackingPanel);
trackingService.addListener(habtk);
windowManager.registerToolWindow("Log", "Log", null, new LogPanel(), ToolWindowAnchor.BOTTOM);
windowManager.registerToolWindow("Tracking", "Tracking", null, trackingPanel, ToolWindowAnchor.LEFT);
windowManager.registerToolWindow("Prediction", null, null, new PredictionPanel(windowManager), ToolWindowAnchor.LEFT);
for(ToolWindow win : windowManager.getToolWindows()) win.setAvailable(true);
windowManager.getToolWindow("Log").setType(ToolWindowType.SLIDING);
window.addWindowListener(new WindowAdapter() {
@Override
public void windowStateChanged(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowOpened(WindowEvent e) {
try {
File workspace = new File("workspace.xml");
if(workspace.exists()) {
FileInputStream in = new FileInputStream(workspace);
windowManager.getPersistenceDelegate().apply(in);
in.close();
}
} catch(Exception e1) {
debugLog.log(Level.SEVERE, "Exception", e);
}
}
@Override
public void windowClosing(WindowEvent e) {
exit();
}
});
window.getContentPane().add(windowManager);
window.pack();
window.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
/**
* Save state and exit
*/
private static void exit() {
try {
FileOutputStream out = new FileOutputStream("workspace.xml");
windowManager.getPersistenceDelegate().save(out);
out.close();
} catch(Exception e1) {
debugLog.log(Level.SEVERE, "Exception", e1);
}
window.dispose();
System.exit(0);
}
/**
* Main method
* @param args Command line arguments
*/
public static void main(String[] args) {
if(args.length == 0) {
DebugLog.setupLogger(9);
} else {
DebugLog.setupLogger(Integer.parseInt(args[0]));
}
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
habtk = new HABtk();
flight = new BalloonFlight();
trackingService = new TrackingService();
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
//try {
//UIManager.setLookAndFeel(new SubstanceTwilightLookAndFeel());
//UIManager.put(SubstanceLookAndFeel.WINDOW_ROUNDED_CORNERS, false);
//} catch (UnsupportedLookAndFeelException e) {
//e.printStackTrace();
//}
setup();
window.setVisible(true);
debugLog.log(Level.INFO, "Application Started");
}
});
} catch(Exception e) {
debugLog.log(Level.SEVERE, "Exception", e);
}
}
@Override
public void positionUpdateEvent(PositionEvent e) {
switch(e.getSource()) {
case PositionEvent.PRIMARY:
MapPoint point = e.getPosition();
flight.getTrack().add(point);
boolean ascending = true;
if(prevPoint != null) {
if(point.getAltitude() < prevPoint.getAltitude()) {
ascending = false;
descendingPkts++;
if(descendingPkts == 5) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MessageDialog(window, "Burst", "Balloon is descending.", 15000);
}
});
}
} else {
descendingPkts = 0;
}
}
prevPoint = point;
Predictor pred = flight.getPredictor().clone();
pred.setStart(e.getPosition());
pred.setAscending(ascending);
MapPath prediction = pred.runPrediction();
flight.updatePrediction(prediction);
MapOverlay predOverlay = new MapOverlay("Prediction");
predOverlay.addPath("Prediction", prediction);
trackingMap.addOverlay("Prediction", predOverlay);
trackingPanel.positionUpdateEvent(
new PositionEvent(PositionEvent.BURST, pred.getBurst()));
trackingPanel.positionUpdateEvent(
new PositionEvent(PositionEvent.LANDING, pred.getLanding()));
break;
}
}
}