Skip to content

Commit d75a726

Browse files
Move text and style calculation to StickyLine
1 parent 86b314e commit d75a726

File tree

8 files changed

+258
-66
lines changed

8 files changed

+258
-66
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public class DefaultStickyLinesProvider implements IStickyLinesProvider {
3333
private StickyLinesProperties fProperties;
3434

3535
@Override
36-
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties) {
36+
public List<IStickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties) {
3737
this.fProperties= properties;
38-
LinkedList<StickyLine> stickyLines= new LinkedList<>();
38+
LinkedList<IStickyLine> stickyLines= new LinkedList<>();
3939

4040
try {
4141
int startIndetation= getStartIndentation(lineNumber, textWidget);
@@ -50,7 +50,7 @@ public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, St
5050

5151
if (indentation < previousIndetation) {
5252
previousIndetation= indentation;
53-
stickyLines.addFirst(new StickyLine(line, i));
53+
stickyLines.addFirst(new StickyLine(i, textWidget));
5454
}
5555
}
5656
} catch (IllegalArgumentException e) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 SAP SE.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* SAP SE - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal.texteditor.stickyscroll;
15+
16+
import org.eclipse.swt.custom.StyleRange;
17+
18+
/**
19+
* Representation of a sticky line.
20+
*/
21+
public interface IStickyLine {
22+
23+
/**
24+
* Returns the line number of the sticky line.
25+
*
26+
* @return the line number of the sticky line
27+
*/
28+
int getLineNumber();
29+
30+
/**
31+
* Returns the text of the sticky line.
32+
*
33+
* @return the text of the sticky line
34+
*/
35+
String getText();
36+
37+
/**
38+
* Returns the style ranges of the sticky line.
39+
*
40+
* @return the style ranges of the sticky line
41+
*/
42+
StyleRange[] getStyleRanges();
43+
44+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public interface IStickyLinesProvider {
4141
* @see ISourceViewer#getTextWidget()
4242
* @see StyledText#getTopIndex()
4343
*/
44-
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);
44+
public List<IStickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);
4545

4646
/**
4747
* Additional properties and access in order to calculate the sticky lines.

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

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,47 @@
1313
*******************************************************************************/
1414
package org.eclipse.ui.internal.texteditor.stickyscroll;
1515

16+
import org.eclipse.swt.custom.StyleRange;
17+
import org.eclipse.swt.custom.StyledText;
18+
1619
/**
17-
*
18-
* A record representing a sticky line containing the text to display, and line number. It serves as
19-
* an abstraction to represent sticky line for sticky scrolling.
20-
*
21-
* @param text the text of the corresponding sticky line
22-
* @param lineNumber the specific line number of the sticky line
20+
* Default implementation of {@link IStickyLine}. Information about the text and style ranges are
21+
* calculated from the given text widget.
2322
*/
24-
public record StickyLine(String text, int lineNumber) {
23+
public class StickyLine implements IStickyLine {
24+
25+
private int lineNumber;
26+
27+
private String text;
28+
29+
private StyledText textWidget;
30+
31+
public StickyLine(int lineNumber, StyledText textWidget) {
32+
this.lineNumber= lineNumber;
33+
this.textWidget= textWidget;
34+
}
35+
36+
@Override
37+
public int getLineNumber() {
38+
return this.lineNumber;
39+
}
40+
41+
@Override
42+
public String getText() {
43+
if (text == null) {
44+
text= textWidget.getLine(lineNumber);
45+
}
46+
return text;
47+
}
48+
49+
@Override
50+
public StyleRange[] getStyleRanges() {
51+
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);
52+
StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, getText().length());
53+
for (StyleRange styleRange : styleRanges) {
54+
styleRange.start= styleRange.start - offsetAtLine;
55+
}
56+
return styleRanges;
57+
}
58+
2559
}

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

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
package org.eclipse.ui.internal.texteditor.stickyscroll;
1515

