001    /*
002     * $Id: EditorPaneLinkVisitor.java,v 1.1 2005/10/12 08:48:28 kleopatra Exp $
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;
022    
023    import java.awt.event.ActionEvent;
024    import java.awt.event.ActionListener;
025    import java.io.IOException;
026    import java.net.URL;
027    
028    import javax.swing.SwingUtilities;
029    import javax.swing.event.HyperlinkEvent;
030    import javax.swing.event.HyperlinkListener;
031    import javax.swing.text.Document;
032    
033    
034    /**
035     * A ActionListener using a JXEditorPane to "visit" a LinkModel.
036     * 
037     * adds an internal HyperlinkListener to visit links contained
038     * in the document. 
039     * 
040     * @author Jeanette Winzenburg
041     */
042    public class EditorPaneLinkVisitor implements ActionListener {
043        private JXEditorPane editorPane;
044        private HyperlinkListener hyperlinkListener;
045        private LinkModel internalLink;
046        
047        public EditorPaneLinkVisitor() {
048            this(null);
049        }
050        
051        public EditorPaneLinkVisitor(JXEditorPane pane) {
052            if (editorPane != null) {
053                editorPane.removeHyperlinkListener(getHyperlinkListener());
054            }
055            if (pane == null) {
056                pane = createDefaultEditorPane();
057            }
058            this.editorPane = pane;
059            pane.addHyperlinkListener(getHyperlinkListener());
060        }
061        
062    
063        public JXEditorPane getOutputComponent() {
064            return editorPane;
065        }
066        
067        public void actionPerformed(ActionEvent e) {
068            if (e.getSource() instanceof LinkModel) {
069                final LinkModel link = (LinkModel) e.getSource();
070                SwingUtilities.invokeLater(new Runnable() {
071                    public void run() {
072                        visit(link);
073    
074                    }
075                });
076            }
077       
078        }
079    
080        public void visit(LinkModel link) {
081            try {
082                // make sure to reload
083                editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null);
084                // JW: editorPane defaults to asynchronous loading
085                // no need to explicitly start a thread - really?
086                editorPane.setPage(link.getURL());
087                link.setVisited(true);
088            } catch (IOException e1) {
089                editorPane.setText("<html>Error 404: couldn't show " + link.getURL() + " </html>");
090            }
091        }
092    
093        protected JXEditorPane createDefaultEditorPane() {
094            final JXEditorPane editorPane = new JXEditorPane();
095            editorPane.setEditable(false);
096            editorPane.setContentType("text/html");
097            return editorPane;
098        }
099    
100        protected HyperlinkListener getHyperlinkListener() {
101            if (hyperlinkListener == null) {
102                hyperlinkListener = createHyperlinkListener();
103            }
104            return hyperlinkListener;
105        }
106    
107        protected HyperlinkListener createHyperlinkListener() {
108            HyperlinkListener l = new HyperlinkListener() {
109    
110                public void hyperlinkUpdate(HyperlinkEvent e) {
111                    if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
112                        visitInternal(e.getURL());
113                    }
114                    
115                }
116                
117            };
118            return l;
119        }
120    
121        protected LinkModel getInternalLink() {
122            if (internalLink == null) {
123                internalLink = new LinkModel("internal");
124            }
125            return internalLink;
126        }
127    
128        protected void visitInternal(URL url) {
129            try {
130                getInternalLink().setURL(url);
131                visit(getInternalLink());
132            } catch (Exception e) {
133                // todo: error feedback
134            }
135        }
136    
137    
138    }