blob: b0c60bcd0bd1b2b712e8fbb67743dba3a0b71214 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.text.projection;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.Position;
/**
* The position updater used to adapt the segments of a projection document to
* changes of the master document. Depending on the flags set on a segment, a
* segment is either extended to shifted if an insertion happens at a segment's
* offset. The last segment is extended if an insert operation happens at the
* end of the segment.
*
* @since 3.0
*/
class SegmentUpdater extends DefaultPositionUpdater {
private Segment fNextSegment= null;
private boolean fIsProjectionChange= false;
/**
* Creates the segment updater for the given category.
*
* @param segmentCategory the position category used for managing the segments of a projection document
*/
protected SegmentUpdater(String segmentCategory) {
super(segmentCategory);
}
@Override
public void update(DocumentEvent event) {
Assert.isTrue(event instanceof ProjectionDocumentEvent);
fIsProjectionChange= ((ProjectionDocumentEvent) event).getChangeType() == ProjectionDocumentEvent.PROJECTION_CHANGE;
try {
Position[] category= event.getDocument().getPositions(getCategory());
fOffset= event.getOffset();
fLength= event.getLength();
fReplaceLength= (event.getText() == null ? 0 : event.getText().length());
fDocument= event.getDocument();
for (int i= 0; i < category.length; i++) {
fPosition= category[i];
Assert.isTrue(fPosition instanceof Segment);
if (i < category.length - 1)
fNextSegment= (Segment) category[i + 1];
else
fNextSegment= null;
fOriginalPosition.offset= fPosition.offset;
fOriginalPosition.length= fPosition.length;
if (notDeleted())
adaptToReplace();
}
} catch (BadPositionCategoryException x) {
// do nothing
}
}
@Override
protected void adaptToInsert() {
Segment segment= (Segment) fPosition;
int myStart= segment.offset;
int myEnd= segment.offset + segment.length - (segment.isMarkedForStretch || fNextSegment == null || isAffectingReplace() ? 0 : 1);
myEnd= Math.max(myStart, myEnd);
int yoursStart= fOffset;
try {
if (myEnd < yoursStart)
return;
if (segment.isMarkedForStretch) {
Assert.isTrue(fIsProjectionChange);
segment.isMarkedForShift= false;
if (fNextSegment != null) {
fNextSegment.isMarkedForShift= true;
fNextSegment.isMarkedForStretch= false;
}
}
if (fLength <= 0) {
if (myStart < (yoursStart + (segment.isMarkedForShift ? 0 : 1)))
fPosition.length += fReplaceLength;
else
fPosition.offset += fReplaceLength;
} else {
if (myStart <= yoursStart && fOriginalPosition.offset <= yoursStart)
fPosition.length += fReplaceLength;
else
fPosition.offset += fReplaceLength;
}
} finally {
segment.clearMark();
}
}
}