| /* HTMLEditorKit.java -- |
| Copyright (C) 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.swing.text.html; |
| |
| |
| import gnu.classpath.NotImplementedException; |
| |
| import java.awt.event.ActionEvent; |
| import java.awt.event.MouseAdapter; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.MouseMotionListener; |
| import java.awt.Cursor; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.Serializable; |
| import java.io.StringReader; |
| import java.io.Writer; |
| |
| import javax.accessibility.Accessible; |
| import javax.accessibility.AccessibleContext; |
| |
| import javax.swing.Action; |
| import javax.swing.JEditorPane; |
| import javax.swing.text.BadLocationException; |
| import javax.swing.text.Document; |
| import javax.swing.text.EditorKit; |
| import javax.swing.text.Element; |
| import javax.swing.text.MutableAttributeSet; |
| import javax.swing.text.StyleConstants; |
| import javax.swing.text.StyleContext; |
| import javax.swing.text.StyledEditorKit; |
| import javax.swing.text.TextAction; |
| import javax.swing.text.View; |
| import javax.swing.text.ViewFactory; |
| import javax.swing.text.html.parser.ParserDelegator; |
| |
| /* Move these imports here after javax.swing.text.html to make it compile |
| with jikes. */ |
| import gnu.javax.swing.text.html.parser.GnuParserDelegator; |
| import gnu.javax.swing.text.html.parser.HTML_401Swing; |
| |
| /** |
| * @author Lillian Angel (langel at redhat dot com) |
| */ |
| public class HTMLEditorKit |
| extends StyledEditorKit |
| implements Serializable, Cloneable, Accessible |
| { |
| |
| /** |
| * Fires the hyperlink events on the associated component |
| * when needed. |
| */ |
| public static class LinkController |
| extends MouseAdapter |
| implements MouseMotionListener, Serializable |
| { |
| |
| /** |
| * Constructor |
| */ |
| public LinkController() |
| { |
| super(); |
| } |
| |
| /** |
| * Dispatched when the mouse is clicked. If the component |
| * is read-only, then the clicked event is used to drive an |
| * attempt to follow the reference specified by a link |
| * |
| * @param e - the mouse event |
| */ |
| public void mouseClicked(MouseEvent e) |
| { |
| /* |
| These MouseInputAdapter methods generate mouse appropriate events around |
| hyperlinks (entering, exiting, and activating). |
| */ |
| // FIXME: Not implemented. |
| } |
| |
| /** |
| * Dispatched when the mouse is dragged on a component. |
| * |
| * @param e - the mouse event. |
| */ |
| public void mouseDragged(MouseEvent e) |
| { |
| /* |
| These MouseInputAdapter methods generate mouse appropriate events around |
| hyperlinks (entering, exiting, and activating). |
| */ |
| // FIXME: Not implemented. |
| } |
| |
| /** |
| * Dispatched when the mouse cursor has moved into the component. |
| * |
| * @param e - the mouse event. |
| */ |
| public void mouseMoved(MouseEvent e) |
| { |
| /* |
| These MouseInputAdapter methods generate mouse appropriate events around |
| hyperlinks (entering, exiting, and activating). |
| */ |
| // FIXME: Not implemented. |
| } |
| |
| /** |
| * If the given position represents a link, then linkActivated is called |
| * on the JEditorPane. Implemented to forward to the method with the same |
| * name, but pos == editor == -1. |
| * |
| * @param pos - the position |
| * @param editor - the editor pane |
| */ |
| protected void activateLink(int pos, |
| JEditorPane editor) |
| { |
| /* |
| This method creates and fires a HyperlinkEvent if the document is an |
| instance of HTMLDocument and the href tag of the link is not null. |
| */ |
| // FIXME: Not implemented. |
| } |
| } |
| |
| /** |
| * This class is used to insert a string of HTML into an existing |
| * document. At least 2 HTML.Tags need to be supplied. The first Tag (parentTag) |
| * identifies the parent in the document to add the elements to. The second, (addTag), |
| * identifies that the first tag should be added to the document as seen in the string. |
| * The parser will generate all appropriate (opening/closing tags_ even if they are not |
| * in the HTML string passed in. |
| */ |
| public static class InsertHTMLTextAction |
| extends HTMLTextAction |
| { |
| |
| /** |
| * Tag in HTML to start adding tags from. |
| */ |
| protected HTML.Tag addTag; |
| |
| /** |
| * Alternate tag in HTML to start adding tags from if parentTag is |
| * not found and alternateParentTag is not found. |
| */ |
| protected HTML.Tag alternateAddTag; |
| |
| /** |
| * Alternate tag to check if parentTag is not found. |
| */ |
| protected HTML.Tag alternateParentTag; |
| |
| /** |
| * HTML to insert. |
| */ |
| protected String html; |
| |
| /** |
| * Tag to check for in the document. |
| */ |
| protected HTML.Tag parentTag; |
| |
| /** |
| * Initializes all fields. |
| * |
| * @param name - the name of the document. |
| * @param html - the html to insert |
| * @param parentTag - the parent tag to check for |
| * @param addTag - the tag to start adding from |
| */ |
| public InsertHTMLTextAction(String name, String html, |
| HTML.Tag parentTag, HTML.Tag addTag) |
| { |
| this(name, html, parentTag, addTag, null, null); |
| } |
| |
| /** |
| * Initializes all fields and calls super |
| * |
| * @param name - the name of the document. |
| * @param html - the html to insert |
| * @param parentTag - the parent tag to check for |
| * @param addTag - the tag to start adding from |
| * @param alternateParentTag - the alternate parent tag |
| * @param alternateAddTag - the alternate add tag |
| */ |
| public InsertHTMLTextAction(String name, String html, HTML.Tag parentTag, |
| HTML.Tag addTag, HTML.Tag alternateParentTag, |
| HTML.Tag alternateAddTag) |
| { |
| super(name); |
| // Fields are for easy access when the action is applied to an actual |
| // document. |
| this.html = html; |
| this.parentTag = parentTag; |
| this.addTag = addTag; |
| this.alternateParentTag = alternateParentTag; |
| this.alternateAddTag = alternateAddTag; |
| } |
| |
| /** |
| * HTMLEditorKit.insertHTML is called. If an exception is |
| * thrown, it is wrapped in a RuntimeException and thrown. |
| * |
| * @param editor - the editor to use to get the editorkit |
| * @param doc - |
| * the Document to insert the HTML into. |
| * @param offset - |
| * where to begin inserting the HTML. |
| * @param html - |
| * the String to insert |
| * @param popDepth - |
| * the number of ElementSpec.EndTagTypes to generate before |
| * inserting |
| * @param pushDepth - |
| * the number of ElementSpec.StartTagTypes with a direction of |
| * ElementSpec.JoinNextDirection that should be generated before |
| * @param addTag - |
| * the first tag to start inserting into document |
| */ |
| protected void insertHTML(JEditorPane editor, HTMLDocument doc, int offset, |
| String html, int popDepth, int pushDepth, |
| HTML.Tag addTag) |
| { |
| try |
| { |
| super.getHTMLEditorKit(editor).insertHTML(doc, offset, html, |
| popDepth, pushDepth, addTag); |
| } |
| catch (IOException e) |
| { |
| throw (RuntimeException) new RuntimeException("Parser is null.").initCause(e); |
| } |
| catch (BadLocationException ex) |
| { |
| throw (RuntimeException) new RuntimeException("BadLocationException: " |
| + offset).initCause(ex); |
| } |
| } |
| |
| /** |
| * Invoked when inserting at a boundary. Determines the number of pops, |
| * and then the number of pushes that need to be performed. The it calls |
| * insertHTML. |
| * |
| * @param editor - |
| * the editor to use to get the editorkit |
| * @param doc - |
| * the Document to insert the HTML into. |
| * @param offset - |
| * where to begin inserting the HTML. |
| * @param insertElement - |
| * the element to insert |
| * @param html - |
| * the html to insert |
| * @param parentTag - |
| * the parent tag |
| * @param addTag - |
| * the first tag |
| */ |
| protected void insertAtBoundary(JEditorPane editor, |
| HTMLDocument doc, int offset, |
| Element insertElement, |
| String html, HTML.Tag parentTag, |
| HTML.Tag addTag) |
| throws NotImplementedException |
| { |
| /* |
| As its name implies, this protected method is used when HTML is inserted at a |
| boundary. (A boundary in this case is an offset in doc that exactly matches the |
| beginning offset of the parentTag.) It performs the extra work required to keep |
| the tag stack in shape and then calls insertHTML(). The editor and doc argu- |
| ments are the editor pane and document where the HTML should go. The offset |
| argument represents the cursor location or selection start in doc. The insert- |
| Element and parentTag arguments are used to calculate the proper number of |
| tag pops and pushes before inserting the HTML (via html and addTag, which are |
| passed directly to insertHTML()). |
| */ |
| // FIXME: not implemented |
| } |
| |
| /** |
| * Invoked when inserting at a boundary. Determines the number of pops, |
| * and then the number of pushes that need to be performed. The it calls |
| * insertHTML. |
| * |
| * @param editor - the editor to use to get the editorkit |
| * @param doc - |
| * the Document to insert the HTML into. |
| * @param offset - |
| * where to begin inserting the HTML. |
| * @param insertElement - the element to insert |
| * @param html - the html to insert |
| * @param parentTag - the parent tag |
| * @param addTag - the first tag |
| * |
| * @deprecated as of v1.3, use insertAtBoundary |
| */ |
| protected void insertAtBoundry(JEditorPane editor, |
| HTMLDocument doc, |
| int offset, Element insertElement, |
| String html, HTML.Tag parentTag, |
| HTML.Tag addTag) |
| { |
| insertAtBoundary(editor, doc, offset, insertElement, |
| html, parentTag, addTag); |
| } |
| |
| /** |
| * Inserts the HTML. |
| * |
| * @param ae - the action performed |
| */ |
| public void actionPerformed(ActionEvent ae) |
| { |
| Object source = ae.getSource(); |
| if (source instanceof JEditorPane) |
| { |
| JEditorPane pane = ((JEditorPane) source); |
| Document d = pane.getDocument(); |
| if (d instanceof HTMLDocument) |
| insertHTML(pane, (HTMLDocument) d, 0, html, 0, 0, addTag); |
| // FIXME: is this correct parameters? |
| } |
| // FIXME: else not implemented |
| } |
| } |
| |
| /** |
| * Abstract Action class that helps inserting HTML into an existing document. |
| */ |
| public abstract static class HTMLTextAction |
| extends StyledEditorKit.StyledTextAction |
| { |
| |
| /** |
| * Constructor |
| */ |
| public HTMLTextAction(String name) |
| { |
| super(name); |
| } |
| |
| /** |
| * Gets the HTMLDocument from the JEditorPane. |
| * |
| * @param e - the editor pane |
| * @return the html document. |
| */ |
| protected HTMLDocument getHTMLDocument(JEditorPane e) |
| { |
| Document d = e.getDocument(); |
| if (d instanceof HTMLDocument) |
| return (HTMLDocument) d; |
| throw new IllegalArgumentException("Document is not a HTMLDocument."); |
| } |
| |
| /** |
| * Gets the HTMLEditorKit |
| * |
| * @param e - the JEditorPane to get the HTMLEditorKit from. |
| * @return the HTMLEditorKit |
| */ |
| protected HTMLEditorKit getHTMLEditorKit(JEditorPane e) |
| { |
| EditorKit d = e.getEditorKit(); |
| if (d instanceof HTMLEditorKit) |
| return (HTMLEditorKit) d; |
| throw new IllegalArgumentException("EditorKit is not a HTMLEditorKit."); |
| } |
| |
| /** |
| * Returns an array of Elements that contain the offset. |
| * The first elements corresponds to the roots of the doc. |
| * |
| * @param doc - the document to get the Elements from. |
| * @param offset - the offset the Elements must contain |
| * @return an array of all the elements containing the offset. |
| */ |
| protected Element[] getElementsAt(HTMLDocument doc, |
| int offset) |
| { |
| return getElementsAt(doc.getDefaultRootElement(), offset, 0); |
| } |
| |
| /** |
| * Helper function to get all elements using recursion. |
| */ |
| private Element[] getElementsAt(Element root, int offset, int depth) |
| { |
| Element[] elements = null; |
| if (root != null) |
| { |
| if (root.isLeaf()) |
| { |
| elements = new Element[depth + 1]; |
| elements[depth] = root; |
| return elements; |
| } |
| elements = getElementsAt(root.getElement(root.getElementIndex(offset)), |
| offset, depth + 1); |
| elements[depth] = root; |
| } |
| return elements; |
| } |
| |
| /** |
| * Returns the number of elements, starting at the deepest point, needed |
| * to get an element representing tag. -1 if no elements are found, 0 if |
| * the parent of the leaf at offset represents the tag. |
| * |
| * @param doc - |
| * the document to search |
| * @param offset - |
| * the offset to check |
| * @param tag - |
| * the tag to look for |
| * @return - the number of elements needed to get an element representing |
| * tag. |
| */ |
| protected int elementCountToTag(HTMLDocument doc, |
| int offset, HTML.Tag tag) |
| { |
| Element root = doc.getDefaultRootElement(); |
| int num = -1; |
| Element next = root.getElement(root.getElementIndex(offset)); |
| |
| while (!next.isLeaf()) |
| { |
| num++; |
| if (next.getAttributes(). |
| getAttribute(StyleConstants.NameAttribute).equals(tag)) |
| return num; |
| next = next.getElement(next.getElementIndex(offset)); |
| } |
| return num; |
| } |
| |
| /** |
| * Gets the deepest element at offset with the |
| * matching tag. |
| * |
| * @param doc - the document to search |
| * @param offset - the offset to check for |
| * @param tag - the tag to match |
| * @return - the element that is found, null if not found. |
| */ |
| protected Element findElementMatchingTag(HTMLDocument doc, |
| int offset, HTML.Tag tag) |
| { |
| Element element = doc.getDefaultRootElement(); |
| Element tagElement = null; |
| |
| while (element != null) |
| { |
| Object otag = element.getAttributes().getAttribute( |
| StyleConstants.NameAttribute); |
| if (otag instanceof HTML.Tag && otag.equals(tag)) |
| tagElement = element; |
| element = element.getElement(element.getElementIndex(offset)); |
| } |
| |
| return tagElement; |
| } |
| } |
| |
| /** |
| * A {@link ViewFactory} that is able to create {@link View}s for |
| * the <code>Element</code>s that are supported. |
| */ |
| public static class HTMLFactory |
| implements ViewFactory |
| { |
| |
| /** |
| * Constructor |
| */ |
| public HTMLFactory() |
| { |
| // Do Nothing here. |
| } |
| |
| /** |
| * Creates a {@link View} for the specified <code>Element</code>. |
| * |
| * @param element the <code>Element</code> to create a <code>View</code> |
| * for |
| * @return the <code>View</code> for the specified <code>Element</code> |
| * or <code>null</code> if the type of <code>element</code> is |
| * not supported |
| */ |
| public View create(Element element) |
| { |
| View view = null; |
| Object attr = |
| element.getAttributes().getAttribute(StyleConstants.NameAttribute); |
| if (attr instanceof HTML.Tag) |
| { |
| HTML.Tag tag = (HTML.Tag) attr; |
| |
| if (tag.equals(HTML.Tag.IMPLIED) || tag.equals(HTML.Tag.P) |
| || tag.equals(HTML.Tag.H1) || tag.equals(HTML.Tag.H2) |
| || tag.equals(HTML.Tag.H3) || tag.equals(HTML.Tag.H4) |
| || tag.equals(HTML.Tag.H5) || tag.equals(HTML.Tag.H6) |
| || tag.equals(HTML.Tag.DT)) |
| view = new ParagraphView(element); |
| else if (tag.equals(HTML.Tag.LI) || tag.equals(HTML.Tag.DL) |
| || tag.equals(HTML.Tag.DD) || tag.equals(HTML.Tag.BODY) |
| || tag.equals(HTML.Tag.HTML) || tag.equals(HTML.Tag.CENTER) |
| || tag.equals(HTML.Tag.DIV) |
| || tag.equals(HTML.Tag.BLOCKQUOTE) |
| || tag.equals(HTML.Tag.PRE)) |
| view = new BlockView(element, View.Y_AXIS); |
| else if (tag.equals(HTML.Tag.IMG)) |
| view = new ImageView(element); |
| |
| // FIXME: Uncomment when the views have been implemented |
| else if (tag.equals(HTML.Tag.CONTENT)) |
| view = new InlineView(element); |
| else if (tag == HTML.Tag.HEAD) |
| view = new NullView(element); |
| else if (tag.equals(HTML.Tag.TABLE)) |
| view = new javax.swing.text.html.TableView(element); |
| else if (tag.equals(HTML.Tag.TD)) |
| view = new ParagraphView(element); |
| else if (tag.equals(HTML.Tag.HR)) |
| view = new HRuleView(element); |
| else if (tag.equals(HTML.Tag.BR)) |
| view = new BRView(element); |
| |
| /* |
| else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR) |
| || tag.equals(HTML.Tag.UL) || tag.equals(HTML.Tag.OL)) |
| view = new ListView(element); |
| else if (tag.equals(HTML.Tag.INPUT) || tag.equals(HTML.Tag.SELECT) |
| || tag.equals(HTML.Tag.TEXTAREA)) |
| view = new FormView(element); |
| else if (tag.equals(HTML.Tag.OBJECT)) |
| view = new ObjectView(element); |
| else if (tag.equals(HTML.Tag.FRAMESET)) |
| view = new FrameSetView(element); |
| else if (tag.equals(HTML.Tag.FRAME)) |
| view = new FrameView(element); */ |
| } |
| if (view == null) |
| { |
| System.err.println("missing tag->view mapping for: " + element); |
| view = new NullView(element); |
| } |
| return view; |
| } |
| } |
| |
| /** |
| * The abstract HTML parser declaration. |
| */ |
| public abstract static class Parser |
| { |
| /** |
| * Parse the HTML text, calling various methods of the provided callback |
| * in response to the occurence of the corresponding HTML constructions. |
| * @param reader The reader to read the source HTML from. |
| * @param callback The callback to receive information about the parsed |
| * HTML structures |
| * @param ignoreCharSet If true, the parser ignores all charset information |
| * that may be present in HTML documents. |
| * @throws IOException, normally if the reader throws one. |
| */ |
| public abstract void parse(Reader reader, ParserCallback callback, |
| boolean ignoreCharSet) throws IOException; |
| } |
| |
| /** |
| * The "hook" that receives all information about the HTML document |
| * structure while parsing it. The methods are invoked by parser |
| * and should be normally overridden. |
| */ |
| public static class ParserCallback |
| { |
| /** |
| * If the tag does not occurs in the html stream directly, but |
| * is supposed by parser, the tag attribute set contains this additional |
| * attribute, having value Boolean.True. |
| */ |
| public static final Object IMPLIED = "_implied_"; |
| |
| /** |
| * Constructor |
| */ |
| public ParserCallback() |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * The parser calls this method after it finishes parsing the document. |
| */ |
| public void flush() throws BadLocationException |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Handle HTML comment, present in the given position. |
| * @param comment the comment |
| * @position the position of the comment in the text being parsed. |
| */ |
| public void handleComment(char[] comment, int position) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Notifies about the character sequences, used to separate lines in |
| * this document. The parser calls this method after it finishes |
| * parsing the document, but before flush(). |
| * @param end_of_line The "end of line sequence", one of: \r or \n or \r\n. |
| */ |
| public void handleEndOfLineString(String end_of_line) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * The method is called when the HTML closing tag ((like </table>) |
| * is found or if the parser concludes that the one should be present |
| * in the current position. |
| * @param tag The tag being handled |
| * @param position the tag position in the text being parsed. |
| */ |
| public void handleEndTag(HTML.Tag tag, int position) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Handle the error. |
| * @param message The message, explaining the error. |
| * @param position The starting position of the fragment that has caused |
| * the error in the html document being parsed. |
| */ |
| public void handleError(String message, int position) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Handle the tag with no content, like <br>. The method is |
| * called for the elements that, in accordance with the current DTD, |
| * has an empty content. |
| * @param tag The tag being handled. |
| * @param position The tag position in the text being parsed. |
| */ |
| public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attributes, |
| int position) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * The method is called when the HTML opening tag ((like <table>) |
| * is found or if the parser concludes that the one should be present |
| * in the current position. |
| * @param tag The tag being handled |
| * @param position The tag position in the text being parsed |
| */ |
| public void handleStartTag(HTML.Tag tag, MutableAttributeSet attributes, |
| int position) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Handle the text section. |
| * @param text A section text. |
| * @param position The text position in the HTML document text being parsed. |
| */ |
| public void handleText(char[] text, int position) |
| { |
| // Nothing to do here. |
| } |
| } |
| |
| /** |
| * Use serialVersionUID (v1.4) for interoperability. |
| */ |
| private static final long serialVersionUID = 8751997116710384592L; |
| |
| /** |
| * Default cascading stylesheed file ("default.css"). |
| */ |
| public static final String DEFAULT_CSS = "default.css"; |
| |
| /** |
| * The <b>bold</b> action identifier. |
| */ |
| public static final String BOLD_ACTION = "html-bold-action"; |
| |
| /** |
| * The <i>italic</i> action identifier. |
| */ |
| public static final String ITALIC_ACTION = "html-italic-action"; |
| |
| /** |
| * The <font color="#FF0000">color</font> action indentifier |
| * (passing the color as an argument). |
| */ |
| public static final String COLOR_ACTION = "html-color-action"; |
| |
| /** |
| * The <font size="+1">increase</font> font action identifier. |
| */ |
| public static final String FONT_CHANGE_BIGGER = "html-font-bigger"; |
| |
| /** |
| * The <font size="-1">decrease</font> font action identifier. |
| */ |
| public static final String FONT_CHANGE_SMALLER = "html-font-smaller"; |
| |
| /** |
| * Align images at the bottom. |
| */ |
| public static final String IMG_ALIGN_BOTTOM = "html-image-align-bottom"; |
| |
| /** |
| * Align images at the middle. |
| */ |
| public static final String IMG_ALIGN_MIDDLE = "html-image-align-middle"; |
| |
| /** |
| * Align images at the top. |
| */ |
| public static final String IMG_ALIGN_TOP = "html-image-align-top"; |
| |
| /** |
| * Align images at the border. |
| */ |
| public static final String IMG_BORDER = "html-image-border"; |
| |
| /** |
| * The "logical style" action identifier, passing that style as parameter. |
| */ |
| public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action"; |
| |
| /** |
| * The "ident paragraph left" action. |
| */ |
| public static final String PARA_INDENT_LEFT = "html-para-indent-left"; |
| |
| /** |
| * The "ident paragraph right" action. |
| */ |
| public static final String PARA_INDENT_RIGHT = "html-para-indent-right"; |
| |
| /** |
| * Actions for HTML |
| */ |
| private static final Action[] defaultActions = { |
| // FIXME: Add default actions for html |
| }; |
| |
| /** |
| * The current style sheet. |
| */ |
| StyleSheet styleSheet; |
| |
| /** |
| * The ViewFactory for HTMLFactory. |
| */ |
| HTMLFactory viewFactory; |
| |
| /** |
| * The Cursor for links. |
| */ |
| Cursor linkCursor; |
| |
| /** |
| * The default cursor. |
| */ |
| Cursor defaultCursor; |
| |
| /** |
| * The parser. |
| */ |
| Parser parser; |
| |
| /** |
| * The mouse listener used for links. |
| */ |
| LinkController mouseListener; |
| |
| /** |
| * Style context for this editor. |
| */ |
| StyleContext styleContext; |
| |
| /** The content type */ |
| String contentType = "text/html"; |
| |
| /** The input attributes defined by default.css */ |
| MutableAttributeSet inputAttributes; |
| |
| /** The editor pane used. */ |
| JEditorPane editorPane; |
| |
| /** |
| * Constructs an HTMLEditorKit, creates a StyleContext, and loads the style sheet. |
| */ |
| public HTMLEditorKit() |
| { |
| super(); |
| styleContext = new StyleContext(); |
| styleSheet = new StyleSheet(); |
| styleSheet.importStyleSheet(getClass().getResource(DEFAULT_CSS)); |
| // FIXME: Set inputAttributes with default.css |
| } |
| |
| /** |
| * Gets a factory suitable for producing views of any |
| * models that are produced by this kit. |
| * |
| * @return the view factory suitable for producing views. |
| */ |
| public ViewFactory getViewFactory() |
| { |
| if (viewFactory == null) |
| viewFactory = new HTMLFactory(); |
| return viewFactory; |
| } |
| |
| /** |
| * Create a text storage model for this type of editor. |
| * |
| * @return the model |
| */ |
| public Document createDefaultDocument() |
| { |
| HTMLDocument document = new HTMLDocument(getStyleSheet()); |
| document.setParser(getParser()); |
| return document; |
| } |
| |
| /** |
| * Get the parser that this editor kit uses for reading HTML streams. This |
| * method can be overridden to use the alternative parser. |
| * |
| * @return the HTML parser (by default, {@link ParserDelegator}). |
| */ |
| protected Parser getParser() |
| { |
| if (parser == null) |
| { |
| parser = new GnuParserDelegator(HTML_401Swing.getInstance()); |
| } |
| return parser; |
| } |
| |
| /** |
| * Inserts HTML into an existing document. |
| * |
| * @param doc - the Document to insert the HTML into. |
| * @param offset - where to begin inserting the HTML. |
| * @param html - the String to insert |
| * @param popDepth - the number of ElementSpec.EndTagTypes |
| * to generate before inserting |
| * @param pushDepth - the number of ElementSpec.StartTagTypes |
| * with a direction of ElementSpec.JoinNextDirection that |
| * should be generated before |
| * @param insertTag - the first tag to start inserting into document |
| * @throws IOException - on any I/O error |
| * @throws BadLocationException - if pos represents an invalid location |
| * within the document |
| */ |
| public void insertHTML(HTMLDocument doc, int offset, String html, |
| int popDepth, int pushDepth, HTML.Tag insertTag) |
| throws BadLocationException, IOException |
| { |
| Parser parser = getParser(); |
| if (offset < 0 || offset > doc.getLength()) |
| throw new BadLocationException("Bad location", offset); |
| if (parser == null) |
| throw new IOException("Parser is null."); |
| |
| ParserCallback pc = ((HTMLDocument) doc).getReader |
| (offset, popDepth, pushDepth, insertTag); |
| |
| // FIXME: What should ignoreCharSet be set to? |
| |
| // parser.parse inserts html into the buffer |
| parser.parse(new StringReader(html), pc, false); |
| pc.flush(); |
| } |
| |
| /** |
| * Inserts content from the given stream. Inserting HTML into a non-empty |
| * document must be inside the body Element, if you do not insert into |
| * the body an exception will be thrown. When inserting into a non-empty |
| * document all tags outside of the body (head, title) will be dropped. |
| * |
| * @param in - the stream to read from |
| * @param doc - the destination for the insertion |
| * @param pos - the location in the document to place the content |
| * @throws IOException - on any I/O error |
| * @throws BadLocationException - if pos represents an invalid location |
| * within the document |
| */ |
| public void read(Reader in, Document doc, int pos) throws IOException, |
| BadLocationException |
| { |
| if (doc instanceof HTMLDocument) |
| { |
| Parser parser = getParser(); |
| if (pos < 0 || pos > doc.getLength()) |
| throw new BadLocationException("Bad location", pos); |
| if (parser == null) |
| throw new IOException("Parser is null."); |
| |
| HTMLDocument hd = ((HTMLDocument) doc); |
| if (editorPane != null) |
| hd.setBase(editorPane.getPage()); |
| ParserCallback pc = hd.getReader(pos); |
| |
| // FIXME: What should ignoreCharSet be set to? |
| |
| // parser.parse inserts html into the buffer |
| parser.parse(in, pc, false); |
| pc.flush(); |
| } |
| else |
| // read in DefaultEditorKit is called. |
| // the string is inserted in the document as usual. |
| super.read(in, doc, pos); |
| } |
| |
| /** |
| * Writes content from a document to the given stream in |
| * an appropriate format. |
| * |
| * @param out - the stream to write to |
| * @param doc - the source for the write |
| * @param pos - the location in the document to get the content. |
| * @param len - the amount to write out |
| * @throws IOException - on any I/O error |
| * @throws BadLocationException - if pos represents an invalid location |
| * within the document |
| */ |
| public void write(Writer out, Document doc, int pos, int len) |
| throws IOException, BadLocationException |
| { |
| if (doc instanceof HTMLDocument) |
| { |
| // FIXME: Not implemented. Use HTMLWriter. |
| out.write(doc.getText(pos, len)); |
| } |
| else |
| super.write(out, doc, pos, len); |
| } |
| |
| /** |
| * Gets the content type that the kit supports. |
| * This kit supports the type text/html. |
| * |
| * @returns the content type supported. |
| */ |
| public String getContentType() |
| { |
| return contentType; |
| } |
| |
| /** |
| * Creates a copy of the editor kit. |
| * |
| * @return a copy of this. |
| */ |
| public Object clone() |
| { |
| // FIXME: Need to clone all fields |
| return (HTMLEditorKit) super.clone(); |
| } |
| |
| /** |
| * Copies the key/values in elements AttributeSet into set. |
| * This does not copy component, icon, or element names attributes. |
| * This is called anytime the caret moves over a different location. |
| * |
| * @param element - the element to create the input attributes for. |
| * @param set - the set to copy the values into. |
| */ |
| protected void createInputAttributes(Element element, |
| MutableAttributeSet set) |
| { |
| set.removeAttributes(set); |
| set.addAttributes(element.getAttributes()); |
| // FIXME: Not fully implemented. |
| } |
| |
| /** |
| * Called when this is installed into the JEditorPane. |
| * |
| * @param c - the JEditorPane installed into. |
| */ |
| public void install(JEditorPane c) |
| { |
| super.install(c); |
| mouseListener = new LinkController(); |
| c.addMouseListener(mouseListener); |
| editorPane = c; |
| // FIXME: need to set up hyperlinklistener object |
| } |
| |
| /** |
| * Called when the this is removed from the JEditorPane. |
| * It unregisters any listeners. |
| * |
| * @param c - the JEditorPane being removed from. |
| */ |
| public void deinstall(JEditorPane c) |
| { |
| super.deinstall(c); |
| c.removeMouseListener(mouseListener); |
| mouseListener = null; |
| editorPane = null; |
| } |
| |
| /** |
| * Gets the AccessibleContext associated with this. |
| * |
| * @return the AccessibleContext for this. |
| */ |
| public AccessibleContext getAccessibleContext() |
| { |
| // FIXME: Should return an instance of |
| // javax.swing.text.html.AccessibleHTML$RootHTMLAccessibleContext |
| // Not implemented yet. |
| return null; |
| } |
| |
| /** |
| * Gets the action list. This list is supported by the superclass |
| * augmented by the collection of actions defined locally for style |
| * operations. |
| * |
| * @return an array of all the actions |
| */ |
| public Action[] getActions() |
| { |
| return TextAction.augmentList(super.getActions(), defaultActions); |
| } |
| |
| /** |
| * Returns the default cursor. |
| * |
| * @return the default cursor |
| */ |
| public Cursor getDefaultCursor() |
| { |
| if (defaultCursor == null) |
| defaultCursor = Cursor.getDefaultCursor(); |
| return defaultCursor; |
| } |
| |
| /** |
| * Returns the cursor for links. |
| * |
| * @return the cursor for links. |
| */ |
| public Cursor getLinkCursor() |
| { |
| if (linkCursor == null) |
| linkCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); |
| return linkCursor; |
| } |
| |
| /** |
| * Sets the Cursor for links. |
| * |
| * @param cursor - the new cursor for links. |
| */ |
| public void setLinkCursor(Cursor cursor) |
| { |
| linkCursor = cursor; |
| } |
| |
| /** |
| * Sets the default cursor. |
| * |
| * @param cursor - the new default cursor. |
| */ |
| public void setDefaultCursor(Cursor cursor) |
| { |
| defaultCursor = cursor; |
| } |
| |
| /** |
| * Gets the input attributes used for the styled editing actions. |
| * |
| * @return the attribute set |
| */ |
| public MutableAttributeSet getInputAttributes() |
| { |
| return inputAttributes; |
| } |
| |
| /** |
| * Get the set of styles currently being used to render the HTML elements. |
| * By default the resource specified by DEFAULT_CSS gets loaded, and is |
| * shared by all HTMLEditorKit instances. |
| * |
| * @return the style sheet. |
| */ |
| public StyleSheet getStyleSheet() |
| { |
| if (styleSheet == null) |
| { |
| styleSheet = new StyleSheet(); |
| styleSheet.importStyleSheet(getClass().getResource(DEFAULT_CSS)); |
| } |
| return styleSheet; |
| } |
| |
| /** |
| * Set the set of styles to be used to render the various HTML elements. |
| * These styles are specified in terms of CSS specifications. Each document |
| * produced by the kit will have a copy of the sheet which it can add the |
| * document specific styles to. By default, the StyleSheet specified is shared |
| * by all HTMLEditorKit instances. |
| * |
| * @param s - the new style sheet |
| */ |
| public void setStyleSheet(StyleSheet s) |
| { |
| styleSheet = s; |
| } |
| } |