+++ /dev/null
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package net.sourceforge.phpdt.internal.corext.textmanipulation;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.text.DocumentEvent;
-import org.eclipse.jface.text.IDocumentListener;
-
-/**
- * A helper class to arrange <code>TextEdit</code>s into a tree to optimize
- * their execution.
- */
-/* package */abstract class TextEditNode {
-
- /* package */TextEditNode fParent;
-
- /* package */List fChildren;
-
- /* package */TextEdit fEdit;
-
- /* package */static class DefaultNode extends TextEditNode {
- public DefaultNode(TextEdit edit) {
- super(edit);
- }
- }
-
- /* package */static class RootNode extends TextEditNode {
- private int fUndoIndex;
-
- public RootNode(int length) {
- super(new NopTextEdit(new TextRange(0, length)));
- fEdit.isSynthetic = true;
- }
-
- public boolean covers(TextEditNode node) {
- return true;
- }
-
- public UndoMemento performDo(TextBuffer buffer, IProgressMonitor pm)
- throws CoreException {
- DoRangeUpdater updater = new DoRangeUpdater();
- UndoMemento undo = new UndoMemento(TextBufferEditor.UNDO);
- try {
- buffer.registerUpdater(updater);
- performDo(buffer, updater, undo, pm);
- } finally {
- buffer.unregisterUpdater(updater);
- updater.setActiveNode(null);
- }
- return undo;
- }
-
- public UndoMemento performUndo(TextBuffer buffer, IProgressMonitor pm)
- throws CoreException {
- UndoRangeUpdater updater = new UndoRangeUpdater(this);
- UndoMemento undo = new UndoMemento(TextBufferEditor.REDO);
- try {
- buffer.registerUpdater(updater);
- performUndo(buffer, updater, undo, pm);
- } finally {
- buffer.unregisterUpdater(updater);
- updater.setActiveNode(null);
- }
- return undo;
- }
-
- protected void setUndoIndex(int index) {
- fUndoIndex = index;
- }
-
- protected int getUndoIndex() {
- return fUndoIndex;
- }
- }
-
- /* package */abstract static class AbstractMoveNode extends TextEditNode {
- private int state;
-
- private int fTargetIndex;
-
- private int fSourceIndex;
-
- private List fAffectedChildren;
-
- public AbstractMoveNode(TextEdit edit) {
- super(edit);
- reset();
- }
-
- protected abstract TextRange getSourceRange();
-
- protected abstract TextRange getTargetRange();
-
- protected abstract boolean isUpMove();
-
- protected boolean isDownMove() {
- return !isUpMove();
- }
-
- public boolean isMove() {
- return true;
- }
-
- protected void checkRange(DocumentEvent event) {
- TextRange range = getChildRange();
- int eventOffset = event.getOffset();
- int eventLength = event.getLength();
- int eventEnd = eventOffset + eventLength - 1;
- // "Edit changes text that lies outside its defined range"
- // Assert.isTrue(range.fOffset <= eventOffset && eventEnd <=
- // range.getInclusiveEnd());
- }
-
- protected boolean activeNodeChanged(int delta) {
- TextRange targetRange = getTargetRange();
- TextRange sourceRange = getSourceRange();
- switch (state) {
- case 0: // the move delete
- init();
- // Assert.isTrue(Math.abs(delta) == sourceRange.fLength);
- if (isUpMove()) {
- updateOffset(fAffectedChildren, delta);
- targetRange.fOffset += delta;
- }
- sourceRange.fLength = 0;
- state = 1;
- break;
- case 1:
- TextEditNode target = (TextEditNode) fParent.fChildren
- .get(fTargetIndex);
- TextEditNode source = (TextEditNode) fParent.fChildren
- .get(fSourceIndex);
- updateOffset(source.fChildren, targetRange.fOffset
- - sourceRange.fOffset);
- target.fChildren = source.fChildren;
- if (target.fChildren != null) {
- for (Iterator iter = target.fChildren.iterator(); iter
- .hasNext();) {
- ((TextEditNode) iter.next()).fParent = target;
- }
- }
- source.fChildren = null;
- if (isDownMove()) {
- updateOffset(fAffectedChildren, delta);
- sourceRange.fOffset += delta;
- }
- targetRange.fLength = delta;
- reset();
- break;
- }
- return true;
- }
-
- private static void updateOffset(List nodes, int delta) {
- if (nodes == null)
- return;
- for (int i = nodes.size() - 1; i >= 0; i--) {
- TextEditNode node = (TextEditNode) nodes.get(i);
- TextRange range = node.getTextRange();
- range.fOffset += delta;
- updateOffset(node.fChildren, delta);
- }
- }
-
- private void init() {
- TextRange source = getSourceRange();
- TextRange target = getTargetRange();
- List children = fParent.fChildren;
- for (int i = children.size() - 1; i >= 0; i--) {
- TextEditNode child = (TextEditNode) children.get(i);
- TextRange range = child.fEdit.getTextRange();
- if (range == source)
- fSourceIndex = i;
- else if (range == target)
- fTargetIndex = i;
- }
- int start = Math.min(fTargetIndex, fSourceIndex);
- int end = Math.max(fTargetIndex, fSourceIndex);
- fAffectedChildren = new ArrayList(3);
- for (int i = start + 1; i < end; i++) {
- fAffectedChildren.add(children.get(i));
- }
- }
-
- private void reset() {
- state = 0;
- fSourceIndex = -1;
- fTargetIndex = -1;
- }
- }
-
- /* package */static class MoveNode extends AbstractMoveNode {
- public MoveNode(TextEdit edit) {
- super(edit);
- }
-
- protected TextRange getChildRange() {
- return ((MoveTextEdit) fEdit).getChildRange();
- }
-
- protected TextRange getSourceRange() {
- return ((MoveTextEdit) fEdit).getSourceRange();
- }
-
- protected TextRange getTargetRange() {
- return ((MoveTextEdit) fEdit).getTargetRange();
- }
-
- protected boolean isUpMove() {
- return ((MoveTextEdit) fEdit).isUpMove();
- }
-
- public boolean isMovePartner(TextEditNode other) {
- if (!(other instanceof TargetMarkNode))
- return false;
- return fEdit == ((MoveTextEdit.TargetMark) other.fEdit)
- .getMoveTextEdit();
- }
-
- public boolean covers(TextEditNode node) {
- if (node instanceof TargetMarkNode) {
- MoveTextEdit.TargetMark edit = (MoveTextEdit.TargetMark) node.fEdit;
- if (edit.getMoveTextEdit() == fEdit)
- return false;
- }
- return getParentRange().covers(node.getChildRange());
- }
- }
-
- /* package */static class TargetMarkNode extends AbstractMoveNode {
- public TargetMarkNode(TextEdit edit) {
- super(edit);
- }
-
- protected TextRange getChildRange() {
- return ((MoveTextEdit.TargetMark) fEdit).getMoveTextEdit()
- .getChildRange();
- }
-
- protected TextRange getSourceRange() {
- return ((MoveTextEdit.TargetMark) fEdit).getMoveTextEdit()
- .getSourceRange();
- }
-
- protected TextRange getTargetRange() {
- return ((MoveTextEdit.TargetMark) fEdit).getMoveTextEdit()
- .getTargetRange();
- }
-
- protected boolean isUpMove() {
- return ((MoveTextEdit.TargetMark) fEdit).getMoveTextEdit()
- .isUpMove();
- }
-
- public boolean isMovePartner(TextEditNode other) {
- return ((MoveTextEdit.TargetMark) fEdit).getMoveTextEdit() == other.fEdit;
- }
- }
-
- // ---- Range updating
- // ---------------------------------------------------------------------------
-
- private static abstract class RangeUpdater implements IDocumentListener {
- protected TextEditNode fActiveNode;
-
- public void documentAboutToBeChanged(DocumentEvent event) {
- }
-
- public void setActiveNode(TextEditNode node) {
- fActiveNode = node;
- }
-
- public void updateParents(int delta) {
- TextEditNode node = fActiveNode.fParent;
- while (node != null) {
- node.childNodeChanged(delta);
- node = node.fParent;
- }
- }
-
- public static int getDelta(DocumentEvent event) {
- return (event.getText() == null ? 0 : event.getText().length())
- - event.getLength();
- }
- }
-
- private static class DoRangeUpdater extends RangeUpdater {
- private List fProcessedNodes = new ArrayList(10);
-
- public void setActiveNode(TextEditNode node) {
- if (fActiveNode != null)
- fProcessedNodes.add(fActiveNode);
- super.setActiveNode(node);
- }
-
- public void documentChanged(DocumentEvent event) {
- fActiveNode.checkRange(event);
- int delta = getDelta(event);
- if (!fActiveNode.activeNodeChanged(delta)) {
- for (Iterator iter = fProcessedNodes.iterator(); iter.hasNext();) {
- ((TextEditNode) iter.next()).previousNodeChanged(delta);
- }
- }
- updateParents(delta);
- }
- }
-
- private static class UndoRangeUpdater extends RangeUpdater {
- private RootNode fRootNode;
-
- public UndoRangeUpdater(RootNode root) {
- fRootNode = root;
- }
-
- public void setActiveNode(TextEditNode node) {
- super.setActiveNode(node);
- }
-
- public void documentChanged(DocumentEvent event) {
- fActiveNode.checkRange(event);
- int delta = getDelta(event);
- if (!fActiveNode.activeNodeChanged(delta)) {
- int start = fRootNode.getUndoIndex() + 1;
- List children = fRootNode.fChildren;
- int size = children != null ? children.size() : 0;
- for (int i = start; i < size; i++) {
- updateUndo((TextEditNode) children.get(i), delta);
- }
- }
- updateParents(delta);
- }
-
- private void updateUndo(TextEditNode node, int delta) {
- node.previousNodeChanged(delta);
- List children = node.fChildren;
- int size = children != null ? children.size() : 0;
- for (int i = 0; i < size; i++) {
- updateUndo((TextEditNode) children.get(i), delta);
- }
- }
- }
-
- // ---- Creating instances
- // ---------------------------------------------------------------------------
-
- static TextEditNode create(TextEdit edit) {
- if (edit instanceof MoveTextEdit)
- return new MoveNode(edit);
- if (edit instanceof MoveTextEdit.TargetMark)
- return new TargetMarkNode(edit);
- return new DefaultNode(edit);
- }
-
- static RootNode createRoot(int length) {
- return new RootNode(length);
- }
-
- private TextEditNode(TextEdit edit) {
- fEdit = edit;
- }
-
- // ---- Adding children
- // ---------------------------------------------------------------------------
-
- protected void add(TextEditNode node) {
- if (fChildren == null) {
- fChildren = new ArrayList(1);
- node.fParent = this;
- fChildren.add(node);
- return;
- }
- // Optimize using binary search
- for (Iterator iter = fChildren.iterator(); iter.hasNext();) {
- TextEditNode child = (TextEditNode) iter.next();
- if (child.covers(node)) {
- child.add(node);
- return;
- }
- }
- for (int i = 0; i < fChildren.size();) {
- TextEditNode child = (TextEditNode) fChildren.get(i);
- if (node.covers(child)) {
- fChildren.remove(i);
- node.add(child);
- } else {
- i++;
- }
- }
- node.fParent = this;
- fChildren.add(node);
- }
-
- public boolean covers(TextEditNode node) {
- return false;
- }
-
- // ---- Accessing
- // --------------------------------------------------------------------------------------
-
- protected RootNode getRoot() {
- TextEditNode candidate = this;
- while (candidate.fParent != null)
- candidate = candidate.fParent;
- return (RootNode) candidate;
- }
-
- // ---- Query interface
- // --------------------------------------------------------------------------------
-
- protected boolean isSynthetic() {
- return fEdit.isSynthetic;
- }
-
- public boolean isMove() {
- return false;
- }
-
- // ---- Accessing Ranges
- // ------------------------------------------------------------------------------
-
- protected void checkRange(DocumentEvent event) {
- TextRange range = getTextRange();
- int eventOffset = event.getOffset();
- int eventLength = event.getLength();
- int eventEnd = eventOffset + eventLength - 1;
- // "Edit changes text that lies outside its defined range"
- // Assert.isTrue(range.fOffset <= eventOffset && eventEnd <=
- // range.getInclusiveEnd());
- }
-
- protected TextRange getTextRange() {
- return fEdit.getTextRange();
- }
-
- protected TextRange getChildRange() {
- return getTextRange();
- }
-
- protected TextRange getParentRange() {
- return getTextRange();
- }
-
- public boolean validate(int bufferLength) {
- if (fChildren == null)
- return true;
- // Only Moves and Nops can be parents
- if (!(fEdit instanceof MoveTextEdit || fEdit instanceof NopTextEdit))
- return false;
- TextRange lastRange = null;
- for (Iterator iter = fChildren.iterator(); iter.hasNext();) {
- TextEditNode node = (TextEditNode) iter.next();
- if (!node.validate(bufferLength))
- return false;
- TextRange range = node.fEdit.getTextRange();
- if (!range.isValid()
- || range.fOffset + range.fLength > bufferLength)
- return false;
- if (lastRange != null
- && !(range.isInsertionPointAt(lastRange.fOffset) || range
- .liesBehind(lastRange)))
- return false;
- lastRange = range;
- }
- return true;
- }
-
- // ---- Updating
- // ----------------------------------------------------------------------------------------
-
- protected boolean activeNodeChanged(int delta) {
- TextRange range = getTextRange();
- range.fLength += delta;
- // we didn't adjust any processed nodes.
- return false;
- }
-
- protected void previousNodeChanged(int delta) {
- TextRange range = getTextRange();
- range.fOffset += delta;
- }
-
- protected void childNodeChanged(int delta) {
- getTextRange().fLength += delta;
- }
-
- // ---- Do it
- // ---------------------------------------------------------------------------------------------
-
- protected void performDo(TextBuffer buffer, RangeUpdater updater,
- UndoMemento undo, IProgressMonitor pm) throws CoreException {
- int size = fChildren != null ? fChildren.size() : 0;
- for (int i = size - 1; i >= 0; i--) {
- TextEditNode child = (TextEditNode) fChildren.get(i);
- child.performDo(buffer, updater, undo, pm);
- }
- updater.setActiveNode(this);
- if (isSynthetic())
- fEdit.perform(buffer);
- else
- undo.add(fEdit.perform(buffer));
- pm.worked(1);
- }
-
- public void performedDo() {
- int size = fChildren != null ? fChildren.size() : 0;
- for (int i = size - 1; i >= 0; i--) {
- TextEditNode child = (TextEditNode) fChildren.get(i);
- child.performedDo();
- }
- fEdit.performed();
- }
-
- // ---- Undo it
- // -------------------------------------------------------------------------------------------
-
- protected void performUndo(TextBuffer buffer, RangeUpdater updater,
- UndoMemento undo, IProgressMonitor pm) throws CoreException {
- int size = fChildren != null ? fChildren.size() : 0;
- for (int i = 0; i < size; i++) {
- setUndoIndex(i);
- TextEditNode child = (TextEditNode) fChildren.get(i);
- child.performUndo(buffer, updater, undo, pm);
- }
- updater.setActiveNode(this);
- if (isSynthetic())
- fEdit.perform(buffer);
- else
- undo.add(fEdit.perform(buffer));
- pm.worked(1);
- }
-
- protected void setUndoIndex(int index) {
- }
-
- public void performedUndo() {
- int size = fChildren != null ? fChildren.size() : 0;
- for (int i = 0; i < size; i++) {
- TextEditNode child = (TextEditNode) fChildren.get(i);
- child.performedUndo();
- }
- fEdit.performed();
- }
-
- // protected void createUndoList(List list) {
- // int size= fChildren != null ? fChildren.size() : 0;
- // for (int i= 0; i < size; i++) {
- // TextEditNode child= (TextEditNode)fChildren.get(i);
- // child.createUndoList(list);
- // }
- // list.add(this);
- // }
-}