1   package gate.swing;
2   
3   import javax.swing.*;
4   import java.io.*;
5   import java.util.*;
6   import java.net.URL;
7   import javax.swing.event.*;
8   import javax.swing.text.*;
9   import java.awt.event.*;
10  import javax.swing.text.html.*;
11  
12  import gate.util.*;
13  import gate.event.*;
14  
15  /**
16   * An enhanced version of {@link javax.swing.JEditorPane} that is able of
17   * handling hyperlinks from the HTML document displayed.
18   */
19  public class XJEditorPane extends JEditorPane {
20  
21    public XJEditorPane(){
22      super();
23      init();
24    }
25  
26    public XJEditorPane(String url) throws IOException{
27      super(url);
28      init();
29    }
30  
31    public XJEditorPane(URL initialPage)throws IOException{
32      super(initialPage);
33      init();
34    }
35  
36    protected void init(){
37      initLocalData();
38      initListeners();
39    }//protected void init()
40  
41    protected void initLocalData(){
42      backUrls = new LinkedList();
43      forwardUrls = new LinkedList();
44      try{
45        backAction = new BackAction();
46        forwardAction = new ForwardAction();
47      }catch(IOException ioe){
48        Err.prln("Resource mising! Is your classpath OK?");
49        ioe.printStackTrace(Err.getPrintWriter());
50      }
51    }//protected void initLocalData()
52  
53    protected void initListeners(){
54      addHyperlinkListener(new HyperlinkListener() {
55        public void hyperlinkUpdate(HyperlinkEvent e){
56          if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED){
57            if (e instanceof HTMLFrameHyperlinkEvent) {
58                HTMLFrameHyperlinkEvent  evt = (HTMLFrameHyperlinkEvent)e;
59                HTMLDocument doc = (HTMLDocument)getDocument();
60                doc.processHTMLFrameHyperlinkEvent(evt);
61            }else{
62              try {
63                backUrls.addLast(getPage());
64                forwardUrls.clear();
65                setPage(e.getURL());
66              }catch (Throwable t){
67                t.printStackTrace(Err.getPrintWriter());
68              }
69            }
70          }else if(e.getEventType() == HyperlinkEvent.EventType.ENTERED){
71            fireStatusChanged(e.getURL().toExternalForm());
72          }else if(e.getEventType() == HyperlinkEvent.EventType.EXITED){
73            fireStatusChanged("");
74          }
75        }//public void hyperlinkUpdate(HyperlinkEvent e)
76      });
77    }//protected void initListeners()
78  
79    public Action getForwardAction(){
80      return forwardAction;
81    }
82  
83    public Action getBackAction(){
84      return backAction;
85    }
86  
87    public void setPage(URL page) throws IOException{
88      try{
89        super.setPage(page);
90      }catch(Exception e){
91        fireStatusChanged(e.toString());
92        e.printStackTrace(Err.getPrintWriter());
93      }
94      updateEnableState();
95    }
96  
97    class ForwardAction extends AbstractAction{
98      private ForwardAction() throws IOException{
99        super("Forward", new ImageIcon(new URL("gate:/img/forward.gif")));
100     }
101 
102     public void actionPerformed(ActionEvent e){
103       backUrls.addLast(getPage());
104       try{
105         setPage((URL)forwardUrls.removeFirst());
106       }catch(IOException ioe){
107         ioe.printStackTrace(Err.getPrintWriter());
108       }
109     }
110   }//class ForwardAction extends AbstractAction
111 
112   class BackAction extends AbstractAction{
113     private BackAction() throws IOException{
114       super("Back", new ImageIcon(new URL("gate:/img/back.gif")));
115     }
116 
117     public void actionPerformed(ActionEvent e){
118       forwardUrls.addFirst(getPage());
119       try{
120         setPage((URL)backUrls.removeLast());
121       }catch(IOException ioe){
122         ioe.printStackTrace(Err.getPrintWriter());
123       }
124     }
125   }//class ForwardAction extends AbstractAction
126 
127 
128   /**
129    * Updates the enabled/disabled state for the back/forward actions
130    */
131   protected void updateEnableState(){
132     forwardAction.setEnabled(!forwardUrls.isEmpty());
133     backAction.setEnabled(!backUrls.isEmpty());
134   }
135   public synchronized void removeStatusListener(StatusListener l) {
136     if (statusListeners != null && statusListeners.contains(l)) {
137       Vector v = (Vector) statusListeners.clone();
138       v.removeElement(l);
139       statusListeners = v;
140     }
141   }
142   public synchronized void addStatusListener(StatusListener l) {
143     Vector v = statusListeners == null ? new Vector(2) : (Vector) statusListeners.clone();
144     if (!v.contains(l)) {
145       v.addElement(l);
146       statusListeners = v;
147     }
148   }
149 
150   protected LinkedList backUrls;
151   protected LinkedList forwardUrls;
152   protected Action backAction;
153   protected Action forwardAction;
154   private transient Vector statusListeners;
155   protected void fireStatusChanged(String e) {
156     if (statusListeners != null) {
157       Vector listeners = statusListeners;
158       int count = listeners.size();
159       for (int i = 0; i < count; i++) {
160         ((StatusListener) listeners.elementAt(i)).statusChanged(e);
161       }
162     }
163   }
164 }//public class XJEditorPane extends JEditorPane
165