Tooltips for features, links for features added
[jalview.git] / src / jalview / appletgui / APopupMenu.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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.awt.*;\r
23 import java.awt.event.*;\r
24 import java.util.Vector;\r
25 \r
26 import jalview.analysis.*;\r
27 import jalview.datamodel.*;\r
28 import jalview.schemes.*;\r
29 \r
30 public class APopupMenu\r
31     extends java.awt.PopupMenu implements ActionListener, ItemListener\r
32 {\r
33   Menu groupMenu = new Menu();\r
34   protected MenuItem clustalColour = new MenuItem();\r
35   protected MenuItem zappoColour = new MenuItem();\r
36   protected MenuItem taylorColour = new MenuItem();\r
37   protected MenuItem hydrophobicityColour = new MenuItem();\r
38   protected MenuItem helixColour = new MenuItem();\r
39   protected MenuItem strandColour = new MenuItem();\r
40   protected MenuItem turnColour = new MenuItem();\r
41   protected MenuItem buriedColour = new MenuItem();\r
42   protected CheckboxMenuItem abovePIDColour = new CheckboxMenuItem();\r
43   protected MenuItem userDefinedColour = new MenuItem();\r
44   protected MenuItem PIDColour = new MenuItem();\r
45   protected MenuItem BLOSUM62Colour = new MenuItem();\r
46   MenuItem noColourmenuItem = new MenuItem();\r
47   protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();\r
48 \r
49   final AlignmentPanel ap;\r
50   MenuItem unGroupMenuItem = new MenuItem();\r
51   MenuItem nucleotideMenuItem = new MenuItem();\r
52   Menu colourMenu = new Menu();\r
53   CheckboxMenuItem showBoxes = new CheckboxMenuItem();\r
54   CheckboxMenuItem showText = new CheckboxMenuItem();\r
55   CheckboxMenuItem showColourText = new CheckboxMenuItem();\r
56   Menu editMenu = new Menu("Edit");\r
57   MenuItem copy = new MenuItem("Copy (Jalview Only)");\r
58   MenuItem cut = new MenuItem("Cut (Jalview Only)");\r
59   MenuItem toUpper = new MenuItem("To Upper Case");\r
60   MenuItem toLower = new MenuItem("To Lower Case");\r
61   MenuItem toggleCase = new MenuItem("Toggle Case");\r
62 \r
63   public APopupMenu(AlignmentPanel apanel, final Sequence seq, Vector links)\r
64   {\r
65     ///////////////////////////////////////////////////////////\r
66     // If this is activated from the sequence panel, the user may want to\r
67     // edit or annotate a particular residue. Therefore display the residue menu\r
68     //\r
69     // If from the IDPanel, we must display the sequence menu\r
70     //////////////////////////////////////////////////////////\r
71 \r
72     this.ap = apanel;\r
73 \r
74     try\r
75     {\r
76       jbInit();\r
77     }\r
78     catch (Exception e)\r
79     {\r
80       e.printStackTrace();\r
81     }\r
82 \r
83     SequenceGroup sg = ap.av.getSelectionGroup();\r
84 \r
85     if (sg != null && sg.getSize()>0)\r
86     {\r
87       showText.setState(sg.getDisplayText());\r
88       showColourText.setState(sg.getColourText());\r
89       showBoxes.setState(sg.getDisplayBoxes());\r
90       if (!ap.av.alignment.getGroups().contains(sg))\r
91       {\r
92         groupMenu.remove(unGroupMenuItem);\r
93       }\r
94 \r
95     }\r
96     else\r
97     {\r
98       remove(groupMenu);\r
99       remove(editMenu);\r
100     }\r
101 \r
102     if (links!=null)\r
103     {\r
104       Menu linkMenu = new Menu("Link");\r
105       MenuItem item;\r
106       String link;\r
107       for(int i=0; i<links.size(); i++)\r
108       {\r
109         link = links.elementAt(i).toString();\r
110         final String target = link.substring(0, link.indexOf("|"));\r
111         item = new MenuItem(target);\r
112 \r
113         final String url;\r
114 \r
115         if (link.indexOf("$SEQUENCE_ID$") > -1)\r
116         {\r
117           String id = seq.getName();\r
118           if (id.indexOf("|") > -1)\r
119             id = id.substring(id.lastIndexOf("|") + 1);\r
120 \r
121           url = link.substring(link.indexOf("|") + 1,\r
122                                link.indexOf("$SEQUENCE_ID$"))\r
123               + id +\r
124               link.substring(link.indexOf("$SEQUENCE_ID$") + 13);\r
125         }\r
126         else\r
127           url = link.substring(link.lastIndexOf("|")+1);\r
128 \r
129            item.addActionListener(new java.awt.event.ActionListener()\r
130            {\r
131                public void actionPerformed(ActionEvent e)\r
132                {\r
133                   ap.alignFrame.showURL(url, target);\r
134                }\r
135            });\r
136           linkMenu.add(item);\r
137       }\r
138       add(linkMenu);\r
139 \r
140       if(seq!=null)\r
141       {\r
142         item = new MenuItem("Show PDB Structure");\r
143         item.addActionListener(new java.awt.event.ActionListener()\r
144         {\r
145           public void actionPerformed(ActionEvent e)\r
146           {\r
147             addPDB(seq);\r
148           }\r
149         });\r
150 \r
151         add(item);\r
152       }\r
153     }\r
154   }\r
155 \r
156   public void itemStateChanged(ItemEvent evt)\r
157   {\r
158     if(evt.getSource()==abovePIDColour)\r
159       abovePIDColour_itemStateChanged();\r
160     else if(evt.getSource()==showColourText)\r
161       showColourText_itemStateChanged();\r
162     else if(evt.getSource()==showText)\r
163       showText_itemStateChanged();\r
164     else if(evt.getSource()==showBoxes)\r
165        showBoxes_itemStateChanged()   ;\r
166   }\r
167 \r
168   public void actionPerformed(ActionEvent evt)\r
169   {\r
170     Object source = evt.getSource();\r
171     if(source==clustalColour)\r
172       clustalColour_actionPerformed();\r
173     else if(source==zappoColour)\r
174       zappoColour_actionPerformed();\r
175     else if(source==taylorColour)\r
176       taylorColour_actionPerformed();\r
177     else if(source==hydrophobicityColour)\r
178       hydrophobicityColour_actionPerformed();\r
179     else if(source==helixColour)\r
180       helixColour_actionPerformed();\r
181     else if(source==strandColour)\r
182       strandColour_actionPerformed();\r
183     else if(source==clustalColour)\r
184       turnColour_actionPerformed();\r
185     else if(source==buriedColour)\r
186       buriedColour_actionPerformed();\r
187     else if(source==nucleotideMenuItem)\r
188       nucleotideMenuItem_actionPerformed();\r
189 \r
190     else if(source==userDefinedColour)\r
191           userDefinedColour_actionPerformed();\r
192         else if(source==PIDColour)\r
193        PIDColour_actionPerformed();\r
194      else if(source==BLOSUM62Colour)\r
195       BLOSUM62Colour_actionPerformed();\r
196     else if(source==noColourmenuItem)\r
197       noColourmenuItem_actionPerformed();\r
198     else if(source==conservationMenuItem)\r
199         conservationMenuItem_itemStateChanged();\r
200       else if(source==unGroupMenuItem)\r
201       unGroupMenuItem_actionPerformed();\r
202 \r
203     else if(source==copy)\r
204       ap.alignFrame.copy_actionPerformed();\r
205     else if(source==cut)\r
206       ap.alignFrame.cut_actionPerformed();\r
207     else if(source==toUpper || source==toLower || source==toggleCase)\r
208     {\r
209       SequenceGroup sg = ap.av.getSelectionGroup();\r
210       if (sg != null)\r
211       {\r
212         for (int g = 0; g < sg.getSize(); g++)\r
213         {\r
214           if (source == toggleCase)\r
215             sg.getSequenceAt(g).toggleCase(sg.getStartRes(), sg.getEndRes() + 1);\r
216           else\r
217             sg.getSequenceAt(g).changeCase(source == toUpper, sg.getStartRes(),\r
218                                            sg.getEndRes() + 1);\r
219         }\r
220         ap.seqPanel.seqCanvas.repaint();\r
221       }\r
222     }\r
223 \r
224   }\r
225 \r
226   void addPDB(Sequence seq)\r
227   {\r
228     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);\r
229     cap.setText("Paste your PDB file here.");\r
230     cap.setPDBImport(seq);\r
231     Frame frame = new Frame();\r
232     frame.add(cap);\r
233     jalview.bin.JalviewLite.addFrame(frame, "Paste PDB file ", 400, 300);\r
234   }\r
235 \r
236   private void jbInit()\r
237       throws Exception\r
238   {\r
239     groupMenu.setLabel("Group");\r
240     groupMenu.setLabel("Define");\r
241 \r
242     unGroupMenuItem.setLabel("Remove Group");\r
243     unGroupMenuItem.addActionListener(this);\r
244 \r
245     nucleotideMenuItem.setLabel("Nucleotide");\r
246     nucleotideMenuItem.addActionListener(this);\r
247     conservationMenuItem.addItemListener(this);\r
248     abovePIDColour.addItemListener(this);\r
249     colourMenu.setLabel("Group Colour");\r
250     showBoxes.setLabel("Boxes");\r
251     showBoxes.setState(true);\r
252     showBoxes.addItemListener(this);\r
253 \r
254     showText.setLabel("Text");\r
255     showText.addItemListener(this);\r
256     showColourText.setLabel("Colour Text");\r
257     showColourText.addItemListener(this);\r
258 \r
259     add(groupMenu);\r
260     groupMenu.add(unGroupMenuItem);\r
261     groupMenu.add(colourMenu);\r
262     groupMenu.addSeparator();\r
263     groupMenu.add(showBoxes);\r
264     groupMenu.add(showText);\r
265     groupMenu.add(showColourText);\r
266     colourMenu.add(noColourmenuItem);\r
267     colourMenu.add(clustalColour);\r
268     colourMenu.add(BLOSUM62Colour);\r
269     colourMenu.add(PIDColour);\r
270     colourMenu.add(zappoColour);\r
271     colourMenu.add(taylorColour);\r
272     colourMenu.add(hydrophobicityColour);\r
273     colourMenu.add(helixColour);\r
274     colourMenu.add(strandColour);\r
275     colourMenu.add(turnColour);\r
276     colourMenu.add(buriedColour);\r
277     colourMenu.add(nucleotideMenuItem);\r
278     colourMenu.add(userDefinedColour);\r
279     colourMenu.addSeparator();\r
280     colourMenu.add(abovePIDColour);\r
281     colourMenu.add(conservationMenuItem);\r
282 \r
283     noColourmenuItem.setLabel("None");\r
284     noColourmenuItem.addActionListener(this);\r
285 \r
286     clustalColour.setLabel("Clustalx colours");\r
287     clustalColour.addActionListener(this);\r
288     zappoColour.setLabel("Zappo");\r
289     zappoColour.addActionListener(this);\r
290     taylorColour.setLabel("Taylor");\r
291     taylorColour.addActionListener(this);\r
292     hydrophobicityColour.setLabel("Hydrophobicity");\r
293     hydrophobicityColour.addActionListener(this);\r
294     helixColour.setLabel("Helix propensity");\r
295     helixColour.addActionListener(this);\r
296     strandColour.setLabel("Strand propensity");\r
297     strandColour.addActionListener(this);\r
298     turnColour.setLabel("Turn propensity");\r
299     turnColour.addActionListener(this);\r
300     buriedColour.setLabel("Buried Index");\r
301     buriedColour.addActionListener(this);\r
302     abovePIDColour.setLabel("Above % Identity");\r
303 \r
304     userDefinedColour.setLabel("User Defined");\r
305     userDefinedColour.addActionListener(this);\r
306     PIDColour.setLabel("Percentage Identity");\r
307     PIDColour.addActionListener(this);\r
308     BLOSUM62Colour.setLabel("BLOSUM62");\r
309     BLOSUM62Colour.addActionListener(this);\r
310     conservationMenuItem.setLabel("Conservation");\r
311 \r
312     add(editMenu);\r
313     editMenu.add(copy);\r
314     copy.addActionListener(this);\r
315     editMenu.add(cut);\r
316     cut.addActionListener(this);\r
317     editMenu.add(toUpper);\r
318     toUpper.addActionListener(this);\r
319     editMenu.add(toLower);\r
320     toLower.addActionListener(this);\r
321     editMenu.add(toggleCase);\r
322     toggleCase.addActionListener(this);\r
323 \r
324   }\r
325 \r
326   void refresh()\r
327   {\r
328     ap.seqPanel.seqCanvas.repaint();\r
329     if(ap.overviewPanel!=null)\r
330       ap.overviewPanel.updateOverviewImage();\r
331   }\r
332 \r
333   protected void clustalColour_actionPerformed()\r
334   {\r
335     SequenceGroup sg = getGroup();\r
336     sg.cs = new ClustalxColourScheme(sg.sequences, ap.av.alignment.getWidth());\r
337     refresh();\r
338   }\r
339 \r
340   protected void zappoColour_actionPerformed()\r
341   {\r
342     getGroup().cs = new ZappoColourScheme();\r
343     refresh();\r
344   }\r
345 \r
346   protected void taylorColour_actionPerformed()\r
347   {\r
348     getGroup().cs = new TaylorColourScheme();\r
349     refresh();\r
350   }\r
351 \r
352   protected void hydrophobicityColour_actionPerformed()\r
353   {\r
354     getGroup().cs = new HydrophobicColourScheme();\r
355     refresh();\r
356   }\r
357 \r
358   protected void helixColour_actionPerformed()\r
359   {\r
360     getGroup().cs = new HelixColourScheme();\r
361     refresh();\r
362   }\r
363 \r
364   protected void strandColour_actionPerformed()\r
365   {\r
366     getGroup().cs = new StrandColourScheme();\r
367     refresh();\r
368   }\r
369 \r
370   protected void turnColour_actionPerformed()\r
371   {\r
372     getGroup().cs = new TurnColourScheme();\r
373     refresh();\r
374   }\r
375 \r
376   protected void buriedColour_actionPerformed()\r
377   {\r
378     getGroup().cs = new BuriedColourScheme();\r
379     refresh();\r
380   }\r
381 \r
382   public void nucleotideMenuItem_actionPerformed()\r
383   {\r
384     getGroup().cs = new NucleotideColourScheme();\r
385     refresh();\r
386   }\r
387 \r
388   protected void abovePIDColour_itemStateChanged()\r
389   {\r
390     SequenceGroup sg = getGroup();\r
391     if(sg.cs==null)\r
392           return;\r
393 \r
394     if (abovePIDColour.getState())\r
395     {\r
396       sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0,\r
397                                                ap.av.alignment.getWidth()));\r
398       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs,\r
399           getGroup().getName());\r
400 \r
401       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());\r
402 \r
403       SliderPanel.showPIDSlider();\r
404 \r
405     }\r
406     else // remove PIDColouring\r
407     {\r
408       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());\r
409     }\r
410 \r
411     refresh();\r
412 \r
413   }\r
414 \r
415   protected void userDefinedColour_actionPerformed()\r
416   {\r
417     new UserDefinedColours(ap, getGroup());\r
418   }\r
419 \r
420   protected void PIDColour_actionPerformed()\r
421   {\r
422     SequenceGroup sg = getGroup();\r
423     sg.cs = new PIDColourScheme();\r
424     sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0,\r
425                                              ap.av.alignment.getWidth()));\r
426     refresh();\r
427   }\r
428 \r
429   protected void BLOSUM62Colour_actionPerformed()\r
430   {\r
431     SequenceGroup sg = getGroup();\r
432 \r
433     sg.cs = new Blosum62ColourScheme();\r
434 \r
435     sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0,\r
436                                              ap.av.alignment.getWidth()));\r
437 \r
438     refresh();\r
439   }\r
440 \r
441   protected void noColourmenuItem_actionPerformed()\r
442   {\r
443     getGroup().cs = null;\r
444     refresh();\r
445   }\r
446 \r
447   protected void conservationMenuItem_itemStateChanged()\r
448   {\r
449     SequenceGroup sg = getGroup();\r
450     if(sg.cs==null)\r
451           return;\r
452 \r
453     if (conservationMenuItem.getState())\r
454     {\r
455 \r
456       Conservation c = new Conservation("Group",\r
457                                         ResidueProperties.propHash, 3,\r
458                                         sg.sequences, 0,\r
459                                         ap.av.alignment.getWidth());\r
460 \r
461       c.calculate();\r
462       c.verdict(false, ap.av.ConsPercGaps);\r
463 \r
464       sg.cs.setConservation(c);\r
465 \r
466       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());\r
467       SliderPanel.showConservationSlider();\r
468     }\r
469     else // remove ConservationColouring\r
470     {\r
471       sg.cs.setConservation(null);\r
472     }\r
473 \r
474     refresh();\r
475   }\r
476 \r
477 \r
478   SequenceGroup getGroup()\r
479   {\r
480     SequenceGroup sg = ap.av.getSelectionGroup();\r
481 \r
482     // this method won't add a new group if it already exists\r
483     if(sg!=null)\r
484       ap.av.alignment.addGroup(sg);\r
485 \r
486     return sg;\r
487   }\r
488 \r
489   void unGroupMenuItem_actionPerformed()\r
490   {\r
491     SequenceGroup sg = ap.av.getSelectionGroup();\r
492     ap.av.alignment.deleteGroup(sg);\r
493     ap.av.setSelectionGroup(null);\r
494     ap.repaint();\r
495   }\r
496 \r
497   public void showColourText_itemStateChanged()\r
498   {\r
499     getGroup().setColourText(showColourText.getState());\r
500     refresh();\r
501   }\r
502 \r
503   public void showText_itemStateChanged()\r
504   {\r
505     getGroup().setDisplayText(showText.getState());\r
506     refresh();\r
507   }\r
508 \r
509   public void showBoxes_itemStateChanged()\r
510   {\r
511     getGroup().setDisplayBoxes(showBoxes.getState());\r
512     refresh();\r
513   }\r
514 \r
515 }\r