Java/Swing JFC/Text EditorPane

Материал из Java эксперт
Версия от 06:46, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Add colored text to the document

  
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class Main extends JTextPane {
  public void append(Color c, String s) {
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
    int len = getDocument().getLength();
    setCaretPosition(len);
    setCharacterAttributes(aset, false);
    replaceSelection(s);
  }
  public static void main(String argv[]) {
    Main pane = new Main();
    for (int n = 1; n <= 4; n += 1) {
        pane.append(Color.black, String.valueOf(n) + " ");
    }
    JFrame f = new JFrame("ColorPane example");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setContentPane(new JScrollPane(pane));
    f.setSize(600, 400);
    f.setVisible(true);
  }

}





Change mouse cursor during mouse-over action on hyperlinks

  
import java.io.FileNotFoundException;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
public class Main implements HyperlinkListener {
  private JEditorPane pane;
  public Main(JEditorPane jep) {
    pane = jep;
  }
  public void hyperlinkUpdate(HyperlinkEvent he) {
    HyperlinkEvent.EventType type = he.getEventType();
    if (type == HyperlinkEvent.EventType.ENTERED) {
        System.out.println(he.getURL().toString());
    } else if (type == HyperlinkEvent.EventType.EXITED) {
      System.out.println("Exited");
    } else if (type == HyperlinkEvent.EventType.ACTIVATED) {
      if (he instanceof HTMLFrameHyperlinkEvent) {
        HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) he;
        HTMLDocument doc = (HTMLDocument) pane.getDocument();
        doc.processHTMLFrameHyperlinkEvent(evt);
      } else {
        try {
          pane.setPage(he.getURL());
          System.out.println(he.getURL().toString());
        } catch (FileNotFoundException fnfe) {
          pane.setText("Could not open file: <tt>" + he.getURL() + "</tt>.<hr>");
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
}





Create a center-aligned tab stop at 300 pixels from the left margin

   
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.TabStop;
public class Main {
  public static void main(String[] argv) {
    List list = new ArrayList();
    int pos = 300;
    int align = TabStop.ALIGN_CENTER;
    int leader = TabStop.LEAD_NONE;
    TabStop tstop = new TabStop(pos, align, leader);
    list.add(tstop);
  }
}





Create a decimal-aligned tab stop at 400 pixels from the left margin

   
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextPane;
import javax.swing.text.TabStop;
public class Main {
  public static void main(String[] argv) {
    // Create a text pane
    JTextPane textPane = new JTextPane();
    List list = new ArrayList();
    int pos = 400;
    int align = TabStop.ALIGN_DECIMAL;
    int leader = TabStop.LEAD_NONE;
    TabStop tstop = new TabStop(pos, align, leader);
    list.add(tstop);
  }
}





Create a right-aligned tab stop at 200 pixels from the left margin

   
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.TabStop;
public class Main {
  public static void main(String[] argv) {
    List list = new ArrayList();
    int pos = 200;
    int align = TabStop.ALIGN_RIGHT;
    int leader = TabStop.LEAD_NONE;
    TabStop tstop = new TabStop(pos, align, leader);
    list.add(tstop);
  }
}





Create a simple browser in Swing

  
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
public class MiniBrowser extends JFrame implements HyperlinkListener {
  private JButton backButton = new JButton("<"), forwardButton = new JButton(">");
  private JTextField locationTextField = new JTextField(35);
  private JEditorPane displayEditorPane = new JEditorPane();
  private ArrayList pageList = new ArrayList();
  public MiniBrowser() {
    setSize(640, 480);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel buttonPanel = new JPanel();
    backButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        actionBack();
      }
    });
    backButton.setEnabled(false);
    buttonPanel.add(backButton);
    forwardButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        actionForward();
      }
    });
    forwardButton.setEnabled(false);
    buttonPanel.add(forwardButton);
    locationTextField.addKeyListener(new KeyAdapter() {
      public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
          actionGo();
        }
      }
    });
    buttonPanel.add(locationTextField);
    JButton goButton = new JButton("GO");
    goButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        actionGo();
      }
    });
    buttonPanel.add(goButton);
    displayEditorPane.setContentType("text/html");
    displayEditorPane.setEditable(false);
    displayEditorPane.addHyperlinkListener(this);
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(buttonPanel, BorderLayout.NORTH);
    getContentPane().add(new JScrollPane(displayEditorPane), BorderLayout.CENTER);
  }
  private void actionBack() {
    URL currentUrl = displayEditorPane.getPage();
    int pageIndex = pageList.indexOf(currentUrl.toString());
    try {
      showPage(new URL((String) pageList.get(pageIndex - 1)), false);
    } catch (Exception e) {
    }
  }
  private void actionForward() {
    URL currentUrl = displayEditorPane.getPage();
    int pageIndex = pageList.indexOf(currentUrl.toString());
    try {
      showPage(new URL((String) pageList.get(pageIndex + 1)), false);
    } catch (Exception e) {
    }
  }
  private void actionGo() {
    URL verifiedUrl = verifyUrl(locationTextField.getText());
    if (verifiedUrl != null) {
      showPage(verifiedUrl, true);
    } else {
      System.out.println("Invalid URL");
    }
  }
  private URL verifyUrl(String url) {
    if (!url.toLowerCase().startsWith("http://"))
      return null;
    URL verifiedUrl = null;
    try {
      verifiedUrl = new URL(url);
    } catch (Exception e) {
      return null;
    }
    return verifiedUrl;
  }
  private void showPage(URL pageUrl, boolean addToList) {
    try {
      URL currentUrl = displayEditorPane.getPage();
      displayEditorPane.setPage(pageUrl);
      URL newUrl = displayEditorPane.getPage();
      if (addToList) {
        int listSize = pageList.size();
        if (listSize <= 0) {
          return;
        }
        int pageIndex = pageList.indexOf(currentUrl.toString());
        if (pageIndex >= listSize - 1) {
          return;
        }
        for (int i = listSize - 1; i > pageIndex; i--) {
          pageList.remove(i);
        }
        pageList.add(newUrl.toString());
      }
      locationTextField.setText(newUrl.toString());
      updateButtons();
    } catch (Exception e) {
      System.out.println("Unable to load page");
    }
  }
  private void updateButtons() {
    if (pageList.size() < 2) {
      backButton.setEnabled(false);
      forwardButton.setEnabled(false);
    } else {
      URL currentUrl = displayEditorPane.getPage();
      int pageIndex = pageList.indexOf(currentUrl.toString());
      backButton.setEnabled(pageIndex > 0);
      forwardButton.setEnabled(pageIndex < (pageList.size() - 1));
    }
  }
  public void hyperlinkUpdate(HyperlinkEvent event) {
    HyperlinkEvent.EventType eventType = event.getEventType();
    if (eventType == HyperlinkEvent.EventType.ACTIVATED) {
      if (event instanceof HTMLFrameHyperlinkEvent) {
        HTMLFrameHyperlinkEvent linkEvent = (HTMLFrameHyperlinkEvent) event;
        HTMLDocument document = (HTMLDocument) displayEditorPane.getDocument();
        document.processHTMLFrameHyperlinkEvent(linkEvent);
      } else {
        showPage(event.getURL(), true);
      }
    }
  }
  public static void main(String[] args) {
    MiniBrowser browser = new MiniBrowser();
    browser.setVisible(true);
  }
}





EditorPane Example 10

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
public class EditorPaneExample10 extends JFrame {
  public EditorPaneExample10() {
    super("JEditorPane Example 10");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        try {
          // Check if the new page and the old
          // page are the same.
          URL url;
          if (selection instanceof URL) {
            url = (URL) selection;
          } else {
            url = new URL((String) selection);
          }
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(url)) {
            return;
          }
          // Try to display the page
          urlCombo.setEnabled(false); // Disable input
          urlCombo.paintImmediately(0, 0, urlCombo.getSize().width,
              urlCombo.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          timeLabel.setText("");
          timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
              timeLabel.getSize().height);
          startTime = System.currentTimeMillis();
          // Choose the loading method
          if (onlineLoad.isSelected()) {
            // Usual load via setPage
            pane.setPage(url);
            loadedType.setText(pane.getContentType());
          } else {
            pane.setContentType("text/html");
            loadedType.setText(pane.getContentType());
            if (loader == null) {
              loader = new HTMLDocumentLoader();
            }
            HTMLDocument doc = loader.loadDocument(url);
            loadComplete();
            pane.setDocument(doc);
            displayLoadTime();
            populateCombo(findLinks(doc, null));
            enableInput();
          }
        } catch (Exception e) {
          System.out.println(e);
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", selection.toString() },
              "File Open Error", JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          enableInput();
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          enableInput();
        }
      }
    });
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(Cursor.getDefaultCursor());
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample10();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private JEditorPane pane;
  private HTMLDocumentLoader loader;
  private JLabel loadingState;
  private JLabel timeLabel;
  private JLabel loadedType;
  private JCheckBox onlineLoad;
  private JComboBox urlCombo;
  private long startTime;
  private boolean populatingCombo;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





EditorPane Sample

   
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
public class EditorSample {
  public static void main(String args[]) {
    JFrame f = new JFrame("JEditorPane Sample");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = f.getContentPane();
    JEditorPane editor = new JEditorPane(
        "text/html",
        "<H3>Help</H3><center><IMG src=file:///c:/cpress/code/Ch01/logo.jpg></center><li>One<li><i>Two</i><li><u>Three</u>");
    editor.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(editor);
    content.add(scrollPane, BorderLayout.CENTER);
    f.setSize(300, 200);
    f.setVisible(true);
  }
}





Get Trailing White Space

   
/*
 * StandardUtilities.java - Various miscallaneous utility functions
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2006 Matthieu Casanova, Slava Pestov
 * Portions copyright (C) 2000 Richard S. Hall
 * Portions copyright (C) 2001 Dirk Moebius
 *
 * This program 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
 * of the License, or any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//{{{ Imports
import javax.swing.text.Segment;
import java.util.ruparator;
import java.util.Stack;
//}}}
/**
 * Several tools that depends on JDK only.
 *
 * @author Matthieu Casanova
 * @version $Id: StandardUtilities.java 12884 2008-06-23 18:17:08Z kpouer $
 * @since 4.3pre5
 */
public class StandardUtilities
{
  //{{{ getTrailingWhiteSpace() method
  /**
   * Returns the number of trailing whitespace characters in the
   * specified string.
   * @param str The string
   */
  public static int getTrailingWhiteSpace(String str)
  {
    int whitespace = 0;
loop:   for(int i = str.length() - 1; i >= 0; i--)
    {
      switch(str.charAt(i))
      {
        case " ":
        case "\t":
          whitespace++;
          break;
        default:
          break loop;
      }
    }
    return whitespace;
  } //}}}

}





JEditorPane and HyperlinkListener Demo

   
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.Container;
import java.awt.Frame;
import java.io.IOException;
import java.net.URL;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.Document;
public class EditorPaneSample {
  public static void main(String args[]) throws IOException {
    JFrame frame = new JFrame("EditorPane Example");
    Container content = frame.getContentPane();
    JEditorPane editorPane = new JEditorPane("http://www.apress.ru");
    editorPane.setEditable(false);
    HyperlinkListener hyperlinkListener = new ActivatedHyperlinkListener(
        frame, editorPane);
    editorPane.addHyperlinkListener(hyperlinkListener);
    JScrollPane scrollPane = new JScrollPane(editorPane);
    content.add(scrollPane);
    frame.setSize(640, 480);
    frame.setVisible(true);
  }
}
class ActivatedHyperlinkListener implements HyperlinkListener {
  Frame frame;
  JEditorPane editorPane;
  public ActivatedHyperlinkListener(Frame frame, JEditorPane editorPane) {
    this.frame = frame;
    this.editorPane = editorPane;
  }
  public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
    HyperlinkEvent.EventType type = hyperlinkEvent.getEventType();
    final URL url = hyperlinkEvent.getURL();
    if (type == HyperlinkEvent.EventType.ENTERED) {
      System.out.println("URL: " + url);
    } else if (type == HyperlinkEvent.EventType.ACTIVATED) {
      System.out.println("Activated");
      Runnable runner = new Runnable() {
        public void run() {
          // Retain reference to original
          Document doc = editorPane.getDocument();
          try {
            editorPane.setPage(url);
          } catch (IOException ioException) {
            JOptionPane.showMessageDialog(frame,
                "Error following link", "Invalid link",
                JOptionPane.ERROR_MESSAGE);
            editorPane.setDocument(doc);
          }
        }
      };
      SwingUtilities.invokeLater(runner);
    }
  }
}





