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