/* JEditorPane.java --
   Copyright (C) 2002, 2004, 2005, 2006,  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;

import java.awt.Container;
import java.awt.Dimension;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleHyperlink;
import javax.accessibility.AccessibleHypertext;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleText;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.WrappedPlainView;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

/**
 * A powerful text editor component that can handle different types of
 * content.
 *
 * The JEditorPane text component is driven by an instance of
 * {@link EditorKit}. The editor kit is responsible for providing
 * a default {@link Document} implementation, a mechanism for loading
 * and saving documents of its supported content type and providing
 * a set of {@link Action}s for manipulating the content.
 *
 * By default the following content types are supported:
 * <ul>
 * <li><code>text/plain</code>: Plain text, handled by
 *   {@link javax.swing.text.DefaultEditorKit}.</li>
 * <li><code>text/html</code>: HTML 4.0 styled text, handled by
 *   {@link javax.swing.text.html.HTMLEditorKit}.</li>
 * <li><code>text/rtf</code>: RTF text, handled by
 *   {@link javax.swing.text.rtf.RTFEditorKit}.</li>
 * </ul>
 *
 * @author original author unknown
 * @author Roman Kennke (roman@kennke.org)
 * @author Anthony Balkissoon abalkiss at redhat dot com
 */
public class JEditorPane extends JTextComponent
{
  /**
   * Provides accessibility support for <code>JEditorPane</code>.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  protected class AccessibleJEditorPane extends AccessibleJTextComponent
  {

    /**
     * Creates a new <code>AccessibleJEditorPane</code> object.
     */
    protected AccessibleJEditorPane()
    {
      super();
    }

    /**
     * Returns a description of this <code>AccessibleJEditorPane</code>. If
     * this property is not set, then this returns the content-type of the
     * editor pane.
     *
     * @return a description of this AccessibleJEditorPane
     */
    public String getAccessibleDescription()
    {
      String descr = super.getAccessibleDescription(); 
      if (descr == null)
        return getContentType();
      else
        return descr;
    }

