
Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
> The problem is that you will have to
> implement your own //TableModel// that can talk to the manager by
> providing the following.
A minor correction. You need a subclass of JTable to fire the
UndoableEditEvents, because they also need to report about
representation issues, like a change of a selection. And the TableModel
is not aware of such changes. But the TableModel is still part of the
game. A customized TableModel will likely need to support the customized
JTable for some types of edits, too.
/Thomas

Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
Thomas Weidenfeller schrieb:
>> Hello!
>>
[quoted text clipped - 21 lines]
> and related edits (e.g. collapsing multiple single character deletions
> into a "word deleted" edit).
Agreed with one exception: to me, e) makes little sense with respect to
tables. Either a cell (or row in the case of additions and deletions)
was updated or it wasn't.
> All this is not much fun to implement.
But it's straight-forward if one implements a Decorator for ordinary
TableModels. Of course, in this case row additions/deletions get lost,
but I'd consider it as a starting point.
To substantiate my babbling, I've written a small implementation,
perhaps someone has some use for it ;) [should I GPL it now? - SCNR]
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.undo.*;
public class UndoableTableModel extends AbstractTableModel
implements TableModelListener {
private TableModel delegate;
private UndoableEditSupport support = new UndoableEditSupport();
public UndoableTableModel( TableModel delegate ) {
setDelegate( delegate );
}
public void setDelegate( TableModel delegate ) {
if ( this.delegate != null )
this.delegate.removeTableModelListener( this );
this.delegate = delegate;
if ( this.delegate != null )
this.delegate.addTableModelListener( this );
fireTableStructureChanged();
}
public Class<?> getColumnClass( int columnIndex ) {
return delegate.getColumnClass( columnIndex );
}
public int getColumnCount() {
return delegate.getColumnCount();
}
public String getColumnName( int columnIndex ) {
return delegate.getColumnName( columnIndex );
}
public int getRowCount() {
return delegate.getRowCount();
}
public Object getValueAt( int rowIndex, int columnIndex ) {
return delegate.getValueAt( rowIndex, columnIndex );
}
public boolean isCellEditable( int rowIndex, int columnIndex ) {
return delegate.isCellEditable( rowIndex, columnIndex );
}
public void setValueAt( Object aValue,
int rowIndex, int columnIndex ) {
Object oldValue = delegate.getValueAt( rowIndex, columnIndex );
delegate.setValueAt( aValue, rowIndex, columnIndex );
Object newValue = delegate.getValueAt( rowIndex, columnIndex );
fireChangeEdit( rowIndex, columnIndex, oldValue, newValue );
}
public void addUndoableEditListener( UndoableEditListener l ) {
support.addUndoableEditListener( l );
}
public void removeUndoableEditListener( UndoableEditListener l ) {
support.removeUndoableEditListener( l );
}
public void tableChanged( TableModelEvent e ) {
TableModelEvent newEvent = new TableModelEvent( this,
e.getFirstRow(), e.getLastRow(), e.getColumn(),
e.getType() );
fireTableChanged( newEvent );
}
protected void fireChangeEdit( int row, int col, Object oldValue,
Object newValue ) {
UndoableEdit edit = new TableChangeEdit(row, col,
oldValue, newValue);
support.beginUpdate();
support.postEdit( edit );
support.endUpdate();
}
private class TableChangeEdit extends AbstractUndoableEdit {
private int columnIndex;
private int rowIndex;
private Object oldValue;
private Object newValue;
public TableChangeEdit( int rowIndex, int columnIndex,
Object oldValue, Object newValue ) {
this.columnIndex = columnIndex;
this.rowIndex = rowIndex;
this.oldValue = oldValue;
this.newValue = newValue;
}
public void undo() {
super.undo();
delegate.setValueAt( oldValue, rowIndex, columnIndex );
}
public void redo() {
super.redo();
delegate.setValueAt( newValue, rowIndex, columnIndex );
}
}
}
Bye
Michael
Thomas Weidenfeller - 17 Nov 2006 08:34 GMT
> Thomas Weidenfeller schrieb:
>> e) Make the //UndoableEdit// a //CompoundEdit// for sequences of
[quoted text clipped - 4 lines]
> tables. Either a cell (or row in the case of additions and deletions)
> was updated or it wasn't.
I was assuming table cells with editable text, where you probably want
to undo/redo text changes while you edit, but also undo/redo minor
operations like selection, deselection, and adjustments of selection.
E.g. what should happen if the user has edited some change in a cell,
the change has not been applied to the model, but the user invokes undo
(e.g. via a keyboard shortcut)? Here it seems to me that the JTable (and
not the TableModel) should have delivered change notifications for the
text edits to the undo manager. And these would be candidates for
/CompoundEdit/. Getting that right, however, would mean to have a close
look at the JTable's cell editing behavior. I am to lazy to do that :-).
> To substantiate my babbling, I've written a small implementation,
> perhaps someone has some use for it ;) [should I GPL it now? - SCNR]
Ask a lawyer :-)
/Thomas

Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
Michael Rauscher - 17 Nov 2006 21:57 GMT
Thomas Weidenfeller schrieb:
>> Thomas Weidenfeller schrieb:
>>> e) Make the //UndoableEdit// a //CompoundEdit// for sequences of
[quoted text clipped - 8 lines]
> to undo/redo text changes while you edit, but also undo/redo minor
> operations like selection, deselection, and adjustments of selection.
Your point.
>> To substantiate my babbling, I've written a small implementation,
>> perhaps someone has some use for it ;) [should I GPL it now? - SCNR]
>
> Ask a lawyer :-)
Perhaps Sun could lend me one :)
Bye
Michael
Thomas Weidenfeller - 20 Nov 2006 08:21 GMT
> Thomas Weidenfeller schrieb:
>> Ask a lawyer :-)
>
> Perhaps Sun could lend me one :)
You do not want a Sun lawyer. These are the guys who write 70+ words of
gibberish in a single sentence, as can be witnessed in the JCP agreement.
/Thomas

Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
Michael Rauscher - 20 Nov 2006 09:07 GMT
Thomas Weidenfeller schrieb:
>> Thomas Weidenfeller schrieb:
>>> Ask a lawyer :-)
[quoted text clipped - 3 lines]
> You do not want a Sun lawyer. These are the guys who write 70+ words of
> gibberish in a single sentence, as can be witnessed in the JCP agreement.
Hmm and I thought Sun's 190 lawyers had to read each of Java SE's 6 Mio.
lines of code [1] - ROTFL.
Bye
Michael
[1] http://www.eweek.com/article2/0,1895,2055770,00.asp
Thomas Weidenfeller - 20 Nov 2006 09:37 GMT
> Hmm and I thought Sun's 190 lawyers had to read each of Java SE's 6 Mio.
> lines of code [1] - ROTFL.
[...]
> [1] http://www.eweek.com/article2/0,1895,2055770,00.asp
Nice. That is ample punishment for lawyers, assuming they really do it
line-by-line. And I guess no one of the developers had told them about
text search tools :-)
/Thomas

Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq