/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing; import sun.swing.SwingUtilities2; import java.awt.*;import java.awt.event.*;import java.lang.reflect.*;import java.net.*;import java.util.*;import java.io.*;import java.util.*; import javax.swing.plaf.*;import javax.swing.text.*;import javax.swing.event.*;import javax.swing.text.html.*;import javax.accessibility.*; /** * A text component to edit various kinds of content. * You can find how-to information and examples of using editor panes in * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/text.html">Using Text Components</a>, * a section in <em>The Java Tutorial.</em> * * <p> * This component uses implementations of the * <code>EditorKit</code> to accomplish its behavior. It effectively * morphs into the proper kind of text editor for the kind * of content it is given. The content type that editor is bound * to at any given time is determined by the <code>EditorKit</code> currently * installed. If the content is set to a new URL, its type is used * to determine the <code>EditorKit</code> that should be used to * load the content. * <p> * By default, the following types of content are known: * <dl> * <dt><b>text/plain</b> * <dd>Plain text, which is the default the type given isn't * recognized. The kit used in this case is an extension of * <code>DefaultEditorKit</code> that produces a wrapped plain text view. * <dt><b>text/html</b> * <dd>HTML text. The kit used in this case is the class * <code>javax.swing.text.html.HTMLEditorKit</code> * which provides HTML 3.2 support. * <dt><b>text/rtf</b> * <dd>RTF text. The kit used in this case is the class * <code>javax.swing.text.rtf.RTFEditorKit</code> * which provides a limited support of the Rich Text Format. * </dl> * <p> * There are several ways to load content into this component. * <ol> * <li> * The {@link #setText setText} method can be used to initialize * the component from a string. In this case the current * <code>EditorKit</code> will be used, and the content type will be * expected to be of this type. * <li> * The {@link #read read} method can be used to initialize the * component from a <code>Reader</code>. Note that if the content type is HTML, * relative references (e.g. for things like images) can't be resolved * unless the <base> tag is used or the <em>Base</em> property * on <code>HTMLDocument</code> is set. * In this case the current <code>EditorKit</code> will be used, * and the content type will be expected to be of this type. * <li> * The {@link #setPage setPage} method can be used to initialize * the component from a URL. In this case, the content type will be * determined from the URL, and the registered <code>EditorKit</code> * for that content type will be set. * </ol> * <p> * Some kinds of content may provide hyperlink support by generating * hyperlink events. The HTML <code>EditorKit</code> will generate * hyperlink events if the <code>JEditorPane</code> is <em>not editable</em> * (<code>JEditorPane.setEditable(false);</code> has been called). * If HTML frames are embedded in the document, the typical response would be * to change a portion of the current document. The following code * fragment is a possible hyperlink listener implementation, that treats * HTML frame events specially, and simply displays any other activated * hyperlinks. * <code><pre> class Hyperactive implements HyperlinkListener { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { JEditorPane pane = (JEditorPane) e.getSource(); if (e instanceof HTMLFrameHyperlinkEvent) { HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e; HTMLDocument doc = (HTMLDocument)pane.getDocument(); doc.processHTMLFrameHyperlinkEvent(evt); } else { try { pane.setPage(e.getURL()); } catch (Throwable t) { t.printStackTrace(); } } } } } * </pre></code> * <p> * For information on customizing how <b>text/html</b> is rendered please see * {@link #W3C_LENGTH_UNITS} and {@link #HONOR_DISPLAY_PROPERTIES} * <p> * Culturally dependent information in some documents is handled through * a mechanism called character encoding. Character encoding is an * unambiguous mapping of the members of a character set (letters, ideographs, * digits, symbols, or control functions) to specific numeric code values. It * represents the way the file is stored. Example character encodings are * ISO-8859-1, ISO-8859-5, Shift-jis, Euc-jp, and UTF-8. When the file is * passed to an user agent (<code>JEditorPane</code>) it is converted to * the document character set (ISO-10646 aka Unicode). * <p> * There are multiple ways to get a character set mapping to happen * with <code>JEditorPane</code>. * <ol> * <li> * One way is to specify the character set as a parameter of the MIME * type. This will be established by a call to the * {@link #setContentType setContentType} method. If the content * is loaded by the {@link #setPage setPage} method the content * type will have been set according to the specification of the URL. * It the file is loaded directly, the content type would be expected to * have been set prior to loading. * <li> * Another way the character set can be specified is in the document itself. * This requires reading the document prior to determining the character set * that is desired. To handle this, it is expected that the * <code>EditorKit</code>.read operation throw a * <code>ChangedCharSetException</code> which will * be caught. The read is then restarted with a new Reader that uses * the character set specified in the <code>ChangedCharSetException</code> * (which is an <code>IOException</code>). * </ol> * <p> * <dl> * <dt><b><font size=+1>Newlines</font></b> * <dd> * For a discussion on how newlines are handled, see * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>. * </dl> * * <p> * <strong>Warning:</strong> Swing is not thread safe. For more * information see <a * href="package-summary.html#threading">Swing's Threading * Policy</a>. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @beaninfo * attribute: isContainer false * description: A text component to edit various types of content. * * @author Timothy Prinzing */public class JEditorPane extends JTextComponent { /** * Creates a new <code>JEditorPane</code>. * The document model is set to <code>null</code>. */ public JEditorPane() { super(); setFocusCycleRoot(true); setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() { public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { if (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) { return super.getComponentAfter(focusCycleRoot, aComponent); } else { Container rootAncestor = getFocusCycleRootAncestor(); return (rootAncestor != null) ? rootAncestor.getFocusTraversalPolicy(). getComponentAfter(rootAncestor, JEditorPane.this) : null; } } public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { if (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) { return super.getComponentBefore(focusCycleRoot, aComponent); } else { Container rootAncestor = getFocusCycleRootAncestor(); return (rootAncestor != null) ? rootAncestor.getFocusTraversalPolicy(). getComponentBefore(rootAncestor, JEditorPane.this) : null; } } public Component getDefaultComponent(Container focusCycleRoot) { return (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) ? super.getDefaultComponent(focusCycleRoot) : null; } protected boolean accept(Component aComponent) { return (aComponent != JEditorPane.this) ? super.accept(aComponent) : false; } }); LookAndFeel.installProperty(this, "focusTraversalKeysForward", JComponent. getManagingFocusForwardTraversalKeys()); LookAndFeel.installProperty(this, "focusTraversalKeysBackward", JComponent. getManagingFocusBackwardTraversalKeys()); } /** * Creates a <code>JEditorPane</code> based on a specified URL for input. * * @param initialPage the URL * @exception IOException if the URL is <code>null</code> * or cannot be accessed */ public JEditorPane(URL initialPage) throws IOException { this(); setPage(initialPage); } /** * Creates a <code>JEditorPane</code> based on a string containing * a URL specification. * * @param url the URL * @exception IOException if the URL is <code>null</code> or * cannot be accessed */ public JEditorPane(String url) throws IOException { this(); setPage(url); } /** * Creates a <code>JEditorPane</code> that has been initialized * to the given text. This is a convenience constructor that calls the * <code>setContentType</code> and <code>setText</code> methods. * * @param type mime type of the given text * @param text the text to initialize with; may be <code>null</code> * @exception NullPointerException if the <code>type</code> parameter * is <code>null</code> */ public JEditorPane(String type, String text) { this(); setContentType(type); setText(text); } /** * Adds a hyperlink listener for notification of any changes, for example * when a link is selected and entered. * * @param listener the listener */ public synchronized void addHyperlinkListener(HyperlinkListener listener) { listenerList.add(HyperlinkListener.class, listener); } /** * Removes a hyperlink listener. * * @param listener the listener */ public synchronized void removeHyperlinkListener(HyperlinkListener listener) { listenerList.remove(HyperlinkListener.class, listener); } /** * Returns an array of all the <code>HyperLinkListener</code>s added * to this JEditorPane with addHyperlinkListener(). * * @return all of the <code>HyperLinkListener</code>s added or an empty * array if no listeners have been added * @since 1.4 */ public synchronized HyperlinkListener[] getHyperlinkListeners() { return listenerList.getListeners(javax.swing.event.HyperlinkListener.class); } /** * Notifies all listeners that have registered interest for * notification on this event type. This is normally called * by the currently installed <code>EditorKit</code> if a content type * that supports hyperlinks is currently active and there * was activity with a link. The listener list is processed * last to first. * * @param e the event * @see EventListenerList */ public void fireHyperlinkUpdate(HyperlinkEvent e) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==HyperlinkListener.class) { ((HyperlinkListener)listeners[i+1]).hyperlinkUpdate(e); } } } /** * Sets the current URL being displayed. The content type of the * pane is set, and if the editor kit for the pane is * non-<code>null</code>, then * a new default document is created and the URL is read into it. * If the URL contains and reference location, the location will * be scrolled to by calling the <code>scrollToReference</code> * method. If the desired URL is the one currently being displayed, * the document will not be reloaded. To force a document * reload it is necessary to clear the stream description property * of the document. The following code shows how this can be done: * * <pre> * Document doc = jEditorPane.getDocument(); * doc.putProperty(Document.StreamDescriptionProperty, null); * </pre> * * If the desired URL is not the one currently being * displayed, the <code>getStream</code> method is called to * give subclasses control over the stream provided. * <p> * This may load either synchronously or asynchronously * depending upon the document returned by the <code>EditorKit</code>. * If the <code>Document</code> is of type * <code>AbstractDocument</code> and has a value returned by * <code>AbstractDocument.getAsynchronousLoadPriority</code> * that is greater than or equal to zero, the page will be * loaded on a separate thread using that priority. * <p> * If the document is loaded synchronously, it will be * filled in with the stream prior to being installed into * the editor with a call to <code>setDocument</code>, which * is bound and will fire a property change event. If an * <code>IOException</code> is thrown the partially loaded * document will * be discarded and neither the document or page property * change events will be fired. If the document is * successfully loaded and installed, a view will be * built for it by the UI which will then be scrolled if * necessary, and then the page property change event * will be fired. * <p> * If the document is loaded asynchronously, the document * will be installed into the editor immediately using a * call to <code>setDocument</code> which will fire a * document property change event, then a thread will be * created which will begin doing the actual loading. * In this case, the page property change event will not be * fired by the call to this method directly, but rather will be * fired when the thread doing the loading has finished. * It will also be fired on the event-dispatch thread. * Since the calling thread can not throw an <code>IOException</code> * in the event of failure on the other thread, the page * property change event will be fired when the other * thread is done whether the load was successful or not. * * @param page the URL of the page * @exception IOException for a <code>null</code> or invalid * page specification, or exception from the stream being read * @see #getPage * @beaninfo * description: the URL used to set content * bound: true * expert: true */ public void setPage(URL page) throws IOException { if (page == null) { throw new IOException("invalid url"); } URL loaded = getPage(); // reset scrollbar if (!page.equals(loaded) && page.getRef() == null) { scrollRectToVisible(new Rectangle(0,0,1,1)); } boolean reloaded = false; Object postData = getPostData(); if ((loaded == null) || !loaded.sameFile(page) || (postData != null)) { // different url or POST method, load the new content int p = getAsynchronousLoadPriority(getDocument()); if (p < 0) { // open stream synchronously InputStream in = getStream(page); if (kit != null) { Document doc = initializeModel(kit, page); // At this point, one could either load up the model with no // view notifications slowing it down (i.e. best synchronous // behavior) or set the model and start to feed it on a separate // thread (best asynchronous behavior). p = getAsynchronousLoadPriority(doc); if (p >= 0) { // load asynchronously setDocument(doc); synchronized(this) { pageLoader = new PageLoader(doc, in, loaded, page); pageLoader.execute(); } return; } read(in, doc); setDocument(doc); reloaded = true; } } else { // we may need to cancel background loading if (pageLoader != null) { pageLoader.cancel(true); } // Do everything in a background thread. // Model initialization is deferred to that thread, too. pageLoader = new PageLoader(null, null, loaded, page); pageLoader.execute(); return; } } final String reference = page.getRef(); if (reference != null) { if (!reloaded) { scrollToReference(reference); } else { // Have to scroll after painted. SwingUtilities.invokeLater(new Runnable() { public void run() { scrollToReference(reference); } }); } getDocument().putProperty(Document.StreamDescriptionProperty, page); } firePropertyChange("page", loaded, page); } /** * Create model and initialize document properties from page properties. */ private Document initializeModel(EditorKit kit, URL page) { Document doc = kit.createDefaultDocument(); if (pageProperties != null) { // transfer properties discovered in stream to the // document property collection. for (Enumeration<String> e = pageProperties.keys(); e.hasMoreElements() ;) { String key = e.nextElement(); doc.putProperty(key, pageProperties.get(key)); } pageProperties.clear();Lines 1–500 of 2410. Load more
/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing; import sun.swing.SwingUtilities2; import java.awt.*; import java.awt.event.*; import java.lang.reflect.*; import java.net.*; import java.util.*; import java.io.*; import java.util.*; import javax.swing.plaf.*; import javax.swing.text.*; import javax.swing.event.*; import javax.swing.text.html.*; import javax.accessibility.*; /** * A text component to edit various kinds of content. * You can find how-to information and examples of using editor panes in * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/text.html">Using Text Components</a>, * a section in <em>The Java Tutorial.</em> * * <p> * This component uses implementations of the * <code>EditorKit</code> to accomplish its behavior. It effectively * morphs into the proper kind of text editor for the kind * of content it is given. The content type that editor is bound * to at any given time is determined by the <code>EditorKit</code> currently * installed. If the content is set to a new URL, its type is used * to determine the <code>EditorKit</code> that should be used to * load the content. * <p> * By default, the following types of content are known: * <dl> * <dt><b>text/plain</b> * <dd>Plain text, which is the default the type given isn't * recognized. The kit used in this case is an extension of * <code>DefaultEditorKit</code> that produces a wrapped plain text view. * <dt><b>text/html</b> * <dd>HTML text. The kit used in this case is the class * <code>javax.swing.text.html.HTMLEditorKit</code> * which provides HTML 3.2 support. * <dt><b>text/rtf</b> * <dd>RTF text. The kit used in this case is the class * <code>javax.swing.text.rtf.RTFEditorKit</code> * which provides a limited support of the Rich Text Format. * </dl> * <p> * There are several ways to load content into this component. * <ol> * <li> * The {@link #setText setText} method can be used to initialize * the component from a string. In this case the current * <code>EditorKit</code> will be used, and the content type will be * expected to be of this type. * <li> * The {@link #read read} method can be used to initialize the * component from a <code>Reader</code>. Note that if the content type is HTML, * relative references (e.g. for things like images) can't be resolved * unless the <base> tag is used or the <em>Base</em> property * on <code>HTMLDocument</code> is set. * In this case the current <code>EditorKit</code> will be used, * and the content type will be expected to be of this type. * <li> * The {@link #setPage setPage} method can be used to initialize * the component from a URL. In this case, the content type will be * determined from the URL, and the registered <code>EditorKit</code> * for that content type will be set. * </ol> * <p> * Some kinds of content may provide hyperlink support by generating * hyperlink events. The HTML <code>EditorKit</code> will generate * hyperlink events if the <code>JEditorPane</code> is <em>not editable</em> * (<code>JEditorPane.setEditable(false);</code> has been called). * If HTML frames are embedded in the document, the typical response would be * to change a portion of the current document. The following code * fragment is a possible hyperlink listener implementation, that treats * HTML frame events specially, and simply displays any other activated * hyperlinks. * <code><pre> class Hyperactive implements HyperlinkListener { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { JEditorPane pane = (JEditorPane) e.getSource(); if (e instanceof HTMLFrameHyperlinkEvent) { HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e; HTMLDocument doc = (HTMLDocument)pane.getDocument(); doc.processHTMLFrameHyperlinkEvent(evt); } else { try { pane.setPage(e.getURL()); } catch (Throwable t) { t.printStackTrace(); } } } } } * </pre></code> * <p> * For information on customizing how <b>text/html</b> is rendered please see * {@link #W3C_LENGTH_UNITS} and {@link #HONOR_DISPLAY_PROPERTIES} * <p> * Culturally dependent information in some documents is handled through * a mechanism called character encoding. Character encoding is an * unambiguous mapping of the members of a character set (letters, ideographs, * digits, symbols, or control functions) to specific numeric code values. It * represents the way the file is stored. Example character encodings are * ISO-8859-1, ISO-8859-5, Shift-jis, Euc-jp, and UTF-8. When the file is * passed to an user agent (<code>JEditorPane</code>) it is converted to * the document character set (ISO-10646 aka Unicode). * <p> * There are multiple ways to get a character set mapping to happen * with <code>JEditorPane</code>. * <ol> * <li> * One way is to specify the character set as a parameter of the MIME * type. This will be established by a call to the * {@link #setContentType setContentType} method. If the content * is loaded by the {@link #setPage setPage} method the content * type will have been set according to the specification of the URL. * It the file is loaded directly, the content type would be expected to * have been set prior to loading. * <li> * Another way the character set can be specified is in the document itself. * This requires reading the document prior to determining the character set * that is desired. To handle this, it is expected that the * <code>EditorKit</code>.read operation throw a * <code>ChangedCharSetException</code> which will * be caught. The read is then restarted with a new Reader that uses * the character set specified in the <code>ChangedCharSetException</code> * (which is an <code>IOException</code>). * </ol> * <p> * <dl> * <dt><b><font size=+1>Newlines</font></b> * <dd> * For a discussion on how newlines are handled, see * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>. * </dl> * * <p> * <strong>Warning:</strong> Swing is not thread safe. For more * information see <a * href="package-summary.html#threading">Swing's Threading * Policy</a>. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @beaninfo * attribute: isContainer false * description: A text component to edit various types of content. * * @author Timothy Prinzing */ public class JEditorPane extends JTextComponent { /** * Creates a new <code>JEditorPane</code>. * The document model is set to <code>null</code>. */ public JEditorPane() { super(); setFocusCycleRoot(true); setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() { public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { if (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) { return super.getComponentAfter(focusCycleRoot, aComponent); } else { Container rootAncestor = getFocusCycleRootAncestor(); return (rootAncestor != null) ? rootAncestor.getFocusTraversalPolicy(). getComponentAfter(rootAncestor, JEditorPane.this) : null; } } public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { if (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) { return super.getComponentBefore(focusCycleRoot, aComponent); } else { Container rootAncestor = getFocusCycleRootAncestor(); return (rootAncestor != null) ? rootAncestor.getFocusTraversalPolicy(). getComponentBefore(rootAncestor, JEditorPane.this) : null; } } public Component getDefaultComponent(Container focusCycleRoot) { return (focusCycleRoot != JEditorPane.this || (!isEditable() && getComponentCount() > 0)) ? super.getDefaultComponent(focusCycleRoot) : null; } protected boolean accept(Component aComponent) { return (aComponent != JEditorPane.this) ? super.accept(aComponent) : false; } }); LookAndFeel.installProperty(this, "focusTraversalKeysForward", JComponent. getManagingFocusForwardTraversalKeys()); LookAndFeel.installProperty(this, "focusTraversalKeysBackward", JComponent. getManagingFocusBackwardTraversalKeys()); } /** * Creates a <code>JEditorPane</code> based on a specified URL for input. * * @param initialPage the URL * @exception IOException if the URL is <code>null</code> * or cannot be accessed */ public JEditorPane(URL initialPage) throws IOException { this(); setPage(initialPage); } /** * Creates a <code>JEditorPane</code> based on a string containing * a URL specification. * * @param url the URL * @exception IOException if the URL is <code>null</code> or * cannot be accessed */ public JEditorPane(String url) throws IOException { this(); setPage(url); } /** * Creates a <code>JEditorPane</code> that has been initialized * to the given text. This is a convenience constructor that calls the * <code>setContentType</code> and <code>setText</code> methods. * * @param type mime type of the given text * @param text the text to initialize with; may be <code>null</code> * @exception NullPointerException if the <code>type</code> parameter * is <code>null</code> */ public JEditorPane(String type, String text) { this(); setContentType(type); setText(text); } /** * Adds a hyperlink listener for notification of any changes, for example * when a link is selected and entered. * * @param listener the listener */ public synchronized void addHyperlinkListener(HyperlinkListener listener) { listenerList.add(HyperlinkListener.class, listener); } /** * Removes a hyperlink listener. * * @param listener the listener */ public synchronized void removeHyperlinkListener(HyperlinkListener listener) { listenerList.remove(HyperlinkListener.class, listener); } /** * Returns an array of all the <code>HyperLinkListener</code>s added * to this JEditorPane with addHyperlinkListener(). * * @return all of the <code>HyperLinkListener</code>s added or an empty * array if no listeners have been added * @since 1.4 */ public synchronized HyperlinkListener[] getHyperlinkListeners() { return listenerList.getListeners(javax.swing.event.HyperlinkListener.class); } /** * Notifies all listeners that have registered interest for * notification on this event type. This is normally called * by the currently installed <code>EditorKit</code> if a content type * that supports hyperlinks is currently active and there * was activity with a link. The listener list is processed * last to first. * * @param e the event * @see EventListenerList */ public void fireHyperlinkUpdate(HyperlinkEvent e) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==HyperlinkListener.class) { ((HyperlinkListener)listeners[i+1]).hyperlinkUpdate(e); } } } /** * Sets the current URL being displayed. The content type of the * pane is set, and if the editor kit for the pane is * non-<code>null</code>, then * a new default document is created and the URL is read into it. * If the URL contains and reference location, the location will * be scrolled to by calling the <code>scrollToReference</code> * method. If the desired URL is the one currently being displayed, * the document will not be reloaded. To force a document * reload it is necessary to clear the stream description property * of the document. The following code shows how this can be done: * * <pre> * Document doc = jEditorPane.getDocument(); * doc.putProperty(Document.StreamDescriptionProperty, null); * </pre> * * If the desired URL is not the one currently being * displayed, the <code>getStream</code> method is called to * give subclasses control over the stream provided. * <p> * This may load either synchronously or asynchronously * depending upon the document returned by the <code>EditorKit</code>. * If the <code>Document</code> is of type * <code>AbstractDocument</code> and has a value returned by * <code>AbstractDocument.getAsynchronousLoadPriority</code> * that is greater than or equal to zero, the page will be * loaded on a separate thread using that priority. * <p> * If the document is loaded synchronously, it will be * filled in with the stream prior to being installed into * the editor with a call to <code>setDocument</code>, which * is bound and will fire a property change event. If an * <code>IOException</code> is thrown the partially loaded * document will * be discarded and neither the document or page property * change events will be fired. If the document is * successfully loaded and installed, a view will be * built for it by the UI which will then be scrolled if * necessary, and then the page property change event * will be fired. * <p> * If the document is loaded asynchronously, the document * will be installed into the editor immediately using a * call to <code>setDocument</code> which will fire a * document property change event, then a thread will be * created which will begin doing the actual loading. * In this case, the page property change event will not be * fired by the call to this method directly, but rather will be * fired when the thread doing the loading has finished. * It will also be fired on the event-dispatch thread. * Since the calling thread can not throw an <code>IOException</code> * in the event of failure on the other thread, the page * property change event will be fired when the other * thread is done whether the load was successful or not. * * @param page the URL of the page * @exception IOException for a <code>null</code> or invalid * page specification, or exception from the stream being read * @see #getPage * @beaninfo * description: the URL used to set content * bound: true * expert: true */ public void setPage(URL page) throws IOException { if (page == null) { throw new IOException("invalid url"); } URL loaded = getPage(); // reset scrollbar if (!page.equals(loaded) && page.getRef() == null) { scrollRectToVisible(new Rectangle(0,0,1,1)); } boolean reloaded = false; Object postData = getPostData(); if ((loaded == null) || !loaded.sameFile(page) || (postData != null)) { // different url or POST method, load the new content int p = getAsynchronousLoadPriority(getDocument()); if (p < 0) { // open stream synchronously InputStream in = getStream(page); if (kit != null) { Document doc = initializeModel(kit, page); // At this point, one could either load up the model with no // view notifications slowing it down (i.e. best synchronous // behavior) or set the model and start to feed it on a separate // thread (best asynchronous behavior). p = getAsynchronousLoadPriority(doc); if (p >= 0) { // load asynchronously setDocument(doc); synchronized(this) { pageLoader = new PageLoader(doc, in, loaded, page); pageLoader.execute(); } return; } read(in, doc); setDocument(doc); reloaded = true; } } else { // we may need to cancel background loading if (pageLoader != null) { pageLoader.cancel(true); } // Do everything in a background thread. // Model initialization is deferred to that thread, too. pageLoader = new PageLoader(null, null, loaded, page); pageLoader.execute(); return; } } final String reference = page.getRef(); if (reference != null) { if (!reloaded) { scrollToReference(reference); } else { // Have to scroll after painted. SwingUtilities.invokeLater(new Runnable() { public void run() { scrollToReference(reference); } }); } getDocument().putProperty(Document.StreamDescriptionProperty, page); } firePropertyChange("page", loaded, page); } /** * Create model and initialize document properties from page properties. */ private Document initializeModel(EditorKit kit, URL page) { Document doc = kit.createDefaultDocument(); if (pageProperties != null) { // transfer properties discovered in stream to the // document property collection. for (Enumeration<String> e = pageProperties.keys(); e.hasMoreElements() ;) { String key = e.nextElement(); doc.putProperty(key, pageProperties.get(key)); } pageProperties.clear();