update author list in license for (JAL-826)
[jalview.git] / src / jalview / appletgui / IdPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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.addElement("SRS|http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-newId+(([uniprot-all:$SEQUENCE_ID$]))+-view+SwissEntry");
79     }
80   }
81
82   Tooltip tooltip;
83
84   public void mouseMoved(MouseEvent e)
85   {
86     int seq = alignPanel.seqPanel.findSeq(e);
87
88     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
89
90     // look for non-pos features
91     StringBuffer tooltiptext = new StringBuffer();
92     if (sequence != null)
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     SequenceI sq = av.getAlignment().getSequenceAt(seq);
201     if (sq==null)
202     {
203       return;
204     }
205     String id = sq.getName();
206
207     String target = null;
208     String url = null;
209     int i = 0;
210     while (url == null && i < links.size())
211     {
212       // DEFAULT LINK IS FIRST IN THE LINK LIST
213       // BUT IF ITS A REGEX AND DOES NOT MATCH THE NEXT ONE WILL BE TRIED
214       url = links.elementAt(i++).toString();
215       jalview.util.UrlLink urlLink = null;
216       try
217       {
218         urlLink = new UrlLink(url);
219         target = urlLink.getTarget();
220       } catch (Exception foo)
221       {
222         System.err.println("Exception for URLLink '" + url + "'");
223         foo.printStackTrace();
224         url = null;
225         continue;
226       }
227       ;
228       if (!urlLink.isValid())
229       {
230         System.err.println(urlLink.getInvalidMessage());
231         url = null;
232         continue;
233       }
234
235       String urls[] = urlLink.makeUrls(id, true);
236       if (urls == null || urls[0] == null || urls[0].length() < 1)
237       {
238         url = null;
239         continue;
240       }
241       // just take first URL made from regex
242       url = urls[1];
243     }
244     try
245     {
246
247       alignPanel.alignFrame.showURL(url, target);
248     } catch (Exception ex)
249     {
250       ex.printStackTrace();
251     }
252   }
253
254   public void mouseEntered(MouseEvent e)
255   {
256     if (scrollThread != null)
257     {
258       scrollThread.running = false;
259     }
260   }
261
262   public void mouseExited(MouseEvent e)
263   {
264     if (av.getWrapAlignment())
265     {
266       return;
267     }
268
269     if (mouseDragging && e.getY() < 0 && av.getStartSeq() > 0)
270     {
271       scrollThread = new ScrollThread(true);
272     }
273
274     if (mouseDragging && e.getY() >= getSize().height
275             && av.alignment.getHeight() > av.getEndSeq())
276     {
277       scrollThread = new ScrollThread(false);
278     }
279   }
280
281   public void mousePressed(MouseEvent e)
282   {
283     if (e.getClickCount() > 1)
284     {
285       return;
286     }
287
288     int y = e.getY();
289     if (av.getWrapAlignment())
290     {
291       y -= 2 * av.charHeight;
292     }
293
294     int seq = alignPanel.seqPanel.findSeq(e);
295
296     if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
297     {
298       Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq);
299       
300       // build a new links menu based on the current links + any non-positional
301       // features
302       Vector nlinks = new Vector();
303       for (int l = 0, lSize = links.size(); l < lSize; l++)
304       {
305         nlinks.addElement(links.elementAt(l));
306       }
307       SequenceFeature sf[] = sq==null ? null:sq.getSequenceFeatures();
308       for (int sl = 0; sf != null && sl < sf.length; sl++)
309       {
310         if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
311         {
312           if (sf[sl].links != null && sf[sl].links.size() > 0)
313           {
314             for (int l = 0, lSize = sf[sl].links.size(); l < lSize; l++)
315             {
316               nlinks.addElement(sf[sl].links.elementAt(l));
317             }
318           }
319         }
320       }
321
322       APopupMenu popup = new APopupMenu(alignPanel, sq, nlinks);
323       this.add(popup);
324       popup.show(this, e.getX(), e.getY());
325       return;
326     }
327
328     if ((av.getSelectionGroup() == null)
329             || ((!e.isControlDown() && !e.isShiftDown()) && av
330                     .getSelectionGroup() != null))
331     {
332       av.setSelectionGroup(new SequenceGroup());
333       av.getSelectionGroup().setStartRes(0);
334       av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
335     }
336
337     if (e.isShiftDown() && lastid != -1)
338     {
339       selectSeqs(lastid, seq);
340     }
341     else
342     {
343       selectSeq(seq);
344     }
345
346     alignPanel.paintAlignment(false);
347   }
348
349   void selectSeq(int seq)
350   {
351     lastid = seq;
352     SequenceI pickedSeq = av.getAlignment().getSequenceAt(seq);
353     av.getSelectionGroup().addOrRemove(pickedSeq, false);
354   }
355
356   void selectSeqs(int start, int end)
357   {
358
359     lastid = start;
360
361     if (end >= av.getAlignment().getHeight())
362     {
363       end = av.getAlignment().getHeight() - 1;
364     }
365
366     if (end < start)
367     {
368       int tmp = start;
369       start = end;
370       end = tmp;
371       lastid = end;
372     }
373     if (av.getSelectionGroup() == null)
374     {
375       av.setSelectionGroup(new SequenceGroup());
376     }
377     for (int i = start; i <= end; i++)
378     {
379       av.getSelectionGroup().addSequence(
380               av.getAlignment().getSequenceAt(i), false);
381     }
382
383   }
384
385   public void mouseReleased(MouseEvent e)
386   {
387     if (scrollThread != null)
388     {
389       scrollThread.running = false;
390     }
391
392     if (av.getSelectionGroup() != null)
393     {
394       av.getSelectionGroup().recalcConservation();
395     }
396
397     mouseDragging = false;
398     PaintRefresher.Refresh(this, av.getSequenceSetId());
399     // always send selection message when mouse is released
400     av.sendSelection();
401   }
402
403   public void highlightSearchResults(java.util.Vector found)
404   {
405     idCanvas.setHighlighted(found);
406
407     if (found == null)
408     {
409       return;
410     }
411
412     int index = av.alignment.findIndex((SequenceI) found.elementAt(0));
413
414     // do we need to scroll the panel?
415     if (av.getStartSeq() > index || av.getEndSeq() < index)
416     {
417       alignPanel.setScrollValues(av.getStartRes(), index);
418     }
419   }
420
421   // this class allows scrolling off the bottom of the visible alignment
422   class ScrollThread extends Thread
423   {
424     boolean running = false;
425
426     boolean up = true;
427
428     public ScrollThread(boolean up)
429     {
430       this.up = up;
431       start();
432     }
433
434     public void stopScrolling()
435     {
436       running = false;
437     }
438
439     public void run()
440     {
441       running = true;
442       while (running)
443       {
444         if (alignPanel.scrollUp(up))
445         {
446           // scroll was ok, so add new sequence to selection
447           int seq = av.getStartSeq();
448           if (!up)
449           {
450             seq = av.getEndSeq();
451           }
452
453           if (seq < lastid)
454           {
455             selectSeqs(lastid - 1, seq);
456           }
457           else if (seq > lastid && seq < av.alignment.getHeight())
458           {
459             selectSeqs(lastid + 1, seq);
460           }
461
462           lastid = seq;
463         }
464         else
465         {
466           running = false;
467         }
468
469         alignPanel.paintAlignment(true);
470         try
471         {
472           Thread.sleep(100);
473         } catch (Exception ex)
474         {
475         }
476       }
477     }
478   }
479
480 }