Sharing document between JEditorPane and JTextArea
Hi all.
I'm trying to display an HTML string as both formatted text and a 'source code' view. To do this, I'm trying to use JEditorPane (formatted view) and JTextArea (source code view).
If I set the contents of the JTextPane using .setText(), the fields display as I want them to, but (obviously) typing in one field doesn't affect the document in the other.
If I set the contents of the JTextPane using .setDocument() (with the JEditorPane's .getDocument() as the argument), I get the editor effects I want, but the JTextPane no longer shows the HTML tags (or newlines, for that matter).
I want:
1. Changes in one field are reflected in the other.
2. One field shows formatted text, the other shows markup.
Any clues how I can get this to work? Thanks very much.
Source:
import javax.swing.*;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
publicclass SimpleTestextends JFrame{
publicstaticvoid main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
publicvoid run(){
new SimpleTest("<html>\n<h1>Some text</h1>\n<h2>More text</h2>\nAnd more text\n</html>");
}
});
}
public SimpleTest(String html){
setDefaultCloseOperation(EXIT_ON_CLOSE);
JEditorPane txtWys =new JEditorPane();
txtWys.setEditorKit(new HTMLEditorKit());
txtWys.setPreferredSize(new Dimension(250, 300));
txtWys.setText(html);
JTextArea txtSrc =new JTextArea();
txtSrc.setPreferredSize(new Dimension(250, 300));
// SOLUTION A
// if I use txtSrc.setText(), the html renders correctly as source, but the models are not in synch
//txtSrc.setText(html);
// SOLUTION B
// if I use txtSrc.setDocument(), the models are in synch, but the html renders without html markup
// (and without newlines)
txtSrc.setDocument(txtWys.getDocument());
Container content = getContentPane();
JSplitPane sp =new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,new JScrollPane(txtWys),new JScrollPane(txtSrc));
sp.setOneTouchExpandable(true);
content.add(sp);
pack();
setVisible(true);
}
}
[3527 byte] By [
mbmerrilla] at [2007-11-27 8:35:21]

# 2
> Just off the top of my head: Shouldn't you have two
> different Documents? Shouldn't the one be a clone()
> of the other, and be connected via a listener?
Well, it makes sense to me that you'd want a single document (model) and two fields (views).
You could certainly do as you suggest, and update the other document as one is changed by the user. That is, in fact, the route I originally pursued. However, when I got around to implementing undo functionality, I realized that I was going to get wacky results (in my actual implementation, I have a JTabbedPane instead of a JSplitPane - when the undo happens, the field that the action occurred in isn't guaranteed to be visible).
As I was pondering that problem, I discovered that JTextArea has a .setDocument() method... and this solution just seems so much more elegant.... if it would only work. I have no idea why the JTextArea stops displaying HTML tags (and newlines) in my example.
Thank you for responding.
# 4
> Just guessing, but I think the Document only stores
> the text. Then attributes are used to store the tag
> information. So the view that paint the JTextArea
> knows nothing about attributes, since they aren't
> supported so you simply see the text displayed in a
> single line. I would guess the "\n" is converted to a
> < br > tag.
I'd buy that if it always displayed the string the same way. Instead, the method I use to set the contents (.setText() vs .setDocument()) seems to affect how the string gets handled, as in my example.
# 5
> txtSrc.setText(html);
When you use the above then the text area just displays the "hmtl" as a simple String. No surprise there.
> txtWys.setEditorKit(new HTMLEditorKit());
> txtWys.setText(html);
When you use theHTMLEditorKit and then use the setText(...) method the "html" is parsed by the editor kit. The "text" is added to the document as text and the "tags" are added to the document as attributes.
> txtSrc.setDocument(txtWys.getDocument());
Now the Document is added to the text area. The "PlainView" or "WrappedPlainView" used by the text area doesn't know about or care about attributes, so therefore only the text gets painted, not the attributes.
So I suspect that to fix your problem you need to write a new View for the text area. You need a view that treats the attributes as text. I don't know how to do this so I can't be any more help. Maybe if you search the forum you will find examples of extending WrappedPlainView or PlainView.
# 6
> So I suspect that to fix your problem you need to
> write a new View for the text area. You need a view
> that treats the attributes as text. I don't know how
> to do this so I can't be any more help. Maybe if you
> search the forum you will find examples of extending
> WrappedPlainView or PlainView.
Thank you for your assistance, camickr.
I've found a couple of examples on the web of people extending PlainView to create XML-centric editors. The ones I found, should anyone care, are at:
http://www.boplicity.nl/confluence/display/Java/Xml+syntax+highlighting+in+Swing+JTextPane
and
http://www.edankert.com/bounce/index.html
However, they seem dependent on how the text field (whether JEditorPane or another type) gets populated with the data. For example, Bounce seems to work as intended if you load the field via the read() method, but not if you use setDocument() (with the document being shared, as in my original example). Debugging indicates that the text returned by doc.getText() (used in the view's drawUnselectedText() and drawSelectedText()) differs depending on how the model was created; in one case it contains the tags, in another it doesn't.
Looking at PlainView, it seems like I'd need to override drawElement() in order to establish what the tags are for a particular bit of text... except that drawElement() is private. Even if I were able to override it, it seems that not every HTML element causes drawElement() to be called (for example, <html> didn't show up in my debugging). So even that isn't the complete story.
I admit I'm stuck on the 'different ways of initializing the document have different results' problem (if indeed it is a problem, and I'm not overlooking something glaringly obvious). Anyone have any further suggestions?
Thanks.