ca.odell.glazedlists.swing.UndoSupport Maven / Gradle / Ivy
Show all versions of glazedlists_java15 Show documentation
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FunctionList;
import ca.odell.glazedlists.UndoRedoSupport;
import javax.swing.undo.*;
import javax.swing.*;
/**
* This class adapts the generic {@link UndoRedoSupport} provided by Glazed
* Lists for specific use with Swing's native {@link UndoManager}. Each
* {@link UndoRedoSupport.Edit} produced by Glazed List's
* {@link UndoRedoSupport} is adapted to Swing's {@link UndoableEdit} interface
* and then {@link UndoManager#addEdit added} into the given UndoManager.
*
* Fine grain control of the {@link UndoableEdit} that is ultimately added
* to the {@link UndoableEdit} can be achieved by using
* {@link #install(UndoManager, EventList, FunctionList.Function) this} install
* method and specifying a custom Function.
*
* @author James Lemieux
*/
public final class UndoSupport {
/** the manager of all undoable edits for the entire Swing application */
private UndoManager undoManager;
/** glazed List's undo/redo support which is being adapted to Swing's native undo/redo framework */
private UndoRedoSupport undoRedoSupport;
/** a listener that transforms GL-style edits into Swing-style edits using the {@link #editAdapter} and adds them to the {@link #undoManager} */
private UndoRedoSupport.Listener undoSupportHandler = new UndoSupportHandler();
/** the function which transforms GL-style edits into Swing-style edits */
private FunctionList.Function editAdapter;
/**
* The private constructor creates an UndoSupport that provides undo/redo
* capabilties for changes to the given source
. Whenever
* changes occur to the source
, a GL-style
* {@link UndoRedoSupport.Edit} is produced, which is then transformed into
* a Swing-style {@link UndoableEdit} and ultimately added to the given
* undoManager
.
*
* @param undoManager the manager of all undoable edits for the entire Swing application
* @param source the EventList to watch for undoable edits
* @param editAdapter the function that converts GL-style edits into Swing-style edits
*/
private UndoSupport(UndoManager undoManager, EventList source, FunctionList.Function editAdapter) {
this.undoManager = undoManager;
this.undoRedoSupport = UndoRedoSupport.install(source);
this.editAdapter = editAdapter;
// begin watching the GL undoRedoSupport for undoable edits
this.undoRedoSupport.addUndoSupportListener(undoSupportHandler);
}
/**
* Installs support for undoing/redoing edits on the given
* source
. Specifically, {@link UndoableEdit}s are added to the
* undoManager
each time the source
changes.
* {@link UndoableEdit#undo Undoing} and {@link UndoableEdit#redo redoing}
* these edits will unapply/reapply the corresponding changes to the
* source
.
*
* This method uses a default strategy for mapping the GL-style edits
* to {@link UndoableEdit}s.
*
* @param undoManager the manager of all undoable edits for the entire Swing application
* @param source the EventList to watch for undoable edits
* @return an instance of the support class providing undo/redo edit features
*
* @throws IllegalStateException if this method is called from any Thread
* other than the Swing Event Dispatch Thread
*/
public static UndoSupport install(UndoManager undoManager, EventList source) {
return install(undoManager, source, new DefaultEditAdapter());
}
/**
* Installs support for undoing/redoing edits on the given
* source
. Specifically, {@link UndoableEdit}s are added to the
* undoManager
each time the source
changes.
* {@link UndoableEdit#undo Undoing} and {@link UndoableEdit#redo redoing}
* these edits will unapply/reapply the corresponding changes to the
* source
.
*
* This method uses the given editAdapter
for mapping the
* GL-style edits to {@link UndoableEdit}s.
*
* @param undoManager the manager of all undoable edits for the entire Swing application
* @param source the EventList to watch for undoable edits
* @param editAdapter the function that converts GL-style edits into Swing-style edits
* @return an instance of the support class providing undo/redo edit features
*
* @throws IllegalStateException if this method is called from any Thread
* other than the Swing Event Dispatch Thread
*/
public static UndoSupport install(UndoManager undoManager, EventList source, FunctionList.Function editAdapter) {
checkAccessThread();
return new UndoSupport(undoManager, source, editAdapter);
}
/**
* This method removes undo/redo support from the {@link EventList} it was
* installed on. This method is useful when the {@link EventList} must
* outlive the undo/redo support itself. Calling this method will make
* this support object available for garbage collection independently of
* the {@link EventList} of items.
*
* @throws IllegalStateException if this method is called from any Thread
* other than the Swing Event Dispatch Thread
*/
public void uninstall() {
checkAccessThread();
undoRedoSupport.removeUndoSupportListener(undoSupportHandler);
undoRedoSupport.uninstall();
undoSupportHandler = null;
undoRedoSupport = null;
undoManager = null;
editAdapter = null;
}
/**
* A convenience method to ensure {@link UndoSupport} is being accessed
* from the Event Dispatch Thread.
*/
private static void checkAccessThread() {
if (!SwingUtilities.isEventDispatchThread())
throw new IllegalStateException("UndoRedoSupport must be accessed from the Swing Event Dispatch Thread, but was called on Thread \"" + Thread.currentThread().getName() + "\"");
}
/**
* Listens for GL edits and responds by transforming them into Swing edits
* and posting them to the given UndoManager.
*/
private class UndoSupportHandler implements UndoRedoSupport.Listener {
public void undoableEditHappened(UndoRedoSupport.Edit edit) {
undoManager.addEdit(editAdapter.evaluate(edit));
}
}
/**
* The default strategy for transforming GL edits into Swing edits.
*/
private static class DefaultEditAdapter implements FunctionList.Function {
public UndoableEdit evaluate(UndoRedoSupport.Edit edit) {
return new EditAdapter(edit);
}
private static class EditAdapter extends AbstractUndoableEdit {
private final UndoRedoSupport.Edit edit;
public EditAdapter(UndoRedoSupport.Edit edit) {
this.edit = edit;
}
@Override
public void undo() { edit.undo(); }
@Override
public boolean canUndo() { return edit.canUndo(); }
@Override
public void redo() { edit.redo(); }
@Override
public boolean canRedo() { return edit.canRedo(); }
}
}
}