Skip to main content

Slow performance in JTextPane

32 replies [Last post]
seane
Offline
Joined: 2005-06-27

Hi, I have developed a text editor using JTextPane, with syntax highlighting and all other things that a text editor should do, however there is one problem. When I load a huge file, like 17000 lines, the performance only for that text pane becomes slow. The situation is: there is a tabbed pane and there are a few text pane loaded on that tabbed pane, when one of the text panes have a huge file loaded in it, the performance only on that pane becomes slow, the typeing becomes slow and it takes a little time for the pane to react to the key events. but in other panes the performance is okay. So why is that?
And the memory usage goes dramatically high up when I have a file of about 17000 lines, and when I remove that tab from the tabbed pane, the memory usage stays high and doen't change. I tried to set the compoent to null, explicitly calling gc and everythign I could come up with but still after closing a tab, the memory usage is still high and it seems that it does not release the resource.

any idea would be appreciated.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
idk
Offline
Joined: 2005-01-12

Hi,

> Now if I click with the mouse on another part of the text,

You need to repaint the older highlighted rectangle too.

[code]
public void highlight(int start) {
try {
Rectangle r = modelToView(start);
r.x = 0;
r.width = getWidth();
if (! r.equals(rectToHighlight)) {
//we need to repaint the previous
//highlighted rectangle
repaint(rectToHighlight);

rectToHighlight = r;
repaint(rectToHighlight);
}
} catch (Exception ignore) {
ignore.printStackTrace();
}
}
[/code]

>Another question, is there going to be a performance drag

I am not sure there will be any.

> I just call the painter in the mouseReleased.

With repainting both old and new highlighted rectangle it should not necessary.

Thanks,
Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

thanks a lot for all the help, I really learned much about painting, and I could resolve some other issues with line numbers as well.

I found javadesktop forum better than any other similar forums in the way I received prompt (and to the point) responses from experts with real knowledge of Swing. And I definitely recommend javadesktop forum to anybody who's interested in Java.

Thanks again,
Sean

leouser
Offline
Joined: 2005-12-12

SeanE, I have line highlighting that works in my app. Ill study the code I wrote and tell you some steps I took in it to ensure it worked. Im guessing that I had to stash the last line drawn, so I could redraw it if my caret moved to another line. Its not impossible to acheive.

leouser
Offline
Joined: 2005-12-12

ok, here are the relevant notes:

1. Calculates the line hightlight/rectangle each time paint is called.
2. Compares it with the last highlight/rectangle that was drawn. If not equal, call repaint with the old highlight/rectangle. This gets rid of the old highlight/rectangle at the expense of one redraw that matches the size of the hightlight/rectangle.

3. draws highlight/rectangle:
a. If on new line and graphics clip is too small to get full hightlight/rectangle draw, then new graphics object is requested to draw the rectangle completely.
b. If not on new line, just use the graphics object to redraw the clipped area.

-----
One note, my highlighting happens in the paint method. I believe because of this I experienced overpaints of text with the highlight. This lead me to create a color based off of the set color that has alpha transparency. With the alpha transparency my text shows through and the highlight is very mild, not some annoying blazing red color. Easier on the eyes and gets the point across.

seane
Offline
Joined: 2005-06-27

Hi leouser,

Thanks for taking the time and looking at my posting, I've seen some good comments from you. For this particular problem, the solution that Igor proposed worked perfectly and I also noticed that your solution is similar in essence to the one Igor mentioned.

Thanks again.
Sean

idk
Offline
Joined: 2005-01-12

Hi there,

the posted code does not compile.
You might want to post your code inside
[b][[/b][b]code][/b]
[b][[/b][b]/code][/b]
to keep the indentation

Best,
Igor

seane
Offline
Joined: 2005-06-27

Okay, thanks for the tip Igor.

[code]
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;

public class NewEditPane extends JTextPane implements DocumentListener, CaretListener, MouseListener{

protected StyledDocument doc = null;
protected Segment text = new Segment();
protected int caret = 0;
protected int inputLen = 0;
protected NewJavaUtil scanner = null;
protected boolean insertHappened = false;
protected boolean removeHappend = false;
protected boolean fileRead = true;
protected Element root=null, root1 = null;
protected int line = 0, start=0;
protected Element lineElement = null;
private Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.yellow);

public NewEditPane(){
super(new DefaultStyledDocument());
setSize(1600,400);
setPreferredSize(new Dimension(1600,400));
Insets insets = new Insets(2, 11, 2, 11);
setMargin(insets);
addCaretListener(this);
addMouseListener(this);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
setOpaque(true);
setDoubleBuffered(true);
setForeground(Color.black);
setBackground(Color.white);
}

public void setFile(String filename){
scanner = new NewJavaUtil(this);
try{
read(new FileReader(filename), null);
}catch(IOException e){ return;}
scanAll();
invalidate();
highlight(0);
}

public void read (Reader in, Object obj) throws IOException{
doc.removeDocumentListener(this);
super.read(in, obj);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
repaint();
}

public void caretUpdate(CaretEvent e){
painter(); // line highlight
}

public void insertUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = e.getLength();
insertHappened = true;
}

protected void handleStyleOnInsert(int index){
if(index <= 0)
return;
char[] chars = text.array;
AttributeSet currentStyle = getCharacterAttributes();
String str = (String)currentStyle.getAttribute(StyleConstants.NameAttribute);
int start = EditUtil.getStartOfLine(chars, index-1);
int end = EditUtil.getEndOfLine(chars,index+inputLen);
int i = scanner.scan(doc,chars,start,end+1);
end = EditUtil.getEndOfLine(chars,i);
scanner.scan(doc,chars,i+1,end+1);
}

public void removeUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = 0;
removeHappend = true;
}

public void changedUpdate(DocumentEvent e){}

public void repaint(){
Rectangle r = this.getVisibleRect();
repaint(1, r.x, r.y, r.width, r.height);
}

