001/*
002 * $Id: EditorPaneLinkVisitor.java 3927 2011-02-22 16:34:11Z 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 */
021package org.jdesktop.swingx.hyperlink;
022
023import java.awt.event.ActionEvent;
024import java.awt.event.ActionListener;
025import java.io.IOException;
026import java.net.URL;
027
028import javax.swing.SwingUtilities;
029import javax.swing.event.HyperlinkEvent;
030import javax.swing.event.HyperlinkListener;
031import javax.swing.text.Document;
032
033import org.jdesktop.swingx.JXEditorPane;
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 */
044public 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    @Override
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                @Override
072                public void run() {
073                    visit(link);
074
075                }
076            });
077        }
078   
079    }
080
081    public void visit(LinkModel link) {
082        try {
083            // make sure to reload
084            editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null);
085            // JW: editorPane defaults to asynchronous loading
086            // no need to explicitly start a thread - really?
087            editorPane.setPage(link.getURL());
088            link.setVisited(true);
089        } catch (IOException e1) {
090            editorPane.setText("<html>Error 404: couldn't show " + link.getURL() + " </html>");
091        }
092    }
093
094    protected JXEditorPane createDefaultEditorPane() {
095        final JXEditorPane editorPane = new JXEditorPane();
096        editorPane.setEditable(false);
097        editorPane.setContentType("text/html");
098        return editorPane;
099    }
100
101    protected HyperlinkListener getHyperlinkListener() {
102        if (hyperlinkListener == null) {
103            hyperlinkListener = createHyperlinkListener();
104        }
105        return hyperlinkListener;
106    }
107
108    protected HyperlinkListener createHyperlinkListener() {
109        return new HyperlinkListener() {
110            @Override
111            public void hyperlinkUpdate(HyperlinkEvent e) {
112                if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
113                    visitInternal(e.getURL());
114                }
115                
116            }
117            
118        };
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}