JEditorPane and the Swing HTML Package

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class EditorPaneExample1 extends JFrame {
  public EditorPaneExample1() {
    super("JEditorPane Example 1");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout(4, 4));
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, "West");
    textField = new JTextField(32);
    panel.add(textField, "Center");
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String url = textField.getText();
        try {
          // Try to display the page
          pane.setPage(url);
        } catch (IOException e) {
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
        }
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample1();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private JEditorPane pane;
  private JTextField textField;
}





JEditorPane and the Swing HTML Package 2

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.EditorKit;
public class EditorPaneExample2 extends JFrame {
  public EditorPaneExample2() {
    super("JEditorPane Example 2");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 2;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.CENTER;
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.weighty = 1.0;
    c.gridx = 0;
    c.gridy = 0;
    c.insets = new Insets(2, 2, 2, 2);
    getContentPane().add(new JScrollPane(pane), c);
    // Build the panel of controls
    JPanel upperPanel = new JPanel();
    upperPanel.setLayout(new BorderLayout());
    // Add a text area with a surrounding border
    textArea = new JTextArea(5, 30);
    JPanel textPanel = new JPanel();
    textPanel.setLayout(new BorderLayout());
    textPanel.setBorder(BorderFactory.createTitledBorder("Source Text"));
    textPanel.add(new JScrollPane(textArea));
    upperPanel.add(textPanel, "Center"); // Add the text panel
    // Build a subpanel with two radio buttons to
    // select document type and a button to install
    // new text.
    Box controlPanel = new Box(BoxLayout.Y_AXIS);
    // Add the radio buttons
    ButtonGroup group = new ButtonGroup();
    plainButton = new JRadioButton("Plain Text");
    htmlButton = new JRadioButton("HTML");
    group.add(plainButton);
    group.add(htmlButton);
    controlPanel.add(plainButton);
    controlPanel.add(htmlButton);
    // Add a button to install the text
    JButton installButton = new JButton("Install text");
    controlPanel.add(installButton);
    // Add glue to pad out extra space
    controlPanel.add(Box.createVerticalGlue());
    // Add the controls to the upper panel
    // and the upper panel to the content pane
    upperPanel.add(controlPanel, "East");
    c.gridy = 1;
    c.weighty = 0.0; // No vertical expansion
    getContentPane().add(upperPanel, c);
    // Add labels showing the current editor kit and document
    c.gridy = 2;
    c.gridwidth = 1;
    c.weightx = 0.0;
    c.fill = GridBagConstraints.NONE;
    getContentPane().add(new JLabel("Document: ", JLabel.RIGHT), c);
    c.gridy = 3;
    getContentPane().add(new JLabel("Editor Kit:", JLabel.RIGHT), c);
    docLabel = new JLabel("", JLabel.LEFT);
    kitLabel = new JLabel("", JLabel.LEFT);
    c.gridy = 2;
    c.gridx = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;
    getContentPane().add(docLabel, c);
    c.gridy = 3;
    getContentPane().add(kitLabel, c);
    // Add a listener to the button
    installButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        // Get the text and install it in the JEditorPane
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            pane.setText(textArea.getText());
          }
        });
      }
    });
    // Add listeners to the radio buttons
    ActionListener radioButtonListener = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        JRadioButton b = (JRadioButton) evt.getSource();
        String type = ((b == plainButton) ? "text/plain" : "text/html");
        final EditorKit kit = pane.getEditorKitForContentType(type);
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            pane.setEditorKit(kit);
          }
        });
      }
    };
    // Listen to the properties of the editor pane
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        String prop = evt.getPropertyName();
        if (prop.equals("document")) {
          docLabel.setText(evt.getNewValue().getClass().getName());
        } else if (prop.equals("editorKit")) {
          kitLabel.setText(evt.getNewValue().getClass().getName());
        }
      }
    });
    plainButton.addActionListener(radioButtonListener);
    htmlButton.addActionListener(radioButtonListener);
    // Finally, start off by selecting plain text
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        plainButton.setSelected(true);
        docLabel.setText(pane.getDocument().getClass().getName());
        kitLabel.setText(pane.getEditorKit().getClass().getName());
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample2();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private JEditorPane pane;
  private JTextArea textArea;
  private JRadioButton plainButton;
  private JRadioButton htmlButton;
  private JLabel docLabel;
  private JLabel kitLabel;
}





JEditorPane and the Swing HTML Package 3

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class EditorPaneExample3 extends JFrame {
  public EditorPaneExample3() {
    super("JEditorPane Example 3");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String url = textField.getText();
        try {
          // Try to display the page
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          pane.setPage(url);
          loadingState.setText("Loaded");
          loadedType.setText(pane.getContentType());
        } catch (IOException e) {
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
        }
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample3();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private JEditorPane pane;
  private JTextField textField;
  private JLabel loadingState;
  private JLabel loadedType;
}





JEditorPane and the Swing HTML Package 4

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class EditorPaneExample4 extends JFrame {
  public EditorPaneExample4() {
    super("JEditorPane Example 4");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String url = textField.getText();
        try {
          // Check if the new page and the old
          // page are the same.
          URL newURL = new URL(url);
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(newURL)) {
            return;
          }
          // Try to display the page
          textField.setEnabled(false); // Disable input
          textField.paintImmediately(0, 0, textField.getSize().width,
              textField.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          pane.setPage(url);
          loadedType.setText(pane.getContentType());
        } catch (Exception e) {
          System.out.println(e);
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          textField.setEnabled(true);
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadingState.setText("Page loaded.");
          textField.setEnabled(true); // Allow entry of new URL
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample4();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private JEditorPane pane;
  private JTextField textField;
  private JLabel loadingState;
  private JLabel loadedType;
}





JEditorPane and the Swing HTML Package 5

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class EditorPaneExample5 extends JFrame {
  public EditorPaneExample5() {
    super("JEditorPane Example 5");
  
    pane = new JEditorPane();
    pane.setEditable(false);    // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    
    // Build the panel of controls
    JPanel panel = new JPanel();
    
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;  
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);    
    c.gridy = 2;
    panel.add(loadedType, c);    
    
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String url = textField.getText();
        try {
          // Check if the new page and the old
          // page are the same.
          URL newURL = new URL(url);
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(newURL)) {
            return;
          }
          // Try to display the page
          textField.setEnabled(false);    // Disable input
          textField.paintImmediately(0, 0, 
                      textField.getSize().width,
                      textField.getSize().height);
          setCursor(
              Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                  // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0, 
                      loadingState.getSize().width,
                      loadingState.getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0, 
                      loadedType.getSize().width,
                      loadedType.getSize().height);
          pane.setPage(url);
          
          loadedType.setText(pane.getContentType());
        } catch (Exception e) {
          System.out.println(e);          
          JOptionPane.showMessageDialog(pane, 
            new String[] {
              "Unable to open file",
              url
            }, "File Open Error", 
            JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");          
          textField.setEnabled(true);
          setCursor(Cursor.getDefaultCursor());
        } 
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadingState.setText("Page loaded.");
          textField.setEnabled(true);    // Allow entry of new URL
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample5();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private JEditorPane pane;
  private JTextField textField;
  private JLabel loadingState;
  private JLabel loadedType;
}





JEditorPane and the Swing HTML Package 6

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class EditorPaneExample6 extends JFrame {
  public EditorPaneExample6() {
    super("JEditorPane Example 6");
    pane = new JEditorPane();
    pane.setEditable(false); // Start read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("File name: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    c.gridwidth = 2;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    // Add a "Save" button
    saveButton = new JButton("Save");
    saveButton.setEnabled(false);
    c.gridwidth = 1;
    c.gridx = 2;
    c.gridy = 0;
    c.weightx = 0.0;
    panel.add(saveButton, c);
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String fileName = textField.getText().trim();
        file = new File(fileName);
        absolutePath = file.getAbsolutePath();
        String url = "file:///" + absolutePath;
        try {
          // Check if the new page and the old
          // page are the same.
          URL newURL = new URL(url);
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(newURL)) {
            return;
          }
          // Try to display the page
          textField.setEnabled(false); // Disable input
          textField.paintImmediately(0, 0, textField.getSize().width,
              textField.getSize().height);
          saveButton.setEnabled(false);
          saveButton.paintImmediately(0, 0,
              saveButton.getSize().width,
              saveButton.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          pane.setEditable(false);
          pane.setPage(url);
          loadedType.setText(pane.getContentType());
        } catch (Exception e) {
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          textField.setEnabled(true);
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadingState.setText("Page loaded.");
          textField.setEnabled(true); // Allow entry of new file name
          textField.requestFocus();
          setCursor(Cursor.getDefaultCursor());
          // Allow editing and saving if appropriate
          pane.setEditable(file.canWrite());
          saveButton.setEnabled(file.canWrite());
        }
      }
    });
    // Save button
    saveButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        try {
          String type = pane.getContentType();
          OutputStream os = new BufferedOutputStream(
              new FileOutputStream(file + ".save"));
          pane.setEditable(false);
          textField.setEnabled(false);
          saveButton.setEnabled(false);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          Document doc = pane.getDocument();
          int length = doc.getLength();
          if (type.endsWith("/rtf")) {
            // Saving RTF - use the OutputStream
            try {
              pane.getEditorKit().write(os, doc, 0, length);
              os.close();
            } catch (BadLocationException ex) {
            }
          } else {
            // Not RTF - use a Writer.
            Writer w = new OutputStreamWriter(os);
            pane.write(w);
            w.close();
          }
        } catch (IOException e) {
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to save file", file.getAbsolutePath(), },
              "File Save Error", JOptionPane.ERROR_MESSAGE);
        }
        pane.setEditable(file.canWrite());
        textField.setEnabled(true);
        saveButton.setEnabled(file.canWrite());
        setCursor(Cursor.getDefaultCursor());
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample6();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private File file;
  private String absolutePath;
  private JEditorPane pane;
  private JTextField textField;
  private JLabel loadingState;
  private JLabel loadedType;
  private JButton saveButton;
}





JEditorPane and the Swing HTML Package 7

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.text.EditorKit;
public class EditorPaneExample7 extends JFrame {
  public EditorPaneExample7() {
    super("JEditorPane Example 7");
    pane = new JEditorPane();
    pane.setEditable(false); // Start read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("File name: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 1;
    c.weightx = 1.0;
    c.fill = GridBagConstraints.HORIZONTAL;
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    c.gridwidth = 2;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    getContentPane().add(panel, "South");
    panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    saveButton = new JButton("Save");
    plain = new JCheckBox("Plain Text");
    html = new JCheckBox("HTML");
    rtf = new JCheckBox("RTF");
    panel.add(plain);
    panel.add(html);
    panel.add(rtf);
    ButtonGroup group = new ButtonGroup();
    group.add(plain);
    group.add(html);
    group.add(rtf);
    plain.setSelected(true);
    panel.add(Box.createVerticalStrut(10));
    panel.add(saveButton);
    panel.add(Box.createVerticalGlue());
    panel.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));
    getContentPane().add(panel, "East");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String fileName = textField.getText().trim();
        file = new File(fileName);
        absolutePath = file.getAbsolutePath();
        String url = "file:///" + absolutePath;
        try {
          // Check if the new page and the old
          // page are the same.
          URL newURL = new URL(url);
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(newURL)) {
            return;
          }
          // Try to display the page
          textField.setEnabled(false); // Disable input
          textField.paintImmediately(0, 0, textField.getSize().width,
              textField.getSize().height);
          saveButton.setEnabled(false);
          saveButton.paintImmediately(0, 0,
              saveButton.getSize().width,
              saveButton.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          pane.setEditable(false);
          pane.setPage(url);
          loadedType.setText(pane.getContentType());
        } catch (Exception e) {
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          textField.setEnabled(true);
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadingState.setText("Page loaded.");
          textField.setEnabled(true); // Allow entry of new file name
          textField.requestFocus();
          setCursor(Cursor.getDefaultCursor());
          // Allow editing and saving if appropriate
          pane.setEditable(file.canWrite());
          saveButton.setEnabled(file.canWrite());
        }
      }
    });
    saveButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        Writer w = null;
        OutputStream os = System.out;
        String contentType;
        if (plain.isSelected()) {
          contentType = "text/plain";
          w = new OutputStreamWriter(os);
        } else if (html.isSelected()) {
          contentType = "text/html";
          w = new OutputStreamWriter(os);
        } else {
          contentType = "text/rtf";
        }
        EditorKit kit = pane.getEditorKitForContentType(contentType);
        try {
          if (w != null) {
            kit.write(w, pane.getDocument(), 0, pane.getDocument()
                .getLength());
            w.flush();
          } else {
            kit.write(os, pane.getDocument(), 0, pane.getDocument()
                .getLength());
            os.flush();
          }
        } catch (Exception e) {
          System.out.println("Write failed");
        }
      }
    });
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample7();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private JEditorPane pane;
  private JTextField textField;
  private JLabel loadingState;
  private JLabel loadedType;
  private JButton saveButton;
  private JCheckBox plain;
  private JCheckBox html;
  private JCheckBox rtf;
  private File file;
  private String absolutePath;
}