protected void paintComponent(Graphics g){
super.paintComponent(g);
try{
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e1){
return;
}
if(insertHappened || removeHappend){
handleStyleOnInsert(caret);
insertHappened = false;
removeHappend = false;
}
}

/* scans the entire text and set the attributes. */
private void scanAll(){
try {
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e) {
return;
}
char[] chars = text.array;
scanner.scan(doc,chars,0,chars.length);
}
// line highlight
public void painter(){
root = this.getDocument().getDefaultRootElement();
line = root.getElementIndex(getCaretPosition());
lineElement = root.getElement(line);
start = lineElement.getStartOffset();
highlight(start);
repaint();
}

public boolean getScrollableTracksViewportWidth(){
return false;
}

public void setSize(Dimension d){
if(d.width d.width = getParent().getSize().width;
super.setSize(d);
}

public void mousePressed(MouseEvent e) { painter();}
public void mouseClicked(MouseEvent e) { painter();}
public void mouseEntered(MouseEvent e) {painter();}
public void mouseExited(MouseEvent e) {painter();}
public void mouseReleased(MouseEvent e) {painter();}
public void mouseMoved(MouseEvent e) {painter();}
public void mouseDragged(MouseEvent e) {painter();}

public static void main(String args[]){
NewEditPane editPane = new NewEditPane();
editPane.setFile("C:\\EditFrame.java");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.getContentPane().add(new javax.swing.JScrollPane(editPane));
frame.setVisible(true);
}

public void highlight(int start) {
// First remove all old highlights
removeHighlights();
try {
Highlighter highlighter = getHighlighter();
// Create highlighter using private painter and apply around pattern
highlighter.addHighlight(start, start+1, myHighlightPainter);
} catch (BadLocationException e) {

}
}

public void removeHighlights() {
Highlighter hilite = getHighlighter();
Highlighter.Highlight[] hilites = hilite.getHighlights();
for (int i=0; i if (hilites[i].getPainter() instanceof MyHighlightPainter) {
hilite.removeHighlight(hilites[i]);
}
}
}

protected class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {
public MyHighlightPainter(Color color) {
super(color);
}

public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
JTextComponent c, View view) {
try {
Rectangle r = c.modelToView(offs0);
r.x = 0;
r.width =(c.getSize().width)+15500;
g.setColor(getColor());
g.fillRect(r.x, r.y, r.width, r.height);
return r;
} catch (BadLocationException e) {
return null;
}
}
}

}
[/code]

[code]
import javax.swing.text.StyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.Style;
import javax.swing.JTextPane;
import java.util.HashMap;
import java.awt.Color;

public class NewJavaUtil{

private JTextPane textPane;
private static HashMap keywords = null;
private static HashMap primitiveTypes = null;
private static Style styleWord,styleKeyword,styleNumber,styleOperator,styleBracket,styleString,styleComment,
stylePrimitive,styleLineComment;
private int currLen = 0;
private StringBuffer sb;
private int cur = 0;
private boolean isNumber = false;
private Style lastSelectedAttribute;

public NewJavaUtil(JTextPane textPane){
this.textPane = textPane;
setStyles();
keywords = JavaKeywords.getKeyWords();
primitiveTypes = JavaKeywords.getPrimitiveTypes();
}

private void setStyles(){
Color c = new Color(-16777012);
Color c1 = new Color(51,51,51);
styleWord = EditUtil.createStyle(textPane, textPane.getForeground(),"word");
styleKeyword = EditUtil.createStyle(textPane, Color.blue.darker().darker(),"keyword");
styleNumber = EditUtil.createStyle(textPane, Color.red,"number");
styleOperator = EditUtil.createStyle(textPane, Color.blue,"operator");
styleBracket = EditUtil.createStyle(textPane, Color.blue.darker(),"bracket");
styleString = EditUtil.createStyle(textPane, Color.gray,"string");
styleComment = EditUtil.createStyle(textPane, Color.cyan.darker(),"comment");
stylePrimitive = EditUtil.createStyle(textPane, Color.blue,"primitive");
styleLineComment = EditUtil.createStyle(textPane, Color.cyan.darker(),"lineComment");
StyleConstants.setBold(styleWord, false);
StyleConstants.setBold(styleNumber, true);
StyleConstants.setBold(styleOperator, true);
StyleConstants.setBold(styleString, false);
StyleConstants.setBold(styleComment, false);
StyleConstants.setBold(styleLineComment, false);
StyleConstants.setBold(styleKeyword, true);
StyleConstants.setBold(stylePrimitive, true);
}

public int scan(StyledDocument doc, char[] buffer, int start, int end){
EditUtil.setAttribute(doc,styleWord,start,end-start);
int i = start;
char c;
char tempC = 0;
lastSelectedAttribute = styleWord;
if(buffer.length == 0)
return 0;
try{
while(i cur = i;
c = buffer[i++];
currLen = 0;

switch(c){
case ' ': case '\n': case '\t':
break;
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':
case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':
case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':
case 'v':case 'w':case 'x':case 'y':case 'z':case 'S': //case keyword

if(i>1)tempC = buffer[i-2];
if(i>1 && ( tempC== ' ' || tempC == '\n' ||
tempC== '\t' || tempC == '(' ||
tempC == '{' || tempC == '[' ||
tempC=='\r' || tempC=='=')){
sb = new StringBuffer().append(c);
lastSelectedAttribute = styleWord;
for(;;){
c = buffer[i++];
if( c== ' ' || c=='\n'|| c =='\t'|| c=='}' ||
c==')' || c==']' || c=='\r' || c==';' ||
c=='(' || c=='[' || c=='{' || c == 0 || EditUtil.isOperator(c)){
i--;
break;
}
sb.append(c);
}
if(EditUtil.isKeyword(keywords,sb.toString()))
EditUtil.setAttribute(doc,styleKeyword,cur,sb.toString().length());
else if(sb.toString().startsWith("this."))
EditUtil.setAttribute(doc,styleKeyword,cur,4);
else if(EditUtil.isPrimitive(primitiveTypes,sb.toString()))
EditUtil.setAttribute(doc,stylePrimitive,cur,sb.toString().length());
}
break;
}
}
}catch(ArrayIndexOutOfBoundsException e){}
return i;
}

}
[/code]