    /**
     * Returns the accessible state of this <code>AccessibleJEditorPane</code>.
     *
     * @return  the accessible state of this <code>AccessibleJEditorPane</code>
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
      AccessibleStateSet state = super.getAccessibleStateSet();
      // TODO: Figure out what state must be added here to the super's state.
      return state;
    }
  }

  /**
   * Provides accessibility support for <code>JEditorPane</code>s, when the
   * editor kit is an instance of {@link HTMLEditorKit}.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  protected class AccessibleJEditorPaneHTML extends AccessibleJEditorPane
  {
    /**
     * Returns the accessible text of the <code>JEditorPane</code>. This will
     * be an instance of
     * {@link JEditorPaneAccessibleHypertextSupport}.
     *
     * @return the accessible text of the <code>JEditorPane</code>
     */
    public AccessibleText getAccessibleText()
    {
      return new JEditorPaneAccessibleHypertextSupport();
    }
  }

  /**
   * This is the accessible text that is returned by
   * {@link AccessibleJEditorPaneHTML#getAccessibleText()}.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  protected class JEditorPaneAccessibleHypertextSupport
    extends AccessibleJEditorPane implements AccessibleHypertext
  {

    /**
     * Creates a new JEditorPaneAccessibleHypertextSupport object.
     */
    public JEditorPaneAccessibleHypertextSupport()
    {
      super();
    }
    
    /**
     * The accessible representation of a HTML link. 
     *
     * @author Roman Kennke (kennke@aicas.com)
     */
    public class HTMLLink extends AccessibleHyperlink
    {

      /**
       * The element in the document that represents the link.
       */
      Element element;

      /**
       * Creates a new <code>HTMLLink</code>.
       *
       * @param el the link element
       */
      public HTMLLink(Element el)
      {
        this.element = el;
      }

      /**
       * Returns <code>true</code> if this <code>HTMLLink</code> is still
       * valid. A <code>HTMLLink</code> can become invalid when the document
       * changes.
       *
       * @return <code>true</code> if this <code>HTMLLink</code> is still
       *         valid
       */
      public boolean isValid()
      {
        // I test here if the element at our element's start offset is the
        // same as the element in the document at this offset. If this is true,
        // I consider the link valid, if not, then this link no longer
        // represented by this HTMLLink and therefor invalid.
        HTMLDocument doc = (HTMLDocument) getDocument();
        return doc.getCharacterElement(element.getStartOffset()) == element;
      }

      /**
       * Returns the number of AccessibleActions in this link object. In
       * general, link have 1 AccessibleAction associated with them. There are
       * special cases where links can have multiple actions associated, like
       * in image maps.
       * 
       * @return the number of AccessibleActions in this link object
       */
      public int getAccessibleActionCount()
      {
        // TODO: Implement the special cases.
        return 1;
      }

      /**
       * Performs the specified action on the link object. This ususally means
       * activating the link.
       *
       * @return <code>true</code> if the action has been performed
       *         successfully, <code>false</code> otherwise
       */
      public boolean doAccessibleAction(int i)
      {
        String href = (String) element.getAttributes().getAttribute("href");
        HTMLDocument doc = (HTMLDocument) getDocument();
        try
          {
            URL url = new URL(doc.getBase(), href);
            setPage(url);
            String desc = doc.getText(element.getStartOffset(),
                            element.getEndOffset() - element.getStartOffset());
            HyperlinkEvent ev =
              new HyperlinkEvent(JEditorPane.this,
                                 HyperlinkEvent.EventType.ACTIVATED, url, desc,
                                 element);
            fireHyperlinkUpdate(ev);
            return true;
          }
        catch (Exception ex)
          {
            return false;
          }
      }

      /**
       * Returns the description of the action at action index <code>i</code>.
       * This method returns the text within the element associated with this
       * link.
       *
       * @param i the action index
       *
       * @return the description of the action at action index <code>i</code>
       */
      public String getAccessibleActionDescription(int i)
      {
        HTMLDocument doc = (HTMLDocument) getDocument();
        try
          {
            return doc.getText(element.getStartOffset(),
                            element.getEndOffset() - element.getStartOffset());
          }
        catch (BadLocationException ex)
          {
            throw (AssertionError)
            new AssertionError("BadLocationException must not be thrown "
                               + "here.")
              .initCause(ex);
          }
      }

      /**
       * Returns an {@link URL} object, that represents the action at action
       * index <code>i</code>.
       *
       * @param i the action index
       *
       * @return an {@link URL} object, that represents the action at action
       *         index <code>i</code>
       */
      public Object getAccessibleActionObject(int i)
      {
        String href = (String) element.getAttributes().getAttribute("href");
        HTMLDocument doc = (HTMLDocument) getDocument();
        try
          {
            URL url = new URL(doc.getBase(), href);
            return url;
          }
        catch (MalformedURLException ex)
          {
            return null;
          }
      }

      /**
       * Returns an object that represents the link anchor. For examples, if
       * the link encloses a string, then a <code>String</code> object is
       * returned, if the link encloses an &lt;img&gt; tag, then an
       * <code>ImageIcon</code> object is returned.
       *
       * @return an object that represents the link anchor
       */
      public Object getAccessibleActionAnchor(int i)
      {
        // TODO: This is only the String case. Implement all cases.
        return getAccessibleActionDescription(i);
      }

      /**
       * Returns the start index of the hyperlink element.
       *
       * @return the start index of the hyperlink element
       */
      public int getStartIndex()
      {
        return element.getStartOffset();
      }

      /**
       * Returns the end index of the hyperlink element.
       *
       * @return the end index of the hyperlink element
       */
      public int getEndIndex()
      {
        return element.getEndOffset();
      }
      
    }

    /**
     * Returns the number of hyperlinks in the document.
     *
     * @return the number of hyperlinks in the document
     */
    public int getLinkCount()
    {
      HTMLDocument doc = (HTMLDocument) getDocument();
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
      int count = 0;
      while (linkIter.isValid())
        {
          count++;
          linkIter.next();
        }
      return count;
    }

    /**
     * Returns the <code>i</code>-th hyperlink in the document or
     * <code>null</code> if there is no hyperlink with the specified index.
     *
     * @param i the index of the hyperlink to return
     *
     * @return the <code>i</code>-th hyperlink in the document or
     *         <code>null</code> if there is no hyperlink with the specified
     *         index
     */
    public AccessibleHyperlink getLink(int i)
    {
      HTMLDocument doc = (HTMLDocument) getDocument();
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
      int count = 0;
      while (linkIter.isValid())
        {
          count++;
          if (count == i)
            break;
          linkIter.next();
        }
      if (linkIter.isValid())
        {
          int offset = linkIter.getStartOffset();
          // TODO: I fetch the element for the link via getCharacterElement().
          // I am not sure that this is correct, maybe we must use
          // getParagraphElement()?
          Element el = doc.getCharacterElement(offset);
          HTMLLink link = new HTMLLink(el);
          return link;
        }
      else
        return null;
    }

    /**
     * Returns the index of the link element at the character position
     * <code>c</code> within the document, or <code>-1</code> if there is no
     * link at the specified position.
     *
     * @param c the character index from which to fetch the link index
     *
     * @return the index of the link element at the character position
     *         <code>c</code> within the document, or <code>-1</code> if there
     *         is no link at the specified position
     */
    public int getLinkIndex(int c)
    {
      HTMLDocument doc = (HTMLDocument) getDocument();
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
      int count = 0;
      while (linkIter.isValid())
        {
          if (linkIter.getStartOffset() <= c && linkIter.getEndOffset() > c)
            break;
          count++;
          linkIter.next();
        }
      if (linkIter.isValid())
        return count;
      else
        return -1;
    }

    /**
     * Returns the link text of the link at index <code>i</code>, or
     * <code>null</code>, if there is no link at the specified position.
     *
     * @param i the index of the link
     *
     * @return  the link text of the link at index <code>i</code>, or
     *          <code>null</code>, if there is no link at the specified
     *          position
     */
    public String getLinkText(int i)
    {
      HTMLDocument doc = (HTMLDocument) getDocument();
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
      int count = 0;
      while (linkIter.isValid())
        {
          count++;
          if (count == i)
            break;
          linkIter.next();
        }
      if (linkIter.isValid())
        {
          int offset = linkIter.getStartOffset();
          // TODO: I fetch the element for the link via getCharacterElement().
          // I am not sure that this is correct, maybe we must use
          // getParagraphElement()?
          Element el = doc.getCharacterElement(offset);
          try
            {
              String text = doc.getText(el.getStartOffset(),
                                      el.getEndOffset() - el.getStartOffset());
              return text;
            }
          catch (BadLocationException ex)
            {
              throw (AssertionError)
                new AssertionError("BadLocationException must not be thrown "
                                   + "here.")
                  .initCause(ex);
            }
        }
      else
        return null;
    }
  }

  /**
   * An EditorKit used for plain text. This is the default editor kit for
   * JEditorPanes.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  private static class PlainEditorKit extends DefaultEditorKit
  {

    /**
     * Returns a ViewFactory that supplies WrappedPlainViews.
     */
    public ViewFactory getViewFactory()
    {
      return new ViewFactory()
      {
        public View create(Element el)
        {
          return new WrappedPlainView(el);
        }
      };
    }
  }

  private static final long serialVersionUID = 3140472492599046285L;
  
  private URL page;
  private EditorKit editorKit;
  
  boolean focus_root;
  
  // A mapping between content types and registered EditorKit types
  static HashMap registerMap;
  
  // A mapping between content types and used EditorKits
  HashMap editorMap;  

  public JEditorPane()
  {
    init();
    setEditorKit(createDefaultEditorKit());
  }

  public JEditorPane(String url) throws IOException
  {
    this(new URL(url));
  }

  public JEditorPane(String type, String text)
  {
    init();
    setEditorKit(createEditorKitForContentType(type));
    setText(text);
  }

  public JEditorPane(URL url) throws IOException
  {
    init();
    setEditorKit(createEditorKitForContentType("text/html"));;
    setPage(url);
  }
  
  /**
   * Called by the constructors to set up the default bindings for content 
   * types and EditorKits.
   */
  void init()
  {
    editorMap = new HashMap();
    registerMap = new HashMap();
    registerEditorKitForContentType("application/rtf",
                                    "javax.swing.text.rtf.RTFEditorKit");
    registerEditorKitForContentType("text/plain",
                                    "javax.swing.JEditorPane$PlainEditorKit");
    registerEditorKitForContentType("text/html",
                                    "javax.swing.text.html.HTMLEditorKit");
    registerEditorKitForContentType("text/rtf",
                                    "javax.swing.text.rtf.RTFEditorKit");
  }

  protected EditorKit createDefaultEditorKit()
  {
    return new PlainEditorKit();
  }

  /**
   * Creates and returns an EditorKit that is appropriate for the given 
   * content type.  This is created using the default recognized types
   * plus any EditorKit types that have been registered.
   * 
   * @see #registerEditorKitForContentType(String, String)
   * @see #registerEditorKitForContentType(String, String, ClassLoader)
   * @param type the content type
   * @return an EditorKit for use with the given content type
   */
  public static EditorKit createEditorKitForContentType(String type)
  {
    // TODO: Have to handle the case where a ClassLoader was specified
    // when the EditorKit was registered
    EditorKit e = null;
    String className = (String) registerMap.get(type);
    if (className != null)
      {
        try
        {
          e = (EditorKit) Class.forName(className).newInstance();
        }
        catch (Exception e2)
        {    
          // TODO: Not sure what to do here.
        }
      }
    return e;
  }

  /**
   * Sends a given <code>HyperlinkEvent</code> to all registered listeners.
   *
   * @param event the event to send
   */
  public void fireHyperlinkUpdate(HyperlinkEvent event)
  {
    HyperlinkListener[] listeners = getHyperlinkListeners();

    for (int index = 0; index < listeners.length; ++index)
       listeners[index].hyperlinkUpdate(event);
  }

  /**
   * Returns the accessible context associated with this editor pane.
   *
   * @return the accessible context associated with this editor pane
   */
  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      {
        if (getEditorKit() instanceof HTMLEditorKit)
          accessibleContext = new AccessibleJEditorPaneHTML();
        else
          accessibleContext = new AccessibleJEditorPane();
      }
    return accessibleContext;
  }

  public final String getContentType()
  {
    return getEditorKit().getContentType();
  }

  /**
   * Returns the EditorKit. If there is no EditorKit set this method
   * calls createDefaultEditorKit() and setEditorKit() first.
   */
  public EditorKit getEditorKit()
  {
    if (editorKit == null)
      setEditorKit(createDefaultEditorKit());
    return editorKit;
  }

  /**
   * Returns the class name of the EditorKit associated with the given
   * content type.
   * 
   * @since 1.3
   * @param type the content type
   * @return the class name of the EditorKit associated with this content type
   */
  public static String getEditorKitClassNameForContentType(String type)
  {
    return (String) registerMap.get(type);
  }

  /**
   * Returns the EditorKit to use for the given content type.  If an
   * EditorKit has been explicitly set via 
   * <code>setEditorKitForContentType</code>
   * then it will be returned.  Otherwise an attempt will be made to create
   * an EditorKit from the default recognzied content types or any
   * EditorKits that have been registered.  If none can be created, a
   * PlainEditorKit is created.
   * 
   * @see #registerEditorKitForContentType(String, String)
   * @see #registerEditorKitForContentType(String, String, ClassLoader)
   * @param type the content type
   * @return an appropriate EditorKit for the given content type
   */
  public EditorKit getEditorKitForContentType(String type)
  {
    // First check if an EditorKit has been explicitly set.
    EditorKit e = (EditorKit) editorMap.get(type);
    // Then check to see if we can create one.
    if (e == null)
      e = createEditorKitForContentType(type);
    // Otherwise default to PlainEditorKit.
    if (e == null)
      e = new PlainEditorKit();
    return e;
  }

  /**
   * Returns the preferred size for the JEditorPane. This is implemented to
   * return the super's preferred size, unless one of
   * {@link #getScrollableTracksViewportHeight()} or
   * {@link #getScrollableTracksViewportWidth()} returns <code>true</code>,
   * in which case the preferred width and/or height is replaced by the UI's
   * minimum size.
   *
   * @return the preferred size for the JEditorPane
   */
  public Dimension getPreferredSize()
  {
    Dimension pref = super.getPreferredSize();
    if (getScrollableTracksViewportWidth())
      pref.width = getUI().getMinimumSize(this).width;
    if (getScrollableTracksViewportHeight())
      pref.height = getUI().getMinimumSize(this).height;
    return pref;
  }

  /**
   * Returns <code>true</code> when a Viewport should force the height of
   * this component to match the viewport height. This is implemented to return
   * <code>true</code> when  the parent is an instance of JViewport and
   * the viewport height > the UI's minimum height.
   *
   * @return <code>true</code> when a Viewport should force the height of
   *         this component to match the viewport height
   */
  public boolean getScrollableTracksViewportHeight()
  {
    // Tests show that this returns true when the parent is a JViewport
    // and has a height > minimum UI height.
    Container parent = getParent();
    return parent instanceof JViewport
           && parent.getHeight() > getUI().getMinimumSize(this).height;
  }

  /**
   * Returns <code>true</code> when a Viewport should force the width of
   * this component to match the viewport width. This is implemented to return
   * <code>true</code> when  the parent is an instance of JViewport and
   * the viewport width > the UI's minimum width.
   *
   * @return <code>true</code> when a Viewport should force the width of
   *         this component to match the viewport width
   */
  public boolean getScrollableTracksViewportWidth()
  {
    // Tests show that this returns true when the parent is a JViewport
    // and has a width > minimum UI width.
    Container parent = getParent();
    return parent != null && parent instanceof JViewport
           && parent.getWidth() > getUI().getMinimumSize(this).width;
  }

  public URL getPage()
  {
    return page;
  }

  protected InputStream getStream(URL page)
    throws IOException
  {
    return page.openStream();
  }

  public String getText()
  {
    return super.getText();
  }

  public String getUIClassID()
  {
    return "EditorPaneUI";
  }

  public boolean isFocusCycleRoot()
  {
    return focus_root;
  }

  protected String paramString()
  {
    return "JEditorPane";
  }

  /**
   * This method initializes from a stream. 
   */
  public void read(InputStream in, Object desc) throws IOException
  {
    EditorKit kit = getEditorKit();
    if (kit instanceof HTMLEditorKit && desc instanceof HTMLDocument)
      {
        Document doc = (Document) desc;
        try
          {
            kit.read(in, doc, 0);
          }
        catch (BadLocationException ex)
          {
            assert false : "BadLocationException must not be thrown here.";
          }
      }
    else
      {
        Reader inRead = new InputStreamReader(in);
        super.read(inRead, desc);
      }
  }

  /**
   * Establishes a binding between type and classname.  This enables
   * us to create an EditorKit later for the given content type.
   * 
   * @param type the content type
   * @param classname the name of the class that is associated with this 
   * content type
   */
  public static void registerEditorKitForContentType(String type,
                                                     String classname)
  {
    registerMap.put(type, classname);
  }

  /**
   * Establishes the default bindings of type to classname.
   */
  public static void registerEditorKitForContentType(String type,
                                                     String classname,
                                                     ClassLoader loader)
  {
    // TODO: Implement this properly.
  }

  /**
   * Replaces the currently selected content with new content represented
   * by the given string.
   */
  public void replaceSelection(String content)
  {
    // TODO: Implement this properly.
    super.replaceSelection(content);
  }

  /**
   * Scrolls the view to the given reference location (that is, the value
   * returned by the UL.getRef method for the URL being displayed).
   */
  public void scrollToReference(String reference)
  {
    // TODO: Implement this properly.
  }

  public final void setContentType(String type)
  {
    if (editorKit != null
	&& editorKit.getContentType().equals(type))
      return;
    	      
    EditorKit kit = getEditorKitForContentType(type);
	    	
    if (kit != null)
      setEditorKit(kit);
  }

  public void setEditorKit(EditorKit newValue)
  {
    if (editorKit == newValue)
      return;
    	
    if (editorKit != null)
      editorKit.deinstall(this);
	    	    
    EditorKit oldValue = editorKit;
    editorKit = newValue;
			    	
    if (editorKit != null)
      {
	editorKit.install(this);
	setDocument(editorKit.createDefaultDocument());
      }
				    	    
    firePropertyChange("editorKit", oldValue, newValue);
    invalidate();
    repaint();
    // Reset the accessibleContext since this depends on the editorKit.
    accessibleContext = null;
  }

  /**
   * Explicitly sets an EditorKit to be used for the given content type.
   * @param type the content type
   * @param k the EditorKit to use for the given content type
   */
  public void setEditorKitForContentType(String type, EditorKit k)
  {
    editorMap.put(type, k);
  }

  /**
   * Sets the current URL being displayed.  
   */
  public void setPage(String url) throws IOException
  {
    setPage(new URL(url));
  }

  /**
   * Sets the current URL being displayed.  
   */
  public void setPage(URL page) throws IOException
  {
    if (page == null)
      throw new IOException("invalid url");

    try
      {
	this.page = page;
	getEditorKit().read(page.openStream(), getDocument(), 0);
      }
    catch (BadLocationException e)
      {
	// Ignored. '0' is always a valid offset.
      }
  }

  /**
   * Sets the text of the JEditorPane.  The argument <code>t</code>
   * is expected to be in the format of the current EditorKit.  This removes
   * the content of the current document and uses the EditorKit to read in the
   * new text.  This allows the EditorKit to handle the String rather than just
   * inserting in plain text.
   * 
   * @param t the text to display in this JEditorPane
   */
  public void setText(String t)
  {
    try
    {
      // Remove the current content.
      Document doc = getDocument();
      doc.remove(0, doc.getLength());
      if (t == null || t.equals(""))
        return;
      
      // Let the EditorKit read the text into the Document.
      getEditorKit().read(new StringReader(t), doc, 0);
    }
    catch (BadLocationException ble)
    {
      // TODO: Don't know what to do here.
    }
    catch (IOException ioe)
    {
      // TODO: Don't know what to do here.
    }
  }

  /**
   * Add a <code>HyperlinkListener</code> object to this editor pane.
   *
   * @param listener the listener to add
   */
  public void addHyperlinkListener(HyperlinkListener listener)
  {
    listenerList.add(HyperlinkListener.class, listener);
  }

  /**
   * Removes a <code>HyperlinkListener</code> object to this editor pane.
   *
   * @param listener the listener to remove
   */
  public void removeHyperlinkListener(HyperlinkListener listener)
  {
    listenerList.remove(HyperlinkListener.class, listener);
  }

  /**
   * Returns all added <code>HyperlinkListener</code> objects.
   *
   * @return array of listeners
   *
   * @since 1.4
   */
  public HyperlinkListener[] getHyperlinkListeners()
  {
    return (HyperlinkListener[]) getListeners(HyperlinkListener.class);
  }
}
