package net.sf.openrocket.gui.main.flightconfigpanel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.EventObject;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.formatting.RocketDescriptor;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Pair;
import net.sf.openrocket.util.StateChangeListener;
public abstract class FlightConfigurablePanel<T extends FlightConfigurableComponent> extends JPanel {
protected static final Translator trans = Application.getTranslator();
protected RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class);
protected final FlightConfigurationPanel flightConfigurationPanel;
protected final Rocket rocket;
protected final JTable table;
public FlightConfigurablePanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
super(new MigLayout("fill"));
this.flightConfigurationPanel = flightConfigurationPanel;
this.rocket = rocket;
table = initializeTable();
rocket.getDefaultConfiguration().addChangeListener( new StateChangeListener() {
@Override
public void stateChanged(EventObject e) {
FlightConfigurablePanel.this.synchronizeConfigurationSelection();
}
});
installTableListener();
synchronizeConfigurationSelection();
}
public void fireTableDataChanged() {
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
((AbstractTableModel)table.getModel()).fireTableDataChanged();
restoreSelection(selectedRow,selectedColumn);
updateButtonState();
}
protected abstract void updateButtonState();
protected final void synchronizeConfigurationSelection() {
String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
String selectedId = getSelectedConfigurationId();
if ( id == null && selectedId == null ) {
// Nothing to do
} else if ( id == null ) {
// need to unselect
table.clearSelection();
} else if ( !id.equals(selectedId)){
// Need to change selection
// We'll select the correct row, in the currently selected column.
int col = table.getSelectedColumn();
if ( col < 0 ) {
col = (table.getColumnCount() > 1) ? 1 : 0;
}
for( int row = 0; row < table.getRowCount(); row++ ) {
String rowId = rocket.getFlightConfigurationIDs()[row + 1];
if ( rowId.equals(id) ) {
table.changeSelection(row, col, true, false);
break;
}
}
}
}
protected void restoreSelection( int row, int col ) {
if ( row <= 0 || col <= 0 ) {
synchronizeConfigurationSelection();
return;
}
if ( row >= table.getRowCount() || col >= table.getColumnCount() ) {
synchronizeConfigurationSelection();
return;
}
table.changeSelection(row, col, true, false);
}
private final void installTableListener() {
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if ( e.getValueIsAdjusting() ) {
return;
}
int firstrow = e.getFirstIndex();
int lastrow = e.getLastIndex();
ListSelectionModel model = (ListSelectionModel) e.getSource();
for( int row = firstrow; row <= lastrow; row ++) {
if ( model.isSelectedIndex(row) ) {
String id = (String) table.getValueAt(row, table.convertColumnIndexToView(0));
rocket.getDefaultConfiguration().setFlightConfigurationID(id);
return;
}
}
}
});
}
/**
* Override this method to create the embedded JTable and it's backing Model.
*
* @return
*/
protected abstract JTable initializeTable();
protected T getSelectedComponent() {
int col = table.convertColumnIndexToModel(table.getSelectedColumn());
int row = table.convertRowIndexToModel(table.getSelectedRow());
if ( row < 0 || col < 0 ) {
return null;
}
Object tableValue = table.getModel().getValueAt(row, col);
if ( tableValue instanceof Pair ) {
Pair<String,T> selectedComponent = (Pair<String,T>) tableValue;
return selectedComponent.getV();
}
return null;
}
protected String getSelectedConfigurationId() {
int col = table.convertColumnIndexToModel(table.getSelectedColumn());
int row = table.convertRowIndexToModel(table.getSelectedRow());
if ( row < 0 || col < 0 || row >= table.getRowCount() || col >= table.getColumnCount() ) {
return null;
}
Object tableValue = table.getModel().getValueAt(row, col);
if ( tableValue instanceof Pair ) {
Pair<String,T> selectedComponent = (Pair<String,T>) tableValue;
return selectedComponent.getU();
} else if ( tableValue instanceof String ){
return (String) tableValue;
}
return null;
}
protected abstract class FlightConfigurableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
JLabel label = (JLabel) c;
column = table.convertColumnIndexToModel(column);
switch (column) {
case 0: {
label.setText(descriptor.format(rocket, (String) value));
regular(label);
setSelected(label, table, isSelected, hasFocus);
return label;
}
default: {
Pair<String, T> v = (Pair<String, T>) value;
if(v!=null){
String id = v.getU();
T component = v.getV();
label = format(component, id, label );
}
setSelected(label, table, isSelected, hasFocus);
return label;
}
}
}
private final void setSelected( JComponent c, JTable table, boolean isSelected, boolean hasFocus ) {
c.setOpaque(true);
if ( isSelected) {
c.setBackground(table.getSelectionBackground());
} else {
c.setBackground(table.getBackground());
}
Border b = null;
if ( hasFocus ) {
if (isSelected) {
b = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
} else {
b = UIManager.getBorder("Table.focusCellHighligtBorder");
}
} else {
b = new EmptyBorder(1,1,1,1);
}
c.setBorder(b);
}
protected final void shaded(JLabel label) {
GUIUtil.changeFontStyle(label, Font.ITALIC);
label.setForeground(Color.GRAY);
}
protected final void regular(JLabel label) {
GUIUtil.changeFontStyle(label, Font.PLAIN);
label.setForeground(Color.BLACK);
}
protected abstract JLabel format( T component, String configId, JLabel label );
}
}