[code]

import java.util.HashMap;
public class JavaKeywords{

private static HashMap keywords = new HashMap();
private static HashMap primitiveTypes = new HashMap();
private static boolean isKeywordSet = false;
private static boolean isPrimitiveTypeSet = false;

public static HashMap getKeyWords(){
if(!isKeywordSet)
setKeywords();
return keywords;
}

public static HashMap getPrimitiveTypes(){
if(!isPrimitiveTypeSet)
setPrimitiveTypes();
return primitiveTypes;
}

private static void setKeywords(){
keywords.put("new", "new");
keywords.put("null", "null");
keywords.put("public", "public");
keywords.put("private", "private");
keywords.put("protected", "protected");
keywords.put("static", "static");
keywords.put("final", "final");
keywords.put("finally", "finally");
keywords.put("void", "void");
keywords.put("switch", "switch");
keywords.put("case", "case");
keywords.put("default", "default");
keywords.put("class", "class");
keywords.put("interface", "interface");
keywords.put("abstract", "abstract");
keywords.put("implements", "implements");
keywords.put("extends", "extends");
keywords.put("import", "import");
keywords.put("try", "try");
keywords.put("catch", "catch");
keywords.put("throws", "throws");
keywords.put("throw", "throw");
keywords.put("break", "break");
keywords.put("for", "for");
keywords.put("while", "while");
keywords.put("do", "do");
keywords.put("return", "return");
keywords.put("if", "if");
keywords.put("else", "else");
keywords.put("instanceof", "instanceof");
keywords.put("package", "package");
keywords.put("transient", "transient");
keywords.put("synchronized", "synchronized");
keywords.put("this", "this");
keywords.put("super", "super");
isKeywordSet = true;
}

private static void setPrimitiveTypes(){
primitiveTypes.put("int", "int");
primitiveTypes.put("double", "double");
primitiveTypes.put("float", "float");
primitiveTypes.put("long", "long");
primitiveTypes.put("char", "char");
primitiveTypes.put("byte", "byte");
primitiveTypes.put("short", "short");
primitiveTypes.put("boolean", "boolean");
primitiveTypes.put("true", "true");
primitiveTypes.put("false", "false");
primitiveTypes.put("String", "String");
isPrimitiveTypeSet = true;
}

}

[/code]

[code]
import javax.swing.text.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;

public class EditUtil{

public static void setAttribute(StyledDocument doc, Style style, int start, int len){
if(len<=0)
return;
doc.setCharacterAttributes (start, len, style, false);
}

public static Style createStyle(JTextPane textPane, Color color, String name){
Style style = textPane.addStyle(name, null);
StyleConstants.setForeground(style, color);
return style;
}

public static boolean isOperator(char c){
boolean b = false;
switch(c){
case '+':
case '-':
case '*':
case '/':
case '&':
case '|':
case '^':
case '%':
case '!':
case '=':
case '>':
case '<':
b = true;
break;
default:
break;
}
return b;
}

public static boolean isPrimitive(HashMap primitiveTypes, String str){
if(primitiveTypes.get(str) == null)
return false;
return true;
}

public static boolean isKeyword(HashMap keywords, String str){
if(keywords.get(str) == null)
return false;
return true;
}

public static String getAttributeAt(StyledDocument doc, int index){
AttributeSet s = doc.getCharacterElement(index).getAttributes();
return (String)s.getAttribute(StyleConstants.NameAttribute);
}

public static int getEndOfLine(char[] chars, int index){
int len = chars.length;
for(int i = index; i if(chars[i] == '\n' || chars[i]=='\r')
return i;
return len;
}

public static int getStartOfLine(char[] chars, int index){
int len = chars.length;
for(int i = index; i>0 ; i--)
if(chars[i] == '\n' || chars[i]=='\r')
return i+1;
return 0;
}

}
[/code]

idk
Offline
Joined: 2005-01-12

Hi there,

I suggest again not to change styles from inside paintComponent.

[code]
public void insertUpdate(DocumentEvent e){
handleStyleUpdate(e);
}

public void removeUpdate(DocumentEvent e){
handleStyleUpdate(e);
}
protected void handleStyleUpdate(final DocumentEvent e) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
//you do not want this for
//every document change.
//you want to get the current
//row and apply attributes only
//to it
//char[] chars = text.array;
Segment txt = new Segment();
int rowStart, rowEnd;
try {
rowStart = Utilities.getRowStart(NewEditPane.this, e.getOffset());
rowEnd = Utilities.getRowEnd(NewEditPane.this, e.getOffset());
NewEditPane.this.getDocument().getText(rowStart,
rowEnd - rowStart, txt);
scanner.scan(doc, txt.toString().toCharArray(),
rowStart, rowEnd);

} catch (javax.swing.text.BadLocationException ignore) {
ignore.printStackTrace();
}
}
});
}
[/code]

With this code you do not need to override paintComponent.


Tracking document changes in the paintComponent is error prone.
What if there are more than one document change per paintComponent invocation?

You might want to run your application with profiler to find the bottlenecks.
(NetBeans 4.1 comes with the profiler)

Thanks,
Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

Thanks for the comments. I will try your suggestions and let you know.

Do you have any suggestions/comments on the line highlight problem?

Regards,
Sean

idk
Offline
Joined: 2005-01-12

I would not recommend to use a highlighter to highlight the current line.
HiglightPainter should paint only inside the [b]bounds[/b]. Your HiglightPainter obviously needs to break this contract.

Could you try something like:
[code]

public NewEditPane(){
....
setOpaque(false);
....
}
public void highlight(int start) {
try {
Rectangle r = modelToView(start);
r.x = 0;
r.width = getWidth();
if (! r.equals(rectToHighlight)) {
rectToHighlight = r;
System.out.println(rectToHighlight);
repaint(rectToHighlight);
}
} catch (Exception ignore) {
ignore.printStackTrace();
}
}

