merge from 2_4_Release branch
[jalview.git] / src / jalview / appletgui / IdPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 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 package jalview.appletgui;
20
21 import java.awt.*;
22 import java.awt.event.*;
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     if (av.applet != null)
61     {
62       for (int i = 1; i < 10; i++)
63       {
64         label = av.applet.getParameter("linkLabel_" + i);
65         url = av.applet.getParameter("linkURL_" + i);
66
67         if (label != null && url != null)
68         {
69           links.addElement(label + "|" + url);
70         }
71
72       }
73     }
74     if (links.size() < 1)
75     {
76       links = new java.util.Vector();
77       links
78               .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     if (sequence.getDescription() == null)
91     {
92       if (tooltip != null)
93       {
94         tooltip.setVisible(false);
95       }
96       tooltip = null;
97       return;
98     }
99
100     if (tooltip == null)
101     {
102       tooltip = new Tooltip(sequence.getDisplayId(true) + "\n"
103               + sequence.getDescription(), idCanvas);
104     }
105     else
106     {
107       tooltip.setTip(sequence.getDisplayId(true) + "\n"
108               + sequence.getDescription());
109     }
110   }
111
112   public void mouseDragged(MouseEvent e)
113   {
114     mouseDragging = true;
115
116     int seq = Math.max(0, alignPanel.seqPanel.findSeq(e));
117
118     if (seq < lastid)
119     {
120       selectSeqs(lastid - 1, seq);
121     }
122     else if (seq > lastid)
123     {
124       selectSeqs(lastid + 1, seq);
125     }
126
127     lastid = seq;
128     alignPanel.paintAlignment(false);
129   }
130
131   public void mouseClicked(MouseEvent e)
132   {
133     if (e.getClickCount() < 2)
134     {
135       return;
136     }
137
138     // DEFAULT LINK IS FIRST IN THE LINK LIST
139     int seq = alignPanel.seqPanel.findSeq(e);
140     String id = av.getAlignment().getSequenceAt(seq).getName();
141
142     String target = null;
143     String url = null;
144     int i = 0;
145     while (url == null && i < links.size())
146     {
147       // DEFAULT LINK IS FIRST IN THE LINK LIST
148       // BUT IF ITS A REGEX AND DOES NOT MATCH THE NEXT ONE WILL BE TRIED
149       url = links.elementAt(i++).toString();
150       jalview.util.UrlLink urlLink = null;
151       try
152       {
153         urlLink = new UrlLink(url);
154         target = urlLink.getTarget();
155       } catch (Exception foo)
156       {
157         System.err.println("Exception for URLLink '" + url + "'");
158         foo.printStackTrace();
159         url = null;
160         continue;
161       }
162       ;
163       if (!urlLink.isValid())
164       {
165         System.err.println(urlLink.getInvalidMessage());
166         url = null;
167         continue;
168       }
169
170       String urls[] = urlLink.makeUrls(id, true);
171       if (urls == null || urls[0] == null || urls[0].length() < 1)
172       {
173         url = null;
174         continue;
175       }
176       // just take first URL made from regex
177       url = urls[1];
178     }
179     try
180     {
181
182       alignPanel.alignFrame.showURL(url, target);
183     } catch (Exception ex)
184     {
185       ex.printStackTrace();
186     }
187   }
188
189   public void mouseEntered(MouseEvent e)
190   {
191     if (scrollThread != null)
192     {
193       scrollThread.running = false;
194     }
195   }
196
197   public void mouseExited(MouseEvent e)
198   {
199     if (av.getWrapAlignment())
200     {
201       return;
202     }
203
204     if (mouseDragging && e.getY() < 0 && av.getStartSeq() > 0)
205     {
206       scrollThread = new ScrollThread(true);
207     }
208
209     if (mouseDragging && e.getY() >= getSize().height
210             && av.alignment.getHeight() > av.getEndSeq())
211     {
212       scrollThread = new ScrollThread(false);
213     }
214   }
215
216   public void mousePressed(MouseEvent e)
217   {
218     if (e.getClickCount() > 1)
219     {
220       return;
221     }
222
223     int y = e.getY();
224     if (av.getWrapAlignment())
225     {
226       y -= 2 * av.charHeight;
227     }
228
229     int seq = alignPanel.seqPanel.findSeq(e);
230
231     if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
232     {
233       APopupMenu popup = new APopupMenu(alignPanel, (Sequence) av
234               .getAlignment().getSequenceAt(seq), links);
235       this.add(popup);
236       popup.show(this, e.getX(), e.getY());
237       return;
238     }
239
240     if ((av.getSelectionGroup() == null)
241             || ((!e.isControlDown() && !e.isShiftDown()) && av
242                     .getSelectionGroup() != null))
243     {
244       av.setSelectionGroup(new SequenceGroup());
245       av.getSelectionGroup().setStartRes(0);
246       av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
247     }
248
249     if (e.isShiftDown() && lastid != -1)
250     {
251       selectSeqs(lastid, seq);
252     }
253     else
254     {
255       selectSeq(seq);
256     }
257
258     alignPanel.paintAlignment(false);
259   }
260
261   void selectSeq(int seq)
262   {
263     lastid = seq;
264     SequenceI pickedSeq = av.getAlignment().getSequenceAt(seq);
265     av.getSelectionGroup().addOrRemove(pickedSeq, false);
266   }
267
268   void selectSeqs(int start, int end)
269   {
270
271     lastid = start;
272
273     if (end >= av.getAlignment().getHeight())
274     {
275       end = av.getAlignment().getHeight() - 1;
276     }
277
278     if (end < start)
279     {
280       int tmp = start;
281       start = end;
282       end = tmp;
283       lastid = end;
284     }
285
286     for (int i = start; i <= end; i++)
287     {
288       av.getSelectionGroup().addSequence(
289               av.getAlignment().getSequenceAt(i), false);
290     }
291
292   }
293
294   public void mouseReleased(MouseEvent e)
295   {
296     if (scrollThread != null)
297     {
298       scrollThread.running = false;
299     }
300
301     if (av.getSelectionGroup() != null)
302     {
303       av.getSelectionGroup().recalcConservation();
304     }
305
306     mouseDragging = false;
307     PaintRefresher.Refresh(this, av.getSequenceSetId());
308   }
309
310   public void highlightSearchResults(java.util.Vector found)
311   {
312     idCanvas.setHighlighted(found);
313
314     if (found == null)
315     {
316       return;
317     }
318
319     int index = av.alignment.findIndex((SequenceI) found.elementAt(0));
320
321     // do we need to scroll the panel?
322     if (av.getStartSeq() > index || av.getEndSeq() < index)
323     {
324       alignPanel.setScrollValues(av.getStartRes(), index);
325     }
326   }
327
328   // this class allows scrolling off the bottom of the visible alignment
329   class ScrollThread extends Thread
330   {
331     boolean running = false;
332
333     boolean up = true;
334
335     public ScrollThread(boolean up)
336     {
337       this.up = up;
338       start();
339     }
340
341     public void stopScrolling()
342     {
343       running = false;
344     }
345
346     public void run()
347     {
348       running = true;
349       while (running)
350       {
351         if (alignPanel.scrollUp(up))
352         {
353           // scroll was ok, so add new sequence to selection
354           int seq = av.getStartSeq();
355           if (!up)
356           {
357             seq = av.getEndSeq();
358           }
359
360           if (seq < lastid)
361           {
362             selectSeqs(lastid - 1, seq);
363           }
364           else if (seq > lastid && seq < av.alignment.getHeight())
365           {
366             selectSeqs(lastid + 1, seq);
367           }
368
369           lastid = seq;
370         }
371         else
372         {
373           running = false;
374         }
375
376         alignPanel.paintAlignment(true);
377         try
378         {
379           Thread.sleep(100);
380         } catch (Exception ex)
381         {
382         }
383       }
384     }
385   }
386
387 }