JEditorPane and the Swing HTML Package 8

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.EditorKit;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class EditorPaneExample8 {
  public static void createDocumentStyles(StyleContext sc) {
    Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
    // Create and add the main document style
    Style mainStyle = sc.addStyle(mainStyleName, defaultStyle);
    StyleConstants.setLeftIndent(mainStyle, 16);
    StyleConstants.setRightIndent(mainStyle, 16);
    StyleConstants.setFirstLineIndent(mainStyle, 16);
    StyleConstants.setFontFamily(mainStyle, "serif");
    StyleConstants.setFontSize(mainStyle, 12);
    // Create and add the constant width style
    Style cwStyle = sc.addStyle(charStyleName, null);
    StyleConstants.setFontFamily(cwStyle, "monospaced");
    StyleConstants.setForeground(cwStyle, Color.green);
    // Create and add the heading style
    Style heading2Style = sc.addStyle(heading2StyleName, null);
    StyleConstants.setForeground(heading2Style, Color.red);
    StyleConstants.setFontSize(heading2Style, 16);
    StyleConstants.setFontFamily(heading2Style, "serif");
    StyleConstants.setBold(heading2Style, true);
    StyleConstants.setLeftIndent(heading2Style, 8);
    StyleConstants.setFirstLineIndent(heading2Style, 0);
    // Create and add the Component style
    Class baseClass = EditorPaneExample8.class;
    URL url = baseClass.getResource("jexp.gif");
    ImageIcon icon = new ImageIcon(url);
    JLabel comp = new JLabel("Displaying text with attributes", icon,
        JLabel.CENTER);
    comp.setVerticalTextPosition(JLabel.BOTTOM);
    comp.setHorizontalTextPosition(JLabel.CENTER);
    comp.setFont(new Font("serif", Font.BOLD | Font.ITALIC, 14));
    Style componentStyle = sc.addStyle(componentStyleName, null);
    StyleConstants.setComponent(componentStyle, comp);
    // The paragraph style for the component
    Style compParagraphStyle = sc.addStyle(compParaName, null);
    StyleConstants.setSpaceAbove(compParagraphStyle, (float) 16.0);
  }
  public static void addText(JTextPane pane, StyleContext sc,
      Style logicalStyle, Paragraph[] content) {
    // The outer loop adds paragraphs, while the
    // inner loop adds character runs.
    int paragraphs = content.length;
    for (int i = 0; i < paragraphs; i++) {
      Run[] runs = content[i].content;
      for (int j = 0; j < runs.length; j++) {
        pane.setCharacterAttributes(
            runs[j].styleName == null ? SimpleAttributeSet.EMPTY
                : sc.getStyle(runs[j].styleName), true);
        pane.replaceSelection(runs[j].content);
      }
      // At the end of the paragraph, add the logical style and
      // any overriding paragraph style and then terminate the
      // paragraph with a newline.
      pane.setParagraphAttributes(SimpleAttributeSet.EMPTY, true);
      if (logicalStyle != null) {
        pane.setLogicalStyle(logicalStyle);
      }
      if (content[i].styleName != null) {
        pane.setParagraphAttributes(sc.getStyle(content[i].styleName),
            false);
      }
      pane.replaceSelection("\n");
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Saving Data in Various Formats");
    // Create the StyleContext, the document and the pane
    final StyleContext sc = new StyleContext();
    final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
    final JTextPane pane = new JTextPane(doc);
    // Build the styles
    createDocumentStyles(sc);
    try {
      // Add the text and apply the styles
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          // Add the text
          addText(pane, sc, sc.getStyle(mainStyleName), content);
        }
      });
    } catch (Exception e) {
      System.out.println("Exception when constructing document: " + e);
      System.exit(1);
    }
    JScrollPane scrollPane = new JScrollPane(pane);
    scrollPane.setPreferredSize(new Dimension(500, 250));
    f.getContentPane().add(scrollPane, "Center");
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    JButton button = new JButton("Save");
    final JCheckBox plain = new JCheckBox("Plain Text");
    final JCheckBox html = new JCheckBox("HTML");
    final JCheckBox rtf = new JCheckBox("RTF");
    panel.add(plain);
    panel.add(html);
    panel.add(rtf);
    ButtonGroup group = new ButtonGroup();
    group.add(plain);
    group.add(html);
    group.add(rtf);
    plain.setSelected(true);
    panel.add(Box.createVerticalStrut(10));
    panel.add(button);
    panel.add(Box.createVerticalGlue());
    panel.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        Writer w = null;
        OutputStream os = System.out;
        String contentType;
        if (plain.isSelected()) {
          contentType = "text/plain";
          w = new OutputStreamWriter(os);
        } else if (html.isSelected()) {
          contentType = "text/html";
          w = new OutputStreamWriter(os);
        } else {
          contentType = "text/rtf";
        }
        EditorKit kit = pane.getEditorKitForContentType(contentType);
        try {
          if (w != null) {
            kit.write(w, pane.getDocument(), 0, pane.getDocument()
                .getLength());
            w.flush();
          } else {
            kit.write(os, pane.getDocument(), 0, pane.getDocument()
                .getLength());
            os.flush();
          }
        } catch (Exception e) {
          System.out.println("Write failed");
        }
      }
    });
    f.getContentPane().add(panel, "East");
    f.pack();
    f.setVisible(true);
  }
  // Style names
  public static final String mainStyleName = "MainStyle";
  public static final String heading2StyleName = "Heading2";
  public static final String charStyleName = "ConstantWidth";
  public static final String componentStyleName = "Component";
  public static final String compParaName = "CompPara";
  // Inner classes used to define paragraph structure
  public static class Run {
    public Run(String styleName, String content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public String content;
  }
  public static class Paragraph {
    public Paragraph(String styleName, Run[] content) {
      this.styleName = styleName;
      this.content = content;
    }
    public String styleName;
    public Run[] content;
  }
  public static final Paragraph[] content = new Paragraph[] {
      new Paragraph(heading2StyleName, new Run[] { new Run(null,
          "Attributes, Styles and Style Contexts") }),
      new Paragraph(
          null,
          new Run[] {
              new Run(null, "The simple "),
              new Run(charStyleName, "PlainDocument"),
              new Run(
                  null,
                  " class that you saw in the previous "
                      + "chapter is only capable of holding text. "
                      + "The more complex text components use a more "
                      + "sophisticated model that implements the "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " interface. "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " is a sub-interface of "),
              new Run(charStyleName, "Document"),
              new Run(
                  null,
                  " that contains methods for manipulating attributes "
                      + "that control the way in which the text in the "
                      + "document is displayed. The Swing text package "
                      + "contains a concrete implementation of "),
              new Run(charStyleName, "StyledDocument"),
              new Run(null, " called "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null,
                  " that is used as the default model for "),
              new Run(charStyleName, "JTextPane"),
              new Run(
                  null,
                  " and is also the base class from which "
                      + "more specific models, such as the "),
              new Run(charStyleName, "HTMLDocument"),
              new Run(
                  null,
                  " class that handles input in HTML format, can be "
                      + "created. In order to make use of "),
              new Run(charStyleName, "DefaultStyledDocument"),
              new Run(null, " and "),
              new Run(charStyleName, "JTextPane"),
              new Run(null,
                  " you need to understand how Swing represents "
                      + "and uses attributes.") }),
      new Paragraph(compParaName, new Run[] { new Run(componentStyleName,
          " ") }) };
}