protected void paintComponent(Graphics g) {

g.setColor(Color.yellow);
g.fillRect(rectToHighlight.x,
rectToHighlight.y,
rectToHighlight.width,
rectToHighlight.height);
super.paintComponent(g);

}

[/code]

Also you do not want to call
[code]
painter() {
...
repaint()
[/code]

on every caret move. It is way to expensive.

Best,
Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

regarding the line highlight, I did what you suggested, but there is a little problem, when I move the cursor, now nothing happens, for example when I go to the next line, it paint a small part of the line yellow, but if I move the scroll bar horizontally, then it paints it all. And also since it's not opaque any more, the background remains to be gray. Here's the new NewEditPane code. (I removed the scanning for simplicity)

would you be able to explain why it's acting like that, I really appreciate the help since I'm almost out of solutions.

Regards,
Sean
[code]

import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;

public class NewEditPane extends JTextPane implements DocumentListener, CaretListener, MouseListener{

protected StyledDocument doc = null;
protected Segment text = new Segment();
protected int caret = 0;
protected int inputLen = 0;
protected NewJavaUtil scanner = null;
protected boolean insertHappened = false;
protected boolean removeHappend = false;
protected boolean fileRead = true;
protected Element root=null, root1 = null;
protected int line = 0, start=0;
protected Element lineElement = null;
Rectangle rectToHighlight = new Rectangle(0,0,0,0);

public NewEditPane(){
super(new DefaultStyledDocument());
setSize(1600,400);
setPreferredSize(new Dimension(1600,400));
Insets insets = new Insets(2, 11, 2, 11);
setMargin(insets);
addCaretListener(this);
addMouseListener(this);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
setOpaque(false);
setDoubleBuffered(true);
setForeground(Color.black);
setBackground(Color.white);
}

public void setFile(String filename){
scanner = new NewJavaUtil(this);
try{
read(new FileReader(filename), null);
}catch(IOException e){ return;}
scanAll();
invalidate();

}

public void read (Reader in, Object obj) throws IOException{
doc.removeDocumentListener(this);
super.read(in, obj);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
repaint();
}

public void caretUpdate(CaretEvent e){
painter(); // line highlight
}

public void insertUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = e.getLength();
insertHappened = true;
}

protected void handleStyleOnInsert(int index){
if(index <= 0)
return;
char[] chars = text.array;
AttributeSet currentStyle = getCharacterAttributes();
String str = (String)currentStyle.getAttribute(StyleConstants.NameAttribute);
int start = EditUtil.getStartOfLine(chars, index-1);
int end = EditUtil.getEndOfLine(chars,index+inputLen);
int i = scanner.scan(doc,chars,start,end+1);
end = EditUtil.getEndOfLine(chars,i);
scanner.scan(doc,chars,i+1,end+1);
}

public void removeUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = 0;
removeHappend = true;
}

public void changedUpdate(DocumentEvent e){}

private Rectangle highlight(){
root = this.getDocument().getDefaultRootElement();
line = root.getElementIndex(getCaretPosition());
lineElement = root.getElement(line);
start = lineElement.getStartOffset();
try{
Rectangle r = modelToView(start);
r.x = 0;
r.width = getWidth();
return r;
}catch(Exception e){
return new Rectangle(0,0,0,0);
}

}

protected void paintComponent(Graphics g){
Rectangle r = highlight();
g.setColor(Color.yellow);
g.fillRect(r.x,
r.y,
r.width,
r.height);

super.paintComponent(g);
}

/* scans the entire text and set the attributes. */
private void scanAll(){
try {
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e) {
return;
}
char[] chars = text.array;
scanner.scan(doc,chars,0,chars.length);
}
// line highlight
public void painter(){

}

public boolean getScrollableTracksViewportWidth(){
return false;
}

public void setSize(Dimension d){
if(d.width d.width = getParent().getSize().width;
super.setSize(d);
}

public void mousePressed(MouseEvent e) { painter();}
public void mouseClicked(MouseEvent e) { painter();}
public void mouseEntered(MouseEvent e) {painter();}
public void mouseExited(MouseEvent e) {painter();}
public void mouseReleased(MouseEvent e) {painter();}
public void mouseMoved(MouseEvent e) {painter();}
public void mouseDragged(MouseEvent e) {painter();}

public static void main(String args[]){
NewEditPane editPane = new NewEditPane();
editPane.setFile("C:\\EditFrame.java");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.getContentPane().add(new javax.swing.JScrollPane(editPane));
frame.setVisible(true);
}

}
[/code]

idk
Offline
Joined: 2005-01-12

Hey,

>regarding the line highlight, I did what you suggested,

Could you try the suggestion literaly?
Remove repaint from painter() and use the suggested highlight(int start) method ?

Also you do not need to call painter() from the mouse listeners.

> And also since it's not opaque any more, the background remains to be gray

You can paint the background yourself in the paintComponent method.

Cheers,
Igor

seane
Offline
Joined: 2005-06-27

Hey Igor, you're the best.

I tried again and it works and I'm releived, I thought I had
tried it litterally last night, but I must had done something wrong last night.

I get the line highlight correctly, I removed the call to the painter from mouse listener but another problem came up.
Now if I click with the mouse on another part of the text, the previous higlight styas there and a new highlight appears at the location of the click. But as soon as I scroll horizontally it goes back to normal, meaning all the highlights go away but the one that is at the location of the caret. When I put a call to the painter() in mousePressed the problem goes away. Is there any explanation for this behaviour?

