Skip to content

Commit 48e4b9a

Browse files
committed
Allow using visible regions with projections
1 parent a4840da commit 48e4b9a

File tree

2 files changed

+102
-3
lines changed

2 files changed

+102
-3
lines changed

bundles/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionViewer.java

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import org.eclipse.swt.dnd.TextTransfer;
2929
import org.eclipse.swt.dnd.Transfer;
3030
import org.eclipse.swt.events.VerifyEvent;
31+
import org.eclipse.swt.graphics.GC;
3132
import org.eclipse.swt.graphics.Point;
33+
import org.eclipse.swt.graphics.Rectangle;
34+
import org.eclipse.swt.widgets.Canvas;
3235
import org.eclipse.swt.widgets.Composite;
3336
import 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= super.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)

tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/ProjectionViewerTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,32 @@ public void testCopyPaste() {
7575
shell.dispose();
7676
}
7777
}
78+
79+
@Test
80+
public void testVisibleRegionDoesNotChangeWithProjections() {
81+
Shell shell= new Shell();
82+
shell.setLayout(new FillLayout());
83+
ProjectionViewer viewer= new ProjectionViewer(shell, null, null, false, SWT.NONE);
84+
String documentContent= """
85+
Hello
86+
World
87+
123
88+
456
89+
""";
90+
Document document= new Document(documentContent);
91+
viewer.setDocument(document, new AnnotationModel());
92+
int regionLength= documentContent.indexOf('\n');
93+
viewer.setVisibleRegion(0, regionLength);
94+
viewer.enableProjection();
95+
viewer.getProjectionAnnotationModel().addAnnotation(new ProjectionAnnotation(false), new ProjectionPosition(document));
96+
shell.setVisible(true);
97+
viewer.getTextOperationTarget().doOperation(ProjectionViewer.COLLAPSE_ALL);
98+
viewer.getTextOperationTarget().doOperation(ITextOperationTarget.SELECT_ALL);
99+
try {
100+
assertEquals(0, viewer.getVisibleRegion().getOffset());//expected 0 but was 6
101+
assertEquals(regionLength, viewer.getVisibleRegion().getLength());//expected 5 but was 20
102+
} finally {
103+
shell.dispose();
104+
}
105+
}
78106
}

0 commit comments

Comments
 (0)