Mega Code Archive

 
Categories / Java / Swing JFC
 

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();   } }