package org.openflexo.swing;
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 javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
/**
* The ButtonColumn class provides a renderer and an editor that looks like a JButton. The renderer and editor will then be used for a
* specified column in the table. The TableModel will contain the String to be displayed on the button.
*
* The button can be invoked by a mouse click or by pressing the space bar when the cell has focus. Optionally a mnemonic can be set to
* invoke the button. When the button is invoked the provided Action is invoked. The source of the Action will be the table. The action
* command will contain the model row number of the button that was clicked.
*
*/
public class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener {
private Action action;
private int mnemonic;
private Border originalBorder;
private Border focusBorder;
private JButton renderButton;
private JButton editButton;
private Object editorValue;
private JTable table;
private int row;
private boolean isButtonColumnEditor;
/**
* Create the ButtonColumn to be used as a renderer and editor. The renderer and editor will automatically be installed on the
* TableColumn of the specified column.
*
* @param action
* the Action to be invoked when the button is invoked
*/
public ButtonColumn(Action action) {
this.action = action;
renderButton = new JButton();
editButton = new JButton();
editButton.setFocusPainted(false);
editButton.addActionListener(this);
originalBorder = editButton.getBorder();
}
@Override
protected void fireEditingCanceled() {
super.fireEditingCanceled();
setTable(null);
row = -1;
}
@Override
protected void fireEditingStopped() {
super.fireEditingStopped();
setTable(null);
row = -1;
}
/**
* Get foreground color of the button when the cell has focus
*
* @return the foreground color
*/
public Border getFocusBorder() {
return focusBorder;
}
/**
* The foreground color of the button when the cell has focus
*
* @param focusBorder
* the foreground color
*/
public void setFocusBorder(Border focusBorder) {
this.focusBorder = focusBorder;
editButton.setBorder(focusBorder);
}
public int getMnemonic() {
return mnemonic;
}
/**
* The mnemonic to activate the button when the cell has focus
*
* @param mnemonic
* the mnemonic
*/
public void setMnemonic(int mnemonic) {
this.mnemonic = mnemonic;
renderButton.setMnemonic(mnemonic);
editButton.setMnemonic(mnemonic);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
setTable(table);
if (value == null) {
editButton.setText("");
editButton.setIcon(null);
} else if (value instanceof Icon) {
editButton.setText("");
editButton.setIcon((Icon) value);
} else {
editButton.setText(value.toString());
editButton.setIcon(null);
}
this.editorValue = value;
return editButton;
}
private void setTable(JTable table) {
if (this.table != null) {
this.table.removeMouseListener(this);
}
this.table = table;
if (this.table != null) {
this.table.addMouseListener(this);
}
}
@Override
public Object getCellEditorValue() {
return editorValue;
}
//
// Implement TableCellRenderer interface
//
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
renderButton.setForeground(table.getSelectionForeground());
renderButton.setBackground(table.getSelectionBackground());
} else {
renderButton.setForeground(table.getForeground());
renderButton.setBackground(UIManager.getColor("Button.background"));
}
if (hasFocus) {
renderButton.setBorder(focusBorder);
} else {
renderButton.setBorder(originalBorder);
}
// renderButton.setText( (value == null) ? "" : value.toString() );
if (value == null) {
renderButton.setText("");
renderButton.setIcon(null);
} else if (value instanceof Icon) {
renderButton.setText("");
renderButton.setIcon((Icon) value);
} else {
renderButton.setText(value.toString());
renderButton.setIcon(null);
}
return renderButton;
}
//
// Implement ActionListener interface
//
/*
* The button has been pressed. Stop editing and invoke the custom Action
*/
@Override
public void actionPerformed(ActionEvent e) {
int i = table.convertRowIndexToModel(table.getEditingRow());
fireEditingStopped();
row = i;
// Invoke the Action
try {
ActionEvent event = new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, "" + row);
action.actionPerformed(event);
} finally {
row = -1;
}
}
public int getClickedRow() {
return row;
}
@Override
public void mousePressed(MouseEvent e) {
if (table.isEditing() && table.getCellEditor() == this) {
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) {
}
}