JEditorPane and the Swing HTML Package 9

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
public class EditorPaneExample9 extends JFrame {
  public EditorPaneExample9() {
    super("JEditorPane Example 9");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    textField = new JTextField(32);
    panel.add(textField, c);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Change page based on text field
    textField.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        String url = textField.getText();
        try {
          // Check if the new page and the old
          // page are the same.
          URL newURL = new URL(url);
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(newURL)) {
            return;
          }
          // Try to display the page
          textField.setEnabled(false); // Disable input
          textField.paintImmediately(0, 0, textField.getSize().width,
              textField.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          timeLabel.setText("");
          timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
              timeLabel.getSize().height);
          startTime = System.currentTimeMillis();
          // Choose the loading method
          if (onlineLoad.isSelected()) {
            // Usual load via setPage
            pane.setPage(url);
            loadedType.setText(pane.getContentType());
          } else {
            pane.setContentType("text/html");
            loadedType.setText(pane.getContentType());
            if (loader == null) {
              loader = new HTMLDocumentLoader();
            }
            HTMLDocument doc = loader.loadDocument(new URL(url));
            loadComplete();
            pane.setDocument(doc);
            displayLoadTime();
          }
        } catch (Exception e) {
          System.out.println(e);
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", url }, "File Open Error",
              JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          textField.setEnabled(true);
          setCursor(Cursor.getDefaultCursor());
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
        }
      }
    });
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
    textField.setEnabled(true); // Allow entry of new URL
    setCursor(Cursor.getDefaultCursor());
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample9();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  static final String spaces = "                    ";
  static final String LOAD_TIME = "Load time: ";
  private JCheckBox onlineLoad;
  private HTMLDocumentLoader loader;
  private JLabel loadingState;
  private JLabel timeLabel;
  private JLabel loadedType;
  private JTextField textField;
  private JEditorPane pane;
  private long startTime;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 10 - using getIterator

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
public class EditorPaneExample10A extends JFrame {
  public EditorPaneExample10A() {
    super("JEditorPane Example 10 - using getIterator");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        try {
          // Check if the new page and the old
          // page are the same.
          URL url;
          if (selection instanceof URL) {
            url = (URL) selection;
          } else {
            url = new URL((String) selection);
          }
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(url)) {
            return;
          }
          // Try to display the page
          urlCombo.setEnabled(false); // Disable input
          urlCombo.paintImmediately(0, 0, urlCombo.getSize().width,
              urlCombo.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          timeLabel.setText("");
          timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
              timeLabel.getSize().height);
          startTime = System.currentTimeMillis();
          // Choose the loading method
          if (onlineLoad.isSelected()) {
            // Usual load via setPage
            pane.setPage(url);
            loadedType.setText(pane.getContentType());
          } else {
            pane.setContentType("text/html");
            loadedType.setText(pane.getContentType());
            if (loader == null) {
              loader = new HTMLDocumentLoader();
            }
            HTMLDocument doc = loader.loadDocument(url);
            loadComplete();
            pane.setDocument(doc);
            displayLoadTime();
            populateCombo(findLinks(doc, null));
            enableInput();
          }
        } catch (Exception e) {
          System.out.println(e);
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", selection.toString() },
              "File Open Error", JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          enableInput();
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          enableInput();
        }
      }
    });
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(Cursor.getDefaultCursor());
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      HTMLDocument.Iterator iterator = ((HTMLDocument) doc)
          .getIterator(HTML.Tag.A);
      for (; iterator.isValid(); iterator.next()) {
        AttributeSet attrs = iterator.getAttributes();
        Object linkAttr = attrs.getAttribute(HTML.Attribute.HREF);
        if (linkAttr instanceof String) {
          try {
            URL linkURL = new URL(baseURL, (String) linkAttr);
            if (protocol == null
                || protocol.equalsIgnoreCase(linkURL
                    .getProtocol())) {
              String linkURLName = linkURL.toString();
              if (urlNames.contains(linkURLName) == false) {
                urlNames.addElement(linkURLName);
                links.addElement(linkURL);
              }
            }
          } catch (MalformedURLException e) {
            // Ignore invalid links
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample10A();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private JEditorPane pane;
  private HTMLDocumentLoader loader;
  private JLabel loadingState;
  private JLabel timeLabel;
  private JLabel loadedType;
  private JCheckBox onlineLoad;
  private JComboBox urlCombo;
  private long startTime;
  private boolean populatingCombo;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 11

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample11 extends JFrame {
  public EditorPaneExample11() {
    super("JEditorPane Example 11");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        try {
          // Check if the new page and the old
          // page are the same.
          URL url;
          if (selection instanceof URL) {
            url = (URL) selection;
          } else {
            url = new URL((String) selection);
          }
          URL loadedURL = pane.getPage();
          if (loadedURL != null && loadedURL.sameFile(url)) {
            return;
          }
          // Try to display the page
          urlCombo.setEnabled(false); // Disable input
          urlCombo.paintImmediately(0, 0, urlCombo.getSize().width,
              urlCombo.getSize().height);
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          // Busy cursor
          loadingState.setText("Loading...");
          loadingState.paintImmediately(0, 0,
              loadingState.getSize().width, loadingState
                  .getSize().height);
          loadedType.setText("");
          loadedType.paintImmediately(0, 0,
              loadedType.getSize().width,
              loadedType.getSize().height);
          timeLabel.setText("");
          timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
              timeLabel.getSize().height);
          // Display an empty tree while loading
          tree.setModel(emptyModel);
          tree.paintImmediately(0, 0, tree.getSize().width, tree
              .getSize().height);
          startTime = System.currentTimeMillis();
          // Choose the loading method
          if (onlineLoad.isSelected()) {
            // Usual load via setPage
            pane.setPage(url);
            loadedType.setText(pane.getContentType());
          } else {
            pane.setContentType("text/html");
            loadedType.setText(pane.getContentType());
            if (loader == null) {
              loader = new HTMLDocumentLoader();
            }
            HTMLDocument doc = loader.loadDocument(url);
            loadComplete();
            pane.setDocument(doc);
            displayLoadTime();
            populateCombo(findLinks(doc, null));
            TreeNode node = buildHeadingTree(doc);
            tree.setModel(new DefaultTreeModel(node));
            enableInput();
          }
        } catch (Exception e) {
          System.out.println(e);
          JOptionPane.showMessageDialog(pane, new String[] {
              "Unable to open file", selection.toString() },
              "File Open Error", JOptionPane.ERROR_MESSAGE);
          loadingState.setText("Failed");
          enableInput();
        }
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(Cursor.getDefaultCursor());
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample11();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private JEditorPane pane;
  private HTMLDocumentLoader loader;
  private JLabel loadingState;
  private JLabel timeLabel;
  private JLabel loadedType;
  private JCheckBox onlineLoad;
  private JComboBox urlCombo;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 12

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample12 extends JFrame {
  public EditorPaneExample12() {
    super("JEditorPane Example 12");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample12();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 13

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.text.html.StyleSheet;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample13 extends JFrame {
  public EditorPaneExample13() {
    super("JEditorPane Example 13");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Load a new default style sheet
    InputStream is = EditorPaneExample13.class
        .getResourceAsStream("changedDefault.css");
    if (is != null) {
      try {
        StyleSheet ss = loadStyleSheet(is);
        editorKit.setStyleSheet(ss);
      } catch (IOException e) {
        System.out.println("Failed to load new default style sheet");
      }
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public StyleSheet loadStyleSheet(InputStream is) throws IOException {
    StyleSheet s = new StyleSheet();
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    s.loadRules(reader, null);
    reader.close();
    return s;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample13();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
  private static final HTMLEditorKit editorKit = new HTMLEditorKit();
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 14

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.text.html.StyleSheet;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample14 extends JFrame {
  public EditorPaneExample14() {
    super("JEditorPane Example 14");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Modify the default style sheet
    InputStream is = EditorPaneExample14.class
        .getResourceAsStream("changedDefault.css");
    if (is != null) {
      try {
        addToStyleSheet(editorKit.getStyleSheet(), is);
      } catch (IOException e) {
        System.out.println("Failed to modify default style sheet");
      }
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public StyleSheet loadStyleSheet(InputStream is) throws IOException {
    StyleSheet s = new StyleSheet();
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    s.loadRules(reader, null);
    reader.close();
    return s;
  }
  public void addToStyleSheet(StyleSheet s, InputStream is)
      throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    s.loadRules(reader, null);
    reader.close();
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample14();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
  private static final HTMLEditorKit editorKit = new HTMLEditorKit();
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 15

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.text.html.StyleSheet;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample15 extends JFrame {
  public EditorPaneExample15() {
    super("JEditorPane Example 15");
    pane = new JEditorPane();
    pane.setEditable(false); // Read-only
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        // Modify styles for this document only
        modifyStyleSheet(doc.getStyleSheet());
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public void modifyStyleSheet(StyleSheet s) {
    s
        .addRule("h1 { color: teal; text-decoration: underline; text-style: italic }"
            + " p { color: blue; font-family: monospace }");
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample15();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 16

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample16 extends JFrame {
  public EditorPaneExample16() {
    super("JEditorPane Example 16");
    pane = new JEditorPane();
    pane.setEditable(true); // Editable
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridy = 5;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    editableBox = new JCheckBox("Editable JEditorPane");
    panel.add(editableBox, c);
    editableBox.setSelected(true);
    editableBox.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Change editability based on the checkbox
    editableBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editableBox.isSelected());
        pane.revalidate();
        pane.repaint();
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public JEditorPane getEditorPane() {
    return pane;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample16();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JCheckBox editableBox;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 17

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample17 extends JFrame {
  public EditorPaneExample17() {
    super("JEditorPane Example 17");
    pane = new JEditorPane();
    pane.setEditable(true); // Editable
    getContentPane().add(new JScrollPane(pane), "Center");
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridy = 5;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    editableBox = new JCheckBox("Editable JEditorPane");
    panel.add(editableBox, c);
    editableBox.setSelected(true);
    editableBox.setForeground(typeLabel.getForeground());
    c.gridx = 1;
    c.gridy = 0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Register a custom EditorKit for HTML
    ClassLoader loader = getClass().getClassLoader();
    if (loader != null) {
      // Java 2
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.HiddenViewHTMLEditorKit", loader);
    } else {
      // JDK 1.1
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.HiddenViewHTMLEditorKit");
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Change editability based on the checkbox
    editableBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editableBox.isSelected());
        pane.revalidate();
        pane.repaint();
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample17();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JCheckBox editableBox;
  private JTree tree;
  private TreeModel emptyModel;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}





JEditorPane Example 18

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.Action;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.text.rtf.RTFEditorKit;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample18 extends JFrame {
  public EditorPaneExample18() {
    super("JEditorPane Example 18");
    pane = new JEditorPane();
    pane.setEditable(true); // Editable
    getContentPane().add(new JScrollPane(pane), "Center");
    // Add a menu bar
    menuBar = new JMenuBar();
    setJMenuBar(menuBar);
    // Populate it
    createMenuBar();
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridy = 5;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    editableBox = new JCheckBox("Editable JEditorPane");
    panel.add(editableBox, c);
    editableBox.setSelected(true);
    editableBox.setForeground(typeLabel.getForeground());
    c.gridy = 6;
    c.weightx = 0.0;
    JButton saveButton = new JButton("Save");
    panel.add(saveButton, c);
    saveButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        EditorKit kit = pane.getEditorKit();
        try {
          if (kit instanceof RTFEditorKit) {
            kit.write(System.out, pane.getDocument(), 0, pane
                .getDocument().getLength());
            System.out.flush();
          } else {
            if (writer == null) {
              writer = new OutputStreamWriter(System.out);
              pane.write(writer);
              writer.flush();
            }
            kit.write(writer, pane.getDocument(), 0, pane
                .getDocument().getLength());
            writer.flush();
          }
        } catch (Exception e) {
          System.out.println("Write failed");
        }
      }
    });
    c.gridx = 1;
    c.gridy = 0;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Register a custom EditorKit for HTML
    ClassLoader loader = getClass().getClassLoader();
    if (loader != null) {
      // Java 2
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.HiddenViewHTMLEditorKit", loader);
    } else {
      // JDK 1.1
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.HiddenViewHTMLEditorKit");
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Change editability based on the checkbox
    editableBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editableBox.isSelected());
        pane.revalidate();
        pane.repaint();
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          createMenuBar();
          enableMenuBar(true);
          getRootPane().revalidate();
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      enableMenuBar(false);
      urlCombo.paintImmediately(0, 0, menuBar.getSize().width, menuBar
          .getSize().height);
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        createMenuBar();
        enableMenuBar(true);
        getRootPane().revalidate();
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableMenuBar(true);
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public void enableMenuBar(boolean cond) {
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.getMenu(i).setEnabled(cond);
    }
  }
  public void createMenuBar() {
    // Remove the existing menu items
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.remove(menuBar.getMenu(0));
    }
    // Build the new menu.
    Action[] actions = pane.getActions();
    Hashtable actionHash = new Hashtable();
    count = actions.length;
    for (int i = 0; i < count; i++) {
      actionHash.put(actions[i].getValue(Action.NAME), actions[i]);
    }
    // Add the font menu
    JMenu menu = MenuBuilder.buildMenu("Font", fontSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the alignment menu
    menu = MenuBuilder.buildMenu("Align", alignSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the HTML menu
    menu = MenuBuilder.buildMenu("HTML", htmlSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample18();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JCheckBox editableBox;
  private JTree tree;
  private TreeModel emptyModel;
  private JMenuBar menuBar;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
  private OutputStreamWriter writer;
  private static MenuSpec[] sizeSpec = new MenuSpec[] {
      new MenuSpec("Size 8", "font-size-8"),
      new MenuSpec("Size 10", "font-size-10"),
      new MenuSpec("Size 12", "font-size-12"),
      new MenuSpec("Size 14", "font-size-14"),
      new MenuSpec("Size 16", "font-size-16"),
      new MenuSpec("Size 18", "font-size-18"),
      new MenuSpec("Size 24", "font-size-24"),
      new MenuSpec("Size 36", "font-size-36"),
      new MenuSpec("Size 48", "font-size-48") };
  private static MenuSpec[] familySpec = new MenuSpec[] {
      new MenuSpec("Sans Serif", "font-family-SansSerif"),
      new MenuSpec("Monospaced", "font-family-Monospaced"),
      new MenuSpec("Serif", "font-family-Serif") };
  private static MenuSpec[] styleSpec = new MenuSpec[] {
      new MenuSpec("Bold", "font-bold"),
      new MenuSpec("Italics", "font-italic"),
      new MenuSpec("Underline", "font-underline") };
  // Menu definitions for fonts
  private static MenuSpec[] fontSpec = new MenuSpec[] {
      new MenuSpec("Size", sizeSpec), new MenuSpec("Family", familySpec),
      new MenuSpec("Style", styleSpec) };
  // Alignment
  private static MenuSpec[] alignSpec = new MenuSpec[] {
      new MenuSpec("Left", "left-justify"),
      new MenuSpec("Center", "center-justify"),
      new MenuSpec("Right", "right-justify") };
  // HTML menu
  private static MenuSpec[] htmlSpec = new MenuSpec[] {
      new MenuSpec("Table", "InsertTable"),
      new MenuSpec("Table Row", "InsertTableRow"),
      new MenuSpec("Table Cell", "InsertTableDataCell"),
      new MenuSpec("Unordered List", "InsertUnorderedList"),
      new MenuSpec("Unordered List Item", "InsertUnorderedListItem"),
      new MenuSpec("Ordered List", "InsertOrderedList"),
      new MenuSpec("Ordered List Item", "InsertOrderedListItem"),
      new MenuSpec("Preformatted Paragraph", "InsertPre"),
      new MenuSpec("Horizontal Rule", "InsertHR") };
}
class MenuSpec {
  public MenuSpec(String name, MenuSpec[] subMenus) {
    this.name = name;
    this.subMenus = subMenus;
  }
  public MenuSpec(String name, String actionName) {
    this.name = name;
    this.actionName = actionName;
  }
  public MenuSpec(String name, Action action) {
    this.name = name;
    this.action = action;
  }
  public boolean isSubMenu() {
    return subMenus != null;
  }
  public boolean isAction() {
    return action != null;
  }
  public String getName() {
    return name;
  }
  public MenuSpec[] getSubMenus() {
    return subMenus;
  }
  public String getActionName() {
    return actionName;
  }
  public Action getAction() {
    return action;
  }
  private String name;
  private String actionName;
  private Action action;
  private MenuSpec[] subMenus;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}
class MenuBuilder {
  public static JMenu buildMenu(String name, MenuSpec[] menuSpecs,
      Hashtable actions) {
    int count = menuSpecs.length;
    JMenu menu = new JMenu(name);
    for (int i = 0; i < count; i++) {
      MenuSpec spec = menuSpecs[i];
      if (spec.isSubMenu()) {
        // Recurse to handle a sub menu
        JMenu subMenu = buildMenu(spec.getName(), spec.getSubMenus(),
            actions);
        if (subMenu != null) {
          menu.add(subMenu);
        }
      } else if (spec.isAction()) {
        // It"s an Action - add it directly to the menu
        menu.add(spec.getAction());
      } else {
        // It"s an action name - add it if possible
        String actionName = spec.getActionName();
        Action targetAction = (Action) actions.get(actionName);
        // Create the menu item
        JMenuItem menuItem = menu.add(spec.getName());
        if (targetAction != null) {
          // The editor kit knows the action
          menuItem.addActionListener(targetAction);
        } else {
          // Action not known - disable the menu item
          menuItem.setEnabled(false);
        }
      }
    }
    // Return null if nothing was added to the menu.
    if (menu.getMenuComponentCount() == 0) {
      menu = null;
    }
    return menu;
  }
}





JEditorPane Example 19

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.rtf.*;
public class EditorPaneExample19 extends JFrame {
  public EditorPaneExample19() {
    super("JEditorPane Example 19");
  
    pane = new JEditorPane();
    pane.setEditable(true);    // Editable
    getContentPane().add(new JScrollPane(pane), "Center");
    // Add a menu bar
    menuBar = new JMenuBar();
    setJMenuBar(menuBar);
    // Populate it
    createMenuBar();
    
    // Build the panel of controls
    JPanel panel = new JPanel();
    
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);    
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridy = 5;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    editableBox = new JCheckBox("Editable JEditorPane");
    panel.add(editableBox, c);
    editableBox.setSelected(true);
    editableBox.setForeground(typeLabel.getForeground());
    c.gridy = 6;
    c.weightx = 0.0;
    JButton saveButton = new JButton("Save");
    panel.add(saveButton, c);
    saveButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        EditorKit kit = pane.getEditorKit();
        try {
          if (kit instanceof RTFEditorKit) {
            kit.write(System.out, pane.getDocument(), 
              0, pane.getDocument().getLength());
            System.out.flush();
          } else {
            if (writer == null) {
              writer = new OutputStreamWriter(System.out);
              pane.write(writer);
              writer.flush();
            }
            kit.write(writer, pane.getDocument(), 
              0, pane.getDocument().getLength());
            writer.flush();
          }
        } catch (Exception e) {
          System.out.println("Write failed");
        }
      }
    });
    
    c.gridx = 1;
    c.gridy = 0;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;  
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    
    getContentPane().add(panel, "South");
    // Register a custom EditorKit for HTML
    ClassLoader loader = getClass().getClassLoader();
    if (loader != null) {
      // Java 2
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.EnhancedHTMLEditorKit",
          loader);
    } else {
      // JDK 1.1
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.EnhancedHTMLEditorKit");
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode("Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    
    // Change editability based on the checkbox
    editableBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editableBox.isSelected());
        pane.revalidate();
        pane.repaint();
      }
    });  
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          createMenuBar();
          enableMenuBar(true);
          getRootPane().revalidate();
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = 
                (DefaultMutableTreeNode)path.getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading)userObject;
            try {
              Rectangle textRect = pane.modelToView(heading.getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);                          
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane)evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument)sp.getDocument();
            doc.processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent)evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL)page;
      } else {
        url = new URL((String)page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      enableMenuBar(false);
      urlCombo.paintImmediately(0, 0, 
                  menuBar.getSize().width,
                  menuBar.getSize().height);
      // Try to display the page
      urlCombo.setEnabled(false);    // Disable input
      urlCombo.paintImmediately(0, 0, 
                  urlCombo.getSize().width,
                  urlCombo.getSize().height);
      setCursor(waitCursor);    // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, 
                  loadingState.getSize().width,
                  loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, 
                  loadedType.getSize().width,
                  loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, 
                  timeLabel.getSize().width,
                  timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, 
                  tree.getSize().width,
                  tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method          
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        createMenuBar();
        enableMenuBar(true);
        getRootPane().revalidate();
        enableInput();
        loadingPage = false;
      }            
    } catch (Exception e) {
      System.out.println(e);          
      JOptionPane.showMessageDialog(pane, 
        new String[] {
          "Unable to open file",
          page.toString()
        }, "File Open Error", 
        JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableMenuBar(true);
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true);    // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
  }
  public void displayLoadTime() {
    double loadingTime = ((double)(System.currentTimeMillis() - startTime))/1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public void enableMenuBar(boolean cond) {
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.getMenu(i).setEnabled(cond);
    }
  }
  public void createMenuBar() {
    // Remove the existing menu items
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.remove(menuBar.getMenu(0));
    }
    // Build the new menu.
    Action[] actions = pane.getActions();
    Hashtable actionHash = new Hashtable();
    count = actions.length;
    for (int i = 0; i < count; i++) {
      actionHash.put(actions[i].getValue(Action.NAME), actions[i]);
    }
    // Add the font menu
    JMenu menu = MenuBuilder.buildMenu("Font", fontSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the alignment menu
    menu = MenuBuilder.buildMenu("Align", alignSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the HTML menu
    menu = MenuBuilder.buildMenu("HTML", htmlSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL)doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet)link).getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String)linkAttr);
              if (protocol == null || 
                  protocol.equalsIgnoreCase(linkURL.getProtocol())) {
                String linkURLName = linkURL.toString();              
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String)doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {      
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }      
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) ==
            HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, 
                      child.getEndOffset() - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText,
                    level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public JEditorPane getEditorPane() {
    return pane;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample19();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JCheckBox editableBox;
  private JTree tree;
  private TreeModel emptyModel;
  private JMenuBar menuBar;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = 
          Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = 
          Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = 
          Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  private OutputStreamWriter writer;
  
  private static MenuSpec[] sizeSpec = new MenuSpec[] {
      new MenuSpec("Size 8",  "font-size-8"),
      new MenuSpec("Size 10", "font-size-10"),
      new MenuSpec("Size 12", "font-size-12"),
      new MenuSpec("Size 14", "font-size-14"),
      new MenuSpec("Size 16", "font-size-16"),
      new MenuSpec("Size 18", "font-size-18"),
      new MenuSpec("Size 24", "font-size-24"),
      new MenuSpec("Size 36", "font-size-36"),
      new MenuSpec("Size 48", "font-size-48")          
  };
  private static MenuSpec[] familySpec = new MenuSpec[] {
      new MenuSpec("Sans Serif", "font-family-SansSerif"),
      new MenuSpec("Monospaced", "font-family-Monospaced"),
      new MenuSpec("Serif", "font-family-Serif")
  };
  private static MenuSpec[] styleSpec = new MenuSpec[] {
      new MenuSpec("Bold", "font-bold"),
      new MenuSpec("Italics", "font-italic"),
      new MenuSpec("Underline", "font-underline")
  };
  // Menu definitions for fonts
  private static MenuSpec[] fontSpec = new MenuSpec[] {
      new MenuSpec("Size", sizeSpec),
      new MenuSpec("Family", familySpec),
      new MenuSpec("Style", styleSpec)
  };
  // Alignment
  private static MenuSpec[] alignSpec = new MenuSpec[] {
      new MenuSpec("Left", "left-justify"),
      new MenuSpec("Center", "center-justify"),
      new MenuSpec("Right", "right-justify")
  };
  // HTML menu
  private static MenuSpec[] headingSpec = new MenuSpec[] {
    new MenuSpec("Heading 1", "Heading 1"),
    new MenuSpec("Heading 2", "Heading 2")
  };
  private static MenuSpec[] htmlSpec = new MenuSpec[] {
    new MenuSpec("Table", "InsertTable"),
    new MenuSpec("Table Row", "InsertTableRow"),
    new MenuSpec("Table Cell", "InsertTableDataCell"),
    new MenuSpec("Unordered List", "InsertUnorderedList"),
    new MenuSpec("Unordered List Item", "InsertUnorderedListItem"),
    new MenuSpec("Ordered List", "InsertOrderedList"),
    new MenuSpec("Ordered List Item", "InsertOrderedListItem"),
    new MenuSpec("Preformatted Paragraph", "InsertPre"),
    new MenuSpec("Horizontal Rule", "InsertHR"),
    new MenuSpec("Headings", headingSpec)
  };
}
class MenuSpec {
  public MenuSpec(String name, MenuSpec[] subMenus) {
    this.name = name;
    this.subMenus = subMenus;
  }
  public MenuSpec(String name, String actionName) {
    this.name = name;
    this.actionName = actionName;
  }
  public MenuSpec(String name, Action action) {
    this.name = name;
    this.action = action;
  }
  public boolean isSubMenu() {
    return subMenus != null;
  }
  public boolean isAction() {
    return action != null;
  }
  public String getName() {
    return name;
  }
  public MenuSpec[] getSubMenus() {
    return subMenus;
  }
  public String getActionName() {
    return actionName;
  }
  public Action getAction() {
    return action;
  }
  private String name;
  private String actionName;
  private Action action;
  private MenuSpec[] subMenus;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}
class MenuBuilder {
  public static JMenu buildMenu(String name, MenuSpec[] menuSpecs,
      Hashtable actions) {
    int count = menuSpecs.length;
    JMenu menu = new JMenu(name);
    for (int i = 0; i < count; i++) {
      MenuSpec spec = menuSpecs[i];
      if (spec.isSubMenu()) {
        // Recurse to handle a sub menu
        JMenu subMenu = buildMenu(spec.getName(), spec.getSubMenus(),
            actions);
        if (subMenu != null) {
          menu.add(subMenu);
        }
      } else if (spec.isAction()) {
        // It"s an Action - add it directly to the menu
        menu.add(spec.getAction());
      } else {
        // It"s an action name - add it if possible
        String actionName = spec.getActionName();
        Action targetAction = (Action) actions.get(actionName);
        // Create the menu item
        JMenuItem menuItem = menu.add(spec.getName());
        if (targetAction != null) {
          // The editor kit knows the action
          menuItem.addActionListener(targetAction);
        } else {
          // Action not known - disable the menu item
          menuItem.setEnabled(false);
        }
      }
    }
    // Return null if nothing was added to the menu.
    if (menu.getMenuComponentCount() == 0) {
      menu = null;
    }
    return menu;
  }
}





JEditorPane Example 20

   
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.text.rtf.RTFEditorKit;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditorPaneExample20 extends JFrame {
  public EditorPaneExample20() {
    super("JEditorPane Example 20");
    pane = new JEditorPane();
    pane.setEditable(true); // Editable
    getContentPane().add(new JScrollPane(pane), "Center");
    // Add a menu bar
    menuBar = new JMenuBar();
    setJMenuBar(menuBar);
    // Populate it
    createMenuBar();
    // Build the panel of controls
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = 1;
    c.gridheight = 1;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.NONE;
    c.weightx = 0.0;
    c.weighty = 0.0;
    JLabel urlLabel = new JLabel("URL: ", JLabel.RIGHT);
    panel.add(urlLabel, c);
    JLabel loadingLabel = new JLabel("State: ", JLabel.RIGHT);
    c.gridy = 1;
    panel.add(loadingLabel, c);
    JLabel typeLabel = new JLabel("Type: ", JLabel.RIGHT);
    c.gridy = 2;
    panel.add(typeLabel, c);
    c.gridy = 3;
    panel.add(new JLabel(LOAD_TIME), c);
    c.gridy = 4;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    onlineLoad = new JCheckBox("Online Load");
    panel.add(onlineLoad, c);
    onlineLoad.setSelected(true);
    onlineLoad.setForeground(typeLabel.getForeground());
    c.gridy = 5;
    c.gridwidth = 2;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.WEST;
    editableBox = new JCheckBox("Editable JEditorPane");
    panel.add(editableBox, c);
    editableBox.setSelected(true);
    editableBox.setForeground(typeLabel.getForeground());
    c.gridy = 6;
    c.weightx = 0.0;
    JButton saveButton = new JButton("Save");
    panel.add(saveButton, c);
    saveButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        EditorKit kit = pane.getEditorKit();
        try {
          if (kit instanceof RTFEditorKit) {
            kit.write(System.out, pane.getDocument(), 0, pane
                .getDocument().getLength());
            System.out.flush();
          } else {
            if (writer == null) {
              writer = new OutputStreamWriter(System.out);
              pane.write(writer);
              writer.flush();
            }
            kit.write(writer, pane.getDocument(), 0, pane
                .getDocument().getLength());
            writer.flush();
          }
        } catch (Exception e) {
          System.out.println("Write failed");
        }
      }
    });
    c.gridx = 1;
    insertButton = new JButton("Insert HTML");
    panel.add(insertButton, c);
    insertButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (insertFrame == null) {
          insertFrame = new HTMLInsertFrame("HTML Insertion", pane);
          Point pt = EditorPaneExample20.this.getLocationOnScreen();
          Dimension d = EditorPaneExample20.this.getSize();
          insertFrame.setLocation(pt.x + d.width, pt.y);
          insertFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
              insertFrame.dispose();
              insertFrame = null;
              setInsertButtonState();
            }
          });
          insertButton.setEnabled(false);
          insertFrame.setVisible(true);
        }
      }
    });
    insertButton.setEnabled(false);
    c.gridx = 1;
    c.gridy = 0;
    c.weightx = 1.0;
    c.anchor = GridBagConstraints.EAST;
    c.fill = GridBagConstraints.HORIZONTAL;
    urlCombo = new JComboBox();
    panel.add(urlCombo, c);
    urlCombo.setEditable(true);
    loadingState = new JLabel(spaces, JLabel.LEFT);
    loadingState.setForeground(Color.black);
    c.gridy = 1;
    panel.add(loadingState, c);
    loadedType = new JLabel(spaces, JLabel.LEFT);
    loadedType.setForeground(Color.black);
    c.gridy = 2;
    panel.add(loadedType, c);
    timeLabel = new JLabel("");
    c.gridy = 3;
    panel.add(timeLabel, c);
    getContentPane().add(panel, "South");
    // Register a custom EditorKit for HTML
    ClassLoader loader = getClass().getClassLoader();
    if (loader != null) {
      // Java 2
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.EnhancedHTMLEditorKit", loader);
    } else {
      // JDK 1.1
      JEditorPane.registerEditorKitForContentType("text/html",
          "AdvancedSwing.Chapter4.EnhancedHTMLEditorKit");
    }
    // Allocate the empty tree model
    DefaultMutableTreeNode emptyRootNode = new DefaultMutableTreeNode(
        "Empty");
    emptyModel = new DefaultTreeModel(emptyRootNode);
    // Create and place the heading tree
    tree = new JTree(emptyModel);
    tree.setPreferredSize(new Dimension(200, 200));
    getContentPane().add(new JScrollPane(tree), "East");
    // Change page based on combo selection
    urlCombo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        if (populatingCombo == true) {
          return;
        }
        Object selection = urlCombo.getSelectedItem();
        loadNewPage(selection);
      }
    });
    // Change editability based on the checkbox
    editableBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editableBox.isSelected());
        pane.revalidate();
        pane.repaint();
      }
    });
    // Listen for page load to complete
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          loadComplete();
          displayLoadTime();
          populateCombo(findLinks(pane.getDocument(), null));
          TreeNode node = buildHeadingTree(pane.getDocument());
          tree.setModel(new DefaultTreeModel(node));
          createMenuBar();
          enableMenuBar(true);
          getRootPane().revalidate();
          enableInput();
          loadingPage = false;
        }
      }
    });
    // Listener for tree selection
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath path = evt.getNewLeadSelectionPath();
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
              .getLastPathComponent();
          Object userObject = node.getUserObject();
          if (userObject instanceof Heading) {
            Heading heading = (Heading) userObject;
            try {
              Rectangle textRect = pane.modelToView(heading
                  .getOffset());
              textRect.y += 3 * textRect.height;
              pane.scrollRectToVisible(textRect);
            } catch (BadLocationException e) {
            }
          }
        }
      }
    });
    // Listener for hypertext events
    pane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent evt) {
        // Ignore hyperlink events if the frame is busy
        if (loadingPage == true) {
          return;
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          JEditorPane sp = (JEditorPane) evt.getSource();
          if (evt instanceof HTMLFrameHyperlinkEvent) {
            HTMLDocument doc = (HTMLDocument) sp.getDocument();
            doc
                .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) evt);
          } else {
            loadNewPage(evt.getURL());
          }
        } else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          pane.setCursor(handCursor);
        } else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(defaultCursor);
        }
      }
    });
  }
  public void loadNewPage(Object page) {
    try {
      loadingPage = true;
      // Check if the new page and the old
      // page are the same.
      URL url;
      if (page instanceof URL) {
        url = (URL) page;
      } else {
        url = new URL((String) page);
      }
      urlCombo.setSelectedItem(page);
      URL loadedURL = pane.getPage();
      if (loadedURL != null && loadedURL.sameFile(url)) {
        return;
      }
      enableMenuBar(false);
      urlCombo.paintImmediately(0, 0, menuBar.getSize().width, menuBar
          .getSize().height);
      // Try to display the page
      urlCombo.setEnabled(false); // Disable input
      urlCombo.paintImmediately(0, 0, urlCombo.getSize().width, urlCombo
          .getSize().height);
      setCursor(waitCursor); // Busy cursor
      loadingState.setText("Loading...");
      loadingState.paintImmediately(0, 0, loadingState.getSize().width,
          loadingState.getSize().height);
      loadedType.setText("");
      loadedType.paintImmediately(0, 0, loadedType.getSize().width,
          loadedType.getSize().height);
      timeLabel.setText("");
      timeLabel.paintImmediately(0, 0, timeLabel.getSize().width,
          timeLabel.getSize().height);
      // Display an empty tree while loading
      tree.setModel(emptyModel);
      tree.paintImmediately(0, 0, tree.getSize().width,
          tree.getSize().height);
      startTime = System.currentTimeMillis();
      // Choose the loading method
      if (onlineLoad.isSelected()) {
        // Usual load via setPage
        pane.setPage(url);
        loadedType.setText(pane.getContentType());
      } else {
        pane.setContentType("text/html");
        loadedType.setText(pane.getContentType());
        if (loader == null) {
          loader = new HTMLDocumentLoader();
        }
        HTMLDocument doc = loader.loadDocument(url);
        loadComplete();
        pane.setDocument(doc);
        displayLoadTime();
        populateCombo(findLinks(doc, null));
        TreeNode node = buildHeadingTree(doc);
        tree.setModel(new DefaultTreeModel(node));
        createMenuBar();
        enableMenuBar(true);
        getRootPane().revalidate();
        enableInput();
        loadingPage = false;
      }
    } catch (Exception e) {
      System.out.println(e);
      JOptionPane.showMessageDialog(pane, new String[] {
          "Unable to open file", page.toString() },
          "File Open Error", JOptionPane.ERROR_MESSAGE);
      loadingState.setText("Failed");
      enableMenuBar(true);
      enableInput();
      loadingPage = false;
    }
  }
  public void loadComplete() {
    loadingState.setText("Page loaded.");
  }
  public void enableInput() {
    urlCombo.setEnabled(true); // Allow entry of new URL
    setCursor(defaultCursor);
    pane.setCursor(defaultCursor);
    setInsertButtonState();
  }
  public void displayLoadTime() {
    double loadingTime = ((double) (System.currentTimeMillis() - startTime)) / 1000d;
    timeLabel.setText(loadingTime + " seconds");
  }
  public void populateCombo(URL[] urls) {
    // Save existing selection
    Object o = urlCombo.getSelectedItem();
    populatingCombo = true;
    urlCombo.setModel(new DefaultComboBoxModel(urls));
    // Restore original selection
    urlCombo.setSelectedItem(o);
    populatingCombo = false;
  }
  public void enableMenuBar(boolean cond) {
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.getMenu(i).setEnabled(cond);
    }
  }
  public void createMenuBar() {
    // Remove the existing menu items
    int count = menuBar.getMenuCount();
    for (int i = 0; i < count; i++) {
      menuBar.remove(menuBar.getMenu(0));
    }
    // Build the new menu.
    Action[] actions = pane.getActions();
    Hashtable actionHash = new Hashtable();
    count = actions.length;
    for (int i = 0; i < count; i++) {
      actionHash.put(actions[i].getValue(Action.NAME), actions[i]);
    }
    // Add the font menu
    JMenu menu = MenuBuilder.buildMenu("Font", fontSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the alignment menu
    menu = MenuBuilder.buildMenu("Align", alignSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
    // Add the HTML menu
    menu = MenuBuilder.buildMenu("HTML", htmlSpec, actionHash);
    if (menu != null) {
      menuBar.add(menu);
    }
  }
  public void setInsertButtonState() {
    EditorKit kit = pane.getEditorKit();
    insertButton.setEnabled(kit instanceof HTMLEditorKit
        && insertFrame == null);
  }
  public URL[] findLinks(Document doc, String protocol) {
    Vector links = new Vector();
    Vector urlNames = new Vector();
    URL baseURL = (URL) doc.getProperty(Document.StreamDescriptionProperty);
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      while ((elem = iterator.next()) != null) {
        AttributeSet attrs = elem.getAttributes();
        Object link = attrs.getAttribute(HTML.Tag.A);
        if (link instanceof AttributeSet) {
          Object linkAttr = ((AttributeSet) link)
              .getAttribute(HTML.Attribute.HREF);
          if (linkAttr instanceof String) {
            try {
              URL linkURL = new URL(baseURL, (String) linkAttr);
              if (protocol == null
                  || protocol.equalsIgnoreCase(linkURL
                      .getProtocol())) {
                String linkURLName = linkURL.toString();
                if (urlNames.contains(linkURLName) == false) {
                  urlNames.addElement(linkURLName);
                  links.addElement(linkURL);
                }
              }
            } catch (MalformedURLException e) {
              // Ignore invalid links
            }
          }
        }
      }
    }
    URL[] urls = new URL[links.size()];
    links.copyInto(urls);
    links.removeAllElements();
    urlNames.removeAllElements();
    return urls;
  }
  public TreeNode buildHeadingTree(Document doc) {
    String title = (String) doc.getProperty(Document.TitleProperty);
    if (title == null) {
      title = "[No title]";
    }
    Heading rootHeading = new Heading(title, 0, 0);
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        rootHeading);
    DefaultMutableTreeNode lastNode[] = new DefaultMutableTreeNode[7];
    int lastLevel = 0;
    lastNode[lastLevel] = rootNode;
    if (doc instanceof HTMLDocument) {
      Element elem = doc.getDefaultRootElement();
      ElementIterator iterator = new ElementIterator(elem);
      Heading heading;
      while ((heading = getNextHeading(doc, iterator)) != null) {
        // Add the node to the tree
        DefaultMutableTreeNode hNode = new DefaultMutableTreeNode(
            heading);
        int level = heading.getLevel();
        if (level > lastLevel) {
          for (int i = lastLevel + 1; i < level; i++) {
            lastNode[i] = null;
          }
          lastNode[lastLevel].add(hNode);
        } else {
          int prevLevel = level - 1;
          while (prevLevel >= 0) {
            if (lastNode[prevLevel] != null) {
              break;
            }
            lastNode[prevLevel] = null;
            prevLevel--;
          }
          lastNode[prevLevel].add(hNode);
        }
        lastNode[level] = hNode;
        lastLevel = level;
      }
    }
    return rootNode;
  }
  public Heading getNextHeading(Document doc, ElementIterator iter) {
    Element elem;
    while ((elem = iter.next()) != null) {
      AttributeSet attrs = elem.getAttributes();
      Object type = attrs.getAttribute(StyleConstants.NameAttribute);
      int level = getHeadingLevel(type);
      if (level > 0) {
        // It is a heading - get the text
        String headingText = "";
        int count = elem.getElementCount();
        for (int i = 0; i < count; i++) {
          Element child = elem.getElement(i);
          AttributeSet cattrs = child.getAttributes();
          if (cattrs.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.CONTENT) {
            try {
              int offset = child.getStartOffset();
              headingText += doc.getText(offset, child
                  .getEndOffset()
                  - offset);
            } catch (BadLocationException e) {
            }
          }
        }
        headingText = headingText.trim();
        return new Heading(headingText, level, elem.getStartOffset());
      }
    }
    return null;
  }
  public int getHeadingLevel(Object type) {
    if (type instanceof HTML.Tag) {
      if (type == HTML.Tag.H1) {
        return 1;
      }
      if (type == HTML.Tag.H2) {
        return 2;
      }
      if (type == HTML.Tag.H3) {
        return 3;
      }
      if (type == HTML.Tag.H4) {
        return 4;
      }
      if (type == HTML.Tag.H5) {
        return 5;
      }
      if (type == HTML.Tag.H6) {
        return 6;
      }
    }
    return -1;
  }
  static class Heading {
    public Heading(String text, int level, int offset) {
      this.text = text;
      this.level = level;
      this.offset = offset;
    }
    public String getText() {
      return text;
    }
    public int getOffset() {
      return offset;
    }
    public int getLevel() {
      return level;
    }
    public String toString() {
      return text;
    }
    protected String text;
    protected int level;
    protected int offset;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new EditorPaneExample20();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setSize(500, 400);
    f.setVisible(true);
  }
  private static final String spaces = "                    ";
  private static final String LOAD_TIME = "Load time: ";
  private HTMLDocumentLoader loader;
  private JEditorPane pane;
  private JLabel loadingState;
  private JLabel loadedType;
  private JLabel timeLabel;
  private JComboBox urlCombo;
  private JCheckBox onlineLoad;
  private JCheckBox editableBox;
  private JTree tree;
  private TreeModel emptyModel;
  private JMenuBar menuBar;
  private JFrame insertFrame;
  private JButton insertButton;
  private long startTime;
  private boolean populatingCombo;
  private boolean loadingPage;
  private static final Cursor waitCursor = Cursor
      .getPredefinedCursor(Cursor.WAIT_CURSOR);
  private static final Cursor defaultCursor = Cursor
      .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private static final Cursor handCursor = Cursor
      .getPredefinedCursor(Cursor.HAND_CURSOR);
  private OutputStreamWriter writer;
  private static MenuSpec[] sizeSpec = new MenuSpec[] {
      new MenuSpec("Size 8", "font-size-8"),
      new MenuSpec("Size 10", "font-size-10"),
      new MenuSpec("Size 12", "font-size-12"),
      new MenuSpec("Size 14", "font-size-14"),
      new MenuSpec("Size 16", "font-size-16"),
      new MenuSpec("Size 18", "font-size-18"),
      new MenuSpec("Size 24", "font-size-24"),
      new MenuSpec("Size 36", "font-size-36"),
      new MenuSpec("Size 48", "font-size-48") };
  private static MenuSpec[] familySpec = new MenuSpec[] {
      new MenuSpec("Sans Serif", "font-family-SansSerif"),
      new MenuSpec("Monospaced", "font-family-Monospaced"),
      new MenuSpec("Serif", "font-family-Serif") };
  private static MenuSpec[] styleSpec = new MenuSpec[] {
      new MenuSpec("Bold", "font-bold"),
      new MenuSpec("Italics", "font-italic"),
      new MenuSpec("Underline", "font-underline") };
  // Menu definitions for fonts
  private static MenuSpec[] fontSpec = new MenuSpec[] {
      new MenuSpec("Size", sizeSpec), new MenuSpec("Family", familySpec),
      new MenuSpec("Style", styleSpec) };
  // Alignment
  private static MenuSpec[] alignSpec = new MenuSpec[] {
      new MenuSpec("Left", "left-justify"),
      new MenuSpec("Center", "center-justify"),
      new MenuSpec("Right", "right-justify") };
  // HTML menu
  private static MenuSpec[] headingSpec = new MenuSpec[] {
      new MenuSpec("Heading 1", "Heading 1"),
      new MenuSpec("Heading 2", "Heading 2") };
  private static MenuSpec[] htmlSpec = new MenuSpec[] {
      new MenuSpec("Table", "InsertTable"),
      new MenuSpec("Table Row", "InsertTableRow"),
      new MenuSpec("Table Cell", "InsertTableDataCell"),
      new MenuSpec("Unordered List", "InsertUnorderedList"),
      new MenuSpec("Unordered List Item", "InsertUnorderedListItem"),
      new MenuSpec("Ordered List", "InsertOrderedList"),
      new MenuSpec("Ordered List Item", "InsertOrderedListItem"),
      new MenuSpec("Preformatted Paragraph", "InsertPre"),
      new MenuSpec("Horizontal Rule", "InsertHR"),
      new MenuSpec("Headings", headingSpec) };
}
class MenuSpec {
  public MenuSpec(String name, MenuSpec[] subMenus) {
    this.name = name;
    this.subMenus = subMenus;
  }
  public MenuSpec(String name, String actionName) {
    this.name = name;
    this.actionName = actionName;
  }
  public MenuSpec(String name, Action action) {
    this.name = name;
    this.action = action;
  }
  public boolean isSubMenu() {
    return subMenus != null;
  }
  public boolean isAction() {
    return action != null;
  }
  public String getName() {
    return name;
  }
  public MenuSpec[] getSubMenus() {
    return subMenus;
  }
  public String getActionName() {
    return actionName;
  }
  public Action getAction() {
    return action;
  }
  private String name;
  private String actionName;
  private Action action;
  private MenuSpec[] subMenus;
}
class HTMLDocumentLoader {
  public HTMLDocument loadDocument(HTMLDocument doc, URL url, String charSet)
      throws IOException {
    doc.putProperty(Document.StreamDescriptionProperty, url);
    /*
     * This loop allows the document read to be retried if the character
     * encoding changes during processing.
     */
    InputStream in = null;
    boolean ignoreCharSet = false;
    for (;;) {
      try {
        // Remove any document content
        doc.remove(0, doc.getLength());
        URLConnection urlc = url.openConnection();
        in = urlc.getInputStream();
        Reader reader = (charSet == null) ? new InputStreamReader(in)
            : new InputStreamReader(in, charSet);
        HTMLEditorKit.Parser parser = getParser();
        HTMLEditorKit.ParserCallback htmlReader = getParserCallback(doc);
        parser.parse(reader, htmlReader, ignoreCharSet);
        htmlReader.flush();
        // All done
        break;
      } catch (BadLocationException ex) {
        // Should not happen - throw an IOException
        throw new IOException(ex.getMessage());
      } catch (ChangedCharSetException e) {
        // The character set has changed - restart
        charSet = getNewCharSet(e);
        // Prevent recursion by suppressing further exceptions
        ignoreCharSet = true;
        // Close original input stream
        in.close();
        // Continue the loop to read with the correct encoding
      }
    }
    return doc;
  }
  public HTMLDocument loadDocument(URL url, String charSet)
      throws IOException {
    return loadDocument((HTMLDocument) kit.createDefaultDocument(), url,
        charSet);
  }
  public HTMLDocument loadDocument(URL url) throws IOException {
    return loadDocument(url, null);
  }
  // Methods that allow customization of the parser and the callback
  public synchronized HTMLEditorKit.Parser getParser() {
    if (parser == null) {
      try {
        Class c = Class
            .forName("javax.swing.text.html.parser.ParserDelegator");
        parser = (HTMLEditorKit.Parser) c.newInstance();
      } catch (Throwable e) {
      }
    }
    return parser;
  }
  public synchronized HTMLEditorKit.ParserCallback getParserCallback(
      HTMLDocument doc) {
    return doc.getReader(0);
  }
  protected String getNewCharSet(ChangedCharSetException e) {
    String spec = e.getCharSetSpec();
    if (e.keyEqualsCharSet()) {
      // The event contains the new CharSet
      return spec;
    }
    // The event contains the content type
    // plus ";" plus qualifiers which may
    // contain a "charset" directive. First
    // remove the content type.
    int index = spec.indexOf(";");
    if (index != -1) {
      spec = spec.substring(index + 1);
    }
    // Force the string to lower case
    spec = spec.toLowerCase();
    StringTokenizer st = new StringTokenizer(spec, " \t=", true);
    boolean foundCharSet = false;
    boolean foundEquals = false;
    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      if (token.equals(" ") || token.equals("\t")) {
        continue;
      }
      if (foundCharSet == false && foundEquals == false
          && token.equals("charset")) {
        foundCharSet = true;
        continue;
      } else if (foundEquals == false && token.equals("=")) {
        foundEquals = true;
        continue;
      } else if (foundEquals == true && foundCharSet == true) {
        return token;
      }
      // Not recognized
      foundCharSet = false;
      foundEquals = false;
    }
    // No charset found - return a guess
    return "8859_1";
  }
  protected static HTMLEditorKit kit;
  protected static HTMLEditorKit.Parser parser;
  static {
    kit = new HTMLEditorKit();
  }
}
class MenuBuilder {
  public static JMenu buildMenu(String name, MenuSpec[] menuSpecs,
      Hashtable actions) {
    int count = menuSpecs.length;
    JMenu menu = new JMenu(name);
    for (int i = 0; i < count; i++) {
      MenuSpec spec = menuSpecs[i];
      if (spec.isSubMenu()) {
        // Recurse to handle a sub menu
        JMenu subMenu = buildMenu(spec.getName(), spec.getSubMenus(),
            actions);
        if (subMenu != null) {
          menu.add(subMenu);
        }
      } else if (spec.isAction()) {
        // It"s an Action - add it directly to the menu
        menu.add(spec.getAction());
      } else {
        // It"s an action name - add it if possible
        String actionName = spec.getActionName();
        Action targetAction = (Action) actions.get(actionName);
        // Create the menu item
        JMenuItem menuItem = menu.add(spec.getName());
        if (targetAction != null) {
          // The editor kit knows the action
          menuItem.addActionListener(targetAction);
        } else {
          // Action not known - disable the menu item
          menuItem.setEnabled(false);
        }
      }
    }
    // Return null if nothing was added to the menu.
    if (menu.getMenuComponentCount() == 0) {
      menu = null;
    }
    return menu;
  }
}
class HTMLInsertFrame extends JFrame {
  public HTMLInsertFrame(String title, JEditorPane editor) {
    super(title);
    this.pane = editor;
    // Build the layout
    textArea = new JTextArea(10, 32);
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    insertButton = new JButton("Insert HTML");
    JPanel topPanel = new JPanel(new BorderLayout());
    topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
        .createEtchedBorder(), "HTML Source", TitledBorder.CENTER,
        TitledBorder.TOP));
    topPanel.add(new JScrollPane(textArea), BorderLayout.CENTER);
    JPanel bottomPanel = new JPanel();
    bottomPanel.add(insertButton);
    getContentPane().add(topPanel, BorderLayout.CENTER);
    getContentPane().add(bottomPanel, BorderLayout.SOUTH);
    pane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("page")) {
          setGUIState();
        }
      }
    });
    insertButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        EditorKit kit = pane.getEditorKit();
        if (kit instanceof HTMLEditorKit) {
          String htmlString = textArea.getText();
          if (htmlString.trim().equals("") == false) {
            try {
              ((HTMLEditorKit) kit).read(new StringReader(
                  htmlString), pane.getDocument(), pane
                  .getCaretPosition());
            } catch (Exception e) {
            }
          }
        }
      }
    });
    setGUIState(); // Disable if not HTML content
    pack();
  }
  private void setGUIState() {
    boolean editingHTML = pane.getEditorKit() instanceof HTMLEditorKit;
    textArea.setEnabled(editingHTML);
    insertButton.setEnabled(editingHTML);
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new HTMLInsertFrame("Custom HTML Insertion",
        new JEditorPane());
    f.setVisible(true);
  }
  private JEditorPane pane;
  private JTextArea textArea;
  private JButton insertButton;
}





