2828import org .eclipse .swt .dnd .TextTransfer ;
2929import org .eclipse .swt .dnd .Transfer ;
3030import org .eclipse .swt .events .VerifyEvent ;
31+ import org .eclipse .swt .graphics .GC ;
3132import org .eclipse .swt .graphics .Point ;
33+ import org .eclipse .swt .graphics .Rectangle ;
34+ import org .eclipse .swt .widgets .Canvas ;
3235import org .eclipse .swt .widgets .Composite ;
3336import org .eclipse .swt .widgets .Display ;
3437
@@ -272,6 +275,43 @@ private void computeExpectedExecutionCosts() {
272275 }
273276 }
274277
278+ /**
279+ * A {@link ProjectionAnnotation} that is always collapsed and invisible.
280+ */
281+ private static class InvisibleCollapsedProjectionAnnotation extends ProjectionAnnotation {
282+ public InvisibleCollapsedProjectionAnnotation () {
283+ super (true );
284+ }
285+
286+ @ Override
287+ public void paint (GC gc , Canvas canvas , Rectangle rectangle ) {
288+ }
289+ }
290+
291+ /**
292+ * An {@link IProjectionPosition} that includes hiding the offset and length.
293+ */
294+ private static class ExactRegionProjectionPosition extends Position implements IProjectionPosition {
295+
296+ public ExactRegionProjectionPosition (int offset , int length ) {
297+ super (offset , length );
298+ }
299+
300+ @ Override
301+ public IRegion [] computeProjectionRegions (IDocument document ) throws BadLocationException {
302+ return new IRegion [] {
303+ new Region (getOffset (), getLength ())
304+ };
305+ }
306+
307+ @ Override
308+ public int computeCaptionOffset (IDocument document ) throws BadLocationException {
309+ return 0 ;
310+ }
311+
312+ }
313+
314+
275315 /** The projection annotation model used by this viewer. */
276316 private ProjectionAnnotationModel fProjectionAnnotationModel ;
277317 /** The annotation model listener */
@@ -292,6 +332,11 @@ private void computeExpectedExecutionCosts() {
292332 private IDocument fReplaceVisibleDocumentExecutionTrigger ;
293333 /** <code>true</code> if projection was on the last time we switched to segmented mode. */
294334 private boolean fWasProjectionEnabled ;
335+ /**
336+ * The region set by {@link #setVisibleRegion(int, int)} during projection or <code>null</code>
337+ * if not in a projection
338+ */
339+ private IRegion fVisibleRegionDuringProjection ;
295340 /** The queue of projection commands used to assess the costs of projection changes. */
296341 private ProjectionCommandQueue fCommandQueue ;
297342 /**
@@ -510,6 +555,10 @@ public final void disableProjection() {
510555 fProjectionAnnotationModel .removeAllAnnotations ();
511556 fFindReplaceDocumentAdapter = null ;
512557 fireProjectionDisabled ();
558+ if (fVisibleRegionDuringProjection != null ) {
559+ super .setVisibleRegion (fVisibleRegionDuringProjection .getOffset (), fVisibleRegionDuringProjection .getLength ());
560+ fVisibleRegionDuringProjection = null ;
561+ }
513562 }
514563 }
515564
@@ -518,9 +567,13 @@ public final void disableProjection() {
518567 */
519568 public final void enableProjection () {
520569 if (!isProjectionMode ()) {
570+ IRegion visibleRegion = getVisibleRegion ();
521571 addProjectionAnnotationModel (getVisualAnnotationModel ());
522572 fFindReplaceDocumentAdapter = null ;
523573 fireProjectionEnabled ();
574+ if (visibleRegion != null ) {
575+ setVisibleRegion (visibleRegion .getOffset (), visibleRegion .getLength ());
576+ }
524577 }
525578 }
526579
@@ -683,9 +736,24 @@ private int toLineStart(IDocument document, int offset, boolean testLastLine) th
683736
684737 @ Override
685738 public void setVisibleRegion (int start , int length ) {
686- fWasProjectionEnabled = isProjectionMode ();
687- disableProjection ();
688- super .setVisibleRegion (start , length );
739+ if (isProjectionMode ()) {
740+ for (Iterator <Annotation > annotationIterator = fProjectionAnnotationModel .getAnnotationIterator (); annotationIterator .hasNext ();) {
741+ Annotation ann = annotationIterator .next ();
742+ if (ann instanceof InvisibleCollapsedProjectionAnnotation ) {
743+ fProjectionAnnotationModel .removeAnnotation (ann );
744+ }
745+ }
746+ if (start > 0 ) {
747+ fProjectionAnnotationModel .addAnnotation (new InvisibleCollapsedProjectionAnnotation (), new ExactRegionProjectionPosition (0 , start ));
748+ }
749+ int regionEnd = start + length ;
750+ if (regionEnd < getDocument ().getLength ()) {
751+ fProjectionAnnotationModel .addAnnotation (new InvisibleCollapsedProjectionAnnotation (), new Position (regionEnd , getDocument ().getLength () - regionEnd ));
752+ }
753+ fVisibleRegionDuringProjection = new Region (start , length );
754+ } else {
755+ super .setVisibleRegion (start , length );
756+ }
689757 }
690758
691759 @ Override
@@ -710,6 +778,9 @@ public void resetVisibleRegion() {
710778
711779 @ Override
712780 public IRegion getVisibleRegion () {
781+ if (fVisibleRegionDuringProjection != null ) {
782+ return fVisibleRegionDuringProjection ;
783+ }
713784 disableProjection ();
714785 IRegion visibleRegion = getModelCoverage ();
715786 if (visibleRegion == null )
0 commit comments