All Downloads are FREE. Search and download functionalities are using the official Maven repository.

groovy.ui.text.TextUndoManager Maven / Gradle / Ivy

There is a newer version: 3.9
Show newest version
/*
 * Copyright 2003-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package groovy.ui.text;

import java.beans.PropertyChangeListener;

import javax.swing.event.SwingPropertyChangeSupport;
import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;

/**
 * To use this, simply drop this as an UndoableEditListener into your document,
 * and then create actions to call undo/redo as needed (checking can undo/redo
 * first, of course).
 *
 * @author Evan "Hippy" Slatis
 */
public class TextUndoManager extends UndoManager {

    private SwingPropertyChangeSupport propChangeSupport =
            new SwingPropertyChangeSupport(this);

    private StructuredEdit compoundEdit = new StructuredEdit();

    private long firstModified;

    private UndoableEdit modificationMarker = editToBeUndone();

    /**
     * Creates a new instance of TextUndoManager.
     */
    public TextUndoManager() {
    }

    public void addPropertyChangeListener(PropertyChangeListener pcl) {
        propChangeSupport.addPropertyChangeListener(pcl);
    }

    public void die() {
        boolean undoable = canUndo();
        super.die();
        firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
    }

    public void discardAllEdits() {
        boolean undoable = canUndo();
        boolean redoable = canRedo();

        boolean changed = hasChanged();
        super.discardAllEdits();
        modificationMarker = editToBeUndone();

        firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
        firePropertyChangeEvent(UndoManager.UndoName, redoable, canRedo());
    }

    protected void firePropertyChangeEvent(String name,
                                           boolean oldValue,
                                           boolean newValue) {
        propChangeSupport.firePropertyChange(name, oldValue, newValue);
    }

    public boolean hasChanged() {
        return modificationMarker != editToBeUndone();
    }

    public void redo() throws javax.swing.undo.CannotRedoException {
        compoundEdit.end();

        if (firstModified == 0) {
            firstModified = ((StructuredEdit) editToBeRedone()).editedTime();
        }

        boolean undoable = canUndo();

        boolean changed = hasChanged();
        super.redo();

        firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
    }

    protected void redoTo(UndoableEdit edit) {
        compoundEdit.end();

        if (firstModified == 0) {
            firstModified = ((StructuredEdit) editToBeRedone()).editedTime();
        }

        boolean undoable = canUndo();

        boolean changed = hasChanged();
        super.redoTo(edit);

        firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());

    }

    public void removePropertyChangeListener(PropertyChangeListener pcl) {
        propChangeSupport.removePropertyChangeListener(pcl);
    }

    public void reset() {
        boolean changed = modificationMarker != editToBeUndone();
        if (changed) {
            modificationMarker = editToBeUndone();
        }
    }

    protected void trimEdits(int from, int to) {
        boolean undoable = canUndo();
        boolean redoable = canRedo();

        boolean changed = hasChanged();
        super.trimEdits(from, to);

        firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
        firePropertyChangeEvent(UndoManager.RedoName, redoable, canRedo());
    }

    public void undo() throws javax.swing.undo.CannotUndoException {
        compoundEdit.end();

        UndoableEdit edit = editToBeUndone();
        if (((StructuredEdit) editToBeUndone()).editedTime() ==
                firstModified) {
            firstModified = 0;
        } else if (firstModified == 0) {
            firstModified = ((StructuredEdit) editToBeUndone()).editedTime();
        }

        boolean redoable = canRedo();
        boolean changed = hasChanged();
        super.undo();
        firePropertyChangeEvent(UndoManager.RedoName, redoable, canRedo());
    }

    public void undoableEditHappened(UndoableEditEvent uee) {
        UndoableEdit edit = uee.getEdit();
        boolean undoable = canUndo();

        long editTime = System.currentTimeMillis();

        if (firstModified == 0 ||
                editTime - compoundEdit.editedTime() > 700) {
            compoundEdit.end();
            compoundEdit = new StructuredEdit();
        }
        compoundEdit.addEdit(edit);

        firstModified = firstModified == 0 ?
                compoundEdit.editedTime() : firstModified;

        if (lastEdit() != compoundEdit) {
            boolean changed = hasChanged();
            addEdit(compoundEdit);
            firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
        }

    }

    private class StructuredEdit extends CompoundEdit {

        private long editedTime;

        public boolean addEdit(UndoableEdit edit) {
            boolean result = super.addEdit(edit);
            if (result && editedTime == 0) {
                editedTime = System.currentTimeMillis();
            }
            return result;
        }

        public boolean canUndo() {
            return edits.size() > 0;
        }

        protected long editedTime() {
            return editedTime;
        }

        public boolean isInProgress() {
            return false;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy