I am making a java chat application. I have already made the basics, & its working fine. Now I wanted to add the ability to change fonts & insert smilies. I also wanted to add a little Time stamp next to each message.
For the time stamp, its obvious that we need to use tables for nice alignments. But couldn't find an easy solution to have them. After a bit of googleing,
CODE: I created these general variables:
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument HTMLdoc = new HTMLDocument();
jTextPane1.setEditorKit(kit);
jTextPane1.setDocument(HTMLdoc);
In a JButton, I have the following code to insert text/chat:
kit.insertHTML(HTMLdoc, HTMLdoc.getLength(), "<tr>"
+ "<td width=\"50\" valign=\"top\">NAME:</td>"
+ "<td width=\"250\"><font size=\"3\" face=\"Monospaced\">" + addSmiles(JOptionPane.showInputDialog(null)) + "</font></td>"
+ "<td width=\"100\" valign=\"top\"><font size=\"1\">"
+ new SimpleDateFormat("hh:mm a").format(Calendar.getInstance().getTime()).toString() + "</font></td>"
+ "</tr>", 0, 0, null);
The addSmiles method just goes through each word, & replaces a ':)' with the img tag.
To save/reload the conversation, I used this basic code:
kit.read(new FileReader("asd.htm"), HTMLdoc, 0);
kit.write(new FileWriter("asd.htm"), HTMLdoc, 0, HTMLdoc.getLength());
It writes fine, but read produces an error.
java.lang.RuntimeException: Must insert new content into body element
I feel that I have used the insertHTML method wrongly. Can anybody give me a nice link which shows its usage? Especially the last three arguments (pop & pushDepth, insertTag) with examples. Oracle docs, don't explain it to my satisfaction. :/
I hope I explained my problem decently & not too lengthily! :D Looking forward to your answers.
---------EDIT :---------
I changed my code slightly:
The initializations:
HTMLEditorKit kit = new HTMLEditorKit();
jTextPane1.setEditorKit(kit);
HTMLDocument HTMLdoc = (HTMLDocument) jTextPane1.getDocument();
HTMLdoc.putProperty("IgnoreCharsetDirective", true);
I insert the initial lines into the doc, with appropriate try-catch:
kit.insertHTML(HTMLdoc, 0, "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">", 0, 0, null);
kit.insertHTML(HTMLdoc, HTMLdoc.getLength(), "<table id=\"TBL\"></table>", 0, 0, null);
Any chat, I use the same HTML String as before, just changed the method used to insert:
HTMLdoc.insertBeforeEnd(HTMLdoc.getElement("TBL"), "<tr>"
+ "<td width=\"50\" valign=\"top\">NAME:</td>"
+ "<td width=\"250\"><font size=\"3\" face=\"Monospaced\">" + addSmiles(JOptionPane.showInputDialog(null)) + "</font></td>"
+ "<td width=\"100\" valign=\"top\">" + new SimpleDateFormat("hh:mm a").format(Calendar.getInstance().getTime()).toString() + "</td>"
+ "</tr>");
Finally, to save a chat:
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("asd"), "UTF-8");
kit.write(out, HTMLdoc, 0, HTMLdoc.getLength());
out.close();
Until this point, everything works beautifully. When I open file "asd", it shows the HTML correctly. I can even open it in a browser & view the data correctly.
To retrieve the data & insert it back into the JTextPane/Document:
InputStreamReader in = new InputStreamReader(new FileInputStream("asd"), "UTF-8");
kit.read(in, HTMLdoc, 0);
in.close();
In this case, I get an error:
Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Must insert new content into body element-
at javax.swing.text.html.HTMLDocument$HTMLReader.generateEndsSpecsForMidInsert(HTMLDocument.java:2353)
at javax.swing.text.html.HTMLDocument$HTMLReader.<init>(HTMLDocument.java:2300)
at javax.swing.text.html.HTMLDocument$HTMLReader.<init>(HTMLDocument.java:2174)
at javax.swing.text.html.HTMLDocument$HTMLReader.<init>(HTMLDocument.java:2169)
at javax.swing.text.html.HTMLDocument.getReader(HTMLDocument.java:326)
at javax.swing.text.html.HTMLEditorKit.read(HTMLEditorKit.java:260)
at ChatGUI.NewJFrame.jBtnRWActionPerformed(NewJFrame.java:157)
Where line 157 points to the kit.read statement. Can anybody tell me what I am doing wrong here?
EDIT AGAIN------------------------
I realized my mistake :). Had to clear the Document before reading into it:
HTMLdoc.remove(0, HTMLdoc.getLength());
Now it works!!
Here reading the Javadoc is very helpful.
Best to hold the table element somewhere. Then
// Assuming the table has attribute id="TBL":
Element tableElement = htmlDoc.getElement("TBL");
htmlDoc.insertBeforeEnd(tableElement, "<tr>...</tr>");
I would indeed advise to use a StyleSheet which can shorten the HTML.
Maybe as <style type="text/css">
in the HTML (for storing).
Smileys can also be done with images; as alt attribute the ":)".
Best use Unicode, UTF-8, not the current operating system encoding.
new InputStreamReader(new FileInputStream(file), "UTF-8")
new OutputStreamWriter(new FileOutputStream(file), "UTF-8")
With an encoding specified in the file:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">