Skip to content

Commit d22b414

Browse files
[StickyScrolling] Move complex line adaption to central handler
Move sticky lines adaptation to the growing sticky lines control into the central sticky scrolling handler. This change simplifies the sticky lines provider, making implementations for specific languages more straightforward and maintainable. Preparation for eclipse-platform#2398
1 parent d6a50a4 commit d22b414

File tree

7 files changed

+211
-186
lines changed

7 files changed

+211
-186
lines changed

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

+15-70
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

+10-12
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,32 @@
2020
import org.eclipse.jface.text.source.ISourceViewer;
2121

2222
/**
23-
* A sticky lines provider calculates the sticky lines for a given source viewer. The sticky lines
23+
* A sticky lines provider calculates the sticky lines for a given text widget. The sticky lines
2424
* will be displayed in the top area of the editor.
2525
*
2626
* TODO move to public package and add since 3.19
2727
*/
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
31+
* Calculate the sticky lines for the source code of the given textWidget. Specific properties,
32+
* such as the <code>tabWidht</code> and the source viewer, can be retrieved from the
3333
* <code>properties</code>.
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
38-
*
39-
* @see ISourceViewer#getTopIndex()
40-
* @see ISourceViewer#getTextWidget()
41-
* @see StyledText#getTopIndex()
4239
*/
43-
public List<StickyLine> getStickyLines(ISourceViewer sourceViewer, StickyLinesProperties properties);
40+
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);
4441

4542
/**
46-
* Properties required to calculate the sticky lines.
43+
* Additional properties and access in order to calculate the sticky lines.
4744
*
4845
* @param tabWith The with of a tab
46+
* @param sourceViewer The sourceViewer to access additional information
4947
*/
50-
record StickyLinesProperties(int tabWith) {
48+
record StickyLinesProperties(int tabWith, ISourceViewer sourceViewer) {
5149
}
5250

5351
}

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

+9-4
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

+43-2
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)