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.ui.internal.texteditor.quickdiff;
011:
012: import java.util.List;
013: import java.util.ListIterator;
014:
015: import org.eclipse.jface.text.BadLocationException;
016: import org.eclipse.jface.text.IDocument;
017: import org.eclipse.jface.text.source.Annotation;
018: import org.eclipse.jface.text.source.ILineDiffInfo;
019:
020: import org.eclipse.ui.internal.texteditor.NLSUtility;
021: import org.eclipse.ui.internal.texteditor.quickdiff.compare.rangedifferencer.RangeDifference;
022:
023: /**
024: * The local implementation of <code>ILineDiffInfo</code>. As instances are
025: * also <code>Annotation</code>s, they can be used in
026: * <code>DocumentLineDiffer</code>s <code>IAnnotationModel</code> protocol.
027: *
028: * @since 3.0
029: */
030: public final class DiffRegion extends Annotation implements
031: ILineDiffInfo {
032: private final RangeDifference fDifference;
033:
034: private final int fOffset;
035:
036: private final List fList;
037:
038: private final IDocument fDocument;
039:
040: /**
041: * Creates a new diff region.
042: *
043: * @param difference
044: * @param offset
045: * @param differences
046: * @param source
047: */
048: public DiffRegion(RangeDifference difference, int offset,
049: List differences, IDocument source) {
050: super (
051: "org.eclipse.ui.workbench.texteditor.quickdiffChange", false, null); //$NON-NLS-1$
052: fOffset = offset;
053: fDifference = difference;
054: fList = differences;
055: fDocument = source;
056: }
057:
058: /*
059: * @see org.eclipse.jface.text.source.Annotation#getType()
060: */
061: public String getType() {
062: // we return unknown for unchanged regions to avoid
063: // them getting displayed.
064: switch (getChangeType()) {
065: case CHANGED:
066: return "org.eclipse.ui.workbench.texteditor.quickdiffChange"; //$NON-NLS-1$
067: case ADDED:
068: return "org.eclipse.ui.workbench.texteditor.quickdiffAddition"; //$NON-NLS-1$
069: case UNCHANGED:
070: return "org.eclipse.ui.workbench.texteditor.quickdiffUnchanged"; //$NON-NLS-1$
071: default:
072: return TYPE_UNKNOWN;
073: }
074: }
075:
076: /*
077: * @see org.eclipse.jface.text.source.ILineDiffInfo#getRemovedLinesBelow()
078: */
079: public int getRemovedLinesBelow() {
080: if (fOffset == fDifference.rightLength() - 1) {
081:
082: if (getChangeType() != UNCHANGED)
083: return Math.max(fDifference.leftLength()
084: - fDifference.rightLength(), 0);
085:
086: synchronized (fList) {
087: for (ListIterator it = fList.listIterator(); it
088: .hasNext();) {
089: if (fDifference.equals(it.next())) {
090: if (it.hasNext()) {
091: RangeDifference next = (RangeDifference) it
092: .next();
093: if (next.rightLength() == 0)
094: return Math.max(next.leftLength()
095: - next.rightLength(), 0);
096: }
097: break;
098: }
099: }
100: }
101: }
102: return 0;
103: }
104:
105: /*
106: * @see org.eclipse.jface.text.source.ILineDiffInfo#getChangeType()
107: */
108: public int getChangeType() {
109: if (fDifference.kind() == RangeDifference.NOCHANGE)
110: return UNCHANGED;
111: if (fOffset >= fDifference.leftLength())
112: return ADDED;
113: return CHANGED;
114: }
115:
116: /*
117: * @see org.eclipse.jface.text.source.ILineDiffInfo#getRemovedLinesAbove()
118: */
119: public int getRemovedLinesAbove() {
120: if (getChangeType() == UNCHANGED && fOffset == 0) {
121: synchronized (fList) {
122: for (ListIterator it = fList.listIterator(fList.size()); it
123: .hasPrevious();) {
124: if (fDifference.equals(it.previous())) {
125: if (it.hasPrevious()) {
126: RangeDifference previous = (RangeDifference) it
127: .previous();
128: return Math.max(previous.leftLength()
129: - previous.rightLength(), 0);
130: }
131: break;
132: }
133: }
134: }
135: }
136: return 0;
137: }
138:
139: /*
140: * @see org.eclipse.jface.text.source.ILineDiffInfo#hasChanges()
141: */
142: public boolean hasChanges() {
143: return getChangeType() != UNCHANGED
144: || getRemovedLinesAbove() > 0
145: || getRemovedLinesBelow() > 0;
146: }
147:
148: /*
149: * @see org.eclipse.jface.text.source.ILineDiffInfo#getOriginalText()
150: */
151: public String[] getOriginalText() {
152: IDocument doc = fDocument;
153: if (doc != null) {
154: int startLine = fDifference.leftStart() + fOffset;
155: if (startLine >= fDifference.leftEnd())
156: return new String[0]; // original text of an added line is
157: // empty
158:
159: int endLine = startLine + getRemovedLinesBelow();
160: if (getChangeType() == UNCHANGED)
161: startLine++;
162: String[] ret = new String[endLine - startLine + 1];
163: for (int i = 0; i < ret.length; i++) {
164: try {
165: ret[i] = doc.get(doc.getLineOffset(startLine + i),
166: doc.getLineLength(startLine + i));
167: } catch (BadLocationException e) {
168: ret[i] = ""; //$NON-NLS-1$
169: }
170: }
171: return ret;
172: }
173:
174: // in initialization phase?
175: return new String[0];
176: }
177:
178: /*
179: * @see org.eclipse.jface.text.source.Annotation#getText()
180: */
181: public String getText() {
182: int r = fDifference.rightLength();
183: int l = fDifference.leftLength();
184: int c = Math.min(r, l);
185: int a = r - l;
186: String changed = c > 0 ? NLSUtility.format(
187: QuickDiffMessages.quickdiff_annotation_changed,
188: new Integer(c)) : null;
189: String added;
190: if (a > 0)
191: added = NLSUtility.format(
192: QuickDiffMessages.quickdiff_annotation_added,
193: new Integer(a));
194: else if (a < 0)
195: added = NLSUtility.format(
196: QuickDiffMessages.quickdiff_annotation_deleted,
197: new Integer(-a));
198: else
199: added = null;
200: String line = c > 1 || c == 0 && Math.abs(a) > 1 ? QuickDiffMessages.quickdiff_annotation_line_plural
201: : QuickDiffMessages.quickdiff_annotation_line_singular;
202:
203: String ret = (changed != null ? changed : "") + (changed != null ? " " + line : "") //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
204: + (changed != null && added != null ? ", " : " ") + (added != null ? added : "") //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
205: + (added != null && changed == null ? " " + line : ""); //$NON-NLS-1$//$NON-NLS-2$
206: return ret;
207: }
208:
209: /**
210: * @return Returns the difference.
211: */
212: public RangeDifference getDifference() {
213: return fDifference;
214: }
215:
216: /**
217: * @return Returns the offset.
218: */
219: public int getOffset() {
220: return fOffset;
221: }
222: }
|