regex links for launching URL from single click on sequence ID
[jalview.git] / src / jalview / appletgui / IdPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19
20 package jalview.appletgui;
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import jalview.datamodel.*;
26 import jalview.util.UrlLink;
27
28 public class IdPanel
29     extends Panel implements MouseListener, MouseMotionListener
30 {
31
32   protected IdCanvas idCanvas;
33   protected AlignViewport av;
34   protected AlignmentPanel alignPanel;
35   ScrollThread scrollThread = null;
36
37   int offy;
38   int width;
39   int lastid = -1;
40   boolean mouseDragging = false;
41   java.util.Vector links = new java.util.Vector();
42
43   public IdPanel(AlignViewport av, AlignmentPanel parent)
44   {
45     this.av = av;
46     alignPanel = parent;
47     idCanvas = new IdCanvas(av);
48     setLayout(new BorderLayout());
49     add(idCanvas, BorderLayout.CENTER);
50     idCanvas.addMouseListener(this);
51     idCanvas.addMouseMotionListener(this);
52
53     String label, url;
54     if (av.applet != null)
55     {
56       for (int i = 1; i < 10; i++)
57       {
58         label = av.applet.getParameter("linkLabel_" + i);
59         url = av.applet.getParameter("linkURL_" + i);
60
61         if (label != null && url != null)
62         {
63           links.addElement(label + "|" + url);
64         }
65
66       }
67     }
68     if (links.size() < 1)
69     {
70       links = new java.util.Vector();
71       links.addElement("SRS|http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-newId+(([uniprot-all:$SEQUENCE_ID$]))+-view+SwissEntry");
72     }
73   }
74
75   Tooltip tooltip;
76   public void mouseMoved(MouseEvent e)
77   {
78     int seq = alignPanel.seqPanel.findSeq(e);
79
80     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
81
82     if (sequence.getDescription() == null)
83     {
84       if (tooltip != null)
85       {
86         tooltip.setVisible(false);
87       }
88       tooltip = null;
89       return;
90     }
91
92     if (tooltip == null)
93     {
94       tooltip = new Tooltip(
95           sequence.getDisplayId(true)
96           + "\n" + sequence.getDescription(), idCanvas);
97     }
98     else
99     {
100       tooltip.setTip(sequence.getDisplayId(true)
101                      + "\n" + sequence.getDescription());
102     }
103   }
104
105   public void mouseDragged(MouseEvent e)
106   {
107     mouseDragging = true;
108
109     int seq = Math.max(0, alignPanel.seqPanel.findSeq(e));
110
111     if (seq < lastid)
112     {
113       selectSeqs(lastid - 1, seq);
114     }
115     else if (seq > lastid)
116     {
117       selectSeqs(lastid + 1, seq);
118     }
119
120     lastid = seq;
121     alignPanel.paintAlignment(false);
122   }
123
124   public void mouseClicked(MouseEvent e)
125   {
126     if (e.getClickCount() < 2)
127     {
128       return;
129     }
130
131     //DEFAULT LINK IS FIRST IN THE LINK LIST
132     int seq = alignPanel.seqPanel.findSeq(e);
133     String id = av.getAlignment().getSequenceAt(seq).getName();
134     
135     String target = null;
136     String url = null;
137     int i=0;
138     while (url == null && i < links.size())
139     {
140       // DEFAULT LINK IS FIRST IN THE LINK LIST
141       // BUT IF ITS A REGEX AND DOES NOT MATCH THE NEXT ONE WILL BE TRIED
142       url = links.elementAt(i++).toString();
143       jalview.util.UrlLink urlLink = null;
144       try
145       {
146         urlLink = new UrlLink(url);
147         target = urlLink.getTarget();
148       } catch (Exception foo)
149       {
150         System.err.println("Exception for URLLink '" + url + "'");
151         foo.printStackTrace();
152         url = null;
153         continue;
154       }
155       ;
156       if (!urlLink.isValid())
157       {
158         System.err.println(urlLink.getInvalidMessage());
159         url = null;
160         continue;
161       }
162
163       String urls[] = urlLink.makeUrls(id, true);
164       if (urls == null || urls[0]==null || urls[0].length()<1)
165       {
166         url = null;
167         continue;
168       }
169       // just take first URL made from regex
170       url = urls[1];
171     }
172     try
173     {
174
175       alignPanel.alignFrame.showURL(url, target);
176     }
177     catch (Exception ex)
178     {
179       ex.printStackTrace();
180     }
181   }
182
183   public void mouseEntered(MouseEvent e)
184   {
185     if (scrollThread != null)
186     {
187       scrollThread.running = false;
188     }
189   }
190
191   public void mouseExited(MouseEvent e)
192   {
193     if (av.getWrapAlignment())
194     {
195       return;
196     }
197
198     if (mouseDragging && e.getY() < 0 && av.getStartSeq() > 0)
199     {
200       scrollThread = new ScrollThread(true);
201     }
202
203     if (mouseDragging && e.getY() >= getSize().height &&
204         av.alignment.getHeight() > av.getEndSeq())
205     {
206       scrollThread = new ScrollThread(false);
207     }
208   }
209
210   public void mousePressed(MouseEvent e)
211   {
212     if (e.getClickCount() > 1)
213     {
214       return;
215     }
216
217     int y = e.getY();
218     if (av.getWrapAlignment())
219     {
220       y -= 2 * av.charHeight;
221     }
222
223     int seq = alignPanel.seqPanel.findSeq(e);
224
225     if ( (e.getModifiers() & InputEvent.BUTTON3_MASK) ==
226         InputEvent.BUTTON3_MASK)
227     {
228       APopupMenu popup = new APopupMenu(alignPanel,
229                                         (Sequence) av.getAlignment().
230                                         getSequenceAt(seq), links);
231       this.add(popup);
232       popup.show(this, e.getX(), e.getY());
233       return;
234     }
235
236     if ( (av.getSelectionGroup() == null) ||
237         ( (!e.isControlDown() && !e.isShiftDown()) && av.getSelectionGroup() != null))
238     {
239       av.setSelectionGroup(new SequenceGroup());
240       av.getSelectionGroup().setStartRes(0);
241       av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
242     }
243
244     if (e.isShiftDown() && lastid != -1)
245     {
246       selectSeqs(lastid, seq);
247     }
248     else
249     {
250       selectSeq(seq);
251     }
252
253     alignPanel.paintAlignment(false);
254   }
255
256   void selectSeq(int seq)
257   {
258     lastid = seq;
259     SequenceI pickedSeq = av.getAlignment().getSequenceAt(seq);
260     av.getSelectionGroup().addOrRemove(pickedSeq, false);
261   }
262
263   void selectSeqs(int start, int end)
264   {
265
266     lastid = start;
267
268     if (end >= av.getAlignment().getHeight())
269     {
270       end = av.getAlignment().getHeight() - 1;
271     }
272
273     if (end < start)
274     {
275       int tmp = start;
276       start = end;
277       end = tmp;
278       lastid = end;
279     }
280
281     for (int i = start; i <= end; i++)
282     {
283       av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i), false);
284     }
285
286   }
287
288   public void mouseReleased(MouseEvent e)
289   {
290     if (scrollThread != null)
291     {
292       scrollThread.running = false;
293     }
294
295     if (av.getSelectionGroup() != null)
296     {
297       av.getSelectionGroup().recalcConservation();
298     }
299
300     mouseDragging = false;
301     PaintRefresher.Refresh(this, av.getSequenceSetId());
302   }
303
304   public void highlightSearchResults(java.util.Vector found)
305   {
306     idCanvas.setHighlighted(found);
307
308     if (found == null)
309     {
310       return;
311     }
312
313     int index = av.alignment.findIndex( (SequenceI) found.elementAt(0));
314
315     // do we need to scroll the panel?
316     if (av.getStartSeq() > index || av.getEndSeq() < index)
317     {
318       alignPanel.setScrollValues(av.getStartRes(), index);
319     }
320   }
321
322   // this class allows scrolling off the bottom of the visible alignment
323   class ScrollThread
324       extends Thread
325   {
326     boolean running = false;
327     boolean up = true;
328     public ScrollThread(boolean up)
329     {
330       this.up = up;
331       start();
332     }
333
334     public void stopScrolling()
335     {
336       running = false;
337     }
338
339     public void run()
340     {
341       running = true;
342       while (running)
343       {
344         if (alignPanel.scrollUp(up))
345         {
346           // scroll was ok, so add new sequence to selection
347           int seq = av.getStartSeq();
348           if (!up)
349           {
350             seq = av.getEndSeq();
351           }
352
353           if (seq < lastid)
354           {
355             selectSeqs(lastid - 1, seq);
356           }
357           else if (seq > lastid && seq < av.alignment.getHeight())
358           {
359             selectSeqs(lastid + 1, seq);
360           }
361
362           lastid = seq;
363         }
364         else
365         {
366           running = false;
367         }
368
369         alignPanel.paintAlignment(true);
370         try
371         {
372           Thread.sleep(100);
373         }
374         catch (Exception ex)
375         {}
376       }
377     }
378   }
379
380 }