package com.momega.spacesimulator.swing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.springframework.beans.BeanUtils;
import com.momega.spacesimulator.context.Application;
import com.momega.spacesimulator.context.ModelHolder;
import com.momega.spacesimulator.model.HistoryPoint;
import com.momega.spacesimulator.model.Maneuver;
import com.momega.spacesimulator.model.Spacecraft;
import com.momega.spacesimulator.model.Timestamp;
import com.momega.spacesimulator.renderer.ModelChangeEvent;
import com.momega.spacesimulator.renderer.NewManeuverEvent;
import com.momega.spacesimulator.service.HistoryPointService;
import com.momega.spacesimulator.service.ManeuverService;
import com.momega.spacesimulator.utils.TimeUtils;
/**
* The panel for editing the maneuvers
* Created by martin on 8/17/14.
*/
public class ManeuverPanel extends JPanel implements UpdatablePanel {
private static final long serialVersionUID = 6451374273245722605L;
private final Spacecraft spacecraft;
private final ManeuverTableModel tableModel;
private final ManeuverService maneuverService;
private final HistoryPointService historyPointService;
public ManeuverPanel(final Spacecraft spacecraft) {
super(new BorderLayout());
this.spacecraft = spacecraft;
maneuverService = Application.getInstance().getService(ManeuverService.class);
historyPointService = Application.getInstance().getService(HistoryPointService.class);
tableModel = new ManeuverTableModel(copyManeuvers(spacecraft.getManeuvers()));
final JTable table = new JTable(tableModel);
table.setDefaultRenderer(Timestamp.class, new TimestampRenderer());
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
JButton newButton = new JButton("Add");
newButton.setIcon(SwingUtils.createImageIcon("/images/add.png"));
newButton.setAlignmentX(Component.CENTER_ALIGNMENT);
newButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.newManeuver();
}
});
JButton deleteButton = new JButton("Delete");
deleteButton.setAlignmentX(Component.CENTER_ALIGNMENT);
deleteButton.setIcon(SwingUtils.createImageIcon("/images/delete.png"));
deleteButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
tableModel.deleteManeuver(row);
}
});
buttonPanel.add(newButton);
buttonPanel.add(deleteButton);
add(scrollPane, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.EAST);
}
protected List<Maneuver> copyManeuvers(List<Maneuver> input) {
List<Maneuver> result = new ArrayList<>();
for(Maneuver m : input) {
Maneuver mm = new Maneuver();
BeanUtils.copyProperties(m, mm);
result.add(mm);
}
return result;
}
class ManeuverTableModel extends AbstractTableModel {
private static final long serialVersionUID = -295663268290081776L;
private final List<Maneuver> maneuvers;
private String[] columnNames = {"Name", "Start Time", "Start Time (mins)", "End Time", "Duration", "Throttle", "Throttle Alpha", "Throttle Dec"};
ManeuverTableModel(List<Maneuver> maneuvers) {
this.maneuvers = maneuvers;
}
@Override
public int getRowCount() {
return maneuvers.size();
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Maneuver m = maneuvers.get(rowIndex);
switch (columnIndex) {
case 0: return m.getName();
case 1: return m.getStartTime();
case 2: return m.getStartTime().subtract(getStartTime()) / 60d;
case 3: return m.getEndTime();
case 4: return TimeUtils.getDuration(m);
case 5: return m.getThrottle();
case 6: return Math.toDegrees(m.getThrottleAlpha());
case 7: return Math.toDegrees(m.getThrottleDelta());
}
return 0d;
}
public void setValueAt(Object value, int row, int col) {
Maneuver m = maneuvers.get(row);
switch (col) {
case 0:
m.setName((String)value);
m.getStart().setName("Start of" + m.getName());
m.getEnd().setName("End of" + m.getName());
break;
case 2:
Double min = (Double) value;
double duration = TimeUtils.getDuration(m);
m.getStart().setTimestamp(getStartTime().add(min.doubleValue() * 60));
m.getEnd().setTimestamp(m.getStartTime().add(duration));
fireTableRowsUpdated(row, row);
break;
case 4:
double val = (double) value;
m.getEnd().setTimestamp(m.getStartTime().add(val));
fireTableCellUpdated(row, col-1);
break;
case 5: m.setThrottle((Double)value);
break;
case 6: m.setThrottleAlpha(Math.toRadians((Double)value));
break;
case 7: m.setThrottleDelta(Math.toRadians((Double)value));
break;
}
fireTableCellUpdated(row, col);
}
public boolean isCellEditable(int row, int col) {
Maneuver m = maneuvers.get(row);
if (TimeUtils.isIntervalInPast(ModelHolder.getModel().getTime(), m)) {
return false;
}
if (col == 1 || col == 3) {
return false;
} else {
return true;
}
}
public void addManeuver(Maneuver m) {
maneuvers.add(m);
fireTableRowsInserted(maneuvers.size()-1, maneuvers.size()-1);
}
public void newManeuver() {
Maneuver m = maneuverService.createManeuver(spacecraft, "No-name Maneuver", ModelHolder.getModel().getTime(), 3600, 60, 1, 0, Math.toRadians(90));
addManeuver(m);
}
public void deleteManeuver(int row) {
maneuvers.remove(row);
fireTableRowsDeleted(row, row);
}
public List<Maneuver> getManeuvers() {
return maneuvers;
}
protected Timestamp getStartTime() {
HistoryPoint hp = historyPointService.getStartPoint(spacecraft);
return hp.getTimestamp();
}
}
class TimestampRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 3279731371208075652L;
public TimestampRenderer() {
super();
}
public void setValue(Object value) {
Timestamp dt = (Timestamp) value;
setText(TimeUtils.timeAsString(dt));
}
}
@Override
public void updateView(ModelChangeEvent event) {
if (event instanceof NewManeuverEvent) {
NewManeuverEvent nme = (NewManeuverEvent) event;
tableModel.addManeuver(nme.getManeuver());
}
}
@Override
public void updateModel() {
spacecraft.setManeuvers(copyManeuvers(tableModel.getManeuvers()));
}
}