001    /*
002     * $Id: EditorPaneLinkVisitor.java 2951 2008-06-17 10:07:49Z kleopatra $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.hyperlink;
022    
023    import javax.swing.*;
024    import javax.swing.event.HyperlinkEvent;
025    import javax.swing.event.HyperlinkListener;
026    import javax.swing.text.Document;
027    
028    import org.jdesktop.swingx.JXEditorPane;
029    
030    import java.awt.event.ActionEvent;
031    import java.awt.event.ActionListener;
032    import java.io.IOException;
033    import java.net.URL;
034    
035    
036    /**
037     * A ActionListener using a JXEditorPane to "visit" a LinkModel.
038     * 
039     * adds an internal HyperlinkListener to visit links contained
040     * in the document. 
041     * 
042     * @author Jeanette Winzenburg
043     */
044    public class EditorPaneLinkVisitor implements ActionListener {
045        private JXEditorPane editorPane;
046        private HyperlinkListener hyperlinkListener;
047        private LinkModel internalLink;
048        
049        public EditorPaneLinkVisitor() {
050            this(null);
051        }
052        
053        public EditorPaneLinkVisitor(JXEditorPane pane) {
054            if (pane == null) {
055                pane = createDefaultEditorPane();
056            }
057            this.editorPane = pane;
058            pane.addHyperlinkListener(getHyperlinkListener());
059        }
060        
061    
062        public JXEditorPane getOutputComponent() {
063            return editorPane;
064        }
065        
066        public void actionPerformed(ActionEvent e) {
067            if (e.getSource() instanceof LinkModel) {
068                final LinkModel link = (LinkModel) e.getSource();
069                SwingUtilities.invokeLater(new Runnable() {
070                    public void run() {
071                        visit(link);
072    
073                    }
074                });
075            }
076       
077        }
078    
079        public void visit(LinkModel link) {
080            try {
081                // make sure to reload
082                editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null);
083                // JW: editorPane defaults to asynchronous loading
084                // no need to explicitly start a thread - really?
085                editorPane.setPage(link.getURL());
086                link.setVisited(true);
087            } catch (IOException e1) {
088                editorPane.setText("<html>Error 404: couldn't show " + link.getURL() + " </html>");
089            }
090        }
091    
092        protected JXEditorPane createDefaultEditorPane() {
093            final JXEditorPane editorPane = new JXEditorPane();
094            editorPane.setEditable(false);
095            editorPane.setContentType("text/html");
096            return editorPane;
097        }
098    
099        protected HyperlinkListener getHyperlinkListener() {
100            if (hyperlinkListener == null) {
101                hyperlinkListener = createHyperlinkListener();
102            }
103            return hyperlinkListener;
104        }
105    
106        protected HyperlinkListener createHyperlinkListener() {
107            return new HyperlinkListener() {
108                public void hyperlinkUpdate(HyperlinkEvent e) {
109                    if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
110                        visitInternal(e.getURL());
111                    }
112                    
113                }
114                
115            };
116        }
117    
118        protected LinkModel getInternalLink() {
119            if (internalLink == null) {
120                internalLink = new LinkModel("internal");
121            }
122            return internalLink;
123        }
124    
125        protected void visitInternal(URL url) {
126            try {
127                getInternalLink().setURL(url);
128                visit(getInternalLink());
129            } catch (Exception e) {
130                // todo: error feedback
131            }
132        }
133    
134    
135    }