Locates the end of the word at the specified position.

   
/*
 * TextUtilities.java - Utility functions used by the text area classes
 * Copyright (C) 1999 Slava Pestov
 *
 * You may use and modify this package for any purpose. Redistribution is
 * permitted, in both source and binary form, provided that this notice
 * remains intact in all source distributions of this package.
 */

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
 * Class with several utility functions used by the text area component.
 * 
 * @author Slava Pestov
 * @version $Id$
 */
public class TextUtilities
{
  /**
   * Locates the end of the word at the specified position.
   * 
   * @param line
   *           The text
   * @param pos
   *           The position
   */
  public static int findWordEnd( String line, int pos, String noWordSep )
  {
    char ch = line.charAt( pos );
    if( noWordSep == null )
      noWordSep = "";
    boolean selectNoLetter = ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 );
    int wordEnd = line.length();
    for( int i = pos; i < line.length(); i++ )
    {
      ch = line.charAt( i );
      if( selectNoLetter ^ ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 ) )
      {
        wordEnd = i;
        break;
      }
    }
    return wordEnd;
  }
}





Locates the start of the word at the specified position.

   
/*
 * TextUtilities.java - Utility functions used by the text area classes
 * Copyright (C) 1999 Slava Pestov
 *
 * You may use and modify this package for any purpose. Redistribution is
 * permitted, in both source and binary form, provided that this notice
 * remains intact in all source distributions of this package.
 */

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
 * Class with several utility functions used by the text area component.
 * 
 * @author Slava Pestov
 * @version $Id$
 */
