#眉標=Java #副標=使用Java Swing輕鬆寫個Undoable程式(3) #大標=javax.swing.text對Undoable的支援 #作者=文/侯捷 ========<程式1>=============================== //in JTextArea public JTextArea(Document doc, String text, int rows, int cols) { super(); this.rows = rows; this.columns = cols; if (doc == null) { doc = createDefaultModel(); } setDocument(doc); ... } protected Document createDefaultModel() { return new PlainDocument(); } //in JTextComponent public void setDocument(Document doc) { Document old = model; ... model = doc; } public PlainDocument() { this(new GapContent()); } =============<程式1 end>=========================== =======<程式2>================================== public abstract class AbstractDocument implements Document, Serializable { ... private Content data; public interface Content { ... } } ==========<程式2 end >================================== =====================<程式3>============= public class MyClass extends JFrame { protected JTextArea textArea = new JTextArea(); protected UndoManager manager = new UndoManager(); ... public MyClass() { //ctor ... textArea.getDocument().addUndoableEditListener( new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent e) { manager.addEdit(e.getEdit()); updateButtons(); //這是自定的method,用來更新按鈕狀態 } }); ... } public static void main(String argv[]) { new MyClass(); } } ======<程式3end>============== ========<程式4>========================= PlainDocument.insertString() AbstractDocument.insertString() AbstractDocument.handleInsertString() GapContent.insertString() new InsertUndo(產生一個UndoableEdit物件) PlainDocument.insertUpdate() AbstractDocument.insertUpdate() AbstractDocument.fireInsertUpdate() AbstractDocument.fireUndoableEditUpdate() //發送 UndoableEditListener.undoableEditHappened() //接收 =============<程式4 end>========================= =========<程式5 GapContent.InsertUndo的詳細定義>========== class InsertUndo extends AbstractUndoableEdit { protected InsertUndo(int offset, int length) { super(); this.offset = offset; this.length = length; } public void undo() throws CannotUndoException { super.undo(); // Get the Positions in the range being removed. posRefs = getPositionsInRange(null, offset, length); string = getString(offset, length); remove(offset, length); } public void redo() throws CannotRedoException { super.redo(); insertString(offset, string); string = null; // Update the Positions that were in the range removed. if(posRefs != null) { updateUndoPositions(posRefs, offset, length); posRefs = null; } } /** Where string was inserted. */ protected int offset; /** Length of string inserted. */ protected int length; /** The string that was inserted. only be valid after undo. */ protected String string; /** An array of instances of UndoPosRef for the Positions in the * range that was removed, valid after undo. */ protected Vector posRefs; } ================<程式5 end>=========================== ========<程式6 GapContent.RemoveUndo的詳細定義。>======== class RemoveUndo extends AbstractUndoableEdit { protected RemoveUndo(int offset, String string) { super(); this.offset = offset; this.string = string; this.length = string.length(); posRefs = getPositionsInRange(null, offset, length); } public void undo() throws CannotUndoException { super.undo(); insertString(offset, string); // Update the Positions that were in the range removed. if(posRefs != null) { updateUndoPositions(posRefs, offset, length); posRefs = null; } string = null; } public void redo() throws CannotRedoException { super.redo(); string = getString(offset, length); // Get the Positions in the range being removed. posRefs = getPositionsInRange(null, offset, length); remove(offset, length); } /** Where the string was removed from. */ protected int offset; /** Length of string removed. */ protected int length; /** The string that was removed. valid when redo is valid. */ protected String string; /** An array of instances of UndoPosRef for the Positions in the * range that was removed, valid before undo. */ protected Vector posRefs; } ======<程式6 end>=========== #中標=運行分析