I am almost there thanks to the good people on this list. I just need to please have help with the last bit.
I have a JTextPane where I match certain word patterns and change their color to red. Any word or phrase that starts with pipe/open square brace, and ends with close square brace/pipe, like |[this]|, is matched with the following regex "(\\|\\[[^\\]]*\\])"
.
This works 99%, but it does not color the trailing | red. And if I try to include this in the regex, by adding a \\|
to the end, it fails to match the anything.
Here's my code.
In the button that calls the class, I send a silly string for now that has the delimiters:
private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {
JFrame Escapedframe = new JFrame("Skipppy Cars word changer");
Escapedframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JTextPane SkippytextPane = new JTextPane();
SkippytextPane.setDocument(new ElementHighlight());
SkippytextPane.setText("You should try the |[new model]| car, the |[Skippy 2000]|. The Skippy 2000 comes standard with all the |[features]| of the Bippy 3000, at half the price. You can buy one today at your |[athorized Skippy/Bippy]| dealer.");
Escapedframe.add(SkippytextPane);
Escapedframe.setSize(500,400);
Escapedframe.setLocationRelativeTo(null);
Escapedframe.setVisible(true);
}
And then set:
private int pipeCharEnd (String Xtext, int index) {
while (--index >= 0) {
if (String.valueOf(Xtext.charAt(index)).matches("\\|")) {
break;
}
}
return index;
}
private int pipeCharStart (String Xtext, int index) {
while (index < Xtext.length()) {
if (String.valueOf(Xtext.charAt(index)).matches("\\|")) {
break;
}
index++;
}
return index;
}
And finally the class:
class ElementHighlight extends DefaultStyledDocument {
private final MutableAttributeSet XRED = new SimpleAttributeSet();
final StyleContext myProtected = StyleContext.getDefaultStyleContext();
final AttributeSet attR = myProtected.addAttribute(myProtected.getEmptySet(), StyleConstants.Foreground, Color.RED);
final AttributeSet attB = myProtected.addAttribute(myProtected.getEmptySet(), StyleConstants.Foreground, Color.BLUE);
@Override
public void insertString (int offset, String Pstr, AttributeSet RedBlue) throws BadLocationException
{
super.insertString(offset, Pstr, RedBlue);
String text = getText(0, getLength());
int pre = pipeCharEnd(text, offset);
if (pre < 0) pre = 0;
int post = pipeCharStart(text, offset + Pstr.length());
int prewords = pre;
int postwords = pre;
while (postwords <= post) {
if (postwords == post || String.valueOf(text.charAt(postwords)).matches("\\|")) {
if (text.substring(prewords, postwords).matches("(\\|\\[[^\\]]*\\])"))
setCharacterAttributes(prewords, postwords - prewords, attR, false);
else
setCharacterAttributes(prewords, postwords - prewords, attB, false);
prewords = postwords;
}
postwords++;
}
}
}
Every delimited phrase is turning red, just as expected, except for the trailing pipe in each case, which remains blue.
As I said, I've gotten this far with the help of the good people on this list. If somebody could teach me how to colorize the trailing pipe in the delimiter, I would be most grateful.
Since you enter the following if
condition:
text.substring(prewords, postwords).matches("(\\|\\[[^\\]]*\\])")
... it means that the sub String
between the indices prewords
and postword -1
(included) matches (\\|\\[[^\\]]*\\])
. This regex looks for:
|
followed by[
followed by]
followed by]
.So, considering this sample String
:
0123|[6789012345678]|12345
The regex would match |[6789012345678]
(and not the trailing |
). Thus, we would enter the if
condition with prewords
valued at 4
and postwords
set to 20
.
prewords = 4, postwords = 20
v v
0123|[6789012345678]|12345
If you do:
setCharacterAttributes(prewords, postwords - prewords, attR, false);
... then you're declaring that:
postwords - prewords
charactersprewords
... which is 20-4
(16) characters from index 4
, which in our sample String
represents the following sub String
: |[6789012345678]
(only 16 characters).
If you want to also set the colour of one more character... simply add +1
to your method call!
i.e.:
// here
// v
setCharacterAttributes(prewords, postwords - prewords +1, attR, false);