diff options
author | Kai Maetzel | 2002-12-03 13:53:47 +0000 |
---|---|---|
committer | Kai Maetzel | 2002-12-03 13:53:47 +0000 |
commit | 12a19d1dcedb0e74ec7448608e801550e9ddf756 (patch) | |
tree | 666fd0e3d69aeaa61cae9fc0a44a95a6eb6614c1 | |
parent | cca5d0bee1158d234c5366d10b4dcb9126932563 (diff) | |
download | eclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.tar.gz eclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.tar.xz eclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.zip |
projection
59 files changed, 4030 insertions, 578 deletions
diff --git a/org.eclipse.jface.text/.classpath b/org.eclipse.jface.text/.classpath index f5dc5a4c919..df6a2a79e66 100644 --- a/org.eclipse.jface.text/.classpath +++ b/org.eclipse.jface.text/.classpath @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src/"/> + <classpathentry kind="src" path="projection"/> <classpathentry exported="true" kind="src" path="/org.eclipse.text"/> <classpathentry kind="src" path="/org.eclipse.swt"/> <classpathentry kind="src" path="/org.eclipse.jface"/> <classpathentry kind="src" path="/org.eclipse.core.runtime"/> <classpathentry kind="src" path="/org.eclipse.core.boot"/> <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/> + <classpathentry kind="src" path="/org.junit"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/org.eclipse.jface.text/.project b/org.eclipse.jface.text/.project index 31de145d9fa..e27fdaa5b36 100644 --- a/org.eclipse.jface.text/.project +++ b/org.eclipse.jface.text/.project @@ -8,6 +8,7 @@ <project>org.eclipse.jface</project> <project>org.eclipse.swt</project> <project>org.eclipse.text</project> + <project>org.junit</project> </projects> <buildSpec> <buildCommand> diff --git a/org.eclipse.jface.text/build.properties b/org.eclipse.jface.text/build.properties index d435043c207..a9253db9e6f 100644 --- a/org.eclipse.jface.text/build.properties +++ b/org.eclipse.jface.text/build.properties @@ -1,4 +1,5 @@ bin.includes = plugin.properties,\ plugin.xml,\ *.jar -source.jfacetext.jar = src/ +source.jfacetext.jar = src/,\ + projection/ diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/OutlinerRulerColumn.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/OutlinerRulerColumn.java new file mode 100644 index 00000000000..4596a96fb2d --- /dev/null +++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/OutlinerRulerColumn.java @@ -0,0 +1,110 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.jface.text.source; + + +import java.util.Iterator; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + + +/** + * OutlinerRulerColumn.java + */ +public class OutlinerRulerColumn extends AnnotationRulerColumn { + + /** + * Constructor for OutlinerRulerColumn. + * @param model + * @param width + */ + public OutlinerRulerColumn(IAnnotationModel model, int width) { + super(model, width); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.ProjectionRulerColumn#mouseDoubleClicked(int) + */ + protected void mouseDoubleClicked(int line) { + ProjectionAnnotation annotation= findAnnotation(line); + if (annotation != null) { + annotation.run(getCachedTextViewer()); + redraw(); + } + } + + /** + * Method findAnnotation. + * @return ProjectionAnnotation + */ + private ProjectionAnnotation findAnnotation(int line) { + IAnnotationModel model= getModel(); + if (model != null) { + Iterator e= model.getAnnotationIterator(); + while (e.hasNext()) { + Object next= e.next(); + if (next instanceof ProjectionAnnotation) { + ProjectionAnnotation annotation= (ProjectionAnnotation) next; + Position p= model.getPosition(annotation); + if (contains(p, line)) + return annotation; + } + } + } + return null; + } + + /** + * Method contains. + * @param p + * @param line + * @return boolean + */ + private boolean contains(Position p, int line) { + + IDocument document= getCachedTextViewer().getDocument(); + + try { + + int startLine= document.getLineOfOffset(p.getOffset()); + if (line < startLine) + return false; + if (line == startLine) + return true; + + int endLine= document.getLineOfOffset(p.getOffset() + Math.max(p.getLength() -1, 0)); + return (startLine < line && line <= endLine) ; + + } catch (BadLocationException x) { + } + + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.IVerticalRulerColumn#createControl(org.eclipse.jface.text.source.CompositeRuler, org.eclipse.swt.widgets.Composite) + */ + public Control createControl(CompositeRuler parentRuler, Composite parentControl) { + Control control= super.createControl(parentRuler, parentControl); + Display display= parentControl.getDisplay(); + Color background= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); + control.setBackground(background); + return control; + } +} diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotation.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotation.java new file mode 100644 index 00000000000..3f05d2b7484 --- /dev/null +++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotation.java @@ -0,0 +1,101 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.jface.text.source; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; + +/** + * ProjectionAnnotation.java + */ +public class ProjectionAnnotation extends Annotation { + + private static final int OUTER_MARGIN= 1; + private static final int INNER_MARGIN= 1; + private static final int PIXELS= 1; + private static final int LEGS= 2; + private static final int MIDDLE= PIXELS + INNER_MARGIN + LEGS; + private static final int SIZE= 2 * MIDDLE + PIXELS; + + + private Position fProjectionRange; + private boolean fIsFolded= false; + + + public ProjectionAnnotation(Position range) { + fProjectionRange= range; + } + + /* + * @see org.eclipse.jface.text.source.Annotation#paint(org.eclipse.swt.graphics.GC, org.eclipse.swt.widgets.Canvas, org.eclipse.swt.graphics.Rectangle) + */ + public void paint(GC gc, Canvas canvas, Rectangle rectangle) { + Color fg= gc.getForeground(); + gc.setForeground(canvas.getDisplay().getSystemColor(SWT.COLOR_BLUE)); + + + Rectangle r= new Rectangle(rectangle.x + OUTER_MARGIN, rectangle.y + OUTER_MARGIN, SIZE , SIZE); + gc.drawRectangle(r); + gc.drawLine(r.x + PIXELS + INNER_MARGIN, r.y + MIDDLE, r.x + r.width - PIXELS - INNER_MARGIN , r.y + MIDDLE); + if (fIsFolded) { + gc.drawLine(r.x + MIDDLE, r.y + PIXELS + INNER_MARGIN, r.x + MIDDLE, r.y + r.height - PIXELS - INNER_MARGIN); + } else { + gc.drawLine(r.x + MIDDLE, r.y + r.height, r.x + MIDDLE, rectangle.y + rectangle.height - OUTER_MARGIN); + gc.drawLine(r.x + MIDDLE, rectangle.y + rectangle.height - OUTER_MARGIN, r.x + r.width - INNER_MARGIN, rectangle.y + rectangle.height - OUTER_MARGIN); + } + + gc.setForeground(fg); + } + + public void run(ITextViewer viewer) { + + if (viewer instanceof ProjectionSourceViewer) { + ProjectionSourceViewer projectionViewer= (ProjectionSourceViewer) viewer; + + if (fIsFolded) { + + fIsFolded= false; + projectionViewer.expand(fProjectionRange.getOffset(), fProjectionRange.getLength()); + + } else { + + try { + IDocument document= projectionViewer.getDocument(); + int line= document.getLineOfOffset(fProjectionRange.getOffset()); + int offset= document.getLineOffset(line + 1); + + int length= fProjectionRange.getLength() - (offset - fProjectionRange.getOffset()); + if (length > 0) { + fIsFolded= true; + projectionViewer.collapse(offset, length); + } + } catch (BadLocationException x) { + } + } + } + } + + /** + * Returns the fIsFolded. + * @return boolean + */ + public boolean isFolded() { + return fIsFolded; + } +} diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotationModel.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotationModel.java new file mode 100644 index 00000000000..f684d0cb614 --- /dev/null +++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionAnnotationModel.java @@ -0,0 +1,162 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text.source; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.ProjectionDocumentManager; + +/** + * ProjectionAnnotationModel.java + */ +public class ProjectionAnnotationModel implements IAnnotationModel { + + private class ProjectionIterator implements Iterator { + + private Position[] fPositions; + private int fIndex; + + public ProjectionIterator(Position[] positions) { + fPositions= positions; + fIndex= 0; + } + + /* + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + return fIndex < fPositions.length; + } + + /* + * @see java.util.Iterator#next() + */ + public Object next() { + Position p= fPositions[fIndex++]; + return new ProjectionAnnotation(p); + } + + /* + * @see java.util.Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } + }; + + private static class EmptyIterator implements Iterator { + /* + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + return false; + } + + /* + * @see java.util.Iterator#next() + */ + public Object next() { + throw new NoSuchElementException(); + } + + /* + * @see java.util.Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } + }; + + + private ITextViewer fTextViewer; + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#IAnnotationModel() + */ + public ProjectionAnnotationModel() { + } + + public void setTextViewer(ITextViewer viewer) { + fTextViewer= viewer; + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#addAnnotationModelListener(org.eclipse.jface.text.source.IAnnotationModelListener) + */ + public void addAnnotationModelListener(IAnnotationModelListener listener) { +// throw new UnsupportedOperationException(); + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#removeAnnotationModelListener(org.eclipse.jface.text.source.IAnnotationModelListener) + */ + public void removeAnnotationModelListener(IAnnotationModelListener listener) { +// throw new UnsupportedOperationException(); + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#connect(org.eclipse.jface.text.IDocument) + */ + public void connect(IDocument document) { + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#disconnect(org.eclipse.jface.text.IDocument) + */ + public void disconnect(IDocument document) { + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#addAnnotation(org.eclipse.jface.text.source.Annotation, org.eclipse.jface.text.Position) + */ + public void addAnnotation(Annotation annotation, Position position) { +// throw new UnsupportedOperationException(); + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#removeAnnotation(org.eclipse.jface.text.source.Annotation) + */ + public void removeAnnotation(Annotation annotation) { +// throw new UnsupportedOperationException(); + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#getAnnotationIterator() + */ + public Iterator getAnnotationIterator() { + IDocument document= fTextViewer.getDocument(); + if (document != null) { + try { + return new ProjectionIterator(document.getPositions(ProjectionDocumentManager.PROJECTION_DOCUMENTS)); + } catch (BadPositionCategoryException x) { + } + } + return new EmptyIterator(); + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationModel#getPosition(org.eclipse.jface.text.source.Annotation) + */ + public Position getPosition(Annotation annotation) { +// if (annotation instanceof ProjectionAnnotation) { +// Position p= ((ProjectionAnnotation) annotation).getProjectionRange(); +// if (p.getOffset() + p.getLength() < fTextViewer.getDocument().getLength()) +// return new Position(p.getOffset() + Math.max(p.getLength() -1, 0)); +// } + return null; + } +} diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionSourceViewer.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionSourceViewer.java new file mode 100644 index 00000000000..4fc40b5044f --- /dev/null +++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/ProjectionSourceViewer.java @@ -0,0 +1,194 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text.source; + + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ISlaveDocumentManager; +import org.eclipse.jface.text.ITextViewerExtension3; +import org.eclipse.jface.text.ProjectionDocument; +import org.eclipse.jface.text.ProjectionDocumentManager; + + +public class ProjectionSourceViewer extends SourceViewer implements ISourceViewer, ITextViewerExtension3 { + + /** The projection annotation model */ + private IAnnotationModel fProjectionAnnotationModel; + + + /** + * Constructor for ProjectionSourceViewer. + * @param parent + * @param ruler + * @param styles + */ + public ProjectionSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + super(parent, ruler, styles); + } + + /* + * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int) + */ + public void setDocument(IDocument document, IAnnotationModel annotationModel, int visibleRegionOffset, int visibleRegionLength) { + if (getDocument() != null && fProjectionAnnotationModel != null) + fProjectionAnnotationModel.disconnect(getDocument()); + + super.setDocument(document, annotationModel, visibleRegionOffset, visibleRegionLength); + + if (getDocument() != null && fProjectionAnnotationModel != null) + fProjectionAnnotationModel.connect(getDocument()); + } + + /* + * @see TextViewer#handleDispose + */ + protected void handleDispose() { + + if (getDocument() != null && fProjectionAnnotationModel != null) { + fProjectionAnnotationModel.disconnect(getDocument()); + fProjectionAnnotationModel= null; + } + + super.handleDispose(); + } + + /** + * Returns the projectionAnnotationModel. + * @return IAnnotationModel + */ + public IAnnotationModel getProjectionAnnotationModel() { + return fProjectionAnnotationModel; + } + + /** + * Sets the projectionAnnotationModel. + * @param projectionAnnotationModel The projectionAnnotationModel to set + */ + public void setProjectionAnnotationModel(IAnnotationModel projectionAnnotationModel) { + fProjectionAnnotationModel= projectionAnnotationModel; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.TextViewer#createSlaveDocumentManager() + */ + protected ISlaveDocumentManager createSlaveDocumentManager() { + return new ProjectionDocumentManager(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.TextViewer#updateVisibleDocument(org.eclipse.jface.text.IDocument, int, int) + */ + protected boolean updateVisibleDocument(IDocument visibleDocument, int visibleRegionOffset, int visibleRegionLength) throws BadLocationException { + if (visibleDocument instanceof ProjectionDocument) { + ProjectionDocument document= (ProjectionDocument) visibleDocument; + document.addFragment(visibleRegionOffset, visibleRegionLength); + } + return true; + } + + /** + * Hides the given range by collapsing it. + * + * @param offset + * @param length + */ + public void collapse(int offset, int length) { + + IDocument previous= getVisibleDocument(); + IDocument slave= createSlaveDocument(previous); + + if (slave instanceof ProjectionDocument) { + + StyledText textWidget= getTextWidget(); + try { + + if (textWidget != null) + textWidget.setRedraw(false); + + int topIndex= getTopIndex(); + ((ProjectionDocument) slave).hide(offset, length); + setVisibleDocument(slave); + setTopIndex(topIndex); + + } finally { + if(textWidget != null) + textWidget.setRedraw(true); + } + } + } + + /** + * Makes all hidden ranges in the given range visible again. + * + * @param offset + * @param length + */ + public void expand(int offset, int length) { + if (getVisibleDocument() instanceof ProjectionDocument) { + ProjectionDocument document= (ProjectionDocument) getVisibleDocument(); + + StyledText textWidget= getTextWidget(); + try { + + if (textWidget != null) + textWidget.setRedraw(false); + + int topIndex= getTopIndex(); + document.show(offset, length); + setVisibleDocument(document); + setTopIndex(topIndex); + + } finally { + if (textWidget != null) + textWidget.setRedraw(true); + } + } + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewer#_getVisibleRegion() + */ + public IRegion getVisibleRegion() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.TextViewer#_getVisibleRegionOffset() + */ + protected int _getVisibleRegionOffset() { + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.TextViewer#_internalGetVisibleRegion() + */ + protected IRegion _internalGetVisibleRegion() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewer#_overlapsWithVisibleRegion(int, int) + */ + public boolean overlapsWithVisibleRegion(int offset, int length) { + return false; + } + + public IDocument getVisibleDocument() { + return super.getVisibleDocument(); + } +}
\ No newline at end of file diff --git a/org.eclipse.jface.text/scripts/exportplugin.xml b/org.eclipse.jface.text/scripts/exportplugin.xml index 3831f586340..40eae04fff2 100644 --- a/org.eclipse.jface.text/scripts/exportplugin.xml +++ b/org.eclipse.jface.text/scripts/exportplugin.xml @@ -23,6 +23,7 @@ <copy file="plugin.properties" todir="${dest}"/> <zip zipfile="${dest}/jfacetextsrc.zip"> <fileset dir="src" /> + <fileset dir="projection"/> </zip> </target> </project> diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/DefaultUndoManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/DefaultUndoManager.java index 58ca1ea89ba..b73e2e3ef5a 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/DefaultUndoManager.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/DefaultUndoManager.java @@ -89,14 +89,10 @@ public class DefaultUndoManager implements IUndoManager { * @param text the text widget to be modified */ protected void undo(StyledText text) { - undoTextChange(text); - - int length= fPreservedText == null ? 0 : fPreservedText.length(); - IRegion visible= fTextViewer.getVisibleRegion(); - int offset= fStart + visible.getOffset(); - fTextViewer.setSelectedRange(offset, length); - fTextViewer.revealRange(offset, length); + IRegion modelRange= widgetRange2ModelRange(fStart, fPreservedText == null ? 0 : fPreservedText.length()); + fTextViewer.setSelectedRange(modelRange.getOffset(), modelRange.getLength()); + fTextViewer.revealRange(modelRange.getOffset(), modelRange.getLength()); } /** @@ -116,14 +112,20 @@ public class DefaultUndoManager implements IUndoManager { * @param text the text widget to be modified */ protected void redo(StyledText text) { - redoTextChange(text); + IRegion modelRange= widgetRange2ModelRange(fStart, fText == null ? 0 : fText.length()); + fTextViewer.setSelectedRange(modelRange.getOffset(), modelRange.getLength()); + fTextViewer.revealRange(modelRange.getOffset(), modelRange.getLength()); + } + + protected IRegion widgetRange2ModelRange(int offset, int length) { + if (fTextViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fTextViewer; + return extension.widgetRange2ModelRange(new Region(offset, length)); + } - int length= fText == null ? 0 : fText.length(); IRegion visible= fTextViewer.getVisibleRegion(); - int offset= fStart + visible.getOffset(); - fTextViewer.setSelectedRange(offset, length); - fTextViewer.revealRange(offset, length); + return new Region(offset + visible.getOffset(), length); } /** diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/DocumentCommand.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/DocumentCommand.java index 0a3a1f45f9b..a9872d25af7 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/DocumentCommand.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/DocumentCommand.java @@ -250,24 +250,16 @@ public class DocumentCommand { * Translates a verify event into a document replace command using the given offset. * * @param event the event to be translated - * @param offset the offset used for the translation + * @param modelRange the event range as model range */ - void setEvent(VerifyEvent event, int offset) { + void setEvent(VerifyEvent event, IRegion modelRange) { doit= true; + text= event.text; - text= event.text; - - this.offset= event.start; - length= event.end - event.start; - - if (length < 0) { - this.offset += length; - length= -length; - } - - this.offset += offset; - + offset= modelRange.getOffset(); + length= modelRange.getLength(); + owner= null; caretOffset= -1; fCommands.clear(); @@ -279,15 +271,12 @@ public class DocumentCommand { * covers the same range as the verify event considering the given offset. * * @param event the event to be changed - * @param offset to be considered for range comparison + * @param modelRange to be considered for range comparison * @return <code>true</code> if this command and the event cover the same range */ - boolean fillEvent(VerifyEvent event, int offset) { - - int start= this.offset - offset; - + boolean fillEvent(VerifyEvent event, IRegion modelRange) { event.text= text; - event.doit= (start == event.start && start + length == event.end) && doit; + event.doit= (offset == modelRange.getOffset() && length == modelRange.getLength()); return event.doit; } diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/ITextViewerExtension3.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/ITextViewerExtension3.java new file mode 100644 index 00000000000..39050040a64 --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/ITextViewerExtension3.java @@ -0,0 +1,27 @@ +package org.eclipse.jface.text; + + +/** + * Translates between model and presentation coordinates. + */ +public interface ITextViewerExtension3 { + + + public IRegion getModelCoverage(); + + + public int modelLine2WidgetLine(int modelLine); + + public int modelOffset2WidgetOffset(int modelOffset); + + public IRegion modelRange2WidgetRange(IRegion modelRange); + + + public int widgetOffset2ModelOffset(int widgetOffset); + + public IRegion widgetRange2ModelRange(IRegion widgetRange); + + public int widgetlLine2ModelLine(int widgetLine); + + public int widgetLineOfWidgetOffset(int widgetOffset); +} diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java index aff73caf0fb..6b10e2c53cd 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java @@ -75,9 +75,9 @@ import org.eclipse.jface.viewers.Viewer; * @see ITextViewer */ public class TextViewer extends Viewer implements - ITextViewer, ITextViewerExtension, ITextViewerExtension2, - ITextOperationTarget, ITextOperationTargetExtension, - IWidgetTokenOwner { + ITextViewer, ITextViewerExtension, ITextViewerExtension2, + ITextOperationTarget, ITextOperationTargetExtension, + IWidgetTokenOwner { /** Internal flag to indicate the debug state. */ public static boolean TRACE_ERRORS= false; @@ -551,8 +551,7 @@ public class TextViewer extends Viewer implements /* Don't use cached line information because of patched redrawing events. */ if (fTextWidget != null) { - int offset= event.lineOffset + TextViewer.this.getVisibleRegionOffset(); - + int offset= widgetOffset2ModelOffset(event.lineOffset); if (fPosition.includes(offset)) event.lineBackground= fHighlightColor; } @@ -615,8 +614,10 @@ public class TextViewer extends Viewer implements * Paints the highlighting of this range. */ private void paint() { - int offset= fPosition.getOffset() - TextViewer.this.getVisibleRegionOffset(); - int length= fPosition.getLength(); + + IRegion widgetRegion= modelRange2WidgetRange(fPosition); + int offset= widgetRegion.getOffset(); + int length= widgetRegion.getLength(); int count= fTextWidget.getCharCount(); if (offset + length >= count) { @@ -712,27 +713,24 @@ public class TextViewer extends Viewer implements */ public Point getSelection() { Point point= TextViewer.this.getSelectedRange(); - point.x -= TextViewer.this.getVisibleRegionOffset(); - return point; + return modelSelection2WidgetSelection(point); } /* * @see IFindReplaceTarget#findAndSelect(int, String, boolean, boolean, boolean) */ public int findAndSelect(int offset, String findString, boolean searchForward, boolean caseSensitive, boolean wholeWord) { - if (offset != -1) - offset += TextViewer.this.getVisibleRegionOffset(); + int modelOffset= offset == -1 ? -1 : widgetOffset2ModelOffset(offset); + if (fRange != null) { IRegion range= fRange.getRange(); - offset= TextViewer.this.findAndSelectInRange(offset, findString, searchForward, caseSensitive, wholeWord, range.getOffset(), range.getLength()); + modelOffset= TextViewer.this.findAndSelectInRange(modelOffset, findString, searchForward, caseSensitive, wholeWord, range.getOffset(), range.getLength()); } else { - offset= TextViewer.this.findAndSelect(offset, findString, searchForward, caseSensitive, wholeWord); + modelOffset= TextViewer.this.findAndSelect(modelOffset, findString, searchForward, caseSensitive, wholeWord); } - if (offset != -1) - offset -= TextViewer.this.getVisibleRegionOffset(); - + offset= modelOffset == -1 ? -1 : modelOffset2WidgetOffset(modelOffset); return offset; } @@ -800,8 +798,8 @@ public class TextViewer extends Viewer implements * @see IFindReplaceTargetExtension#setSelection(int, int) * @since 2.0 */ - public void setSelection(int offset, int length) { - TextViewer.this.setSelectedRange(offset /*+ TextViewer.this.getVisibleRegionOffset()*/, length); + public void setSelection(int modelOffset, int modelLength) { + TextViewer.this.setSelectedRange(modelOffset, modelLength); } /* @@ -967,8 +965,8 @@ public class TextViewer extends Viewer implements private IDocument fVisibleDocument; /** The viewer's document adapter */ private IDocumentAdapter fDocumentAdapter; - /** The child document manager */ - private ChildDocumentManager fChildDocumentManager; + /** The slave document manager */ + private ISlaveDocumentManager fSlaveDocumentManager; /** The text viewer's double click strategies connector */ private TextDoubleClickStrategyConnector fDoubleClickStrategyConnector; /** @@ -1066,6 +1064,12 @@ public class TextViewer extends Viewer implements /** Indicates whether the viewer's text presentation should be replaced are modified. */ protected boolean fReplaceTextPresentation= false; + /** + * The mapping between model and visible document. + * @since 2.1 + */ + protected IDocumentInformationMapping fInformationMapping; + //---- Construction and disposal ------------------ @@ -1243,23 +1247,25 @@ public class TextViewer extends Viewer implements fTextHoverManager= null; } - if (fDocumentListener != null) + if (fDocumentListener !=null) { + if (fVisibleDocument != null) + fVisibleDocument.removeDocumentListener(fDocumentListener); fDocumentListener= null; - - if (fVisibleDocument instanceof ChildDocument) { - ChildDocument child = (ChildDocument) fVisibleDocument; - child.removeDocumentListener(fDocumentListener); - getChildDocumentManager().freeChildDocument(child); } - + if (fDocumentAdapter != null) { fDocumentAdapter.setDocument(null); fDocumentAdapter= null; } + if (fSlaveDocumentManager != null) { + if (fVisibleDocument != null) + fSlaveDocumentManager.freeSlaveDocument(fVisibleDocument); + fSlaveDocumentManager= null; + } + fVisibleDocument= null; fDocument= null; - fChildDocumentManager= null; fScroller= null; } @@ -1541,8 +1547,7 @@ public class TextViewer extends Viewer implements if (fTextWidget != null) { Point p= fTextWidget.getSelectionRange(); - int offset= getVisibleRegionOffset(); - return new Point(p.x + offset, p.y); + return widgetSelection2ModelSelection(p); } return new Point(-1, -1); @@ -1562,48 +1567,15 @@ public class TextViewer extends Viewer implements if (fTextWidget == null) return; - IDocument document= getVisibleDocument(); - if (document == null) - return; - - int offset= selectionOffset; - int length= selectionLength; - if (selectionLength < 0) { - offset= selectionOffset + selectionLength; - length= -selectionLength; - } - - int end= offset + length; - - if (document instanceof ChildDocument) { - Position p= ((ChildDocument) document).getParentDocumentRange(); - if (p.overlapsWith(offset, length)) { - - if (offset < p.getOffset()) - offset= p.getOffset(); - offset -= p.getOffset(); - - int e= p.getOffset() + p.getLength(); - if (end > e) - end= e; - end -= p.getOffset(); - - } else - return; - } - - length= end - offset; - - int[] selectionRange= new int[] { offset, length }; - validateSelectionRange(selectionRange); - if (selectionRange[0] >= 0 && selectionRange[1] >= 0) { + IRegion widgetSelection= modelRange2WidgetRange(new Region(selectionOffset, selectionLength)); + if (widgetSelection != null) { - if (selectionLength < 0) - fTextWidget.setSelectionRange(selectionRange[0] + selectionRange[1], -selectionRange[1]); - else + int[] selectionRange= new int[] { widgetSelection.getOffset(), widgetSelection.getLength() }; + validateSelectionRange(selectionRange); + if (selectionRange[0] >= 0) { fTextWidget.setSelectionRange(selectionRange[0], selectionRange[1]); - - selectionChanged(selectionRange[0], selectionRange[1]); + selectionChanged(selectionRange[0], selectionRange[1]); + } } } @@ -1629,6 +1601,10 @@ public class TextViewer extends Viewer implements int offset= selectionRange[0]; int length= selectionRange[1]; + if (length < 0) { + length= - length; + offset -= length; + } if (offset <0) offset= 0; @@ -1670,8 +1646,13 @@ public class TextViewer extends Viewer implements return; } - selectionRange[0]= offset; - selectionRange[1]= length; + if (selectionRange[1] < 0) { + selectionRange[0]= offset + length; + selectionRange[1]= -length; + } else { + selectionRange[0]= offset; + selectionRange[1]= length; + } } /* @@ -1712,7 +1693,8 @@ public class TextViewer extends Viewer implements */ protected void selectionChanged(int offset, int length) { if (redraws()) { - ISelection selection= new TextSelection(getDocument(), getVisibleRegionOffset() + offset, length); + IRegion r= widgetRange2ModelRange(new Region(offset, length)); + ISelection selection= r != null ? new TextSelection(getDocument(), r.getOffset(), r.getLength()) : TextSelection.emptySelection(); SelectionChangedEvent event= new SelectionChangedEvent(this, selection); fireSelectionChanged(event); } @@ -1727,8 +1709,13 @@ public class TextViewer extends Viewer implements */ protected void markChanged(int offset, int length) { if (redraws()) { - if (offset != -1) - offset += getVisibleRegionOffset(); + + if (offset != -1) { + IRegion r= widgetRange2ModelRange(new Region(offset, length)); + offset= r.getOffset(); + length= r.getLength(); + } + ISelection selection= new MarkSelection(getDocument(), offset, length); SelectionChangedEvent event= new SelectionChangedEvent(this, selection); fireSelectionChanged(event); @@ -1771,8 +1758,8 @@ public class TextViewer extends Viewer implements if (fTextListeners != null) { DocumentEvent event= cmd.event; - if (event instanceof ChildDocumentEvent) - event= ((ChildDocumentEvent) event).getParentEvent(); + if (event instanceof SlaveDocumentEvent) + event= ((SlaveDocumentEvent) event).getMasterEvent(); TextEvent e= new TextEvent(cmd.start, cmd.length, cmd.text, cmd.preservedText, event, redraws()); for (int i= 0; i < fTextListeners.size(); i++) { @@ -1897,10 +1884,11 @@ public class TextViewer extends Viewer implements fDocument= document; try { - int line= fDocument.getLineOfOffset(visibleRegionOffset); - int offset= fDocument.getLineOffset(line); - int length= (visibleRegionOffset - offset) + visibleRegionLength; - setVisibleDocument(getChildDocumentManager().createChildDocument(fDocument, offset, length)); + + IDocument visibleDocument= createSlaveDocument(document); + updateVisibleDocument(visibleDocument, visibleRegionOffset, visibleRegionLength); + setVisibleDocument(visibleDocument); + } catch (BadLocationException x) { throw new IllegalArgumentException(JFaceTextMessages.getString("TextViewer.error.invalid_visible_region_1")); //$NON-NLS-1$ } @@ -1909,7 +1897,36 @@ public class TextViewer extends Viewer implements fireInputDocumentChanged(oldDocument, fDocument); fReplaceTextPresentation= false; - } + } + + protected IDocument createSlaveDocument(IDocument document) { + ISlaveDocumentManager manager= getSlaveDocumentManager(); + if (manager != null) { + if (manager.isSlaveDocument(document)) + return document; + return manager.createSlaveDocument(document); + } + return document; + } + + protected boolean updateVisibleDocument(IDocument visibleDocument, int visibleRegionOffset, int visibleRegionLength) throws BadLocationException { + if (visibleDocument instanceof ChildDocument) { + ChildDocument childDocument= (ChildDocument) visibleDocument; + + IDocument document= childDocument.getParentDocument(); + int line= document.getLineOfOffset(visibleRegionOffset); + int offset= document.getLineOffset(line); + int length= (visibleRegionOffset - offset) + visibleRegionLength; + + Position parentRange= childDocument.getParentDocumentRange(); + if (offset != parentRange.getOffset() || length != parentRange.getLength()) { + childDocument.setParentDocumentRange(offset, length); + return true; + } + } + return false; + } + //---- Viewports @@ -2010,21 +2027,9 @@ public class TextViewer extends Viewer implements if (fTextWidget != null) { int top= fTextWidget.getTopIndex(); - - int offset= getVisibleRegionOffset(); - if (offset > 0) { - try { - top += getDocument().getLineOfOffset(offset); - } catch (BadLocationException x) { - if (TRACE_ERRORS) - System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getTopIndex")); //$NON-NLS-1$ - return -1; + return widgetlLine2ModelLine(top); } - } - return top; - } - return -1; } @@ -2035,31 +2040,13 @@ public class TextViewer extends Viewer implements if (fTextWidget != null) { - int offset= getVisibleRegionOffset(); - if (offset > 0) { - try { - index -= getDocument().getLineOfOffset(offset); - } catch (BadLocationException x) { - if (TRACE_ERRORS) - System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.setTopIndex_1")); //$NON-NLS-1$ - return; - } - } + int widgetLine= modelLine2WidgetLine(index); + if (widgetLine == -1) + widgetLine= getClosestWidgetLineForModelLine(index); - if (index >= 0) { - - int lines= getVisibleLinesInViewport(); - if (lines > -1 ) { - IDocument d= getVisibleDocument(); - int last= d.getNumberOfLines() - lines; - if (last > 0 && index > last) - index= last; - - fTextWidget.setTopIndex(index); + if (widgetLine > -1) { + fTextWidget.setTopIndex(widgetLine); updateViewportListeners(INTERNAL); - - } else - fTextWidget.setTopIndex(index); } } } @@ -2087,17 +2074,20 @@ public class TextViewer extends Viewer implements if (fTextWidget == null) return -1; - IRegion r= getVisibleRegion(); + IRegion coverage= getModelCoverage(); try { IDocument d= getDocument(); - int startLine= d.getLineOfOffset(r.getOffset()); - int endLine= d.getLineOfOffset(r.getOffset() + r.getLength() - 1); + int startLine= d.getLineOfOffset(coverage.getOffset()); + int endLine= d.getLineOfOffset(coverage.getOffset() + coverage.getLength() - 1); int lines= getVisibleLinesInViewport(); - if (startLine + lines < endLine) - return getTopIndex() + lines - 1; + if (startLine + lines < endLine) { + int widgetTopIndex= fTextWidget.getTopIndex(); + int widgetBottomIndex= widgetTopIndex + lines -1; + return widgetlLine2ModelLine(widgetBottomIndex); + } return endLine; @@ -2118,7 +2108,7 @@ public class TextViewer extends Viewer implements int top= fTextWidget.getTopIndex(); try { top= getVisibleDocument().getLineOffset(top); - return top + getVisibleRegionOffset(); + return widgetlLine2ModelLine(top); } catch (BadLocationException ex) { if (TRACE_ERRORS) System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.getTopIndexStartOffset")); //$NON-NLS-1$ @@ -2137,9 +2127,9 @@ public class TextViewer extends Viewer implements IRegion line= getDocument().getLineInformation(getBottomIndex()); int bottomEndOffset= line.getOffset() + line.getLength() - 1; - IRegion region= getVisibleRegion(); - int visibleRegionEndOffset= region.getOffset() + region.getLength() - 1; - return visibleRegionEndOffset < bottomEndOffset ? visibleRegionEndOffset : bottomEndOffset; + IRegion coverage= getModelCoverage(); + int coverageEndOffset= coverage.getOffset() + coverage.getLength() - 1; + return Math.min(coverageEndOffset, bottomEndOffset); } catch (BadLocationException ex) { if (TRACE_ERRORS) @@ -2156,39 +2146,15 @@ public class TextViewer extends Viewer implements if (fTextWidget == null || !redraws()) return; - if (length < 0) { - start += length; - length= -length; - } - - int end= start + length; - - IDocument document= getVisibleDocument(); - if (document == null) - return; - - Position p= (document instanceof ChildDocument) - ? ((ChildDocument) document).getParentDocumentRange() - : new Position(0, document.getLength()); - - if (p.overlapsWith(start, length)) { - - if (start < p.getOffset()) - start= p.getOffset(); - start -= p.getOffset(); - - int e= p.getOffset() + p.getLength(); - if (end > e) - end= e; - end -= p.getOffset(); - + IRegion modelRange= new Region(start, length); + IRegion widgetRange= modelRange2WidgetRange(modelRange); + if (widgetRange != null) { + internalRevealRange(widgetRange.getOffset(), widgetRange.getOffset() + widgetRange.getLength()); } else { - // http://dev.eclipse.org/bugs/show_bug.cgi?id=15159 - start= start < p.getOffset() ? 0 : p.getLength(); - end= start; + IRegion coverage= getModelCoverage(); + int cursor= start < coverage.getOffset() ? 0 : getVisibleDocument().getLength(); + internalRevealRange(cursor, cursor); } - - internalRevealRange(start, end); } /** @@ -2348,14 +2314,22 @@ public class TextViewer extends Viewer implements //---- visible range support /** - * Returns the child document manager + * Returns the slave document manager * - * @return the child document manager + * @return the slave document manager */ - private ChildDocumentManager getChildDocumentManager() { - if (fChildDocumentManager == null) - fChildDocumentManager= new ChildDocumentManager(); - return fChildDocumentManager; + protected ISlaveDocumentManager getSlaveDocumentManager() { + if (fSlaveDocumentManager == null) + fSlaveDocumentManager= createSlaveDocumentManager(); + return fSlaveDocumentManager; + } + + /** + * Creates a new slave document manager. + * @return ISlaveDocumentManager + */ + protected ISlaveDocumentManager createSlaveDocumentManager() { + return new ChildDocumentManager(); } /* @@ -2374,25 +2348,14 @@ public class TextViewer extends Viewer implements public final void invalidateTextPresentation(int offset, int length) { if (fVisibleDocument != null) { - IRegion visibleRegion= getVisibleRegion(); - - int delta= visibleRegion.getOffset() - offset; - if (delta > 0) { - offset= visibleRegion.getOffset(); - length -= delta; - } - offset -= visibleRegion.getOffset(); + IRegion widgetRange= modelRange2WidgetRange(new Region(offset, length)); - delta= (offset + length) - (visibleRegion.getOffset() + visibleRegion.getLength()); - if (delta > 0) - length -= delta; - fWidgetCommand.event= null; - fWidgetCommand.start= offset; - fWidgetCommand.length= length; + fWidgetCommand.start= widgetRange.getOffset(); + fWidgetCommand.length= widgetRange.getLength(); try { - fWidgetCommand.text= fVisibleDocument.get(offset, length); + fWidgetCommand.text= fVisibleDocument.get(widgetRange.getOffset(), widgetRange.getLength()); updateTextListeners(fWidgetCommand); } catch (BadLocationException x) { // can not happen because of previous checking @@ -2426,12 +2389,13 @@ public class TextViewer extends Viewer implements * * @param document the visible document */ - private void setVisibleDocument(IDocument document) { + protected void setVisibleDocument(IDocument document) { if (fVisibleDocument != null && fDocumentListener != null) fVisibleDocument.removeDocumentListener(fDocumentListener); fVisibleDocument= document; + initializeDocumentInformationMapping(fVisibleDocument); initializeWidgetContents(); resetPlugins(); @@ -2440,6 +2404,11 @@ public class TextViewer extends Viewer implements fVisibleDocument.addDocumentListener(fDocumentListener); } + protected void initializeDocumentInformationMapping(IDocument visibleDocument) { + ISlaveDocumentManager manager= getSlaveDocumentManager(); + fInformationMapping= manager == null ? null : manager.createMasterSlaveMapping(visibleDocument); + } + /** * Returns the viewer's visible document. * @@ -2454,7 +2423,7 @@ public class TextViewer extends Viewer implements * * @return the offset of the visible region */ - protected int getVisibleRegionOffset() { + protected int _getVisibleRegionOffset() { IDocument document= getVisibleDocument(); if (document instanceof ChildDocument) { @@ -2478,7 +2447,22 @@ public class TextViewer extends Viewer implements return new Region(0, document == null ? 0 : document.getLength()); } - + + /* + * @see ITextViewer#overlapsWithVisibleRegion + */ + public boolean overlapsWithVisibleRegion(int start, int length) { + IDocument document= getVisibleDocument(); + if (document instanceof ChildDocument) { + ChildDocument cdoc= (ChildDocument) document; + return cdoc.getParentDocumentRange().overlapsWith(start, length); + } else if (document != null) { + int size= document.getLength(); + return (start >= 0 && length >= 0 && start + length <= size); + } + return false; + } + /* * @see ITextViewer#setVisibleRegion */ @@ -2490,28 +2474,10 @@ public class TextViewer extends Viewer implements return; } - ChildDocument child= null; - IDocument parent= getVisibleDocument(); - - if (parent instanceof ChildDocument) { - child= (ChildDocument) parent; - parent= child.getParentDocument(); - } - try { - - int line= parent.getLineOfOffset(start); - int offset= parent.getLineOffset(line); - length += (start - offset); - - if (child != null) { - child.setParentDocumentRange(offset, length); - } else { - child= getChildDocumentManager().createChildDocument(parent, offset, length); - } - - setVisibleDocument(child); - + IDocument visibleDocument= createSlaveDocument(getVisibleDocument()); + if (updateVisibleDocument(visibleDocument, start, length)) + setVisibleDocument(visibleDocument); } catch (BadLocationException x) { throw new IllegalArgumentException(JFaceTextMessages.getString("TextViewer.error.invalid_visible_region_2")); //$NON-NLS-1$ } @@ -2521,29 +2487,16 @@ public class TextViewer extends Viewer implements * @see ITextViewer#resetVisibleRegion */ public void resetVisibleRegion() { - IDocument document= getVisibleDocument(); - if (document instanceof ChildDocument) { - ChildDocument child = (ChildDocument) document; - setVisibleDocument(child.getParentDocument()); - getChildDocumentManager().freeChildDocument(child); - } - } - - /* - * @see ITextViewer#overlapsWithVisibleRegion - */ - public boolean overlapsWithVisibleRegion(int start, int length) { - IDocument document= getVisibleDocument(); - if (document instanceof ChildDocument) { - ChildDocument cdoc= (ChildDocument) document; - return cdoc.getParentDocumentRange().overlapsWith(start, length); - } else if (document != null) { - int size= document.getLength(); - return (start >= 0 && length >= 0 && start + length <= size); + ISlaveDocumentManager manager= getSlaveDocumentManager(); + if (manager != null) { + IDocument slave= getVisibleDocument(); + IDocument master= manager.getMasterDocument(slave); + if (master != null) { + setVisibleDocument(master); + manager.freeSlaveDocument(slave); + } } - return false; } - //-------------------------------------- @@ -2639,20 +2592,20 @@ public class TextViewer extends Viewer implements return; } - int offset= getVisibleRegionOffset(); - fDocumentCommand.setEvent(e, offset); + IRegion modelRange= event2ModelRange(e); + fDocumentCommand.setEvent(e, modelRange); customizeDocumentCommand(fDocumentCommand); - if (!fDocumentCommand.fillEvent(e, offset)) { + if (!fDocumentCommand.fillEvent(e, modelRange)) { try { fVerifyListener.forward(false); fDocumentCommand.execute(getDocument()); if (fTextWidget != null) { - int caretOffset= fDocumentCommand.caretOffset; + int documentCaret= fDocumentCommand.caretOffset; // old behaviour of document command - if (caretOffset == -1) - caretOffset= fDocumentCommand.offset + (fDocumentCommand.text == null ? 0 : fDocumentCommand.text.length()); - caretOffset -= getVisibleRegionOffset(); - fTextWidget.setCaretOffset(caretOffset); + if (documentCaret == -1) + documentCaret= fDocumentCommand.offset + (fDocumentCommand.text == null ? 0 : fDocumentCommand.text.length()); + int widgetCaret= modelOffset2WidgetOffset(documentCaret); + fTextWidget.setCaretOffset(widgetCaret); } } catch (BadLocationException x) { if (TRACE_ERRORS) @@ -2671,19 +2624,11 @@ public class TextViewer extends Viewer implements * @return <code>true</code> if the marked region of this viewer is empty, otherwise <code>false</code> */ private boolean isMarkedRegionEmpty() { - - if (fTextWidget == null) - return true; - - IRegion region= getVisibleRegion(); - int offset= region.getOffset(); - int length= region.getLength(); - return + fTextWidget == null || fMarkPosition == null || fMarkPosition.isDeleted() || - fMarkPosition.offset < offset || - fMarkPosition.offset > offset + length; + modelRange2WidgetRange(fMarkPosition) == null; } /* @@ -2765,9 +2710,10 @@ public class TextViewer extends Viewer implements case DELETE: deleteText(); break; - case SELECT_ALL: - setSelectedRange(getVisibleRegionOffset(), getVisibleDocument().getLength()); + case SELECT_ALL: { + setSelectedRange(0, getDocument().getLength()); break; + } case SHIFT_RIGHT: shift(false, true, false); break; @@ -2808,21 +2754,15 @@ public class TextViewer extends Viewer implements if (fTextWidget == null) return; - IRegion region= getVisibleRegion(); - int offset= region.getOffset(); - int length= region.getLength(); - - if (fMarkPosition == null || fMarkPosition.isDeleted() || - fMarkPosition.offset < offset || fMarkPosition.offset > offset + length) + if (fMarkPosition == null || fMarkPosition.isDeleted() || modelRange2WidgetRange(fMarkPosition) == null) return; - int markOffset= fMarkPosition.offset - offset; - + int widgetMarkOffset= modelOffset2WidgetOffset(fMarkPosition.offset); Point selection= fTextWidget.getSelection(); - if (selection.x <= markOffset) - fTextWidget.setSelection(selection.x, markOffset); + if (selection.x <= widgetMarkOffset) + fTextWidget.setSelection(selection.x, widgetMarkOffset); else - fTextWidget.setSelection(markOffset, selection.x); + fTextWidget.setSelection(widgetMarkOffset, selection.x); if (delete) { fTextWidget.cut(); @@ -3207,19 +3147,23 @@ public class TextViewer extends Viewer implements return -1; try { - int offset= (startPosition == -1 ? startPosition : startPosition - getVisibleRegionOffset()); - int pos= getVisibleDocument().search(offset, findString, forwardSearch, caseSensitive, wholeWord); - if (pos > -1) { + + int widgetOffset= (startPosition == -1 ? startPosition : modelOffset2WidgetOffset(startPosition)); + int widgetPos= getVisibleDocument().search(widgetOffset, findString, forwardSearch, caseSensitive, wholeWord); + if (widgetPos > -1) { + int length= findString.length(); if (redraws()) { - fTextWidget.setSelectionRange(pos, length); - internalRevealRange(pos, pos + length); - selectionChanged(pos, length); + fTextWidget.setSelectionRange(widgetPos, length); + internalRevealRange(widgetPos, widgetPos + length); + selectionChanged(widgetPos, length); } else { - setSelectedRange(pos + getVisibleRegionOffset(), length); + setSelectedRange(widgetOffset2ModelOffset(widgetPos), length); } + + return widgetOffset2ModelOffset(widgetPos); } - return pos + getVisibleRegionOffset(); + } catch (BadLocationException x) { if (TRACE_ERRORS) System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$ @@ -3237,32 +3181,41 @@ public class TextViewer extends Viewer implements return -1; try { - int offset; + + int modelOffset; if (forwardSearch && (startPosition == -1 || startPosition < rangeOffset)) { - offset= rangeOffset; + modelOffset= rangeOffset; } else if (!forwardSearch && (startPosition == -1 || startPosition > rangeOffset + rangeLength)) { - offset= rangeOffset + rangeLength; + modelOffset= rangeOffset + rangeLength; } else { - offset= startPosition; + modelOffset= startPosition; } - offset -= getVisibleRegionOffset(); - int pos= getVisibleDocument().search(offset, findString, forwardSearch, caseSensitive, wholeWord); + int widgetOffset= modelOffset2WidgetOffset(modelOffset); + if (widgetOffset == -1) + return -1; + int widgetPos= getVisibleDocument().search(widgetOffset, findString, forwardSearch, caseSensitive, wholeWord); + int modelPos= widgetPos == -1 ? -1 : widgetOffset2ModelOffset(widgetPos); + int length = findString.length(); - if (pos != -1 && (pos + getVisibleRegionOffset() < rangeOffset || pos + getVisibleRegionOffset() + length > rangeOffset + rangeLength)) - pos= -1; + if (widgetPos != -1 && (modelPos < rangeOffset || modelPos + length > rangeOffset + rangeLength)) + widgetPos= -1; - if (pos > -1) { + if (widgetPos > -1) { + if (redraws()) { - fTextWidget.setSelectionRange(pos, length); - internalRevealRange(pos, pos + length); - selectionChanged(pos, length); + fTextWidget.setSelectionRange(widgetPos, length); + internalRevealRange(widgetPos, widgetPos + length); + selectionChanged(widgetPos, length); } else { - setSelectedRange(pos + getVisibleRegionOffset(), length); + setSelectedRange(modelPos, length); } + + return modelPos; } - return pos + getVisibleRegionOffset(); + + } catch (BadLocationException x) { if (TRACE_ERRORS) System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$ @@ -3296,10 +3249,17 @@ public class TextViewer extends Viewer implements s.start= start; s.length= length; - fTextWidget.setStyleRange(s); - - if (controlRedraw) - fTextWidget.setRedraw(true); + s= modelStyleRange2WidgetStyleRange(s); + if (s != null) { + + if (controlRedraw) + fTextWidget.setRedraw(false); + + fTextWidget.setStyleRange(s); + + if (controlRedraw) + fTextWidget.setRedraw(true); + } } } @@ -3313,34 +3273,69 @@ public class TextViewer extends Viewer implements StyleRange range= presentation.getDefaultStyleRange(); if (range != null) { - fTextWidget.setStyleRange(range); + range= modelStyleRange2WidgetStyleRange(range); + if (range != null) + fTextWidget.setStyleRange(range); + Iterator e= presentation.getNonDefaultStyleRangeIterator(); while (e.hasNext()) { range= (StyleRange) e.next(); - fTextWidget.setStyleRange(range); + range= modelStyleRange2WidgetStyleRange(range); + if (range != null) + fTextWidget.setStyleRange(range); } } else { - IRegion coverage= presentation.getCoverage(); - if (coverage != null) { - Iterator e= presentation.getAllStyleRangeIterator(); - StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()]; - for (int i= 0; i < ranges.length; i++) - ranges[i]= (StyleRange) e.next(); + List list= new ArrayList(); + Iterator e= presentation.getAllStyleRangeIterator(); + while (e.hasNext()) { + range= (StyleRange) e.next(); + range= modelStyleRange2WidgetStyleRange(range); + if (range != null) + list.add(range); + } - fTextWidget.replaceStyleRanges(coverage.getOffset(), coverage.getLength(), ranges); + if (!list.isEmpty()) { + StyleRange[] ranges= new StyleRange[list.size()]; + list.toArray(ranges); + IRegion region= modelRange2WidgetRange(presentation.getCoverage()); + fTextWidget.replaceStyleRanges(region.getOffset(), region.getLength(), ranges); } } } /** + * Applies the given presentation to the given text widget. Helper method. + * + * @param presentation the style information + * @since 2.1 + */ + private void applyTextPresentation(TextPresentation presentation) { + + List list= new ArrayList(); + Iterator e= presentation.getAllStyleRangeIterator(); + while (e.hasNext()) { + StyleRange range= (StyleRange) e.next(); + range= modelStyleRange2WidgetStyleRange(range); + if (range != null) + list.add(range); + } + + if (!list.isEmpty()) { + StyleRange[] ranges= new StyleRange[list.size()]; + list.toArray(ranges); + fTextWidget.setStyleRanges(ranges); + } + } + + /** * Returns the visible region if it is not equal to the whole document. * Otherwise returns <code>null</code>. * * @return the viewer's visible region if smaller than input document, otherwise <code>null</code> */ - protected IRegion internalGetVisibleRegion() { + protected IRegion _internalGetVisibleRegion() { IDocument document= getVisibleDocument(); if (document instanceof ChildDocument) { @@ -3359,7 +3354,6 @@ public class TextViewer extends Viewer implements if (presentation == null || !redraws()) return; - presentation.setResultWindow(internalGetVisibleRegion()); if (presentation.isEmpty() || fTextWidget == null) return; @@ -3367,7 +3361,7 @@ public class TextViewer extends Viewer implements fTextWidget.setRedraw(false); if (fReplaceTextPresentation) - TextPresentation.applyTextPresentation(presentation, fTextWidget); + applyTextPresentation(presentation); else addPresentation(presentation); @@ -3483,7 +3477,7 @@ public class TextViewer extends Viewer implements fMarkPosition.undelete(); } - markChanged(fMarkPosition.offset - getVisibleRegionOffset(), 0); + markChanged(modelOffset2WidgetOffset(fMarkPosition.offset), 0); } } @@ -3574,11 +3568,6 @@ public class TextViewer extends Viewer implements if (fTextWidget != null && !fTextWidget.isDisposed()) fTextWidget.setRedraw(false); - - /* - * TODO: should be removed. - */ - fireRedrawChanged(); } /* @@ -3659,4 +3648,192 @@ public class TextViewer extends Viewer implements return fTextHoverManager.getHoverEventLocation(); } + + // ----------------------------------- conversions ------------------------------------------------------- + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#modelLine2WidgetLine(int) + */ + public int modelLine2WidgetLine(int modelLine) { + if (fInformationMapping == null) + return modelLine; + + try { + return fInformationMapping.toImageLine(modelLine); + } catch (BadLocationException x) { + } + + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#modelOffset2WidgetOffset(int) + */ + public int modelOffset2WidgetOffset(int modelOffset) { + if (fInformationMapping == null) + return modelOffset; + + try { + return fInformationMapping.toImageOffset(modelOffset); + } catch (BadLocationException x) { + } + + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#modelRange2WidgetRange(org.eclipse.jface.text.IRegion) + */ + public IRegion modelRange2WidgetRange(IRegion modelRange) { + if (fInformationMapping == null) + return modelRange; + + try { + return fInformationMapping.toImageRegion(modelRange); + } catch (BadLocationException x) { + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#widgetlLine2ModelLine(int) + */ + public int widgetlLine2ModelLine(int widgetLine) { + if (fInformationMapping == null) + return widgetLine; + + try { + return fInformationMapping.toOriginLine(widgetLine); + } catch (BadLocationException x) { + } + + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#widgetOffset2ModelOffset(int) + */ + public int widgetOffset2ModelOffset(int widgetOffset) { + if (fInformationMapping == null) + return widgetOffset; + + try { + return fInformationMapping.toOriginOffset(widgetOffset); + } catch (BadLocationException x) { + if (widgetOffset == getVisibleDocument().getLength()) { + IRegion coverage= fInformationMapping.getCoverage(); + return coverage.getOffset() + coverage.getLength(); + } + } + + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#widgetRange2ModelRange(org.eclipse.jface.text.IRegion) + */ + public IRegion widgetRange2ModelRange(IRegion widgetRange) { + if (fInformationMapping == null) + return widgetRange; + + try { + return fInformationMapping.toOriginRegion(widgetRange); + } catch (BadLocationException x) { + int modelOffset= widgetOffset2ModelOffset(widgetRange.getOffset()); + if (modelOffset > -1) { + int modelEndOffset= widgetOffset2ModelOffset(widgetRange.getOffset() + widgetRange.getLength()); + if (modelEndOffset > -1) + return new Region(modelOffset, modelEndOffset - modelOffset); + } + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#getModelCoverage() + */ + public IRegion getModelCoverage() { + if (fInformationMapping == null) { + IDocument document= getDocument(); + if (document == null) + return null; + return new Region(0, document.getLength()); + } + + return fInformationMapping.getCoverage(); + } + + protected int getClosestWidgetLineForModelLine(int modelLine) { + if (fInformationMapping == null) + return modelLine; + + try { + return fInformationMapping.toClosestImageLine(modelLine); + } catch (BadLocationException x) { + } + + return -1; + } + + protected StyleRange modelStyleRange2WidgetStyleRange(StyleRange range) { + IRegion region= modelRange2WidgetRange(new Region(range.start, range.length)); + if (region != null) { + StyleRange result= (StyleRange) range.clone(); + result.start= region.getOffset(); + result.length= region.getLength(); + return result; + } + return null; + } + + protected IRegion modelRange2WidgetRange(Position modelPosition) { + return modelRange2WidgetRange(new Region(modelPosition.getOffset(), modelPosition.getLength())); + } + + protected IRegion event2ModelRange(VerifyEvent event) { + + Region region= null; + if (event.start <= event.end) + region= new Region(event.start, event.end - event.start); + else + region= new Region(event.end, event.start - event.end); + + return widgetRange2ModelRange(region); + } + + protected Point widgetSelection2ModelSelection(Point widgetSelection) { + IRegion region= new Region(widgetSelection.x, widgetSelection.y); + region= widgetRange2ModelRange(region); + return region == null ? null : new Point(region.getOffset(), region.getLength()); + } + + protected Point modelSelection2WidgetSelection(Point modelSelection) { + if (fInformationMapping == null) + return modelSelection; + + try { + IRegion region= new Region(modelSelection.x, modelSelection.y); + region= fInformationMapping.toImageRegion(region); + return new Point(region.getOffset(), region.getLength()); + } catch (BadLocationException x) { + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextViewerExtension3#widgetLineOfWidgetOffset(int) + */ + public int widgetLineOfWidgetOffset(int widgetOffset) { + IDocument document= getVisibleDocument(); + if (document != null) { + try { + return document.getLineOfOffset(widgetOffset); + } catch (BadLocationException e) { + } + } + return -1; + } } diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewerHoverManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewerHoverManager.java index 23a1fbdd002..864a4da69c4 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewerHoverManager.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewerHoverManager.java @@ -174,14 +174,18 @@ class TextViewerHoverManager extends AbstractHoverInformationControlManager impl */ private int computeOffsetAtLocation(int x, int y) { - StyledText styledText= fTextViewer.getTextWidget(); - IDocument document= fTextViewer.getVisibleDocument(); - - if (document == null) - return -1; - try { - return styledText.getOffsetAtLocation(new Point(x, y)) + fTextViewer.getVisibleRegionOffset(); + + StyledText styledText= fTextViewer.getTextWidget(); + int widgetOffset= styledText.getOffsetAtLocation(new Point(x, y)); + + if (fTextViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fTextViewer; + return extension.widgetOffset2ModelOffset(widgetOffset); + } + + return widgetOffset + fTextViewer._getVisibleRegionOffset(); + } catch (IllegalArgumentException e) { return -1; } @@ -195,14 +199,11 @@ class TextViewerHoverManager extends AbstractHoverInformationControlManager impl */ private Rectangle computeArea(IRegion region) { + IRegion widgetRegion= modelRange2WidgetRange(region); + int start= widgetRegion.getOffset(); + int end= widgetRegion.getOffset() + widgetRegion.getLength(); + StyledText styledText= fTextViewer.getTextWidget(); - - IRegion visibleRegion= fTextViewer.getVisibleRegion(); - int start= region.getOffset() - visibleRegion.getOffset(); - int end= start + region.getLength(); - if (end > visibleRegion.getLength()) - end= visibleRegion.getLength(); - Point upperLeft= styledText.getLocationAtOffset(start); Point lowerRight= new Point(upperLeft.x, upperLeft.y); @@ -231,6 +232,26 @@ class TextViewerHoverManager extends AbstractHoverInformationControlManager impl return new Rectangle(upperLeft.x, upperLeft.y, width, height); } + /** + * Method modelRange2WidgetRange. + * @param region + * @return IRegion + */ + private IRegion modelRange2WidgetRange(IRegion region) { + if (fTextViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fTextViewer; + return extension.modelRange2WidgetRange(region); + } + + IRegion visibleRegion= fTextViewer.getVisibleRegion(); + int start= region.getOffset() - visibleRegion.getOffset(); + int end= start + region.getLength(); + if (end > visibleRegion.getLength()) + end= visibleRegion.getLength(); + + return new Region(start, end - start); + } + /* * @see AbstractInformationControlManager#showInformationControl(Rectangle) */ diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/information/InformationPresenter.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/information/InformationPresenter.java index 4360fe922d5..7c7390a056a 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/information/InformationPresenter.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/information/InformationPresenter.java @@ -37,9 +37,11 @@ import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.IWidgetTokenKeeper; import org.eclipse.jface.text.IWidgetTokenOwner; +import org.eclipse.jface.text.Region; import org.eclipse.jface.util.Assert; @@ -308,13 +310,12 @@ public class InformationPresenter extends AbstractInformationControlManager impl * @return the graphical extend of the given region */ private Rectangle computeArea(IRegion region) { + + IRegion widgetRegion= modelRange2WidgetRange(region); + int start= widgetRegion.getOffset(); + int end= widgetRegion.getOffset() + widgetRegion.getLength(); StyledText styledText= fTextViewer.getTextWidget(); - - IRegion visible= fTextViewer.getVisibleRegion(); - int start= region.getOffset() - visible.getOffset(); - int end= start + region.getLength(); - Point upperLeft= styledText.getLocationAtOffset(start); Point lowerRight= new Point(upperLeft.x, upperLeft.y); @@ -345,6 +346,26 @@ public class InformationPresenter extends AbstractInformationControlManager impl return new Rectangle(upperLeft.x, upperLeft.y, width, height); } + /** + * Method modelRange2WidgetRange. + * @param region + * @return IRegion + */ + private IRegion modelRange2WidgetRange(IRegion region) { + if (fTextViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fTextViewer; + return extension.modelRange2WidgetRange(region); + } + + IRegion visibleRegion= fTextViewer.getVisibleRegion(); + int start= region.getOffset() - visibleRegion.getOffset(); + int end= start + region.getLength(); + if (end > visibleRegion.getLength()) + end= visibleRegion.getLength(); + + return new Region(start, end - start); + } + /* * @see IInformationPresenter#install(ITextViewer) */ diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/presentation/PresentationReconciler.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/presentation/PresentationReconciler.java index 566be49bc0a..fcce99149e8 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/presentation/PresentationReconciler.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/presentation/PresentationReconciler.java @@ -28,6 +28,7 @@ import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextInputListener; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextEvent; @@ -175,13 +176,12 @@ public class PresentationReconciler implements IPresentationReconciler { IDocument d= fViewer.getDocument(); processDamage(new Region(0, d.getLength()), d); } else { - IRegion visible= fViewer.getVisibleRegion(); - IRegion region= new Region(e.getOffset() + visible.getOffset(), e.getLength()); + IRegion region= widgetRegion2ModelRegion(e); processDamage(region, fViewer.getDocument()); } } else { - + IRegion damage= getDamage(de); if (damage != null) processDamage(damage, de.getDocument()); @@ -190,6 +190,17 @@ public class PresentationReconciler implements IPresentationReconciler { fDocumentPartitioningChanged= false; fChangedDocumentPartitions= null; } + + protected IRegion widgetRegion2ModelRegion(TextEvent e) { + if (fViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fViewer; + return extension.widgetRange2ModelRange(new Region(e.getOffset(), e.getLength())); + } + + IRegion visible= fViewer.getVisibleRegion(); + IRegion region= new Region(e.getOffset() + visible.getOffset(), e.getLength()); + return region; + } }; /** The map of presentation damagers. */ diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java index fc1d1141efa..33f0a0a75ae 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java @@ -20,6 +20,8 @@ import org.eclipse.jface.text.AbstractHoverInformationControlManager; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewerExtension3; + import org.eclipse.jface.util.Assert; @@ -73,14 +75,18 @@ class AnnotationBarHoverManager extends AbstractHoverInformationControlManager { } /** - * Returns for a given absolute line number the corresponding line - * number relative to the viewer's visible region. - * + * Returns for the widget line number for the given document line number. + * * @param line the absolute line number * @return the line number relative to the viewer's visible region * @throws BadLocationException if <code>line</code> is not valid in the viewer's document */ - private int getRelativeLineNumber(int line) throws BadLocationException { + private int getWidgetLineNumber(int line) throws BadLocationException { + if (fSourceViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) fSourceViewer; + return extension.modelLine2WidgetLine(line); + } + IRegion region= fSourceViewer.getVisibleRegion(); int firstLine= fSourceViewer.getDocument().getLineOfOffset(region.getOffset()); return line - firstLine; @@ -96,7 +102,7 @@ class AnnotationBarHoverManager extends AbstractHoverInformationControlManager { try { StyledText text= fSourceViewer.getTextWidget(); int lineHeight= text.getLineHeight(); - int y= getRelativeLineNumber(line) * lineHeight - text.getTopPixel(); + int y= getWidgetLineNumber(line) * lineHeight - text.getTopPixel(); Point size= fVerticalRuler.getControl().getSize(); return new Rectangle(0, y, size.x, lineHeight); } catch (BadLocationException x) { diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java index 8c0959ae1a4..cc1bb18a3a4 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java @@ -37,8 +37,10 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextEvent; @@ -97,6 +99,8 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { private InternalListener fInternalListener= new InternalListener(); /** The width of this vertical ruler */ private int fWidth; + /** Switch for enabling/disabling the setModel method. */ + private boolean fAllowSetModel= true; /** @@ -104,6 +108,18 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { * * @param width the width of the vertical ruler */ + public AnnotationRulerColumn(IAnnotationModel model, int width) { + fWidth= width; + fAllowSetModel= false; + fModel= model; + fModel.addAnnotationModelListener(fInternalListener); + } + + /** + * Constructs this column with the given width. + * + * @param width the width of the vertical ruler + */ public AnnotationRulerColumn(int width) { fWidth= width; } @@ -158,6 +174,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { public void mouseDoubleClick(MouseEvent event) { fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y); + mouseDoubleClicked(fParentRuler.getLineOfLastMouseButtonActivity()); } }); @@ -169,6 +186,9 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { return fCanvas; } + protected void mouseDoubleClicked(int rulerLine) { + } + /** * Disposes the ruler's resources. */ @@ -214,7 +234,11 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { try { gc.setBackground(fCanvas.getBackground()); gc.fillRectangle(0, 0, size.x, size.y); - doPaint(gc); + + if (fCachedTextViewer instanceof ITextViewerExtension3) + doPaint1(gc); + else + doPaint(gc); } finally { gc.dispose(); } @@ -331,6 +355,64 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { } } + protected void doPaint1(GC gc) { + + if (fModel == null || fCachedTextViewer == null) + return; + + ITextViewerExtension3 extension= (ITextViewerExtension3) fCachedTextViewer; + + fScrollPos= fCachedTextWidget.getTopPixel(); + int lineheight= fCachedTextWidget.getLineHeight(); + Point dimension= fCanvas.getSize(); + int shift= fCachedTextViewer.getTopInset(); + + // draw Annotations + Rectangle r= new Rectangle(0, 0, 0, 0); + int maxLayer= 1; // loop at least once thru layers. + + for (int layer= 0; layer < maxLayer; layer++) { + Iterator iter= fModel.getAnnotationIterator(); + while (iter.hasNext()) { + + Annotation annotation= (Annotation) iter.next(); + + int lay= annotation.getLayer(); + maxLayer= Math.max(maxLayer, lay+1); // dynamically update layer maximum + if (lay != layer) // wrong layer: skip annotation + continue; + + Position position= fModel.getPosition(annotation); + if (position == null) + continue; + + IRegion widgetRegion= extension.modelRange2WidgetRange(new Region(position.getOffset(), position.getLength())); + if (widgetRegion == null) + continue; + + int startLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset()); + if (startLine == -1) + continue; + + int endLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset() + Math.max(widgetRegion.getLength() -1, 0)); + if (endLine == -1) + continue; + + r.x= 0; + r.y= (startLine * lineheight) - fScrollPos + shift; + r.width= dimension.x; + int lines= endLine - startLine; + if (lines < 0) + lines= -lines; + r.height= (lines+1) * lineheight; + + if (r.y < dimension.y) // annotation within visible area + annotation.paint(gc, fCanvas, r); + } + } + } + + /** * Post a redraw request for thid column into the UI thread. */ @@ -362,7 +444,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { * @see IVerticalRulerColumn#setModel */ public void setModel(IAnnotationModel model) { - if (model != fModel) { + if (fAllowSetModel && model != fModel) { if (fModel != null) fModel.removeAnnotationModelListener(fInternalListener); @@ -381,4 +463,12 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn { */ public void setFont(Font font) { } + + protected ITextViewer getCachedTextViewer() { + return fCachedTextViewer; + } + + protected IAnnotationModel getModel() { + return fModel; + } } diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/CompositeRuler.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/CompositeRuler.java index 406e9c23728..6bbd3a228e5 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/CompositeRuler.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/CompositeRuler.java @@ -47,6 +47,7 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension; +import org.eclipse.jface.text.ITextViewerExtension3; /** @@ -693,15 +694,24 @@ public class CompositeRuler implements IVerticalRuler, IVerticalRulerExtension { return -1; StyledText text= fTextViewer.getTextWidget(); - int line= ((y_coordinate + text.getTopPixel()) / text.getLineHeight()); + int line= ((y_coordinate + text.getTopPixel()) / text.getLineHeight()); + return widgetLine2ModelLine(fTextViewer, line); + } + + protected final static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) { + + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + return extension.widgetlLine2ModelLine(widgetLine); + } + try { - IRegion r= fTextViewer.getVisibleRegion(); - IDocument d= fTextViewer.getDocument(); - line += d.getLineOfOffset(r.getOffset()); + IRegion r= viewer.getVisibleRegion(); + IDocument d= viewer.getDocument(); + return widgetLine += d.getLineOfOffset(r.getOffset()); } catch (BadLocationException x) { } - - return line; + return widgetLine; } /** diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java index 23d0a20c7a6..c639ccd2c31 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java @@ -41,6 +41,7 @@ import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.TextEvent; @@ -512,7 +513,12 @@ public final class LineNumberRulerColumn implements IVerticalRulerColumn { try { gc.setBackground(getBackground(fCanvas.getDisplay())); gc.fillRectangle(0, 0, size.x, size.y); - doPaint(gc); + + if (fCachedTextViewer instanceof ITextViewerExtension3) + doPaint1(gc); + else + doPaint(gc); + } finally { gc.dispose(); } @@ -584,6 +590,67 @@ public final class LineNumberRulerColumn implements IVerticalRulerColumn { } } + private void doPaint1(GC gc) { + + if (fCachedTextViewer == null) + return; + + ITextViewerExtension3 extension= (ITextViewerExtension3) fCachedTextViewer; + + int firstLine= 0; + + + int widgetTopLine= fCachedTextWidget.getTopIndex(); + if (widgetTopLine > 0) + -- widgetTopLine; + + int topLine= extension.widgetlLine2ModelLine(widgetTopLine); + int bottomLine= fCachedTextViewer.getBottomIndex(); + if (bottomLine >= 0) + ++ bottomLine; + + try { + + IRegion region= extension.getModelCoverage(); + IDocument doc= fCachedTextViewer.getDocument(); + + firstLine= doc.getLineOfOffset(region.getOffset()); + if (firstLine > topLine || topLine == -1) + topLine= firstLine; + + int lastLine= doc.getLineOfOffset(region.getOffset() + region.getLength()); + if (lastLine < bottomLine || bottomLine == -1) + bottomLine= lastLine; + + } catch (BadLocationException x) { + return; + } + + fSensitiveToTextChanges= bottomLine - topLine < getVisibleLinesInViewport(); + + int lineheight= fCachedTextWidget.getLineHeight(); + fScrollPos= fCachedTextWidget.getTopPixel(); + int canvasheight= fCanvas.getSize().y; + + NumberFormat nf= NumberFormat.getInstance(); + + int y= (widgetTopLine * lineheight) - fScrollPos + fCachedTextViewer.getTopInset(); + for (int modelLine= topLine; modelLine <= bottomLine; modelLine++) { + + if (y >= canvasheight) + break; + + int widgetLine= extension.modelLine2WidgetLine(modelLine); + if (widgetLine == -1) + continue; + + String s= Integer.toString(modelLine + 1); + int indentation= fIndentation[s.length()]; + gc.drawString(nf.format(modelLine + 1), indentation, y); + y+= lineheight; + } + } + /* * @see IVerticalRulerColumn#redraw */ diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java index dcad1009c21..b4811d1c99e 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java @@ -423,7 +423,7 @@ public class SourceViewer extends TextViewer implements ISourceViewer { IDocument document= getDocument(); Position p= new Position(s.x, s.y); - IRegion r= (s.y == 0) ? getVisibleRegion() : new Region(s.x, s.y); + IRegion r= (s.y == 0) ? getModelCoverage() : new Region(s.x, s.y); try { setRedraw(false); diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VerticalRuler.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VerticalRuler.java index 78ef11c835f..fab8064dcc8 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VerticalRuler.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VerticalRuler.java @@ -32,8 +32,10 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextEvent; @@ -201,7 +203,12 @@ public final class VerticalRuler implements IVerticalRuler, IVerticalRulerExtens try { gc.setBackground(fCanvas.getBackground()); gc.fillRectangle(0, 0, size.x, size.y); - doPaint(gc); + + if (fTextViewer instanceof ITextViewerExtension3) + doPaint1(gc); + else + doPaint(gc); + } finally { gc.dispose(); } @@ -238,7 +245,7 @@ public final class VerticalRuler implements IVerticalRuler, IVerticalRulerExtens * * @param gc the gc to draw into */ - private void doPaint(GC gc) { + protected void doPaint(GC gc) { if (fModel == null || fTextViewer == null) return; @@ -320,6 +327,64 @@ public final class VerticalRuler implements IVerticalRuler, IVerticalRulerExtens } } } + + protected void doPaint1(GC gc) { + + if (fModel == null || fTextViewer == null) + return; + + ITextViewerExtension3 extension= (ITextViewerExtension3) fTextViewer; + StyledText textWidget= fTextViewer.getTextWidget(); + + fScrollPos= textWidget.getTopPixel(); + int lineheight= textWidget.getLineHeight(); + Point dimension= fCanvas.getSize(); + int shift= fTextViewer.getTopInset(); + + // draw Annotations + Rectangle r= new Rectangle(0, 0, 0, 0); + int maxLayer= 1; // loop at least once thru layers. + + for (int layer= 0; layer < maxLayer; layer++) { + Iterator iter= fModel.getAnnotationIterator(); + while (iter.hasNext()) { + + Annotation annotation= (Annotation) iter.next(); + + int lay= annotation.getLayer(); + maxLayer= Math.max(maxLayer, lay+1); // dynamically update layer maximum + if (lay != layer) // wrong layer: skip annotation + continue; + + Position position= fModel.getPosition(annotation); + if (position == null) + continue; + + IRegion widgetRegion= extension.modelRange2WidgetRange(new Region(position.getOffset(), position.getLength())); + if (widgetRegion == null) + continue; + + int startLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset()); + if (startLine == -1) + continue; + + int endLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset() + Math.max(widgetRegion.getLength() -1, 0)); + if (endLine == -1) + continue; + + r.x= 0; + r.y= (startLine * lineheight) - fScrollPos + shift; + r.width= dimension.x; + int lines= endLine - startLine; + if (lines < 0) + lines= -lines; + r.height= (lines+1) * lineheight; + + if (r.y < dimension.y) // annotation within visible area + annotation.paint(gc, fCanvas, r); + } + } + } /** * Thread-safe implementation. @@ -401,15 +466,24 @@ public final class VerticalRuler implements IVerticalRuler, IVerticalRulerExtens return -1; StyledText text= fTextViewer.getTextWidget(); - int line= ((y_coordinate + fScrollPos) / text.getLineHeight()); + int line= ((y_coordinate + fScrollPos) / text.getLineHeight()); + return widgetLine2ModelLine(fTextViewer, line); + } + + protected final static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) { + + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + return extension.widgetlLine2ModelLine(widgetLine); + } + try { - IRegion r= fTextViewer.getVisibleRegion(); - IDocument d= fTextViewer.getDocument(); - line += d.getLineOfOffset(r.getOffset()); + IRegion r= viewer.getVisibleRegion(); + IDocument d= viewer.getDocument(); + return widgetLine += d.getLineOfOffset(r.getOffset()); } catch (BadLocationException x) { } - - return line; + return widgetLine; } /* diff --git a/org.eclipse.text/.classpath b/org.eclipse.text/.classpath index d8b3fa0d8f2..16fb22f551c 100644 --- a/org.eclipse.text/.classpath +++ b/org.eclipse.text/.classpath @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="projection"/> <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/> + <classpathentry kind="src" path="/org.junit"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/org.eclipse.text/.project b/org.eclipse.text/.project index 9e0b25af586..e6a88f34e13 100644 --- a/org.eclipse.text/.project +++ b/org.eclipse.text/.project @@ -3,6 +3,7 @@ <name>org.eclipse.text</name> <comment></comment> <projects> + <project>org.junit</project> </projects> <buildSpec> <buildCommand> diff --git a/org.eclipse.text/build.properties b/org.eclipse.text/build.properties index 04e9be9a51b..03e53ece0c8 100644 --- a/org.eclipse.text/build.properties +++ b/org.eclipse.text/build.properties @@ -1,4 +1,5 @@ bin.includes = plugin.properties,\ plugin.xml,\ *.jar -source.text.jar = src/ +source.text.jar = src/,\ + projection/ diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java b/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java new file mode 100644 index 00000000000..f4c7c3017f8 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java @@ -0,0 +1,288 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + +import java.util.Arrays; +import java.util.Comparator; + +/** + * + */ +public class CoordinatesTranslator implements IDocumentInformationMapping { + + private IDocument fParentDocument; + private String fParentCategory; + private ProjectionDocument fProjectionDocument; + private String fProjectionCategory; + + public CoordinatesTranslator(IDocument parent, String parentCategory, ProjectionDocument projection, String projectionCategory) { + fParentDocument= parent; + fParentCategory= parentCategory; + fProjectionDocument= projection; + fProjectionCategory= projectionCategory; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginOffset(int) + */ + public int toOriginOffset(int imageOffset) throws BadLocationException { + Fragment fragment= (Fragment) getPositionOfOffset(fProjectionDocument, ProjectionDocument.FRAGMENT_CATEGORY, imageOffset); + if (fragment == null) { + if (imageOffset == 0) + return 0; + throw new BadLocationException(); + } + + int relative= imageOffset - fragment.offset; + return fragment.getOrigin().offset + relative; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginRegion(org.eclipse.jface.text.IRegion) + */ + public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException { + + int projectionOffset= imageRegion.getOffset(); + int projectionLength= imageRegion.getLength(); + + if (projectionLength == 0) { + if (projectionOffset == 0 && projectionLength == fProjectionDocument.getLength()) + return new Region(0, fParentDocument.getLength()); + return new Region(toOriginOffset(projectionOffset), 0); + } + + int o1= toOriginOffset(projectionOffset); + int o2= toOriginOffset(projectionOffset + projectionLength -1); + return new Region(o1, o2 - o1 + 1); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLines(int) + */ + public IRegion toOriginLines(int imageLine) throws BadLocationException { + + IRegion projectionDocumentRegion= fProjectionDocument.getLineInformation(imageLine); + IRegion parentDocumentRegion= toOriginRegion(projectionDocumentRegion); + + int startLine= fParentDocument.getLineOfOffset(parentDocumentRegion.getOffset()); + if (parentDocumentRegion.getLength() == 0) + return new Region(startLine, 0); + + int endLine= fParentDocument.getLineOfOffset(parentDocumentRegion.getOffset() + parentDocumentRegion.getLength() -1); + return new Region(startLine, endLine - startLine); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLine(int) + */ + public int toOriginLine(int imageLine) throws BadLocationException { + IRegion lines= toOriginLines(imageLine); + if (lines.getLength() > 0) + throw new IllegalStateException(); + return lines.getOffset(); + } + + public int toImageOffset(int originOffset) throws BadLocationException { + ProjectionPosition projection= (ProjectionPosition) getPositionOfOffset(fParentDocument, ProjectionDocumentManager.PROJECTION_DOCUMENTS, originOffset); + if (projection != null) + return translateOffset(projection, originOffset, projection.getFragment()); + // not included + return -1; + } + + public IRegion toImageRegion(IRegion originRegion) throws BadLocationException { + + if (originRegion.getLength() == 0) { + int projectionOffset= toImageOffset(originRegion.getOffset()); + return projectionOffset == -1 ? null : new Region(projectionOffset, 0); + } + + Position[] positions= getPositionsOfRange(fParentDocument, ProjectionDocumentManager.PROJECTION_DOCUMENTS, originRegion, null); + if (positions != null && positions.length > 0) { + ProjectionPosition projection= (ProjectionPosition) positions[0]; + + int offset= originRegion.getOffset(); + int length= originRegion.getLength(); + + int delta= projection.getOffset() - offset; + if (delta > 0) { + offset += delta; + length -= delta; + } + int start= translateOffset(projection, offset, projection.getFragment()); + + projection= (ProjectionPosition) positions[positions.length -1]; + int decrease= 0; + int endOffset= offset + length; + if (length > 0) + decrease= 1; + endOffset -= decrease; + + delta= endOffset - (projection.getOffset() + Math.max(projection.getLength() -1, 0)); + if (delta > 0) + endOffset -= delta; + + int end= translateOffset(projection, endOffset, projection.getFragment()); + return new Region(start, end - start + decrease); + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageLine(int) + */ + public int toImageLine(int originLine) throws BadLocationException { + + IRegion parentDocumentRegion= fParentDocument.getLineInformation(originLine); + IRegion projectionDocumentRegion= toImageRegion(parentDocumentRegion); + if (projectionDocumentRegion == null) + return -1; + + int startLine= fProjectionDocument.getLineOfOffset(projectionDocumentRegion.getOffset()); + if (projectionDocumentRegion.getLength() == 0) + return startLine; + + int endLine= fProjectionDocument.getLineOfOffset(projectionDocumentRegion.getOffset() + projectionDocumentRegion.getLength() -1); + if (endLine != startLine) + throw new IllegalStateException(); + + return startLine; + } + + + //----------------------------------------------------------------------------------------------------------------------------------- + + + private int translateOffset(Position origin, int originOffset, Position target) { + int relative= originOffset - origin.offset; + return target.offset + relative; + } + + private Position getPositionOfOffset(IDocument document, String category, int offset) throws BadLocationException { + try { + int index= getPositionIndexOfOffset(document, category, offset, 0); + if (index > -1) { + Position[] positions= document.getPositions(category); + return positions[index]; + } + } catch (BadPositionCategoryException x) { + } + return null; + } + + private Position[] getPositionsOfRange(IDocument document, String category, IRegion range, Comparator comparator) { + + int offset= range.getOffset(); + int length= range.getLength(); + + try { + + int start= getPositionIndexOfOffset(document, category, offset, length); + int end= getPositionIndexOfOffset(document, category, offset + length -1, 1 - length); + + if (start > -1 && end > -1) { + + Position[] positions= document.getPositions(category); + + if (start == end) + return new Position[] { positions[start] }; + + Position[] result= new Position[end - start + 1]; + for (int i= start; i <= end; i++) + result[i - start]= positions[i]; + + if (comparator != null) + Arrays.sort(result, comparator); + + return result; + } + + } catch (BadPositionCategoryException e) { + } catch (BadLocationException e) { + } + + return new Position[0]; + } + + private int getPositionIndexOfOffset(IDocument document, String category, int offset, int direction ) throws BadPositionCategoryException, BadLocationException{ + + Position[] positions= document.getPositions(category); + if (positions != null && positions.length > 0) { + + // test for inclusion + int index= document.computeIndexInCategory(category, offset); + if (index < positions.length && positions[index].includes(offset)) + return index; + if (index > 0 && positions[index -1].includes(offset)) + return index -1; + + // find next accorrding to direction + if (direction != 0) { + if (direction > 0) { + if (index < positions.length && positions[index].overlapsWith(offset, direction)) + return index; + } else { + if (index > 0 && positions[index -1].overlapsWith(offset + direction, -direction)) + return index -1; + } + } + } + + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#getCoverage() + */ + public IRegion getCoverage() { + Position coverage= fProjectionDocument.getParentDocumentCoverage(); + return new Region(coverage.getOffset(), coverage.getLength()); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toClosestImageLine(int) + */ + public int toClosestImageLine(int originLine) throws BadLocationException { + try { + + int modelLineOffset= fParentDocument.getLineOffset(originLine); + int index= fParentDocument.computeIndexInCategory(ProjectionDocumentManager.PROJECTION_DOCUMENTS, modelLineOffset); + Position[] projections= fParentDocument.getPositions(ProjectionDocumentManager.PROJECTION_DOCUMENTS); + + if (index < projections.length) { + Position p= projections[index -1]; + int delta1= modelLineOffset - (p.getOffset() + p.getLength()); + p= projections[index]; + int delta2= modelLineOffset - (p.getOffset() + p.getLength()); + if (delta1 < delta2) { + p= projections[index -1]; + originLine= fParentDocument.getLineOfOffset(p.getOffset() + Math.max(p.getLength() -1, 0)); + } else { + originLine= fParentDocument.getLineOfOffset(p.getOffset()); + } + } else if (projections.length > 0) { + Position p= projections[index -1]; + originLine= fParentDocument.getLineOfOffset(p.getOffset() + Math.max(p.getLength() -1, 0)); + } else { + return 0; + } + + return toImageLine(originLine); + + } catch (BadLocationException x) { + } catch (BadPositionCategoryException x) { + } + + return 0; + } +} diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java b/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java new file mode 100644 index 00000000000..22ee665eee6 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java @@ -0,0 +1,43 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + +import org.eclipse.jface.text.Position; + +/** + * Fragment.java + */ +public class Fragment extends Position { + + private Position fOrigin; + + public Fragment(int offset, int length, Position origin) { + super(offset, length); + fOrigin= origin; + } + +// public Fragment(int offset, int length) { +// super(offset, length); +// } + + /** + * Returns the fOrigin. + * @return Position + */ + public Position getOrigin() { + return fOrigin; + } + + public void setOrigin(Position origin) { + fOrigin= origin; + } +} diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java b/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java new file mode 100644 index 00000000000..7233a2ce57d --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java @@ -0,0 +1,104 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + + +/** + * The position updater used to adapt the fragments of a projection document to + * changes of the master document. + */ +public class FragmentUpdater extends DefaultPositionUpdater { + + private boolean fShiftMode= false; + private boolean fIsLast= false; + + /** + * Creates the fragment updater. + */ + protected FragmentUpdater(String fragmentCategory) { + super(fragmentCategory); + } + + public void enableShiftMode(boolean enable) { + fShiftMode= enable; + } + + /** + * If an insertion happens at a fragment's offset, the fragment is extended + * rather than shifted. Also, the last fragment is extended if an inserted + * happends at the end of the fragment. + */ + protected void adaptToInsert() { + + if (fShiftMode) { + super.adaptToInsert(); + return; + } + + int myStart= fPosition.offset; + int myEnd= fPosition.offset + fPosition.length - (fIsLast ? 0 : 1); + myEnd= Math.max(myStart, myEnd); + + int yoursStart= fOffset; + int yoursEnd= fOffset + fReplaceLength -1; + yoursEnd= Math.max(yoursStart, yoursEnd); + + if (myEnd < yoursStart) + return; + + if (fLength <= 0) { + + if (myStart <= yoursStart) + fPosition.length += fReplaceLength; + else + fPosition.offset += fReplaceLength; + + } else { + + if (myStart <= yoursStart && fOriginalPosition.offset <= yoursStart) + fPosition.length += fReplaceLength; + else + fPosition.offset += fReplaceLength; + } + } + + /* + * @see IPositionUpdater#update(DocumentEvent event) + */ + public void update(DocumentEvent event) { + + 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]; + fIsLast= (i == category.length -1); + + fOriginalPosition.offset= fPosition.offset; + fOriginalPosition.length= fPosition.length; + + if (notDeleted()) + adaptToReplace(); + } + + } catch (BadPositionCategoryException x) { + // do nothing + } + } +};
\ No newline at end of file diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java new file mode 100644 index 00000000000..9191c9186d4 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java @@ -0,0 +1,745 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + +import java.util.Arrays; +import java.util.Comparator; + + + +/** + * A patch document represent a projection of its parent document. + * The patch document is always in sync with its parent document + * by utilizing the parent document as its <code>ITextStore</code>. + * This class is for internal use only. + * + * TODO: sorting Fragments on creation/joining + * + * @see ITextStore + */ +public final class ProjectionDocument extends AbstractDocument { + + final public static String FRAGMENT_CATEGORY= "__fragment_category"; + + /** The parent document */ + private IDocument fParentDocument; + /** The parent document as document extension */ + private IDocumentExtension fExtension; + /** The position category defining the projection */ + private String fProjectionCategory; + /** The document event issued by the parent document */ + private DocumentEvent fParentEvent; + /** The document event issued and to be issued by the patch document */ + private SlaveDocumentEvent fEvent; + /** Indicates whether the patch document initiated a parent document update or not */ + private boolean fIsUpdating= false; + /** The fragment updater */ + private FragmentUpdater fFragmentUpdater= new FragmentUpdater(FRAGMENT_CATEGORY); + + /** + * Creates a projection document of the given parent document. + * + * @param parentDocument the parent Document + * @param projectionCategory the document position category whose positions define the projection of the parent document + */ + public ProjectionDocument(IDocument parentDocument, String projectionCategory) { + super(); + + fParentDocument= parentDocument; + if (fParentDocument instanceof IDocumentExtension) + fExtension= (IDocumentExtension) fParentDocument; + + ITextStore s= new ProjectionTextStore(this); + ILineTracker tracker= new DefaultLineTracker(); + + setTextStore(s); + setLineTracker(tracker); + + completeInitialization(); + + initializeProjection(projectionCategory); + tracker.set(s.get(0, s.getLength())); + } + + /** + * Initializes the projection document from the parent document based on the given + * projection category. + * @param projectionCategory the document position category whose positions define the projection of the parent document + */ + private void initializeProjection(String projectionCategory) { + + fProjectionCategory= projectionCategory; + + try { + + addPositionCategory(FRAGMENT_CATEGORY); + addPositionUpdater(fFragmentUpdater); + + int offset= 0; + Position[] patch= fParentDocument.getPositions(fProjectionCategory); + for (int i= 0; i < patch.length; i++) { + Position p= patch[i]; + addPosition(FRAGMENT_CATEGORY, new Fragment(offset, p.length, p)); + offset += p.length; + } + + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + } + + /** + * Creates a fragment from a postion of the parent document. + * @param parentPosition a position of the parent document + * @return the fragment representing the range given by the parent position + */ + public Fragment createFragment(Position parentPosition) { + try { + + int index= fParentDocument.computeIndexInCategory(fProjectionCategory, parentPosition.offset); + if (index <= 0) + return new Fragment(0, parentPosition.length, parentPosition); + + Position[] fragments= getPositions(FRAGMENT_CATEGORY); + Position p= fragments[index -1]; + return new Fragment(p.offset + p.length, parentPosition.length, parentPosition); + + } catch (BadPositionCategoryException e) { + } catch (BadLocationException e) { + } + + return null; + } + + private int getPositionOfOffset(IDocument document, String category, int offset, int direction ) throws BadPositionCategoryException, BadLocationException{ + + Position[] positions= document.getPositions(category); + if (positions != null && positions.length > 0) { + + // test for inclusion + int index= document.computeIndexInCategory(category, offset); + if (index < positions.length && positions[index].includes(offset)) + return index; + if (index > 0 && positions[index -1].includes(offset)) + return index -1; + + // find next accorrding to direction + if (direction != 0) { + if (direction > 0) { + if (index < positions.length && positions[index].overlapsWith(offset, direction)) + return index; + } else { + if (index > 0 && positions[index -1].overlapsWith(offset + direction, -direction)) + return index -1; + } + } + } + + return -1; + } + + /** + * Returns the position which is used to manage a parent + * document range represented in this projection document and that + * includes or is close to the given parent document offset. The distance + * is computed based on the given direction hint. + * + * @param offsetInParent the parent document offset + * @param direction the direction hint used for computing the distance + * @return position the parent document position including or near to the parent document offset + */ + private Position getParentDocumentPositionOfOffset(int offsetInParent, int direction ) { + try { + + int index= getPositionOfOffset(fParentDocument, fProjectionCategory, offsetInParent, direction); + if (index > -1) { + Position[] positions= fParentDocument.getPositions(fProjectionCategory); + return positions[index]; + } + + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + + return null; + } + + /** + * Returns the offset in the projection document corresponding to the + * given parent document offset. + * + * @param offsetInParent the parent document offset + * @return the projection document offset corresponding to the given parent document offset + */ + private int toProjectionDocumentOffset(int offsetInParent, int direction) { + + Position p= getParentDocumentPositionOfOffset(offsetInParent, direction); + if (p == null) + return -1; + + int relative= offsetInParent - p.offset; + + if (direction > 0) { + if (relative < 0) + relative= 0; + } else if (direction < 0) { + if (relative >= p.length) + relative= p.length -1; + } + + Fragment f= findCorrespondingFragment(p); + return f.offset + relative; + } + + /** + * Creates a position describing the projection document range corresponding to + * the given parent document range. + * + * @param offsetInParent the parent document offset + * @param lengthInParent the parent document lengh + * @return position describing the projection document range corresponding to the given parent document range + */ + public Position computeProjectionDocumentPosition(int offsetInParent, int lengthInParent) { + + Position p= getParentDocumentCoverage(); + if (p != null) { + + if (p.overlapsWith(offsetInParent, lengthInParent)) { + + int o1= toProjectionDocumentOffset(offsetInParent, lengthInParent); + if (o1 == -1) + return null; + + if (lengthInParent == 0) + return new Position(o1, 0); + + int o2= toProjectionDocumentOffset(offsetInParent + lengthInParent -1, 1 - lengthInParent); + if (o2 == -1) + return null; + + return new Position(o1, o2 - o1 + 1); + + } else if (p.getOffset() + p.getLength() == offsetInParent + lengthInParent) { + + Position[] fragments= getFragmentation(); + if (fragments != null && fragments.length > 0) { + Position last= fragments[fragments.length -1]; + return new Position(last.getOffset() + last.getLength()); + } + } + } + + return null; + } + + public int toParentDocumentOffset(int offset) throws BadLocationException { + Fragment fragment= getFragmentOfOffset(offset); + + if (fragment == null) { + +// if (offset == 0) +// return 0; +// throw new BadLocationException(); + + Position[] fragmentation= getFragmentation(); + if (fragmentation != null && fragmentation.length > 0) { + Fragment last= (Fragment) fragmentation[fragmentation.length -1]; + if (last.offset + last.length == offset) { + Position origin= last.getOrigin(); + return origin.offset + origin.length; + } + } + + throw new BadLocationException(); + } + + int relative= offset - fragment.offset; + return fragment.getOrigin().offset + relative; + } + + public IRegion computeParentDocumentRegion(int offset, int length) throws BadLocationException { + + if (length == 0) { + if (offset == 0 && length == getLength()) + return new Region(0, fParentDocument.getLength()); + return new Region(toParentDocumentOffset(offset), 0); + } + + int o1= toParentDocumentOffset(offset); + int o2= toParentDocumentOffset(offset + length -1); + return new Region(o1, o2 - o1 + 1); + } + + /** + * Removes all fragments and thus empties this projection document. + */ + public void removeAllFragments() { + Position[] projection= getProjection(); + if (projection == null) + return; + + for (int i= 0; i < projection.length; i++) { + try { + removeFragment(projection[i]); + } catch (BadLocationException e) { + } + } + } + + /** + * Add a new fragment of the parent document to this projection document. + * + * @param offsetInParent offset of the parent document range + * @param lengthInParent length of the parent document range + * @return returns the position representing the parent document range in this projection document + * @throws BadLocationException + */ + public void addFragment(int offsetInParent, int lengthInParent) throws BadLocationException { + + if (lengthInParent == 0) + return; + + try { + + ProjectionPosition p= new ProjectionPosition(this, offsetInParent, lengthInParent); + fParentDocument.addPosition(fProjectionCategory, p); + + Fragment fragment= createFragment(p); + p.setFragment(fragment); + fireDocumentProjectionChanged(new DocumentEvent(this, fragment.offset, 0, fParentDocument.get(offsetInParent, lengthInParent))); + addPosition(FRAGMENT_CATEGORY, fragment); + + + getTracker().set(getStore().get(0, getStore().getLength())); + + } catch (BadPositionCategoryException x) { + } + + } + + public void joinFragments() { + try { + while (joinTwoFragments()) {} + } catch (BadPositionCategoryException x) { + } + } + + private boolean joinTwoFragments() throws BadPositionCategoryException { + Position[] projection= getProjection(); + if (projection != null && projection.length > 0) { + Position previous= projection[0]; + for (int i= 1; i < projection.length; i++) { + Position current= projection[i]; + if (previous.offset + previous.length == current.offset) { + join(previous, current); + return true; + } + previous= current; + } + } + return false; + } + + private void join(Position p1, Position p2) throws BadPositionCategoryException { + // remove p2 + Fragment fragment= findCorrespondingFragment(p2); + removePosition(FRAGMENT_CATEGORY, fragment); + fParentDocument.removePosition(fProjectionCategory, p2); + // extend p1 by length of p2 + fragment= findCorrespondingFragment(p1); + fragment.length += p2.length; + p1.length += p2.length; + } + + /** + * Removes the given parent document range from this projection document. + * + * @param parentPosition the position representing the parent document range + * @throws BadLocationException + */ + public void removeFragment(Position parentPosition) throws BadLocationException { + try { + + Fragment fragment= findCorrespondingFragment(parentPosition); + if (fragment != null) { + removePosition(FRAGMENT_CATEGORY, fragment); + fParentDocument.removePosition(fProjectionCategory, parentPosition); + fireDocumentProjectionChanged(new DocumentEvent(this, fragment.offset, fragment.length, null)); + getTracker().set(getStore().get(0, getStore().getLength())); + } + + } catch (BadPositionCategoryException x) { + } + } + + public Position[] getAffectedFragments(int offsetInParent, int lengthInParent) { + + Position p= computeProjectionDocumentPosition(offsetInParent, lengthInParent); + if (p == null) + return null; + + Fragment[] f= getFragmentsOfRange(p.offset, p.length); + if (f == null) + return null; + + Position[] result= new Position[f.length]; + for (int i= 0; i < f.length; i++) + result[i]= f[i].getOrigin(); + return result; + } + + /** + * Finds the fragment that represents the given parent document range in this projection document. + * + * @param parentPosition the parent document range + * @return the fragment representing the given parent document range + */ + private Fragment findCorrespondingFragment(Position parentPosition) { + try { + Position[] fragments= getPositions(FRAGMENT_CATEGORY); + for (int i= 0; i < fragments.length; i++) { + Fragment f= (Fragment) fragments[i]; + if (parentPosition.equals(f.getOrigin())) + return f; + } + } catch (BadPositionCategoryException x) { + } + + return null; + } + + /** + * Returns the fragment that contains the given offset. + * + * @param offset the offset + * @return the fragment that contains the given offset + */ + protected Fragment getFragmentOfOffset(int offset) throws BadLocationException { + try { + int index= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset, 0); + if (index > -1) { + Position[] fragments= getPositions(FRAGMENT_CATEGORY); + return (Fragment) fragments[index]; + } + } catch (BadPositionCategoryException x) { + } + return null; + } + + /** + * Returns the minimal consecutive list of fragments that completely covers the given range. + * + * @param offset the offset of the range + * @param length the length of the range + * @return the minimal consecutive list of fragments convering the given range + */ + protected Fragment[] getFragmentsOfRange(int offset, int length) { + + try { + + int start= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset, length); + int end= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset + length -1, 1 - length); + + if (start > -1 && end > -1) { + + Position[] positions= getPositions(FRAGMENT_CATEGORY); + + if (start == end) + return new Fragment[] { (Fragment) positions[start] }; + + Fragment[] result= new Fragment[end - start + 1]; + for (int i= start; i <= end; i++) + result[i - start]= (Fragment) positions[i]; + sortFragments(result); + return result; + } + + } catch (BadPositionCategoryException e) { + } catch (BadLocationException e) { + } + + return new Fragment[0]; + } + + /** + * Sorts a list of fragments based on the sequence of their origins in the parent document. + * @param result + */ + private void sortFragments(Object[] result) { + + Comparator comparator= new Comparator() { + + public int compare(Object o1, Object o2) { + Fragment f1= (Fragment) o1; + Fragment f2= (Fragment) o2; + return f1.getOrigin().getOffset() - f2.getOrigin().getOffset(); + } + + public boolean equals(Object obj) { + return false; + } + }; + + Arrays.sort(result, comparator); + } + + /** + * Returns the minimal range of the parent document that covers all fragments. + * + * @return a position describing the minimal parent document range covering all fragments + */ + public Position getParentDocumentCoverage() { + Position[] projection= getProjection(); + if (projection != null && projection.length > 0) { + Position first=projection[0]; + Position last= projection[projection.length -1]; + return new Position(first.offset, last.offset - first.offset + last.length); + } + return new Position(0, 0); + } + + private void fireDocumentProjectionChanged(DocumentEvent event) { + fFragmentUpdater.enableShiftMode(true); + try { + updatePositions(event); + } finally { + fFragmentUpdater.enableShiftMode(false); + } + } + + /** + * Returns parent document + * + * @return the parent document + */ + public IDocument getParentDocument() { + return fParentDocument; + } + + /** + * Returns the ranges of the parent document covered by this patch document. + * + * @return the child document's parent document range + */ + public Position[] getProjection() { + try { + return fParentDocument.getPositions(fProjectionCategory); + } catch (BadPositionCategoryException x) { + } + return null; + } + + public Position[] getFragmentation() { + try { + + Position[] fragmentation= getPositions(FRAGMENT_CATEGORY); + sortFragments(fragmentation); + return fragmentation; + + } catch (BadPositionCategoryException x) { + } + return null; + } + + /** + * Transforms a document event of the parent document into a patch document + * based document event. + * + * @param e the parent document event + * @return the child document event + */ + private SlaveDocumentEvent normalize(DocumentEvent e) { + + Position c= computeProjectionDocumentPosition(e.getOffset(), e.getLength()); + + if (c != null) { + if (c.length == 0) { + int insertLength= e.getText() == null ? 0 : e.getText().length(); + if (insertLength == 0) + return null; + } + return new SlaveDocumentEvent(this, c.offset, c.length, e.getText(), e); + } + + return null; + } + + /** + * When called this patch document is informed about a forthcoming change + * of its parent document. This child document checks whether the parent + * document change affects it and if so informs all document listeners. + * + * @param event the parent document event + */ + public void parentDocumentAboutToBeChanged(DocumentEvent event) { + fParentEvent= event; + fEvent= normalize(event); + if (fEvent != null) + delayedFireDocumentAboutToBeChanged(); + } + + /** + * When called this child document is informed about a change of its parent document. + * If this child document is affected it informs all of its document listeners. + * + * @param event the parent document event + */ + public void parentDocumentChanged(DocumentEvent event) { + if ( !fIsUpdating && event == fParentEvent && fEvent != null) { + try { + getTracker().replace(fEvent.getOffset(), fEvent.getLength(), fEvent.getText()); + fireDocumentChanged(fEvent); + } catch (BadLocationException x) { + Assert.isLegal(false); + } + } + } + + /* + * @see AbstractDocument#fireDocumentAboutToBeChanged + */ + protected void fireDocumentAboutToBeChanged(DocumentEvent event) { + // delay it until there is a notification from the parent document + // otherwise there it is expensive to construct the parent document information + } + + /** + * Fires the child document event as about-to-be-changed event to all registed listeners. + */ + private void delayedFireDocumentAboutToBeChanged() { + super.fireDocumentAboutToBeChanged(fEvent); + } + + /** + * Ignores the given event and sends the similar child document event instead. + * + * @param event the event to be ignored + */ + protected void fireDocumentChanged(DocumentEvent event) { + super.fireDocumentChanged(fEvent); + } + + /* + * @see IDocument#replace(int, int, String) + * @since 2.0 + */ + public void replace(int offset, int length, String text) throws BadLocationException { + try { + fIsUpdating= true; + if (fExtension != null) + fExtension.stopPostNotificationProcessing(); + + super.replace(offset, length, text); + + } finally { + fIsUpdating= false; + if (fExtension != null) + fExtension.resumePostNotificationProcessing(); + } + } + + /* + * @see IDocument#set(String) + * @since 2.0 + */ + public void set(String text) { + try { + fIsUpdating= true; + if (fExtension != null) + fExtension.stopPostNotificationProcessing(); + + super.set(text); + + } finally { + fIsUpdating= false; + if (fExtension != null) + fExtension.resumePostNotificationProcessing(); + } + } + + /* + * @see IDocumentExtension#registerPostNotificationReplace(IDocumentListener, IDocumentExtension.IReplace) + * @since 2.0 + */ + public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { + if (!fIsUpdating) + throw new UnsupportedOperationException(); + super.registerPostNotificationReplace(owner, replace); + } + + + /** + * Convenience method for hiding the specified region of the document. + *
* @param document
* @param offsetInParent
* @param lengthInParent
*/ + public void hide(int offsetInParent, int lengthInParent) { + + IDocument parent= getParentDocument(); + Position[] effected= getAffectedFragments(offsetInParent, lengthInParent); + + try { + + if (effected == null) { + // populate new document with two new fragments, the left and the right of the hidden region + int end= offsetInParent + lengthInParent; + addFragment(0, offsetInParent); + addFragment(end, parent.getLength() - end); + } else if (effected.length == 1) { + // the only affected fragment must be splitted into two + Position fragment= effected[0]; + removeFragment(fragment); + addFragment(fragment.offset, offsetInParent - fragment.offset); + int secondOffset= offsetInParent + lengthInParent; + addFragment(secondOffset, fragment.offset + fragment.length - secondOffset); + } else { + // first expand and than collapse + internalShow(offsetInParent, lengthInParent, effected); + hide(offsetInParent, lengthInParent); + } + + joinFragments(); + + } catch (BadLocationException x) { + } + } + + public void show(int offsetInParent, int lengthInParent) { + + Position[] effected= getAffectedFragments(offsetInParent, lengthInParent); + if (effected == null || effected.length == 0) { + try { + addFragment(offsetInParent, lengthInParent); + joinFragments(); + } catch (BadLocationException x) { + } + return; + } + + internalShow(offsetInParent, lengthInParent, effected); + joinFragments(); + + } + + private void internalShow(int offsetInParent, int lengthInParent, Position[] effected) { + try { + + int size= effected.length; + for (int i= 0; i < size; i++) + removeFragment(effected[i]); + + int offset= Math.min(offsetInParent, effected[0].offset); + int end= Math.max(offsetInParent + lengthInParent, effected[size -1].offset + effected[size -1].length); + addFragment(offset, end - offset); + + } catch (BadLocationException x) { + } + } +}
\ No newline at end of file diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java new file mode 100644 index 00000000000..a039af8c598 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java @@ -0,0 +1,287 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + + +/** + * Manages a set of child documents for given parent documents. + * A child document represents a particular range of the parent + * document and is accordingly adapted to changes of the parent document. + * Vice versa, the parent document is accordingly adapted to changes of + * its child documents. The manager does not maintain any particular management + * structure but utilizes mechanisms given by <code>IDocument</code> such + * as position categories and position updaters. <p> + * + * For internal use only. + */ +public final class ProjectionDocumentManager implements IDocumentListener, ISlaveDocumentManager { + + + /** + * Name of the position categories used to keep track of the child + * documents offset ranges into the parent document. + */ + public final static String PROJECTION_DOCUMENTS= "__projectiondocuments"; //$NON-NLS-1$ + + +// /** +// * The child document partitioner uses the parent document to answer all questions. +// */ +// static class ChildPartitioner implements IDocumentPartitioner { +// +// protected ProjectionDocument fChildDocument; +// protected IDocument fParentDocument; +// +// protected ChildPartitioner() { +// } +// +// /* +// * @see IDocumentPartitioner#getPartition(int) +// */ +// public ITypedRegion getPartition(int offset) { +// try { +// offset += fChildDocument.getParentDocumentRange().getOffset(); +// return fParentDocument.getPartition(offset); +// } catch (BadLocationException x) { +// } +// +// return null; +// } +// +// /* +// * @see IDocumentPartitioner#computePartitioning(int, int) +// */ +// public ITypedRegion[] computePartitioning(int offset, int length) { +// try { +// offset += fChildDocument.getParentDocumentRange().getOffset(); +// return fParentDocument.computePartitioning(offset, length); +// } catch (BadLocationException x) { +// } +// +// return null; +// } +// +// /* +// * @see IDocumentPartitioner#getContentType(int) +// */ +// public String getContentType(int offset) { +// try { +// offset += fChildDocument.getParentDocumentRange().getOffset(); +// return fParentDocument.getContentType(offset); +// } catch (BadLocationException x) { +// } +// +// return null; +// } +// +// /* +// * @see IDocumentPartitioner#getLegalContentTypes() +// */ +// public String[] getLegalContentTypes() { +// return fParentDocument.getLegalContentTypes(); +// } +// +// /* +// * @see IDocumentPartitioner#documentChanged(DocumentEvent) +// */ +// public boolean documentChanged(DocumentEvent event) { +// // ignore as the parent does this for us +// return false; +// } +// +// /* +// * @see IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent) +// */ +// public void documentAboutToBeChanged(DocumentEvent event) { +// // ignore as the parent does this for us +// } +// +// /* +// * @see IDocumentPartitioner#disconnect() +// */ +// public void disconnect() { +// fChildDocument= null; +// fParentDocument= null; +// } +// +// /* +// * @see IDocumentPartitioner#connect(IDocument) +// */ +// public void connect(IDocument childDocument) { +// Assert.isTrue(childDocument instanceof ProjectionDocument); +// fChildDocument= (ProjectionDocument) childDocument; +// fParentDocument= fChildDocument.getParentDocument(); +// } +// }; + + + + /** The position updater shared by all documents which have projection documents */ + private IPositionUpdater fProjectionPositionUpdater; + + private Map fRegistar= new HashMap(); + + + /** + * Returns the projection position updater. If necessary, it is dynamically created. + * + * @return the child position updater + */ + protected IPositionUpdater getProjectionPositionUpdater() { + if (fProjectionPositionUpdater == null) + fProjectionPositionUpdater= new FragmentUpdater(PROJECTION_DOCUMENTS); + return fProjectionPositionUpdater; + } + + private void add(IDocument parent, ProjectionDocument projection) { + List list= (List) fRegistar.get(parent); + if (list == null) { + list= new ArrayList(1); + fRegistar.put(parent, list); + } + list.add(projection); + } + + private void remove(IDocument parent, ProjectionDocument projection) { + List list= (List) fRegistar.get(parent); + if (list != null) { + list.remove(projection); + if (list.size() == 0) + fRegistar.remove(parent); + } + } + + private boolean hasProjection(IDocument parent) { + return (fRegistar.get(parent) instanceof List); + } + + private Iterator getProjectionsIterator(IDocument parent) { + List list= (List) fRegistar.get(parent); + if (list != null) + return list.iterator(); + return null; + } + + /** + * Informs all child documents of the document which issued this document event. + * + * @param about indicates whether the change is about to happen or alread happend + * @param event the document event which will be processed to inform child documents + */ + protected void fireDocumentEvent(boolean about, DocumentEvent event) { + IDocument parent= event.getDocument(); + Iterator e= getProjectionsIterator(parent); + if (e == null) + return; + + while (e.hasNext()) { + ProjectionDocument document= (ProjectionDocument) e.next(); + if (about) + document.parentDocumentAboutToBeChanged(event); + else + document.parentDocumentChanged(event); + } + } + + /* + * @see IDocumentListener#documentChanged(DocumentEvent) + */ + public void documentChanged(DocumentEvent event) { + fireDocumentEvent(false, event); + } + + /* + * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent) + */ + public void documentAboutToBeChanged(DocumentEvent event) { + fireDocumentEvent(true, event); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#createMasterSlaveMapping(org.eclipse.jface.text.IDocument) + */ + public IDocumentInformationMapping createMasterSlaveMapping(IDocument slave) { + if (slave instanceof ProjectionDocument) { + ProjectionDocument projectionDocument= (ProjectionDocument) slave; + return new CoordinatesTranslator(projectionDocument.getParentDocument(), PROJECTION_DOCUMENTS, projectionDocument, ProjectionDocument.FRAGMENT_CATEGORY); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#createSlaveDocument(org.eclipse.jface.text.IDocument) + */ + public IDocument createSlaveDocument(IDocument master) { + if (!master.containsPositionCategory(PROJECTION_DOCUMENTS)) { + master.addPositionCategory(PROJECTION_DOCUMENTS); + master.addPositionUpdater(getProjectionPositionUpdater()); + master.addDocumentListener(this); + } + + ProjectionDocument slave= new ProjectionDocument(master, PROJECTION_DOCUMENTS); +// IDocumentPartitioner partitioner= new ChildPartitioner(); +// child.setDocumentPartitioner(partitioner); +// partitioner.connect(child); + + add(master, slave); + return slave; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#freeSlaveDocument(org.eclipse.jface.text.IDocument) + */ + public void freeSlaveDocument(IDocument slave) { + + if ( !(slave instanceof ProjectionDocument)) + return; + + ProjectionDocument projectionDocument= (ProjectionDocument) slave; + +// childDocument.getDocumentPartitioner().disconnect(); + + IDocument parent= projectionDocument.getParentDocument(); + remove(parent, projectionDocument); + + try { + if (!hasProjection(parent)) { + parent.removeDocumentListener(this); + parent.removePositionUpdater(getProjectionPositionUpdater()); + parent.removePositionCategory(PROJECTION_DOCUMENTS); + } + } catch (BadPositionCategoryException x) { + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#getMasterDocument(org.eclipse.jface.text.IDocument) + */ + public IDocument getMasterDocument(IDocument slave) { + if (slave instanceof ProjectionDocument) + return ((ProjectionDocument) slave).getParentDocument(); + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#isSlaveDocument(org.eclipse.jface.text.IDocument) + */ + public boolean isSlaveDocument(IDocument document) { + return (document instanceof ProjectionDocument); + } +}
\ No newline at end of file diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java new file mode 100644 index 00000000000..14b0eacdcf1 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java @@ -0,0 +1,42 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.jface.text; + +/** + * ProjectionPosition.java + */ +public class ProjectionPosition extends Position { + + private IDocument fProjectionDocument; + private Fragment fFragment; + + public ProjectionPosition(IDocument projectionDocument, int offset, int length) { + super(offset, length); + fProjectionDocument= projectionDocument; + } + + public void setFragment(Fragment fragment) { + fFragment= fragment; + } + + public Fragment getFragment() { + return fFragment; + } + +// /** +// * Changed to be compatible to the position updater behavior +// * @see Position#overlapsWith(int, int) +// */ +// public boolean overlapsWith(int offset, int length) { +// boolean append= (offset == this.offset + this.length) && length == 0; +// return append || super.overlapsWith(offset, length); +// } +} diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java new file mode 100644 index 00000000000..a82cf4ce5d3 --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java @@ -0,0 +1,51 @@ +package org.eclipse.jface.text; + +import org.eclipse.jface.text.DefaultPositionUpdater; + +/** + * The position updater used to adapt the positions representing + * the child document ranges to changes of the parent document. + */ + +public class ProjectionPositionUpdater extends DefaultPositionUpdater { + + /** + * Creates the position updated. + */ + protected ProjectionPositionUpdater(String category) { + super(category); + } + + /** + * Child document ranges cannot be deleted other then by calling + * freeChildDocument. + */ + protected boolean notDeleted() { + return true; + } + + /** + * If an insertion happens at a child document's start offset, the + * position is extended rather than shifted. Also, if something is added + * right behind the end of the position, the position is extended rather + * than kept stable. + */ + protected void adaptToInsert() { + + int myStart= fPosition.offset; + int myEnd= fPosition.offset + fPosition.length; + myEnd= Math.max(myStart, myEnd); + + int yoursStart= fOffset; + int yoursEnd= fOffset + fReplaceLength -1; + yoursEnd= Math.max(yoursStart, yoursEnd); + + if (myEnd < yoursStart) + return; + + if (myStart <= yoursStart) + fPosition.length += fReplaceLength; + else + fPosition.offset += fReplaceLength; + } +} diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java new file mode 100644 index 00000000000..467578330fc --- /dev/null +++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java @@ -0,0 +1,132 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + + +/** + * ProjectionTextStore.java + */ +public class ProjectionTextStore implements ITextStore { + + private ProjectionDocument fProjectionDocument; + + public ProjectionTextStore(ProjectionDocument projectionDocument) { + fProjectionDocument= projectionDocument; + } + + private int computeParentDocumentOffset(int offset) { + try { + return fProjectionDocument.toParentDocumentOffset(offset); + } catch (BadLocationException x) { + throw new RuntimeException(); + } + } + + /* + * @see ITextStore#set + */ + public void set(String contents) { + + try { + + Position[] projection= fProjectionDocument.getProjection(); + if (projection != null && projection.length > 0) { + Position first=projection[0]; + Position last= projection[projection.length -1]; + int length= last.offset - first.offset + last.length; + getParentDocument().replace(first.getOffset(), length, contents); + } else { + getParentDocument().set(contents); + } + + } catch (BadLocationException x) { + } + } + + /* + * @see ITextStore#replace + */ + public void replace(int offset, int length, String text) { + + try { + + int endoffset= length > 0 ? offset + length -1 : offset; + int o2= computeParentDocumentOffset(endoffset); + if (length > 0) + ++ o2; + + offset= computeParentDocumentOffset(offset); + length= o2 - offset; + + getParentDocument().replace(offset, length, text); + + } catch (BadLocationException x) { + // ignored as surrounding document should have handled this + } + } + + /* + * @see ITextStore#getLength + */ + public int getLength() { + Position[] projection= fProjectionDocument.getProjection(); + if (projection == null || projection.length == 0) + return 0; + + int length= 0; + for (int i= 0; i < projection.length; i++) + length += projection[i].length; + return length; + } + + /* + * @see ITextStore#get + */ + public String get(int offset, int length) { + try { + + Fragment[] fragments= fProjectionDocument.getFragmentsOfRange(offset, length); + if (fragments == null || fragments.length == 0) + return ""; + + StringBuffer buffer= new StringBuffer(); + for (int i= 0; i < fragments.length; i++) { + Position p= fragments[i].getOrigin(); + buffer.append(getParentDocument().get(p.offset, p.length)); + } + + offset -= fragments[0].offset; + return buffer.substring(offset, offset + length); + + } catch (BadLocationException x) { + } + + return null; + } + + private IDocument getParentDocument() { + return fProjectionDocument.getParentDocument(); + } + + /* + * @see ITextStore#get + */ + public char get(int offset) { + try { + int o= computeParentDocumentOffset(offset); + return getParentDocument().getChar(o); + } catch (BadLocationException x) { + } + + return (char) 0; + } +}
\ No newline at end of file diff --git a/org.eclipse.text/scripts/exportplugin.xml b/org.eclipse.text/scripts/exportplugin.xml index 870cc45dc6b..ba29a6de216 100644 --- a/org.eclipse.text/scripts/exportplugin.xml +++ b/org.eclipse.text/scripts/exportplugin.xml @@ -23,6 +23,7 @@ <copy file="plugin.properties" todir="${dest}"/> <zip zipfile="${dest}/textsrc.zip"> <fileset dir="src" /> + <fileset dir="projection"/> </zip> </target> </project> diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java index 7d2185c3302..c534dd30d96 100644 --- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java +++ b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java @@ -177,7 +177,7 @@ public final class ChildDocument extends AbstractDocument { if (offset + length > fRange.getLength()) length= fRange.getLength() - offset; - return new ChildDocumentEvent(this, offset, length, e.fText, e); + return new SlaveDocumentEvent(this, offset, length, e.fText, e); } /** diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java deleted file mode 100644 index cc5e52976b5..00000000000 --- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.eclipse.jface.text; - -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ - -/** - * A child document event represents a parent document event as a - * child-relative document event. It also carries the original event. - */ -public class ChildDocumentEvent extends DocumentEvent { - - /** The parent document event */ - private DocumentEvent fParentEvent; - - /** - * Creates a new child document event. - * - * @param doc the child document - * @param offset the offset in the child document - * @param length the length in the child document - * @param text the substitution text - * @param parentEvent the parent Event - */ - public ChildDocumentEvent(IDocument doc, int offset, int length, String text, DocumentEvent parentEvent) { - super(doc, offset, length, text); - fParentEvent= parentEvent; - } - - /** - * Returns this event's parent event. - * - * @return this event's parent event - */ - public DocumentEvent getParentEvent() { - return fParentEvent; - } -}
\ No newline at end of file diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java index 2b9ed9a4b19..ecf02967892 100644 --- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java +++ b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java @@ -1,10 +1,15 @@ -package org.eclipse.jface.text; +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.jface.text; @@ -19,7 +24,7 @@ package org.eclipse.jface.text; * * For internal use only. */ -public final class ChildDocumentManager implements IDocumentListener { +public final class ChildDocumentManager implements IDocumentListener, ISlaveDocumentManager { /** @@ -210,47 +215,45 @@ public final class ChildDocumentManager implements IDocumentListener { return fChildPositionUpdater; } - /** - * Creates and returns a new child document for the specified range of the given parent document. - * The created child document is initialized with a child document partitioner. - * - * @param parent the parent document - * @param offset the offset of the parent document range - * @param length the length of the parent document range - * @exception BadLocationException if the specified range is invalid in the parent document + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#createSlaveDocument(org.eclipse.jface.text.IDocument) */ - public ChildDocument createChildDocument(IDocument parent, int offset, int length) throws BadLocationException { - - if (!parent.containsPositionCategory(CHILDDOCUMENTS)) { - parent.addPositionCategory(CHILDDOCUMENTS); - parent.addPositionUpdater(getChildPositionUpdater()); - parent.addDocumentListener(this); + public IDocument createSlaveDocument(IDocument master) { + + if (!master.containsPositionCategory(CHILDDOCUMENTS)) { + master.addPositionCategory(CHILDDOCUMENTS); + master.addPositionUpdater(getChildPositionUpdater()); + master.addDocumentListener(this); } - - ChildPosition pos= new ChildPosition(parent, offset, length); + + ChildPosition pos= new ChildPosition(master, 0, 0); try { - parent.addPosition(CHILDDOCUMENTS, pos); + master.addPosition(CHILDDOCUMENTS, pos); } catch (BadPositionCategoryException x) { // cannot happen + } catch (BadLocationException x) { + // (0, 0) is OK } - - ChildDocument child= new ChildDocument(parent, pos); + + ChildDocument child= new ChildDocument(master, pos); IDocumentPartitioner partitioner= new ChildPartitioner(); child.setDocumentPartitioner(partitioner); partitioner.connect(child); - + pos.fChildDocument= child; return child; } - /** - * Disconnects the given child document from it's parent document and frees - * all resources which are no longer needed. - * - * @param childDocument the child document to be freed + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#freeSlaveDocument(org.eclipse.jface.text.IDocument) */ - public void freeChildDocument(ChildDocument childDocument) { + public void freeSlaveDocument(IDocument slave) { + + if (! (slave instanceof ChildDocument)) + return; + + ChildDocument childDocument= (ChildDocument) slave; childDocument.getDocumentPartitioner().disconnect(); @@ -270,6 +273,31 @@ public final class ChildDocumentManager implements IDocumentListener { } } + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#createMasterSlaveMapping(org.eclipse.jface.text.IDocument) + */ + public IDocumentInformationMapping createMasterSlaveMapping(IDocument slave) { + if (slave instanceof ChildDocument) + return new ParentChildMapping((ChildDocument) slave); + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#getMasterDocument(org.eclipse.jface.text.IDocument) + */ + public IDocument getMasterDocument(IDocument slave) { + if (slave instanceof ChildDocument) + return ((ChildDocument) slave).getParentDocument(); + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ISlaveDocumentManager#isSlaveDocument(org.eclipse.jface.text.IDocument) + */ + public boolean isSlaveDocument(IDocument document) { + return (document instanceof ChildDocument); + } + /** * Informs all child documents of the document which issued this document event. * diff --git a/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java b/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java new file mode 100644 index 00000000000..6fead880e86 --- /dev/null +++ b/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java @@ -0,0 +1,27 @@ +package org.eclipse.jface.text; + + + +public interface IDocumentInformationMapping { + + IRegion getCoverage(); + + + int toOriginOffset(int imageOffset) throws BadLocationException; + + IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException; + + IRegion toOriginLines(int imageLine) throws BadLocationException; + + int toOriginLine(int imageLine) throws BadLocationException; + + + + int toImageOffset(int originOffset) throws BadLocationException; + + IRegion toImageRegion(IRegion originRegion) throws BadLocationException; + + int toImageLine(int originLine) throws BadLocationException; + + int toClosestImageLine(int originLine) throws BadLocationException; +}
\ No newline at end of file diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java b/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java new file mode 100644 index 00000000000..d74731d20af --- /dev/null +++ b/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java @@ -0,0 +1,57 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + +/** + * Slave documents are documents that use a text store which is based on a + * master document. + */ +public interface ISlaveDocumentManager { + + /** + * Creates a new slave document for the given master document. + * + * @param master + * @return IDocument + */ + IDocument createSlaveDocument(IDocument master); + + /** + * Frees the given slave document. + * + * @param slave + */ + void freeSlaveDocument(IDocument slave); + + /** + * Creates a new mapping between the given slave document and its master. + * + * @param slaveDocument + * @return IDocumentInformationMapping + */ + IDocumentInformationMapping createMasterSlaveMapping(IDocument slave); + + /** + * Returns the master of the given slave document. + * + * @param slave + * @return IDocument + */ + IDocument getMasterDocument(IDocument slave); + + /** + * Method isSlaveDocument. + * @param document + * @return boolean + */ + boolean isSlaveDocument(IDocument document); +}
\ No newline at end of file diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java b/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java new file mode 100644 index 00000000000..d47e2c9c796 --- /dev/null +++ b/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java @@ -0,0 +1,139 @@ +package org.eclipse.jface.text; + +/** + * ParentChildMapping.java + */ +public class ParentChildMapping implements IDocumentInformationMapping { + + private IDocument fParentDocument; + private ChildDocument fChildDocument; + + + public ParentChildMapping(ChildDocument childDocument) { + fParentDocument= childDocument.getParentDocument(); + fChildDocument= childDocument; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#getCoverage() + */ + public IRegion getCoverage() { + Position p= fChildDocument.getParentDocumentRange(); + return new Region(p.getOffset(), p.getLength()); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginOffset(int) + */ + public int toOriginOffset(int imageOffset) throws BadLocationException { + int anchorOffset= fChildDocument.getParentDocumentRange().getOffset(); + return anchorOffset + imageOffset; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginRegion(org.eclipse.jface.text.IRegion) + */ + public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException { + int anchorOffset= fChildDocument.getParentDocumentRange().getOffset(); + return new Region(anchorOffset + imageRegion.getOffset(), imageRegion.getLength()); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLines(int) + */ + public IRegion toOriginLines(int imageLine) throws BadLocationException { + IRegion imageDocumentRegion= fChildDocument.getLineInformation(imageLine); + IRegion originDocumentRegion= toOriginRegion(imageDocumentRegion); + + int startLine= fParentDocument.getLineOfOffset(originDocumentRegion.getOffset()); + if (originDocumentRegion.getLength() == 0) + return new Region(startLine, 0); + + int endLine= fParentDocument.getLineOfOffset(originDocumentRegion.getOffset() + originDocumentRegion.getLength() -1); + return new Region(startLine, endLine - startLine); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLine(int) + */ + public int toOriginLine(int imageLine) throws BadLocationException { + int anchorOffset= fChildDocument.getParentDocumentRange().getOffset(); + return fParentDocument.getLineOfOffset(anchorOffset) + imageLine; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageOffset(int) + */ + public int toImageOffset(int originOffset) throws BadLocationException { + Position p= fChildDocument.getParentDocumentRange(); + if (p.includes(originOffset)) + return originOffset - p.getOffset(); + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageRegion(org.eclipse.jface.text.IRegion) + */ + public IRegion toImageRegion(IRegion originRegion) throws BadLocationException { + + int offset= originRegion.getOffset(); + int length= originRegion.getLength(); + + if (length < 0) { + length= -length; + offset -= length; + } + + Position p= fChildDocument.getParentDocumentRange(); + if (p.overlapsWith(offset, length)) { + + if (offset < p.getOffset()) + offset= p.getOffset(); + + int end= offset + length; + int e= p.getOffset() + p.getLength(); + if (end > e) + end= e; + + offset -= p.getOffset(); + end -= p.getOffset(); + + if (originRegion.getLength() < 0) + return new Region(end, offset - end); + return new Region(offset, end - offset); + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageLine(int) + */ + public int toImageLine(int originLine) throws BadLocationException { + int anchorOffset= fChildDocument.getParentDocumentRange().getOffset(); + int startLine= fParentDocument.getLineOfOffset(anchorOffset); + + int imageLine= originLine - startLine; + if (imageLine < 0 || imageLine > fChildDocument.getNumberOfLines()) + return -1; + return imageLine; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IDocumentInformationMapping#toClosestImageLine(int) + */ + public int toClosestImageLine(int originLine) throws BadLocationException { + int anchorOffset= fChildDocument.getParentDocumentRange().getOffset(); + int startLine= fParentDocument.getLineOfOffset(anchorOffset); + + int imageLine= originLine - startLine; + if (imageLine < 0) + return 0; + + int maxLine= fChildDocument.getNumberOfLines(); + if (imageLine > maxLine) + return maxLine; + + return imageLine; + } +} diff --git a/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java b/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java new file mode 100644 index 00000000000..6563524707f --- /dev/null +++ b/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java @@ -0,0 +1,45 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.jface.text; + +/** + * A slave document event represents a master document event as a slave-relative + * document event. It also carries the master document event. + */ +public class SlaveDocumentEvent extends DocumentEvent { + + /** The master document event */ + private DocumentEvent fMasterEvent; + + /** + * Creates a new slave document event. + * + * @param doc the slave document + * @param offset the offset in the slave document + * @param length the length in the slave document + * @param text the substitution text + * @param masterEvent the master document event + */ + public SlaveDocumentEvent(IDocument doc, int offset, int length, String text, DocumentEvent masterEvent) { + super(doc, offset, length, text); + fMasterEvent= masterEvent; + } + + /** + * Returns this event's master event. + * + * @return this event's master event + */ + public DocumentEvent getMasterEvent() { + return fMasterEvent; + } +}
\ No newline at end of file diff --git a/org.eclipse.ui.editors/.classpath b/org.eclipse.ui.editors/.classpath index 843ecb0dc07..736b0952d17 100644 --- a/org.eclipse.ui.editors/.classpath +++ b/org.eclipse.ui.editors/.classpath @@ -2,6 +2,7 @@ <classpath> <classpathentry kind="src" path="src/"/> <classpathentry kind="src" path="extensions"/> + <classpathentry kind="src" path="projection"/> <classpathentry kind="src" path="/org.eclipse.text"/> <classpathentry kind="src" path="/org.eclipse.jface"/> <classpathentry kind="src" path="/org.eclipse.core.resources"/> diff --git a/org.eclipse.ui.editors/build.properties b/org.eclipse.ui.editors/build.properties index 62e61b8210f..7aef06c7c65 100644 --- a/org.eclipse.ui.editors/build.properties +++ b/org.eclipse.ui.editors/build.properties @@ -1,5 +1,6 @@ source.editors.jar = src/,\ - extensions/ + extensions/,\ + projection/ bin.includes = *.jar,\ plugin.xml,\ plugin.properties diff --git a/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/DefineProjectionAction.java b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/DefineProjectionAction.java new file mode 100644 index 00000000000..93811a78c9c --- /dev/null +++ b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/DefineProjectionAction.java @@ -0,0 +1,65 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.ui.editors.text; + +import java.util.ResourceBundle; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextEditorAction; + +/** + * CollapseAction.java + */ +public class DefineProjectionAction extends TextEditorAction { + + /** + * Constructor for CollapseAction. + * @param bundle + * @param prefix + * @param editor + */ + public DefineProjectionAction(ResourceBundle bundle, String prefix, ITextEditor editor) { + super(bundle, prefix, editor); + } + + /* + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + ProjectionTextEditor editor= (ProjectionTextEditor) getTextEditor(); + ITextSelection s= (ITextSelection) editor.getSelectionProvider().getSelection(); + + IDocumentProvider provider= editor.getDocumentProvider(); + IDocument document= provider.getDocument(editor.getEditorInput()); + + try { + + int line1= document.getLineOfOffset(s.getOffset()); + int start= document.getLineOffset(line1); + + int line2= document.getLineOfOffset(s.getOffset() + s.getLength()); + int lineStart= document.getLineOffset(line2); + int end= lineStart + document.getLineLength(line2); + + if (line2 > line1) { + System.out.println("lines " + line1 + " and " + line2 + " are defined as collapsable."); + editor.defineProjection(start, end - start); + } + + } catch (BadLocationException x) { + } + } +} diff --git a/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.java b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.java new file mode 100644 index 00000000000..f71827f0b69 --- /dev/null +++ b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.java @@ -0,0 +1,30 @@ +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +package org.eclipse.ui.editors.text; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +class EditorMessages { + + private static final String RESOURCE_BUNDLE= "org.eclipse.ui.editors.text.EditorMessages";//$NON-NLS-1$ + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private EditorMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + } + + public static ResourceBundle getResourceBundle() { + return fgResourceBundle; + } +} diff --git a/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.properties b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.properties new file mode 100644 index 00000000000..4d118ddf14c --- /dev/null +++ b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/EditorMessages.properties @@ -0,0 +1,3 @@ +Editor.Collapse.label=Collapse +Editor.Expand.label=Expand +Editor.DefineProjection.label=Define Projection diff --git a/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionPainter.java b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionPainter.java new file mode 100644 index 00000000000..f48b9eb3304 --- /dev/null +++ b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionPainter.java @@ -0,0 +1,124 @@ +package org.eclipse.ui.editors.text; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ProjectionAnnotation; +import org.eclipse.jface.text.source.ProjectionSourceViewer; + +/** + * ProjectionPainter.java + */ +public class ProjectionPainter implements PaintListener{ + + private ProjectionSourceViewer fSourceViewer; + + + public ProjectionPainter(ProjectionSourceViewer sourceViewer) { + fSourceViewer= sourceViewer; + } + + private IAnnotationModel getAnnotationModel() { + return fSourceViewer.getProjectionAnnotationModel(); + } + + private IDocument getDocument() { + return fSourceViewer.getDocument(); + } + + + /* (non-Javadoc) + * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent) + */ + public void paintControl(PaintEvent e) { + IRegion lineRange= computeLineRange(e); + IRegion characterRange= computeCharacterRange(lineRange); + List annotations= findAnnotations(characterRange); + if (annotations != null) { + + IAnnotationModel model= getAnnotationModel(); + IDocument document= getDocument(); + StyledText text= fSourceViewer.getTextWidget(); + + Iterator iter= annotations.iterator(); + while (iter.hasNext()) { + ProjectionAnnotation a= (ProjectionAnnotation) iter.next(); + Position p= model.getPosition(a); + + try { + IRegion lineInfo= document.getLineInformationOfOffset(p.getOffset()); + int modelOffset= lineInfo.getOffset() + lineInfo.getLength(); + int widgetOffset= fSourceViewer.modelOffset2WidgetOffset(modelOffset); + doPaint(text, e.gc, text.getLocationAtOffset(widgetOffset)); + } catch (BadLocationException x) { + } + } + } + } + + private void doPaint(StyledText styledText, GC gc, Point point) { + gc.setForeground(styledText.getDisplay().getSystemColor(SWT.COLOR_BLUE)); + FontMetrics metrics= gc.getFontMetrics(); + gc.drawRectangle(point.x +3, point.y, metrics.getAverageCharWidth() * 2, metrics.getHeight() - 1); + } + + private IRegion computeLineRange(PaintEvent e) { + StyledText text= fSourceViewer.getTextWidget(); + int widgetLine= ((e.y + text.getTopPixel()) / text.getLineHeight()); + int startLine= fSourceViewer.widgetlLine2ModelLine(widgetLine); + + widgetLine= ((e.y + e.height + text.getTopPixel()) / text.getLineHeight()); + IDocument visible= fSourceViewer.getVisibleDocument(); + widgetLine= Math.min(widgetLine, visible.getNumberOfLines() -1); + int endLine= fSourceViewer.widgetlLine2ModelLine(widgetLine); + + return new Region(startLine, Math.max(0, endLine - startLine)); + } + + private IRegion computeCharacterRange(IRegion lineRange) { + IDocument document= fSourceViewer.getDocument(); + try { + int startOffset= document.getLineOffset(lineRange.getOffset()); + int endLine= lineRange.getOffset() + lineRange.getLength(); + int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine); + return new Region(startOffset, endOffset - startOffset); + } catch (BadLocationException x) { + } + return null; + } + + private List findAnnotations(IRegion characterRange) { + List result= new ArrayList(); + IAnnotationModel model= getAnnotationModel(); + if (model != null) { + Iterator e= model.getAnnotationIterator(); + while (e.hasNext()) { + Object next= e.next(); + if (next instanceof ProjectionAnnotation) { + ProjectionAnnotation annotation= (ProjectionAnnotation) next; + if (annotation.isFolded()) { + Position p= model.getPosition(annotation); + if (p.overlapsWith(characterRange.getOffset(), characterRange.getLength())) + result.add(annotation); + } + } + } + } + return result; + } +}
\ No newline at end of file diff --git a/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionTextEditor.java b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionTextEditor.java new file mode 100644 index 00000000000..e4b91cab9b8 --- /dev/null +++ b/org.eclipse.ui.editors/projection/org/eclipse/ui/editors/text/ProjectionTextEditor.java @@ -0,0 +1,119 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.ui.editors.text; + + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationRulerColumn; +import org.eclipse.jface.text.source.CompositeRuler; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.IVerticalRulerColumn; +import org.eclipse.jface.text.source.LineNumberRulerColumn; +import org.eclipse.jface.text.source.OutlinerRulerColumn; +import org.eclipse.jface.text.source.ProjectionAnnotation; +import org.eclipse.jface.text.source.ProjectionSourceViewer; + +import org.eclipse.jface.action.IMenuManager; + +import org.eclipse.ui.texteditor.ITextEditorActionConstants; + + +/** + * ProjectionTextEditor.java + */ +public class ProjectionTextEditor extends TextEditor { + + private IAnnotationModel fProjectionAnnotationModel; + + public void collapse(int offset, int length) { + ProjectionSourceViewer viewer= (ProjectionSourceViewer) getSourceViewer(); + viewer.collapse(offset, length); + } + + public void expand(int offset, int length) { + ProjectionSourceViewer viewer= (ProjectionSourceViewer) getSourceViewer();; + viewer.expand(offset, length); + } + + public void defineProjection(int offset, int length) { + Position p= new Position(offset, length); + fProjectionAnnotationModel.addAnnotation(new ProjectionAnnotation(p), p); + } + + protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + ProjectionSourceViewer viewer= new ProjectionSourceViewer(parent, ruler, styles); + if (fProjectionAnnotationModel != null) { + viewer.setProjectionAnnotationModel(fProjectionAnnotationModel); + StyledText text= viewer.getTextWidget(); + text.addPaintListener(new ProjectionPainter(viewer)); + } + return viewer; + } + + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions() + */ + protected void createActions() { + super.createActions(); + setAction("DefineProjection", new DefineProjectionAction(EditorMessages.getResourceBundle(), "Editor.DefineProjection.", this)); + } + + /* + * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager) + */ + protected void editorContextMenuAboutToShow(IMenuManager menu) { + super.editorContextMenuAboutToShow(menu); + addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "DefineProjection"); + } + + /* + * @see AbstractTextEditor#createVerticalRuler() + */ + protected IVerticalRuler createVerticalRuler() { + CompositeRuler ruler= new CompositeRuler(2); + ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH)); + ruler.addDecorator(1, new LineNumberRulerColumn()); + fProjectionAnnotationModel= new AnnotationModel(); + IVerticalRulerColumn column= new OutlinerRulerColumn(fProjectionAnnotationModel, VERTICAL_RULER_WIDTH); + ruler.addDecorator(2, column); + return ruler; + } + + /* + * @see ITextEditor#setHighlightRange + */ + public void setHighlightRange(int start, int length, boolean moveCursor) { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer != null) { + IRegion rangeIndication= sourceViewer.getRangeIndication(); + if (rangeIndication == null || start != rangeIndication.getOffset() || length != rangeIndication.getLength()) + sourceViewer.setRangeIndication(start, length, moveCursor); + } + } + + /* + * @see ITextEditor#getHighlightRange + */ + public IRegion getHighlightRange() { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer != null) + return sourceViewer.getRangeIndication(); + return null; + } +} diff --git a/org.eclipse.ui.editors/scripts/exportplugin.xml b/org.eclipse.ui.editors/scripts/exportplugin.xml index 6106df01a88..bb8dcd8ed0b 100644 --- a/org.eclipse.ui.editors/scripts/exportplugin.xml +++ b/org.eclipse.ui.editors/scripts/exportplugin.xml @@ -24,6 +24,7 @@ <zip zipfile="${dest}/editorssrc.zip"> <fileset dir="src" /> <fileset dir="extensions" /> + <fileset dir="projection"/> </zip> </target> </project> diff --git a/org.eclipse.ui.examples.javaeditor/.classpath b/org.eclipse.ui.examples.javaeditor/.classpath index 973aed0d7ef..828ce7c2fdb 100644 --- a/org.eclipse.ui.examples.javaeditor/.classpath +++ b/org.eclipse.ui.examples.javaeditor/.classpath @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="Eclipse Java Editor Example"/> - <classpathentry kind="src" path="/org.eclipse.ui"/> - <classpathentry kind="src" path="/org.eclipse.swt"/> - <classpathentry kind="src" path="/org.eclipse.core.resources"/> - <classpathentry kind="src" path="/org.eclipse.core.runtime"/> - <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/> - <classpathentry kind="output" path="bin"/> -</classpath> +<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="Eclipse Java Editor Example/"/>
+ <classpathentry kind="src" path="/org.eclipse.ui"/>
+ <classpathentry kind="src" path="/org.eclipse.core.resources"/>
+ <classpathentry kind="src" path="/org.eclipse.core.runtime"/>
+ <classpathentry kind="src" path="/org.eclipse.core.boot"/>
+ <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.ui.examples.javaeditor/.project b/org.eclipse.ui.examples.javaeditor/.project index afe248a3b87..50be6132535 100644 --- a/org.eclipse.ui.examples.javaeditor/.project +++ b/org.eclipse.ui.examples.javaeditor/.project @@ -3,10 +3,10 @@ <name>org.eclipse.ui.examples.javaeditor</name>
<comment></comment>
<projects>
- <project>org.eclipse.ui</project>
- <project>org.eclipse.core.runtime</project>
- <project>org.eclipse.swt</project>
+ <project>org.eclipse.core.boot</project>
<project>org.eclipse.core.resources</project>
+ <project>org.eclipse.core.runtime</project>
+ <project>org.eclipse.ui</project>
</projects>
<buildSpec>
<buildCommand>
diff --git a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaActionContributor.java b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaActionContributor.java index 234cb02c9e7..ecf3178b7f6 100644 --- a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaActionContributor.java +++ b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaActionContributor.java @@ -1,14 +1,28 @@ +/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
package org.eclipse.ui.examples.javaeditor;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jface.action.*;
-import org.eclipse.ui.*;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.editors.text.TextEditorActionContributor;
-import org.eclipse.ui.texteditor.*;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+import org.eclipse.ui.texteditor.TextEditorAction;
/**
* Contributes interesting Java actions to the desktop's Edit menu and the toolbar.
diff --git a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaDocumentProvider.java b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaDocumentProvider.java index a78662ffcc4..22ab20735d4 100644 --- a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaDocumentProvider.java +++ b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaDocumentProvider.java @@ -1,14 +1,23 @@ +/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
package org.eclipse.ui.examples.javaeditor;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
import org.eclipse.core.runtime.CoreException;
+
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.rules.DefaultPartitioner;
+
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.examples.javaeditor.java.JavaPartitionScanner;
diff --git a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaEditor.java b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaEditor.java index c097bcd8085..00b0cf7dc30 100644 --- a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaEditor.java +++ b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaEditor.java @@ -1,16 +1,25 @@ +/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
package org.eclipse.ui.examples.javaeditor;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.text.source.ISourceViewer;
+
import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.editors.text.ProjectionTextEditor;
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
import org.eclipse.ui.texteditor.TextOperationAction;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
@@ -18,7 +27,7 @@ import org.eclipse.ui.views.contentoutline.IContentOutlinePage; /**
* Java specific text editor.
*/
-public class JavaEditor extends TextEditor {
+public class JavaEditor extends ProjectionTextEditor {
/** The outline page */
private JavaContentOutlinePage fOutlinePage;
diff --git a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaSourceViewerConfiguration.java b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaSourceViewerConfiguration.java index 5d770501fb5..4b65f87ae33 100644 --- a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaSourceViewerConfiguration.java +++ b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/JavaSourceViewerConfiguration.java @@ -1,19 +1,40 @@ +/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
package org.eclipse.ui.examples.javaeditor;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jface.text.*;
+import org.eclipse.swt.graphics.RGB;
+
+import org.eclipse.jface.text.DefaultAutoIndentStrategy;
+import org.eclipse.jface.text.IAutoIndentStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
-import org.eclipse.jface.text.rules.*;
-import org.eclipse.jface.text.source.*;
-import org.eclipse.swt.graphics.RGB;
-import org.eclipse.ui.examples.javaeditor.java.*;
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+import org.eclipse.ui.examples.javaeditor.java.JavaAutoIndentStrategy;
+import org.eclipse.ui.examples.javaeditor.java.JavaCompletionProcessor;
+import org.eclipse.ui.examples.javaeditor.java.JavaDoubleClickSelector;
+import org.eclipse.ui.examples.javaeditor.java.JavaPartitionScanner;
import org.eclipse.ui.examples.javaeditor.javadoc.JavaDocCompletionProcessor;
import org.eclipse.ui.examples.javaeditor.util.JavaColorProvider;
@@ -71,8 +92,8 @@ public class JavaSourceViewerConfiguration extends SourceViewerConfiguration { assistant.enableAutoActivation(true);
assistant.setAutoActivationDelay(500);
- assistant.setProposalPopupOrientation(assistant.PROPOSAL_OVERLAY);
- assistant.setContextInformationPopupOrientation(assistant.CONTEXT_INFO_ABOVE);
+ assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
+ assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
assistant.setContextInformationPopupBackground(JavaEditorEnvironment.getJavaColorProvider().getColor(new RGB(150, 150, 0)));
return assistant;
@@ -111,11 +132,11 @@ public class JavaSourceViewerConfiguration extends SourceViewerConfiguration { reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
- dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(provider.JAVADOC_DEFAULT))));
+ dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(JavaColorProvider.JAVADOC_DEFAULT))));
reconciler.setDamager(dr, JavaPartitionScanner.JAVA_DOC);
reconciler.setRepairer(dr, JavaPartitionScanner.JAVA_DOC);
- dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(provider.MULTI_LINE_COMMENT))));
+ dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(JavaColorProvider.MULTI_LINE_COMMENT))));
reconciler.setDamager(dr, JavaPartitionScanner.JAVA_MULTILINE_COMMENT);
reconciler.setRepairer(dr, JavaPartitionScanner.JAVA_MULTILINE_COMMENT);
diff --git a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/PresentationAction.java b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/PresentationAction.java index 9f9e6b003b4..cc1ad334625 100644 --- a/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/PresentationAction.java +++ b/org.eclipse.ui.examples.javaeditor/Eclipse Java Editor Example/org/eclipse/ui/examples/javaeditor/PresentationAction.java @@ -1,9 +1,16 @@ +/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
package org.eclipse.ui.examples.javaeditor;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;
diff --git a/org.eclipse.ui.workbench.texteditor/scripts/exportplugin.xml b/org.eclipse.ui.workbench.texteditor/scripts/exportplugin.xml index 755041d0318..4a100642047 100644 --- a/org.eclipse.ui.workbench.texteditor/scripts/exportplugin.xml +++ b/org.eclipse.ui.workbench.texteditor/scripts/exportplugin.xml @@ -23,6 +23,7 @@ <copy file="plugin.properties" todir="${dest}"/> <zip zipfile="${dest}/texteditorsrc.jar"> <fileset dir="src" /> + <fileset dir="icons"/> </zip> </target> diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java index b9c31ef5603..0e0a83e0284 100644 --- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java @@ -23,6 +23,31 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ST; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.ShellAdapter; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; + import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -37,19 +62,6 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuListener; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.preference.PreferenceConverter; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IFindReplaceTarget; @@ -62,7 +74,9 @@ import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewerExtension; +import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.source.Annotation; @@ -74,6 +88,20 @@ import org.eclipse.jface.text.source.IVerticalRulerInfo; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.source.VerticalRuler; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.Assert; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; @@ -82,31 +110,6 @@ import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.ST; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.custom.VerifyKeyListener; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.Shell; - import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorActionBarContributor; import org.eclipse.ui.IEditorDescriptor; @@ -205,8 +208,8 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit */ public void verifyText(VerifyEvent e) { if (! validateEditorInputState()) - e.doit= false; - } + e.doit= false; + } }; /** @@ -520,8 +523,6 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit } } } - if (fKeyBindingService.processKey(event)) - event.doit= false; } /** @@ -540,7 +541,6 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit } fKeyBindingService= getEditorSite().getKeyBindingService(); - fKeyBindingService.enable(true); fIsInstalled= true; } } @@ -823,7 +823,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit int lineLength; try { - int caretOffsetInDocument= caretOffset + getSourceViewer().getVisibleRegion().getOffset(); + int caretOffsetInDocument= widgetOffset2ModelOffset(getSourceViewer(), caretOffset); lineLength= getSourceViewer().getDocument().getLineInformationOfOffset(caretOffsetInDocument).getLength(); } catch (BadLocationException ex) { return; @@ -838,7 +838,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit i--; } i++; - + // Remember current selection Point oldSelection= st.getSelection(); @@ -911,7 +911,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit int lineLength; try { - int caretOffsetInDocument= caretOffset + getSourceViewer().getVisibleRegion().getOffset(); + int caretOffsetInDocument= widgetOffset2ModelOffset(getSourceViewer(), caretOffset); lineLength= getSourceViewer().getDocument().getLineInformationOfOffset(caretOffsetInDocument).getLength(); } catch (BadLocationException ex) { return; @@ -923,7 +923,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit int i= 0; while (i < lineLength && Character.isWhitespace(line.charAt(i))) i++; - + // Remember current selection Point oldSelection= st.getSelection(); @@ -2254,7 +2254,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit fSourceViewer.removeTextListener(fTextListener); fTextListener= null; } - + fTextInputListener= null; fSelectionProvider= null; fSourceViewer= null; @@ -2579,25 +2579,25 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit if (! (provider instanceof IDocumentProviderExtension)) return; - IDocumentProviderExtension extension= (IDocumentProviderExtension) provider; - - boolean wasReadOnly= isEditorInputReadOnly(); - + IDocumentProviderExtension extension= (IDocumentProviderExtension) provider; + + boolean wasReadOnly= isEditorInputReadOnly(); + try { - extension.validateState(input, getSite().getShell()); - + extension.validateState(input, getSite().getShell()); + } catch (CoreException exception) { // for backward compatibility only if (exception instanceof ValidateStateException) { if (fSourceViewer != null) fSourceViewer.setEditable(isEditable()); - + if (wasReadOnly != isEditorInputReadOnly()) - updateStateDependentActions(); + updateStateDependentActions(); } - - ILog log= Platform.getPlugin(PlatformUI.PLUGIN_ID).getLog(); + + ILog log= Platform.getPlugin(PlatformUI.PLUGIN_ID).getLog(); log.log(exception.getStatus()); Shell shell= getSite().getShell(); @@ -2606,14 +2606,14 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit ErrorDialog.openError(shell, title, msg, exception.getStatus()); return; - } + } if (fSourceViewer != null) fSourceViewer.setEditable(isEditable()); if (wasReadOnly != isEditorInputReadOnly()) updateStateDependentActions(); - } + } /* * @see org.eclipse.ui.texteditor.ITextEditorExtension2.validateEditorInputState() @@ -2630,7 +2630,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit } finally { viewer.removeTextInputListener(fTextInputListener); - } + } } /** @@ -3574,11 +3574,8 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit return; if (fShowHighlightRangeOnly) { - if (moveCursor) { - IRegion visibleRegion= fSourceViewer.getVisibleRegion(); - if (start != visibleRegion.getOffset() || length != visibleRegion.getLength()) - fSourceViewer.setVisibleRegion(start, length); - } + if (moveCursor) + fSourceViewer.setVisibleRegion(start, length); } else { IRegion rangeIndication= fSourceViewer.getRangeIndication(); if (rangeIndication == null || start != rangeIndication.getOffset() || length != rangeIndication.getLength()) @@ -3594,7 +3591,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit return null; if (fShowHighlightRangeOnly) - return fSourceViewer.getVisibleRegion(); + return getCoverage(fSourceViewer); return fSourceViewer.getRangeIndication(); } @@ -3624,7 +3621,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit if (fSourceViewer == null) return; - if (!fSourceViewer.overlapsWithVisibleRegion(offset, length)) + if (!isVisible(fSourceViewer, offset, length)) fSourceViewer.resetVisibleRegion(); } @@ -3812,9 +3809,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit return fErrorLabel; StyledText styledText= fSourceViewer.getTextWidget(); - - int offset= fSourceViewer.getVisibleRegion().getOffset(); - int caret= offset + styledText.getCaretOffset(); + int caret= widgetOffset2ModelOffset(fSourceViewer, styledText.getCaretOffset()); IDocument document= fSourceViewer.getDocument(); if (document == null) @@ -3854,7 +3849,7 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit } return true; } - + /* * @see ITextEditorExtension2#isEditorInputModifiable() * @since 2.1 @@ -3895,5 +3890,29 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) { return true; } - + + protected final static int widgetOffset2ModelOffset(ISourceViewer viewer, int widgetOffset) { + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + return extension.widgetOffset2ModelOffset(widgetOffset); + } + return widgetOffset + viewer.getVisibleRegion().getOffset(); + } + + protected final static IRegion getCoverage(ISourceViewer viewer) { + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + return extension.getModelCoverage(); + } + return viewer.getVisibleRegion(); + } + + protected final static boolean isVisible(ISourceViewer viewer, int offset, int length) { + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + IRegion overlap= extension.modelRange2WidgetRange(new Region(offset, length)); + return overlap != null; + } + return viewer.overlapsWithVisibleRegion(offset, length); + } }
\ No newline at end of file diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/IncrementalFindTarget.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/IncrementalFindTarget.java index bb1bd10abfa..39bb497c63b 100644 --- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/IncrementalFindTarget.java +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/IncrementalFindTarget.java @@ -102,7 +102,6 @@ class IncrementalFindTarget implements IFindReplaceTarget, IFindReplaceTargetExt return; } - // TODO: reverse searches should put the caret at the start of the selection, instead of the end text.setSelectionRange(searchResult.selection, searchResult.length); text.showSelection(); diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/MarkRegionTarget.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/MarkRegionTarget.java index 369f54184b7..9f04b1cf59e 100644 --- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/MarkRegionTarget.java +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/MarkRegionTarget.java @@ -19,6 +19,7 @@ import org.eclipse.jface.text.IMarkRegionTarget; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension; +import org.eclipse.jface.text.ITextViewerExtension3; /** * Default implementation of <code>IMarkRegionTarget</code> using <code>ITextViewer</code> @@ -85,11 +86,7 @@ public class MarkRegionTarget implements IMarkRegionTarget { return; } - IRegion region= fViewer.getVisibleRegion(); - int offset= region.getOffset(); - int length= region.getLength(); - - if (markPosition < offset || markPosition > offset + length) { + if (!isVisible(fViewer, markPosition)) { fStatusLine.setErrorMessage("mark not in visible region"); fStatusLine.setMessage(""); //$NON-NLS-1$ return; @@ -104,4 +101,15 @@ public class MarkRegionTarget implements IMarkRegionTarget { fStatusLine.setErrorMessage(""); //$NON-NLS-1$ fStatusLine.setMessage(EditorMessages.getString("Editor.mark.status.message.mark.swapped")); //$NON-NLS-1$ } -} + + protected final static boolean isVisible(ITextViewer viewer, int offset) { + if (viewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension= (ITextViewerExtension3) viewer; + return extension.modelOffset2WidgetOffset(offset) >= 0; + } else { + IRegion region= viewer.getVisibleRegion(); + int vOffset= region.getOffset(); + return (vOffset <= offset && offset <= vOffset + region.getLength()); + } + } +} |