/* * LanguageTableModel.java * Copyright 2010 (C) Connor Petty <cpmeister@users.sourceforge.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Created on May 11, 2010, 2:01:06 PM */ package pcgen.gui2.tabs.summary; import java.awt.CardLayout; import java.awt.Component; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractCellEditor; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import pcgen.facade.core.CharacterFacade; import pcgen.facade.core.LanguageChooserFacade; import pcgen.facade.core.LanguageFacade; import pcgen.facade.util.event.ListEvent; import pcgen.facade.util.event.ListListener; import pcgen.facade.util.ListFacade; import pcgen.gui2.UIPropertyContext; import pcgen.gui2.dialog.LanguageChooserDialog; import pcgen.gui2.tabs.Utilities; import pcgen.gui2.tools.Utility; import pcgen.gui2.util.SignIcon.Sign; import pcgen.gui2.util.table.TableCellUtilities; import pcgen.system.LanguageBundle; public class LanguageTableModel extends AbstractTableModel implements ListListener<LanguageFacade> { private ListFacade<LanguageFacade> languages; private ListFacade<LanguageChooserFacade> choosers; private CharacterFacade character; private JTable table; private int dirtyRow = -1; private MouseListener mouseListener = new MouseListener(); private Renderer renderer = new Renderer(); private Editor editor = new Editor(); public LanguageTableModel(CharacterFacade character, JTable table) { super(); this.table = table; this.character = character; languages = character.getLanguages(); choosers = character.getLanguageChoosers(); languages.addListListener(this); } public static void initializeTable(JTable table) { table.setCellSelectionEnabled(false); table.setRowSelectionAllowed(false); table.setColumnSelectionAllowed(false); table.setFocusable(false); table.setRowHeight(21); table.getTableHeader().setReorderingAllowed(false); } public void install() { table.addMouseListener(mouseListener); table.addMouseMotionListener(mouseListener); table.setModel(this); table.setDefaultRenderer(Object.class, renderer); table.setDefaultEditor(Object.class, editor); } public void uninstall() { table.removeMouseListener(mouseListener); table.removeMouseMotionListener(mouseListener); dirtyRow = -1; } @Override public int getRowCount() { return languages.getSize() + choosers.getSize(); } @Override public String getColumnName(int column) { return LanguageBundle.getString("in_sumLanguages"); //$NON-NLS-1$ } @Override public int getColumnCount() { return 1; } @Override public Object getValueAt(int rowIndex, int columnIndex) { if (rowIndex < languages.getSize()) { return languages.getElementAt(rowIndex); } else { return choosers.getElementAt(rowIndex - languages.getSize()); } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { if (rowIndex < languages.getSize() && !character.isRemovable(languages.getElementAt(rowIndex))) { return false; } return true; } @Override public void elementAdded(ListEvent<LanguageFacade> e) { fireTableRowsInserted(e.getIndex(), e.getIndex()); editor.cancelCellEditing(); } @Override public void elementRemoved(ListEvent<LanguageFacade> e) { fireTableRowsDeleted(e.getIndex(), e.getIndex()); editor.cancelCellEditing(); } @Override public void elementsChanged(ListEvent<LanguageFacade> e) { fireTableDataChanged(); editor.cancelCellEditing(); } @Override public void elementModified(ListEvent<LanguageFacade> e) { fireTableRowsUpdated(e.getIndex(), e.getIndex()); } private class MouseListener extends MouseAdapter { @Override public void mouseExited(MouseEvent e) { table.repaint(table.getCellRect(dirtyRow, 0, true)); dirtyRow = -1; } @Override public void mouseMoved(MouseEvent e) { int row = table.rowAtPoint(e.getPoint()); if (row != dirtyRow) { editor.cancelCellEditing(); table.repaint(table.getCellRect(dirtyRow, 0, true)); dirtyRow = row; table.repaint(table.getCellRect(dirtyRow, 0, true)); } } } private class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener { private static final String ADD_ID = "Add"; private static final String REMOVE_ID = "Remove"; private JPanel cellPanel = new JPanel(); private CardLayout cardLayout = new CardLayout(); private JLabel addLabel = new JLabel(); private JLabel cellLabel = new JLabel(); public Editor() { cellPanel.setLayout(cardLayout); cellPanel.setOpaque(true); JButton addButton = Utilities.createSignButton(Sign.Plus); JButton removeButton = Utilities.createSignButton(Sign.Minus); addButton.setActionCommand(ADD_ID); removeButton.setActionCommand(REMOVE_ID); addButton.setFocusable(false); removeButton.setFocusable(false); addButton.addActionListener(this); removeButton.addActionListener(this); Box box = Box.createHorizontalBox(); box.add(Box.createHorizontalGlue()); box.add(addLabel); box.add(Box.createHorizontalStrut(3)); box.add(addButton); box.add(Box.createHorizontalStrut(2)); cellPanel.add(box, ADD_ID); box = Box.createHorizontalBox(); box.add(Box.createHorizontalStrut(3)); box.add(cellLabel); box.add(Box.createHorizontalGlue()); box.add(removeButton); box.add(Box.createHorizontalStrut(2)); cellPanel.add(box, REMOVE_ID); } @Override public Component getTableCellEditorComponent(JTable jTable, Object value, boolean isSelected, int row, int column) { TableCellUtilities.setToRowBackground(cellPanel, jTable, row); if (row >= languages.getSize()) { addLabel.setForeground(jTable.getForeground()); addLabel.setFont(jTable.getFont()); addLabel.setText(((LanguageChooserFacade) value).getName()); cardLayout.show(cellPanel, ADD_ID); } else { cellLabel.setForeground(jTable.getForeground()); cellLabel.setFont(jTable.getFont()); cellLabel.setText(value.toString()); cardLayout.show(cellPanel, REMOVE_ID); } return cellPanel; } @Override public void actionPerformed(ActionEvent e) { if (ADD_ID.equals(e.getActionCommand())) { Frame frame = JOptionPane.getFrameForComponent(table); LanguageChooserFacade chooser = choosers.getElementAt( table.getEditingRow() - languages.getSize()); LanguageChooserDialog dialog = new LanguageChooserDialog(frame, chooser); Utility.setComponentRelativeLocation(frame, dialog); dialog.setVisible(true); } else { LanguageFacade lang = (LanguageFacade) getValueAt(table.getEditingRow(), 0); character.removeLanguage(lang); } cancelCellEditing(); } @Override public Object getCellEditorValue() { return null; } } private class Renderer extends JPanel implements TableCellRenderer { private static final String ADD_ID = "Add"; private static final String REMOVE_ID = "Remove"; private CardLayout cardLayout = new CardLayout(); //private JPanel cellPanel = new JPanel(); private JLabel cellLabel = new JLabel(); private JButton addButton = Utilities.createSignButton(Sign.Plus); private JButton removeButton = Utilities.createSignButton(Sign.Minus); private JLabel addLabel = new JLabel(); public Renderer() { setLayout(cardLayout); Box box = Box.createHorizontalBox(); box.add(Box.createHorizontalStrut(3)); box.add(cellLabel); box.add(Box.createHorizontalGlue()); box.add(removeButton); box.add(Box.createHorizontalStrut(2)); add(box, REMOVE_ID); box = Box.createHorizontalBox(); box.add(Box.createHorizontalGlue()); box.add(addLabel); box.add(Box.createHorizontalStrut(3)); box.add(addButton); box.add(Box.createHorizontalStrut(2)); add(box, ADD_ID); } @Override public Component getTableCellRendererComponent(JTable jTable, Object value, boolean isSelected, boolean hasFocus, int row, int column) { TableCellUtilities.setToRowBackground(this, jTable, row); if (row < languages.getSize()) { boolean automatic = value instanceof LanguageFacade && character.isAutomatic((LanguageFacade) value); boolean removable = value instanceof LanguageFacade && character.isRemovable((LanguageFacade) value); if (automatic) { cellLabel.setForeground(UIPropertyContext.getAutomaticColor()); } else { cellLabel.setForeground(jTable.getForeground()); } cellLabel.setText(value.toString()); cellLabel.setFont(jTable.getFont()); removeButton.setEnabled(dirtyRow == row); removeButton.setVisible(removable); cardLayout.show(this, REMOVE_ID); } else { addLabel.setText(((LanguageChooserFacade) value).getName()); addLabel.setFont(jTable.getFont()); addLabel.setForeground(jTable.getForeground()); cardLayout.show(this, ADD_ID); } return this; } } }