Skip to content

Commit 86b314e

Browse files
StickyScrolling: Move complex line adaption to central handler
1 parent d50e66d commit 86b314e

File tree

7 files changed

+209
-181
lines changed

7 files changed

+209
-181
lines changed

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

Lines changed: 15 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919

2020
import org.eclipse.swt.custom.StyledText;
2121

22-
import org.eclipse.jface.text.ITextViewerExtension5;
23-
import org.eclipse.jface.text.source.ISourceViewer;
24-
2522
/**
2623
* This class provides sticky lines for the given source code in the source viewer. The
2724
* implementation is completely based on indentation and therefore works by default for several
@@ -36,83 +33,31 @@ public class DefaultStickyLinesProvider implements IStickyLinesProvider {
3633
private StickyLinesProperties fProperties;
3734

3835
@Override
39-
public List<StickyLine> getStickyLines(ISourceViewer sourceViewer, StickyLinesProperties properties) {
40-
if (sourceViewer.getTopIndex() == 0) {
41-
return Collections.emptyList();
42-
}
43-
36+
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties) {
4437
this.fProperties= properties;
4538
LinkedList<StickyLine> stickyLines= new LinkedList<>();
4639

4740
try {
48-
StyledText textWidget= sourceViewer.getTextWidget();
49-
int startLine= textWidget.getTopIndex();
41+
int startIndetation= getStartIndentation(lineNumber, textWidget);
5042

51-
calculateStickyLinesForLineNumber(stickyLines, sourceViewer, startLine);
52-
calculateStickyLinesUnderStickyLineControl(stickyLines, sourceViewer, startLine);
53-
} catch (IllegalArgumentException e) {
54-
stickyLines.clear();
55-
}
43+
for (int i= lineNumber, previousIndetation= startIndetation; i >= 0; i--) {
44+
String line= textWidget.getLine(i);
45+
int indentation= getIndentation(line);
5646

57-
return stickyLines;
58-
}
47+
if (indentation == IGNORE_LINE_INDENTATION) {
48+
continue;
49+
}
5950

60-
private void calculateStickyLinesForLineNumber(LinkedList<StickyLine> stickyLines, ISourceViewer sourceViewer, int lineNumber) {
61-
StyledText textWidget= sourceViewer.getTextWidget();
62-
int startIndetation= getStartIndentation(lineNumber, textWidget);
63-
64-
for (int i= lineNumber, previousIndetation= startIndetation; i >= 0; i--) {
65-
String line= textWidget.getLine(i);
66-
int indentation= getIndentation(line);
67-
68-
if (indentation == IGNORE_LINE_INDENTATION) {
69-
continue;
70-
}
71-
72-
if (indentation < previousIndetation) {
73-
previousIndetation= indentation;
74-
stickyLines.addFirst(new StickyLine(line, mapLineNumberToSourceViewerLine(i, sourceViewer)));
75-
}
76-
}
77-
}
78-
79-
private void calculateStickyLinesUnderStickyLineControl(LinkedList<StickyLine> stickyLines, ISourceViewer sourceViewer, int startLine) {
80-
int firstBelowControl= startLine + stickyLines.size();
81-
StyledText textWidget= sourceViewer.getTextWidget();
82-
int lineCount= textWidget.getLineCount();
83-
84-
for (int i= startLine; i < firstBelowControl && i < lineCount; i++) {
85-
86-
String line= textWidget.getLine(i);
87-
int indentation= getIndentation(line);
88-
if (indentation == IGNORE_LINE_INDENTATION) {
89-
continue;
90-
}
91-
92-
while (!stickyLines.isEmpty() && indentation <= getLastStickyLineIndentation(stickyLines) && i < firstBelowControl) {
93-
stickyLines.removeLast();
94-
firstBelowControl--;
95-
}
96-
97-
String nextContentLine= getNextContentLine(i, textWidget);
98-
if (getIndentation(nextContentLine) > indentation && i < firstBelowControl) {
99-
stickyLines.addLast(new StickyLine(line, mapLineNumberToSourceViewerLine(i, sourceViewer)));
100-
firstBelowControl++;
101-
continue;
51+
if (indentation < previousIndetation) {
52+
previousIndetation= indentation;
53+
stickyLines.addFirst(new StickyLine(line, i));
54+
}
10255
}
56+
} catch (IllegalArgumentException e) {
57+
stickyLines.clear();
10358
}
104-
}
10559

106-
private int getLastStickyLineIndentation(LinkedList<StickyLine> stickyLines) {
107-
String text= stickyLines.getLast().text();
108-
return getIndentation(text);
109-
}
110-
111-
private int mapLineNumberToSourceViewerLine(int lineNumber, ISourceViewer sourceViewer) {
112-
if (sourceViewer instanceof ITextViewerExtension5 extension) {
113-
return extension.widgetLine2ModelLine(lineNumber);
114-
}
115-
return lineNumber;
60+
return stickyLines;
11661
}
11762

11863
private int getStartIndentation(int startFromLine, StyledText styledText) {

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,28 @@
2828
public interface IStickyLinesProvider {
2929

3030
/**
31-
* Calculate the sticky lines for the source code of the given sourceViewer. Specific
32-
* properties, such as the <code>tabWidht</code> can be retrieved from the
33-
* <code>properties</code>.
31+
* Calculate the sticky lines for the source code of the given textWidget. Specific properties,
32+
* such as the <code>tabWidht</code> can be retrieved from the <code>properties</code>. To get
33+
* access to additional information, the source viewer can be used.
3434
*
35-
* @param sourceViewer The source viewer containing the source code and information about the
36-
* first visible line
35+
* @param textWidget The text widget containing the source code
36+
* @param lineNumber The line number to calculate the sticky lines for
37+
* @param properties Properties for additional information
3738
* @return The list of sticky lines to show
3839
*
3940
* @see ISourceViewer#getTopIndex()
4041
* @see ISourceViewer#getTextWidget()
4142
* @see StyledText#getTopIndex()
4243
*/
43-
public List<StickyLine> getStickyLines(ISourceViewer sourceViewer, StickyLinesProperties properties);
44+
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);
4445