Another question, is there going to be a performance drag
because of the painting activities in the paintComponent()?
(since I first paint the background white, then paint yellow and then call the super method. What do you suggest that I could do to maximize the performance with respect to the new code?
Thank you again,
Sean

[code]
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;

public class NewEditPane extends JTextPane implements DocumentListener, CaretListener, MouseListener{

protected StyledDocument doc = null;
protected Segment text = new Segment();
protected int caret = 0;
protected int inputLen = 0;
protected NewJavaUtil scanner = null;
protected boolean insertHappened = false;
protected boolean removeHappend = false;
protected boolean fileRead = true;
protected Element root=null, root1 = null;
protected int line = 0, start=0;
protected Element lineElement = null;
Rectangle rectToHighlight = new Rectangle(0,0,0,0);

public NewEditPane(){
super(new DefaultStyledDocument());
setSize(1600,400);
setPreferredSize(new Dimension(1600,400));
Insets insets = new Insets(2, 11, 2, 11);
setMargin(insets);
addCaretListener(this);
addMouseListener(this);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
setOpaque(false);
setDoubleBuffered(true);
setForeground(Color.black);
setBackground(Color.white);
}

public void setFile(String filename){
scanner = new NewJavaUtil(this);
try{
read(new FileReader(filename), null);
}catch(IOException e){ return;}
scanAll();
invalidate();

}

public void read (Reader in, Object obj) throws IOException{
doc.removeDocumentListener(this);
super.read(in, obj);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
repaint();
}

public void caretUpdate(CaretEvent e){
painter(); // line highlight
}

public void insertUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = e.getLength();
insertHappened = true;
}

protected void handleStyleOnInsert(int index){
if(index <= 0)
return;
char[] chars = text.array;
AttributeSet currentStyle = getCharacterAttributes();
String str = (String)currentStyle.getAttribute(StyleConstants.NameAttribute);
int start = EditUtil.getStartOfLine(chars, index-1);
int end = EditUtil.getEndOfLine(chars,index+inputLen);
int i = scanner.scan(doc,chars,start,end+1);
end = EditUtil.getEndOfLine(chars,i);
scanner.scan(doc,chars,i+1,end+1);
}

public void removeUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = 0;
removeHappend = true;
}

public void changedUpdate(DocumentEvent e){}

public void highlight(int start) {
try {
Rectangle r = modelToView(start);
r.x = 0;
r.width = getWidth();
if (! r.equals(rectToHighlight)) {
rectToHighlight = r;
System.out.println("higlight is called .... ");
repaint(rectToHighlight);
}
} catch (Exception ignore) {
ignore.printStackTrace();
}
}

protected void paintComponent(Graphics g){
g.setColor(Color.white);
Rectangle r = getVisibleRect();
System.out.println(r);
g.fillRect(r.x,r.y,r.width,r.height);
g.setColor(Color.yellow);
g.fillRect(rectToHighlight.x,
rectToHighlight.y,
rectToHighlight.width,
rectToHighlight.height);

super.paintComponent(g);
}

/* scans the entire text and set the attributes. */
private void scanAll(){
try {
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e) {
return;
}
char[] chars = text.array;
scanner.scan(doc,chars,0,chars.length);
}
// line highlight
public void painter(){
root = this.getDocument().getDefaultRootElement();
line = root.getElementIndex(getCaretPosition());
lineElement = root.getElement(line);
start = lineElement.getStartOffset();
highlight(start);
}

public boolean getScrollableTracksViewportWidth(){
return false;
}

public void setSize(Dimension d){
if(d.width d.width = getParent().getSize().width;
super.setSize(d);
}

public void mousePressed(MouseEvent e) {painter();}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {}

public static void main(String args[]){
NewEditPane editPane = new NewEditPane();
editPane.setFile("NewEditPane.java");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.getContentPane().add(new javax.swing.JScrollPane(editPane));
frame.setVisible(true);
}

}
[/code]

idk
Offline
Joined: 2005-01-12

Hi,

Could you tell me what is your project about?

Thanks,
Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

The editor is a part of a bigger project. The editor is targetted for mid size projects, files of about 1000 to 3000 lines maximum. It's capable of doing all the things an editor shouuld do, like search, replace, save, copy, paste, syntax highlight (including multi-line comments), etc. I was concerned about the worst case senarios like 20000 lines as well which I have seen in even the top companies in the software industry. That's a high level rundown of the project.

Well if you have any comments/suggestions that I should keep in mind in general, I would appreciate that. Thanks for resolving the line highlight problem, I think it works perfectly after I just call the painter in the mouseReleased.

Regards,
Sean

leouser
Offline
Joined: 2005-12-12

you dont mind me asking, but how is your colorization being applied?

seane
Offline
Joined: 2005-06-27

when the first time the file is loaded, I just scan through the document and based on the settings for keywords,etc. I call the setAttribute methods to do the coloring. During the editing the document listener will tell where the editing is happening and the modification to the styles are done on those particular regions.

that actually doesn't take long even for a huge file (20000 lines) it takes about a few seconds. But the actual problem is in typing in it. When you type it's like there's a short period line a second or less (but notable) for the letter to be typed on the textPane. And that I don't understand why? Is it because of the paiting?

leouser
Offline
Joined: 2005-12-12

ok, another question based off of your response: Are you sure you are not reapplying all those attributes per letter typed?

----
another thought: it may be good to start timing your operations. Either via tool, or selectively adding time catching code. Then you can get some visibility into what is 'slow'.

seane
Offline
Joined: 2005-06-27

Hi leouser,

yes I'm sure I'm not reapplying, the scan during the editing is only scaning at most the current line or only one word, and in case of multi line comments a little mroe than than sometimes. I timed the operation, the only thing that it takes time is the scanning of long long multi line comments, to get the begining and/or end of it if necessary, but even that is not notable to the user, user will feel a bit of sluggishness but it's okay and once the user types outside the long comment, things go back to normal. I was thinking maybe it's the document listener, could it be the cause, for a large document, wouuld it take a lot more for the document listener to monitor the entire document?

leouser
Offline
Joined: 2005-12-12

hmmm... maybe it would be good to start from a basic position for everyone:

What is the performance of your large file loaded into a base JTextPane? --one that doesn't have anything added to, nor is it modified. If the basic piece is slow, then we need to look at figuring out what part of that piece is slow and get it up to speed. This is somewhat of interest to me since Im using the widget as well, but it will be highly unusual in my application for a file of your size to be loaded into the widget.

seane
Offline
Joined: 2005-06-27

