Non positional features shown as mouse over
[jalview.git] / src / jalview / gui / IdPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 \r
26 import javax.swing.*;\r
27 \r
28 \r
29 /**\r
30  * DOCUMENT ME!\r
31  *\r
32  * @author $author$\r
33  * @version $Revision$\r
34  */\r
35 public class IdPanel extends JPanel implements MouseListener,\r
36     MouseMotionListener\r
37 {\r
38     protected IdCanvas idCanvas;\r
39     protected AlignViewport av;\r
40     protected AlignmentPanel alignPanel;\r
41     ScrollThread scrollThread = null;\r
42     int offy;\r
43     int width;\r
44     int lastid = -1;\r
45     boolean mouseDragging = false;\r
46 \r
47     /**\r
48      * Creates a new IdPanel object.\r
49      *\r
50      * @param av DOCUMENT ME!\r
51      * @param parent DOCUMENT ME!\r
52      */\r
53     public IdPanel(AlignViewport av, AlignmentPanel parent)\r
54     {\r
55         this.av = av;\r
56         alignPanel = parent;\r
57         idCanvas = new IdCanvas(av);\r
58         setLayout(new BorderLayout());\r
59         add(idCanvas, BorderLayout.CENTER);\r
60         addMouseListener(this);\r
61         addMouseMotionListener(this);\r
62         ToolTipManager.sharedInstance().registerComponent(this);\r
63     }\r
64 \r
65     /**\r
66      * DOCUMENT ME!\r
67      *\r
68      * @param e DOCUMENT ME!\r
69      */\r
70     public void mouseMoved(MouseEvent e)\r
71     {\r
72       int y = e.getY();\r
73 \r
74       if (av.getWrapAlignment())\r
75       {\r
76         y = getWrappedY(y);\r
77       }\r
78 \r
79       final int seq = av.getIndex(y);\r
80       if(seq!=-1)\r
81       {\r
82         SequenceI sequence = av.alignment.getSequenceAt(seq);\r
83         StringBuffer tip = new StringBuffer("<html>");\r
84         tip.append(sequence.getDisplayId(true));\r
85         if (av.alignment.getSequenceAt(seq).getDescription() != null)\r
86         {\r
87           tip.append("<table width=250 border=0><tr><td><i>");\r
88           tip.append(av.alignment.getSequenceAt(seq).getDescription());\r
89 \r
90           //ADD NON POSITIONAL SEQUENCE INFO\r
91           SequenceFeature [] features = sequence.getDatasetSequence().getSequenceFeatures();\r
92           if(features!=null)\r
93           {\r
94             for(int i=0; i<features.length; i++)\r
95             {\r
96               if(features[i].begin == 0 && features[i].end ==0)\r
97               {\r
98                 tip.append("<br>"+features[i].featureGroup\r
99                           +" "+ features[i].getType()+" "+features[i].description);\r
100               }\r
101             }\r
102           }\r
103 \r
104           tip.append("</i></td></tr></table>");\r
105         }\r
106         tip.append("</html>");\r
107         setToolTipText(tip.toString());\r
108       }\r
109 \r
110       if(av.hasHiddenRows)\r
111       {\r
112         if(av.adjustForHiddenSeqs(seq) -\r
113            av.adjustForHiddenSeqs(seq-1)>1)\r
114         {\r
115           JPopupMenu pop = new JPopupMenu();\r
116           JMenuItem item = new JMenuItem("Reveal");\r
117           item.addActionListener(new ActionListener()\r
118           {\r
119             public void actionPerformed(ActionEvent e)\r
120             {\r
121               av.showSequence(seq);\r
122               alignPanel.repaint();\r
123               if(alignPanel.overviewPanel!=null)\r
124                 alignPanel.overviewPanel.updateOverviewImage();\r
125             }\r
126           });\r
127           pop.add(item);\r
128           pop.show(this, e.getX(), e.getY());\r
129         }\r
130       }\r
131     }\r
132 \r
133 \r
134     int getWrappedY(int y)\r
135     {\r
136       int hgap = av.charHeight;\r
137       if (av.scaleAboveWrapped)\r
138         hgap += av.charHeight;\r
139 \r
140       return y - hgap;\r
141     }\r
142 \r
143 \r
144     /**\r
145      * DOCUMENT ME!\r
146      *\r
147      * @param e DOCUMENT ME!\r
148      */\r
149     public void mouseDragged(MouseEvent e)\r
150     {\r
151         mouseDragging = true;\r
152 \r
153         int y = e.getY();\r
154 \r
155         if (av.getWrapAlignment())\r
156         {\r
157             y = getWrappedY(y);\r
158         }\r
159 \r
160         int seq = av.getIndex(y);\r
161 \r
162         if (seq < 0)\r
163         {\r
164             return;\r
165         }\r
166 \r
167         if (seq < lastid)\r
168         {\r
169             selectSeqs(lastid - 1, seq);\r
170         }\r
171         else if (seq > lastid)\r
172         {\r
173             selectSeqs(lastid + 1, seq);\r
174         }\r
175 \r
176         lastid = seq;\r
177         alignPanel.repaint();\r
178     }\r
179 \r
180 \r
181     /**\r
182      * DOCUMENT ME!\r
183      *\r
184      * @param e DOCUMENT ME!\r
185      */\r
186     public void mouseClicked(MouseEvent e)\r
187     {\r
188       if (e.getClickCount() < 2)\r
189         return;\r
190 \r
191       java.util.Vector links = Preferences.sequenceURLLinks;\r
192       if (links == null || links.size() < 1)\r
193         return;\r
194 \r
195       int y = e.getY();\r
196 \r
197       if (av.getWrapAlignment())\r
198       {\r
199          y = getWrappedY(y);\r
200       }\r
201 \r
202       //DEFAULT LINK IS FIRST IN THE LINK LIST\r
203       int seq = av.getIndex(y);\r
204       if(seq==-1)\r
205         return;\r
206 \r
207       String id = av.getAlignment().getSequenceAt(seq).getName();\r
208       if (id.indexOf("|") > -1)\r
209         id = id.substring(id.lastIndexOf("|") + 1);\r
210 \r
211 \r
212       String url = links.elementAt(0).toString();\r
213       url = url.substring(url.indexOf("|")+1);\r
214 \r
215       int index = url.indexOf("$SEQUENCE_ID$");\r
216       url = url.substring(0, index)+ id + url.substring(index+13);\r
217 \r
218       try\r
219       {\r
220         jalview.util.BrowserLauncher.openURL(url);\r
221       }\r
222       catch (Exception ex)\r
223       {\r
224        JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
225            "Unixers: Couldn't find default web browser."\r
226           +"\nAdd the full path to your browser in Preferences.",\r
227           "Web browser not found", JOptionPane.WARNING_MESSAGE );\r
228         ex.printStackTrace();\r
229       }\r
230     }\r
231 \r
232     /**\r
233      * DOCUMENT ME!\r
234      *\r
235      * @param e DOCUMENT ME!\r
236      */\r
237     public void mouseEntered(MouseEvent e)\r
238     {\r
239         if (scrollThread != null)\r
240         {\r
241             scrollThread.running = false;\r
242         }\r
243     }\r
244 \r
245     /**\r
246      * DOCUMENT ME!\r
247      *\r
248      * @param e DOCUMENT ME!\r
249      */\r
250     public void mouseExited(MouseEvent e)\r
251     {\r
252         if (av.getWrapAlignment())\r
253         {\r
254             return;\r
255         }\r
256 \r
257         if (mouseDragging && (e.getY() < 0) && (av.getStartSeq() > 0))\r
258         {\r
259             scrollThread = new ScrollThread(true);\r
260         }\r
261 \r
262         if (mouseDragging && (e.getY() >= getHeight()) &&\r
263                 (av.alignment.getHeight() > av.getEndSeq()))\r
264         {\r
265             scrollThread = new ScrollThread(false);\r
266         }\r
267     }\r
268 \r
269     /**\r
270      * DOCUMENT ME!\r
271      *\r
272      * @param e DOCUMENT ME!\r
273      */\r
274     public void mousePressed(MouseEvent e)\r
275     {\r
276         if (e.getClickCount() == 2)\r
277         {\r
278             return;\r
279         }\r
280 \r
281         int y = e.getY();\r
282 \r
283         if (av.getWrapAlignment())\r
284         {\r
285             y = getWrappedY(y);\r
286         }\r
287 \r
288         int seq = av.getIndex(y);\r
289 \r
290         if (seq == -1)\r
291         {\r
292             return;\r
293         }\r
294 \r
295         if (javax.swing.SwingUtilities.isRightMouseButton(e))\r
296         {\r
297             jalview.gui.PopupMenu pop = new jalview.gui.PopupMenu(alignPanel,\r
298                     (Sequence) av.getAlignment().getSequenceAt(seq),\r
299                     Preferences.sequenceURLLinks);\r
300             pop.show(this, e.getX(), y);\r
301 \r
302             return;\r
303         }\r
304 \r
305       /*  if (!e.isControlDown() && !e.isShiftDown() &&\r
306                 (av.alignment.findGroup(av.alignment.getSequenceAt(seq)) != null))\r
307         {\r
308           System.out.println("no modifiers");\r
309             SequenceGroup selection = new SequenceGroup();\r
310             SequenceGroup sg = av.alignment.findGroup(av.alignment.getSequenceAt(\r
311                         seq));\r
312             selection.setStartRes(0);\r
313             selection.setEndRes(av.alignment.getWidth() - 1);\r
314 \r
315             for (int i = 0; i < sg.getSize(); i++)\r
316             {\r
317                 selection.addSequence(sg.getSequenceAt(i), true);\r
318             }\r
319 \r
320             av.setSelectionGroup(selection);\r
321 \r
322             return;\r
323         }*/\r
324 \r
325         if ((av.getSelectionGroup() == null) ||\r
326                 ((!e.isControlDown() && !e.isShiftDown()) && av.getSelectionGroup() != null))\r
327         {\r
328           av.setSelectionGroup(new SequenceGroup());\r
329           av.getSelectionGroup().setStartRes(0);\r
330           av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);\r
331         }\r
332 \r
333 \r
334 \r
335         if (e.isShiftDown() && (lastid != -1))\r
336         {\r
337             selectSeqs(lastid, seq);\r
338         }\r
339         else\r
340         {\r
341             selectSeq(seq);\r
342         }\r
343 \r
344         alignPanel.repaint();\r
345     }\r
346 \r
347     /**\r
348      * DOCUMENT ME!\r
349      *\r
350      * @param seq DOCUMENT ME!\r
351      */\r
352     void selectSeq(int seq)\r
353     {\r
354         lastid = seq;\r
355 \r
356         SequenceI pickedSeq = av.getAlignment().getSequenceAt(seq);\r
357         av.getSelectionGroup().addOrRemove(pickedSeq, true);\r
358     }\r
359 \r
360     /**\r
361      * DOCUMENT ME!\r
362      *\r
363      * @param start DOCUMENT ME!\r
364      * @param end DOCUMENT ME!\r
365      */\r
366     void selectSeqs(int start, int end)\r
367     {\r
368       if(av.getSelectionGroup()==null)\r
369             return;\r
370 \r
371         lastid = start;\r
372 \r
373         if (end < start)\r
374         {\r
375             int tmp = start;\r
376             start = end;\r
377             end = tmp;\r
378             lastid = end;\r
379         }\r
380 \r
381         for (int i = start; i <= end; i++)\r
382         {\r
383           av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i),\r
384                 true);\r
385         }\r
386     }\r
387 \r
388     /**\r
389      * DOCUMENT ME!\r
390      *\r
391      * @param e DOCUMENT ME!\r
392      */\r
393     public void mouseReleased(MouseEvent e)\r
394     {\r
395         if (scrollThread != null)\r
396         {\r
397             scrollThread.running = false;\r
398         }\r
399 \r
400         mouseDragging = false;\r
401         PaintRefresher.Refresh(av.alignment);\r
402     }\r
403 \r
404     /**\r
405      * DOCUMENT ME!\r
406      *\r
407      * @param found DOCUMENT ME!\r
408      */\r
409     public void highlightSearchResults(java.util.Vector found)\r
410     {\r
411         idCanvas.setHighlighted(found);\r
412 \r
413         if (found == null)\r
414         {\r
415             return;\r
416         }\r
417 \r
418         int index = av.alignment.findIndex((SequenceI) found.get(0));\r
419 \r
420         // do we need to scroll the panel?\r
421         if ((av.getStartSeq() > index) || (av.getEndSeq() < index))\r
422         {\r
423             alignPanel.setScrollValues(av.getStartRes(), index);\r
424         }\r
425     }\r
426 \r
427     // this class allows scrolling off the bottom of the visible alignment\r
428     class ScrollThread extends Thread\r
429     {\r
430         boolean running = false;\r
431         boolean up = true;\r
432 \r
433         public ScrollThread(boolean up)\r
434         {\r
435             this.up = up;\r
436             start();\r
437         }\r
438 \r
439         public void stopScrolling()\r
440         {\r
441             running = false;\r
442         }\r
443 \r
444         public void run()\r
445         {\r
446             running = true;\r
447 \r
448             while (running)\r
449             {\r
450                 if (alignPanel.scrollUp(up))\r
451                 {\r
452                     // scroll was ok, so add new sequence to selection\r
453                     int seq = av.getStartSeq();\r
454 \r
455                     if (!up)\r
456                     {\r
457                         seq = av.getEndSeq();\r
458                     }\r
459 \r
460                     if (seq < lastid)\r
461                     {\r
462                         selectSeqs(lastid - 1, seq);\r
463                     }\r
464                     else if (seq > lastid)\r
465                     {\r
466                         selectSeqs(lastid + 1, seq);\r
467                     }\r
468 \r
469                     lastid = seq;\r
470                 }\r
471                 else\r
472                 {\r
473                     running = false;\r
474                 }\r
475 \r
476                 alignPanel.repaint();\r
477 \r
478                 try\r
479                 {\r
480                     Thread.sleep(100);\r
481                 }\r
482                 catch (Exception ex)\r
483                 {\r
484                 }\r
485             }\r
486         }\r
487     }\r
488 }\r