View Javadoc

1   /*
2    *                Doelan development code
3    *
4    * This code may be freely distributed and modified under the
5    * terms of the GNU General Public Licence.  This should
6    * be distributed with the code. If you do not have a copy,
7    * see:
8    *
9    *      http://www.gnu.org/copyleft/gpl.txt
10   *
11   * Copyright (c) 2004-2005 ENS Microarray Platform
12   * Copyright for this code is held jointly by the individual
13   * authors.  These should be listed in @author doc comments.
14   *
15   * For more information on the Doelan project and its aims,
16   * or to join the Doelan mailing list, visit the home page
17   * at:
18   *
19   *      http://www.transcriptome.ens.fr/doelan
20   */
21  
22  package fr.ens.transcriptome.doelan.gui;
23  
24  import java.awt.Cursor;
25  import java.awt.Point;
26  import java.awt.event.MouseEvent;
27  import java.io.IOException;
28  import java.io.Serializable;
29  import java.net.MalformedURLException;
30  import java.net.URL;
31  import java.util.Map;
32  
33  import javax.swing.JEditorPane;
34  import javax.swing.JOptionPane;
35  import javax.swing.event.HyperlinkEvent;
36  import javax.swing.event.MouseInputAdapter;
37  import javax.swing.text.AttributeSet;
38  import javax.swing.text.Document;
39  import javax.swing.text.Element;
40  import javax.swing.text.StyleConstants;
41  import javax.swing.text.View;
42  import javax.swing.text.ViewFactory;
43  import javax.swing.text.html.HTML;
44  import javax.swing.text.html.HTMLDocument;
45  import javax.swing.text.html.HTMLEditorKit;
46  
47  import fr.ens.transcriptome.doelan.DoelanRegistery;
48  import fr.ens.transcriptome.nividic.util.WebBrowser;
49  
50  /***
51   * HTML viewer which can display image.
52   * @author Laurent Jourdren
53   */
54  public class DoelanEditorKit extends HTMLEditorKit {
55  
56    private Map mapImages;
57  
58    /***
59     * Get the factor viewer.
60     * @return the viewer factory
61     */
62    public ViewFactory getViewFactory() {
63  
64      return new HTMLFactoryX(getMapImages());
65    }
66  
67    /***
68     * Get the map of the images.
69     * @return Returns the mapImages
70     */
71    public Map getMapImages() {
72      return mapImages;
73    }
74  
75    /***
76     * Set the map of the images.
77     * @param mapImages The mapImages to set
78     */
79    public void setMapImages(final Map mapImages) {
80      this.mapImages = mapImages;
81    }
82  
83    //
84    //
85    // Clickodrome
86    //
87    //
88  
89    // Since we only have two mouse events to listen to, we'll use the same
90    // method to generate the appropriate hyperlinks and distinguish
91    // between them when we react to the mouse events.
92    private static final int JUMP = 0;
93    private static final int MOVE = 1;
94  
95    private LinkController myController = new LinkController();
96  
97    /***
98     * Overide the install method of the EditorKit.
99     * @param c The editor pane to listen
100    */
101   public void install(final JEditorPane c) {
102     c.addMouseListener(myController);
103     c.addMouseMotionListener(myController);
104   }
105 
106   /***
107    * This class implements a HTML factory which can display image.
108    * @author Laurent Jourdren
109    */
110   public static class HTMLFactoryX extends HTMLFactory implements ViewFactory {
111 
112     private Map mapImages;
113 
114     /***
115      * Display an element.
116      * @param elem to display
117      * @return a view object
118      */
119     public View create(final Element elem) {
120       Object o = elem.getAttributes()
121           .getAttribute(StyleConstants.NameAttribute);
122       if (o instanceof HTML.Tag) {
123         HTML.Tag kind = (HTML.Tag) o;
124         if (kind == HTML.Tag.IMG) {
125           MyImageView v = new MyImageView(elem, this.mapImages);
126           return v;
127         }
128 
129       }
130       return super.create(elem);
131     }
132 
133     HTMLFactoryX(final Map mapImages) {
134 
135       this.mapImages = mapImages;
136     }
137 
138   }
139 
140   private static class LinkController extends MouseInputAdapter implements
141       Serializable {
142 
143     private URL currentUrl;
144 
145     // here's the mouseClicked event similar to the one in
146     // the regular HTMLEditorKit, updated to indicate this is
147     // a "jump" event
148     public void mouseClicked(final MouseEvent e) {
149       JEditorPane editor = (JEditorPane) e.getSource();
150 
151       if (!editor.isEditable()) {
152         Point pt = new Point(e.getX(), e.getY());
153         int pos = editor.viewToModel(pt);
154         if (pos >= 0) {
155           activateLink(pos, editor, JUMP);
156         }
157       }
158     }
159 
160     // And here's our addition. Now the mouseMove events will
161     // also call activateLink, but with a "move" type
162     public void mouseMoved(final MouseEvent e) {
163 
164       JEditorPane editor = (JEditorPane) e.getSource();
165       editor.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
166       // editor.setCursor(Cursor.getDefaultCursor());
167 
168       if (!editor.isEditable()) {
169         Point pt = new Point(e.getX(), e.getY());
170         int pos = editor.viewToModel(pt);
171         if (pos >= 0) {
172           activateLink(pos, editor, MOVE);
173         }
174 
175       }
176     }
177 
178     // activateLink has now been updated to decide which hyperlink
179     // event to generate, based on the event type and status of the
180     // currentUrl field. Rather than have two handlers (one for
181     // enter/exit, one for active) we do all the work here. This
182     // saves us the effort of duplicating the href location code.
183     // But that's really minor point. You could certainly provide
184     // two handlers if that makes more sense to you.
185     protected void activateLink(final int pos, final JEditorPane html,
186         final int type) {
187       Document doc = html.getDocument();
188       if (doc instanceof HTMLDocument) {
189         HTMLDocument hdoc = (HTMLDocument) doc;
190         Element e = hdoc.getCharacterElement(pos);
191         AttributeSet a = e.getAttributes();
192         AttributeSet anchor = (AttributeSet) a.getAttribute(HTML.Tag.A);
193         String href = (anchor != null) ? (String) anchor
194             .getAttribute(HTML.Attribute.HREF) : null;
195         boolean shouldExit = false;
196 
197         HyperlinkEvent linkEvent = null;
198         if (href != null) {
199           URL u;
200           try {
201             u = new URL(hdoc.getBase(), href);
202           } catch (MalformedURLException m) {
203             u = null;
204             return;
205           }
206 
207           html.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
208 
209           if ((type == MOVE) && (!u.equals(currentUrl))) {
210             linkEvent = new HyperlinkEvent(html,
211                 HyperlinkEvent.EventType.ENTERED, u, href);
212             currentUrl = u;
213 
214           } else if (type == JUMP) {
215             linkEvent = new HyperlinkEvent(html,
216                 HyperlinkEvent.EventType.ACTIVATED, u, href);
217             shouldExit = true;
218 
219             try {
220 
221               String alternativeBrowserPath = DoelanRegistery
222                   .getAlternativeBrowserPath();
223 
224               WebBrowser.launch(alternativeBrowserPath, u);
225             } catch (IOException exception) {
226               JOptionPane.showInternalMessageDialog(html,
227                   "Error while launching navigator : ", "Error",
228                   JOptionPane.ERROR_MESSAGE);
229             }
230           } else
231             return;
232 
233           html.fireHyperlinkUpdate(linkEvent);
234         } else if (currentUrl != null) {
235           shouldExit = true;
236         }
237         if (shouldExit) {
238           linkEvent = new HyperlinkEvent(html, HyperlinkEvent.EventType.EXITED,
239               currentUrl, null);
240           html.fireHyperlinkUpdate(linkEvent);
241           currentUrl = null;
242         }
243       }
244     }
245   }
246 
247 }