/*
* Copyright (c) 2010-2016, Sikuli.org, sikulix.com
* Released under the MIT License.
*
*/
package org.sikuli.ide;
import javax.swing.event.DocumentEvent;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;
import java.util.ArrayList;
import org.sikuli.basics.Debug;
class MyCompoundEdit extends CompoundEdit {
boolean isUnDone=false;
public int getLength() {
return edits.size();
}
@Override
public void undo() throws CannotUndoException {
super.undo();
isUnDone=true;
}
@Override
public void redo() throws CannotUndoException {
super.redo();
isUnDone=false;
}
@Override
public boolean canUndo() {
return edits.size()>0 && !isUnDone;
}
@Override
public boolean canRedo() {
return edits.size()>0 && isUnDone;
}
}
public class EditorUndoManager extends AbstractUndoableEdit
implements UndoableEditListener {
private static final String me = "EditorUndoManager: ";
String lastEditName=null;
ArrayList<MyCompoundEdit> edits=new ArrayList<MyCompoundEdit>();
MyCompoundEdit current;
int pointer=-1;
@Override
public void undoableEditHappened(UndoableEditEvent e) {
UndoableEdit edit=e.getEdit();
if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
AbstractDocument.DefaultDocumentEvent event=(AbstractDocument.DefaultDocumentEvent)edit;
int start=event.getOffset();
int len=event.getLength();
Debug.log(9, "undoableEditHappened " + start + "," + len);
boolean isNeedStart=false;
if(event.getType().equals(DocumentEvent.EventType.CHANGE) ||
event.getType().equals(DocumentEvent.EventType.INSERT) ){
try {
String text=event.getDocument().getText(start, len);
if (text.contains("\n"))
isNeedStart=true;
} catch (BadLocationException e1) {
Debug.error(me + "undoableEditHappened: Problem getting text\n%s", e1.getMessage());
}
}
if (current==null) {
isNeedStart=true;
}
else if (lastEditName==null || !lastEditName.equals(edit.getPresentationName())) {
isNeedStart=true;
}
while (pointer<edits.size()-1) {
edits.remove(edits.size()-1);
isNeedStart=true;
}
if (isNeedStart) {
createCompoundEdit();
}
current.addEdit(edit);
lastEditName=edit.getPresentationName();
refreshControls();
}
}
public void createCompoundEdit() {
if (current==null) {
current= new MyCompoundEdit();
}
else if (current.getLength()>0) {
current= new MyCompoundEdit();
}
edits.add(current);
pointer++;
}
@Override
public void undo() throws CannotUndoException {
if (!canUndo()) {
throw new CannotUndoException();
}
MyCompoundEdit u=edits.get(pointer);
u.undo();
pointer--;
refreshControls();
}
@Override
public void redo() throws CannotUndoException {
if (!canRedo()) {
throw new CannotUndoException();
}
pointer++;
MyCompoundEdit u=edits.get(pointer);
u.redo();
refreshControls();
}
@Override
public boolean canUndo() {
return pointer>=0;
}
@Override
public boolean canRedo() {
return edits.size()>0 && pointer<edits.size()-1;
}
public void refreshControls() {
SikuliIDE.getInstance().updateUndoRedoStates();
}
}