Hi leouser,

okay if you mean on a plain JTextPane, I created a simple JTextPane, put it in a JScrollPane and a JFrame, it took about 9 seconds to load the file of about 18000 lines. After the loading the speed of typing was normal, maybe just a little slower than usual but you could ignore it if you aren't that picky.

Then on my own software (with scanning and everything) it took about 12 seconds to load the same file(1.8 Giga Hz Celeron, 256 Ram). Which again is acceptable for such a large file, however the speed of typing is slow. When I remove the document listener from the text pane, it becomes a little better, still you can feel the sluggishness however. I have alnog with other things a line highlight as well which also has a problem of showing a white gap on the location of the cursor. This line higligt is only gets called from the paintComponent of the text pane. all the scanning gets triggered from within the paintComponent as well. So the paintComponent has the duty of both scanning and line highlight. it looks like this:

void paintComponent(Graphics g){
super.paintComponent(g);
if(textChanged/entered/removed)
scan();
lineHigligt();
}

Sean

leouser
Offline
Joined: 2005-12-12

what does the scan do? Apply the attributes?

You may be creating extra work by this approach. If Im reading your code right, you paint and then scan. If your scan is adding attributes you may be setting yourself up for another paint, from within your paint. This may be why your experiencing extra slowness in comparison to a vanilla TextPane. Prune the scanning and highlighting and see what performance changes to.

Note: Im just assuming adding attributes will lead to repainting. It just seems to make sense to me. :)

seane
Offline
Joined: 2005-06-27

yes I apply attributes to the text, but applying attributes does not trigger another paint, but hightlight does. Sorry my mistake, the highlight doesn't get triggered from the paintComponent, it gets triggered by the caretListener.

applying attributes doesn't trigger the paint, I have tested this and made sure of it, I initially put the line highlight in paintComponent but it made it extermely slow until I realized that the line highlight triggers the pain and paint triggers the line highlight in and endless loop. But now the paint itself only gets triggered when there is a move, like typing. I'm just not sure how the paint works. It could be painting the entire pane, how can I make sure that it only paints the visible area?

seane
Offline
Joined: 2005-06-27

So anybody can tell me why a JTextPane becomes slow once the document is too large?

And why when a tab is removed from a JTabbedPane containing a large amount of data, the tabbed pane does not release the resources(such as memory)?

Any help is appreciated.

Sean

idk
Offline
Joined: 2005-01-12

Hey,

Would you mind posting a small runable test case to demonstrate the problem?

> And why when a tab is removed from a JTabbedPane containing a large amount of data, the tabbed pane does not release the resources(such as memory)?

You might want to try profilers to see what is holding the document.

> yes I apply attributes to the text, but applying attributes does not trigger another paint, but highlight does.

Changing attributes should trigger repaint. Changing highlights triggers the repaint too. Guess these two requests are coalesced by the RepaintManager

Triggering repaint inside the paint might not be the best solution since it'll paint twice.

Could not you listen for the document changes instead?

Thanks,
Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

I will put something to gether tomorrow, it's a big application and I have to put some pieces together.

I already listen to changes in the document, and the rescan only happens when a document changes. It's strange that you say applying attribues trigger the repaint, becuase in my edit pane it doesn't. since I didn't use explicity any synchronization techniques, I put the restyling in the paint component so it always stays in synch with the repaint. And I have put some print statements in the paintComponent method and it does not get triggered after the restyle. Though I have to double check again now that you mentioned it.

Thanks,
Sean

seane
Offline
Joined: 2005-06-27

Hi Igor,

my apology for the 3 day delay. This is the code, I had to cut a lot of stuff to make the code short, like handling of comments, Strings, etc. but keywords are still highlighted and also line highlight is still there. You can open a file of about 18000 lines and you will see the slowness, you can compare the speed with a file of about 100 lines.

Also as you will notice there is also a problem with the line highlight which I can't figure out, when you scroll to the right, the lingh highlight does not move and does not expand with the expansion of the view. I really appreciate any insight and help.

here's the code, it's 3 files. The main method is in NewEditPane.java

import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;

public class NewEditPane extends JTextPane implements DocumentListener, CaretListener, MouseListener{

protected StyledDocument doc = null;
protected Segment text = new Segment();
protected int caret = 0;
protected int inputLen = 0;
protected NewJavaUtil scanner = null;
protected boolean insertHappened = false;
protected boolean removeHappend = false;
protected boolean fileRead = true;
protected Element root=null, root1 = null;
protected int line = 0, start=0;
protected Element lineElement = null;
private Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.yellow);

public NewEditPane(){
super(new DefaultStyledDocument());
setSize(1600,400);
setPreferredSize(new Dimension(1600,400));
Insets insets = new Insets(2, 11, 2, 11);
setMargin(insets);
addCaretListener(this);
addMouseListener(this);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
setOpaque(true);
setDoubleBuffered(true);
setForeground(Color.black);
setBackground(Color.white);
}

public void setFile(String filename){
scanner = new NewJavaUtil(this);
try{
read(new FileReader(filename), null);
}catch(IOException e){ return;}
scanAll();
invalidate();
highlight(0);
}

public void read (Reader in, Object obj) throws IOException{
doc.removeDocumentListener(this);
super.read(in, obj);
doc = (StyledDocument) getDocument();
doc.addDocumentListener(this);
repaint();
}

public void caretUpdate(CaretEvent e){
painter(); // line highlight
}

public void insertUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = e.getLength();
insertHappened = true;
}

protected void handleStyleOnInsert(int index){
if(index <= 0)
return;
char[] chars = text.array;
AttributeSet currentStyle = getCharacterAttributes();
String str = (String)currentStyle.getAttribute(StyleConstants.NameAttribute);
int start = EditUtil.getStartOfLine(chars, index-1);
int end = EditUtil.getEndOfLine(chars,index+inputLen);
int i = scanner.scan(doc,chars,start,end+1);
end = EditUtil.getEndOfLine(chars,i);
scanner.scan(doc,chars,i+1,end+1);
}