public class TextUtilities
{
  /**
   * Locates the start of the word at the specified position.
   * 
   * @param line
   *           The text
   * @param pos
   *           The position
   */
  public static int findWordStart( String line, int pos, String noWordSep )
  {
    char ch = line.charAt( pos - 1 );
    if( noWordSep == null )
      noWordSep = "";
    boolean selectNoLetter = ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 );
    int wordStart = 0;
    for( int i = pos - 1; i >= 0; i-- )
    {
      ch = line.charAt( i );
      if( selectNoLetter ^ ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 ) )
      {
        wordStart = i + 1;
        break;
      }
    }
    return wordStart;
  }

}





Returns the offset of the bracket matching the one at the specified offset of the document

   
/*
 * TextUtilities.java - Utility functions used by the text area classes
 * Copyright (C) 1999 Slava Pestov
 *
 * You may use and modify this package for any purpose. Redistribution is
 * permitted, in both source and binary form, provided that this notice
 * remains intact in all source distributions of this package.
 */

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
 * Class with several utility functions used by the text area component.
 * 
 * @author Slava Pestov
 * @version $Id$
 */
public class TextUtilities
{
  /**
   * Returns the offset of the bracket matching the one at the specified offset
   * of the document, or -1 if the bracket is unmatched (or if the character is
   * not a bracket).
   * 
   * @param doc
   *           The document
   * @param offset
   *           The offset
   * @exception BadLocationException
   *               If an out-of-bounds access was attempted on the document
   *               text
   */
  public static int findMatchingBracket( Document doc, int offset ) throws BadLocationException
  {
    if( doc.getLength() == 0 )
      return -1;
    char c = doc.getText( offset, 1 ).charAt( 0 );
    char cprime; // c` - corresponding character
    boolean direction; // true = back, false = forward
    switch( c )
    {
    case "(" :
      cprime = ")";
      direction = false;
      break;
    case ")" :
      cprime = "(";
      direction = true;
      break;
    case "[" :
      cprime = "]";
      direction = false;
      break;
    case "]" :
      cprime = "[";
      direction = true;
      break;
    case "{" :
      cprime = "}";
      direction = false;
      break;
    case "}" :
      cprime = "{";
      direction = true;
      break;
    default :
      return -1;
    }
    int count;
    // How to merge these two cases is left as an exercise
    // for the reader.
    // Go back or forward
    if( direction )
    {
      // Count is 1 initially because we have already
      // `found" one closing bracket
      count = 1;
      // Get text[0,offset-1];
      String text = doc.getText( 0, offset );
      // Scan backwards
      for( int i = offset - 1; i >= 0; i-- )
      {
        // If text[i] == c, we have found another
        // closing bracket, therefore we will need
        // two opening brackets to complete the
        // match.
        char x = text.charAt( i );
        if( x == c )
          count++ ;
        // If text[i] == cprime, we have found a
        // opening bracket, so we return i if
        // --count == 0
        else if( x == cprime )
        {
          if( --count == 0 )
            return i;
        }
      }
    }
    else
    {
      // Count is 1 initially because we have already
      // `found" one opening bracket
      count = 1;
      // So we don"t have to + 1 in every loop
      offset++ ;
      // Number of characters to check
      int len = doc.getLength() - offset;
      // Get text[offset+1,len];
      String text = doc.getText( offset, len );
      // Scan forwards
      for( int i = 0; i < len; i++ )
      {
        // If text[i] == c, we have found another
        // opening bracket, therefore we will need
        // two closing brackets to complete the
        // match.
        char x = text.charAt( i );
        if( x == c )
          count++ ;
        // If text[i] == cprime, we have found an
        // closing bracket, so we return i if
        // --count == 0
        else if( x == cprime )
        {
          if( --count == 0 )
            return i + offset;
        }
      }
    }
    // Nothing found
    return -1;
  }
}





