package hirondelle.starfield.gui;
import hirondelle.starfield.catalog.parser.Catalog;
import hirondelle.starfield.physics.InputParameterException;
import hirondelle.starfield.physics.InputParameters;
import hirondelle.starfield.physics.Starfield;
import hirondelle.starfield.physics.StarfieldStats;
import hirondelle.starfield.projection.Projector;
import hirondelle.starfield.util.Consts;
import hirondelle.starfield.util.UiUtil;
import hirondelle.starfield.util.Util;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.RootPaneContainer;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.CC;
import com.jgoodies.forms.layout.FormLayout;
final class Screen {
void buildAndShow(){
fFrame = new JFrame(Consts.APP_NAME);
fFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fFrame.getContentPane().add(buildPanel());
UiUtil.centerAndShow(fFrame);
}
private JFrame fFrame;
private JTextField fBeta = new JTextField("0.993");
private JTextField fLimitingMagnitude = new JTextField("5.0");
private JComboBox<Catalog> fCatalog = new JComboBox<Catalog>(Catalog.values());
private JTextField fCatalogDir = new JTextField("C:\\astro-cat\\yale-bright-star-cat");
private JComboBox<Projector> fProjection = new JComboBox<Projector>(Projector.values());
private JTextField fOutputFile = new JTextField("C:\\TEMP\\starfield1.png");
private JTextArea fMessages = new JTextArea(10, 10);
private JTextField fImageSize = new JTextField("800");
private JTextField fMagnification = new JTextField("1");
private JCheckBox fOpenFile = new JCheckBox();
private JTextField fDirectionRA = new JTextField("0");
private JTextField fDirectionDec = new JTextField("90");
private JTextField fDirectionPhi = new JTextField("0");
private JButton fApply = new JButton("Generate Image");
private JPanel buildPanel(){
String COLUMNS = "left:pref, 3dlu, p:grow, 12dlu, p";
String ROWS = "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p ";
FormLayout layout = new FormLayout(COLUMNS, ROWS);
PanelBuilder builder = new PanelBuilder(layout);
builder.setDefaultDialogBorder();
fBeta.setToolTipText("0..1: speed of the spacecraft, as a fraction of the speed limit");
builder.addLabel("Lorentz Boost Beta:", CC.xy(1, 1));
builder.add(fBeta, CC.xy(3, 1));
builder.addLabel("Limiting Magnitude:", CC.xy(1, 3));
fLimitingMagnitude.setToolTipText("The magnitude at which stars are taken to be invisible to the average human eye");
builder.add(fLimitingMagnitude, CC.xy(3, 3));
builder.addLabel("Catalog:", CC.xy(1, 5));
fCatalog.setToolTipText("The name of the star catalog");
builder.add(fCatalog, CC.xy(3, 5));
builder.addLabel("Catalog Directory:", CC.xy(1, 7));
fCatalogDir.setToolTipText("The directory (folder) containing the downloaded star catalog data (and only that data)");
builder.add(fCatalogDir, CC.xy(3, 7));
builder.addLabel("Projection:", CC.xy(1, 9));
fProjection.setToolTipText("'The projection formula for projecting stars onto the image plane");
builder.add(fProjection, CC.xy(3, 9));
builder.addLabel("Output File:", CC.xy(1, 11));
fOutputFile.setToolTipText("The location and name of the image file generated by this tool");
builder.add(fOutputFile, CC.xy(3, 11));
fOpenFile.setSelected(true);
builder.addLabel("Open Output File:", CC.xy(1, 13));
fOpenFile.setToolTipText("Open the generated image file when finished");
builder.add(fOpenFile, CC.xy(3, 13));
builder.addLabel("Image Size In Pixels:", CC.xy(1, 15));
fImageSize.setToolTipText("The width (and height) of the generated image");
builder.add(fImageSize, CC.xy(3, 15));
builder.addLabel("Magnification (half-sky only):", CC.xy(1, 17));
fMagnification.setToolTipText("Zoom factor. Applies to the half-sky projections only.");
builder.add(fMagnification, CC.xy(3, 17));
builder.addLabel("Direction of Motion RA:", CC.xy(1, 19));
fDirectionRA.setToolTipText("Direction of motion of the spacecraft. Right ascension in degrees, 0..360.");
builder.add(fDirectionRA, CC.xy(3, 19));
builder.addLabel("Direction of Motion Dec:", CC.xy(1, 21));
builder.add(fDirectionDec, CC.xy(3, 21));
fDirectionDec.setToolTipText("Direction of motion of the spacecraft. Declination in degrees, -90..+90.");
builder.addLabel("Rotation:", CC.xy(1, 23));
fDirectionPhi.setToolTipText("Rotate the image around the center (the direction of motion). Degrees, 0..360.");
builder.add(fDirectionPhi, CC.xy(3, 23));
fApply.addActionListener(new ApplyAction());
builder.add(fApply, CC.xy(5,23));
builder.addLabel("Messages:", CC.xy(1, 25));
fMessages.setEditable(false);
Document document = fMessages.getDocument();
DocumentPrintStream documentPrintStream = new DocumentPrintStream(document, System.out);
System.setOut(documentPrintStream);
builder.add(new JScrollPane(fMessages), CC.xywh(1,27,5,1));
return builder.getPanel();
}
private final class ApplyAction implements ActionListener {
@Override public void actionPerformed(ActionEvent aEvent) {
long start = System.currentTimeMillis();
Util.log("JRE total memory: " + Runtime.getRuntime().totalMemory() + Consts.NL);
Util.log("JRE free memory: " + Runtime.getRuntime().freeMemory() + Consts.NL);
Util.log(""+Consts.NL);
InputParameters input = null;
try {
startWaitCursor();
input = new InputParameters(
fBeta.getText(), fLimitingMagnitude.getText(), fCatalogDir.getText(),
fCatalog.getSelectedItem().toString(), fOutputFile.getText(), fProjection.getSelectedItem().toString(),
fImageSize.getText(), fMagnification.getText(), fDirectionRA.getText(), fDirectionDec.getText(), fDirectionPhi.getText()
);
Util.log(input);
Util.log(""+Consts.NL);
Starfield starfield = new Starfield(input);
StarfieldStats stats = starfield.calculate();
Util.log(stats.toString());
long end = System.currentTimeMillis();
Util.log(Consts.NL + "Done. Elapsed time: " + (end-start)/1000.0D + " seconds." + Consts.NL);
Util.log("--------------------------------------------------------"+Consts.NL);
if (fOpenFile.isSelected()){
Desktop.getDesktop().open(input.getOutputFile());
}
}
catch (InputParameterException ex){
for(String error : ex.getErrors()){
Util.log(error + Consts.NL);
}
Util.log("Error: Aborting, arguments not correct. Please see javadoc for more information.");
}
catch (IOException ex) {
Util.log("Unable to open output image file.");
}
finally {
stopWaitCursor();
}
}
}
private static final class DocumentPrintStream extends PrintStream {
public DocumentPrintStream(Document document, OutputStream delegateStream) {
super(delegateStream);
fDocument = document;
}
@Override public void print(String string) {
int offset = fDocument.getLength();
try {
fDocument.insertString(offset, string, null);
}
catch (BadLocationException e) {
}
super.print(string); }
private Document fDocument;
}
private void startWaitCursor() {
RootPaneContainer root = (RootPaneContainer) fFrame.getRootPane().getTopLevelAncestor();
root.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
root.getGlassPane().setVisible(true);
}
private void stopWaitCursor() {
RootPaneContainer root = (RootPaneContainer) fFrame.getRootPane().getTopLevelAncestor();
root.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
root.getGlassPane().setVisible(false);
}
}