package mekhq.gui.model; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.ResourceBundle; import java.util.Set; import javax.swing.AbstractCellEditor; import javax.swing.Action; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import megamek.common.util.EncodeControl; import mekhq.campaign.parts.PartInUse; public class PartsInUseTableModel extends DataTableModel { private static final long serialVersionUID = -7166100476703184175L; private static final DecimalFormat FORMATTER = new DecimalFormat(); static { FORMATTER.setMaximumFractionDigits(3); } private static final String EMPTY_CELL = ""; //$NON-NLS-1$ public final static int COL_PART = 0; public final static int COL_IN_USE = 1; public final static int COL_STORED = 2; public final static int COL_TONNAGE = 3; public final static int COL_IN_TRANSFER = 4; public final static int COL_COST = 5; public final static int COL_BUTTON_BUY = 6; public final static int COL_BUTTON_BUY_BULK = 7; public final static int COL_BUTTON_GMADD = 8; public final static int COL_BUTTON_GMADD_BULK = 9; private ResourceBundle resourceMap; public PartsInUseTableModel () { resourceMap = ResourceBundle.getBundle("mekhq.resources.PartsInUseTableModel", new EncodeControl()); //$NON-NLS-1$ data = new ArrayList<PartInUse>(); } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { return COL_BUTTON_GMADD_BULK + 1; } @Override public String getColumnName(int column) { switch(column) { case COL_PART: return resourceMap.getString("part.heading"); //$NON-NLS-1$ case COL_IN_USE: return resourceMap.getString("inUse.heading"); //$NON-NLS-1$ case COL_STORED: return resourceMap.getString("stored.heading"); //$NON-NLS-1$ case COL_TONNAGE: return resourceMap.getString("storedTonnage.heading"); //$NON-NLS-1$ case COL_IN_TRANSFER: return resourceMap.getString("ordered.heading"); //$NON-NLS-1$ case COL_COST: return resourceMap.getString("cost.heading"); //$NON-NLS-1$ default: return EMPTY_CELL; } } @Override public Object getValueAt(int row, int column) { PartInUse piu = getPartInUse(row); switch(column) { case COL_PART: return piu.getDescription(); case COL_IN_USE: return FORMATTER.format(piu.getUseCount()); case COL_STORED: return (piu.getStoreCount() > 0) ? FORMATTER.format(piu.getStoreCount()) : EMPTY_CELL; case COL_TONNAGE: return (piu.getStoreTonnage() > 0) ? FORMATTER.format(piu.getStoreTonnage()) : EMPTY_CELL; case COL_IN_TRANSFER: if( piu.getTransferCount() > 0 && piu.getPlannedCount() <= 0 ) { return FORMATTER.format(piu.getTransferCount()); } else if( piu.getPlannedCount() > 0 ) { return String.format("%s [+%s]", //$NON-NLS-1$ FORMATTER.format(piu.getTransferCount()), FORMATTER.format(piu.getPlannedCount())); } else { return EMPTY_CELL; } case COL_COST: return FORMATTER.format(piu.getCost()); case COL_BUTTON_BUY: return resourceMap.getString("buy.text"); //$NON-NLS-1$ case COL_BUTTON_BUY_BULK: return resourceMap.getString("buyInBulk.text"); //$NON-NLS-1$ case COL_BUTTON_GMADD: return resourceMap.getString("add.text"); //$NON-NLS-1$ case COL_BUTTON_GMADD_BULK: return resourceMap.getString("addInBulk.text"); //$NON-NLS-1$ default: return EMPTY_CELL; } } @Override public Class<?> getColumnClass(int c) { return String.class; } @Override public boolean isCellEditable(int row, int col) { switch(col) { case COL_BUTTON_BUY: case COL_BUTTON_BUY_BULK: case COL_BUTTON_GMADD: case COL_BUTTON_GMADD_BULK: return true; default: return false; } } public void setData(Set<PartInUse> data) { setData(new ArrayList<PartInUse>(data)); } @SuppressWarnings("unchecked") public void updateRow(int row, PartInUse piu) { ((ArrayList<PartInUse>) data).set(row, piu); fireTableRowsUpdated(row, row); } public PartInUse getPartInUse(int row) { if((row < 0) || (row >= data.size())) { return null; } return (PartInUse) data.get(row); } public boolean isBuyable(int row) { return (row >= 0) && (row < data.size()) && (null != ((PartInUse) data.get(row)).getPartToBuy()); } public int getAlignment(int column) { switch(column) { case COL_PART: return SwingConstants.LEFT; case COL_IN_USE: case COL_STORED: case COL_TONNAGE: case COL_IN_TRANSFER: case COL_COST: return SwingConstants.RIGHT; default: return SwingConstants.CENTER; } } public int getPreferredWidth(int column) { switch(column) { case COL_PART: return 300; case COL_IN_USE: case COL_STORED: case COL_TONNAGE: case COL_IN_TRANSFER: case COL_COST: return 20; case COL_BUTTON_BUY: return 50; case COL_BUTTON_GMADD: return 70; case COL_BUTTON_BUY_BULK: return 80; default: return 100; } } public boolean hasConstantWidth(int col) { switch(col) { case COL_BUTTON_BUY: case COL_BUTTON_BUY_BULK: case COL_BUTTON_GMADD: case COL_BUTTON_GMADD_BULK: return true; default: return false; } } public int getWidth(int col) { switch(col) { case COL_BUTTON_BUY: case COL_BUTTON_BUY_BULK: case COL_BUTTON_GMADD: case COL_BUTTON_GMADD_BULK: // Calculate from button width, respecting style JButton btn = new JButton(getValueAt(0, col).toString()); return btn.getPreferredSize().width; default: return Integer.MAX_VALUE; } } public PartsInUseTableModel.Renderer getRenderer() { return new PartsInUseTableModel.Renderer(); } public static class Renderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1403740113670268591L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); setOpaque(true); setHorizontalAlignment(((PartsInUseTableModel)table.getModel()).getAlignment(column)); setForeground(Color.BLACK); if (isSelected) { setBackground(Color.DARK_GRAY); setForeground(Color.WHITE); } else { // tiger stripes if (row % 2 == 1) { setBackground(new Color(230,230,230)); } else { setBackground(Color.WHITE); } } return this; } } public static class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener { private static final long serialVersionUID = 5632710519408125751L; private JTable table; private Action action; private Border originalBorder; private Border focusBorder; private JButton renderButton; private JButton editButton; private Object editorValue; private boolean isButtonColumnEditor; private boolean enabled; public ButtonColumn(JTable table, Action action, int column) { this.table = table; this.action = action; renderButton = new JButton(); editButton = new JButton(); editButton.setFocusPainted(false); editButton.addActionListener(this); originalBorder = editButton.getBorder(); enabled = true; TableColumnModel columnModel = table.getColumnModel(); columnModel.getColumn(column).setCellRenderer(this); columnModel.getColumn(column).setCellEditor(this); table.addMouseListener(this); } public Border getFocusBorder() { return focusBorder; } public void setFocusBorder(Border focusBorder) { this.focusBorder = focusBorder; editButton.setBorder(focusBorder); } public void setEnabled(boolean enabled) { this.enabled = enabled; editButton.setEnabled(enabled); renderButton.setEnabled(enabled); } @Override public Object getCellEditorValue() { return editorValue; } @Override public void mousePressed(MouseEvent e) { if(table.isEditing() && (this == table.getCellEditor())) { isButtonColumnEditor = true; } } @Override public void mouseReleased(MouseEvent e) { if(isButtonColumnEditor && table.isEditing()) { table.getCellEditor().stopCellEditing(); } isButtonColumnEditor = false; } @Override public void mouseClicked(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void actionPerformed(ActionEvent e) { int row = table.convertRowIndexToModel(table.getEditingRow()); fireEditingStopped(); // Invoke the Action ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row); //$NON-NLS-1$ action.actionPerformed(event); } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { boolean buyable = ((PartsInUseTableModel) table.getModel()).isBuyable(table.getRowSorter().convertRowIndexToModel(row)); if(value == null) { editButton.setText(EMPTY_CELL); editButton.setIcon(null); } else if(value instanceof Icon) { editButton.setText(EMPTY_CELL); editButton.setIcon((Icon)value); } else { editButton.setText(value.toString()); editButton.setIcon(null); } editButton.setEnabled(enabled && buyable); this.editorValue = value; return editButton; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { boolean buyable = ((PartsInUseTableModel) table.getModel()).isBuyable(table.getRowSorter().convertRowIndexToModel(row)); if(isSelected && enabled && buyable) { renderButton.setForeground(table.getSelectionForeground()); renderButton.setBackground(table.getSelectionBackground()); } else { renderButton.setForeground(table.getForeground()); renderButton.setBackground(UIManager.getColor("Button.background")); //$NON-NLS-1$ } if(hasFocus && enabled && buyable) { renderButton.setBorder(focusBorder); } else { renderButton.setBorder(originalBorder); } if(value == null) { renderButton.setText(EMPTY_CELL); renderButton.setIcon(null); } else if (value instanceof Icon) { renderButton.setText(EMPTY_CELL); renderButton.setIcon((Icon)value); } else { renderButton.setText(value.toString()); renderButton.setIcon(null); } renderButton.setEnabled(enabled && buyable); return renderButton; } } }