Skip to content

Commit f082218

Browse files
[StickyScrolling] Sticky line is considering hidden source viewer lines
The source viewer can contain hidden lines, for example via code folding. The sticky line needs to consider this lines (see ITextViewerExtension5) when calculating the text and the style ranges from the text widget
1 parent d03901e commit f082218

File tree

4 files changed

+107
-27
lines changed

4 files changed

+107
-27
lines changed

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public List<IStickyLine> getStickyLines(ISourceViewer sourceViewer, int lineNumb
5555

5656
if (indentation < previousIndetation) {
5757
previousIndetation= indentation;
58-
stickyLines.addFirst(new StickyLine(mapLineNumberToViewer(sourceViewer, i), textWidget));
58+
stickyLines.addFirst(new StickyLine(mapLineNumberToViewer(sourceViewer, i), sourceViewer));
5959
}
6060
}
6161
} catch (IllegalArgumentException e) {

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLine.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,24 @@
1616
import org.eclipse.swt.custom.StyleRange;
1717
import org.eclipse.swt.custom.StyledText;
1818

19+
import org.eclipse.jface.text.ITextViewerExtension5;
20+
import org.eclipse.jface.text.source.ISourceViewer;
21+
1922
/**
2023
* Default implementation of {@link IStickyLine}. Information about the text and style ranges are
2124
* calculated from the given text widget.
2225
*/
2326
public class StickyLine implements IStickyLine {
2427

25-
private int lineNumber;
28+
protected int lineNumber;
2629

27-
private String text;
30+
protected String text;
2831

29-
private StyledText textWidget;
32+
protected ISourceViewer sourceViewer;
3033

31-
public StickyLine(int lineNumber, StyledText textWidget) {
34+
public StickyLine(int lineNumber, ISourceViewer sourceViewer) {
3235
this.lineNumber= lineNumber;
33-
this.textWidget= textWidget;
36+
this.sourceViewer= sourceViewer;
3437
}
3538

3639
@Override
@@ -41,19 +44,28 @@ public int getLineNumber() {
4144
@Override
4245
public String getText() {
4346
if (text == null) {
44-
text= textWidget.getLine(lineNumber);
47+
StyledText textWidget= sourceViewer.getTextWidget();
48+
text= textWidget.getLine(getWidgetLineNumber());
4549
}
4650
return text;
4751
}
4852

4953
@Override
5054
public StyleRange[] getStyleRanges() {
51-
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);
55+
StyledText textWidget= sourceViewer.getTextWidget();
56+
int offsetAtLine= textWidget.getOffsetAtLine(getWidgetLineNumber());
5257
StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, getText().length());
5358
for (StyleRange styleRange : styleRanges) {
5459
styleRange.start= styleRange.start - offsetAtLine;
5560
}
5661
return styleRanges;
5762
}
5863

64+
private int getWidgetLineNumber() {
65+
if (sourceViewer instanceof ITextViewerExtension5 extension) {
66+
return extension.modelLine2WidgetLine(lineNumber);
67+
}
68+
return lineNumber;
69+
}
70+
5971
}

tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProviderTest.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.eclipse.swt.widgets.Display;
3030
import org.eclipse.swt.widgets.Shell;
3131

32+
import org.eclipse.jface.text.Document;
3233
import org.eclipse.jface.text.IRegion;
3334
import org.eclipse.jface.text.ITextViewerExtension5;
3435
import org.eclipse.jface.text.source.IVerticalRuler;
@@ -48,6 +49,7 @@ public class DefaultStickyLinesProviderTest {
4849
public void setup() {
4950
shell = new Shell(Display.getDefault());
5051
sourceViewer = new SourceViewer(shell, null, SWT.None);
52+
sourceViewer.setDocument(new Document());
5153
stickyLinesProvider = new DefaultStickyLinesProvider();
5254
textWidget = sourceViewer.getTextWidget();
5355
stickyLinesProperties = new StickyLinesProperties(4);
@@ -65,12 +67,13 @@ public void testSingleStickyLine() {
6567
String text = """
6668
line 1
6769
line 2<""";
68-
setText(text);
70+
textWidget.setText(text);
6971

7072
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 1, stickyLinesProperties);
7173

7274
assertEquals(1, stickyLines.size());
7375
assertEquals(0, stickyLines.get(0).getLineNumber());
76+
assertEquals("line 1", stickyLines.get(0).getText());
7477
}
7578

7679
@Test
@@ -80,7 +83,7 @@ public void testLineUnderStickyLine() {
8083
line 2<
8184
line 3
8285
line 4""";
83-
setText(text);
86+
textWidget.setText(text);
8487

8588
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 1, stickyLinesProperties);
8689

@@ -95,7 +98,7 @@ public void testNewStickyRoot() {
9598
line 2
9699
line 3
97100
line 4<""";
98-
setText(text);
101+
textWidget.setText(text);
99102

100103
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 3, stickyLinesProperties);
101104

@@ -111,7 +114,7 @@ public void testIgnoreEmptyLines() {
111114
line 2
112115
113116
line 3<""";
114-
setText(text);
117+
textWidget.setText(text);
115118

116119
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 4, stickyLinesProperties);
117120

@@ -127,7 +130,7 @@ public void testLinesWithTabs() {
127130
line 1
128131
\tline 2
129132
\t\tline 3<""";
130-
setText(text);
133+
textWidget.setText(text);
131134

132135
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 2, stickyLinesProperties);
133136

@@ -162,7 +165,7 @@ public void testStartAtEmptyLineWithPrevious() {
162165
line 3
163166
164167
line 4""";
165-
setText(text);
168+
textWidget.setText(text);
166169

167170
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 3, stickyLinesProperties);
168171

@@ -174,27 +177,21 @@ public void testStartAtEmptyLineWithPrevious() {
174177
@Test
175178
public void testStickyLineWithSourceViewerLineMapping() {
176179
sourceViewer = new SourceViewerWithLineMapping(shell, null, SWT.None);
180+
sourceViewer.setDocument(new Document());
177181
textWidget = sourceViewer.getTextWidget();
178182

179183
String text = """
180184
line 1
181185
line 2<""";
182-
setText(text);
186+
textWidget.setText(text);
183187

184188
// Source viewer line 43 that is mapped to line 1 in the text widget
185189
List<IStickyLine> stickyLines = stickyLinesProvider.getStickyLines(sourceViewer, 1 + 42, stickyLinesProperties);
186190

187191
assertEquals(1, stickyLines.size());
188192
// Source viewer line 42 that is mapped to line 0 in the text widget
189193
assertEquals(0 + 42, stickyLines.get(0).getLineNumber());
190-
}
191-
192-
/**
193-
* Set the text into the text widget and set the top index to the line
194-
* containing the <.
195-
*/
196-
private void setText(String text) {
197-
textWidget.setText(text);
194+
assertEquals("line 1", stickyLines.get(0).getText());
198195
}
199196

200197
private class SourceViewerWithLineMapping extends SourceViewer implements ITextViewerExtension5 {

tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLineTest.java

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,29 @@
2323
import org.eclipse.swt.custom.StyleRange;
2424
import org.eclipse.swt.custom.StyledText;
2525
import org.eclipse.swt.graphics.Color;
26+
import org.eclipse.swt.widgets.Composite;
2627
import org.eclipse.swt.widgets.Shell;
2728

29+
import org.eclipse.jface.text.Document;
30+
import org.eclipse.jface.text.IRegion;
31+
import org.eclipse.jface.text.ITextViewerExtension5;
32+
import org.eclipse.jface.text.source.ISourceViewer;
33+
import org.eclipse.jface.text.source.IVerticalRuler;
34+
import org.eclipse.jface.text.source.SourceViewer;
35+
2836
public class StickyLineTest {
2937

3038
private Shell shell;
3139
private StyledText textWidget;
3240
private Color color;
41+
private ISourceViewer sourceViewer;
3342

3443
@Before
3544
public void setUp() {
3645
shell = new Shell();
37-
textWidget = new StyledText(shell, SWT.NONE);
46+
sourceViewer = new SourceViewer(shell, null, SWT.None);
47+
sourceViewer.setDocument(new Document());
48+
textWidget = sourceViewer.getTextWidget();
3849
color = new Color(0, 0, 0);
3950
}
4051

@@ -46,15 +57,15 @@ public void tearDown() {
4657

4758
@Test
4859
public void testGetLineNumber() {
49-
StickyLine stickyLine = new StickyLine(1, textWidget);
60+
StickyLine stickyLine = new StickyLine(1, sourceViewer);
5061

5162
assertEquals(1, stickyLine.getLineNumber());
5263
}
5364

5465
@Test
5566
public void testGetText() {
5667
textWidget.setText("line1\nline2\nline3");
57-
StickyLine stickyLine = new StickyLine(1, textWidget);
68+
StickyLine stickyLine = new StickyLine(1, sourceViewer);
5869

5970
assertEquals("line2", stickyLine.getText());
6071
}
@@ -73,7 +84,7 @@ public void testGetStyleRanges() {
7384
// line3
7485
textWidget.setStyleRange(new StyleRange(15, 1, color, null));
7586

76-
StickyLine stickyLine = new StickyLine(1, textWidget);
87+
StickyLine stickyLine = new StickyLine(1, sourceViewer);
7788
StyleRange[] styleRanges = stickyLine.getStyleRanges();
7889

7990
assertEquals(2, styleRanges.length);
@@ -83,4 +94,64 @@ public void testGetStyleRanges() {
8394
assertEquals(2, styleRanges[1].length);
8495
}
8596

97+
@Test
98+
public void WithSourceViewerLineMapping() {
99+
sourceViewer = new SourceViewerWithLineMapping(shell, null, SWT.None);
100+
sourceViewer.setDocument(new Document());
101+
textWidget = sourceViewer.getTextWidget();
102+
103+
textWidget.setText("line1\nline2\nline3");
104+
105+
// line1
106+
textWidget.setStyleRange(new StyleRange(2, 1, color, null));
107+
108+
// line2
109+
textWidget.setStyleRange(new StyleRange(6, 1, color, null));
110+
textWidget.setStyleRange(new StyleRange(8, 2, color, null));
111+
112+
// line3
113+
textWidget.setStyleRange(new StyleRange(15, 1, color, null));
114+
115+
StickyLine stickyLine = new StickyLine(1 + 42, sourceViewer);
116+
StyleRange[] styleRanges = stickyLine.getStyleRanges();
117+
118+
assertEquals(1 + 42, stickyLine.getLineNumber());
119+
120+
assertEquals("line2", stickyLine.getText());
121+
122+
assertEquals(2, styleRanges.length);
123+
assertEquals(0, styleRanges[0].start);
124+
assertEquals(1, styleRanges[0].length);
125+
assertEquals(2, styleRanges[1].start);
126+
assertEquals(2, styleRanges[1].length);
127+
}
128+
129+
private class SourceViewerWithLineMapping extends SourceViewer implements ITextViewerExtension5 {
130+
131+
public SourceViewerWithLineMapping(Composite parent, IVerticalRuler ruler, int styles) {
132+
super(parent, ruler, styles);
133+
}
134+
135+
@Override
136+
public IRegion[] getCoveredModelRanges(IRegion modelRange) {
137+
return null;
138+
}
139+
140+
@Override
141+
public boolean exposeModelRange(IRegion modelRange) {
142+
return false;
143+
}
144+
145+
@Override
146+
public int widgetLine2ModelLine(int widgetLine) {
147+
return widgetLine + 42;
148+
}
149+
150+
@Override
151+
public int modelLine2WidgetLine(int widgetLine) {
152+
return widgetLine - 42;
153+
}
154+
155+
}
156+
86157
}

0 commit comments

Comments
 (0)