Return the leading whitespace of that string, for indenting subsequent lines

   
/*
 * StandardUtilities.java - Various miscallaneous utility functions
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2006 Matthieu Casanova, Slava Pestov
 * Portions copyright (C) 2000 Richard S. Hall
 * Portions copyright (C) 2001 Dirk Moebius
 *
 * This program 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
 * of the License, or any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//{{{ Imports
import javax.swing.text.Segment;
import java.util.ruparator;
import java.util.Stack;
//}}}
/**
 * Several tools that depends on JDK only.
 *
 * @author Matthieu Casanova
 * @version $Id: StandardUtilities.java 12884 2008-06-23 18:17:08Z kpouer $
 * @since 4.3pre5
 */
public class StandardUtilities
{
  //{{{ getPrevIndentStyle() method
  /**
   * @param str A java string
     * @return the leading whitespace of that string, for indenting subsequent lines.
   * @since jEdit 4.3pre10
   */
  public static String getIndentString(String str)
  {
    StringBuilder indentString = new StringBuilder();
    int idx = 0;
    char ch = str.charAt(idx);
    while (idx < str.length() && Character.isWhitespace(ch)) {
      indentString.append(ch);
      idx++;
      ch = str.charAt(idx);
    }
    return indentString.toString();
  } //}}}
}





