Different Styles in PlainView - Syntax Highlighting?
Hi,
I've managed to extend PlainView and looking at old JEdit code I have the syntax highlighting working for the most part. However, at certain times while typing the cursor starts to get way ahead of the text it's typing. And as I backspace on the line the cursor eventually gets closer to the character the closer it gets to the start of the line.
I'm overridding the "drawUnselectedText()" method in PlainView to do the coloring.
Here's the code, you can see the call to SyntaxUtilities.paintSyntaxLine() which is JEdit's class to do the drawing.
/**
* Renders the given range in the model as normal unselected text. This
* is implemented to paint colors based upon the token-to-color
* translations. To reduce the number of calls to the Graphics object,
* text is batched up until a color change is detected or the entire
* requested range has been reached.
*
* @param g
*the graphics context
* @param x
*the starting X coordinate
* @param y
*the starting Y coordinate
* @param p0
*the beginning position in the model
* @param p1
*the ending position in the model
* @returns the location of the end of the range
* @exception BadLocationException
*if the range is invalid
*/
protectedint drawUnselectedText(Graphics g,int x,int y,int p0,int p1)throws BadLocationException{
System.out.println("p0: " + p0 +" p1: " + p1 +" x: " + x +" y: " + y);
// Get the start of the element
int lineIndex = doc.getDefaultRootElement().getElementIndex(p0);
// Get the element for the line
Element elem = doc.getDefaultRootElement().getElement(lineIndex);
System.out.println("lineIndex: " + lineIndex +" elemStartIDX: " + elem.getStartOffset() +" elemEndIDX: " + elem.getEndOffset());
// Get the line text
doc.getText(p0, p1 - p0, currentLineText);
// If highlighting, mark the tokens
if (marker !=null){
Token t = marker.markTokens(currentLineText, lineIndex);
x = SyntaxUtilities.paintSyntaxLine(currentLineText, t, styles, this, g, x, y, p0, p1);
System.out.println("Painted line at: " + x);
}else{
// No highlighting requested, draw normal text
Font defaultFont = g.getFont();
Color defaultColor = styles[0].getColor();// Default color of text
g.setFont(defaultFont);
g.setColor(defaultColor);
x = Utilities.drawTabbedText(currentLineText, x, y, g, this, p0);
}
// Set the last line processed
lastLine = lineIndex;
return x;
}
Here is the code from the paintSyntaxLine() method:
/**
* Paints the specified line onto the graphics context. Note that this
* method munges the offset and count values of the segment.
*
* @param line
*The line segment
* @param tokens
*The token list for the line
* @param styles
*The syntax style list
* @param expander
*The tab expander used to determine tab stops. May be null
* @param gfx
*The graphics context
* @param x
*The x co-ordinate
* @param y
*The y co-ordinate
* @return The x co-ordinate, plus the width of the painted string
*/
publicstaticint paintSyntaxLine(Segment line, Token tokens, SyntaxStyle[] styles, TabExpander expander, Graphics gfx,int x,int y,int p0,int p1){
Font defaultFont = gfx.getFont();
Color defaultColor = Color.black;
FontMetrics fm = gfx.getFontMetrics(defaultFont);
int offset = 0;
while (tokens !=null && tokens.id != Token.END){
int length = tokens.length;
if (tokens.id == Token.NULL){
if (!defaultColor.equals(gfx.getColor()))
gfx.setColor(defaultColor);
if (!defaultFont.equals(gfx.getFont()))
gfx.setFont(defaultFont);
}else{
styles[tokens.id].setGraphicsFlags(gfx, defaultFont);
//fm = gfx.getFontMetrics();//[tokens.id].getStyledFont(defaultFont);
//FontMetrics dfm = Toolkit.getDefaultToolkit().getFontMetrics(defaultFont);
//System.out.println("Font Info: CharWidth[" + fm.charWidth(line.array[p1])+"], Max Advance[" + fm.getMaxAdvance()+"]");
//System.out.println("Default Font Info: CharWidth[" + dfm.charWidth(line.array[p1])+"], DMax Advance[" + dfm.getMaxAdvance()+"]");
////x = fm.charsWidth(line.array, p0, length);
}
line.count = length;
x = Utilities.drawTabbedText(line, x, y, gfx, expander, p0);
line.offset += length;
offset += length;
tokens = tokens.next;
}
return x;
}
I'm not sure what the problem is..i thought it might be an issue with the View and drawing multiple font styles. Since plain view only deals with a single font color and size. I tried using LabelView but that seems to need a StyledDocument and I had problems when I tried to use DefaultStyledDocument for my syntaxdocument. I was getting strange offset issues when using the Segment class.
Here's what I posted: http://forum.java.sun.com/thread.jspa?threadID=780801
I am using PlainDocument because that seemed to be what everyone was using for a syntax editor..since the structure of the document in a Plain Document is less complex.
I orginally started out using the setCharacterAttributes() method on the DefaultStyledDocument and letting the views draw the text. That all seemed to work except for the "segment offset" issue. And I wasn't sure where the best spot to get the document to redraw subsequent lines in the case of changing a multiline comment, etc.
So, everything I read about others attempts for syntax highlighters seems to use either StyledEditorKit with a fixed language set with custom parsing and using the setCharacterAttributes method. Or they use the plaindocument approach with a custom view..(which no one seems to share the source) or the project just simply uses the JEditTextArea directly (which we can't do in our product).
We don't need multiple fonts per-line.. The document will always use one font face (Arial, Helvetica, etc) but may use different styles per word (bold, italic, etc).
I thought I'd need to use FontMetrics to get the size of the font and such. But there didn't seem to be a difference in measurements based on the style of the font. (i.,e A bold font has the same charWidth('m') size as a regular style.
At least that's what my test program showed..
The other thing I noticed is that when the document is successfully colored and I use the mouse to select a region of text, the style of the text reverts back to normal. I'm sure that's because I only override the drawUnselectedText() method.
Any ideas? Is there anyone who has successfully done this?
Thanks,
- Tim

