package org.reldb.dbrowser.ui.content.cmd; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; import org.eclipse.swt.custom.ExtendedModifyEvent; import org.eclipse.swt.custom.ExtendedModifyListener; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; /** Provide undo/redo support for a StyledText. */ public class UndoRedo { private static class Capture { private String content; private int caretOffset; private int topIndex; public Capture(StyledText text) { this.content = text.getText(); this.caretOffset = text.getCaretOffset(); this.topIndex = text.getTopIndex(); } public void restore(StyledText text) { text.setText(content); text.setCaretOffset(caretOffset); text.setTopIndex(topIndex); } } private StyledText text; private Vector<Capture> buffer = new Vector<Capture>(); private int currentUndoPoint = -1; private Timer quietTimer = new Timer(); private boolean captured = false; private boolean ignore = false; private void capture() { if (!(buffer.size() > 0 && text.getText().equals(buffer.get(buffer.size() - 1)))) { buffer.add(new Capture(text)); if (buffer.size() > 100) buffer.remove(0); } currentUndoPoint = -1; captured = true; } private void restore() { ignore = true; buffer.get(currentUndoPoint).restore(text); ignore = false; } private ExtendedModifyListener extendedModifyListener = new ExtendedModifyListener() { @Override public void modifyText(ExtendedModifyEvent event) { if (ignore) return; captured = false; currentUndoPoint = -1; quietTimer.cancel(); quietTimer = new Timer(); quietTimer.schedule(new TimerTask() { @Override public void run() { quietTimer.cancel(); Display.getDefault().syncExec(new Runnable() { public void run() { capture(); } }); } }, 250); } }; public UndoRedo(StyledText text) { this.text = text; text.addExtendedModifyListener(extendedModifyListener); } public void undo() { quietTimer.cancel(); if (!captured) capture(); if (currentUndoPoint == 0) return; if (currentUndoPoint < 0) currentUndoPoint = buffer.size() - 1; currentUndoPoint--; if (currentUndoPoint < 0) return; restore(); } public void redo() { quietTimer.cancel(); if (currentUndoPoint == -1 || currentUndoPoint >= buffer.size() - 1) return; currentUndoPoint++; restore(); } public void dispose() { text.removeExtendedModifyListener(extendedModifyListener); } }