public void removeUpdate(DocumentEvent e){
caret = e.getOffset();
inputLen = 0;
removeHappend = true;
}

public void changedUpdate(DocumentEvent e){}

public void repaint(){
Rectangle r = this.getVisibleRect();
repaint(1, r.x, r.y, r.width, r.height);
}

protected void paintComponent(Graphics g){
super.paintComponent(g);
try{
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e1){
return;
}
if(insertHappened || removeHappend){
handleStyleOnInsert(caret);
insertHappened = false;
removeHappend = false;
}
}

/* scans the entire text and set the attributes. */
private void scanAll(){
try {
doc.getText(0, doc.getLength(), text);
}
catch(BadLocationException e) {
return;
}
char[] chars = text.array;
scanner.scan(doc,chars,0,chars.length);
}
// line highlight
public void painter(){
root = this.getDocument().getDefaultRootElement();
line = root.getElementIndex(getCaretPosition());
lineElement = root.getElement(line);
start = lineElement.getStartOffset();
highlight(start);
repaint();
}

public boolean getScrollableTracksViewportWidth(){
return false;
}

public void setSize(Dimension d){
if(d.width d.width = getParent().getSize().width;
super.setSize(d);
}

public void mousePressed(MouseEvent e) { painter();}
public void mouseClicked(MouseEvent e) { painter();}
public void mouseEntered(MouseEvent e) {painter();}
public void mouseExited(MouseEvent e) {painter();}
public void mouseReleased(MouseEvent e) {painter();}
public void mouseMoved(MouseEvent e) {painter();}
public void mouseDragged(MouseEvent e) {painter();}

public static void main(String args[]){
NewEditPane editPane = new NewEditPane();
editPane.setFile("C:\\EditFrame.java");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.getContentPane().add(new javax.swing.JScrollPane(editPane));
frame.setVisible(true);
}

public void highlight(int start) {
// First remove all old highlights
removeHighlights();
try {
Highlighter highlighter = getHighlighter();
// Create highlighter using private painter and apply around pattern
highlighter.addHighlight(start, start+1, myHighlightPainter);
} catch (BadLocationException e) {

}
}

public void removeHighlights() {
Highlighter hilite = getHighlighter();
Highlighter.Highlight[] hilites = hilite.getHighlights();
for (int i=0; i if (hilites[i].getPainter() instanceof MyHighlightPainter) {
hilite.removeHighlight(hilites[i]);
}
}
}

protected class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {
public MyHighlightPainter(Color color) {
super(color);
}

public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
JTextComponent c, View view) {
try {
Rectangle r = c.modelToView(offs0);
r.x = 0;
r.width =(c.getSize().width)+15500;
g.setColor(getColor());
g.fillRect(r.x, r.y, r.width, r.height);
return r;
} catch (BadLocationException e) {
return null;
}
}
}

}

/**********
Class NewJavaUtil.java
it does the scanning.
*********/

import javax.swing.text.StyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.Style;
import javax.swing.JTextPane;
import java.util.HashMap;
import java.awt.Color;

public class NewJavaUtil{

private JTextPane textPane;
private static HashMap keywords = null;
private static HashMap primitiveTypes = null;
private static Style styleWord,styleKeyword,styleNumber,styleOperator,styleBracket,styleString,styleComment,
stylePrimitive,styleLineComment;
private int currLen = 0;
private StringBuffer sb;
private int cur = 0;
private boolean isNumber = false;
private Style lastSelectedAttribute;

public NewJavaUtil(JTextPane textPane){
this.textPane = textPane;
setStyles();
keywords = JavaKeywords.getKeyWords();
primitiveTypes = JavaKeywords.getPrimitiveTypes();
}

private void setStyles(){
Color c = new Color(-16777012);
Color c1 = new Color(51,51,51);
styleWord = EditUtil.createStyle(textPane, textPane.getForeground(),"word");
styleKeyword = EditUtil.createStyle(textPane, Color.blue.darker().darker(),"keyword");
styleNumber = EditUtil.createStyle(textPane, Color.red,"number");
styleOperator = EditUtil.createStyle(textPane, Color.blue,"operator");
styleBracket = EditUtil.createStyle(textPane, Color.blue.darker(),"bracket");
styleString = EditUtil.createStyle(textPane, Color.gray,"string");
styleComment = EditUtil.createStyle(textPane, Color.cyan.darker(),"comment");
stylePrimitive = EditUtil.createStyle(textPane, Color.blue,"primitive");
styleLineComment = EditUtil.createStyle(textPane, Color.cyan.darker(),"lineComment");
StyleConstants.setBold(styleWord, false);
StyleConstants.setBold(styleNumber, true);
StyleConstants.setBold(styleOperator, true);
StyleConstants.setBold(styleString, false);
StyleConstants.setBold(styleComment, false);
StyleConstants.setBold(styleLineComment, false);
StyleConstants.setBold(styleKeyword, true);
StyleConstants.setBold(stylePrimitive, true);
}

public int scan(StyledDocument doc, char[] buffer, int start, int end){
EditUtil.setAttribute(doc,styleWord,start,end-start);
int i = start;
char c;
char tempC = 0;
lastSelectedAttribute = styleWord;
if(buffer.length == 0)
return 0;
try{
while(i cur = i;
c = buffer[i++];
currLen = 0;

switch(c){
case ' ': case '\n': case '\t':
break;
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':
case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':
case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':
case 'v':case 'w':case 'x':case 'y':case 'z':case 'S': //case keyword

if(i>1)tempC = buffer[i-2];
if(i>1 && ( tempC== ' ' || tempC == '\n' ||
tempC== '\t' || tempC == '(' ||
tempC == '{' || tempC == '[' ||
tempC=='\r' || tempC=='=')){
sb = new StringBuffer().append(c);
lastSelectedAttribute = styleWord;
for(;;){
c = buffer[i++];
if( c== ' ' || c=='\n'|| c =='\t'|| c=='}' ||
c==')' || c==']' || c=='\r' || c==';' ||
c=='(' || c=='[' || c=='{' || c == 0 || EditUtil.isOperator(c)){
i--;
break;
}
sb.append(c);
}
if(EditUtil.isKeyword(keywords,sb.toString()))
EditUtil.setAttribute(doc,styleKeyword,cur,sb.toString().length());
else if(sb.toString().startsWith("this."))
EditUtil.setAttribute(doc,styleKeyword,cur,4);
else if(EditUtil.isPrimitive(primitiveTypes,sb.toString()))
EditUtil.setAttribute(doc,stylePrimitive,cur,sb.toString().length());
}
break;
}
}
}catch(ArrayIndexOutOfBoundsException e){}
return i;
}

}