Setting the Font and Color of Text in a JTextPane Using Styles: Inherits from "Red"; makes text red and underlined

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    Style style = textPane.addStyle("Red", null);
    StyleConstants.setForeground(style, Color.red);
    // Inherits from "Red"; makes text red and underlined
    style = textPane.addStyle("Red Underline", style);
    StyleConstants.setUnderline(style, true);
  }
}





Setting the Font and Color of Text in a JTextPane Using Styles: Makes text 24pts

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // Makes text 24pts
    Style style = textPane.addStyle("24pts", null);
    StyleConstants.setFontSize(style, 24);
  }
}





Setting the Font and Color of Text in a JTextPane Using Styles: Makes text italicized

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // Makes text italicized
    Style style = textPane.addStyle("Italic", null);
    StyleConstants.setItalic(style, true);
  }
}





Setting the Font and Color of Text in a JTextPane Using Styles: Makes text red

   
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextPane textPane = new JTextPane();
    StyledDocument doc = textPane.getStyledDocument();
    // Makes text red
    Style style = textPane.addStyle("Red", null);
    StyleConstants.setForeground(style, Color.red);

  }
}





Show html

  

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
public class Main {
  public static void main(String[] args) throws Exception {
    JEditorPane editor = new JEditorPane("text/html",
        "<H1>A!</H1><P><FONT COLOR=blue>blue</FONT></P>");
    editor.setEditable(false);
    JScrollPane pane = new JScrollPane(editor);
    JFrame f = new JFrame("HTML Demo");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(pane);
    f.setSize(800, 600);
    f.setVisible(true);
  }
}





Show web page

  
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
public class Main{
  public static void main(String[] args) throws Exception {
    String url = "http://www.yahoo.ru";
    JEditorPane editor = new JEditorPane(url);
    editor.setEditable(false);
    JScrollPane pane = new JScrollPane(editor);
    JFrame f = new JFrame("HTML Demo");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(pane);
    f.setSize(800, 600);
    f.setVisible(true);
  }
}





Use SimpleAttributeSet with JTextPane

  
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class Main extends JTextPane {
  public void appendNaive(Color c, String s) {
    SimpleAttributeSet aset = new SimpleAttributeSet();
    StyleConstants.setForeground(aset, c);
    int len = getText().length();
    setCaretPosition(len);
    setCharacterAttributes(aset, false);
    replaceSelection(s);
  }
  public static void main(String argv[]) {
    Main pane = new Main();
    for (int n = 1; n <= 4; n += 1) {
        pane.appendNaive(Color.black, String.valueOf(n) + " ");
    }
    JFrame f = new JFrame("ColorPane example");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setContentPane(new JScrollPane(pane));
    f.setSize(600, 400);
    f.setVisible(true);
  }
}





Viewing RTF format

   
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.rtf.RTFEditorKit;
public class RTFView extends JFrame {
  public RTFView() {
    setTitle("RTF Text Application");
    setSize(400, 240);
    setBackground(Color.gray);
    getContentPane().setLayout(new BorderLayout());
    JPanel topPanel = new JPanel();
    topPanel.setLayout(new BorderLayout());
    getContentPane().add(topPanel, BorderLayout.CENTER);
    // Create an RTF editor window
    RTFEditorKit rtf = new RTFEditorKit();
    JEditorPane editor = new JEditorPane();
    editor.setEditorKit(rtf);
    editor.setBackground(Color.white);
    // This text could be big so add a scroll pane
    JScrollPane scroller = new JScrollPane();
    scroller.getViewport().add(editor);
    topPanel.add(scroller, BorderLayout.CENTER);
    // Load an RTF file into the editor
    try {
      FileInputStream fi = new FileInputStream("test.rtf");
      rtf.read(fi, editor.getDocument(), 0);
    } catch (FileNotFoundException e) {
      System.out.println("File not found");
    } catch (IOException e) {
      System.out.println("I/O error");
    } catch (BadLocationException e) {
    }
  }
  public static void main(String args[]) {
    // Create an instance of the test application
    RTFView mainFrame = new RTFView();
    mainFrame.setVisible(true);
  }
}