9

I was wondering if there is a straightforward way to display line numbers with StyledText text field - even if lines are wrapped. I'm using it in my application and if content gets to big, some line numbers would be nice.

Thank you.

kon
  • 3,732
  • 3
  • 26
  • 34
  • There's no true straightforward way as far as I'm aware; you could always put an uneditable text box to the left of your text editor. – Michael Jun 15 '12 at 20:38
  • Check the implementation the Eclipse guys are using. – Adam Arold Jun 18 '12 at 07:54
  • @Adam They are using a `SourceViewer` as shown [here](http://www.dsource.org/projects/dwt/wiki/JFaceTextExample). I tried this example, but somehow I wasn't able to get it running properly. It was doing strange stuff on runtime. Anyway, I would like to keep my `StyleText` :) – kon Jul 12 '12 at 09:22

5 Answers5

6

The key is org.eclipse.swt.custom.Bullet. It's basically a symbol (or in our case a number) you can add to the beginning of a line.

//text is your StyledText
text.addLineStyleListener(new LineStyleListener()
{
    public void lineGetStyle(LineStyleEvent e)
    {
        //Set the line number
        e.bulletIndex = text.getLineAtOffset(e.lineOffset);

        //Set the style, 12 pixles wide for each digit
        StyleRange style = new StyleRange();
        style.metrics = new GlyphMetrics(0, 0, Integer.toString(text.getLineCount()+1).length()*12);

        //Create and set the bullet
        e.bullet = new Bullet(ST.BULLET_NUMBER,style);
    }
});
Ava
  • 2,038
  • 3
  • 23
  • 45
  • 2
    It works nice. It just misses to redraw all lines if the total amount of lines increases from 9 to 10. Or if a lines is removed in the middle of the file. Thank you. – kon Aug 27 '12 at 12:08
4

This is my working implementation.

styledText.addLineStyleListener(new LineStyleListener() {
    @Override
    public void lineGetStyle(LineStyleEvent event) {
        // Using ST.BULLET_NUMBER sometimes results in weird alignment.
        //event.bulletIndex = styledText.getLineAtOffset(event.lineOffset);
        StyleRange styleRange = new StyleRange();
        styleRange.foreground = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
        int maxLine = styledText.getLineCount();
        int bulletLength = Integer.toString(maxLine).length();
        // Width of number character is half the height in monospaced font, add 1 character width for right padding.
        int bulletWidth = (bulletLength + 1) * styledText.getLineHeight() / 2;
        styleRange.metrics = new GlyphMetrics(0, 0, bulletWidth);
        event.bullet = new Bullet(ST.BULLET_TEXT, styleRange);
        // getLineAtOffset() returns a zero-based line index.
        int bulletLine = styledText.getLineAtOffset(event.lineOffset) + 1;
        event.bullet.text = String.format("%" + bulletLength + "s", bulletLine);
    }
});
styledText.addModifyListener(new ModifyListener() {
    @Override
    public void modifyText(ModifyEvent e) {
        // For line number redrawing.
        styledText.redraw();
    }
});

Note that the possible overhead of syntax highlighting recalculation when calling redraw() is likely to be acceptable, because lineGetStyle() are only called with lines currently on screen.

Hai Zhang
  • 5,574
  • 1
  • 44
  • 51
1

I believe that using a LineStyleListener should work. Something along the lines of:

styledText.addLineStyleListener(
    new LineStyleListener() {
        @Override
        public void lineGetStyle(LineStyleEvent event) {
            String line = event.lineText;
            int lineNumber = event.lineOffset;
            // Do stuff to add line numbers
        }
    }
);
  • Could you please mention some more details about your approach? On the web, I just found a bunch of examples with `LineStyleListener` highlighting the content of a line in a certain way e.g. [this example](http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/TurnsecharactersredusingaLineStyleListener.htm). Thank you. – kon Jul 09 '12 at 11:59
1

This is a way to use bullets that updates the numbers when the content changes:

text.addModifyListener(new ModifyListener() {
    public void modifyText(ModifyEvent event) {
        int maxLine = text.getLineCount();
        int lineCountWidth = Math.max(String.valueOf(maxLine).length(), 3);

        StyleRange style = new StyleRange();
        style.metrics = new GlyphMetrics(0, 0, lineCountWidth * 8 + 5);
        Bullet bullet = new Bullet(ST.BULLET_NUMBER, style);
        text.setLineBullet(0, text.getLineCount(), null);
        text.setLineBullet(0, text.getLineCount(), bullet);
    }
});
fgb
  • 18,439
  • 2
  • 38
  • 52
0

As a side-note for colouring the line numbers:

Device device = Display.getCurrent();
style.background = new Color(device, LINE_NUMBER_BG);
style.foreground = new Color(device, LINE_NUMBER_FG);

where LINE_NUMBER_BG and LINE_NUMBER_FG might be a RGB object such as:

final RGB LINE_NUMBER_BG = new RBG(160, 80, 0); // brown
final RGB LINE_NUMBER_FG = new RGB(255, 255, 255); // white
The_Cute_Hedgehog
  • 1,280
  • 13
  • 22