Index: javax/swing/DefaultCellEditor.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/DefaultCellEditor.java,v retrieving revision 1.10 diff -u -r1.10 DefaultCellEditor.java --- javax/swing/DefaultCellEditor.java 27 Jul 2005 12:41:33 -0000 1.10 +++ javax/swing/DefaultCellEditor.java 9 Aug 2005 15:52:59 -0000 @@ -43,9 +43,13 @@ 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.JTable; +import javax.swing.JTextField; +import javax.swing.event.CellEditorListener; import javax.swing.table.TableCellEditor; import javax.swing.tree.TreeCellEditor; @@ -91,8 +95,10 @@ * * @param event TODO */ - public void setValue(Object event) + public void setValue(Object value) { + // TODO: should be setting the value in the editorComp + this.value = value; } /** @@ -102,7 +108,8 @@ */ public Object getCellEditorValue() { - return null; // TODO + // TODO: should be getting the updated value from the editorComp + return value; } // getCellEditorValue() /** @@ -114,7 +121,11 @@ */ public boolean isCellEditable(EventObject event) { - return false; // TODO + if (!(event instanceof MouseEvent)) + return true; + + //Todo: if the right number of clicks has occured, return true; + return false; } // isCellEditable() /** @@ -126,7 +137,8 @@ */ public boolean shouldSelectCell(EventObject event) { - return false; // TODO + // return true to indicate that the editing cell may be selected + return true; } // shouldSelectCell() /** @@ -136,7 +148,8 @@ */ public boolean stopCellEditing() { - return false; // TODO + fireEditingStopped(); + return true; } // stopCellEditing() /** @@ -144,7 +157,7 @@ */ public void cancelCellEditing() { - // TODO + fireEditingCanceled(); } // cancelCellEditing() /** @@ -156,7 +169,8 @@ */ public boolean startCellEditing(EventObject event) { - return false; // TODO + // return true to indicate that editing has begun + return true; } // startCellEditing() /** @@ -166,7 +180,7 @@ */ public void actionPerformed(ActionEvent event) { - // TODO + stopCellEditing(); } // actionPerformed() /** @@ -176,9 +190,23 @@ */ public void itemStateChanged(ItemEvent event) { - // TODO + stopCellEditing(); } // itemStateChanged() + void fireEditingStopped() + { + CellEditorListener[] listeners = getCellEditorListeners(); + for (int index = 0; index < listeners.length; index++) + listeners[index].editingStopped(changeEvent); + + } + + void fireEditingCanceled() + { + CellEditorListener[] listeners = getCellEditorListeners(); + for (int index = 0; index < listeners.length; index++) + listeners[index].editingCanceled(changeEvent); + } } // EditorDelegate /** @@ -203,7 +231,8 @@ */ public DefaultCellEditor(JTextField textfield) { - // TODO + editorComponent = textfield; + clickCountToStart = 2; } // DefaultCellEditor() /** @@ -213,7 +242,8 @@ */ public DefaultCellEditor(JCheckBox checkbox) { - // TODO + editorComponent = checkbox; + clickCountToStart = 1; } // DefaultCellEditor() /** @@ -223,7 +253,8 @@ */ public DefaultCellEditor(JComboBox combobox) { - // TODO + editorComponent = combobox; + clickCountToStart = 1; } // DefaultCellEditor() /** @@ -233,7 +264,7 @@ */ public Component getComponent() { - return null; // TODO + return editorComponent; } // getComponent() /** @@ -243,7 +274,7 @@ */ public int getClickCountToStart() { - return 0; // TODO + return clickCountToStart; } // getClickCountToStart() /** @@ -253,7 +284,7 @@ */ public void setClickCountToStart(int count) { - // TODO + clickCountToStart = count; } // setClickCountToStart() /** @@ -263,7 +294,7 @@ */ public Object getCellEditorValue() { - return null; // TODO + return delegate.getCellEditorValue(); } // getCellEditorValue() /** @@ -275,7 +306,7 @@ */ public boolean isCellEditable(EventObject event) { - return false; // TODO + return delegate.isCellEditable(event); } // isCellEditable() /** @@ -287,7 +318,7 @@ */ public boolean shouldSelectCell(EventObject event) { - return false; // TODO + return delegate.shouldSelectCell(event); } // shouldSelectCell() /** @@ -297,7 +328,7 @@ */ public boolean stopCellEditing() { - return false; // TODO + return delegate.stopCellEditing(); } // stopCellEditing() /** @@ -305,7 +336,7 @@ */ public void cancelCellEditing() { - // TODO + delegate.cancelCellEditing(); } // cancelCellEditing() /** @@ -339,10 +370,30 @@ * * @returns Component */ - public Component getTableCellEditorComponent(JTable tree, Object value, + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - return null; // TODO + // NOTE: as specified by Sun, we don't call new() everytime, we return + // editorComponent on each call to getTableCellEditorComponent or + // getTreeCellEditorComponent. However, currently JTextFields have a + // problem with getting rid of old text, so without calling new() there + // are some strange results. If you edit more than one cell in the table + // text from previously edited cells may unexpectedly show up in the + // cell you are currently editing. This will be fixed automatically + // when JTextField is fixed. + if (editorComponent instanceof JTextField) + { + ((JTextField)editorComponent).setText(value.toString()); + delegate = new EditorDelegate(); + ((JTextField)editorComponent).addActionListener(delegate); + } + else + { + // TODO + } + return editorComponent; } // getTableCellEditorComponent() + + } Index: javax/swing/JTable.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/JTable.java,v retrieving revision 1.38 diff -u -r1.38 JTable.java --- javax/swing/JTable.java 2 Aug 2005 19:25:34 -0000 1.38 +++ javax/swing/JTable.java 9 Aug 2005 15:52:59 -0000 @@ -43,9 +43,12 @@ import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.text.DateFormat; import java.text.NumberFormat; import java.util.Date; +import java.util.EventObject; import java.util.Hashtable; import java.util.Vector; @@ -69,6 +72,7 @@ import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; +import javax.swing.text.Caret; public class JTable extends JComponent implements TableModelListener, Scrollable, TableColumnModelListener, @@ -351,6 +355,7 @@ */ protected transient Component editorComp; + /** * Whether or not the table should automatically compute a matching * address@hidden TableColumnModel} and assign it to the address@hidden #columnModel} @@ -555,7 +560,21 @@ */ protected JTableHeader tableHeader; - + /** + * The row of the cell being edited. + */ + int rowBeingEdited = -1; + + /** + * The column of the cell being edited. + */ + int columnBeingEdited = -1; + + /** + * The action listener for the editor's Timer. + */ + Timer editorTimer = new EditorUpdateTimer(); + /** * Creates a new JTable instance. */ @@ -673,6 +692,51 @@ this(new DefaultTableModel(data, columnNames)); } + /** + * The timer that updates the editor component. + */ + private class EditorUpdateTimer + extends Timer + implements ActionListener + { + /** + * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds. + */ + public EditorUpdateTimer() + { + super(500, null); + addActionListener(this); + } + + /** + * Lets the caret blink and repaints the table. + */ + public void actionPerformed(ActionEvent ev) + { + Caret c = ((JTextField)JTable.this.editorComp).getCaret(); + if (c != null) + c.setVisible(!c.isVisible()); + JTable.this.repaint(); + } + + /** + * Updates the blink delay according to the current caret. + */ + public void update() + { + stop(); + Caret c = ((JTextField)JTable.this.editorComp).getCaret(); + if (c != null) + { + setDelay(c.getBlinkRate()); + if (((JTextField)JTable.this.editorComp).isEditable()) + start(); + else + c.setVisible(false); + } + } + } + public void addColumn(TableColumn column) { if (column.getHeaderValue() == null) @@ -779,6 +843,21 @@ public void editingStopped (ChangeEvent event) { + if (rowBeingEdited > -1 && columnBeingEdited > -1) + { + if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField) + { + remove((Component)getValueAt(rowBeingEdited, columnBeingEdited)); + setValueAt(((JTextField)editorComp).getText(), + rowBeingEdited, columnBeingEdited); + } + rowBeingEdited = -1; + columnBeingEdited = -1; + } + editorTimer.stop(); + editorComp = null; + cellEditor = null; + requestFocusInWindow(false); repaint(); } @@ -980,7 +1059,7 @@ if (editor == null) editor = getDefaultEditor(dataModel.getColumnClass(column)); - + return editor; } @@ -2116,6 +2195,8 @@ public void setValueAt(Object value, int row, int column) { + if (value instanceof Component) + add((Component)value); dataModel.setValueAt(value, row, convertColumnIndexToModel(column)); } @@ -2206,5 +2287,58 @@ } + } + + /** + * Programmatically starts editing the specified cell. + * + * @param row the row of the cell to edit. + * @param column the column of the cell to edit. + */ + public boolean editCellAt (int row, int column) + { + setCellEditor(getCellEditor(row, column)); + editorComp = prepareEditor(cellEditor, row, column); + cellEditor.addCellEditorListener(this); + rowBeingEdited = row; + columnBeingEdited = column; + setValueAt(editorComp, row, column); + ((JTextField)editorComp).requestFocusInWindow(false); + editorTimer.start(); + return true; + } + + /** + * Programmatically starts editing the specified cell. + * + * @param row the row of the cell to edit. + * @param column the column of the cell to edit. + */ + public boolean editCellAt (int row, int column, EventObject e) + { + return editCellAt(row, column); + } + + /** + * Discards the editor object. + */ + public void removeEditor() + { + editingStopped(new ChangeEvent(this)); + } + + /** + * Prepares the editor by querying for the value and selection state of the + * cell at (row, column). + * + * @param editor the TableCellEditor to set up + * @param row the row of the cell to edit + * @param column the column of the cell to edit + * @return the Component being edited + */ + public Component prepareEditor (TableCellEditor editor, int row, int column) + { + return editor.getTableCellEditorComponent + (this, getValueAt(row, column), isCellSelected(row, column), row, column); } } Index: javax/swing/plaf/basic/BasicTableUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTableUI.java,v retrieving revision 1.19 diff -u -r1.19 BasicTableUI.java --- javax/swing/plaf/basic/BasicTableUI.java 2 Aug 2005 19:25:34 -0000 1.19 +++ javax/swing/plaf/basic/BasicTableUI.java 9 Aug 2005 15:52:59 -0000 @@ -56,10 +56,12 @@ import javax.swing.CellRendererPane; import javax.swing.JComponent; import javax.swing.JTable; +import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; import javax.swing.event.MouseInputListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.TableUI; @@ -393,7 +395,7 @@ } else if (evt.getKeyCode() == KeyEvent.VK_F2) { - // FIXME: Implement "start editing" + table.editCellAt(rowLead,colLead); } else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP) { @@ -592,15 +594,15 @@ (table.getCellRect(rowModel.getLeadSelectionIndex(), colModel.getLeadSelectionIndex(), false)); } - + public void keyReleased(KeyEvent e) { } - + public void keyTyped(KeyEvent e) { } - + /** * Returns the column index of the first visible column. * @@ -718,6 +720,11 @@ } public void mousePressed(MouseEvent e) { + ListSelectionModel rowModel = table.getSelectionModel(); + ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); + int rowLead = rowModel.getLeadSelectionIndex(); + int colLead = colModel.getLeadSelectionIndex(); + begin = new Point(e.getX(), e.getY()); curr = new Point(e.getX(), e.getY()); //if control is pressed and the cell is already selected, deselect it @@ -733,7 +740,12 @@ } else updateSelection(e.isControlDown()); - + + // If we were editing, but the moved to another cell, stop editing + if (rowLead != rowModel.getLeadSelectionIndex() || + colLead != colModel.getLeadSelectionIndex()) + if (table.isEditing()) + table.editingStopped(new ChangeEvent(e)); } public void mouseReleased(MouseEvent e) { @@ -896,6 +908,8 @@ ((JComponent) comp).setBorder(cellBorder); } comp.paint(gfx); + if (comp instanceof JTextField) + ((JTextField)comp).getCaret().paint(gfx); gfx.translate(-x, -y); } y += height; @@ -948,6 +962,5 @@ } gfx.setColor(save); } - } } Index: javax/swing/table/DefaultTableCellRenderer.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/table/DefaultTableCellRenderer.java,v retrieving revision 1.13 diff -u -r1.13 DefaultTableCellRenderer.java --- javax/swing/table/DefaultTableCellRenderer.java 2 Jul 2005 20:32:51 -0000 1.13 +++ javax/swing/table/DefaultTableCellRenderer.java 9 Aug 2005 15:52:59 -0000 @@ -47,6 +47,7 @@ import javax.swing.JTable; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; +import javax.swing.JTextField; /** * Class to display every cells. @@ -123,7 +124,11 @@ int row, int column) { if (value != null) - super.setText(value.toString()); + { + if (value instanceof JTextField) + return new JTextField(((JTextField)value).getText()); + super.setText(value.toString()); + } setOpaque(true);