1 7 package javax.swing.text.html; 8 9 import java.lang.reflect.Method ; 10 import java.awt.*; 11 import java.awt.event.*; 12 import java.io.*; 13 import java.net.MalformedURLException ; 14 import java.net.URL ; 15 import javax.swing.text.*; 16 import javax.swing.*; 17 import javax.swing.border.*; 18 import javax.swing.event.*; 19 import javax.swing.plaf.TextUI ; 20 import java.util.*; 21 import javax.accessibility.*; 22 import java.lang.ref.*; 23 24 145 public class HTMLEditorKit extends StyledEditorKit implements Accessible { 146 147 private JEditorPane theEditor; 148 149 153 public HTMLEditorKit() { 154 155 } 156 157 164 public String getContentType() { 165 return "text/html"; 166 } 167 168 175 public ViewFactory getViewFactory() { 176 return defaultFactory; 177 } 178 179 185 public Document createDefaultDocument() { 186 StyleSheet styles = getStyleSheet(); 187 StyleSheet ss = new StyleSheet (); 188 189 ss.addStyleSheet(styles); 190 191 HTMLDocument doc = new HTMLDocument (ss); 192 doc.setParser(getParser()); 193 doc.setAsynchronousLoadPriority(4); 194 doc.setTokenThreshold(100); 195 return doc; 196 } 197 198 216 public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { 217 218 if (doc instanceof HTMLDocument ) { 219 HTMLDocument hdoc = (HTMLDocument ) doc; 220 Parser p = getParser(); 221 if (p == null) { 222 throw new IOException("Can't load parser"); 223 } 224 if (pos > doc.getLength()) { 225 throw new BadLocationException("Invalid location", pos); 226 } 227 228 ParserCallback receiver = hdoc.getReader(pos); 229 Boolean ignoreCharset = (Boolean )doc.getProperty("IgnoreCharsetDirective"); 230 p.parse(in, receiver, (ignoreCharset == null) ? false : ignoreCharset.booleanValue()); 231 receiver.flush(); 232 } else { 233 super.read(in, doc, pos); 234 } 235 } 236 237 251 public void insertHTML(HTMLDocument doc, int offset, String html, 252 int popDepth, int pushDepth, 253 HTML.Tag insertTag) throws 254 BadLocationException, IOException { 255 Parser p = getParser(); 256 if (p == null) { 257 throw new IOException("Can't load parser"); 258 } 259 if (offset > doc.getLength()) { 260 throw new BadLocationException("Invalid location", offset); 261 } 262 263 ParserCallback receiver = doc.getReader(offset, popDepth, pushDepth, 264 insertTag); 265 Boolean ignoreCharset = (Boolean )doc.getProperty 266 ("IgnoreCharsetDirective"); 267 p.parse(new StringReader(html), receiver, (ignoreCharset == null) ? 268 false : ignoreCharset.booleanValue()); 269 receiver.flush(); 270 } 271 272 285 public void write(Writer out, Document doc, int pos, int len) 286 throws IOException, BadLocationException { 287 288 if (doc instanceof HTMLDocument ) { 289 HTMLWriter w = new HTMLWriter (out, (HTMLDocument )doc, pos, len); 290 w.write(); 291 } else if (doc instanceof StyledDocument) { 292 MinimalHTMLWriter w = new MinimalHTMLWriter (out, (StyledDocument)doc, pos, len); 293 w.write(); 294 } else { 295 super.write(out, doc, pos, len); 296 } 297 } 298 299 305 public void install(JEditorPane c) { 306 c.addMouseListener(linkHandler); 307 c.addMouseMotionListener(linkHandler); 308 c.addCaretListener(nextLinkAction); 309 super.install(c); 310 theEditor = c; 311 } 312 313 320 public void deinstall(JEditorPane c) { 321 c.removeMouseListener(linkHandler); 322 c.removeMouseMotionListener(linkHandler); 323 c.removeCaretListener(nextLinkAction); 324 super.deinstall(c); 325 theEditor = null; 326 } 327 328 332 public static final String DEFAULT_CSS = "default.css"; 333 334 344 public void setStyleSheet(StyleSheet s) { 345 defaultStyles = s; 346 } 347 348 354 public StyleSheet getStyleSheet() { 355 if (defaultStyles == null) { 356 defaultStyles = new StyleSheet (); 357 try { 358 InputStream is = HTMLEditorKit.getResourceAsStream(DEFAULT_CSS); 359 Reader r = new BufferedReader( 360 new InputStreamReader(is, "ISO-8859-1")); 361 defaultStyles.loadRules(r, null); 362 r.close(); 363 } catch (Throwable e) { 364 } 367 } 368 return defaultStyles; 369 } 370 371 381 static InputStream getResourceAsStream(String name) { 382 try { 383 return ResourceLoader.getResourceAsStream(name); 384 } catch (Throwable e) { 385 return HTMLEditorKit .class.getResourceAsStream(name); 388 } 389 } 390 391 399 public Action[] getActions() { 400 return TextAction.augmentList(super.getActions(), this.defaultActions); 401 } 402 403 412 protected void createInputAttributes(Element element, 413 MutableAttributeSet set) { 414 set.removeAttributes(set); 415 set.addAttributes(element.getAttributes()); 416 set.removeAttribute(StyleConstants.ComposedTextAttribute); 417 418 Object o = set.getAttribute(StyleConstants.NameAttribute); 419 if (o instanceof HTML.Tag ) { 420 HTML.Tag tag = (HTML.Tag )o; 421 if(tag == HTML.Tag.IMG) { 424 set.removeAttribute(HTML.Attribute.SRC); 426 set.removeAttribute(HTML.Attribute.HEIGHT); 427 set.removeAttribute(HTML.Attribute.WIDTH); 428 set.addAttribute(StyleConstants.NameAttribute, 429 HTML.Tag.CONTENT); 430 } 431 else if (tag == HTML.Tag.HR || tag == HTML.Tag.BR) { 432 set.addAttribute(StyleConstants.NameAttribute, 434 HTML.Tag.CONTENT); 435 } 436 else if (tag == HTML.Tag.COMMENT) { 437 set.addAttribute(StyleConstants.NameAttribute, 439 HTML.Tag.CONTENT); 440 set.removeAttribute(HTML.Attribute.COMMENT); 441 } 442 else if (tag == HTML.Tag.INPUT) { 443 set.addAttribute(StyleConstants.NameAttribute, 445 HTML.Tag.CONTENT); 446 set.removeAttribute(HTML.Tag.INPUT); 447 } 448 else if (tag instanceof HTML.UnknownTag ) { 449 set.addAttribute(StyleConstants.NameAttribute, 451 HTML.Tag.CONTENT); 452 set.removeAttribute(HTML.Attribute.ENDTAG); 453 } 454 } 455 } 456 457 463 public MutableAttributeSet getInputAttributes() { 464 if (input == null) { 465 input = getStyleSheet().addStyle(null, null); 466 } 467 return input; 468 } 469 470 475 public void setDefaultCursor(Cursor cursor) { 476 defaultCursor = cursor; 477 } 478 479 484 public Cursor getDefaultCursor() { 485 return defaultCursor; 486 } 487 488 493 public void setLinkCursor(Cursor cursor) { 494 linkCursor = cursor; 495 } 496 497 500 public Cursor getLinkCursor() { 501 return linkCursor; 502 } 503 504 514 public boolean isAutoFormSubmission() { 515 return isAutoFormSubmission; 516 } 517 518 527 public void setAutoFormSubmission(boolean isAuto) { 528 isAutoFormSubmission = isAuto; 529 } 530 531 536 public Object clone() { 537 HTMLEditorKit o = (HTMLEditorKit )super.clone(); 538 if (o != null) { 539 o.input = null; 540 o.linkHandler = new LinkController(); 541 } 542 return o; 543 } 544 545 553 protected Parser getParser() { 554 if (defaultParser == null) { 555 try { 556 Class c = Class.forName("javax.swing.text.html.parser.ParserDelegator"); 557 defaultParser = (Parser) c.newInstance(); 558 } catch (Throwable e) { 559 } 560 } 561 return defaultParser; 562 } 563 564 private AccessibleContext accessibleContext; 566 567 573 public AccessibleContext getAccessibleContext() { 574 if (theEditor == null) { 575 return null; 576 } 577 if (accessibleContext == null) { 578 AccessibleHTML a = new AccessibleHTML (theEditor); 579 accessibleContext = a.getAccessibleContext(); 580 } 581 return accessibleContext; 582 } 583 584 586 private static final Cursor MoveCursor = Cursor.getPredefinedCursor 587 (Cursor.HAND_CURSOR); 588 private static final Cursor DefaultCursor = Cursor.getPredefinedCursor 589 (Cursor.DEFAULT_CURSOR); 590 591 592 private static final ViewFactory defaultFactory = new HTMLFactory(); 593 594 MutableAttributeSet input; 595 private static StyleSheet defaultStyles = null; 596 private LinkController linkHandler = new LinkController(); 597 private static Parser defaultParser = null; 598 private Cursor defaultCursor = DefaultCursor; 599 private Cursor linkCursor = MoveCursor; 600 private boolean isAutoFormSubmission = true; 601 602 606 public static class LinkController extends MouseAdapter implements MouseMotionListener, Serializable { 607 private Element curElem = null; 608 611 private boolean curElemImage = false; 612 private String href = null; 613 615 private Position.Bias[] bias = new Position.Bias[1]; 616 619 private int curOffset; 620 621 630 public void mouseClicked(MouseEvent e) { 631 JEditorPane editor = (JEditorPane) e.getSource(); 632 633 if (! editor.isEditable() && SwingUtilities.isLeftMouseButton(e)) { 634 Point pt = new Point(e.getX(), e.getY()); 635 int pos = editor.viewToModel(pt); 636 if (pos >= 0) { 637 activateLink(pos, editor, e.getX(), e.getY()); 638 } 639 } 640 } 641 642 public void mouseDragged(MouseEvent e) { 644 } 645 646 public void mouseMoved(MouseEvent e) { 648 JEditorPane editor = (JEditorPane) e.getSource(); 649 HTMLEditorKit kit = (HTMLEditorKit )editor.getEditorKit(); 650 boolean adjustCursor = true; 651 Cursor newCursor = kit.getDefaultCursor(); 652 if (!editor.isEditable()) { 653 Point pt = new Point(e.getX(), e.getY()); 654 int pos = editor.getUI().viewToModel(editor, pt, bias); 655 if (bias[0] == Position.Bias.Backward && pos > 0) { 656 pos--; 657 } 658 if (pos >= 0 &&(editor.getDocument() instanceof HTMLDocument )){ 659 HTMLDocument hdoc = (HTMLDocument )editor.getDocument(); 660 Element elem = hdoc.getCharacterElement(pos); 661 if (!doesElementContainLocation(editor, elem, pos, 662 e.getX(), e.getY())) { 663 elem = null; 664 } 665 if (curElem != elem || curElemImage) { 666 Element lastElem = curElem; 667 curElem = elem; 668 String href = null; 669 curElemImage = false; 670 if (elem != null) { 671 AttributeSet a = elem.getAttributes(); 672 AttributeSet anchor = (AttributeSet)a. 673 getAttribute(HTML.Tag.A); 674 if (anchor == null) { 675 curElemImage = (a.getAttribute(StyleConstants. 676 NameAttribute) == HTML.Tag.IMG); 677 if (curElemImage) { 678 href = getMapHREF(editor, hdoc, elem, a, 679 pos, e.getX(), e.getY()); 680 } 681 } 682 else { 683 href = (String )anchor.getAttribute 684 (HTML.Attribute.HREF); 685 } 686 } 687 688 if (href != this.href) { 689 fireEvents(editor, hdoc, href, lastElem); 691 this.href = href; 692 if (href != null) { 693 newCursor = kit.getLinkCursor(); 694 } 695 } 696 else { 697 adjustCursor = false; 698 } 699 } 700 else { 701 adjustCursor = false; 702 } 703 curOffset = pos; 704 } 705 } 706 if (adjustCursor && editor.getCursor() != newCursor) { 707 editor.setCursor(newCursor); 708 } 709 } 710 711 715 private String getMapHREF(JEditorPane html, HTMLDocument hdoc, 716 Element elem, AttributeSet attr, int offset, 717 int x, int y) { 718 Object useMap = attr.getAttribute(HTML.Attribute.USEMAP); 719 if (useMap != null && (useMap instanceof String )) { 720 Map m = hdoc.getMap((String )useMap); 721 if (m != null && offset < hdoc.getLength()) { 722 Rectangle bounds; 723 TextUI ui = html.getUI(); 724 try { 725 Shape lBounds = ui.modelToView(html, offset, 726 Position.Bias.Forward); 727 Shape rBounds = ui.modelToView(html, offset + 1, 728 Position.Bias.Backward); 729 bounds = lBounds.getBounds(); 730 bounds.add((rBounds instanceof Rectangle) ? 731 (Rectangle)rBounds : rBounds.getBounds()); 732 } catch (BadLocationException ble) { 733 bounds = null; 734 } 735 if (bounds != null) { 736 AttributeSet area = m.getArea(x - bounds.x, 737 y - bounds.y, 738 bounds.width, 739 bounds.height); 740 if (area != null) { 741 return (String )area.getAttribute(HTML.Attribute. 742 HREF); 743 } 744 } 745 } 746 } 747 return null; 748 } 749 750 755 private boolean doesElementContainLocation(JEditorPane editor, 756 Element e, int offset, 757 int x, int y) { 758 if (e != null && offset > 0 && e.getStartOffset() == offset) { 759 try { 760 TextUI ui = editor.getUI(); 761 Shape s1 = ui.modelToView(editor, offset, 762 Position.Bias.Forward); 763 if (s1 == null) { 764 return false; 765 } 766 Rectangle r1 = (s1 instanceof Rectangle) ? (Rectangle)s1 : 767 s1.getBounds(); 768 Shape s2 = ui.modelToView(editor, e.getEndOffset(), 769 Position.Bias.Backward); 770 if (s2 != null) { 771 Rectangle r2 = (s2 instanceof Rectangle) ? (Rectangle)s2 : 772 s2.getBounds(); 773 r1.add(r2); 774 } 775 return r1.contains(x, y); 776 } catch (BadLocationException ble) { 777 } 778 } 779 return true; 780 } 781 782 791 protected void activateLink(int pos, JEditorPane editor) { 792 activateLink(pos, editor, -1, -1); 793 } 794 795 805 void activateLink(int pos, JEditorPane html, int x, int y) { 806 Document doc = html.getDocument(); 807 if (doc instanceof HTMLDocument ) { 808 HTMLDocument hdoc = (HTMLDocument ) doc; 809 Element e = hdoc.getCharacterElement(pos); 810 AttributeSet a = e.getAttributes(); 811 AttributeSet anchor = (AttributeSet)a.getAttribute(HTML.Tag.A); 812 HyperlinkEvent linkEvent = null; 813 String description; 814 815 if (anchor == null) { 816 href = getMapHREF(html, hdoc, e, a, pos, x, y); 817 } 818 else { 819 href = (String )anchor.getAttribute(HTML.Attribute.HREF); 820 } 821 822 if (href != null) { 823 linkEvent = createHyperlinkEvent(html, hdoc, href, anchor, 824 e); 825 } 826 if (linkEvent != null) { 827 html.fireHyperlinkUpdate(linkEvent); 828 } 829 } 830 } 831 832 837 HyperlinkEvent createHyperlinkEvent(JEditorPane html, 838 HTMLDocument hdoc, String href, 839 AttributeSet anchor, 840 Element element) { 841 URL u; 842 try { 843 URL base = hdoc.getBase(); 844 u = new URL (base, href); 845 if (href != null && "file".equals(u.getProtocol()) && 849 href.startsWith("#")) { 850 String baseFile = base.getFile(); 851 String newFile = u.getFile(); 852 if (baseFile != null && newFile != null && 853 !newFile.startsWith(baseFile)) { 854 u = new URL (base, baseFile + href); 855 } 856 } 857 } catch (MalformedURLException m) { 858 u = null; 859 } 860 HyperlinkEvent linkEvent = null; 861 862 if (!hdoc.isFrameDocument()) { 863 linkEvent = new HyperlinkEvent(html, HyperlinkEvent.EventType. 864 ACTIVATED, u, href, element); 865 } else { 866 String target = (anchor != null) ? 867 (String )anchor.getAttribute(HTML.Attribute.TARGET) : null; 868 if ((target == null) || (target.equals(""))) { 869 target = hdoc.getBaseTarget(); 870 } 871 if ((target == null) || (target.equals(""))) { 872 target = "_self"; 873 } 874 linkEvent = new HTMLFrameHyperlinkEvent (html, HyperlinkEvent. 875 EventType.ACTIVATED, u, href, element, target); 876 } 877 return linkEvent; 878 } 879 880 void fireEvents(JEditorPane editor, HTMLDocument doc, String href, 881 Element lastElem) { 882 if (this.href != null) { 883 URL u; 885 try { 886 u = new URL (doc.getBase(), this.href); 887 } catch (MalformedURLException m) { 888 u = null; 889 } 890 HyperlinkEvent exit = new HyperlinkEvent(editor, 891 HyperlinkEvent.EventType.EXITED, u, this.href, 892 lastElem); 893 editor.fireHyperlinkUpdate(exit); 894 } 895 if (href != null) { 896 URL u; 898 try { 899 u = new URL (doc.getBase(), href); 900 } catch (MalformedURLException m) { 901 u = null; 902 } 903 HyperlinkEvent entered = new HyperlinkEvent(editor, 904 HyperlinkEvent.EventType.ENTERED, 905 u, href, curElem); 906 editor.fireHyperlinkUpdate(entered); 907 } 908 } 909 } 910 911 916 public static abstract class Parser { 917 922 public abstract void parse(Reader r, ParserCallback cb, boolean ignoreCharSet) throws IOException; 923 924 } 925 926 938 public static class ParserCallback { 939 946 public static final Object IMPLIED = "_implied_"; 947 948 949 public void flush() throws BadLocationException { 950 } 951 952 public void handleText(char[] data, int pos) { 953 } 954 955 public void handleComment(char[] data, int pos) { 956 } 957 958 public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) { 959 } 960 961 public void handleEndTag(HTML.Tag t, int pos) { 962 } 963 964 public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) { 965 } 966 967 public void handleError(String errorMsg, int pos){ 968 } 969 970 978 public void handleEndOfLineString(String eol) { 979 } 980 } 981 982 1063 public static class HTMLFactory implements ViewFactory { 1064 1065 1071 public View create(Element elem) { 1072 Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute); 1073 if (o instanceof HTML.Tag ) { 1074 HTML.Tag kind = (HTML.Tag ) o; 1075 if (kind == HTML.Tag.CONTENT) { 1076 return new InlineView (elem); 1077 } else if (kind == HTML.Tag.IMPLIED) { 1078 String ws = (String ) elem.getAttributes().getAttribute( 1079 CSS.Attribute.WHITE_SPACE); 1080 if ((ws != null) && ws.equals("pre")) { 1081 return new LineView (elem); 1082 } 1083 return new javax.swing.text.html.ParagraphView (elem); 1084 } else if ((kind == HTML.Tag.P) || 1085 (kind == HTML.Tag.H1) || 1086 (kind == HTML.Tag.H2) || 1087 (kind == HTML.Tag.H3) || 1088 (kind == HTML.Tag.H4) || 1089 (kind == HTML.Tag.H5) || 1090 (kind == HTML.Tag.H6) || 1091 (kind == HTML.Tag.DT)) { 1092 return new javax.swing.text.html.ParagraphView (elem); 1094 } else if ((kind == HTML.Tag.MENU) || 1095 (kind == HTML.Tag.DIR) || 1096 (kind == HTML.Tag.UL) || 1097 (kind == HTML.Tag.OL)) { 1098 return new ListView (elem); 1099 } else if (kind == HTML.Tag.BODY) { 1100 return new BodyBlockView(elem); 1101 } else if (kind == HTML.Tag.HTML) { 1102 return new BlockView (elem, View.Y_AXIS); 1103 } else if ((kind == HTML.Tag.LI) || 1104 (kind == HTML.Tag.CENTER) || 1105 (kind == HTML.Tag.DL) || 1106 (kind == HTML.Tag.DD) || 1107 (kind == HTML.Tag.DIV) || 1108 (kind == HTML.Tag.BLOCKQUOTE) || 1109 (kind == HTML.Tag.PRE) || 1110 (kind == HTML.Tag.FORM)) { 1111 return new BlockView (elem, View.Y_AXIS); 1113 } else if (kind == HTML.Tag.NOFRAMES) { 1114 return new NoFramesView (elem, View.Y_AXIS); 1115 } else if (kind==HTML.Tag.IMG) { 1116 return new ImageView (elem); 1117 } else if (kind == HTML.Tag.ISINDEX) { 1118 return new IsindexView (elem); 1119 } else if (kind == HTML.Tag.HR) { 1120 return new HRuleView (elem); 1121 } else if (kind == HTML.Tag.BR) { 1122 return new BRView (elem); 1123 } else if (kind == HTML.Tag.TABLE) { 1124 return new javax.swing.text.html.TableView (elem); 1125 } else if ((kind == HTML.Tag.INPUT) || 1126 (kind == HTML.Tag.SELECT) || 1127 (kind == HTML.Tag.TEXTAREA)) { 1128 return new FormView (elem); 1129 } else if (kind == HTML.Tag.OBJECT) { 1130 return new ObjectView (elem); 1131 } else if (kind == HTML.Tag.FRAMESET) { 1132 if (elem.getAttributes().isDefined(HTML.Attribute.ROWS)) { 1133 return new FrameSetView (elem, View.Y_AXIS); 1134 } else if (elem.getAttributes().isDefined(HTML.Attribute.COLS)) { 1135 return new FrameSetView (elem, View.X_AXIS); 1136 } 1137 throw new RuntimeException ("Can't build a" + kind + ", " + elem + ":" + 1138 "no ROWS or COLS defined."); 1139 } else if (kind == HTML.Tag.FRAME) { 1140 return new FrameView (elem); 1141 } else if (kind instanceof HTML.UnknownTag ) { 1142 return new HiddenTagView (elem); 1143 } else if (kind == HTML.Tag.COMMENT) { 1144 return new CommentView (elem); 1145 } else if (kind == HTML.Tag.HEAD) { 1146 return new BlockView (elem, View.X_AXIS) { 1151 public float getPreferredSpan(int axis) { 1152 return 0; 1153 } 1154 public float getMinimumSpan(int axis) { 1155 return 0; 1156 } 1157 public float getMaximumSpan(int axis) { 1158 return 0; 1159 } 1160 protected void loadChildren(ViewFactory f) { 1161 } 1162 public Shape modelToView(int pos, Shape a, 1163 Position.Bias b) throws BadLocationException { 1164 return a; 1165 } 1166 public int getNextVisualPositionFrom(int pos, 1167 Position.Bias b, Shape a, 1168 int direction, Position.Bias[] biasRet) { 1169 return getElement().getEndOffset(); 1170 } 1171 }; 1172 } else if ((kind == HTML.Tag.TITLE) || 1173 (kind == HTML.Tag.META) || 1174 (kind == HTML.Tag.LINK) || 1175 (kind == HTML.Tag.STYLE) || 1176 (kind == HTML.Tag.SCRIPT) || 1177 (kind == HTML.Tag.AREA) || 1178 (kind == HTML.Tag.MAP) || 1179 (kind == HTML.Tag.PARAM) || 1180 (kind == HTML.Tag.APPLET)) { 1181 return new HiddenTagView (elem); 1182 } 1183 } 1184 String nm = elem.getName(); 1187 if (nm != null) { 1188 if (nm.equals(AbstractDocument.ContentElementName)) { 1189 return new LabelView(elem); 1190 } else if (nm.equals(AbstractDocument.ParagraphElementName)) { 1191 return new ParagraphView (elem); 1192 } else if (nm.equals(AbstractDocument.SectionElementName)) { 1193 return new BoxView(elem, View.Y_AXIS); 1194 } else if (nm.equals(StyleConstants.ComponentElementName)) { 1195 return new ComponentView(elem); 1196 } else if (nm.equals(StyleConstants.IconElementName)) { 1197 return new IconView(elem); 1198 } 1199 } 1200 1201 return new LabelView(elem); 1203 } 1204 1205 static class BodyBlockView extends BlockView implements ComponentListener { 1206 public BodyBlockView(Element elem) { 1207 super(elem,View.Y_AXIS); 1208 } 1209 protected SizeRequirements calculateMajorAxisRequirements(int axis, SizeRequirements r) { 1213 r = super.calculateMajorAxisRequirements(axis, r); 1214 r.maximum = Integer.MAX_VALUE; 1215 return r; 1216 } 1217 1218 protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { 1219 Container container = getContainer(); 1220 Container parentContainer; 1221 if (container != null 1222 && (container instanceof javax.swing.JEditorPane ) 1223 && (parentContainer = container.getParent()) != null 1224 && (parentContainer instanceof javax.swing.JViewport )) { 1225 JViewport viewPort = (JViewport)parentContainer; 1226 Object cachedObject; 1227 if (cachedViewPort != null) { 1228 if ((cachedObject = cachedViewPort.get()) != null) { 1229 if (cachedObject != viewPort) { 1230 ((JComponent)cachedObject).removeComponentListener(this); 1231 } 1232 } else { 1233 cachedViewPort = null; 1234 } 1235 } 1236 if (cachedViewPort == null) { 1237 viewPort.addComponentListener(this); 1238 cachedViewPort = new WeakReference(viewPort); 1239 } 1240 1241 componentVisibleWidth = viewPort.getExtentSize().width; 1242 if (componentVisibleWidth > 0) { 1243 Insets insets = container.getInsets(); 1244 viewVisibleWidth = componentVisibleWidth - insets.left - getLeftInset(); 1245 targetSpan = Math.min(targetSpan, viewVisibleWidth); 1247 } 1248 } else { 1249 if (cachedViewPort != null) { 1250 Object cachedObject; 1251 if ((cachedObject = cachedViewPort.get()) != null) { 1252 ((JComponent)cachedObject).removeComponentListener(this); 1253 } 1254 cachedViewPort = null; 1255 } 1256 } 1257 super.layoutMinorAxis(targetSpan, axis, offsets, spans); 1258 } 1259 1260 public void setParent(View parent) { 1261 if (parent == null) { 1263 if (cachedViewPort != null) { 1264 Object cachedObject; 1265 if ((cachedObject = cachedViewPort.get()) != null) { 1266 ((JComponent)cachedObject).removeComponentListener(this); 1267 } 1268 cachedViewPort = null; 1269 } 1270 } 1271 super.setParent(parent); 1272 } 1273 1274 public void componentResized(ComponentEvent e) { 1275 if ( !(e.getSource() instanceof JViewport) ) { 1276 return; 1277 } 1278 JViewport viewPort = (JViewport)e.getSource(); 1279 if (componentVisibleWidth != viewPort.getExtentSize().width) { 1280 Document doc = getDocument(); 1281 if (doc instanceof AbstractDocument) { 1282 AbstractDocument document = (AbstractDocument)getDocument(); 1283 document.readLock(); 1284 try { 1285 layoutChanged(X_AXIS); 1286 preferenceChanged(null, true, true); 1287 } finally { 1288 document.readUnlock(); 1289 } 1290 1291 } 1292 } 1293 } 1294 public void componentHidden(ComponentEvent e) { 1295 } 1296 public void componentMoved(ComponentEvent e) { 1297 } 1298 public void componentShown(ComponentEvent e) { 1299 } 1300 1306 private Reference cachedViewPort = null; 1307 private boolean isListening = false; 1308 private int viewVisibleWidth = Integer.MAX_VALUE; 1309 private int componentVisibleWidth = Integer.MAX_VALUE; 1310 } 1311 1312 } 1313 1314 1316 1318 public static final String BOLD_ACTION = "html-bold-action"; 1319 1321 public static final String ITALIC_ACTION = "html-italic-action"; 1322 1324 public static final String PARA_INDENT_LEFT = "html-para-indent-left"; 1325 1327 public static final String PARA_INDENT_RIGHT = "html-para-indent-right"; 1328 1330 public static final String FONT_CHANGE_BIGGER = "html-font-bigger"; 1331 1333 public static final String FONT_CHANGE_SMALLER = "html-font-smaller"; 1334 1337 public static final String COLOR_ACTION = "html-color-action"; 1338 1341 public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action"; 1342 1345 public static final String IMG_ALIGN_TOP = "html-image-align-top"; 1346 1347 1350 public static final String IMG_ALIGN_MIDDLE = "html-image-align-middle"; 1351 1352 1355 public static final String IMG_ALIGN_BOTTOM = "html-image-align-bottom"; 1356 1357 1360 public static final String IMG_BORDER = "html-image-border"; 1361 1362 1363 1364 private static final String INSERT_TABLE_HTML = "<table border=1><tr><td></td></tr></table>"; 1365 1366 1367 private static final String INSERT_UL_HTML = "<ul><li></li></ul>"; 1368 1369 1370 private static final String INSERT_OL_HTML = "<ol><li></li></ol>"; 1371 1372 1373 private static final String INSERT_HR_HTML = "<hr>"; 1374 1375 1376 private static final String INSERT_PRE_HTML = "<pre></pre>"; 1377 1378 private static NavigateLinkAction nextLinkAction = 1379 new NavigateLinkAction("next-link-action"); 1380 1381 private static NavigateLinkAction previousLinkAction = 1382 new NavigateLinkAction("previous-link-action"); 1383 1384 private static ActivateLinkAction activateLinkAction = 1385 new ActivateLinkAction("activate-link-action"); 1386 1387 private static final Action[] defaultActions = { 1388 new InsertHTMLTextAction("InsertTable", INSERT_TABLE_HTML, 1389 HTML.Tag.BODY, HTML.Tag.TABLE), 1390 new InsertHTMLTextAction("InsertTableRow", INSERT_TABLE_HTML, 1391 HTML.Tag.TABLE, HTML.Tag.TR, 1392 HTML.Tag.BODY, HTML.Tag.TABLE), 1393 new InsertHTMLTextAction("InsertTableDataCell", INSERT_TABLE_HTML, 1394 HTML.Tag.TR, HTML.Tag.TD, 1395 HTML.Tag.BODY, HTML.Tag.TABLE), 1396 new InsertHTMLTextAction("InsertUnorderedList", INSERT_UL_HTML, 1397 HTML.Tag.BODY, HTML.Tag.UL), 1398 new InsertHTMLTextAction("InsertUnorderedListItem", INSERT_UL_HTML, 1399 HTML.Tag.UL, HTML.Tag.LI, 1400 HTML.Tag.BODY, HTML.Tag.UL), 1401 new InsertHTMLTextAction("InsertOrderedList", INSERT_OL_HTML, 1402 HTML.Tag.BODY, HTML.Tag.OL), 1403 new InsertHTMLTextAction("InsertOrderedListItem", INSERT_OL_HTML, 1404 HTML.Tag.OL, HTML.Tag.LI, 1405 HTML.Tag.BODY, HTML.Tag.OL), 1406 new InsertHRAction(), 1407 new InsertHTMLTextAction("InsertPre", INSERT_PRE_HTML, 1408 HTML.Tag.BODY, HTML.Tag.PRE), 1409 nextLinkAction, previousLinkAction, activateLinkAction 1410 }; 1411 1412 1413 1420 public static abstract class HTMLTextAction extends StyledTextAction { 1421 public HTMLTextAction(String name) { 1422 super(name); 1423 } 1424 1425 1428 protected HTMLDocument getHTMLDocument(JEditorPane e) { 1429 Document d = e.getDocument(); 1430 if (d instanceof HTMLDocument ) { 1431 return (HTMLDocument ) d; 1432 } 1433 throw new IllegalArgumentException ("document must be HTMLDocument"); 1434 } 1435 1436 1439 protected HTMLEditorKit getHTMLEditorKit(JEditorPane e) { 1440 EditorKit k = e.getEditorKit(); 1441 if (k instanceof HTMLEditorKit ) { 1442 return (HTMLEditorKit ) k; 1443 } 1444 throw new IllegalArgumentException ("EditorKit must be HTMLEditorKit"); 1445 } 1446 1447 1451 protected Element[] getElementsAt(HTMLDocument doc, int offset) { 1452 return getElementsAt(doc.getDefaultRootElement(), offset, 0); 1453 } 1454 1455 1458 private Element[] getElementsAt(Element parent, int offset, 1459 int depth) { 1460 if (parent.isLeaf()) { 1461 Element[] retValue = new Element[depth + 1]; 1462 retValue[depth] = parent; 1463 return retValue; 1464 } 1465 Element[] retValue = getElementsAt(parent.getElement 1466 (parent.getElementIndex(offset)), offset, depth + 1); 1467 retValue[depth] = parent; 1468 return retValue; 1469 } 1470 1471 1478 protected int elementCountToTag(HTMLDocument doc, int offset, 1479 HTML.Tag tag) { 1480 int depth = -1; 1481 Element e = doc.getCharacterElement(offset); 1482 while (e != null && e.getAttributes().getAttribute 1483 (StyleConstants.NameAttribute) != tag) { 1484 e = e.getParentElement(); 1485 depth++; 1486 } 1487 if (e == null) { 1488 return -1; 1489 } 1490 return depth; 1491 } 1492 1493 1497 protected Element findElementMatchingTag(HTMLDocument doc, int offset, 1498 HTML.Tag tag) { 1499 Element e = doc.getDefaultRootElement(); 1500 Element lastMatch = null; 1501 while (e != null) { 1502 if (e.getAttributes().getAttribute 1503 (StyleConstants.NameAttribute) == tag) { 1504 lastMatch = e; 1505 } 1506 e = e.getElement(e.getElementIndex(offset)); 1507 } 1508 return lastMatch; 1509 } 1510 } 1511 1512 1513 1530 public static class InsertHTMLTextAction extends HTMLTextAction { 1531 public InsertHTMLTextAction(String name, String html, 1532 HTML.Tag parentTag, HTML.Tag addTag) { 1533 this(name, html, parentTag, addTag, null, null); 1534 } 1535 1536 public InsertHTMLTextAction(String name, String html, 1537 HTML.Tag parentTag, 1538 HTML.Tag addTag, 1539 HTML.Tag alternateParentTag, 1540 HTML.Tag alternateAddTag) { 1541 this(name, html, parentTag, addTag, alternateParentTag, 1542 alternateAddTag, true); 1543 } 1544 1545 1546 InsertHTMLTextAction(String name, String html, 1547 HTML.Tag parentTag, 1548 HTML.Tag addTag, 1549 HTML.Tag alternateParentTag, 1550 HTML.Tag alternateAddTag, 1551 boolean adjustSelection) { 1552 super(name); 1553 this.html = html; 1554 this.parentTag = parentTag; 1555 this.addTag = addTag; 1556 this.alternateParentTag = alternateParentTag; 1557 this.alternateAddTag = alternateAddTag; 1558 this.adjustSelection = adjustSelection; 1559 } 1560 1561 1565 protected void insertHTML(JEditorPane editor, HTMLDocument doc, 1566 int offset, String html, int popDepth, 1567 int pushDepth, HTML.Tag addTag) { 1568 try { 1569 getHTMLEditorKit(editor).insertHTML(doc, offset, html, 1570 popDepth, pushDepth, 1571 addTag); 1572 } catch (IOException ioe) { 1573 throw new RuntimeException ("Unable to insert: " + ioe); 1574 } catch (BadLocationException ble) { 1575 throw new RuntimeException ("Unable to insert: " + ble); 1576 } 1577 } 1578 1579 1585 protected void insertAtBoundary(JEditorPane editor, HTMLDocument doc, 1586 int offset, Element insertElement, 1587 String html, HTML.Tag parentTag, 1588 HTML.Tag addTag) { 1589 insertAtBoundry(editor, doc, offset, insertElement, html, 1590 parentTag, addTag); 1591 } 1592 1593 1599 @Deprecated 1600 protected void insertAtBoundry(JEditorPane editor, HTMLDocument doc, 1601 int offset, Element insertElement, 1602 String html, HTML.Tag parentTag, 1603 HTML.Tag addTag) { 1604 Element e; 1606 Element commonParent; 1607 boolean isFirst = (offset == 0); 1608 1609 if (offset > 0 || insertElement == null) { 1610 e = doc.getDefaultRootElement(); 1611 while (e != null && e.getStartOffset() != offset && 1612 !e.isLeaf()) { 1613 e = e.getElement(e.getElementIndex(offset)); 1614 } 1615 commonParent = (e != null) ? e.getParentElement() : null; 1616 } 1617 else { 1618 commonParent = insertElement; 1621 } 1622 if (commonParent != null) { 1623 int pops = 0; 1625 int pushes = 0; 1626 if (isFirst && insertElement != null) { 1627 e = commonParent; 1628 while (e != null && !e.isLeaf()) { 1629 e = e.getElement(e.getElementIndex(offset)); 1630 pops++; 1631 } 1632 } 1633 else { 1634 e = commonParent; 1635 offset--; 1636 while (e != null && !e.isLeaf()) { 1637 e = e.getElement(e.getElementIndex(offset)); 1638 pops++; 1639 } 1640 1641 e = commonParent; 1643 offset++; 1644 while (e != null && e != insertElement) { 1645 e = e.getElement(e.getElementIndex(offset)); 1646 pushes++; 1647 } 1648 } 1649 pops = Math.max(0, pops - 1); 1650 1651 insertHTML(editor, doc, offset, html, pops, pushes, addTag); 1653 } 1654 } 1655 1656 1662 1663 boolean insertIntoTag(JEditorPane editor, HTMLDocument doc, 1664 int offset, HTML.Tag tag, HTML.Tag addTag) { 1665 Element e = findElementMatchingTag(doc, offset, tag); 1666 if (e != null && e.getStartOffset() == offset) { 1667 insertAtBoundary(editor, doc, offset, e, html, 1668 tag, addTag); 1669 return true; 1670 } 1671 else if (offset > 0) { 1672 int depth = elementCountToTag(doc, offset - 1, tag); 1673 if (depth != -1) { 1674 insertHTML(editor, doc, offset, html, depth, 0, addTag); 1675 return true; 1676 } 1677 } 1678 return false; 1679 } 1680 1681 1684 1685 void adjustSelection(JEditorPane pane, HTMLDocument doc, 1686 int startOffset, int oldLength) { 1687 int newLength = doc.getLength(); 1688 if (newLength != oldLength && startOffset < newLength) { 1689 if (startOffset > 0) { 1690 String text; 1691 try { 1692 text = doc.getText(startOffset - 1, 1); 1693 } catch (BadLocationException ble) { 1694 text = null; 1695 } 1696 if (text != null && text.length() > 0 && 1697 text.charAt(0) == '\n') { 1698 pane.select(startOffset, startOffset); 1699 } 1700 else { 1701 pane.select(startOffset + 1, startOffset + 1); 1702 } 1703 } 1704 else { 1705 pane.select(1, 1); 1706 } 1707 } 1708 } 1709 1710 1715 public void actionPerformed(ActionEvent ae) { 1716 JEditorPane editor = getEditor(ae); 1717 if (editor != null) { 1718 HTMLDocument doc = getHTMLDocument(editor); 1719 int offset = editor.getSelectionStart(); 1720 int length = doc.getLength(); 1721 boolean inserted; 1722 if (!insertIntoTag(editor, doc, offset, parentTag, addTag) && 1724 alternateParentTag != null) { 1725 inserted = insertIntoTag(editor, doc, offset, 1727 alternateParentTag, 1728 alternateAddTag); 1729 } 1730 else { 1731 inserted = true; 1732 } 1733 if (adjustSelection && inserted) { 1734 adjustSelection(editor, doc, offset, length); 1735 } 1736 } 1737 } 1738 1739 1740 protected String html; 1741 1742 protected HTML.Tag parentTag; 1743 1744 protected HTML.Tag addTag; 1745 1747 protected HTML.Tag alternateParentTag; 1748 1750 protected HTML.Tag alternateAddTag; 1751 1752 boolean adjustSelection; 1753 } 1754 1755 1756 1761 static class InsertHRAction extends InsertHTMLTextAction { 1762 InsertHRAction() { 1763 super("InsertHR", "<hr>", null, HTML.Tag.IMPLIED, null, null, 1764 false); 1765 } 1766 1767 1772 public void actionPerformed(ActionEvent ae) { 1773 JEditorPane editor = getEditor(ae); 1774 if (editor != null) { 1775 HTMLDocument doc = getHTMLDocument(editor); 1776 int offset = editor.getSelectionStart(); 1777 Element paragraph = doc.getParagraphElement(offset); 1778 if (paragraph.getParentElement() != null) { 1779 parentTag = (HTML.Tag )paragraph.getParentElement(). 1780 getAttributes().getAttribute 1781 (StyleConstants.NameAttribute); 1782 super.actionPerformed(ae); 1783 } 1784 } 1785 } 1786 1787 } 1788 1789 1792 static private Object getAttrValue(AttributeSet attr, HTML.Attribute key) { 1793 Enumeration names = attr.getAttributeNames(); 1794 while (names.hasMoreElements()) { 1795 Object nextKey = names.nextElement(); 1796 Object nextVal = attr.getAttribute(nextKey); 1797 if (nextVal instanceof AttributeSet) { 1798 Object value = getAttrValue((AttributeSet)nextVal, key); 1799 if (value != null) { 1800 return value; 1801 } 1802 } else if (nextKey == key) { 1803 return nextVal; 1804 } 1805 } 1806 return null; 1807 } 1808 1809 1815 static class NavigateLinkAction extends TextAction 1816 implements CaretListener { 1817 1818 private static int prevHypertextOffset = -1; 1819 private static boolean foundLink = false; 1820 private FocusHighlightPainter focusPainter = 1821 new FocusHighlightPainter(null); 1822 private Object selectionTag; 1823 private boolean focusBack = false; 1824 1825 1828 public NavigateLinkAction(String actionName) { 1829 super(actionName); 1830 if ("previous-link-action".equals(actionName)) { 1831 focusBack = true; 1832 } 1833 } 1834 1835 1840 public void caretUpdate(CaretEvent e) { 1841 if (foundLink) { 1842 foundLink = false; 1843 Object src = e.getSource(); 1847 if (src instanceof JTextComponent) { 1848 ((JTextComponent)src).getAccessibleContext().firePropertyChange( 1849 AccessibleContext.ACCESSIBLE_HYPERTEXT_OFFSET, 1850 new Integer (prevHypertextOffset), 1851 new Integer (e.getDot())); 1852 } 1853 } 1854 } 1855 1856 1859 public void actionPerformed(ActionEvent e) { 1860 JTextComponent comp = getTextComponent(e); 1861 if (comp == null || comp.isEditable()) { 1862 return; 1863 } 1864 Document doc = comp.getDocument(); 1865 if (doc == null) { 1866 return; 1867 } 1868 ElementIterator ei = new ElementIterator(doc); 1871 1872 int currentOffset = comp.getCaretPosition(); 1873 int prevStartOffset = -1; 1874 int prevEndOffset = -1; 1875 1876 Element nextElement = null; 1878 while ((nextElement = ei.next()) != null) { 1879 String name = nextElement.getName(); 1880 AttributeSet attr = nextElement.getAttributes(); 1881 1882 Object href = getAttrValue(attr, HTML.Attribute.HREF); 1883 if (!(name.equals(HTML.Tag.OBJECT.toString())) && href == null) { 1884 continue; 1885 } 1886 1887 int elementOffset = nextElement.getStartOffset(); 1888 if (focusBack) { 1889 if (elementOffset >= currentOffset && 1890 prevStartOffset >= 0) { 1891 1892 foundLink = true; 1893 comp.setCaretPosition(prevStartOffset); 1894 moveCaretPosition(comp, prevStartOffset, 1895 prevEndOffset); 1896 prevHypertextOffset = prevStartOffset; 1897 return; 1898 } 1899 } else { if (elementOffset > currentOffset) { 1901 1902 foundLink = true; 1903 comp.setCaretPosition(elementOffset); 1904 moveCaretPosition(comp, elementOffset, 1905 nextElement.getEndOffset()); 1906 prevHypertextOffset = elementOffset; 1907 return; 1908 } 1909 } 1910 prevStartOffset = nextElement.getStartOffset(); 1911 prevEndOffset = nextElement.getEndOffset(); 1912 } 1913 if (focusBack && prevStartOffset >= 0) { 1914 foundLink = true; 1915 comp.setCaretPosition(prevStartOffset); 1916 moveCaretPosition(comp, prevStartOffset, 1917 prevEndOffset); 1918 prevHypertextOffset = prevStartOffset; 1919 return; 1920 } 1921 } 1922 1923 1926 private void moveCaretPosition(JTextComponent comp, int mark, int dot) { 1927 Highlighter h = comp.getHighlighter(); 1928 if (h != null) { 1929 int p0 = Math.min(dot, mark); 1930 int p1 = Math.max(dot, mark); 1931 try { 1932 if (selectionTag != null) { 1933 h.changeHighlight(selectionTag, p0, p1); 1934 } else { 1935 Highlighter.HighlightPainter p = focusPainter; 1936 selectionTag = h.addHighlight(p0, p1, p); 1937 } 1938 } catch (BadLocationException e) { 1939 } 1940 } 1941 } 1942 1943 1947 class FocusHighlightPainter extends 1948 DefaultHighlighter.DefaultHighlightPainter { 1949 1950 FocusHighlightPainter(Color color) { 1951 super(color); 1952 } 1953 1954 1966 public Shape paintLayer(Graphics g, int offs0, int offs1, 1967 Shape bounds, JTextComponent c, View view) { 1968 1969 Color color = getColor(); 1970 1971 if (color == null) { 1972 g.setColor(c.getSelectionColor()); 1973 } 1974 else { 1975 g.setColor(color); 1976 } 1977 if (offs0 == view.getStartOffset() && 1978 offs1 == view.getEndOffset()) { 1979 Rectangle alloc; 1981 if (bounds instanceof Rectangle) { 1982 alloc = (Rectangle)bounds; 1983 } 1984 else { 1985 alloc = bounds.getBounds(); 1986 } 1987 g.drawRect(alloc.x, alloc.y, alloc.width - 1, alloc.height); 1988 return alloc; 1989 } 1990 else { 1991 try { 1993 Shape shape = view.modelToView(offs0, Position.Bias.Forward, 1995 offs1,Position.Bias.Backward, 1996 bounds); 1997 Rectangle r = (shape instanceof Rectangle) ? 1998 (Rectangle)shape : shape.getBounds(); 1999 g.drawRect(r.x, r.y, r.width - 1, r.height); 2000 return r; 2001 } catch (BadLocationException e) { 2002 } 2004 } 2005 return null; 2007 } 2008 } 2009 } 2010 2011 2017 static class ActivateLinkAction extends TextAction { 2018 2019 2022 public ActivateLinkAction(String actionName) { 2023 super(actionName); 2024 } 2025 2026 2029 private void activateLink(String href, HTMLDocument doc, 2030 JEditorPane editor, int offset) { 2031 try { 2032 URL page = 2033 (URL )doc.getProperty(Document.StreamDescriptionProperty); 2034 URL url = new URL (page, href); 2035 HyperlinkEvent linkEvent = new HyperlinkEvent 2036 (editor, HyperlinkEvent.EventType. 2037 ACTIVATED, url, url.toExternalForm(), 2038 doc.getCharacterElement(offset)); 2039 editor.fireHyperlinkUpdate(linkEvent); 2040 } catch (MalformedURLException m) { 2041 } 2042 } 2043 2044 2047 private void doObjectAction(JEditorPane editor, Element elem) { 2048 View view = getView(editor, elem); 2049 if (view != null && view instanceof ObjectView ) { 2050 Component comp = ((ObjectView )view).getComponent(); 2051 if (comp != null && comp instanceof Accessible) { 2052 AccessibleContext ac = ((Accessible)comp).getAccessibleContext(); 2053 if (ac != null) { 2054 AccessibleAction aa = ac.getAccessibleAction(); 2055 if (aa != null) { 2056 aa.doAccessibleAction(0); 2057 } 2058 } 2059 } 2060 } 2061 } 2062 2063 2066 private View getRootView(JEditorPane editor) { 2067 return editor.getUI().getRootView(editor); 2068 } 2069 2070 2073 private View getView(JEditorPane editor, Element elem) { 2074 Object lock = lock(editor); 2075 try { 2076 View rootView = getRootView(editor); 2077 int start = elem.getStartOffset(); 2078 if (rootView != null) { 2079 return getView(rootView, elem, start); 2080 } 2081 return null; 2082 } finally { 2083 unlock(lock); 2084 } 2085 } 2086 2087 private View getView(View parent, Element elem, int start) { 2088 if (parent.getElement() == elem) { 2089 return parent; 2090 } 2091 int index = parent.getViewIndex(start, Position.Bias.Forward); 2092 2093 if (index != -1 && index < parent.getViewCount()) { 2094 return getView(parent.getView(index), elem, start); 2095 } 2096 return null; 2097 } 2098 2099 2104 private Object lock(JEditorPane editor) { 2105 Document document = editor.getDocument(); 2106 2107 if (document instanceof AbstractDocument) { 2108 ((AbstractDocument)document).readLock(); 2109 return document; 2110 } 2111 return null; 2112 } 2113 2114 2117 private void unlock(Object key) { 2118 if (key != null) { 2119 ((AbstractDocument)key).readUnlock(); 2120 } 2121 } 2122 2123 2126 public void actionPerformed(ActionEvent e) { 2127 2128 JTextComponent c = getTextComponent(e); 2129 if (c.isEditable() || !(c instanceof JEditorPane)) { 2130 return; 2131 } 2132 JEditorPane editor = (JEditorPane)c; 2133 2134 Document d = editor.getDocument(); 2135 if (d == null || !(d instanceof HTMLDocument )) { 2136 return; 2137 } 2138 HTMLDocument doc = (HTMLDocument )d; 2139 2140 ElementIterator ei = new ElementIterator(doc); 2141 int currentOffset = editor.getCaretPosition(); 2142 2143 String urlString = null; 2145 String objString = null; 2146 Element currentElement = null; 2147 while ((currentElement = ei.next()) != null) { 2148 String name = currentElement.getName(); 2149 AttributeSet attr = currentElement.getAttributes(); 2150 2151 Object href = getAttrValue(attr, HTML.Attribute.HREF); 2152 if (href != null) { 2153 if (currentOffset >= currentElement.getStartOffset() && 2154 currentOffset <= currentElement.getEndOffset()) { 2155 2156 activateLink((String )href, doc, editor, currentOffset); 2157 return; 2158 } 2159 } else if (name.equals(HTML.Tag.OBJECT.toString())) { 2160 Object obj = getAttrValue(attr, HTML.Attribute.CLASSID); 2161 if (obj != null) { 2162 if (currentOffset >= currentElement.getStartOffset() && 2163 currentOffset <= currentElement.getEndOffset()) { 2164 2165 doObjectAction(editor, currentElement); 2166 return; 2167 } 2168 } 2169 } 2170 } 2171 } 2172 } 2173} 2174 | Popular Tags |