001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jface.text.projection;
011:
012: import org.eclipse.core.runtime.Assert;
013:
014: import org.eclipse.jface.text.BadPositionCategoryException;
015: import org.eclipse.jface.text.DefaultPositionUpdater;
016: import org.eclipse.jface.text.DocumentEvent;
017: import org.eclipse.jface.text.Position;
018:
019: /**
020: * The position updater used to adapt the segments of a projection document to
021: * changes of the master document. Depending on the flags set on a segment, a
022: * segment is either extended to shifted if an insertion happens at a segment's
023: * offset. The last segment is extended if an insert operation happens at the
024: * end of the segment.
025: *
026: * @since 3.0
027: */
028: class SegmentUpdater extends DefaultPositionUpdater {
029:
030: private Segment fNextSegment = null;
031: private boolean fIsProjectionChange = false;
032:
033: /**
034: * Creates the segment updater for the given category.
035: *
036: * @param segmentCategory the position category used for managing the segments of a projection document
037: */
038: protected SegmentUpdater(String segmentCategory) {
039: super (segmentCategory);
040: }
041:
042: /*
043: * @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
044: */
045: public void update(DocumentEvent event) {
046:
047: Assert.isTrue(event instanceof ProjectionDocumentEvent);
048: fIsProjectionChange = ((ProjectionDocumentEvent) event)
049: .getChangeType() == ProjectionDocumentEvent.PROJECTION_CHANGE;
050:
051: try {
052:
053: Position[] category = event.getDocument().getPositions(
054: getCategory());
055:
056: fOffset = event.getOffset();
057: fLength = event.getLength();
058: fReplaceLength = (event.getText() == null ? 0 : event
059: .getText().length());
060: fDocument = event.getDocument();
061:
062: for (int i = 0; i < category.length; i++) {
063:
064: fPosition = category[i];
065: Assert.isTrue(fPosition instanceof Segment);
066:
067: if (i < category.length - 1)
068: fNextSegment = (Segment) category[i + 1];
069: else
070: fNextSegment = null;
071:
072: fOriginalPosition.offset = fPosition.offset;
073: fOriginalPosition.length = fPosition.length;
074:
075: if (notDeleted())
076: adaptToReplace();
077:
078: }
079:
080: } catch (BadPositionCategoryException x) {
081: // do nothing
082: }
083: }
084:
085: /*
086: * @see org.eclipse.jface.text.DefaultPositionUpdater#adaptToInsert()
087: */
088: protected void adaptToInsert() {
089:
090: Segment segment = (Segment) fPosition;
091: int myStart = segment.offset;
092: int myEnd = segment.offset
093: + segment.length
094: - (segment.isMarkedForStretch || fNextSegment == null
095: || isAffectingReplace() ? 0 : 1);
096: myEnd = Math.max(myStart, myEnd);
097: int yoursStart = fOffset;
098:
099: try {
100:
101: if (myEnd < yoursStart)
102: return;
103:
104: if (segment.isMarkedForStretch) {
105: Assert.isTrue(fIsProjectionChange);
106: segment.isMarkedForShift = false;
107: if (fNextSegment != null) {
108: fNextSegment.isMarkedForShift = true;
109: fNextSegment.isMarkedForStretch = false;
110: }
111: }
112:
113: if (fLength <= 0) {
114:
115: if (myStart < (yoursStart + (segment.isMarkedForShift ? 0
116: : 1)))
117: fPosition.length += fReplaceLength;
118: else
119: fPosition.offset += fReplaceLength;
120:
121: } else {
122:
123: if (myStart <= yoursStart
124: && fOriginalPosition.offset <= yoursStart)
125: fPosition.length += fReplaceLength;
126: else
127: fPosition.offset += fReplaceLength;
128: }
129:
130: } finally {
131: segment.clearMark();
132: }
133: }
134: }
|