Skip to content

Commit

Permalink
Move text and style calculation to StickyLine
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher-Hermann committed Oct 14, 2024
1 parent 86b314e commit d75a726
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ public class DefaultStickyLinesProvider implements IStickyLinesProvider {
private StickyLinesProperties fProperties;

@Override
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties) {
public List<IStickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties) {
this.fProperties= properties;
LinkedList<StickyLine> stickyLines= new LinkedList<>();
LinkedList<IStickyLine> stickyLines= new LinkedList<>();

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

if (indentation < previousIndetation) {
previousIndetation= indentation;
stickyLines.addFirst(new StickyLine(line, i));
stickyLines.addFirst(new StickyLine(i, textWidget));
}
}
} catch (IllegalArgumentException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2024 SAP SE.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP SE - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.texteditor.stickyscroll;

import org.eclipse.swt.custom.StyleRange;

/**
* Representation of a sticky line.
*/
public interface IStickyLine {

/**
* Returns the line number of the sticky line.
*
* @return the line number of the sticky line
*/
int getLineNumber();

/**
* Returns the text of the sticky line.
*
* @return the text of the sticky line
*/
String getText();

/**
* Returns the style ranges of the sticky line.
*
* @return the style ranges of the sticky line
*/
StyleRange[] getStyleRanges();

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public interface IStickyLinesProvider {
* @see ISourceViewer#getTextWidget()
* @see StyledText#getTopIndex()
*/
public List<StickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);
public List<IStickyLine> getStickyLines(StyledText textWidget, int lineNumber, StickyLinesProperties properties);

/**
* Additional properties and access in order to calculate the sticky lines.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,47 @@
*******************************************************************************/
package org.eclipse.ui.internal.texteditor.stickyscroll;

import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;

/**
*
* A record representing a sticky line containing the text to display, and line number. It serves as
* an abstraction to represent sticky line for sticky scrolling.
*
* @param text the text of the corresponding sticky line
* @param lineNumber the specific line number of the sticky line
* Default implementation of {@link IStickyLine}. Information about the text and style ranges are
* calculated from the given text widget.
*/
public record StickyLine(String text, int lineNumber) {
public class StickyLine implements IStickyLine {

private int lineNumber;

private String text;

private StyledText textWidget;

public StickyLine(int lineNumber, StyledText textWidget) {
this.lineNumber= lineNumber;
this.textWidget= textWidget;
}

@Override
public int getLineNumber() {
return this.lineNumber;
}

@Override
public String getText() {
if (text == null) {
text= textWidget.getLine(lineNumber);
}
return text;
}

@Override
public StyleRange[] getStyleRanges() {
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);
StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, getText().length());
for (StyleRange styleRange : styleRanges) {
styleRange.start= styleRange.start - offsetAtLine;
}
return styleRanges;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
package org.eclipse.ui.internal.texteditor.stickyscroll;

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

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

private List<StickyLine> stickyLines;
private List<IStickyLine> stickyLines;

private ISourceViewer sourceViewer;

Expand Down Expand Up @@ -135,7 +133,7 @@ public StickyScrollingControl(ISourceViewer sourceViewer, IVerticalRuler vertica
*
* @param stickyLines The sticky lines to show
*/
public void setStickyLines(List<StickyLine> stickyLines) {
public void setStickyLines(List<IStickyLine> stickyLines) {
if (!stickyLines.equals(this.stickyLines)) {
this.stickyLines= stickyLines;
updateStickyScrollingControls();
Expand Down Expand Up @@ -206,9 +204,9 @@ private void updateStickyScrollingControls() {
StringJoiner stickyLineTextJoiner= new StringJoiner(System.lineSeparator());
StringJoiner stickyLineNumberJoiner= new StringJoiner(System.lineSeparator());
for (int i= 0; i < getNumberStickyLines(); i++) {
StickyLine stickyLine= stickyLines.get(i);
stickyLineTextJoiner.add(stickyLine.text());
int lineNumber= getSourceViewerLineNumber(stickyLine.lineNumber());
IStickyLine stickyLine= stickyLines.get(i);
stickyLineTextJoiner.add(stickyLine.getText());
int lineNumber= getSourceViewerLineNumber(stickyLine.getLineNumber());
stickyLineNumberJoiner.add(fillLineNumberWithLeadingSpaces(lineNumber + 1));
}

Expand Down Expand Up @@ -244,14 +242,19 @@ private void styleStickyLines() {
return;
}

List<StyleRange> stickyLinesStyleRanges= new ArrayList<>();
int stickyLineTextOffset= 0;
for (int i= 0; i < getNumberStickyLines(); i++) {
StickyLine stickyLine= stickyLines.get(i);
stickyLinesStyleRanges.addAll(getStickyLineStyleRanges(stickyLine, stickyLineTextOffset));
stickyLineTextOffset+= stickyLine.text().length() + System.lineSeparator().length();
int stickyLineOffset= 0;
for (IStickyLine stickyLine : stickyLines) {
StyleRange[] styleRanges= stickyLine.getStyleRanges();

if (styleRanges != null) {
for (StyleRange styleRange : styleRanges) {
styleRange.start+= stickyLineOffset;
stickyLineText.setStyleRange(styleRange);
}
}

stickyLineOffset+= stickyLine.getText().length() + System.lineSeparator().length();
}
stickyLineText.setStyleRanges(stickyLinesStyleRanges.toArray(StyleRange[]::new));

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

private List<StyleRange> getStickyLineStyleRanges(StickyLine stickyLine, int stickyLineTextOffset) {
int lineNumber= stickyLine.lineNumber();
try {
StyledText textWidget= sourceViewer.getTextWidget();
int offsetAtLine= textWidget.getOffsetAtLine(lineNumber);
StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, stickyLine.text().length());
for (StyleRange styleRange : styleRanges) {
styleRange.start= styleRange.start - offsetAtLine + stickyLineTextOffset;
}
return Arrays.asList(styleRanges);
} catch (IllegalArgumentException e) {
//Styling could not be copied, skip!
return Collections.emptyList();
}
}

private void layoutStickyLines() {
if (getNumberStickyLines() == 0) {
stickyLinesCanvas.setVisible(false);
Expand Down Expand Up @@ -365,12 +352,12 @@ private void calculateAndSetStickyLinesCanvasBounds() {

private void navigateToClickedLine(MouseEvent event) {
int clickedStickyLineIndex= stickyLineText.getLineIndex(event.y);
StickyLine clickedStickyLine= stickyLines.get(clickedStickyLineIndex);
IStickyLine clickedStickyLine= stickyLines.get(clickedStickyLineIndex);

try {
int offset= sourceViewer.getDocument().getLineOffset(clickedStickyLine.lineNumber());
int offset= sourceViewer.getDocument().getLineOffset(clickedStickyLine.getLineNumber());
sourceViewer.setSelectedRange(offset, 0);
ensureSourceViewerLineVisible(clickedStickyLine.lineNumber());
ensureSourceViewerLineVisible(clickedStickyLine.getLineNumber());
} catch (BadLocationException e) {
//Do not navigate
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public void viewportChanged(int newVerticalOffset) {
}

private void calculateAndShowStickyLines() {
List<StickyLine> stickyLines= Collections.emptyList();
List<IStickyLine> stickyLines= Collections.emptyList();

StyledText textWidget= sourceViewer.getTextWidget();
int startLine= textWidget.getTopIndex();
Expand All @@ -171,19 +171,19 @@ private void calculateAndShowStickyLines() {
stickyScrollingControl.setStickyLines(stickyLines);
}

private List<StickyLine> adaptStickyLinesToVisibleArea(List<StickyLine> stickyLines, int startLine) {
private List<IStickyLine> adaptStickyLinesToVisibleArea(List<IStickyLine> stickyLines, int startLine) {
if (stickyLines.isEmpty()) {
return stickyLines;
}

LinkedList<StickyLine> adaptedStickyLines= new LinkedList<>(stickyLines);
LinkedList<IStickyLine> adaptedStickyLines= new LinkedList<>(stickyLines);

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

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

if (stickyLinesInLineI.size() > adaptedStickyLines.size()) {
adaptedStickyLines= new LinkedList<>(stickyLinesInLineI);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2024 SAP SE.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP SE - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.texteditor.stickyscroll;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Shell;

public class StickyLineTest {

private Shell shell;
private StyledText textWidget;
private Color color;

@Before
public void setUp() {
shell = new Shell();
textWidget = new StyledText(shell, SWT.NONE);
color = new Color(0, 0, 0);
}

@After
public void tearDown() {
shell.dispose();
color.dispose();
}

@Test
public void testGetLineNumber() {
StickyLine stickyLine = new StickyLine(1, textWidget);

assertEquals(1, stickyLine.getLineNumber());
}

@Test
public void testGetText() {
textWidget.setText("line1\nline2\nline3");
StickyLine stickyLine = new StickyLine(1, textWidget);

assertEquals("line2", stickyLine.getText());
}

@Test
public void testGetStyleRanges() {
textWidget.setText("line1\nline2\nline3");

// line1
textWidget.setStyleRange(new StyleRange(2, 1, color, null));

// line2
textWidget.setStyleRange(new StyleRange(6, 1, color, null));
textWidget.setStyleRange(new StyleRange(8, 2, color, null));

// line3
textWidget.setStyleRange(new StyleRange(15, 1, color, null));

StickyLine stickyLine = new StickyLine(1, textWidget);
StyleRange[] styleRanges = stickyLine.getStyleRanges();

assertEquals(2, styleRanges.length);
assertEquals(0, styleRanges[0].start);
assertEquals(1, styleRanges[0].length);
assertEquals(2, styleRanges[1].start);
assertEquals(2, styleRanges[1].length);
}

}
Loading

0 comments on commit d75a726

Please sign in to comment.