views:

679

answers:

2

I'm viewing HTML in an SWT Browser widget. I am appending logging messages to the end of the content and would like to keep the bottom visible all the time. Currently, whenever I append text to the content, I first set the new text:

browser.setText(content);

And then I scroll down the Browser widget via JavaScript:

browser.execute("window.scrollTo(0,100000);");

The problem with this is that when I set the text, the widget switches to the top again before scrolling down, so when I append lots of messages quickly, the browser widget is showing the top part most of the time, occasionally flickering when switching to the bottom. This makes it impossible to follow what is being logged at the bottom.

I am aware that I could use a tree viewer and get all the convenience of the Eclipse platform, but there is a Swing version of the app too and both should use the same HTML with CSS presentation.

Ideally I'd like to avoid embedding a Swing component, but if there is one that would allow this, I'd be happy to hear about it. I have tried it with a JEditorPane inside a JScrollPane, appending to the content via the editor kit's read method:

editorPane.getEditorKit().read(/*...*/);

And then scrolling down like this:

editorPane.setCaretPosition(editorPane.getDocument().getLength());

This works very smoothly for the standalone Swing app, but embedded in Eclipse it flickers and does not keep up with fast updates of the HTML content.

Right now the only way I can make this work smoothly inside Eclipse is prepending to the Browser widget's content instead of appending, but I'd really prefer adding new messages at the bottom, not at the top.

+1  A: 

Rewriting the whole HTML content every time seems unnecessarily busy-work, and there may not be a way to prevent some browsers from scrolling to the top each time you redraw the entire page. Especially if you allow the logs you show to get very long, this will get slower and slower as the log gets longer.

A better solution might be to use JavaScript to append to the page. You're already using

browser.execute()

How about something like this (assuming "itemID" is the ID of the DIV containing the content):

String newContent = newContent.replaceAll("\n", "<br>").replaceAll("'", "\\\\'");
browser.execute("document.getElementById(\"itemID\").innerHTML += '"
                newContent + "'");

You have to do the replaceAll() and you may need a couple more transformations, depending on your log content. I've noticed that browser.execute() doesn't like it if the script contains newlines, for example, and single quotes in your string needed to be quoted as I show above.

Eddie
Thank you, this is much better, even if I set the entire text each time.
Fabian Steeg
Just wanted add that a downside of this is that it does not seem to work on the Mac with a default Browser widget. A workaround is to force Mozilla usage in the Browser widget with the SWT.MOZILLA option, which requires an installed XulRunner (see http://www.eclipse.org/swt/faq.php#howusemozilla).
Fabian Steeg
@Fabian Steeg: You may want to log an SWT bug report about this.
Eddie
+1  A: 

I would have just added this as a comment, but it wouldn't let me (not enough reputation). You can ship XUL in a nonstandard location on the mac, by setting a system property.

System.setProperty("org.eclipse.swt.browser.XULRunnerPath", "/fubar/xul/Versions/1.9.0.7/");

Thanks, this is good to know for the future. In this particular case I ended up not using the browser widget but a tree viewer (for other reasons).
Fabian Steeg