1:
37:
38:
39: package ;
40:
41:
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48:
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58:
59: import ;
60: import ;
61:
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79:
80:
82: import ;
83: import ;
84:
85:
88: public class HTMLEditorKit
89: extends StyledEditorKit
90: implements Serializable, Cloneable, Accessible
91: {
92:
93:
97: public static class LinkController
98: extends MouseAdapter
99: implements MouseMotionListener, Serializable
100: {
101:
102:
105: private Element lastAnchorElement;
106:
107:
110: public LinkController()
111: {
112: super();
113: }
114:
115:
122: public void mouseClicked(MouseEvent e)
123: {
124: JEditorPane editor = (JEditorPane) e.getSource();
125: if (! editor.isEditable() && SwingUtilities.isLeftMouseButton(e))
126: {
127: Point loc = e.getPoint();
128: int pos = editor.viewToModel(loc);
129: if (pos >= 0)
130: activateLink(pos, editor, e.getX(), e.getY());
131: }
132: }
133:
134:
139: public void mouseDragged(MouseEvent e)
140: {
141:
142: }
143:
144:
149: public void mouseMoved(MouseEvent e)
150: {
151: JEditorPane editor = (JEditorPane) e.getSource();
152: HTMLEditorKit kit = (HTMLEditorKit) editor.getEditorKit();
153: if (! editor.isEditable())
154: {
155: Document doc = editor.getDocument();
156: if (doc instanceof HTMLDocument)
157: {
158: Cursor newCursor = kit.getDefaultCursor();
159: HTMLDocument htmlDoc = (HTMLDocument) doc;
160: Point loc = e.getPoint();
161: int pos = editor.viewToModel(loc);
162: Element el = htmlDoc.getCharacterElement(pos);
163: if (pos < el.getStartOffset() || pos >= el.getEndOffset())
164: el = null;
165: if (el != null)
166: {
167: AttributeSet aAtts = (AttributeSet)
168: el.getAttributes().getAttribute(HTML.Tag.A);
169: if (aAtts != null)
170: {
171: if (el != lastAnchorElement)
172: {
173: if (lastAnchorElement != null)
174: htmlDoc.updateSpecialClass(lastAnchorElement,
175: HTML.Attribute.DYNAMIC_CLASS,
176: null);
177: lastAnchorElement = el;
178: htmlDoc.updateSpecialClass(el,
179: HTML.Attribute.DYNAMIC_CLASS,
180: "hover");
181: }
182: newCursor = kit.getLinkCursor();
183: }
184: else
185: {
186: if (lastAnchorElement != null)
187: htmlDoc.updateSpecialClass(lastAnchorElement,
188: HTML.Attribute.DYNAMIC_CLASS,
189: null);
190: lastAnchorElement = null;
191: }
192: }
193: else
194: {
195: if (lastAnchorElement != null)
196: htmlDoc.updateSpecialClass(lastAnchorElement,
197: HTML.Attribute.DYNAMIC_CLASS,
198: null);
199: lastAnchorElement = null;
200: }
201: if (editor.getCursor() != newCursor)
202: {
203: editor.setCursor(newCursor);
204: }
205: }
206: }
207: }
208:
209:
216: protected void activateLink(int pos, JEditorPane editor)
217: {
218: activateLink(pos, editor);
219: }
220:
221: private void activateLink(int pos, JEditorPane editor, int x, int y)
222: {
223:
224:
225: Document doc = editor.getDocument();
226: if (doc instanceof HTMLDocument)
227: {
228: HTMLDocument htmlDoc = (HTMLDocument) doc;
229: Element el = htmlDoc.getCharacterElement(pos);
230: AttributeSet atts = el.getAttributes();
231: AttributeSet anchorAtts =
232: (AttributeSet) atts.getAttribute(HTML.Tag.A);
233: String href = null;
234: if (anchorAtts != null)
235: {
236: href = (String) anchorAtts.getAttribute(HTML.Attribute.HREF);
237: htmlDoc.updateSpecialClass(el, HTML.Attribute.PSEUDO_CLASS,
238: "visited");
239: }
240: else
241: {
242:
243: }
244: HyperlinkEvent event = null;
245: if (href != null)
246: event = createHyperlinkEvent(editor, htmlDoc, href,
247: anchorAtts, el);
248: if (event != null)
249: editor.fireHyperlinkUpdate(event);
250: }
251:
252: }
253:
254:
267: private HyperlinkEvent createHyperlinkEvent(JEditorPane editor,
268: HTMLDocument doc,
269: String href,
270: AttributeSet anchor,
271: Element el)
272: {
273: URL url;
274: try
275: {
276: URL base = doc.getBase();
277: url = new URL(base, href);
278:
279: }
280: catch (MalformedURLException ex)
281: {
282: url = null;
283: }
284: HyperlinkEvent ev;
285: if (doc.isFrameDocument())
286: {
287: String target = null;
288: if (anchor != null)
289: target = (String) anchor.getAttribute(HTML.Attribute.TARGET);
290: if (target == null || target.equals(""))
291: target = doc.getBaseTarget();
292: if (target == null || target.equals(""))
293: target = "_self";
294: ev = new HTMLFrameHyperlinkEvent(editor,
295: HyperlinkEvent.EventType.ACTIVATED,
296: url, href, el, target);
297: }
298: else
299: {
300: ev = new HyperlinkEvent(editor, HyperlinkEvent.EventType.ACTIVATED,
301: url, href, el);
302: }
303: return ev;
304: }
305: }
306:
307:
315: public static class InsertHTMLTextAction
316: extends HTMLTextAction
317: {
318:
319:
322: protected HTML.Tag addTag;
323:
324:
328: protected HTML.Tag alternateAddTag;
329:
330:
333: protected HTML.Tag alternateParentTag;
334:
335:
338: protected String html;
339:
340:
343: protected HTML.Tag parentTag;
344:
345:
353: public InsertHTMLTextAction(String name, String html,
354: HTML.Tag parentTag, HTML.Tag addTag)
355: {
356: this(name, html, parentTag, addTag, null, null);
357: }
358:
359:
369: public InsertHTMLTextAction(String name, String html, HTML.Tag parentTag,
370: HTML.Tag addTag, HTML.Tag alternateParentTag,
371: HTML.Tag alternateAddTag)
372: {
373: super(name);
374:
375:
376: this.html = html;
377: this.parentTag = parentTag;
378: this.addTag = addTag;
379: this.alternateParentTag = alternateParentTag;
380: this.alternateAddTag = alternateAddTag;
381: }
382:
383:
403: protected void insertHTML(JEditorPane editor, HTMLDocument doc, int offset,
404: String html, int popDepth, int pushDepth,
405: HTML.Tag addTag)
406: {
407: try
408: {
409: super.getHTMLEditorKit(editor).insertHTML(doc, offset, html,
410: popDepth, pushDepth, addTag);
411: }
412: catch (IOException e)
413: {
414: throw (RuntimeException) new RuntimeException("Parser is null.").initCause(e);
415: }
416: catch (BadLocationException ex)
417: {
418: throw (RuntimeException) new RuntimeException("BadLocationException: "
419: + offset).initCause(ex);
420: }
421: }
422:
423:
443: protected void insertAtBoundary(JEditorPane editor,
444: HTMLDocument doc, int offset,
445: Element insertElement,
446: String html, HTML.Tag parentTag,
447: HTML.Tag addTag)
448: {
449: insertAtBoundry(editor, doc, offset, insertElement,
450: html, parentTag, addTag);
451: }
452:
453:
470: protected void insertAtBoundry(JEditorPane editor,
471: HTMLDocument doc,
472: int offset, Element insertElement,
473: String html, HTML.Tag parentTag,
474: HTML.Tag addTag)
475: {
476: Element parent = insertElement;
477: Element el;
478:
479: if (offset > 0 || insertElement == null)
480: {
481: el = doc.getDefaultRootElement();
482: while (el != null && el.getStartOffset() != offset
483: && ! el.isLeaf())
484: el = el.getElement(el.getElementIndex(offset));
485: parent = el != null ? el.getParentElement() : null;
486: }
487: if (parent != null)
488: {
489: int pops = 0;
490: int pushes = 0;
491: if (offset == 0 && insertElement != null)
492: {
493: el = parent;
494: while (el != null && ! el.isLeaf())
495: {
496: el = el.getElement(el.getElementIndex(offset));
497: pops++;
498: }
499: }
500: else
501: {
502: el = parent;
503: offset--;
504: while (el != null && ! el.isLeaf())
505: {
506: el = el.getElement(el.getElementIndex(offset));
507: pops++;
508: }
509: el = parent;
510: offset++;
511: while (el != null && el != insertElement)
512: {
513: el = el.getElement(el.getElementIndex(offset));
514: pushes++;
515: }
516: }
517: pops = Math.max(0, pops - 1);
518: insertHTML(editor, doc, offset, html, pops, pushes, addTag);
519: }
520: }
521:
522:
527: public void actionPerformed(ActionEvent ae)
528: {
529: JEditorPane source = getEditor(ae);
530: if (source != null)
531: {
532: HTMLDocument d = getHTMLDocument(source);
533: int offset = source.getSelectionStart();
534: int length = d.getLength();
535: boolean inserted = true;
536: if (! tryInsert(source, d, offset, parentTag, addTag))
537: {
538: inserted = tryInsert(source, d, offset, alternateParentTag,
539: alternateAddTag);
540: }
541: if (inserted)
542: adjustSelection(source, d, offset, length);
543: }
544: }
545:
546:
558: private boolean tryInsert(JEditorPane pane, HTMLDocument doc, int offset,
559: HTML.Tag tag, HTML.Tag addTag)
560: {
561: boolean inserted = false;
562: Element el = findElementMatchingTag(doc, offset, tag);
563: if (el != null && el.getStartOffset() == offset)
564: {
565: insertAtBoundary(pane, doc, offset, el, html, tag, addTag);
566: inserted = true;
567: }
568: else if (offset > 0)
569: {
570: int depth = elementCountToTag(doc, offset - 1, tag);
571: if (depth != -1)
572: {
573: insertHTML(pane, doc, offset, html, depth, 0, addTag);
574: inserted = true;
575: }
576: }
577: return inserted;
578: }
579:
580:
588: private void adjustSelection(JEditorPane pane, HTMLDocument doc,
589: int offset, int oldLen)
590: {
591: int newLen = doc.getLength();
592: if (newLen != oldLen && offset < newLen)
593: {
594: if (offset > 0)
595: {
596: String text;
597: try
598: {
599: text = doc.getText(offset - 1, 1);
600: }
601: catch (BadLocationException ex)
602: {
603: text = null;
604: }
605: if (text != null && text.length() > 0
606: && text.charAt(0) == '\n')
607: {
608: pane.select(offset, offset);
609: }
610: else
611: {
612: pane.select(offset + 1, offset + 1);
613: }
614: }
615: else
616: {
617: pane.select(1, 1);
618: }
619: }
620: }
621: }
622:
623:
626: public abstract static class HTMLTextAction
627: extends StyledEditorKit.StyledTextAction
628: {
629:
630:
633: public HTMLTextAction(String name)
634: {
635: super(name);
636: }
637:
638:
644: protected HTMLDocument getHTMLDocument(JEditorPane e)
645: {
646: Document d = e.getDocument();
647: if (d instanceof HTMLDocument)
648: return (HTMLDocument) d;
649: throw new IllegalArgumentException("Document is not a HTMLDocument.");
650: }
651:
652:
658: protected HTMLEditorKit getHTMLEditorKit(JEditorPane e)
659: {
660: EditorKit d = e.getEditorKit();
661: if (d instanceof HTMLEditorKit)
662: return (HTMLEditorKit) d;
663: throw new IllegalArgumentException("EditorKit is not a HTMLEditorKit.");
664: }
665:
666:
674: protected Element[] getElementsAt(HTMLDocument doc,
675: int offset)
676: {
677: return getElementsAt(doc.getDefaultRootElement(), offset, 0);
678: }
679:
680:
683: private Element[] getElementsAt(Element root, int offset, int depth)
684: {
685: Element[] elements = null;
686: if (root != null)
687: {
688: if (root.isLeaf())
689: {
690: elements = new Element[depth + 1];
691: elements[depth] = root;
692: return elements;
693: }
694: elements = getElementsAt(root.getElement(root.getElementIndex(offset)),
695: offset, depth + 1);
696: elements[depth] = root;
697: }
698: return elements;
699: }
700:
701:
715: protected int elementCountToTag(HTMLDocument doc,
716: int offset, HTML.Tag tag)
717: {
718: Element root = doc.getDefaultRootElement();
719: int num = -1;
720: Element next = root.getElement(root.getElementIndex(offset));
721:
722: while (!next.isLeaf())
723: {
724: num++;
725: if (next.getAttributes().
726: getAttribute(StyleConstants.NameAttribute).equals(tag))
727: return num;
728: next = next.getElement(next.getElementIndex(offset));
729: }
730: return num;
731: }
732:
733:
742: protected Element findElementMatchingTag(HTMLDocument doc,
743: int offset, HTML.Tag tag)
744: {
745: Element element = doc.getDefaultRootElement();
746: Element tagElement = null;
747:
748: while (element != null)
749: {
750: Object otag = element.getAttributes().getAttribute(
751: StyleConstants.NameAttribute);
752: if (otag instanceof HTML.Tag && otag.equals(tag))
753: tagElement = element;
754: element = element.getElement(element.getElementIndex(offset));
755: }
756:
757: return tagElement;
758: }
759: }
760:
761:
765: public static class HTMLFactory
766: implements ViewFactory
767: {
768:
769:
772: public HTMLFactory()
773: {
774:
775: }
776:
777:
786: public View create(Element element)
787: {
788: View view = null;
789: Object attr =
790: element.getAttributes().getAttribute(StyleConstants.NameAttribute);
791: if (attr instanceof HTML.Tag)
792: {
793: HTML.Tag tag = (HTML.Tag) attr;
794:
795: if (tag == HTML.Tag.IMPLIED || tag == HTML.Tag.P
796: || tag == HTML.Tag.H1 || tag == HTML.Tag.H2
797: || tag == HTML.Tag.H3 || tag == HTML.Tag.H4
798: || tag == HTML.Tag.H5 || tag == HTML.Tag.H6
799: || tag == HTML.Tag.DT)
800: view = new ParagraphView(element);
801: else if (tag == HTML.Tag.LI || tag == HTML.Tag.DL
802: || tag == HTML.Tag.DD || tag == HTML.Tag.BODY
803: || tag == HTML.Tag.HTML || tag == HTML.Tag.CENTER
804: || tag == HTML.Tag.DIV
805: || tag == HTML.Tag.BLOCKQUOTE
806: || tag == HTML.Tag.PRE
807: || tag == HTML.Tag.FORM
808:
809:
810: || tag == HTML.Tag.TD || tag == HTML.Tag.TH)
811: view = new BlockView(element, View.Y_AXIS);
812: else if (tag == HTML.Tag.TR)
813:
814: