Question

Problem: I have CaretListener and DocumentListener listening on a JTextPane.

I need an algorithm that is able to tell which line is the caret at in a JTextPane, here's an illustrative example:

alt text

Result: 3rd line

alt text

Result: 2nd line

alt text

Result: 4th line

and if the algorithm can tell which line the caret is in the JTextPane, it should be fairly easy to substring whatever that is in between the parentheses as the picture (caret is at character m of metadata):

alt text

--

This is how I divide the entire text that I retrieved from the JTextPane into sentences:

String[] lines = textPane.getText().split("\r?\n|\r", -1);

The sentences in the textPane is separated with \n.

Problem is, how can I manipulate the caret to let me know at which position and which line it is in? I know the dot of the caret says at which position it is, but I can't tell which line it is at. Assuming if I know which line the caret is, then I can just do lines[<line number>] and manipulate the string from there.

In Short: How do I use CaretListener and/or DocumentListener to know which line the caret is currently at, and retrieve the line for further string manipulation? Please help. Thanks.

Do let me know if further clarification is needed. Thanks for your time.

Was it helpful?

Solution

Here is the source code you requested :

static int getLineOfOffset(JTextComponent comp, int offset) throws BadLocationException {
    Document doc = comp.getDocument();
    if (offset < 0) {
        throw new BadLocationException("Can't translate offset to line", -1);
    } else if (offset > doc.getLength()) {
        throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1);
    } else {
        Element map = doc.getDefaultRootElement();
        return map.getElementIndex(offset);
    }
}

static int getLineStartOffset(JTextComponent comp, int line) throws BadLocationException {
    Element map = comp.getDocument().getDefaultRootElement();
    if (line < 0) {
        throw new BadLocationException("Negative line", -1);
    } else if (line >= map.getElementCount()) {
        throw new BadLocationException("No such line", comp.getDocument().getLength() + 1);
    } else {
        Element lineElem = map.getElement(line);
        return lineElem.getStartOffset();
    }
}

...

public void caretUpdate(CaretEvent e) {
    int dot = e.getDot();
    int line = getLineOfOffset(textComponent, dot);
    int positionInLine = dot - getLineStartOffset(textComponent, line);
    ...
}

OTHER TIPS

Use the notion of paragraph in in the StyledDocument with JTextPane.getStyledDocument.

With the position of cursor, you know the current paragraph with StyledDocument.getParagraph(pos). Then you iterate throw the paragraphs from StyledDocument.getRootElements and children, to search the number of current paragraph, so the number of current line.

Sorry for my english.

This is how I divide the entire text that I retrieved from the JTextPane into sentences:

Your solution is not very efficient.

First of all only a "\n" is ever stored in a Document not matter what OS is being used. So you can simplify the regex.

However, there is no need to use a regex to parse the entire Document since you only care about 1 line in the Document. Now that you know about the Element interface you can make the code more efficient.

a) get the line as demonstrated previously
b) now you can get the Element represented by that line, from the root Element
c) now you can use the start/end offsets and the getText(...) method to get only the text for that particular line.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top