1616
import java.util.ArrayList;
17-
import java.util.Arrays;
18-
import java.util.Collections;
1917
import java.util.Iterator;
2018
import java.util.List;
2119
import java.util.StringJoiner;
@@ -65,7 +63,7 @@
6563
/**
6664
* This class builds a control that is rendered on top of the given source viewer. The controls
6765
* shows the sticky lines that are set via {@link #setStickyLines(List)} on top of the source
68-
* viewer. The {@link StickyLine#lineNumber()} is linked to to corresponding line number in the
66+
* viewer. The {@link StickyLine#getLineNumber()} is linked to to corresponding line number in the
6967
* given source viewer, with index starting at 0.
7068
*
7169
* As part of its responsibilities, the class handles layout arrangement and styling of the sticky
@@ -87,7 +85,7 @@ public class StickyScrollingControl {
8785

8886
private static final String DISABLE_CSS= "org.eclipse.e4.ui.css.disabled"; //$NON-NLS-1$
8987

90-
private List<StickyLine> stickyLines;
88+
private List<IStickyLine> stickyLines;
9189

9290
private ISourceViewer sourceViewer;
9391

@@ -135,7 +133,7 @@ public StickyScrollingControl(ISourceViewer sourceViewer, IVerticalRuler vertica
135133
*
136134
* @param stickyLines The sticky lines to show
137135
*/
138-
public void setStickyLines(List<StickyLine> stickyLines) {
136+
public void setStickyLines(List<IStickyLine> stickyLines) {
139137
if (!stickyLines.equals(this.stickyLines)) {
140138
this.stickyLines= stickyLines;
141139
updateStickyScrollingControls();
@@ -206,9 +204,9 @@ private void updateStickyScrollingControls() {
206204
StringJoiner stickyLineTextJoiner= new StringJoiner(System.lineSeparator());
207205
StringJoiner stickyLineNumberJoiner= new StringJoiner(System.lineSeparator());
208206
for (int i= 0; i < getNumberStickyLines(); i++) {
209-
StickyLine stickyLine= stickyLines.get(i);
210-
stickyLineTextJoiner.add(stickyLine.text());
211-
int lineNumber= getSourceViewerLineNumber(stickyLine.lineNumber());
207+
IStickyLine stickyLine= stickyLines.get(i);
208+
stickyLineTextJoiner.add(stickyLine.getText());
209+
int lineNumber= getSourceViewerLineNumber(stickyLine.getLineNumber());
212210
stickyLineNumberJoiner.add(fillLineNumberWithLeadingSpaces(lineNumber + 1));
213211
}
214212

@@ -244,14 +242,19 @@ private void styleStickyLines() {
244242
return;
245243
}
246244

247-
List<StyleRange> stickyLinesStyleRanges= new ArrayList<>();
248-
int stickyLineTextOffset= 0;
249-
for (int i= 0; i < getNumberStickyLines(); i++) {
250-
StickyLine stickyLine= stickyLines.get(i);
251-
stickyLinesStyleRanges.addAll(getStickyLineStyleRanges(stickyLine, stickyLineTextOffset));
252-
stickyLineTextOffset+= stickyLine.text().length() + System.lineSeparator().length();
245+
int stickyLineOffset= 0;
246+
for (IStickyLine stickyLine : stickyLines) {
247+
StyleRange[] styleRanges= stickyLine.getStyleRanges();
248+
249+
if (styleRanges != null) {
250+
for (StyleRange styleRange : styleRanges) {
251+
styleRange.start+= stickyLineOffset;
252+
stickyLineText.setStyleRange(styleRange);
253+
}
254+
}
255+
256+
stickyLineOffset+= stickyLine.getText().length() + System.lineSeparator().length();
253257
}
254-
stickyLineText.setStyleRanges(stickyLinesStyleRanges.toArray(StyleRange[]::new));
255258

256259
stickyLineNumber.setFont(textWidget.getFont());
257260
stickyLineNumber.setStyleRange(new StyleRange(0, stickyLineNumber.getText().length(), settings.lineNumberColor(), null));
@@ -263,22 +266,6 @@ private void styleStickyLines() {
263266
stickyLineText.setLeftMargin(textWidget.getLeftMargin());
264267
}
265268

266-
private List<StyleRange> getStickyLineStyleRanges(StickyLine stickyLine, int stickyLineTextOffset) {
267-
int lineNumber= stickyLine.lineNumber();
268-
try {
269-
StyledText textWidget= sourceViewer.getTextWidget();
270-
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);
271-
StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, stickyLine.text().length());
272-
for (StyleRange styleRange : styleRanges) {
273-
styleRange.start= styleRange.start - offsetAtLine + stickyLineTextOffset;
274-
}
275-
return Arrays.asList(styleRanges);
276-
} catch (IllegalArgumentException e) {
277-
//Styling could not be copied, skip!
278-
return Collections.emptyList();
279-
}
280-
}
281-
282269
private void layoutStickyLines() {
283270
if (getNumberStickyLines() == 0) {
284271
stickyLinesCanvas.setVisible(false);
@@ -365,12 +352,12 @@ private void calculateAndSetStickyLinesCanvasBounds() {
365352

366353
private void navigateToClickedLine(MouseEvent event) {
367354
int clickedStickyLineIndex= stickyLineText.getLineIndex(event.y);
368-
StickyLine clickedStickyLine= stickyLines.get(clickedStickyLineIndex);
355+
IStickyLine clickedStickyLine= stickyLines.get(clickedStickyLineIndex);
369356

370357
try {
371-
int offset= sourceViewer.getDocument().getLineOffset(clickedStickyLine.lineNumber());
358+
int offset= sourceViewer.getDocument().getLineOffset(clickedStickyLine.getLineNumber());
372359
sourceViewer.setSelectedRange(offset, 0);
373-
ensureSourceViewerLineVisible(clickedStickyLine.lineNumber());
360+
ensureSourceViewerLineVisible(clickedStickyLine.getLineNumber());
374361
} catch (BadLocationException e) {
375362
//Do not navigate
376363
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public void viewportChanged(int newVerticalOffset) {
153153
}
154154

155155
private void calculateAndShowStickyLines() {
156-
List<StickyLine> stickyLines= Collections.emptyList();
156+
List<IStickyLine> stickyLines= Collections.emptyList();
157157

158158
StyledText textWidget= sourceViewer.getTextWidget();
159159
int startLine= textWidget.getTopIndex();
@@ -171,19 +171,19 @@ private void calculateAndShowStickyLines() {
171171
stickyScrollingControl.setStickyLines(stickyLines);
172172
}
173173

174-
private List<StickyLine> adaptStickyLinesToVisibleArea(List<StickyLine> stickyLines, int startLine) {
174+
private List<IStickyLine> adaptStickyLinesToVisibleArea(List<IStickyLine> stickyLines, int startLine) {
175175
if (stickyLines.isEmpty()) {
176176
return stickyLines;
177177
}
178178

179-
LinkedList<StickyLine> adaptedStickyLines= new LinkedList<>(stickyLines);
179+
LinkedList<IStickyLine> adaptedStickyLines= new LinkedList<>(stickyLines);
180180

181181
int firstVisibleLine= startLine + adaptedStickyLines.size();
182182
StyledText textWidget= sourceViewer.getTextWidget();
183183
int maximumLines= textWidget.getLineCount();
184184

185185
for (int i= startLine + 1; i <= firstVisibleLine && i < maximumLines; i++) {
186-
List<StickyLine> stickyLinesInLineI= stickyLinesProvider.getStickyLines(textWidget, i, stickyLinesProperties);
186+
List<IStickyLine> stickyLinesInLineI= stickyLinesProvider.getStickyLines(textWidget, i, stickyLinesProperties);
187187

188188
if (stickyLinesInLineI.size() > adaptedStickyLines.size()) {
189189
adaptedStickyLines= new LinkedList<>(stickyLinesInLineI);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 SAP SE.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* SAP SE - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal.texteditor.stickyscroll;
15+
16+
import static org.junit.Assert.assertEquals;
17+
18+
import org.junit.After;
19+
import org.junit.Before;
20+
import org.junit.Test;
21+
22+
import org.eclipse.swt.SWT;
23+
import org.eclipse.swt.custom.StyleRange;
24+
import org.eclipse.swt.custom.StyledText;
25+
import org.eclipse.swt.graphics.Color;
26+
import org.eclipse.swt.widgets.Shell;
27+
28+
public class StickyLineTest {
29+
30+
private Shell shell;
31+
private StyledText textWidget;
32+
private Color color;
33+
34+
@Before
35+
public void setUp() {
36+
shell = new Shell();
37+
textWidget = new StyledText(shell, SWT.NONE);
38+
color = new Color(0, 0, 0);
39+
}
40+
41+
@After
42+
public void tearDown() {
43+
shell.dispose();
44+
color.dispose();
45+
}
46+
47+
@Test
48+
public void testGetLineNumber() {
49+
StickyLine stickyLine = new StickyLine(1, textWidget);
50+
51+
assertEquals(1, stickyLine.getLineNumber());
52+
}
53+
54+
@Test
55+
public void testGetText() {
56+
textWidget.setText("line1\nline2\nline3");
57+
StickyLine stickyLine = new StickyLine(1, textWidget);
58+
59+
assertEquals("line2", stickyLine.getText());
60+
}
61+
62+
@Test
63+
public void testGetStyleRanges() {
64+
textWidget.setText("line1\nline2\nline3");
65+
66+
// line1
67+
textWidget.setStyleRange(new StyleRange(2, 1, color, null));
68+
69+
// line2
70+
textWidget.setStyleRange(new StyleRange(6, 1, color, null));
71+
textWidget.setStyleRange(new StyleRange(8, 2, color, null));
72+
73+
// line3
74+
textWidget.setStyleRange(new StyleRange(15, 1, color, null));
75+
76+
StickyLine stickyLine = new StickyLine(1, textWidget);
77+
StyleRange[] styleRanges = stickyLine.getStyleRanges();
78+
79+
assertEquals(2, styleRanges.length);
80+
assertEquals(0, styleRanges[0].start);
81+
assertEquals(1, styleRanges[0].length);
82+
assertEquals(2, styleRanges[1].start);
83+
assertEquals(2, styleRanges[1].length);
84+
}
85+
86+
}

0 commit comments

Comments
 (0)