/**
*
*/
package com.momega.spacesimulator.swing;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.momega.common.BeanUtils;
import com.momega.spacesimulator.context.Application;
import com.momega.spacesimulator.context.ModelHolder;
import com.momega.spacesimulator.model.CelestialBody;
import com.momega.spacesimulator.model.HabitableModule;
import com.momega.spacesimulator.model.KeplerianOrbit;
import com.momega.spacesimulator.model.Planet;
import com.momega.spacesimulator.model.Propulsion;
import com.momega.spacesimulator.model.Spacecraft;
import com.momega.spacesimulator.model.SpacecraftSubsystem;
import com.momega.spacesimulator.model.Timestamp;
import com.momega.spacesimulator.model.Vector3d;
import com.momega.spacesimulator.renderer.RendererModel;
import com.momega.spacesimulator.service.SpacecraftService;
/**
* @author martin
*
*/
public class CreateSpacecraftPanel extends AbstractDefaultPanel implements ListDataListener {
private static final Logger logger = LoggerFactory.getLogger(CreateSpacecraftPanel.class);
private static final long serialVersionUID = -5382116628099978038L;
private CelestialBodiesObjectModel celestialBodiesObjectModel;
private SubsystemObjectModel subsystemObjectModel;
private IndexModel indexModel;
private JTextField txtName;
private JTextField txtInclincation;
private JTextField txtTheta;
private JTextField txtVelocity;
private JComboBox<CelestialBody> cmbCelestialBodies;
private JComboBox<Integer> indexBox;
private SpacecraftService spacecraftService;
private JTextField txtAltitude;
private JTextField txtAscendingNode;
private JTextField txtArgumentOfPeriapsis;
private JList<SpacecraftSubsystem> subsystemBox;
private JTextField txtMass;
private double mass;
private Spacecraft newSpacecraft;
public CreateSpacecraftPanel() {
celestialBodiesObjectModel = new CelestialBodiesObjectModel();
subsystemObjectModel = new SubsystemObjectModel();
subsystemObjectModel.addListDataListener(this);
indexModel = new IndexModel();
spacecraftService = Application.getInstance().getService(SpacecraftService.class);
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
JLabel lblName = new JLabel("Name:", SwingConstants.RIGHT);
JLabel lblPlanet = new JLabel("Target Body:", SwingConstants.RIGHT);
JLabel lblAltitude = new JLabel("Altitude:", SwingConstants.RIGHT);
JLabel lblOrbit = new JLabel("Orbit:", SwingConstants.RIGHT);
JLabel lblVelocity = new JLabel("Velocity:", SwingConstants.RIGHT);
JLabel lblIndex = new JLabel("Image Index:", SwingConstants.RIGHT);
JLabel lblSubsystems = new JLabel("Subsystems:", SwingConstants.RIGHT);
JPanel grpOrbit = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
txtTheta = new JTextField("0", SwingConstants.RIGHT);
txtInclincation = new JTextField("0", SwingConstants.RIGHT);
txtAscendingNode = new JTextField("0", SwingConstants.RIGHT);
txtArgumentOfPeriapsis = new JTextField("0", SwingConstants.RIGHT);
grpOrbit.add(new JLabel("i="));
grpOrbit.add(txtInclincation);
grpOrbit.add(new JLabel("\u0398="));
grpOrbit.add(txtAscendingNode);
grpOrbit.add(new JLabel("\u03C9="));
grpOrbit.add(txtArgumentOfPeriapsis);
grpOrbit.add(new JLabel("\u03D1="));
grpOrbit.add(txtTheta);
txtName = new JTextField("New Spacecraft");
txtName.addFocusListener(new FocusTextListener(txtName));
txtName.setColumns(30);
JPanel grpAltitude = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
txtAltitude = new JTextField("0");
txtAltitude.addFocusListener(new FocusTextListener(txtAltitude));
txtAltitude.setColumns(20);
grpAltitude.add(txtAltitude);
grpAltitude.add(new JLabel("km"));
txtInclincation.addFocusListener(new FocusTextListener(txtInclincation));
txtInclincation.setColumns(5);
txtTheta.addFocusListener(new FocusTextListener(txtTheta));
txtTheta.setColumns(5);
txtAscendingNode.addFocusListener(new FocusTextListener(txtAscendingNode));
txtAscendingNode.setColumns(5);
txtArgumentOfPeriapsis.addFocusListener(new FocusTextListener(txtArgumentOfPeriapsis));
txtArgumentOfPeriapsis.setColumns(5);
JPanel grpVelocity = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
txtVelocity = new JTextField("0");
txtVelocity.addFocusListener(new FocusTextListener(txtVelocity));
txtVelocity.setColumns(20);
grpVelocity.add(txtVelocity);
grpVelocity.add(new JLabel("m/s"));
cmbCelestialBodies = new JComboBox<CelestialBody>();
cmbCelestialBodies.setModel(celestialBodiesObjectModel);
cmbCelestialBodies.setRenderer(new MovingObjectListRenderer());
cmbCelestialBodies.setMaximumSize(new Dimension(300, 100));
indexBox = new JComboBox<Integer>();
indexBox.setModel(indexModel);
indexBox.setMaximumSize(new Dimension(300, 100));
subsystemBox = new JList<>(subsystemObjectModel);
subsystemBox.setCellRenderer(new SubsystemObjectListRenderer());
subsystemBox.setMaximumSize(new Dimension(300, 100));
final JPopupMenu popup = new JPopupMenu();
popup.add(new JMenuItem(new AbstractAction("Add Habitat") {
private static final long serialVersionUID = 8974522940460420771L;
public void actionPerformed(ActionEvent e) {
final HabitableModule habitat = new HabitableModule();
habitat.setName("New Habitat");
habitat.setCrewCapacity(1);
habitat.setMass(1000.0);
HabitatPanel panel = new HabitatPanel(habitat) {
private static final long serialVersionUID = 3208028406589668188L;
@Override
public boolean okPressed() {
boolean result = super.okPressed();
if (result) {
subsystemObjectModel.addElement(habitat);
}
return result;
}
};
SwingUtils.openDialog(panel.creatDialog("Habitable Module"));
}
}));
popup.add(new JMenuItem(new AbstractAction("Add Propulsion") {
private static final long serialVersionUID = 1722095734714791910L;
public void actionPerformed(ActionEvent e) {
final Propulsion propulsion = new Propulsion();
propulsion.setName("New Propulsion");
propulsion.setMassFlow(219.0);
propulsion.setMass(123000.0);
propulsion.setSpecificImpulse(421.0);
propulsion.setFuel(123000.0-13500.0);
PropulsionPanel panel = new PropulsionPanel(propulsion) {
private static final long serialVersionUID = 3208028406589668188L;
@Override
public boolean okPressed() {
boolean result = super.okPressed();
if (result) {
subsystemObjectModel.addElement(propulsion);
}
return result;
}
};
SwingUtils.openDialog(panel.creatDialog("Propulsion"));
}
}));
JPanel subsystemPanel = new JPanel(new GridLayout(3, 1));
final JButton addButton = new JButton("Add");
addButton.setIcon(SwingUtils.createImageIcon("/images/add.png"));
addButton.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
popup.show(e.getComponent(), addButton.getBounds().x, addButton.getBounds().y
+ addButton.getBounds().height);
popup.setPopupSize(addButton.getBounds().width, addButton.getBounds().height * 2);
}
});
JButton removeButton = new JButton("Remove");
removeButton.setIcon(SwingUtils.createImageIcon("/images/delete.png"));
removeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int index = subsystemBox.getSelectedIndex();
subsystemObjectModel.remove(index);
}
});
JButton editButton = new JButton("Edit");
editButton.setIcon(SwingUtils.createImageIcon("/images/pencil.png"));
editButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final int index = subsystemBox.getSelectedIndex();
final SpacecraftSubsystem oldSubsystem = subsystemObjectModel.get(index);
final SpacecraftSubsystem newSubsystem = BeanUtils.copyInstance(oldSubsystem);
if (newSubsystem instanceof HabitableModule) {
HabitatPanel hd = new HabitatPanel((HabitableModule) newSubsystem) {
private static final long serialVersionUID = 3208028406589668188L;
@Override
public boolean okPressed() {
boolean result = super.okPressed();
if (result) {
subsystemObjectModel.set(index, newSubsystem);
}
return result;
}
};
SwingUtils.openDialog(hd.creatDialog("Habitable Module"));
} else if (newSubsystem instanceof Propulsion) {
PropulsionPanel pd = new PropulsionPanel((Propulsion) newSubsystem) {
private static final long serialVersionUID = -3596648463134624923L;
@Override
public boolean okPressed() {
boolean result = super.okPressed();
if (result) {
subsystemObjectModel.set(index, newSubsystem);
}
return result;
}
};
SwingUtils.openDialog(pd.creatDialog("Propulsion"));
}
}
});
subsystemPanel.add(addButton);
subsystemPanel.add(editButton);
subsystemPanel.add(removeButton);
JLabel lblMass = new JLabel("Mass:", SwingConstants.RIGHT);
txtMass = new JTextField("0.0");
txtMass.addFocusListener(new FocusTextListener(txtMass));
txtMass.setColumns(20);
txtMass.setEditable(false);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblName)
.addComponent(txtName)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblPlanet)
.addComponent(cmbCelestialBodies)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblAltitude)
.addComponent(grpAltitude)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblOrbit)
.addComponent(grpOrbit)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblVelocity)
.addComponent(grpVelocity)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblIndex)
.addComponent(indexBox)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblSubsystems)
.addComponent(subsystemBox)
.addComponent(subsystemPanel)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblMass)
.addComponent(txtMass)
)
);
layout.setHorizontalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblName)
.addComponent(lblPlanet)
.addComponent(lblAltitude)
.addComponent(lblOrbit)
.addComponent(lblVelocity)
.addComponent(lblIndex)
.addComponent(lblSubsystems)
.addComponent(lblMass)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(txtName)
.addComponent(cmbCelestialBodies)
.addComponent(grpAltitude)
.addComponent(grpOrbit)
.addComponent(grpVelocity)
.addComponent(indexBox)
.addComponent(subsystemBox)
.addComponent(txtMass)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(subsystemPanel)
)
);
}
public boolean okPressed() {
super.okPressed();
try {
String name = txtName.getText();
Integer index = (Integer) indexBox.getSelectedItem();
double v = Double.parseDouble(txtVelocity.getText());
double altitude = Double.parseDouble(txtAltitude.getText());
double[] color = new double[] {1, 1, 0};
Planet planet = (Planet) cmbCelestialBodies.getSelectedItem();
Vector3d position = KeplerianOrbit.getCartesianPosition(altitude * 1E3 + planet.getRadius(), 0, 0, Math.PI, 0d);
Vector3d top = planet.getOrientation().getV();
Vector3d velocity = position.normalize().cross(top).scale(v).negate();
Timestamp timestamp = ModelHolder.getModel().getTime();
List<SpacecraftSubsystem> subsystems = subsystemObjectModel.values();
CelestialBody centralObject = ModelHolder.getModel().getRootSoi().getBody();
Spacecraft spacecraft = spacecraftService.createSpacecraft(planet, centralObject, name, position, velocity, index, timestamp, color, subsystems);
ModelHolder.getModel().getMovingObjects().add(spacecraft);
spacecraft.setTimestamp(timestamp);
RendererModel.getInstance().setNewSpacecraft(spacecraft);
logger.info("spacecraft with the name {} created", spacecraft.getName());
return true;
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Invalid values",
"Create Spacecraft Error",
JOptionPane.ERROR_MESSAGE);
}
return false;
}
@Override
public void intervalAdded(ListDataEvent e) {
computetTotalMass();
}
private void computetTotalMass() {
Enumeration<SpacecraftSubsystem> enumeration = subsystemObjectModel.elements();
mass = 0.0;
while(enumeration.hasMoreElements()) {
SpacecraftSubsystem subsystem = enumeration.nextElement();
mass += subsystem.getMass();
}
txtMass.setText(String.valueOf(mass));
}
@Override
public void intervalRemoved(ListDataEvent e) {
computetTotalMass();
}
@Override
public void contentsChanged(ListDataEvent e) {
computetTotalMass();
}
public Spacecraft getNewSpacecraft() {
return newSpacecraft;
}
}