| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * 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 com.intellij.openapi.editor.impl.event; |
| |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.editor.event.DocumentEvent; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.util.diff.Diff; |
| import com.intellij.util.diff.FilesTooBigForDiffException; |
| import org.jetbrains.annotations.NotNull; |
| |
| public class DocumentEventImpl extends DocumentEvent { |
| private final int myOffset; |
| private final CharSequence myOldString; |
| private final int myOldLength; |
| private final CharSequence myNewString; |
| private final int myNewLength; |
| |
| private boolean isOnlyOneLineChangedCalculated = false; |
| private boolean isOnlyOneLineChanged; |
| |
| private boolean isStartOldIndexCalculated = false; |
| private int myStartOldIndex; |
| |
| private final long myOldTimeStamp; |
| private final boolean myIsWholeDocReplaced; |
| private Diff.Change myChange; |
| private static final Diff.Change TOO_BIG_FILE = new Diff.Change(0, 0, 0, 0, null) { |
| }; |
| |
| private int myOptimizedLineShift = -1; |
| private boolean myOptimizedLineShiftCalculated; |
| |
| private int myOptimizedOldLineShift = -1; |
| private boolean myOptimizedOldLineShiftCalculated; |
| |
| public DocumentEventImpl(@NotNull Document document, |
| int offset, |
| CharSequence oldString, |
| CharSequence newString, |
| long oldTimeStamp, |
| boolean wholeTextReplaced) { |
| super(document); |
| myOffset = offset; |
| |
| myOldString = oldString == null ? "" : oldString; |
| myOldLength = myOldString.length(); |
| |
| myNewString = newString == null ? "" : newString; |
| myNewLength = myNewString.length(); |
| |
| myOldTimeStamp = oldTimeStamp; |
| |
| if (getDocument().getTextLength() == 0) { |
| isOnlyOneLineChangedCalculated = true; |
| isOnlyOneLineChanged = false; |
| myIsWholeDocReplaced = false; |
| } |
| else { |
| myIsWholeDocReplaced = wholeTextReplaced; |
| } |
| } |
| |
| @Override |
| public int getOffset() { |
| return myOffset; |
| } |
| |
| @Override |
| public int getOldLength() { |
| return myOldLength; |
| } |
| |
| @Override |
| public int getNewLength() { |
| return myNewLength; |
| } |
| |
| @NotNull |
| @Override |
| public CharSequence getOldFragment() { |
| return myOldString; |
| } |
| |
| @NotNull |
| @Override |
| public CharSequence getNewFragment() { |
| return myNewString; |
| } |
| |
| @Override |
| @NotNull |
| public Document getDocument() { |
| return (Document)getSource(); |
| } |
| |
| public int getStartOldIndex() { |
| if (isStartOldIndexCalculated) return myStartOldIndex; |
| |
| isStartOldIndexCalculated = true; |
| myStartOldIndex = getDocument().getLineNumber(myOffset); |
| return myStartOldIndex; |
| } |
| |
| public boolean isOnlyOneLineChanged() { |
| if (isOnlyOneLineChangedCalculated) return isOnlyOneLineChanged; |
| |
| isOnlyOneLineChangedCalculated = true; |
| isOnlyOneLineChanged = true; |
| |
| for (int i = 0; i < myOldString.length(); i++) { |
| if (myOldString.charAt(i) == '\n') { |
| isOnlyOneLineChanged = false; |
| break; |
| } |
| } |
| |
| if (isOnlyOneLineChanged) { |
| for (int i = 0; i < myNewString.length(); i++) { |
| if (myNewString.charAt(i) == '\n') { |
| isOnlyOneLineChanged = false; |
| break; |
| } |
| } |
| } |
| return isOnlyOneLineChanged; |
| } |
| |
| @Override |
| public long getOldTimeStamp() { |
| return myOldTimeStamp; |
| } |
| |
| @SuppressWarnings({"HardCodedStringLiteral"}) |
| public String toString() { |
| return "DocumentEventImpl[myOffset=" + myOffset + ", myOldLength=" + myOldLength + ", myNewLength=" + myNewLength + |
| ", myOldString='" + myOldString + "', myNewString='" + myNewString + "']" + (isWholeTextReplaced() ? " Whole." : "."); |
| } |
| |
| @Override |
| public boolean isWholeTextReplaced() { |
| return myIsWholeDocReplaced; |
| } |
| |
| public int translateLineViaDiff(int line) throws FilesTooBigForDiffException { |
| Diff.Change change = reBuildDiffIfNeeded(); |
| if (change == null) return line; |
| |
| int newLine = line; |
| |
| while (change != null) { |
| if (line < change.line0) break; |
| if (line >= change.line0 + change.deleted) { |
| newLine += change.inserted - change.deleted; |
| } |
| else { |
| int delta = Math.min(change.inserted, line - change.line0); |
| newLine = change.line1 + delta; |
| break; |
| } |
| |
| change = change.link; |
| } |
| |
| return newLine; |
| } |
| |
| public int translateLineViaDiffStrict(int line) throws FilesTooBigForDiffException { |
| Diff.Change change = reBuildDiffIfNeeded(); |
| if (change == null) return line; |
| return Diff.translateLine(change, line); |
| } |
| |
| private Diff.Change reBuildDiffIfNeeded() throws FilesTooBigForDiffException { |
| if (myChange == TOO_BIG_FILE) throw new FilesTooBigForDiffException(0); |
| if (myChange == null) { |
| try { |
| myChange = Diff.buildChanges(myOldString, myNewString); |
| } |
| catch (FilesTooBigForDiffException e) { |
| myChange = TOO_BIG_FILE; |
| throw e; |
| } |
| } |
| return myChange; |
| } |
| |
| public int getOptimizedLineShift() { |
| if (!myOptimizedLineShiftCalculated) { |
| myOptimizedLineShiftCalculated = true; |
| |
| if (myOldLength == 0) { |
| int lineShift = StringUtil.countNewLines(myNewString); |
| |
| myOptimizedLineShift = lineShift == 0 ? -1 : lineShift; |
| } |
| } |
| return myOptimizedLineShift; |
| } |
| |
| public int getOptimizedOldLineShift() { |
| if (!myOptimizedOldLineShiftCalculated) { |
| myOptimizedOldLineShiftCalculated = true; |
| |
| if (myNewLength == 0) { |
| int lineShift = StringUtil.countNewLines(myOldString); |
| |
| myOptimizedOldLineShift = lineShift == 0 ? -1 : lineShift; |
| } |
| } |
| return myOptimizedOldLineShift; |
| } |
| } |