4546
/**
46-
* Properties required to calculate the sticky lines.
47+
* Additional properties and access in order to calculate the sticky lines.
4748
*
4849
* @param tabWith The with of a tab
50+
* @param sourceViewer The sourceViewer to access additional information
4951
*/
50-
record StickyLinesProperties(int tabWith) {
52+
record StickyLinesProperties(int tabWith, ISourceViewer sourceViewer) {
5153
}
5254

5355
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ private void updateStickyScrollingControls() {
208208
for (int i= 0; i < getNumberStickyLines(); i++) {
209209
StickyLine stickyLine= stickyLines.get(i);
210210
stickyLineTextJoiner.add(stickyLine.text());
211-
stickyLineNumberJoiner.add(fillLineNumberWithLeadingSpaces(stickyLine.lineNumber() + 1));
211+
int lineNumber= getSourceViewerLineNumber(stickyLine.lineNumber());
212+
stickyLineNumberJoiner.add(fillLineNumberWithLeadingSpaces(lineNumber + 1));
212213
}
213214

214215
String newStickyLineText= stickyLineTextJoiner.toString();
@@ -223,6 +224,13 @@ private void updateStickyScrollingControls() {
223224
}
224225
}
225226

227+
private int getSourceViewerLineNumber(int i) {
228+
if (sourceViewer instanceof ITextViewerExtension5 extension) {
229+
return extension.widgetLine2ModelLine(i);
230+
}
231+
return i;
232+
}
233+
226234
private String fillLineNumberWithLeadingSpaces(int lineNumber) {
227235
int lineCount= sourceViewer.getDocument().getNumberOfLines();
228236
int lineNumberLength= String.valueOf(lineCount).length();
@@ -257,9 +265,6 @@ private void styleStickyLines() {
257265

258266
private List<StyleRange> getStickyLineStyleRanges(StickyLine stickyLine, int stickyLineTextOffset) {
259267
int lineNumber= stickyLine.lineNumber();
260-
if (sourceViewer instanceof ITextViewerExtension5 extension) {
261-
lineNumber= extension.modelLine2WidgetLine(lineNumber);
262-
}
263268
try {
264269
StyledText textWidget= sourceViewer.getTextWidget();
265270
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);

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

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
import java.time.Duration;
2424
import java.util.Collections;
25+
import java.util.LinkedList;
2526
import java.util.List;
2627

28+
import org.eclipse.swt.custom.StyledText;
2729
import org.eclipse.swt.graphics.Color;
2830
import org.eclipse.swt.graphics.RGB;
2931

@@ -138,7 +140,7 @@ private StickyScrollingControlSettings loadControlSettings(IPreferenceStore stor
138140

139141
private StickyLinesProperties loadStickyLinesProperties(IPreferenceStore store) {
140142
int tabWidth= store.getInt(EDITOR_TAB_WIDTH);
141-
return new StickyLinesProperties(tabWidth);
143+
return new StickyLinesProperties(tabWidth, sourceViewer);
142144
}
143145

144146
@Override
@@ -151,13 +153,52 @@ public void viewportChanged(int newVerticalOffset) {
151153
}
152154

153155
private void calculateAndShowStickyLines() {
154-
List<StickyLine> stickyLines= stickyLinesProvider.getStickyLines(sourceViewer, stickyLinesProperties);
156+
List<StickyLine> stickyLines= Collections.emptyList();
157+
158+
StyledText textWidget= sourceViewer.getTextWidget();
159+
int startLine= textWidget.getTopIndex();
160+
161+
if (startLine > 0) {
162+
stickyLines= stickyLinesProvider.getStickyLines(textWidget, startLine, stickyLinesProperties);
163+
}
164+
155165
if (stickyLines == null) {
156166
stickyLines= Collections.emptyList();
157167
}
168+
169+
stickyLines= adaptStickyLinesToVisibleArea(stickyLines, startLine);
170+
158171
stickyScrollingControl.setStickyLines(stickyLines);
159172
}
160173

174+
private List<StickyLine> adaptStickyLinesToVisibleArea(List<StickyLine> stickyLines, int startLine) {
175+
if (stickyLines.isEmpty()) {
176+
return stickyLines;
177+
}
178+
179+
LinkedList<StickyLine> adaptedStickyLines= new LinkedList<>(stickyLines);
180+
181+
int firstVisibleLine= startLine + adaptedStickyLines.size();
182+
StyledText textWidget= sourceViewer.getTextWidget();
183+
int maximumLines= textWidget.getLineCount();
184+
185+
for (int i= startLine + 1; i <= firstVisibleLine && i < maximumLines; i++) {
186+
List<StickyLine> stickyLinesInLineI= stickyLinesProvider.getStickyLines(textWidget, i, stickyLinesProperties);
187+
188+
if (stickyLinesInLineI.size() > adaptedStickyLines.size()) {
189+
adaptedStickyLines= new LinkedList<>(stickyLinesInLineI);
190+
firstVisibleLine= startLine + adaptedStickyLines.size();
191+
}
192+
193+
while (stickyLinesInLineI.size() < adaptedStickyLines.size() && i < firstVisibleLine) {
194+
adaptedStickyLines.removeLast();
195+
firstVisibleLine--;
196+
}
197+
}
198+
199+
return adaptedStickyLines;
200+
}
201+
161202
/**
162203
* Uninstalls the sticky scrolling handler from the source viewer. This completely disposes the
163204
* {@link StickyScrollingControl} and removes all corresponding listeners.

0 commit comments

Comments
 (0)