001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Vadim L. Bogdanov, Alexander T. Simbirtsev
019: * @version $Revision$
020: */package javax.swing.text.html;
021:
022: import java.awt.Color;
023: import java.awt.Cursor;
024: import java.awt.Graphics;
025: import java.awt.Point;
026: import java.awt.Rectangle;
027: import java.awt.Shape;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.MouseAdapter;
030: import java.awt.event.MouseEvent;
031: import java.awt.event.MouseMotionListener;
032: import java.io.BufferedReader;
033: import java.io.IOException;
034: import java.io.InputStreamReader;
035: import java.io.Reader;
036: import java.io.Serializable;
037: import java.io.StringReader;
038: import java.io.Writer;
039: import java.net.URL;
040: import java.util.ArrayList;
041: import java.util.HashMap;
042:
043: import javax.accessibility.Accessible;
044: import javax.accessibility.AccessibleContext;
045: import javax.swing.Action;
046: import javax.swing.JEditorPane;
047: import javax.swing.event.HyperlinkEvent;
048: import javax.swing.text.AttributeSet;
049: import javax.swing.text.BadLocationException;
050: import javax.swing.text.Caret;
051: import javax.swing.text.DefaultHighlighter;
052: import javax.swing.text.Document;
053: import javax.swing.text.EditorKit;
054: import javax.swing.text.Element;
055: import javax.swing.text.Highlighter;
056: import javax.swing.text.JTextComponent;
057: import javax.swing.text.MutableAttributeSet;
058: import javax.swing.text.Position;
059: import javax.swing.text.StyleConstants;
060: import javax.swing.text.StyledEditorKit;
061: import javax.swing.text.View;
062: import javax.swing.text.ViewFactory;
063: import javax.swing.text.Position.Bias;
064: import javax.swing.text.html.parser.ParserDelegator;
065:
066: import org.apache.harmony.awt.text.TextUtils;
067: import org.apache.harmony.x.swing.StringConstants;
068:
069: import org.apache.harmony.x.swing.internal.nls.Messages;
070:
071: public class HTMLEditorKit extends StyledEditorKit implements
072: Accessible {
073: public static class HTMLFactory implements ViewFactory {
074:
075: public View create(final Element elem) {
076: HTML.Tag tag = getHTMLTagByElement(elem);
077:
078: if (HTML.Tag.CONTENT.equals(tag)) {
079: return new InlineView(elem);
080:
081: } else if (HTML.Tag.IMPLIED.equals(tag)
082: || HTML.Tag.P.equals(tag)
083: || HTML.Tag.H1.equals(tag)
084: || HTML.Tag.H2.equals(tag)
085: || HTML.Tag.H3.equals(tag)
086: || HTML.Tag.H4.equals(tag)
087: || HTML.Tag.H5.equals(tag)
088: || HTML.Tag.H6.equals(tag)
089: || HTML.Tag.DT.equals(tag)) {
090: return new ParagraphView(elem);
091:
092: } else if (HTML.Tag.MENU.equals(tag)
093: || HTML.Tag.DIR.equals(tag)
094: || HTML.Tag.UL.equals(tag)
095: || HTML.Tag.OL.equals(tag)) {
096: return new ListView(elem);
097:
098: } else if (HTML.Tag.LI.equals(tag)
099: || HTML.Tag.DL.equals(tag)
100: || HTML.Tag.DD.equals(tag)
101: || HTML.Tag.BODY.equals(tag)
102: || HTML.Tag.HTML.equals(tag)
103: || HTML.Tag.CENTER.equals(tag)
104: || HTML.Tag.DIV.equals(tag)
105: || HTML.Tag.BLOCKQUOTE.equals(tag)
106: || HTML.Tag.PRE.equals(tag)) {
107: return new BlockView(elem, View.Y_AXIS);
108:
109: } else if (HTML.Tag.IMG.equals(tag)) {
110: return new ImageView(elem);
111:
112: } else if (HTML.Tag.HR.equals(tag)) {
113: return new HRuleTagView(elem);
114:
115: } else if (HTML.Tag.BR.equals(tag)) {
116: return new BRView(elem);
117:
118: } else if (HTML.Tag.TABLE.equals(tag)) {
119: return new TableTagView(elem);
120:
121: } else if (HTML.Tag.FORM.equals(tag)) {
122: return new BlockView(elem, View.X_AXIS);
123:
124: } else if (HTML.Tag.INPUT.equals(tag)) {
125: return new FormView(elem);
126:
127: } else if (HTML.Tag.SELECT.equals(tag)
128: || HTML.Tag.TEXTAREA.equals(tag)) {
129: return new FormView(elem);
130:
131: } else if (HTML.Tag.OBJECT.equals(tag)) {
132: return new ObjectView(elem);
133:
134: } else if (HTML.Tag.FRAMESET.equals(tag)) {
135: return new FrameSetTagView(elem);
136:
137: } else if (HTML.Tag.FRAME.equals(tag)) {
138: return new FrameTagView(elem);
139:
140: } else if (HTML.Tag.NOFRAMES.equals(tag)) {
141: return new NoFramesTagView(elem);
142:
143: } else if (HTML.Tag.HEAD.equals(tag)) {
144: return new HeadTagView(elem);
145: }
146:
147: // HARMONY-4570
148: // We should not throw exception on uknown tag
149: return new InlineView(elem);
150: }
151: }
152:
153: public abstract static class HTMLTextAction extends
154: StyledTextAction {
155: public HTMLTextAction(final String name) {
156: super (name);
157: }
158:
159: protected int elementCountToTag(final HTMLDocument doc,
160: final int offset, final HTML.Tag tag) {
161: int count = -1;
162: Element e;
163: for (e = doc.getCharacterElement(offset); e != null
164: && !tag.equals(getHTMLTagByElement(e)); e = e
165: .getParentElement()) {
166: count++;
167: }
168: if (e == null) {
169: return -1;
170: }
171: return count;
172: }
173:
174: protected Element findElementMatchingTag(
175: final HTMLDocument doc, final int offset,
176: final HTML.Tag tag) {
177: Element e = doc.getCharacterElement(offset);
178: while (e != null && !tag.equals(getHTMLTagByElement(e))) {
179: e = e.getParentElement();
180: }
181: return e;
182: }
183:
184: protected Element[] getElementsAt(final HTMLDocument doc,
185: final int offset) {
186: ArrayList list = new ArrayList();
187: Element e = doc.getDefaultRootElement();
188: while (true) {
189: list.add(e);
190: if (e.getElementCount() == 0) {
191: break;
192: }
193: e = e.getElement(e.getElementIndex(offset));
194: }
195:
196: return (Element[]) list.toArray(new Element[list.size()]);
197: }
198:
199: protected HTMLDocument getHTMLDocument(final JEditorPane pane) {
200: Document doc = pane.getDocument();
201: if (doc instanceof HTMLDocument) {
202: return (HTMLDocument) doc;
203: }
204: throw new IllegalArgumentException(Messages
205: .getString("swing.A0")); //$NON-NLS-1$
206: }
207:
208: protected HTMLEditorKit getHTMLEditorKit(final JEditorPane pane) {
209: EditorKit editorKit = pane.getEditorKit();
210: if (editorKit instanceof HTMLEditorKit) {
211: return (HTMLEditorKit) editorKit;
212: }
213: throw new IllegalArgumentException(Messages
214: .getString("swing.A1")); //$NON-NLS-1$
215: }
216: }
217:
218: public static class InsertHTMLTextAction extends HTMLTextAction {
219: protected HTML.Tag addTag;
220: protected HTML.Tag alternateAddTag;
221: protected HTML.Tag alternateParentTag;
222: protected String html;
223: protected HTML.Tag parentTag;
224:
225: public InsertHTMLTextAction(final String name,
226: final String html, final HTML.Tag parentTag,
227: final HTML.Tag addTag,
228: final HTML.Tag alternateParentTag,
229: final HTML.Tag alternateAddTag) {
230: super (name);
231: this .html = html;
232: this .parentTag = parentTag;
233: this .addTag = addTag;
234: this .alternateParentTag = alternateParentTag;
235: this .alternateAddTag = alternateAddTag;
236: }
237:
238: public InsertHTMLTextAction(final String name,
239: final String html, final HTML.Tag parentTag,
240: final HTML.Tag addTag) {
241: super (name);
242: this .html = html;
243: this .parentTag = parentTag;
244: this .addTag = addTag;
245: }
246:
247: public void actionPerformed(final ActionEvent event) {
248: if (event == null) {
249: return;
250: }
251:
252: JEditorPane editor = getEditor(event);
253: HTMLDocument doc = getHTMLDocument(editor);
254: int offset = editor.getCaretPosition();
255:
256: HTML.Tag usedParentTag = parentTag;
257: HTML.Tag usedAddTag = addTag;
258: int popDepth = elementCountToTag(doc, offset, parentTag);
259: if (popDepth == -1 && alternateParentTag != null) {
260: usedParentTag = alternateParentTag;
261: usedAddTag = alternateAddTag;
262: popDepth = elementCountToTag(doc, offset,
263: alternateParentTag);
264: }
265: if (popDepth == -1) {
266: return;
267: }
268:
269: Element insertElement = findElementMatchingTag(doc, offset,
270: usedParentTag);
271: if (insertElement.getStartOffset() == offset) {
272: insertAtBoundary(editor, doc, offset, insertElement,
273: html, usedParentTag, usedAddTag);
274: } else {
275: int pushDepth = 0;
276: insertHTML(editor, doc, offset, html, popDepth,
277: pushDepth, usedAddTag);
278: }
279: }
280:
281: protected void insertHTML(final JEditorPane editor,
282: final HTMLDocument doc, final int offset,
283: final String html, final int popDepth,
284: final int pushDepth, final HTML.Tag addTag) {
285: HTMLEditorKit editorKit = getHTMLEditorKit(editor);
286: try {
287: editorKit.insertHTML(doc, offset, html, popDepth,
288: pushDepth, addTag);
289: } catch (BadLocationException e) {
290: throw new RuntimeException(e);
291: } catch (IOException e) {
292: throw new RuntimeException(e);
293: }
294: }
295:
296: protected void insertAtBoundary(final JEditorPane editor,
297: final HTMLDocument doc, final int offset,
298: final Element insertElement, final String html,
299: final HTML.Tag parentTag, final HTML.Tag addTag) {
300: insertAtBoundaryImpl(editor, doc, offset, insertElement,
301: html, parentTag, addTag);
302: }
303:
304: /**
305: * @deprecated
306: */
307: protected void insertAtBoundry(final JEditorPane editor,
308: final HTMLDocument doc, final int offset,
309: final Element insertElement, final String html,
310: final HTML.Tag parentTag, final HTML.Tag addTag) {
311: insertAtBoundaryImpl(editor, doc, offset, insertElement,
312: html, parentTag, addTag);
313: }
314:
315: private void insertAtBoundaryImpl(final JEditorPane editor,
316: final HTMLDocument doc, final int offset,
317: final Element insertElement, final String html,
318: final HTML.Tag parentTag, final HTML.Tag addTag) {
319: int popDepth = elementCountToTag(doc, offset, parentTag) + 1;
320: int pushDepth = 1;
321: insertHTML(editor, doc, offset, html, popDepth, pushDepth,
322: addTag);
323: }
324: }
325:
326: public static class LinkController extends MouseAdapter implements
327: MouseMotionListener, Serializable {
328:
329: private Element prevLinkUnderMouse;
330:
331: public void mouseClicked(final MouseEvent e) {
332: JEditorPane pane = (JEditorPane) e.getSource();
333: if (pane.isEditable()) {
334: return;
335: }
336:
337: int pos = pane.viewToModel(e.getPoint());
338: activateLink(pos, pane);
339: }
340:
341: public void mouseDragged(final MouseEvent e) {
342: // does nothing
343: }
344:
345: public void mouseMoved(final MouseEvent e) {
346: JEditorPane pane = (JEditorPane) e.getSource();
347: Element linkElement = getLinkElement(pane, e.getPoint());
348: updateMouseCursor(e, linkElement);
349:
350: if (pane.isEditable()) {
351: return;
352: }
353:
354: fireHyperlinkEvent(e, linkElement);
355: }
356:
357: protected void activateLink(final int pos,
358: final JEditorPane editor) {
359: Element elem = HTMLEditorKit.getLinkElement(editor, pos);
360: if (elem != null) {
361: HTMLEditorKit.fireHyperlinkEvent(editor,
362: HyperlinkEvent.EventType.ACTIVATED, elem);
363: }
364: }
365:
366: private void updateMouseCursor(final MouseEvent e,
367: final Element linkElement) {
368: JEditorPane pane = (JEditorPane) e.getSource();
369: HTMLEditorKit editorKit = (HTMLEditorKit) pane
370: .getEditorKit();
371: if (!pane.isEditable() && linkElement != null) {
372: e.getComponent().setCursor(editorKit.getLinkCursor());
373: } else {
374: e.getComponent()
375: .setCursor(editorKit.getDefaultCursor());
376: }
377: }
378:
379: private void fireHyperlinkEvent(final MouseEvent e,
380: final Element linkElement) {
381: if (prevLinkUnderMouse == linkElement) {
382: return;
383: }
384:
385: JEditorPane pane = (JEditorPane) e.getSource();
386: if (prevLinkUnderMouse != null) {
387: HTMLEditorKit.fireHyperlinkEvent(pane,
388: HyperlinkEvent.EventType.EXITED,
389: prevLinkUnderMouse);
390: }
391: if (linkElement != null) {
392: HTMLEditorKit.fireHyperlinkEvent(pane,
393: HyperlinkEvent.EventType.ENTERED, linkElement);
394: }
395: prevLinkUnderMouse = linkElement;
396: }
397:
398: private Element getLinkElement(final JEditorPane pane,
399: final Point p) {
400: return HTMLEditorKit.getLinkElement(pane, pane
401: .viewToModel(p));
402: }
403: }
404:
405: public abstract static class Parser {
406: public abstract void parse(final Reader r,
407: final ParserCallback cb, final boolean ignoreCharSet)
408: throws IOException;
409: }
410:
411: public static class ParserCallback {
412: public static final Object IMPLIED = "_implied_";
413:
414: public void flush() throws BadLocationException {
415: }
416:
417: public void handleComment(final char[] data, final int pos) {
418: }
419:
420: public void handleEndOfLineString(final String eol) {
421: }
422:
423: public void handleEndTag(final HTML.Tag tag, final int pos) {
424: }
425:
426: public void handleError(final String errorMsg, final int pos) {
427: }
428:
429: public void handleSimpleTag(final HTML.Tag tag,
430: final MutableAttributeSet attr, final int pos) {
431: }
432:
433: public void handleStartTag(final HTML.Tag tag,
434: final MutableAttributeSet attr, final int pos) {
435: }
436:
437: public void handleText(final char[] data, final int pos) {
438: }
439: }
440:
441: private static class NavigateLinkAction extends HTMLTextAction {
442: private static final HashMap highlightTags = new HashMap();
443:
444: public NavigateLinkAction(final String name) {
445: super (name);
446: }
447:
448: public void actionPerformed(final ActionEvent e) {
449: if (getEditor(e).isEditable()) {
450: return;
451: }
452:
453: JEditorPane editor = getEditor(e);
454: Caret caret = editor.getCaret();
455: HTMLDocument doc = getHTMLDocument(editor);
456:
457: Element link = getNextLinkElement(doc, caret.getDot(),
458: isForward());
459: if (link != null) {
460: moveHighlight(editor, link.getStartOffset(), link
461: .getEndOffset());
462: }
463: }
464:
465: private boolean isForward() {
466: return "next-link-action".equals(getValue(NAME));
467: }
468:
469: private static Element getNextLinkElement(
470: final HTMLDocument doc, final int pos,
471: final boolean forward) {
472: HTMLDocument.Iterator it = doc.getIterator(HTML.Tag.A);
473: int linkPos = -1;
474: for (; it.isValid(); it.next()) {
475: if (forward) {
476: if (it.getStartOffset() > pos) {
477: linkPos = it.getStartOffset();
478: break;
479: }
480: } else {
481: if (it.getStartOffset() >= pos) {
482: break;
483: }
484: linkPos = it.getStartOffset();
485: }
486: }
487:
488: return linkPos != -1 ? doc.getCharacterElement(linkPos)
489: : null;
490: }
491:
492: private static void moveHighlight(final JEditorPane editor,
493: final int start, final int end) {
494: Highlighter highlighter = editor.getHighlighter();
495: Object tag = highlightTags.get(highlighter);
496: if (tag != null) {
497: highlighter.removeHighlight(tag);
498: highlightTags.remove(highlighter);
499: }
500: try {
501: tag = highlighter.addHighlight(start, end,
502: new LinkHighlightPainter());
503: highlightTags.put(highlighter, tag);
504: editor.getCaret().setDot(start);
505: } catch (final BadLocationException e) {
506: }
507: }
508:
509: static void removeHighlight(final JEditorPane editor) {
510: Highlighter highlighter = editor.getHighlighter();
511: Object tag = highlightTags.get(highlighter);
512: if (tag != null) {
513: highlighter.removeHighlight(tag);
514: highlightTags.remove(highlighter);
515: }
516: }
517: }
518:
519: private static class ActivateLinkAction extends HTMLTextAction {
520: public ActivateLinkAction() {
521: super ("activate-link-action");
522: }
523:
524: public void actionPerformed(final ActionEvent e) {
525: JEditorPane editor = getEditor(e);
526: if (!editor.isEditable()) {
527: activateLink(editor.getCaretPosition(), editor);
528: }
529: }
530: }
531:
532: private static class LinkHighlightPainter extends
533: DefaultHighlighter.DefaultHighlightPainter {
534: public LinkHighlightPainter() {
535: super (Color.RED);
536: }
537:
538: public Shape paintLayer(final Graphics g, final int p0,
539: final int p1, final Shape shape,
540: final JTextComponent jtc, final View view) {
541: return TextUtils.paintLayer(g, p0, p1, shape, jtc
542: .getSelectionColor(), view, false);
543: }
544: }
545:
546: private static class HeadTagView extends View {
547: public HeadTagView(final Element elem) {
548: super (elem);
549: }
550:
551: public float getPreferredSpan(final int axis) {
552: return 0.0f;
553: }
554:
555: public int viewToModel(final float x, final float y,
556: final Shape a, final Bias[] biasRet) {
557: return 0;
558: }
559:
560: public void paint(final Graphics g, final Shape allocation) {
561: }
562:
563: public Shape modelToView(final int pos, final Shape a,
564: final Bias b) throws BadLocationException {
565: return new Rectangle(0, 0);
566: }
567:
568: public int getNextVisualPositionFrom(final int pos,
569: final Bias b, final Shape a, final int direction,
570: final Bias[] biasRet) throws BadLocationException {
571: if (direction != NORTH && direction != SOUTH
572: && direction != EAST && direction != WEST) {
573: throw new IllegalArgumentException(Messages
574: .getString("swing.84")); //$NON-NLS-1$
575: }
576: biasRet[0] = Position.Bias.Forward;
577: return getEndOffset();
578: }
579: }
580:
581: public static final String BOLD_ACTION = "html-bold-action";
582: public static final String COLOR_ACTION = "html-color-action";
583: public static final String FONT_CHANGE_BIGGER = "html-font-bigger";
584: public static final String FONT_CHANGE_SMALLER = "html-font-smaller";
585: public static final String IMG_ALIGN_BOTTOM = "html-image-align-bottom";
586: public static final String IMG_ALIGN_MIDDLE = "html-image-align-middle";
587: public static final String IMG_ALIGN_TOP = "html-image-align-top";
588: public static final String IMG_BORDER = "html-image-border";
589: public static final String ITALIC_ACTION = "html-italic-action";
590: public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action";
591: public static final String PARA_INDENT_LEFT = "html-para-indent-left";
592: public static final String PARA_INDENT_RIGHT = "html-para-indent-right";
593:
594: public static final String DEFAULT_CSS = "default.css";
595:
596: private static StyleSheet styleSheet;
597: private static Parser parser;
598: private static ViewFactory viewFactory;
599: private static final LinkController linkController = new LinkController();
600: private static Action[] actions;
601:
602: private Cursor defaultCursor = Cursor
603: .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
604: private Cursor linkCursor = Cursor
605: .getPredefinedCursor(Cursor.HAND_CURSOR);
606: private boolean autoFormSubmission = true;
607:
608: public HTMLEditorKit() {
609: if (actions == null) {
610: createStaticActions();
611: }
612: }
613:
614: public Object clone() {
615: return super .clone();
616: }
617:
618: public Document createDefaultDocument() {
619: HTMLDocument document = new HTMLDocument();
620: document.getStyleSheet().addStyleSheet(getStyleSheet());
621: document.setParser(getParser());
622: document.setAsynchronousLoadPriority(4);
623: return document;
624: }
625:
626: public AccessibleContext getAccessibleContext() {
627: // TODO: implement
628: throw new UnsupportedOperationException(Messages
629: .getString("swing.9F")); //$NON-NLS-1$
630: }
631:
632: public Action[] getActions() {
633: return (Action[]) actions.clone();
634: }
635:
636: public String getContentType() {
637: return "text/html";
638: }
639:
640: public MutableAttributeSet getInputAttributes() {
641: return super .getInputAttributes();
642: }
643:
644: public ViewFactory getViewFactory() {
645: if (viewFactory == null) {
646: viewFactory = new HTMLFactory();
647: }
648: return viewFactory;
649: }
650:
651: public void install(final JEditorPane pane) {
652: super .install(pane);
653:
654: pane.addMouseListener(linkController);
655: pane.addMouseMotionListener(linkController);
656: }
657:
658: public void deinstall(final JEditorPane pane) {
659: pane.removeMouseListener(linkController);
660: pane.removeMouseMotionListener(linkController);
661: NavigateLinkAction.removeHighlight(pane);
662:
663: super .deinstall(pane);
664: }
665:
666: public void setAutoFormSubmission(final boolean auto) {
667: autoFormSubmission = auto;
668: }
669:
670: public boolean isAutoFormSubmission() {
671: return autoFormSubmission;
672: }
673:
674: public void setDefaultCursor(final Cursor cursor) {
675: defaultCursor = cursor;
676: }
677:
678: public Cursor getDefaultCursor() {
679: return defaultCursor;
680: }
681:
682: public void setLinkCursor(final Cursor cursor) {
683: linkCursor = cursor;
684: }
685:
686: public Cursor getLinkCursor() {
687: return linkCursor;
688: }
689:
690: public void setStyleSheet(final StyleSheet ss) {
691: styleSheet = ss;
692: }
693:
694: public StyleSheet getStyleSheet() {
695: if (styleSheet == null) {
696: styleSheet = new StyleSheet();
697: URL url = HTMLEditorKit.class.getResource(DEFAULT_CSS);
698: try {
699: styleSheet.loadRules(new BufferedReader(
700: new InputStreamReader(url.openStream())), url);
701: } catch (final IOException e) {
702: e.printStackTrace();
703: }
704: }
705:
706: return styleSheet;
707: }
708:
709: public void insertHTML(final HTMLDocument doc, final int offset,
710: final String html, final int popDepth, final int pushDepth,
711: final HTML.Tag insertTag) throws BadLocationException,
712: IOException {
713: if (offset > doc.getLength()) {
714: throw new BadLocationException(Messages
715: .getString("swing.98"), offset); //$NON-NLS-1$
716: }
717:
718: ParserCallback htmlReader = doc.getReader(offset, popDepth,
719: pushDepth, insertTag);
720: StringReader in = new StringReader(html);
721:
722: getParser().parse(in, htmlReader, false);
723: htmlReader.flush();
724: in.close();
725: }
726:
727: public void read(final Reader in, final Document doc, final int pos)
728: throws IOException, BadLocationException {
729: if (!(doc instanceof HTMLDocument)) {
730: super .read(in, doc, pos);
731: return;
732: }
733:
734: HTMLDocument htmlDoc = (HTMLDocument) doc;
735: checkReadPosition(htmlDoc, pos);
736:
737: ParserCallback htmlReader = htmlDoc.getReader(pos);
738: Object property = doc
739: .getProperty(StringConstants.IGNORE_CHARSET_DIRECTIVE);
740: getParser().parse(
741: in,
742: htmlReader,
743: property == null ? false : ((Boolean) property)
744: .booleanValue());
745: htmlReader.flush();
746: in.close();
747: }
748:
749: public void write(final Writer out, final Document doc,
750: final int pos, final int len) throws IOException,
751: BadLocationException {
752: HTMLDocument htmlDoc;
753: int fixedPos = pos;
754:
755: if (doc instanceof HTMLDocument) {
756: htmlDoc = (HTMLDocument) doc;
757: } else {
758: htmlDoc = (HTMLDocument) createDefaultDocument();
759: htmlDoc.insertString(0, doc.getText(pos, len), null);
760: fixedPos = 0;
761: }
762:
763: HTMLWriter writer = new HTMLWriter(out, htmlDoc, fixedPos, len);
764: writer.write();
765: }
766:
767: protected Parser getParser() {
768: if (parser == null) {
769: parser = new ParserDelegator();
770: }
771:
772: return parser;
773: }
774:
775: protected void createInputAttributes(final Element elem,
776: final MutableAttributeSet set) {
777: super .createInputAttributes(elem, set);
778: }
779:
780: static HTML.Tag getHTMLTagByElement(final Element elem) {
781: final Object result = elem.getAttributes().getAttribute(
782: StyleConstants.NameAttribute);
783: return (result instanceof HTML.Tag) ? (HTML.Tag) result : null;
784: }
785:
786: private static String getURLString(final Element e) {
787: AttributeSet aSet = (AttributeSet) e.getAttributes()
788: .getAttribute(HTML.Tag.A);
789: return aSet == null ? null : (String) aSet
790: .getAttribute(HTML.Attribute.HREF);
791: }
792:
793: private static void checkReadPosition(final HTMLDocument doc,
794: final int pos) throws BadLocationException {
795: if (pos < 0) {
796: throw new RuntimeException(Messages.getString("swing.A2")); //$NON-NLS-1$
797: }
798: if (pos > doc.getLength()) {
799: throw new BadLocationException(Messages
800: .getString("swing.98"), pos); //$NON-NLS-1$
801: }
802: if (doc.getLength() != 0) {
803: Element body = doc.getElement(doc.getDefaultRootElement(),
804: StyleConstants.NameAttribute, HTML.Tag.BODY);
805: if (pos < body.getStartOffset()
806: || pos > body.getEndOffset()) {
807: throw new RuntimeException(Messages
808: .getString("swing.A3")); //$NON-NLS-1$
809: }
810: }
811: }
812:
813: private Action[] createStaticActions() {
814: if (actions == null) {
815: Action[] htmlActions = getDefaultActions();
816: Action[] styledActions = super .getActions();
817: actions = new Action[htmlActions.length
818: + styledActions.length];
819: System.arraycopy(styledActions, 0, actions, 0,
820: styledActions.length);
821: System.arraycopy(htmlActions, 0, actions,
822: styledActions.length, htmlActions.length);
823: }
824: return actions;
825: }
826:
827: private Action[] getDefaultActions() {
828: return new Action[] {
829: new InsertHTMLTextAction("InsertOrderedList",
830: "<ol><li></li></ol>", HTML.Tag.BODY,
831: HTML.Tag.OL),
832: new InsertHTMLTextAction("InsertOrderedListItem",
833: "<ol><li></li></ol>", HTML.Tag.OL, HTML.Tag.LI,
834: HTML.Tag.BODY, HTML.Tag.OL),
835: new InsertHTMLTextAction("InsertUnorderedList",
836: "<ul><li></li></ul>", HTML.Tag.BODY,
837: HTML.Tag.UL),
838: new InsertHTMLTextAction("InsertUnorderedListItem",
839: "<ul><li></li></ul>", HTML.Tag.UL, HTML.Tag.LI,
840: HTML.Tag.BODY, HTML.Tag.UL),
841: new InsertHTMLTextAction("InsertTable",
842: "<table border=1><tr><td></td></tr></table>",
843: HTML.Tag.BODY, HTML.Tag.TABLE),
844: new InsertHTMLTextAction("InsertTableDataCell",
845: "<table border=1><tr><td></td></tr></table>",
846: HTML.Tag.TR, HTML.Tag.TD, HTML.Tag.BODY,
847: HTML.Tag.TABLE),
848: new InsertHTMLTextAction("InsertTableRow",
849: "<table border=1><tr><td></td></tr></table>",
850: HTML.Tag.TABLE, HTML.Tag.TR, HTML.Tag.BODY,
851: HTML.Tag.TABLE),
852: new InsertHTMLTextAction("InsertPre", "<pre></pre>",
853: HTML.Tag.BODY, HTML.Tag.PRE),
854: new InsertHTMLTextAction("InsertHR", "<hr>",
855: HTML.Tag.P, HTML.Tag.HR),
856: new NavigateLinkAction("next-link-action"),
857: new NavigateLinkAction("previous-link-action"),
858: new ActivateLinkAction() };
859: }
860:
861: private static void activateLink(final int pos,
862: final JEditorPane editor) {
863: Element elem = getLinkElement(editor, pos);
864: if (elem != null) {
865: fireHyperlinkEvent(editor,
866: HyperlinkEvent.EventType.ACTIVATED, elem);
867: }
868: }
869:
870: private static void fireHyperlinkEvent(final JEditorPane pane,
871: final HyperlinkEvent.EventType eventID, final Element elem) {
872: String urlString = getURLString(elem);
873:
874: URL base = ((HTMLDocument) pane.getDocument()).getBase();
875: HyperlinkEvent event = new HyperlinkEvent(pane, eventID, HTML
876: .resolveURL(urlString, base), urlString, elem);
877: pane.fireHyperlinkUpdate(event);
878: }
879:
880: private static Element getLinkElement(final JEditorPane pane,
881: final int pos) {
882: Element e = (((HTMLDocument) pane.getDocument())
883: .getCharacterElement(pos));
884: for (; e != null; e = e.getParentElement()) {
885: if (getURLString(e) != null) {
886: return e;
887: }
888: }
889:
890: return null;
891: }
892: }
|