/*************
Class JavaKeywords.java
*************/

import java.util.HashMap;
public class JavaKeywords{

private static HashMap keywords = new HashMap();
private static HashMap primitiveTypes = new HashMap();
private static boolean isKeywordSet = false;
private static boolean isPrimitiveTypeSet = false;

public static HashMap getKeyWords(){
if(!isKeywordSet)
setKeywords();
return keywords;
}

public static HashMap getPrimitiveTypes(){
if(!isPrimitiveTypeSet)
setPrimitiveTypes();
return primitiveTypes;
}

private static void setKeywords(){
keywords.put("new", "new");
keywords.put("null", "null");
keywords.put("public", "public");
keywords.put("private", "private");
keywords.put("protected", "protected");
keywords.put("static", "static");
keywords.put("final", "final");
keywords.put("finally", "finally");
keywords.put("void", "void");
keywords.put("switch", "switch");
keywords.put("case", "case");
keywords.put("default", "default");
keywords.put("class", "class");
keywords.put("interface", "interface");
keywords.put("abstract", "abstract");
keywords.put("implements", "implements");
keywords.put("extends", "extends");
keywords.put("import", "import");
keywords.put("try", "try");
keywords.put("catch", "catch");
keywords.put("throws", "throws");
keywords.put("throw", "throw");
keywords.put("break", "break");
keywords.put("for", "for");
keywords.put("while", "while");
keywords.put("do", "do");
keywords.put("return", "return");
keywords.put("if", "if");
keywords.put("else", "else");
keywords.put("instanceof", "instanceof");
keywords.put("package", "package");
keywords.put("transient", "transient");
keywords.put("synchronized", "synchronized");
keywords.put("this", "this");
keywords.put("super", "super");
isKeywordSet = true;
}

private static void setPrimitiveTypes(){
primitiveTypes.put("int", "int");
primitiveTypes.put("double", "double");
primitiveTypes.put("float", "float");
primitiveTypes.put("long", "long");
primitiveTypes.put("char", "char");
primitiveTypes.put("byte", "byte");
primitiveTypes.put("short", "short");
primitiveTypes.put("boolean", "boolean");
primitiveTypes.put("true", "true");
primitiveTypes.put("false", "false");
primitiveTypes.put("String", "String");
isPrimitiveTypeSet = true;
}

}

Sorry that it's a long posting, I tried to trim it down as much as I couuld to leave only necessary code.

Thanks,
Sean

seane
Offline
Joined: 2005-06-27

I forget the utility class:

/****************************/
import javax.swing.text.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;

public class EditUtil{

public static void setAttribute(StyledDocument doc, Style style, int start, int len){
if(len<=0)
return;
doc.setCharacterAttributes (start, len, style, false);
}

public static Style createStyle(JTextPane textPane, Color color, String name){
Style style = textPane.addStyle(name, null);
StyleConstants.setForeground(style, color);
return style;
}

public static boolean isOperator(char c){
boolean b = false;
switch(c){
case '+':
case '-':
case '*':
case '/':
case '&':
case '|':
case '^':
case '%':
case '!':
case '=':
case '>':
case '<':
b = true;
break;
default:
break;
}
return b;
}

public static boolean isPrimitive(HashMap primitiveTypes, String str){
if(primitiveTypes.get(str) == null)
return false;
return true;
}

public static boolean isKeyword(HashMap keywords, String str){
if(keywords.get(str) == null)
return false;
return true;
}

public static String getAttributeAt(StyledDocument doc, int index){
AttributeSet s = doc.getCharacterElement(index).getAttributes();
return (String)s.getAttribute(StyleConstants.NameAttribute);
}

public static int getEndOfLine(char[] chars, int index){
int len = chars.length;
for(int i = index; i if(chars[i] == '\n' || chars[i]=='\r')
return i;
return len;
}

public static int getStartOfLine(char[] chars, int index){
int len = chars.length;
for(int i = index; i>0 ; i--)
if(chars[i] == '\n' || chars[i]=='\r')
return i+1;
return 0;
}

}

idk
Offline
Joined: 2005-01-12

Hi,

Guess you can look at netbeans sources
http://editor.netbeans.org/

Netbeans handles big sources files easily.

Thanks,
Igor

seane
Offline
Joined: 2005-06-27

Hi, thanks for the suggestion.

I actually downloaded NetBeans and I found the look and feel very nice, alot better than Oracle JDeveloper, but it's slow (even slower than Oracle JDeveloper) on my laptop which has a 256 RAM, it's very slow and I stopped using it because it kept freezing and I got tired of it.

I'm sure the slowness of my software is not due to memory, I know it takes a huge amount of memory but the slowness of typing is not due to that, becaue other tabs have a normal behaviour and if the problem was due to memory, then it shoudl be global across all the text panes, so I assume the problem is somehow related to the size of the text pane whith the large amount of data. Could it be the painting? any ideas?

idk
Offline
Joined: 2005-01-12

Hi,

> kept freezing and I got tired of it.

Sorry to hear that. Was it the "latest and greatest" Netbeans4.1 ?

There is FAQ you might be interested in :
http://www.netbeans.org/kb/faqs/performance.html

-Igor

seane
Offline
Joined: 2005-06-27

Hi Igor,

it was the latest I downloaded a couple of weeks ago, the one with JDK 1.5 (it was the latest, right?)