001: package org.columba.core.gui.htmlviewer;
002:
003: import java.io.IOException;
004: import java.io.Reader;
005: import java.io.StringReader;
006: import java.net.URL;
007:
008: import javax.swing.BorderFactory;
009: import javax.swing.JComponent;
010: import javax.swing.JScrollPane;
011: import javax.swing.JTextPane;
012: import javax.swing.text.BadLocationException;
013: import javax.swing.text.Document;
014: import javax.swing.text.Element;
015: import javax.swing.text.ElementIterator;
016: import javax.swing.text.MutableAttributeSet;
017: import javax.swing.text.StyleContext;
018: import javax.swing.text.html.HTML;
019: import javax.swing.text.html.HTMLDocument;
020: import javax.swing.text.html.HTMLEditorKit;
021: import javax.swing.text.html.HTMLDocument.HTMLReader;
022:
023: import org.columba.core.gui.htmlviewer.api.IHTMLViewerPlugin;
024: import org.columba.core.io.DiskIO;
025:
026: public class JavaHTMLViewerPlugin extends JScrollPane implements
027: IHTMLViewerPlugin {
028:
029: private HTMLEditorKit htmlEditorKit;
030:
031: private AsynchronousHTMLDocument doc;
032:
033: private JTextPane textPane = new JTextPane();
034:
035: public JavaHTMLViewerPlugin() {
036: super ();
037:
038: setViewportView(textPane);
039: // textPane.setMargin(new Insets(5, 5, 5, 5));
040: textPane.setEditable(false);
041:
042: htmlEditorKit = new HTMLEditorKit();
043: textPane.setEditorKit(htmlEditorKit);
044:
045: textPane.setContentType("text/html");
046:
047: setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
048: }
049:
050: /*
051: * public void view(String htmlSource) {
052: *
053: * setText(htmlSource);
054: *
055: * postView(); }
056: */
057:
058: private void postView() {
059: // setup base url in order to be able to display images
060: // in html-component
061: URL baseUrl = DiskIO
062: .getResourceURL("org/columba/core/icons/MISC/");
063:
064: ((HTMLDocument) textPane.getDocument()).setBase(baseUrl);
065:
066: // scroll window to the beginning
067: textPane.setCaretPosition(0);
068: }
069:
070: public void view(String text) {
071: if (text == null)
072: return;
073:
074: doc = new AsynchronousHTMLDocument();
075:
076: Reader rd = new StringReader(text);
077: try {
078: htmlEditorKit.read(rd, doc, 0);
079: } catch (BadLocationException e) {
080: // TODO Auto-generated catch block
081: e.printStackTrace();
082: } catch (IOException e) {
083: // TODO Auto-generated catch block
084: e.printStackTrace();
085: }
086: textPane.setDocument(doc);
087:
088: postView();
089: }
090:
091: public JComponent getComponent() {
092: return textPane;
093: }
094:
095: /**
096: * Setting HTMLDocument to be an asynchronize model.
097: * <p>
098: * JTextPane therefore uses a background thread to display the message. This
099: * dramatically improves the performance of displaying a message.
100: * <p>
101: * Trick is to overwrite the getAsynchronousLoadPriority() to return a
102: * decent value.
103: *
104: * @author fdietz
105: */
106:
107: public class AsynchronousHTMLDocument extends HTMLDocument {
108:
109: /**
110: *
111: */
112: public AsynchronousHTMLDocument() {
113: super ();
114: putProperty("IgnoreCharsetDirective", new Boolean(true));
115: }
116:
117: /*Overwrite the method to maintain line breaks when copying
118: * messages form the MessageViewer.
119: * @author aoki-y
120: * @see javax.swing.text.html.HTMLDocument#getReader(int)
121: */
122: public HTMLEditorKit.ParserCallback getReader(int pos) {
123: Object desc = getProperty(Document.StreamDescriptionProperty);
124: if (desc instanceof URL) {
125: setBase((URL) desc);
126: }
127: HTMLReader reader = new MyReader(pos);
128: return reader;
129: }
130:
131: public class MyReader extends HTMLDocument.HTMLReader {
132: public MyReader(int pos) {
133: super (pos);
134: }
135:
136: protected void addSpecialElement(HTML.Tag t,
137: MutableAttributeSet a) {
138: super .addSpecialElement(t, a);
139: if (t == HTML.Tag.BR) {
140: int size = parseBuffer.size();
141: parseBuffer.removeElementAt(size - 1);
142: char[] c = { '\n' };
143: parseBuffer.addElement(new ElementSpec(a
144: .copyAttributes(), ElementSpec.ContentType,
145: c, 0, c.length));
146: }
147: }
148: }
149:
150: /**
151: * From the JDK1.4 reference:
152: * <p>
153: * This may load either synchronously or asynchronously depending upon
154: * the document returned by the EditorKit. If the Document is of type
155: * AbstractDocument and has a value returned by
156: * AbstractDocument.getAsynchronousLoadPriority that is greater than or
157: * equal to zero, the page will be loaded on a separate thread using
158: * that priority.
159: *
160: * @see javax.swing.text.AbstractDocument#getAsynchronousLoadPriority()
161: */
162: public int getAsynchronousLoadPriority() {
163: return 10;
164: }
165:
166: public String getTextWithLineBreaks(int start, int end)
167: throws BadLocationException {
168: StringBuffer result = new StringBuffer(end - start);
169: ElementIterator iter = new ElementIterator(this );
170:
171: // First find the beginning element
172: for (iter.next(); iter.current() != null; iter.next()) {
173: Element e = iter.current();
174: if (e.isLeaf()
175: && (e.getStartOffset() >= start || e
176: .getEndOffset() >= start)
177: && e.getStartOffset() <= end) {
178: Object a = e.getAttributes().getAttribute(
179: StyleContext.NamedStyle.NameAttribute);
180: if (a == HTML.Tag.CONTENT) {
181: int as = Math.max(e.getStartOffset(), start);
182: int ae = Math.min(e.getEndOffset(), end);
183: result.append(super .getText(as, ae - as));
184: }
185: if (a == HTML.Tag.BR) {
186: result.append("\n");
187: }
188: }
189: }
190:
191: return result.toString();
192: }
193: }
194:
195: public boolean initialized() {
196: return true;
197: }
198:
199: /**
200: * @see javax.swing.text.JTextComponent#getSelectedText()
201: */
202: public String getSelectedText() {
203: try {
204: return doc.getTextWithLineBreaks(textPane
205: .getSelectionStart(), textPane.getSelectionEnd());
206: } catch (BadLocationException e) {
207: return "";
208: }
209: }
210:
211: public JComponent getContainer() {
212: return this ;
213: }
214:
215: public String getText() {
216: try {
217: return doc.getTextWithLineBreaks(0, doc.getLength());
218: } catch (BadLocationException e) {
219: return "";
220: }
221: }
222:
223: /**
224: * @see org.columba.core.gui.htmlviewer.api.IHTMLViewerPlugin#setCaretPosition(int)
225: */
226: public void setCaretPosition(int position) {
227: textPane.setCaretPosition(position);
228: }
229:
230: /**
231: * @see org.columba.core.gui.htmlviewer.api.IHTMLViewerPlugin#moveCaretPosition(int)
232: */
233: public void moveCaretPosition(int position) {
234: textPane.moveCaretPosition(position);
235: }
236:
237: }
|