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