package org.korsakow.ide.ui.components;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.io.Serializable;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JTextField;
/**
* Copied from javax.swing.DefaultCellEditor
*/
public class DefaultListCellEditor extends AbstractCellEditor
implements ListCellEditor {
//
// Instance Variables
//
/** The Swing component being edited. */
protected JComponent editorComponent;
/**
* The delegate class which handles all methods sent from the
* <code>CellEditor</code>.
*/
protected EditorDelegate delegate;
/**
* An integer specifying the number of clicks needed to start editing.
* Even if <code>clickCountToStart</code> is defined as zero, it
* will not initiate until a click occurs.
*/
protected int clickCountToStart = 1;
//
// Constructors
//
/**
* Constructs a <code>DefaultCellEditor</code> that uses a text field.
*
* @param textField a <code>JTextField</code> object
*/
public DefaultListCellEditor(final JTextField textField) {
editorComponent = textField;
clickCountToStart = 2;
delegate = new EditorDelegate() {
@Override
public void setValue(Object value) {
textField.setText((value != null) ? value.toString() : "");
}
@Override
public Object getCellEditorValue() {
return textField.getText();
}
};
textField.addActionListener(delegate);
}
/**
* Constructs a <code>DefaultCellEditor</code> object that uses a check box.
*
* @param checkBox a <code>JCheckBox</code> object
*/
public DefaultListCellEditor(final JCheckBox checkBox) {
editorComponent = checkBox;
delegate = new EditorDelegate() {
@Override
public void setValue(Object value) {
boolean selected = false;
if (value instanceof Boolean) {
selected = ((Boolean)value).booleanValue();
}
else if (value instanceof String) {
selected = value.equals("true");
}
checkBox.setSelected(selected);
}
@Override
public Object getCellEditorValue() {
return Boolean.valueOf(checkBox.isSelected());
}
};
checkBox.addActionListener(delegate);
// if (DRAG_FIX) {
// checkBox.setRequestFocusEnabled(false);
// }
}
/**
* Constructs a <code>DefaultCellEditor</code> object that uses a
* combo box.
*
* @param comboBox a <code>JComboBox</code> object
*/
public DefaultListCellEditor(final JComboBox comboBox) {
editorComponent = comboBox;
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
delegate = new EditorDelegate() {
@Override
public void setValue(Object value) {
comboBox.setSelectedItem(value);
}
@Override
public Object getCellEditorValue() {
return comboBox.getSelectedItem();
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
MouseEvent e = (MouseEvent)anEvent;
return e.getID() != MouseEvent.MOUSE_DRAGGED;
}
return true;
}
@Override
public boolean stopCellEditing() {
if (comboBox.isEditable()) {
// Commit edited value.
comboBox.actionPerformed(new ActionEvent(
DefaultListCellEditor.this, 0, ""));
}
return super.stopCellEditing();
}
};
comboBox.addActionListener(delegate);
}
/**
* Returns a reference to the editor component.
*
* @return the editor <code>Component</code>
*/
public Component getComponent() {
return editorComponent;
}
//
// Modifying
//
/**
* Specifies the number of clicks needed to start editing.
*
* @param count an int specifying the number of clicks needed to start editing
* @see #getClickCountToStart
*/
public void setClickCountToStart(int count) {
clickCountToStart = count;
}
/**
* Returns the number of clicks needed to start editing.
* @return the number of clicks needed to start editing
*/
public int getClickCountToStart() {
return clickCountToStart;
}
//
// Override the implementations of the superclass, forwarding all methods
// from the CellEditor interface to our delegate.
//
/**
* Forwards the message from the <code>CellEditor</code> to
* the <code>delegate</code>.
* @see EditorDelegate#getCellEditorValue
*/
public Object getCellEditorValue() {
return delegate.getCellEditorValue();
}
/**
* Forwards the message from the <code>CellEditor</code> to
* the <code>delegate</code>.
* @see EditorDelegate#isCellEditable(EventObject)
*/
@Override
public boolean isCellEditable(EventObject anEvent) {
return delegate.isCellEditable(anEvent);
}
/**
* Forwards the message from the <code>CellEditor</code> to
* the <code>delegate</code>.
* @see EditorDelegate#shouldSelectCell(EventObject)
*/
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return delegate.shouldSelectCell(anEvent);
}
/**
* Forwards the message from the <code>CellEditor</code> to
* the <code>delegate</code>.
* @see EditorDelegate#stopCellEditing
*/
@Override
public boolean stopCellEditing() {
return delegate.stopCellEditing();
}
/**
* Forwards the message from the <code>CellEditor</code> to
* the <code>delegate</code>.
* @see EditorDelegate#cancelCellEditing
*/
@Override
public void cancelCellEditing() {
delegate.cancelCellEditing();
}
//
// Implementing the CellEditor Interface
//
/** Implements the <code>TableCellEditor</code> interface. */
public Component getListCellEditorComponent(JList list, Object value,
boolean isSelected,
int row) {
delegate.setValue(value);
return editorComponent;
}
//
// Protected EditorDelegate class
//
/**
* The protected <code>EditorDelegate</code> class.
*/
protected class EditorDelegate implements ActionListener, ItemListener, Serializable {
/** The value of this cell. */
protected Object value;
/**
* Returns the value of this cell.
* @return the value of this cell
*/
public Object getCellEditorValue() {
return value;
}
/**
* Sets the value of this cell.
* @param value the new value of this cell
*/
public void setValue(Object value) {
this.value = value;
}
/**
* Returns true if <code>anEvent</code> is <b>not</b> a
* <code>MouseEvent</code>. Otherwise, it returns true
* if the necessary number of clicks have occurred, and
* returns false otherwise.
*
* @param anEvent the event
* @return true if cell is ready for editing, false otherwise
* @see #setClickCountToStart
* @see #shouldSelectCell
*/
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
}
return true;
}
/**
* Returns true to indicate that the editing cell may
* be selected.
*
* @param anEvent the event
* @return true
* @see #isCellEditable
*/
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
/**
* Returns true to indicate that editing has begun.
*
* @param anEvent the event
*/
public boolean startCellEditing(EventObject anEvent) {
return true;
}
/**
* Stops editing and
* returns true to indicate that editing has stopped.
* This method calls <code>fireEditingStopped</code>.
*
* @return true
*/
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
/**
* Cancels editing. This method calls <code>fireEditingCanceled</code>.
*/
public void cancelCellEditing() {
fireEditingCanceled();
}
/**
* When an action is performed, editing is ended.
* @param e the action event
* @see #stopCellEditing
*/
public void actionPerformed(ActionEvent e) {
DefaultListCellEditor.this.stopCellEditing();
}
/**
* When an item's state changes, editing is ended.
* @param e the action event
* @see #stopCellEditing
*/
public void itemStateChanged(ItemEvent e) {
DefaultListCellEditor.this.stopCellEditing();
}
}
} // End of class JCellEditor