1 /* HTMLDocument.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.text.html;
41 import gnu.classpath.NotImplementedException;
43 import java.io.IOException;
44 import java.io.StringReader;
45 import java.net.MalformedURLException;
47 import java.util.ArrayList;
48 import java.util.HashMap;
49 import java.util.Stack;
50 import java.util.Vector;
52 import javax.swing.ButtonGroup;
53 import javax.swing.DefaultButtonModel;
54 import javax.swing.JEditorPane;
55 import javax.swing.ListSelectionModel;
56 import javax.swing.event.DocumentEvent;
57 import javax.swing.event.UndoableEditEvent;
58 import javax.swing.text.AbstractDocument;
59 import javax.swing.text.AttributeSet;
60 import javax.swing.text.BadLocationException;
61 import javax.swing.text.DefaultStyledDocument;
62 import javax.swing.text.Element;
63 import javax.swing.text.ElementIterator;
64 import javax.swing.text.GapContent;
65 import javax.swing.text.MutableAttributeSet;
66 import javax.swing.text.PlainDocument;
67 import javax.swing.text.SimpleAttributeSet;
68 import javax.swing.text.StyleConstants;
69 import javax.swing.text.html.HTML.Tag;
72 * Represents the HTML document that is constructed by defining the text and
73 * other components (images, buttons, etc) in HTML language. This class can
74 * becomes the default document for {@link JEditorPane} after setting its
75 * content type to "text/html". HTML document also serves as an intermediate
76 * data structure when it is needed to parse HTML and then obtain the content of
77 * the certain types of tags. This class also has methods for modifying the HTML
80 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
81 * @author Anthony Balkissoon (abalkiss@redhat.com)
82 * @author Lillian Angel (langel@redhat.com)
84 public class HTMLDocument extends DefaultStyledDocument
86 /** A key for document properies. The value for the key is
87 * a Vector of Strings of comments not found in the body.
89 public static final String AdditionalComments = "AdditionalComments";
91 boolean preservesUnknownTags = true;
92 int tokenThreshold = Integer.MAX_VALUE;
93 HTMLEditorKit.Parser parser;
96 * Indicates whether this document is inside a frame or not.
98 private boolean frameDocument;
101 * Package private to avoid accessor methods.
106 * Constructs an HTML document using the default buffer size and a default
109 public HTMLDocument()
111 this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleSheet());
115 * Constructs an HTML document with the default content storage
116 * implementation and the specified style/attribute storage mechanism.
118 * @param styles - the style sheet
120 public HTMLDocument(StyleSheet styles)
122 this(new GapContent(BUFFER_SIZE_DEFAULT), styles);
126 * Constructs an HTML document with the given content storage implementation
127 * and the given style/attribute storage mechanism.
129 * @param c - the document's content
130 * @param styles - the style sheet
132 public HTMLDocument(AbstractDocument.Content c, StyleSheet styles)
138 * Gets the style sheet with the document display rules (CSS) that were specified
139 * in the HTML document.
141 * @return - the style sheet
143 public StyleSheet getStyleSheet()
145 return (StyleSheet) getAttributeContext();
149 * This method creates a root element for the new document.
151 * @return the new default root
153 protected AbstractElement createDefaultRoot()
155 AbstractDocument.AttributeContext ctx = getAttributeContext();
157 // Create html element.
158 AttributeSet atts = ctx.getEmptySet();
159 atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.HTML);
160 BranchElement html = (BranchElement) createBranchElement(null, atts);
162 // Create body element.
163 atts = ctx.getEmptySet();
164 atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.BODY);
165 BranchElement body = (BranchElement) createBranchElement(html, atts);
166 html.replace(0, 0, new Element[] { body });
169 atts = ctx.getEmptySet();
170 atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.P);
171 BranchElement p = (BranchElement) createBranchElement(body, atts);
172 body.replace(0, 0, new Element[] { p });
174 // Create an empty leaf element.
175 atts = ctx.getEmptySet();
176 atts = ctx.addAttribute(atts, StyleConstants.NameAttribute,
178 Element leaf = createLeafElement(p, atts, 0, 1);
179 p.replace(0, 0, new Element[]{ leaf });
185 * This method returns an HTMLDocument.RunElement object attached to
186 * parent representing a run of text from p0 to p1. The run has
187 * attributes described by a.
189 * @param parent - the parent element
190 * @param a - the attributes for the element
191 * @param p0 - the beginning of the range >= 0
192 * @param p1 - the end of the range >= p0
194 * @return the new element
196 protected Element createLeafElement(Element parent, AttributeSet a, int p0,
199 return new RunElement(parent, a, p0, p1);
203 * This method returns an HTMLDocument.BlockElement object representing the
204 * attribute set a and attached to parent.
206 * @param parent - the parent element
207 * @param a - the attributes for the element
209 * @return the new element
211 protected Element createBranchElement(Element parent, AttributeSet a)
213 return new BlockElement(parent, a);
217 * Returns the parser used by this HTMLDocument to insert HTML.
219 * @return the parser used by this HTMLDocument to insert HTML.
221 public HTMLEditorKit.Parser getParser()
227 * Sets the parser used by this HTMLDocument to insert HTML.
229 * @param p the parser to use
231 public void setParser (HTMLEditorKit.Parser p)
236 * Sets the number of tokens to buffer before trying to display the
239 * @param n the number of tokens to buffer
241 public void setTokenThreshold (int n)
247 * Returns the number of tokens that are buffered before the document
250 * @return the number of tokens buffered
252 public int getTokenThreshold ()
254 return tokenThreshold;
258 * Returns the location against which to resolve relative URLs.
259 * This is the document's URL if the document was loaded from a URL.
260 * If a <code>base</code> tag is found, it will be used.
261 * @return the base URL
269 * Sets the location against which to resolve relative URLs.
270 * @param u the new base URL
272 public void setBase(URL u)
275 getStyleSheet().setBase(u);
279 * Returns whether or not the parser preserves unknown HTML tags.
280 * @return true if the parser preserves unknown tags
282 public boolean getPreservesUnknownTags()
284 return preservesUnknownTags;
288 * Sets the behaviour of the parser when it encounters unknown HTML tags.
289 * @param preservesTags true if the parser should preserve unknown tags.
291 public void setPreservesUnknownTags(boolean preservesTags)
293 preservesUnknownTags = preservesTags;
297 * An iterator to iterate through LeafElements in the document.
299 class LeafIterator extends Iterator
305 public LeafIterator (HTML.Tag t, HTMLDocument d)
309 it = new ElementIterator(doc);
313 * Return the attributes for the tag associated with this iteartor
314 * @return the AttributeSet
316 public AttributeSet getAttributes()
318 if (it.current() != null)
319 return it.current().getAttributes();
324 * Get the end of the range for the current occurrence of the tag
325 * being defined and having the same attributes.
326 * @return the end of the range
328 public int getEndOffset()
330 if (it.current() != null)
331 return it.current().getEndOffset();
336 * Get the start of the range for the current occurrence of the tag
337 * being defined and having the same attributes.
338 * @return the start of the range (-1 if it can't be found).
341 public int getStartOffset()
343 if (it.current() != null)
344 return it.current().getStartOffset();
349 * Advance the iterator to the next LeafElement .
354 while (it.current()!= null && !it.current().isLeaf())
359 * Indicates whether or not the iterator currently represents an occurrence
361 * @return true if the iterator currently represents an occurrence of the
364 public boolean isValid()
366 return it.current() != null;
370 * Type of tag for this iterator.
379 public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event)
381 String target = event.getTarget();
382 Element el = event.getSourceElement();
383 URL url = event.getURL();
384 if (target.equals("_self"))
386 updateFrame(el, url);
388 else if (target.equals("_parent"))
390 updateFrameSet(el.getParentElement(), url);
394 Element targetFrame = findFrame(target);
395 if (targetFrame != null)
396 updateFrame(targetFrame, url);
401 * Finds the named frame inside this document.
403 * @param target the name to look for
405 * @return the frame if there is a matching frame, <code>null</code>
408 private Element findFrame(String target)
410 ElementIterator i = new ElementIterator(this);
412 while ((next = i.next()) != null)
414 AttributeSet atts = next.getAttributes();
415 if (atts.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.FRAME)
417 String name = (String) atts.getAttribute(HTML.Attribute.NAME);
418 if (name != null && name.equals(target))
426 * Updates the frame that is represented by the specified element to
427 * refer to the specified URL.
429 * @param el the element
430 * @param url the new url
432 private void updateFrame(Element el, URL url)
437 DefaultDocumentEvent ev =
438 new DefaultDocumentEvent(el.getStartOffset(), 1,
439 DocumentEvent.EventType.CHANGE);
440 AttributeSet elAtts = el.getAttributes();
441 AttributeSet copy = elAtts.copyAttributes();
442 MutableAttributeSet matts = (MutableAttributeSet) elAtts;
443 ev.addEdit(new AttributeUndoableEdit(el, copy, false));
444 matts.removeAttribute(HTML.Attribute.SRC);
445 matts.addAttribute(HTML.Attribute.SRC, url.toString());
447 fireChangedUpdate(ev);
448 fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
457 * Updates the frameset that is represented by the specified element
458 * to create a frame that refers to the specified URL.
460 * @param el the element
463 private void updateFrameSet(Element el, URL url)
465 int start = el.getStartOffset();
466 int end = el.getEndOffset();
468 StringBuilder html = new StringBuilder();
469 html.append("<frame");
472 html.append(" src=\"");
473 html.append(url.toString());
477 if (getParser() == null)
478 setParser(new HTMLEditorKit().getParser());
481 setOuterHTML(el, html.toString());
483 catch (BadLocationException ex)
485 ex.printStackTrace();
487 catch (IOException ex)
489 ex.printStackTrace();
494 * Gets an iterator for the given HTML.Tag.
495 * @param t the requested HTML.Tag
496 * @return the Iterator
498 public HTMLDocument.Iterator getIterator (HTML.Tag t)
500 return new HTMLDocument.LeafIterator(t, this);
504 * An iterator over a particular type of tag.
506 public abstract static class Iterator
509 * Return the attribute set for this tag.
510 * @return the <code>AttributeSet</code> (null if none found).
512 public abstract AttributeSet getAttributes();
515 * Get the end of the range for the current occurrence of the tag
516 * being defined and having the same attributes.
517 * @return the end of the range
519 public abstract int getEndOffset();
522 * Get the start of the range for the current occurrence of the tag
523 * being defined and having the same attributes.
524 * @return the start of the range (-1 if it can't be found).
526 public abstract int getStartOffset();
529 * Move the iterator forward.
531 public abstract void next();
534 * Indicates whether or not the iterator currently represents an occurrence
536 * @return true if the iterator currently represents an occurrence of the
539 public abstract boolean isValid();
542 * Type of tag this iterator represents.
545 public abstract HTML.Tag getTag();
548 public class BlockElement extends AbstractDocument.BranchElement
550 public BlockElement (Element parent, AttributeSet a)
556 * Gets the resolving parent. Since HTML attributes are not
557 * inherited at the model level, this returns null.
559 public AttributeSet getResolveParent()
565 * Gets the name of the element.
567 * @return the name of the element if it exists, null otherwise.
569 public String getName()
571 Object tag = getAttribute(StyleConstants.NameAttribute);
574 name = tag.toString();
576 name = super.getName();
582 * RunElement represents a section of text that has a set of
583 * HTML character level attributes assigned to it.
585 public class RunElement extends AbstractDocument.LeafElement
589 * Constructs an element that has no children. It represents content
590 * within the document.
592 * @param parent - parent of this
593 * @param a - elements attributes
594 * @param start - the start offset >= 0
595 * @param end - the end offset
597 public RunElement(Element parent, AttributeSet a, int start, int end)
599 super(parent, a, start, end);
603 * Gets the name of the element.
605 * @return the name of the element if it exists, null otherwise.
607 public String getName()
609 Object tag = getAttribute(StyleConstants.NameAttribute);
612 name = tag.toString();
614 name = super.getName();
619 * Gets the resolving parent. HTML attributes do not inherit at the
620 * model level, so this method returns null.
624 public AttributeSet getResolveParent()
631 * A reader to load an HTMLDocument with HTML structure.
633 * @author Anthony Balkissoon abalkiss at redhat dot com
635 public class HTMLReader extends HTMLEditorKit.ParserCallback
638 * The maximum token threshold. We don't grow it larger than this.
640 private static final int MAX_THRESHOLD = 10000;
643 * The threshold growth factor.
645 private static final int GROW_THRESHOLD = 5;
648 * Holds the current character attribute set *
650 protected MutableAttributeSet charAttr = new SimpleAttributeSet();
652 protected Vector<ElementSpec> parseBuffer = new Vector<ElementSpec>();
655 * The parse stack. It holds the current element tree path.
657 private Stack<HTML.Tag> parseStack = new Stack<HTML.Tag>();
660 * A stack for character attribute sets *
662 Stack charAttrStack = new Stack();
664 /** A mapping between HTML.Tag objects and the actions that handle them **/
667 /** Tells us whether we've received the '</html>' tag yet **/
668 boolean endHTMLEncountered = false;
671 * Related to the constructor with explicit insertTag
676 * Related to the constructor with explicit insertTag
681 * Related to the constructor with explicit insertTag
686 * The tag (inclusve), after that the insertion should start.
691 * This variable becomes true after the insert tag has been encountered.
693 boolean insertTagEncountered;
696 /** A temporary variable that helps with the printing out of debug information **/
697 boolean debug = false;
700 * This is true when we are inside a pre tag.
702 boolean inPreTag = false;
705 * This is true when we are inside a style tag. This will add text
706 * content inside this style tag beeing parsed as CSS.
708 * This is package private to avoid accessor methods.
710 boolean inStyleTag = false;
713 * This is true when we are inside a <textarea> tag. Any text
714 * content will then be added to the text area.
716 * This is package private to avoid accessor methods.
718 boolean inTextArea = false;
721 * This contains all stylesheets that are somehow read, either
722 * via embedded style tags, or via linked stylesheets. The
723 * elements will be String objects containing a stylesheet each.
728 * The document model for a textarea.
730 * This is package private to avoid accessor methods.
732 ResetablePlainDocument textAreaDocument;
735 * The current model of a select tag. Can be a ComboBoxModel or a
736 * ListModel depending on the type of the select box.
741 * The current option beeing read.
746 * The current number of options in the current select model.
751 * The current button groups mappings.
753 HashMap buttonGroups;
756 * The token threshold. This gets increased while loading.
758 private int threshold;
760 public class TagAction
763 * This method is called when a start tag is seen for one of the types
764 * of tags associated with this Action. By default this does nothing.
766 public void start(HTML.Tag t, MutableAttributeSet a)
768 // Nothing to do here.
772 * Called when an end tag is seen for one of the types of tags associated
773 * with this Action. By default does nothing.
775 public void end(HTML.Tag t)
777 // Nothing to do here.
781 public class BlockAction extends TagAction
784 * This method is called when a start tag is seen for one of the types
785 * of tags associated with this Action.
787 public void start(HTML.Tag t, MutableAttributeSet a)
789 // Tell the parse buffer to open a new block for this tag.
794 * Called when an end tag is seen for one of the types of tags associated
797 public void end(HTML.Tag t)
799 // Tell the parse buffer to close this block.
804 public class CharacterAction extends TagAction
807 * This method is called when a start tag is seen for one of the types
808 * of tags associated with this Action.
810 public void start(HTML.Tag t, MutableAttributeSet a)
812 // Put the old attribute set on the stack.
813 pushCharacterStyle();
815 // Initialize with link pseudo class.
817 a.addAttribute(HTML.Attribute.PSEUDO_CLASS, "link");
819 // Just add the attributes in <code>a</code>.
820 charAttr.addAttribute(t, a.copyAttributes());
824 * Called when an end tag is seen for one of the types of tags associated
827 public void end(HTML.Tag t)
834 * Processes elements that make up forms: <input>, <textarea>,
835 * <select> and <option>.
837 public class FormAction extends SpecialAction
840 * This method is called when a start tag is seen for one of the types
841 * of tags associated with this Action.
843 public void start(HTML.Tag t, MutableAttributeSet a)
845 if (t == HTML.Tag.INPUT)
847 String type = (String) a.getAttribute(HTML.Attribute.TYPE);
850 type = "text"; // Default to 'text' when nothing was specified.
851 a.addAttribute(HTML.Attribute.TYPE, type);
855 else if (t == HTML.Tag.TEXTAREA)
858 textAreaDocument = new ResetablePlainDocument();
859 a.addAttribute(StyleConstants.ModelAttribute, textAreaDocument);
861 else if (t == HTML.Tag.SELECT)
863 int size = HTML.getIntegerAttributeValue(a, HTML.Attribute.SIZE,
865 boolean multi = a.getAttribute(HTML.Attribute.MULTIPLE) != null;
866 if (size > 1 || multi)
868 SelectListModel m = new SelectListModel();
870 m.getSelectionModel().setSelectionMode(ListSelectionModel
871 .MULTIPLE_INTERVAL_SELECTION);
876 selectModel = new SelectComboBoxModel();
878 a.addAttribute(StyleConstants.ModelAttribute, selectModel);
880 if (t == HTML.Tag.OPTION)
882 option = new Option(a);
883 if (selectModel instanceof SelectListModel)
885 SelectListModel m = (SelectListModel) selectModel;
886 m.addElement(option);
887 if (option.isSelected())
889 m.getSelectionModel().addSelectionInterval(numOptions,
891 m.addInitialSelection(numOptions);
894 else if (selectModel instanceof SelectComboBoxModel)
896 SelectComboBoxModel m = (SelectComboBoxModel) selectModel;
897 m.addElement(option);
898 if (option.isSelected())
900 m.setSelectedItem(option);
901 m.setInitialSelection(option);
908 // Build the element.
914 * Called when an end tag is seen for one of the types of tags associated
917 public void end(HTML.Tag t)
919 if (t == HTML.Tag.OPTION)
925 if (t == HTML.Tag.TEXTAREA)
929 else if (t == HTML.Tag.SELECT)
934 // Finish the element.
939 private void setModel(String type, MutableAttributeSet attrs)
941 if (type.equals("submit") || type.equals("reset")
942 || type.equals("image"))
945 attrs.addAttribute(StyleConstants.ModelAttribute,
946 new DefaultButtonModel());
948 else if (type.equals("text") || type.equals("password"))
950 String text = (String) attrs.getAttribute(HTML.Attribute.VALUE);
951 ResetablePlainDocument doc = new ResetablePlainDocument();
954 doc.setInitialText(text);
957 doc.insertString(0, text, null);
959 catch (BadLocationException ex)
965 attrs.addAttribute(StyleConstants.ModelAttribute, doc);
967 else if (type.equals("file"))
969 attrs.addAttribute(StyleConstants.ModelAttribute,
970 new PlainDocument());
972 else if (type.equals("checkbox") || type.equals("radio"))
974 ResetableToggleButtonModel model =
975 new ResetableToggleButtonModel();
976 if (attrs.getAttribute(HTML.Attribute.SELECTED) != null)
978 model.setSelected(true);
979 model.setInitial(true);
981 if (type.equals("radio"))
983 String name = (String) attrs.getAttribute(HTML.Attribute.NAME);
986 if (buttonGroups == null)
987 buttonGroups = new HashMap();
988 ButtonGroup group = (ButtonGroup) buttonGroups.get(name);
991 group = new ButtonGroup();
992 buttonGroups.put(name, group);
994 model.setGroup(group);
997 attrs.addAttribute(StyleConstants.ModelAttribute, model);
1003 * Called for form tags.
1009 * Clears the button group mapping.
1011 public void end(HTML.Tag t)
1014 buttonGroups = null;
1019 * This action indicates that the content between starting and closing HTML
1020 * elements (like script - /script) should not be visible. The content is
1021 * still inserted and can be accessed when iterating the HTML document. The
1022 * parser will only fire
1023 * {@link javax.swing.text.html.HTMLEditorKit.ParserCallback#handleText} for
1024 * the hidden tags, regardless from that html tags the hidden section may
1027 public class HiddenAction
1031 * This method is called when a start tag is seen for one of the types
1032 * of tags associated with this Action.
1034 public void start(HTML.Tag t, MutableAttributeSet a)
1040 * Called when an end tag is seen for one of the types of tags associated
1043 public void end(HTML.Tag t)
1050 * Handles <isindex> tags.
1052 public class IsindexAction extends TagAction
1055 * This method is called when a start tag is seen for one of the types
1056 * of tags associated with this Action.
1058 public void start(HTML.Tag t, MutableAttributeSet a)
1060 blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1061 addSpecialElement(t, a);
1062 blockClose(HTML.Tag.IMPLIED);
1066 public class ParagraphAction extends BlockAction
1069 * This method is called when a start tag is seen for one of the types
1070 * of tags associated with this Action.
1072 public void start(HTML.Tag t, MutableAttributeSet a)
1078 * Called when an end tag is seen for one of the types of tags associated
1081 public void end(HTML.Tag t)
1088 * This action is performed when a <pre> tag is parsed.
1090 public class PreAction extends BlockAction
1093 * This method is called when a start tag is seen for one of the types
1094 * of tags associated with this Action.
1096 public void start(HTML.Tag t, MutableAttributeSet a)
1100 a.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
1101 blockOpen(HTML.Tag.IMPLIED, a);
1105 * Called when an end tag is seen for one of the types of tags associated
1108 public void end(HTML.Tag t)
1110 blockClose(HTML.Tag.IMPLIED);
1117 * Inserts the elements that are represented by ths single tag with
1118 * attributes (only). The closing tag, even if present, mut follow
1119 * immediately after the starting tag without providing any additional
1120 * information. Hence the {@link TagAction#end} method need not be
1121 * overridden and still does nothing.
1123 public class SpecialAction extends TagAction
1126 * The functionality is delegated to {@link HTMLReader#addSpecialElement}
1128 public void start(HTML.Tag t, MutableAttributeSet a)
1130 addSpecialElement(t, a);
1134 class AreaAction extends TagAction
1137 * This method is called when a start tag is seen for one of the types
1138 * of tags associated with this Action.
1140 public void start(HTML.Tag t, MutableAttributeSet a)
1141 throws NotImplementedException
1143 // FIXME: Implement.
1147 * Called when an end tag is seen for one of the types of tags associated
1150 public void end(HTML.Tag t)
1151 throws NotImplementedException
1153 // FIXME: Implement.
1158 * Converts HTML tags to CSS attributes.
1164 public void start(HTML.Tag tag, MutableAttributeSet atts)
1166 pushCharacterStyle();
1167 charAttr.addAttribute(tag, atts.copyAttributes());
1168 StyleSheet styleSheet = getStyleSheet();
1169 // TODO: Add other tags here.
1170 if (tag == HTML.Tag.FONT)
1172 String color = (String) atts.getAttribute(HTML.Attribute.COLOR);
1174 styleSheet.addCSSAttribute(charAttr, CSS.Attribute.COLOR, color);
1175 String face = (String) atts.getAttribute(HTML.Attribute.FACE);
1177 styleSheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_FAMILY,
1179 String size = (String) atts.getAttribute(HTML.Attribute.SIZE);
1181 styleSheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_SIZE,
1186 public void end(HTML.Tag tag)
1188 popCharacterStyle();
1192 class BaseAction extends TagAction
1195 * This method is called when a start tag is seen for one of the types
1196 * of tags associated with this Action.
1198 public void start(HTML.Tag t, MutableAttributeSet a)
1200 baseTarget = (String) a.getAttribute(HTML.Attribute.TARGET);
1204 class HeadAction extends BlockAction
1207 * This method is called when a start tag is seen for one of the types
1208 * of tags associated with this Action.
1210 public void start(HTML.Tag t, MutableAttributeSet a)
1211 throws NotImplementedException
1213 // FIXME: Implement.
1218 * Called when an end tag is seen for one of the types of tags associated
1221 public void end(HTML.Tag t)
1223 // We read in all the stylesheets that are embedded or referenced
1224 // inside the header.
1227 int numStyles = styles.size();
1228 for (int i = 0; i < numStyles; i++)
1230 String style = (String) styles.get(i);
1231 getStyleSheet().addRule(style);
1238 class LinkAction extends HiddenAction
1241 * This method is called when a start tag is seen for one of the types
1242 * of tags associated with this Action.
1244 public void start(HTML.Tag t, MutableAttributeSet a)
1247 String type = (String) a.getAttribute(HTML.Attribute.TYPE);
1250 if (type.equals("text/css"))
1252 String rel = (String) a.getAttribute(HTML.Attribute.REL);
1253 String media = (String) a.getAttribute(HTML.Attribute.MEDIA);
1254 String title = (String) a.getAttribute(HTML.Attribute.TITLE);
1258 media = media.toLowerCase();
1261 rel = rel.toLowerCase();
1262 if ((media.indexOf("all") != -1
1263 || media.indexOf("screen") != -1)
1264 && (rel.equals("stylesheet")))
1266 String href = (String) a.getAttribute(HTML.Attribute.HREF);
1270 url = new URL(baseURL, href);
1272 catch (MalformedURLException ex)
1276 url = new URL(href);
1278 catch (MalformedURLException ex2)
1287 getStyleSheet().importStyleSheet(url);
1289 catch (Exception ex)
1291 // Don't let exceptions and runtime exceptions
1292 // in CSS parsing disprupt the HTML parsing
1293 // process. But inform the user/developer
1294 // on the console about it.
1295 ex.printStackTrace();
1305 class MapAction extends TagAction
1308 * This method is called when a start tag is seen for one of the types
1309 * of tags associated with this Action.
1311 public void start(HTML.Tag t, MutableAttributeSet a)
1312 throws NotImplementedException
1314 // FIXME: Implement.
1318 * Called when an end tag is seen for one of the types of tags associated
1321 public void end(HTML.Tag t)
1322 throws NotImplementedException
1324 // FIXME: Implement.
1328 class MetaAction extends TagAction
1331 * This method is called when a start tag is seen for one of the types
1332 * of tags associated with this Action.
1334 public void start(HTML.Tag t, MutableAttributeSet a)
1335 throws NotImplementedException
1337 // FIXME: Implement.
1341 * Called when an end tag is seen for one of the types of tags associated
1344 public void end(HTML.Tag t)
1345 throws NotImplementedException
1347 // FIXME: Implement.
1351 class StyleAction extends TagAction
1354 * This method is called when a start tag is seen for one of the types
1355 * of tags associated with this Action.
1357 public void start(HTML.Tag t, MutableAttributeSet a)
1363 * Called when an end tag is seen for one of the types of tags associated
1366 public void end(HTML.Tag t)
1372 class TitleAction extends TagAction
1375 * This method is called when a start tag is seen for one of the types
1376 * of tags associated with this Action.
1378 public void start(HTML.Tag t, MutableAttributeSet a)
1379 throws NotImplementedException
1381 // FIXME: Implement.
1385 * Called when an end tag is seen for one of the types of tags associated
1388 public void end(HTML.Tag t)
1389 throws NotImplementedException
1391 // FIXME: Implement.
1395 public HTMLReader(int offset)
1397 this (offset, 0, 0, null);
1400 public HTMLReader(int offset, int popDepth, int pushDepth,
1403 this.insertTag = insertTag;
1404 this.offset = offset;
1405 this.popDepth = popDepth;
1406 this.pushDepth = pushDepth;
1407 threshold = getTokenThreshold();
1413 tagToAction = new HashMap(72);
1414 CharacterAction characterAction = new CharacterAction();
1415 HiddenAction hiddenAction = new HiddenAction();
1416 AreaAction areaAction = new AreaAction();
1417 BaseAction baseAction = new BaseAction();
1418 BlockAction blockAction = new BlockAction();
1419 SpecialAction specialAction = new SpecialAction();
1420 ParagraphAction paragraphAction = new ParagraphAction();
1421 HeadAction headAction = new HeadAction();
1422 FormAction formAction = new FormAction();
1423 IsindexAction isindexAction = new IsindexAction();
1424 LinkAction linkAction = new LinkAction();
1425 MapAction mapAction = new MapAction();
1426 PreAction preAction = new PreAction();
1427 MetaAction metaAction = new MetaAction();
1428 StyleAction styleAction = new StyleAction();
1429 TitleAction titleAction = new TitleAction();
1431 ConvertAction convertAction = new ConvertAction();
1432 tagToAction.put(HTML.Tag.A, characterAction);
1433 tagToAction.put(HTML.Tag.ADDRESS, characterAction);
1434 tagToAction.put(HTML.Tag.APPLET, hiddenAction);
1435 tagToAction.put(HTML.Tag.AREA, areaAction);
1436 tagToAction.put(HTML.Tag.B, characterAction);
1437 tagToAction.put(HTML.Tag.BASE, baseAction);
1438 tagToAction.put(HTML.Tag.BASEFONT, characterAction);
1439 tagToAction.put(HTML.Tag.BIG, characterAction);
1440 tagToAction.put(HTML.Tag.BLOCKQUOTE, blockAction);
1441 tagToAction.put(HTML.Tag.BODY, blockAction);
1442 tagToAction.put(HTML.Tag.BR, specialAction);
1443 tagToAction.put(HTML.Tag.CAPTION, blockAction);
1444 tagToAction.put(HTML.Tag.CENTER, blockAction);
1445 tagToAction.put(HTML.Tag.CITE, characterAction);
1446 tagToAction.put(HTML.Tag.CODE, characterAction);
1447 tagToAction.put(HTML.Tag.DD, blockAction);
1448 tagToAction.put(HTML.Tag.DFN, characterAction);
1449 tagToAction.put(HTML.Tag.DIR, blockAction);
1450 tagToAction.put(HTML.Tag.DIV, blockAction);
1451 tagToAction.put(HTML.Tag.DL, blockAction);
1452 tagToAction.put(HTML.Tag.DT, paragraphAction);
1453 tagToAction.put(HTML.Tag.EM, characterAction);
1454 tagToAction.put(HTML.Tag.FONT, convertAction);
1455 tagToAction.put(HTML.Tag.FORM, new FormTagAction());
1456 tagToAction.put(HTML.Tag.FRAME, specialAction);
1457 tagToAction.put(HTML.Tag.FRAMESET, blockAction);
1458 tagToAction.put(HTML.Tag.H1, paragraphAction);
1459 tagToAction.put(HTML.Tag.H2, paragraphAction);
1460 tagToAction.put(HTML.Tag.H3, paragraphAction);
1461 tagToAction.put(HTML.Tag.H4, paragraphAction);
1462 tagToAction.put(HTML.Tag.H5, paragraphAction);
1463 tagToAction.put(HTML.Tag.H6, paragraphAction);
1464 tagToAction.put(HTML.Tag.HEAD, headAction);
1465 tagToAction.put(HTML.Tag.HR, specialAction);
1466 tagToAction.put(HTML.Tag.HTML, blockAction);
1467 tagToAction.put(HTML.Tag.I, characterAction);
1468 tagToAction.put(HTML.Tag.IMG, specialAction);
1469 tagToAction.put(HTML.Tag.INPUT, formAction);
1470 tagToAction.put(HTML.Tag.ISINDEX, isindexAction);
1471 tagToAction.put(HTML.Tag.KBD, characterAction);
1472 tagToAction.put(HTML.Tag.LI, blockAction);
1473 tagToAction.put(HTML.Tag.LINK, linkAction);
1474 tagToAction.put(HTML.Tag.MAP, mapAction);
1475 tagToAction.put(HTML.Tag.MENU, blockAction);
1476 tagToAction.put(HTML.Tag.META, metaAction);
1477 tagToAction.put(HTML.Tag.NOFRAMES, blockAction);
1478 tagToAction.put(HTML.Tag.OBJECT, specialAction);
1479 tagToAction.put(HTML.Tag.OL, blockAction);
1480 tagToAction.put(HTML.Tag.OPTION, formAction);
1481 tagToAction.put(HTML.Tag.P, paragraphAction);
1482 tagToAction.put(HTML.Tag.PARAM, hiddenAction);
1483 tagToAction.put(HTML.Tag.PRE, preAction);
1484 tagToAction.put(HTML.Tag.SAMP, characterAction);
1485 tagToAction.put(HTML.Tag.SCRIPT, hiddenAction);
1486 tagToAction.put(HTML.Tag.SELECT, formAction);
1487 tagToAction.put(HTML.Tag.SMALL, characterAction);
1488 tagToAction.put(HTML.Tag.STRIKE, characterAction);
1489 tagToAction.put(HTML.Tag.S, characterAction);
1490 tagToAction.put(HTML.Tag.STRONG, characterAction);
1491 tagToAction.put(HTML.Tag.STYLE, styleAction);
1492 tagToAction.put(HTML.Tag.SUB, characterAction);
1493 tagToAction.put(HTML.Tag.SUP, characterAction);
1494 tagToAction.put(HTML.Tag.TABLE, blockAction);
1495 tagToAction.put(HTML.Tag.TD, blockAction);
1496 tagToAction.put(HTML.Tag.TEXTAREA, formAction);
1497 tagToAction.put(HTML.Tag.TH, blockAction);
1498 tagToAction.put(HTML.Tag.TITLE, titleAction);
1499 tagToAction.put(HTML.Tag.TR, blockAction);
1500 tagToAction.put(HTML.Tag.TT, characterAction);
1501 tagToAction.put(HTML.Tag.U, characterAction);
1502 tagToAction.put(HTML.Tag.UL, blockAction);
1503 tagToAction.put(HTML.Tag.VAR, characterAction);
1507 * Pushes the current character style onto the stack.
1510 protected void pushCharacterStyle()
1512 charAttrStack.push(charAttr.copyAttributes());
1516 * Pops a character style off of the stack and uses it as the
1517 * current character style.
1520 protected void popCharacterStyle()
1522 if (!charAttrStack.isEmpty())
1523 charAttr = (MutableAttributeSet) charAttrStack.pop();
1527 * Registers a given tag with a given Action. All of the well-known tags
1528 * are registered by default, but this method can change their behaviour
1529 * or add support for custom or currently unsupported tags.
1531 * @param t the Tag to register
1532 * @param a the Action for the Tag
1534 protected void registerTag(HTML.Tag t, HTMLDocument.HTMLReader.TagAction a)
1536 tagToAction.put (t, a);
1540 * This is the last method called on the HTMLReader, allowing any pending
1541 * changes to be flushed to the HTMLDocument.
1543 public void flush() throws BadLocationException
1549 * Flushes the buffer and handle partial inserts.
1552 private void flushImpl()
1553 throws BadLocationException
1555 int oldLen = getLength();
1556 int size = parseBuffer.size();
1557 ElementSpec[] elems = new ElementSpec[size];
1558 parseBuffer.copyInto(elems);
1562 insert(offset, elems);
1563 parseBuffer.removeAllElements();
1564 offset += getLength() - oldLen;
1568 * This method is called by the parser to indicate a block of
1569 * text was encountered. Should insert the text appropriately.
1571 * @param data the text that was inserted
1572 * @param pos the position at which the text was inserted
1574 public void handleText(char[] data, int pos)
1576 if (shouldInsert() && data != null && data.length > 0)
1579 textAreaContent(data);
1582 else if (option != null)
1583 option.setLabel(new String(data));
1584 else if (inStyleTag)
1587 styles = new ArrayList();
1588 styles.add(new String(data));
1591 addContent(data, 0, data.length);
1597 * Checks if the HTML tag should be inserted. The tags before insert tag (if
1598 * specified) are not inserted. Also, the tags after the end of the html are
1601 * @return true if the tag should be inserted, false otherwise.
1603 private boolean shouldInsert()
1605 return ! endHTMLEncountered
1606 && (insertTagEncountered || insertTag == null);
1610 * This method is called by the parser and should route the call to the
1611 * proper handler for the tag.
1613 * @param t the HTML.Tag
1614 * @param a the attribute set
1615 * @param pos the position at which the tag was encountered
1617 public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
1620 insertTagEncountered = true;
1624 TagAction action = (TagAction) tagToAction.get(t);
1631 * This method called by parser to handle a comment block.
1633 * @param data the comment
1634 * @param pos the position at which the comment was encountered
1636 public void handleComment(char[] data, int pos)
1640 TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
1643 action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
1644 action.end(HTML.Tag.COMMENT);
1650 * This method is called by the parser and should route the call to the
1651 * proper handler for the tag.
1653 * @param t the HTML.Tag
1654 * @param pos the position at which the tag was encountered
1656 public void handleEndTag(HTML.Tag t, int pos)
1660 // If this is the </html> tag we need to stop calling the Actions
1661 if (t == HTML.Tag.HTML)
1662 endHTMLEncountered = true;
1664 TagAction action = (TagAction) tagToAction.get(t);
1671 * This is a callback from the parser that should be routed to the
1672 * appropriate handler for the tag.
1674 * @param t the HTML.Tag that was encountered
1675 * @param a the attribute set
1676 * @param pos the position at which the tag was encountered
1678 public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos)
1681 insertTagEncountered = true;
1685 TagAction action = (TagAction) tagToAction.get(t);
1695 * This is invoked after the stream has been parsed but before it has been
1698 * @param eol one of \n, \r, or \r\n, whichever was encountered the most in
1699 * parsing the stream
1702 public void handleEndOfLineString(String eol)
1704 // FIXME: Implement.
1708 * Adds the given text to the textarea document. Called only when we are
1709 * within a textarea.
1711 * @param data the text to add to the textarea
1713 protected void textAreaContent(char[] data)
1717 int offset = textAreaDocument.getLength();
1718 String text = new String(data);
1719 textAreaDocument.setInitialText(text);
1720 textAreaDocument.insertString(offset, text, null);
1722 catch (BadLocationException ex)
1724 // Must not happen as we insert at a model location that we
1725 // got from the document itself.
1731 * Adds the given text that was encountered in a <PRE> element.
1732 * This adds synthesized lines to hold the text runs.
1734 * @param data the text
1736 protected void preContent(char[] data)
1739 for (int i = 0; i < data.length; i++)
1741 if (data[i] == '\n')
1743 addContent(data, start, i - start + 1);
1744 blockClose(HTML.Tag.IMPLIED);
1745 MutableAttributeSet atts = new SimpleAttributeSet();
1746 atts.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
1747 blockOpen(HTML.Tag.IMPLIED, atts);
1751 if (start < data.length)
1753 // Add remaining last line.
1754 addContent(data, start, data.length - start);
1759 * Instructs the parse buffer to create a block element with the given
1762 * @param t the tag that requires opening a new block
1763 * @param attr the attribute set for the new block
1765 protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
1767 if (inImpliedParagraph())
1768 blockClose(HTML.Tag.IMPLIED);
1770 // Push the new tag on top of the stack.
1773 DefaultStyledDocument.ElementSpec element;
1775 AbstractDocument.AttributeContext ctx = getAttributeContext();
1776 AttributeSet copy = attr.copyAttributes();
1777 copy = ctx.addAttribute(copy, StyleConstants.NameAttribute, t);
1778 element = new DefaultStyledDocument.ElementSpec(copy,
1779 DefaultStyledDocument.ElementSpec.StartTagType);
1780 parseBuffer.addElement(element);
1784 * Returns true when we are currently inside a paragraph, either
1785 * a real one or an implied, false otherwise.
1789 private boolean inParagraph()
1791 boolean inParagraph = false;
1792 if (! parseStack.isEmpty())
1794 HTML.Tag top = parseStack.peek();
1795 inParagraph = top == HTML.Tag.P || top == HTML.Tag.IMPLIED;
1800 private boolean inImpliedParagraph()
1802 boolean inParagraph = false;
1803 if (! parseStack.isEmpty())
1805 HTML.Tag top = parseStack.peek();
1806 inParagraph = top == HTML.Tag.IMPLIED;
1812 * Instructs the parse buffer to close the block element associated with
1813 * the given HTML.Tag
1815 * @param t the HTML.Tag that is closing its block
1817 protected void blockClose(HTML.Tag t)
1819 DefaultStyledDocument.ElementSpec element;
1821 if (inImpliedParagraph() && t != HTML.Tag.IMPLIED)
1822 blockClose(HTML.Tag.IMPLIED);
1824 // Pull the token from the stack.
1825 if (! parseStack.isEmpty()) // Just to be sure.
1828 // If the previous tag is a start tag then we insert a synthetic
1830 DefaultStyledDocument.ElementSpec prev;
1831 prev = parseBuffer.size() > 0 ? (DefaultStyledDocument.ElementSpec)
1832 parseBuffer.get(parseBuffer.size() - 1) : null;
1834 prev.getType() == DefaultStyledDocument.ElementSpec.StartTagType)
1836 addContent(new char[]{' '}, 0, 1);
1839 element = new DefaultStyledDocument.ElementSpec(null,
1840 DefaultStyledDocument.ElementSpec.EndTagType);
1841 parseBuffer.addElement(element);
1845 * Adds text to the appropriate context using the current character
1848 * @param data the text to add
1849 * @param offs the offset at which to add it
1850 * @param length the length of the text to add
1852 protected void addContent(char[] data, int offs, int length)
1854 addContent(data, offs, length, true);
1858 * Adds text to the appropriate context using the current character
1859 * attribute set, and possibly generating an IMPLIED Tag if necessary.
1861 * @param data the text to add
1862 * @param offs the offset at which to add it
1863 * @param length the length of the text to add
1864 * @param generateImpliedPIfNecessary whether or not we should generate
1865 * an HTML.Tag.IMPLIED tag if necessary
1867 protected void addContent(char[] data, int offs, int length,
1868 boolean generateImpliedPIfNecessary)
1870 if (generateImpliedPIfNecessary && ! inParagraph())
1872 blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1875 AbstractDocument.AttributeContext ctx = getAttributeContext();
1876 DefaultStyledDocument.ElementSpec element;
1877 AttributeSet attributes = null;
1879 // Copy the attribute set, don't use the same object because
1881 if (charAttr != null)
1882 attributes = charAttr.copyAttributes();
1884 attributes = ctx.getEmptySet();
1885 attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
1887 element = new DefaultStyledDocument.ElementSpec(attributes,
1888 DefaultStyledDocument.ElementSpec.ContentType,
1889 data, offs, length);
1891 // Add the element to the buffer
1892 parseBuffer.addElement(element);
1894 if (parseBuffer.size() > threshold)
1896 if (threshold <= MAX_THRESHOLD)
1897 threshold *= GROW_THRESHOLD;
1902 catch (BadLocationException ble)
1904 // TODO: what to do here?
1910 * Adds content that is specified in the attribute set.
1912 * @param t the HTML.Tag
1913 * @param a the attribute set specifying the special content
1915 protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
1917 if (t != HTML.Tag.FRAME && ! inParagraph())
1919 blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1922 a.addAttribute(StyleConstants.NameAttribute, t);
1924 // The two spaces are required because some special elements like HR
1925 // must be broken. At least two characters are needed to break into the
1927 DefaultStyledDocument.ElementSpec spec =
1928 new DefaultStyledDocument.ElementSpec(a.copyAttributes(),
1929 DefaultStyledDocument.ElementSpec.ContentType,
1930 new char[] {' '}, 0, 1 );
1931 parseBuffer.add(spec);
1937 * Gets the reader for the parser to use when loading the document with HTML.
1939 * @param pos - the starting position
1940 * @return - the reader
1942 public HTMLEditorKit.ParserCallback getReader(int pos)
1944 return new HTMLReader(pos);
1948 * Gets the reader for the parser to use when loading the document with HTML.
1950 * @param pos - the starting position
1951 * @param popDepth - the number of EndTagTypes to generate before inserting
1952 * @param pushDepth - the number of StartTagTypes with a direction
1953 * of JoinNextDirection that should be generated before inserting,
1954 * but after the end tags have been generated.
1955 * @param insertTag - the first tag to start inserting into document
1956 * @return - the reader
1958 public HTMLEditorKit.ParserCallback getReader(int pos,
1963 return new HTMLReader(pos, popDepth, pushDepth, insertTag);
1967 * Gets the reader for the parser to use when inserting the HTML fragment into
1968 * the document. Checks if the parser is present, sets the parent in the
1969 * element stack and removes any actions for BODY (it can be only one body in
1972 * @param pos - the starting position
1973 * @param popDepth - the number of EndTagTypes to generate before inserting
1974 * @param pushDepth - the number of StartTagTypes with a direction of
1975 * JoinNextDirection that should be generated before inserting, but
1976 * after the end tags have been generated.
1977 * @param insertTag - the first tag to start inserting into document
1978 * @param parent the element that will be the parent in the document. HTML
1979 * parsing includes checks for the parent, so it must be available.
1980 * @return - the reader
1981 * @throws IllegalStateException if the parsert is not set.
1983 public HTMLEditorKit.ParserCallback getInsertingReader(int pos, int popDepth,
1986 final Element parent)
1987 throws IllegalStateException
1990 throw new IllegalStateException("Parser has not been set");
1992 HTMLReader reader = new HTMLReader(pos, popDepth, pushDepth, insertTag)
1997 public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
1999 if (t != HTML.Tag.BODY)
2000 super.handleStartTag(t, a, pos);
2006 public void handleEndTag(HTML.Tag t, int pos)
2008 if (t != HTML.Tag.BODY)
2009 super.handleEndTag(t, pos);
2017 * Gets the child element that contains the attribute with the value or null.
2020 * @param e - the element to begin search at
2021 * @param attribute - the desired attribute
2022 * @param value - the desired value
2023 * @return the element found with the attribute and value specified or null if
2026 public Element getElement(Element e, Object attribute, Object value)
2030 if (e.getAttributes().containsAttribute(attribute, value))
2033 int count = e.getElementCount();
2034 for (int j = 0; j < count; j++)
2036 Element child = e.getElement(j);
2037 if (child.getAttributes().containsAttribute(attribute, value))
2040 Element grandChild = getElement(child, attribute, value);
2041 if (grandChild != null)
2049 * Returns the element that has the given id Attribute (for instance, <p id
2050 * ='my paragraph >'). If it is not found, null is returned. The HTML tag,
2051 * having this attribute, is not checked by this method and can be any. The
2052 * method is not thread-safe.
2054 * @param attrId - the value of the attribute id to look for
2055 * @return the element that has the given id.
2057 public Element getElement(String attrId)
2059 return getElement(getDefaultRootElement(), HTML.Attribute.ID,
2064 * Replaces the children of the given element with the contents of
2065 * the string. The document must have an HTMLEditorKit.Parser set.
2066 * This will be seen as at least two events, n inserts followed by a remove.
2068 * @param elem - the brance element whose children will be replaced
2069 * @param htmlText - the string to be parsed and assigned to element.
2070 * @throws BadLocationException
2071 * @throws IOException
2072 * @throws IllegalArgumentException - if elem is a leaf
2073 * @throws IllegalStateException - if an HTMLEditorKit.Parser has not been set
2075 public void setInnerHTML(Element elem, String htmlText)
2076 throws BadLocationException, IOException
2079 throw new IllegalArgumentException("Element is a leaf");
2081 int start = elem.getStartOffset();
2082 int end = elem.getEndOffset();
2084 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2085 end, 0, 0, HTML.Tag.BODY, elem);
2088 getParser().parse(new StringReader(htmlText), reader, true);
2090 // Remove the previous content
2091 remove(start, end - start);
2095 * Replaces the given element in the parent with the string. When replacing a
2096 * leaf, this will attempt to make sure there is a newline present if one is
2097 * needed. This may result in an additional element being inserted. This will
2098 * be seen as at least two events, n inserts followed by a remove. The
2099 * HTMLEditorKit.Parser must be set.
2101 * @param elem - the branch element whose parent will be replaced
2102 * @param htmlText - the string to be parsed and assigned to elem
2103 * @throws BadLocationException
2104 * @throws IOException
2105 * @throws IllegalStateException - if parser is not set
2107 public void setOuterHTML(Element elem, String htmlText)
2108 throws BadLocationException, IOException
2110 // Remove the current element:
2111 int start = elem.getStartOffset();
2112 int end = elem.getEndOffset();
2114 remove(start, end-start);
2116 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2117 start, 0, 0, HTML.Tag.BODY, elem);
2120 getParser().parse(new StringReader(htmlText), reader, true);
2124 * Inserts the string before the start of the given element. The parser must
2127 * @param elem - the element to be the root for the new text.
2128 * @param htmlText - the string to be parsed and assigned to elem
2129 * @throws BadLocationException
2130 * @throws IOException
2131 * @throws IllegalStateException - if parser has not been set
2133 public void insertBeforeStart(Element elem, String htmlText)
2134 throws BadLocationException, IOException
2136 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2137 elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
2140 getParser().parse(new StringReader(htmlText), reader, true);
2144 * Inserts the string at the end of the element. If elem's children are
2145 * leaves, and the character at elem.getEndOffset() - 1 is a newline, then it
2146 * will be inserted before the newline. The parser must be set.
2148 * @param elem - the element to be the root for the new text
2149 * @param htmlText - the text to insert
2150 * @throws BadLocationException
2151 * @throws IOException
2152 * @throws IllegalStateException - if parser is not set
2154 public void insertBeforeEnd(Element elem, String htmlText)
2155 throws BadLocationException, IOException
2157 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2158 elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
2161 getParser().parse(new StringReader(htmlText), reader, true);
2166 * Inserts the string after the end of the given element.
2167 * The parser must be set.
2169 * @param elem - the element to be the root for the new text
2170 * @param htmlText - the text to insert
2171 * @throws BadLocationException
2172 * @throws IOException
2173 * @throws IllegalStateException - if parser is not set
2175 public void insertAfterEnd(Element elem, String htmlText)
2176 throws BadLocationException, IOException
2178 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2179 elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
2182 getParser().parse(new StringReader(htmlText), reader, true);
2186 * Inserts the string at the start of the element.
2187 * The parser must be set.
2189 * @param elem - the element to be the root for the new text
2190 * @param htmlText - the text to insert
2191 * @throws BadLocationException
2192 * @throws IOException
2193 * @throws IllegalStateException - if parser is not set
2195 public void insertAfterStart(Element elem, String htmlText)
2196 throws BadLocationException, IOException
2198 HTMLEditorKit.ParserCallback reader = getInsertingReader(
2199 elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
2202 getParser().parse(new StringReader(htmlText), reader, true);
2206 * Overridden to tag content with the synthetic HTML.Tag.CONTENT
2209 protected void insertUpdate(DefaultDocumentEvent evt, AttributeSet att)
2213 SimpleAttributeSet sas = new SimpleAttributeSet();
2214 sas.addAttribute(StyleConstants.NameAttribute, HTML.Tag.CONTENT);
2217 super.insertUpdate(evt, att);
2221 * Returns <code>true</code> when this document is inside a frame,
2222 * <code>false</code> otherwise.
2224 * @return <code>true</code> when this document is inside a frame,
2225 * <code>false</code> otherwise
2227 boolean isFrameDocument()
2229 return frameDocument;
2233 * Set <code>true</code> when this document is inside a frame,
2234 * <code>false</code> otherwise.
2236 * @param frameDoc <code>true</code> when this document is inside a frame,
2237 * <code>false</code> otherwise
2239 void setFrameDocument(boolean frameDoc)
2241 frameDocument = frameDoc;
2245 * Returns the target that is specified in the base tag, if this is the case.
2247 * @return the target that is specified in the base tag, if this is the case
2249 String getBaseTarget()
2255 * Updates the A tag's pseudo class value in response to a hyperlink
2258 * @param el the corresponding element
2259 * @param value the new value
2261 void updateSpecialClass(Element el, HTML.Attribute cl, String value)
2266 DefaultDocumentEvent ev =
2267 new DefaultDocumentEvent(el.getStartOffset(), 1,
2268 DocumentEvent.EventType.CHANGE);
2269 AttributeSet elAtts = el.getAttributes();
2270 AttributeSet anchorAtts = (AttributeSet) elAtts.getAttribute(HTML.Tag.A);
2271 if (anchorAtts != null)
2273 AttributeSet copy = elAtts.copyAttributes();
2274 StyleSheet ss = getStyleSheet();
2277 anchorAtts = ss.addAttribute(anchorAtts, cl, value);
2281 anchorAtts = ss.removeAttribute(anchorAtts, cl);
2283 MutableAttributeSet matts = (MutableAttributeSet) elAtts;
2284 ev.addEdit(new AttributeUndoableEdit(el, copy, false));
2285 matts.removeAttribute(HTML.Tag.A);
2286 matts.addAttribute(HTML.Tag.A, anchorAtts);
2288 fireChangedUpdate(ev);
2289 fireUndoableEditUpdate(new UndoableEditEvent(this, ev));