merge from 2_4_Release branch
[jalview.git] / src / jalview / gui / PopupMenu.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.gui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import javax.swing.*;
26
27 import MCview.*;
28 import jalview.analysis.*;
29 import jalview.commands.*;
30 import jalview.datamodel.*;
31 import jalview.io.*;
32 import jalview.schemes.*;
33 import jalview.util.UrlLink;
34
35 /**
36  * DOCUMENT ME!
37  * 
38  * @author $author$
39  * @version $Revision$
40  */
41 public class PopupMenu extends JPopupMenu
42 {
43   JMenu groupMenu = new JMenu();
44
45   JMenuItem groupName = new JMenuItem();
46
47   protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
48
49   protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
50
51   protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
52
53   protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
54
55   protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
56
57   protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
58
59   protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
60
61   protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
62
63   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
64
65   protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
66
67   protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
68
69   protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
70
71   JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
72
73   protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
74
75   AlignmentPanel ap;
76
77   JMenu sequenceMenu = new JMenu();
78
79   JMenuItem sequenceName = new JMenuItem();
80
81   Sequence sequence;
82
83   JMenuItem unGroupMenuItem = new JMenuItem();
84
85   JMenuItem outline = new JMenuItem();
86
87   JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
88
89   JMenu colourMenu = new JMenu();
90
91   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
92
93   JCheckBoxMenuItem showText = new JCheckBoxMenuItem();
94
95   JCheckBoxMenuItem showColourText = new JCheckBoxMenuItem();
96
97   JMenu editMenu = new JMenu();
98
99   JMenuItem cut = new JMenuItem();
100
101   JMenuItem copy = new JMenuItem();
102
103   JMenuItem upperCase = new JMenuItem();
104
105   JMenuItem lowerCase = new JMenuItem();
106
107   JMenuItem toggle = new JMenuItem();
108
109   JMenu pdbMenu = new JMenu();
110
111   JMenuItem pdbFromFile = new JMenuItem();
112
113   JMenuItem enterPDB = new JMenuItem();
114
115   JMenuItem discoverPDB = new JMenuItem();
116
117   JMenu outputMenu = new JMenu();
118
119   JMenuItem sequenceFeature = new JMenuItem();
120
121   JMenuItem textColour = new JMenuItem();
122
123   JMenu jMenu1 = new JMenu();
124
125   JMenu structureMenu = new JMenu();
126
127   JMenu viewStructureMenu = new JMenu();
128
129   // JMenu colStructureMenu = new JMenu();
130   JMenuItem editSequence = new JMenuItem();
131
132   // JMenuItem annotationMenuItem = new JMenuItem();
133
134   /**
135    * Creates a new PopupMenu object.
136    * 
137    * @param ap
138    *                DOCUMENT ME!
139    * @param seq
140    *                DOCUMENT ME!
141    */
142   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
143   {
144     // /////////////////////////////////////////////////////////
145     // If this is activated from the sequence panel, the user may want to
146     // edit or annotate a particular residue. Therefore display the residue menu
147     //
148     // If from the IDPanel, we must display the sequence menu
149     // ////////////////////////////////////////////////////////
150     this.ap = ap;
151     sequence = seq;
152
153     ButtonGroup colours = new ButtonGroup();
154     colours.add(noColourmenuItem);
155     colours.add(clustalColour);
156     colours.add(zappoColour);
157     colours.add(taylorColour);
158     colours.add(hydrophobicityColour);
159     colours.add(helixColour);
160     colours.add(strandColour);
161     colours.add(turnColour);
162     colours.add(buriedColour);
163     colours.add(abovePIDColour);
164     colours.add(userDefinedColour);
165     colours.add(PIDColour);
166     colours.add(BLOSUM62Colour);
167
168     for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
169     {
170       JMenuItem item = new JMenuItem(
171               jalview.io.FormatAdapter.WRITEABLE_FORMATS[i]);
172
173       item.addActionListener(new java.awt.event.ActionListener()
174       {
175         public void actionPerformed(ActionEvent e)
176         {
177           outputText_actionPerformed(e);
178         }
179       });
180
181       outputMenu.add(item);
182     }
183
184     try
185     {
186       jbInit();
187     } catch (Exception e)
188     {
189       e.printStackTrace();
190     }
191
192     if (seq != null)
193     {
194       sequenceMenu.setText(sequence.getName());
195
196       JMenuItem menuItem;
197       if (seq.getDatasetSequence().getPDBId() != null
198               && seq.getDatasetSequence().getPDBId().size() > 0)
199       {
200         java.util.Enumeration e = seq.getDatasetSequence().getPDBId()
201                 .elements();
202
203         while (e.hasMoreElements())
204         {
205           final PDBEntry pdb = (PDBEntry) e.nextElement();
206
207           menuItem = new JMenuItem();
208           menuItem.setText(pdb.getId());
209           menuItem.addActionListener(new java.awt.event.ActionListener()
210           {
211             public void actionPerformed(ActionEvent e)
212             {
213               Vector seqs = new Vector();
214               for (int i = 0; i < ap.av.alignment.getHeight(); i++)
215               {
216                 Vector pdbs = ap.av.alignment.getSequenceAt(i)
217                         .getDatasetSequence().getPDBId();
218                 if (pdbs == null)
219                   continue;
220
221                 for (int p = 0; p < pdbs.size(); p++)
222                 {
223                   PDBEntry p1 = (PDBEntry) pdbs.elementAt(p);
224                   if (p1.getId().equals(pdb.getId()))
225                   {
226                     if (!seqs.contains(ap.av.alignment.getSequenceAt(i)))
227                       seqs.addElement(ap.av.alignment.getSequenceAt(i));
228
229                     continue;
230                   }
231                 }
232               }
233
234               SequenceI[] seqs2 = new SequenceI[seqs.size()];
235               seqs.toArray(seqs2);
236
237               new AppJmol(pdb, seqs2, null, ap);
238               // new PDBViewer(pdb, seqs2, null, ap, AppletFormatAdapter.FILE);
239             }
240           });
241           viewStructureMenu.add(menuItem);
242
243           /*
244            * menuItem = new JMenuItem(); menuItem.setText(pdb.getId());
245            * menuItem.addActionListener(new java.awt.event.ActionListener() {
246            * public void actionPerformed(ActionEvent e) {
247            * colourByStructure(pdb.getId()); } });
248            * colStructureMenu.add(menuItem);
249            */
250         }
251       }
252       else
253       {
254         structureMenu.remove(viewStructureMenu);
255         // structureMenu.remove(colStructureMenu);
256       }
257
258       menuItem = new JMenuItem("Hide Sequences");
259       menuItem.addActionListener(new java.awt.event.ActionListener()
260       {
261         public void actionPerformed(ActionEvent e)
262         {
263           hideSequences(false);
264         }
265       });
266       add(menuItem);
267
268       if (ap.av.getSelectionGroup() != null
269               && ap.av.getSelectionGroup().getSize() > 1)
270       {
271         menuItem = new JMenuItem("Represent Group with " + seq.getName());
272         menuItem.addActionListener(new java.awt.event.ActionListener()
273         {
274           public void actionPerformed(ActionEvent e)
275           {
276             hideSequences(true);
277           }
278         });
279         sequenceMenu.add(menuItem);
280       }
281
282       if (ap.av.hasHiddenRows)
283       {
284         final int index = ap.av.alignment.findIndex(seq);
285
286         if (ap.av.adjustForHiddenSeqs(index)
287                 - ap.av.adjustForHiddenSeqs(index - 1) > 1)
288         {
289           menuItem = new JMenuItem("Reveal Sequences");
290           menuItem.addActionListener(new ActionListener()
291           {
292             public void actionPerformed(ActionEvent e)
293             {
294               ap.av.showSequence(index);
295               if (ap.overviewPanel != null)
296               {
297                 ap.overviewPanel.updateOverviewImage();
298               }
299             }
300           });
301           add(menuItem);
302         }
303
304         menuItem = new JMenuItem("Reveal All");
305         menuItem.addActionListener(new ActionListener()
306         {
307           public void actionPerformed(ActionEvent e)
308           {
309             ap.av.showAllHiddenSeqs();
310             if (ap.overviewPanel != null)
311             {
312               ap.overviewPanel.updateOverviewImage();
313             }
314           }
315         });
316
317         add(menuItem);
318       }
319
320     }
321
322     SequenceGroup sg = ap.av.getSelectionGroup();
323
324     if (sg != null)
325     {
326       groupName.setText(sg.getName());
327
328       if (sg.cs instanceof ZappoColourScheme)
329       {
330         zappoColour.setSelected(true);
331       }
332       else if (sg.cs instanceof TaylorColourScheme)
333       {
334         taylorColour.setSelected(true);
335       }
336       else if (sg.cs instanceof PIDColourScheme)
337       {
338         PIDColour.setSelected(true);
339       }
340       else if (sg.cs instanceof Blosum62ColourScheme)
341       {
342         BLOSUM62Colour.setSelected(true);
343       }
344       else if (sg.cs instanceof UserColourScheme)
345       {
346         userDefinedColour.setSelected(true);
347       }
348       else if (sg.cs instanceof HydrophobicColourScheme)
349       {
350         hydrophobicityColour.setSelected(true);
351       }
352       else if (sg.cs instanceof HelixColourScheme)
353       {
354         helixColour.setSelected(true);
355       }
356       else if (sg.cs instanceof StrandColourScheme)
357       {
358         strandColour.setSelected(true);
359       }
360       else if (sg.cs instanceof TurnColourScheme)
361       {
362         turnColour.setSelected(true);
363       }
364       else if (sg.cs instanceof BuriedColourScheme)
365       {
366         buriedColour.setSelected(true);
367       }
368       else if (sg.cs instanceof ClustalxColourScheme)
369       {
370         clustalColour.setSelected(true);
371       }
372       else
373       {
374         noColourmenuItem.setSelected(true);
375       }
376
377       if (sg.cs != null && sg.cs.conservationApplied())
378       {
379         conservationMenuItem.setSelected(true);
380       }
381
382       showText.setSelected(sg.getDisplayText());
383       showColourText.setSelected(sg.getColourText());
384       showBoxes.setSelected(sg.getDisplayBoxes());
385     }
386     else
387     {
388       groupMenu.setVisible(false);
389       editMenu.setVisible(false);
390     }
391
392     if (!ap.av.alignment.getGroups().contains(sg))
393     {
394       unGroupMenuItem.setVisible(false);
395     }
396
397     if (seq == null)
398     {
399       sequenceMenu.setVisible(false);
400       structureMenu.setVisible(false);
401     }
402
403     if (links != null && links.size() > 0)
404     {
405       JMenu linkMenu = new JMenu("Link");
406
407       for (int i = 0; i < links.size(); i++)
408       {
409         String link = links.elementAt(i).toString();
410         UrlLink urlLink = null;
411         try
412         {
413           urlLink = new UrlLink(link);
414         } catch (Exception foo)
415         {
416           jalview.bin.Cache.log.error("Exception for URLLink '" + link
417                   + "'", foo);
418           continue;
419         }
420         ;
421         if (!urlLink.isValid())
422         {
423           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
424           continue;
425         }
426         final String label = urlLink.getLabel();
427         if (urlLink.isDynamic())
428         {
429
430           // collect matching db-refs
431           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq
432                   .getDBRef(), new String[]
433           { urlLink.getTarget() });
434           // collect id string too
435           String id = seq.getName();
436           if (dbr != null)
437           {
438             for (int r = 0; r < dbr.length; r++)
439             {
440               if (id != null && dbr[r].getAccessionId().equals(id))
441               {
442                 // suppress duplicate link creation for the bare sequence ID
443                 // string with this link
444                 id = null;
445               }
446               // create Bare ID link for this RUL
447               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
448                       true);
449               if (urls != null)
450               {
451                 for (int u = 0; u < urls.length; u += 2)
452                 {
453                   addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
454                 }
455               }
456             }
457           }
458           if (id != null)
459           {
460             // create Bare ID link for this RUL
461             String[] urls = urlLink.makeUrls(id, true);
462             if (urls != null)
463             {
464               for (int u = 0; u < urls.length; u += 2)
465               {
466                 addshowLink(linkMenu, label, urls[u + 1]);
467               }
468             }
469           }
470         }
471         else
472         {
473           // Add a non-dynamic link
474           addshowLink(linkMenu, label, urlLink.getUrl_prefix());
475         }
476       }
477       if (sequence != null)
478       {
479         sequenceMenu.add(linkMenu);
480       }
481       else
482       {
483         add(linkMenu);
484       }
485     }
486   }
487
488   /**
489    * add a show URL menu item to the given linkMenu
490    * 
491    * @param linkMenu
492    * @param label -
493    *                menu label string
494    * @param url -
495    *                url to open
496    */
497   private void addshowLink(JMenu linkMenu, String label, final String url)
498   {
499     JMenuItem item = new JMenuItem(label);
500     item.setToolTipText("open URL: " + url);
501     item.addActionListener(new java.awt.event.ActionListener()
502     {
503       public void actionPerformed(ActionEvent e)
504       {
505         new Thread(new Runnable()
506         {
507
508           public void run()
509           {
510             showLink(url);
511           }
512
513         }).start();
514       }
515     });
516
517     linkMenu.add(item);
518   }
519
520   /**
521    * DOCUMENT ME!
522    * 
523    * @throws Exception
524    *                 DOCUMENT ME!
525    */
526   private void jbInit() throws Exception
527   {
528     groupMenu.setText("Group");
529     groupMenu.setText("Selection");
530     groupName.setText("Name");
531     groupName.addActionListener(new java.awt.event.ActionListener()
532     {
533       public void actionPerformed(ActionEvent e)
534       {
535         groupName_actionPerformed();
536       }
537     });
538     sequenceMenu.setText("Sequence");
539     sequenceName.setText("Edit Name/Description");
540     sequenceName.addActionListener(new java.awt.event.ActionListener()
541     {
542       public void actionPerformed(ActionEvent e)
543       {
544         sequenceName_actionPerformed();
545       }
546     });
547     PIDColour.setFocusPainted(false);
548     unGroupMenuItem.setText("Remove Group");
549     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
550     {
551       public void actionPerformed(ActionEvent e)
552       {
553         unGroupMenuItem_actionPerformed();
554       }
555     });
556
557     outline.setText("Border colour");
558     outline.addActionListener(new java.awt.event.ActionListener()
559     {
560       public void actionPerformed(ActionEvent e)
561       {
562         outline_actionPerformed();
563       }
564     });
565     nucleotideMenuItem.setText("Nucleotide");
566     nucleotideMenuItem.addActionListener(new ActionListener()
567     {
568       public void actionPerformed(ActionEvent e)
569       {
570         nucleotideMenuItem_actionPerformed();
571       }
572     });
573     colourMenu.setText("Group Colour");
574     showBoxes.setText("Boxes");
575     showBoxes.setState(true);
576     showBoxes.addActionListener(new ActionListener()
577     {
578       public void actionPerformed(ActionEvent e)
579       {
580         showBoxes_actionPerformed();
581       }
582     });
583     showText.setText("Text");
584     showText.setState(true);
585     showText.addActionListener(new ActionListener()
586     {
587       public void actionPerformed(ActionEvent e)
588       {
589         showText_actionPerformed();
590       }
591     });
592     showColourText.setText("Colour Text");
593     showColourText.addActionListener(new ActionListener()
594     {
595       public void actionPerformed(ActionEvent e)
596       {
597         showColourText_actionPerformed();
598       }
599     });
600     editMenu.setText("Edit");
601     cut.setText("Cut");
602     cut.addActionListener(new ActionListener()
603     {
604       public void actionPerformed(ActionEvent e)
605       {
606         cut_actionPerformed();
607       }
608     });
609     upperCase.setText("To Upper Case");
610     upperCase.addActionListener(new ActionListener()
611     {
612       public void actionPerformed(ActionEvent e)
613       {
614         changeCase(e);
615       }
616     });
617     copy.setText("Copy");
618     copy.addActionListener(new ActionListener()
619     {
620       public void actionPerformed(ActionEvent e)
621       {
622         copy_actionPerformed();
623       }
624     });
625     lowerCase.setText("To Lower Case");
626     lowerCase.addActionListener(new ActionListener()
627     {
628       public void actionPerformed(ActionEvent e)
629       {
630         changeCase(e);
631       }
632     });
633     toggle.setText("Toggle Case");
634     toggle.addActionListener(new ActionListener()
635     {
636       public void actionPerformed(ActionEvent e)
637       {
638         changeCase(e);
639       }
640     });
641     pdbMenu.setText("Associate Structure with Sequence");
642     pdbFromFile.setText("From File");
643     pdbFromFile.addActionListener(new ActionListener()
644     {
645       public void actionPerformed(ActionEvent e)
646       {
647         pdbFromFile_actionPerformed();
648       }
649     });
650     enterPDB.setText("Enter PDB Id");
651     enterPDB.addActionListener(new ActionListener()
652     {
653       public void actionPerformed(ActionEvent e)
654       {
655         enterPDB_actionPerformed();
656       }
657     });
658     discoverPDB.setText("Discover PDB ids");
659     discoverPDB.addActionListener(new ActionListener()
660     {
661       public void actionPerformed(ActionEvent e)
662       {
663         discoverPDB_actionPerformed();
664       }
665     });
666     outputMenu.setText("Output to Textbox...");
667     sequenceFeature.setText("Create Sequence Feature");
668     sequenceFeature.addActionListener(new ActionListener()
669     {
670       public void actionPerformed(ActionEvent e)
671       {
672         sequenceFeature_actionPerformed();
673       }
674     });
675     textColour.setText("Text Colour");
676     textColour.addActionListener(new ActionListener()
677     {
678       public void actionPerformed(ActionEvent e)
679       {
680         textColour_actionPerformed();
681       }
682     });
683     jMenu1.setText("Group");
684     structureMenu.setText("Structure");
685     viewStructureMenu.setText("View Structure");
686     // colStructureMenu.setText("Colour By Structure");
687     editSequence.setText("Edit Sequence...");
688     editSequence.addActionListener(new ActionListener()
689     {
690       public void actionPerformed(ActionEvent actionEvent)
691       {
692         editSequence_actionPerformed(actionEvent);
693       }
694     });
695     /*
696      * annotationMenuItem.setText("By Annotation");
697      * annotationMenuItem.addActionListener(new ActionListener() { public void
698      * actionPerformed(ActionEvent actionEvent) {
699      * annotationMenuItem_actionPerformed(actionEvent); } });
700      */
701
702     add(groupMenu);
703
704     add(sequenceMenu);
705     this.add(structureMenu);
706     groupMenu.add(editMenu);
707     groupMenu.add(outputMenu);
708     groupMenu.add(sequenceFeature);
709     groupMenu.add(jMenu1);
710     sequenceMenu.add(sequenceName);
711     colourMenu.add(textColour);
712     colourMenu.add(noColourmenuItem);
713     colourMenu.add(clustalColour);
714     colourMenu.add(BLOSUM62Colour);
715     colourMenu.add(PIDColour);
716     colourMenu.add(zappoColour);
717     colourMenu.add(taylorColour);
718     colourMenu.add(hydrophobicityColour);
719     colourMenu.add(helixColour);
720     colourMenu.add(strandColour);
721     colourMenu.add(turnColour);
722     colourMenu.add(buriedColour);
723     colourMenu.add(nucleotideMenuItem);
724     colourMenu.add(userDefinedColour);
725
726     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
727     {
728       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
729               .getUserColourSchemes().keys();
730
731       while (userColours.hasMoreElements())
732       {
733         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
734         item.addActionListener(new ActionListener()
735         {
736           public void actionPerformed(ActionEvent evt)
737           {
738             userDefinedColour_actionPerformed(evt);
739           }
740         });
741         colourMenu.add(item);
742       }
743     }
744
745     colourMenu.addSeparator();
746     colourMenu.add(abovePIDColour);
747     colourMenu.add(conservationMenuItem);
748     // colourMenu.add(annotationMenuItem);
749     editMenu.add(copy);
750     editMenu.add(cut);
751     editMenu.add(editSequence);
752     editMenu.add(upperCase);
753     editMenu.add(lowerCase);
754     editMenu.add(toggle);
755     pdbMenu.add(pdbFromFile);
756     pdbMenu.add(enterPDB);
757     pdbMenu.add(discoverPDB);
758     jMenu1.add(groupName);
759     jMenu1.add(unGroupMenuItem);
760     jMenu1.add(colourMenu);
761     jMenu1.add(showBoxes);
762     jMenu1.add(showText);
763     jMenu1.add(showColourText);
764     jMenu1.add(outline);
765     structureMenu.add(pdbMenu);
766     structureMenu.add(viewStructureMenu);
767     // structureMenu.add(colStructureMenu);
768     noColourmenuItem.setText("None");
769     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
770     {
771       public void actionPerformed(ActionEvent e)
772       {
773         noColourmenuItem_actionPerformed();
774       }
775     });
776
777     clustalColour.setText("Clustalx colours");
778     clustalColour.addActionListener(new java.awt.event.ActionListener()
779     {
780       public void actionPerformed(ActionEvent e)
781       {
782         clustalColour_actionPerformed();
783       }
784     });
785     zappoColour.setText("Zappo");
786     zappoColour.addActionListener(new java.awt.event.ActionListener()
787     {
788       public void actionPerformed(ActionEvent e)
789       {
790         zappoColour_actionPerformed();
791       }
792     });
793     taylorColour.setText("Taylor");
794     taylorColour.addActionListener(new java.awt.event.ActionListener()
795     {
796       public void actionPerformed(ActionEvent e)
797       {
798         taylorColour_actionPerformed();
799       }
800     });
801     hydrophobicityColour.setText("Hydrophobicity");
802     hydrophobicityColour
803             .addActionListener(new java.awt.event.ActionListener()
804             {
805               public void actionPerformed(ActionEvent e)
806               {
807                 hydrophobicityColour_actionPerformed();
808               }
809             });
810     helixColour.setText("Helix propensity");
811     helixColour.addActionListener(new java.awt.event.ActionListener()
812     {
813       public void actionPerformed(ActionEvent e)
814       {
815         helixColour_actionPerformed();
816       }
817     });
818     strandColour.setText("Strand propensity");
819     strandColour.addActionListener(new java.awt.event.ActionListener()
820     {
821       public void actionPerformed(ActionEvent e)
822       {
823         strandColour_actionPerformed();
824       }
825     });
826     turnColour.setText("Turn propensity");
827     turnColour.addActionListener(new java.awt.event.ActionListener()
828     {
829       public void actionPerformed(ActionEvent e)
830       {
831         turnColour_actionPerformed();
832       }
833     });
834     buriedColour.setText("Buried Index");
835     buriedColour.addActionListener(new java.awt.event.ActionListener()
836     {
837       public void actionPerformed(ActionEvent e)
838       {
839         buriedColour_actionPerformed();
840       }
841     });
842     abovePIDColour.setText("Above % Identity");
843     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
844     {
845       public void actionPerformed(ActionEvent e)
846       {
847         abovePIDColour_actionPerformed();
848       }
849     });
850     userDefinedColour.setText("User Defined...");
851     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
852     {
853       public void actionPerformed(ActionEvent e)
854       {
855         userDefinedColour_actionPerformed(e);
856       }
857     });
858     PIDColour.setText("Percentage Identity");
859     PIDColour.addActionListener(new java.awt.event.ActionListener()
860     {
861       public void actionPerformed(ActionEvent e)
862       {
863         PIDColour_actionPerformed();
864       }
865     });
866     BLOSUM62Colour.setText("BLOSUM62");
867     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
868     {
869       public void actionPerformed(ActionEvent e)
870       {
871         BLOSUM62Colour_actionPerformed();
872       }
873     });
874     conservationMenuItem.setText("Conservation");
875     conservationMenuItem
876             .addActionListener(new java.awt.event.ActionListener()
877             {
878               public void actionPerformed(ActionEvent e)
879               {
880                 conservationMenuItem_actionPerformed();
881               }
882             });
883   }
884
885   /**
886    * DOCUMENT ME!
887    */
888   void refresh()
889   {
890     ap.paintAlignment(true);
891
892     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
893   }
894
895   /**
896    * DOCUMENT ME!
897    * 
898    * @param e
899    *                DOCUMENT ME!
900    */
901   protected void clustalColour_actionPerformed()
902   {
903     SequenceGroup sg = getGroup();
904     sg.cs = new ClustalxColourScheme(sg
905             .getSequences(ap.av.hiddenRepSequences), ap.av.alignment
906             .getWidth());
907     refresh();
908   }
909
910   /**
911    * DOCUMENT ME!
912    * 
913    * @param e
914    *                DOCUMENT ME!
915    */
916   protected void zappoColour_actionPerformed()
917   {
918     getGroup().cs = new ZappoColourScheme();
919     refresh();
920   }
921
922   /**
923    * DOCUMENT ME!
924    * 
925    * @param e
926    *                DOCUMENT ME!
927    */
928   protected void taylorColour_actionPerformed()
929   {
930     getGroup().cs = new TaylorColourScheme();
931     refresh();
932   }
933
934   /**
935    * DOCUMENT ME!
936    * 
937    * @param e
938    *                DOCUMENT ME!
939    */
940   protected void hydrophobicityColour_actionPerformed()
941   {
942     getGroup().cs = new HydrophobicColourScheme();
943     refresh();
944   }
945
946   /**
947    * DOCUMENT ME!
948    * 
949    * @param e
950    *                DOCUMENT ME!
951    */
952   protected void helixColour_actionPerformed()
953   {
954     getGroup().cs = new HelixColourScheme();
955     refresh();
956   }
957
958   /**
959    * DOCUMENT ME!
960    * 
961    * @param e
962    *                DOCUMENT ME!
963    */
964   protected void strandColour_actionPerformed()
965   {
966     getGroup().cs = new StrandColourScheme();
967     refresh();
968   }
969
970   /**
971    * DOCUMENT ME!
972    * 
973    * @param e
974    *                DOCUMENT ME!
975    */
976   protected void turnColour_actionPerformed()
977   {
978     getGroup().cs = new TurnColourScheme();
979     refresh();
980   }
981
982   /**
983    * DOCUMENT ME!
984    * 
985    * @param e
986    *                DOCUMENT ME!
987    */
988   protected void buriedColour_actionPerformed()
989   {
990     getGroup().cs = new BuriedColourScheme();
991     refresh();
992   }
993
994   /**
995    * DOCUMENT ME!
996    * 
997    * @param e
998    *                DOCUMENT ME!
999    */
1000   public void nucleotideMenuItem_actionPerformed()
1001   {
1002     getGroup().cs = new NucleotideColourScheme();
1003     refresh();
1004   }
1005
1006   /**
1007    * DOCUMENT ME!
1008    * 
1009    * @param e
1010    *                DOCUMENT ME!
1011    */
1012   protected void abovePIDColour_actionPerformed()
1013   {
1014     SequenceGroup sg = getGroup();
1015     if (sg.cs == null)
1016     {
1017       return;
1018     }
1019
1020     if (abovePIDColour.isSelected())
1021     {
1022       sg.cs.setConsensus(AAFrequency.calculate(sg
1023               .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1024               .getEndRes() + 1));
1025
1026       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1027               .getName());
1028
1029       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1030
1031       SliderPanel.showPIDSlider();
1032     }
1033     else
1034     // remove PIDColouring
1035     {
1036       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1037     }
1038
1039     refresh();
1040   }
1041
1042   /**
1043    * DOCUMENT ME!
1044    * 
1045    * @param e
1046    *                DOCUMENT ME!
1047    */
1048   protected void userDefinedColour_actionPerformed(ActionEvent e)
1049   {
1050     SequenceGroup sg = getGroup();
1051
1052     if (e.getActionCommand().equals("User Defined..."))
1053     {
1054       new UserDefinedColours(ap, sg);
1055     }
1056     else
1057     {
1058       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1059               .getUserColourSchemes().get(e.getActionCommand());
1060
1061       sg.cs = udc;
1062     }
1063     refresh();
1064   }
1065
1066   /**
1067    * DOCUMENT ME!
1068    * 
1069    * @param e
1070    *                DOCUMENT ME!
1071    */
1072   protected void PIDColour_actionPerformed()
1073   {
1074     SequenceGroup sg = getGroup();
1075     sg.cs = new PIDColourScheme();
1076     sg.cs.setConsensus(AAFrequency.calculate(sg
1077             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1078             .getEndRes() + 1));
1079     refresh();
1080   }
1081
1082   /**
1083    * DOCUMENT ME!
1084    * 
1085    * @param e
1086    *                DOCUMENT ME!
1087    */
1088   protected void BLOSUM62Colour_actionPerformed()
1089   {
1090     SequenceGroup sg = getGroup();
1091
1092     sg.cs = new Blosum62ColourScheme();
1093
1094     sg.cs.setConsensus(AAFrequency.calculate(sg
1095             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1096             .getEndRes() + 1));
1097
1098     refresh();
1099   }
1100
1101   /**
1102    * DOCUMENT ME!
1103    * 
1104    * @param e
1105    *                DOCUMENT ME!
1106    */
1107   protected void noColourmenuItem_actionPerformed()
1108   {
1109     getGroup().cs = null;
1110     refresh();
1111   }
1112
1113   /**
1114    * DOCUMENT ME!
1115    * 
1116    * @param e
1117    *                DOCUMENT ME!
1118    */
1119   protected void conservationMenuItem_actionPerformed()
1120   {
1121     SequenceGroup sg = getGroup();
1122     if (sg.cs == null)
1123     {
1124       return;
1125     }
1126
1127     if (conservationMenuItem.isSelected())
1128     {
1129       Conservation c = new Conservation("Group",
1130               ResidueProperties.propHash, 3, sg
1131                       .getSequences(ap.av.hiddenRepSequences), sg
1132                       .getStartRes(), sg.getEndRes() + 1);
1133
1134       c.calculate();
1135       c.verdict(false, ap.av.ConsPercGaps);
1136
1137       sg.cs.setConservation(c);
1138
1139       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1140       SliderPanel.showConservationSlider();
1141     }
1142     else
1143     // remove ConservationColouring
1144     {
1145       sg.cs.setConservation(null);
1146     }
1147
1148     refresh();
1149   }
1150
1151   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1152   {
1153     SequenceGroup sg = getGroup();
1154     if (sg == null)
1155     {
1156       return;
1157     }
1158
1159     AnnotationColourGradient acg = new AnnotationColourGradient(sequence
1160             .getAnnotation()[0], null,
1161             AnnotationColourGradient.NO_THRESHOLD);
1162
1163     acg.predefinedColours = true;
1164     sg.cs = acg;
1165
1166     refresh();
1167   }
1168
1169   /**
1170    * DOCUMENT ME!
1171    * 
1172    * @param e
1173    *                DOCUMENT ME!
1174    */
1175   protected void groupName_actionPerformed()
1176   {
1177
1178     SequenceGroup sg = getGroup();
1179     EditNameDialog dialog = new EditNameDialog(sg.getName(), sg
1180             .getDescription(), "       Group Name ", "Group Description ",
1181             "Edit Group Name/Description");
1182
1183     if (!dialog.accept)
1184     {
1185       return;
1186     }
1187
1188     sg.setName(dialog.getName());
1189     sg.setDescription(dialog.getDescription());
1190   }
1191
1192   /**
1193    * DOCUMENT ME!
1194    * 
1195    * @return DOCUMENT ME!
1196    */
1197   SequenceGroup getGroup()
1198   {
1199     SequenceGroup sg = ap.av.getSelectionGroup();
1200     // this method won't add a new group if it already exists
1201     if (sg != null)
1202     {
1203       ap.av.alignment.addGroup(sg);
1204     }
1205
1206     return sg;
1207   }
1208
1209   /**
1210    * DOCUMENT ME!
1211    * 
1212    * @param e
1213    *                DOCUMENT ME!
1214    */
1215   void sequenceName_actionPerformed()
1216   {
1217     EditNameDialog dialog = new EditNameDialog(sequence.getName(), sequence
1218             .getDescription(), "       Sequence Name ",
1219             "Sequence Description ", "Edit Sequence Name/Description");
1220
1221     if (!dialog.accept)
1222     {
1223       return;
1224     }
1225
1226     if (dialog.getName() != null)
1227     {
1228       if (dialog.getName().indexOf(" ") > -1)
1229       {
1230         JOptionPane.showMessageDialog(ap,
1231                 "Spaces have been converted to \"_\"",
1232                 "No spaces allowed in Sequence Name",
1233                 JOptionPane.WARNING_MESSAGE);
1234       }
1235
1236       sequence.setName(dialog.getName().replace(' ', '_'));
1237       ap.paintAlignment(false);
1238     }
1239
1240     sequence.setDescription(dialog.getDescription());
1241
1242     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1243             .getSequences());
1244
1245   }
1246
1247   /**
1248    * DOCUMENT ME!
1249    * 
1250    * @param e
1251    *                DOCUMENT ME!
1252    */
1253   void unGroupMenuItem_actionPerformed()
1254   {
1255     SequenceGroup sg = ap.av.getSelectionGroup();
1256     ap.av.alignment.deleteGroup(sg);
1257     ap.av.setSelectionGroup(null);
1258     refresh();
1259   }
1260
1261   /**
1262    * DOCUMENT ME!
1263    * 
1264    * @param e
1265    *                DOCUMENT ME!
1266    */
1267   protected void outline_actionPerformed()
1268   {
1269     SequenceGroup sg = getGroup();
1270     Color col = JColorChooser.showDialog(this, "Select Outline Colour",
1271             Color.BLUE);
1272
1273     if (col != null)
1274     {
1275       sg.setOutlineColour(col);
1276     }
1277
1278     refresh();
1279   }
1280
1281   /**
1282    * DOCUMENT ME!
1283    * 
1284    * @param e
1285    *                DOCUMENT ME!
1286    */
1287   public void showBoxes_actionPerformed()
1288   {
1289     getGroup().setDisplayBoxes(showBoxes.isSelected());
1290     refresh();
1291   }
1292
1293   /**
1294    * DOCUMENT ME!
1295    * 
1296    * @param e
1297    *                DOCUMENT ME!
1298    */
1299   public void showText_actionPerformed()
1300   {
1301     getGroup().setDisplayText(showText.isSelected());
1302     refresh();
1303   }
1304
1305   /**
1306    * DOCUMENT ME!
1307    * 
1308    * @param e
1309    *                DOCUMENT ME!
1310    */
1311   public void showColourText_actionPerformed()
1312   {
1313     getGroup().setColourText(showColourText.isSelected());
1314     refresh();
1315   }
1316
1317   public void showLink(String url)
1318   {
1319     try
1320     {
1321       jalview.util.BrowserLauncher.openURL(url);
1322     } catch (Exception ex)
1323     {
1324       JOptionPane
1325               .showInternalMessageDialog(
1326                       Desktop.desktop,
1327                       "Unixers: Couldn't find default web browser."
1328                               + "\nAdd the full path to your browser in Preferences.",
1329                       "Web browser not found", JOptionPane.WARNING_MESSAGE);
1330
1331       ex.printStackTrace();
1332     }
1333   }
1334
1335   void hideSequences(boolean representGroup)
1336   {
1337     SequenceGroup sg = ap.av.getSelectionGroup();
1338     if (sg == null || sg.getSize() < 1)
1339     {
1340       ap.av.hideSequence(new SequenceI[]
1341       { sequence });
1342       return;
1343     }
1344
1345     ap.av.setSelectionGroup(null);
1346
1347     if (representGroup)
1348     {
1349       ap.av.hideRepSequences(sequence, sg);
1350
1351       return;
1352     }
1353
1354     int gsize = sg.getSize();
1355     SequenceI[] hseqs;
1356
1357     hseqs = new SequenceI[gsize];
1358
1359     int index = 0;
1360     for (int i = 0; i < gsize; i++)
1361     {
1362       hseqs[index++] = sg.getSequenceAt(i);
1363     }
1364
1365     ap.av.hideSequence(hseqs);
1366   }
1367
1368   public void copy_actionPerformed()
1369   {
1370     ap.alignFrame.copy_actionPerformed(null);
1371   }
1372
1373   public void cut_actionPerformed()
1374   {
1375     ap.alignFrame.cut_actionPerformed(null);
1376   }
1377
1378   void changeCase(ActionEvent e)
1379   {
1380     Object source = e.getSource();
1381     SequenceGroup sg = ap.av.getSelectionGroup();
1382
1383     if (sg != null)
1384     {
1385       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1386               sg.getEndRes() + 1);
1387
1388       String description;
1389       int caseChange;
1390
1391       if (source == toggle)
1392       {
1393         description = "Toggle Case";
1394         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1395       }
1396       else if (source == upperCase)
1397       {
1398         description = "To Upper Case";
1399         caseChange = ChangeCaseCommand.TO_UPPER;
1400       }
1401       else
1402       {
1403         description = "To Lower Case";
1404         caseChange = ChangeCaseCommand.TO_LOWER;
1405       }
1406
1407       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description, sg
1408               .getSequencesAsArray(ap.av.hiddenRepSequences), startEnd,
1409               caseChange);
1410
1411       ap.alignFrame.addHistoryItem(caseCommand);
1412
1413       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1414               .getSequences());
1415
1416     }
1417   }
1418
1419   public void outputText_actionPerformed(ActionEvent e)
1420   {
1421     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1422     cap.setForInput(null);
1423     Desktop.addInternalFrame(cap, "Alignment output - "
1424             + e.getActionCommand(), 600, 500);
1425
1426     String[] omitHidden = null;
1427
1428     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1429                                             // or we simply trust the user wants
1430                                             // wysiwig behaviour
1431     SequenceGroup sg = ap.av.getSelectionGroup();
1432     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1433     omitHidden = ap.av.getViewAsString(true);
1434     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1435     AlignmentAnnotation[] nala = ap.av.alignment.getAlignmentAnnotation();
1436     for (int i = 0; i < nala.length; i++)
1437     {
1438       AlignmentAnnotation na = nala[i];
1439       oal.addAnnotation(na);
1440     }
1441     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1442             oal, omitHidden, csel, sg));
1443     oal = null;
1444   }
1445
1446   public void pdbFromFile_actionPerformed()
1447   {
1448     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1449             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1450     chooser.setFileView(new jalview.io.JalviewFileView());
1451     chooser.setDialogTitle("Select a PDB file");
1452     chooser.setToolTipText("Load a PDB file");
1453
1454     int value = chooser.showOpenDialog(null);
1455
1456     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1457     {
1458       PDBEntry entry = new PDBEntry();
1459       String choice = chooser.getSelectedFile().getPath();
1460       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1461       try
1462       {
1463         MCview.PDBfile pdbfile = new MCview.PDBfile(choice,
1464                 jalview.io.AppletFormatAdapter.FILE);
1465
1466         if (pdbfile.id == null)
1467         {
1468           String reply = JOptionPane
1469                   .showInternalInputDialog(
1470                           Desktop.desktop,
1471                           "Couldn't find a PDB id in the file supplied."
1472                                   + "Please enter an Id to identify this structure.",
1473                           "No PDB Id in File", JOptionPane.QUESTION_MESSAGE);
1474           if (reply == null)
1475           {
1476             return;
1477           }
1478
1479           entry.setId(reply);
1480         }
1481         else
1482         {
1483           entry.setId(pdbfile.id);
1484         }
1485       } catch (java.io.IOException ex)
1486       {
1487         ex.printStackTrace();
1488       }
1489
1490       entry.setFile(choice);
1491       sequence.getDatasetSequence().addPDBId(entry);
1492     }
1493
1494   }
1495
1496   public void enterPDB_actionPerformed()
1497   {
1498     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
1499             "Enter PDB Id", "Enter PDB Id", JOptionPane.QUESTION_MESSAGE);
1500
1501     if (id != null && id.length() > 0)
1502     {
1503       PDBEntry entry = new PDBEntry();
1504       entry.setId(id.toUpperCase());
1505       sequence.getDatasetSequence().addPDBId(entry);
1506     }
1507   }
1508
1509   public void discoverPDB_actionPerformed()
1510   {
1511
1512     final SequenceI[] sequences = ((ap.av.selectionGroup == null) ? new Sequence[]
1513     { sequence }
1514             : ap.av.selectionGroup.getSequencesInOrder(ap.av.alignment));
1515     Thread discpdb = new Thread(new Runnable()
1516     {
1517       public void run()
1518       {
1519
1520         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
1521                 .fetchDBRefs(false);
1522       }
1523
1524     });
1525     discpdb.start();
1526   }
1527
1528   public void sequenceFeature_actionPerformed()
1529   {
1530     SequenceGroup sg = ap.av.getSelectionGroup();
1531     if (sg == null)
1532     {
1533       return;
1534     }
1535
1536     int gSize = sg.getSize();
1537     SequenceI[] seqs = new SequenceI[gSize];
1538     SequenceFeature[] features = new SequenceFeature[gSize];
1539
1540     for (int i = 0; i < gSize; i++)
1541     {
1542       seqs[i] = sg.getSequenceAt(i).getDatasetSequence();
1543       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
1544       int end = sg.findEndRes(sg.getSequenceAt(i));
1545       features[i] = new SequenceFeature(null, null, null, start, end,
1546               "Jalview");
1547     }
1548
1549     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
1550             features, true, ap))
1551     {
1552       ap.alignFrame.showSeqFeatures.setSelected(true);
1553       ap.av.setShowSequenceFeatures(true);
1554       ap.highlightSearchResults(null);
1555     }
1556   }
1557
1558   public void textColour_actionPerformed()
1559   {
1560     SequenceGroup sg = getGroup();
1561     if (sg != null)
1562     {
1563       new TextColourChooser().chooseColour(ap, sg);
1564     }
1565   }
1566
1567   public void colourByStructure(String pdbid)
1568   {
1569     Annotation[] anots = jalview.structure.StructureSelectionManager
1570             .getStructureSelectionManager().colourSequenceFromStructure(
1571                     sequence, pdbid);
1572
1573     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
1574             "Coloured by " + pdbid, anots);
1575
1576     ap.av.alignment.addAnnotation(an);
1577     an.createSequenceMapping(sequence, 0, true);
1578     // an.adjustForAlignment();
1579     ap.av.alignment.setAnnotationIndex(an, 0);
1580
1581     ap.adjustAnnotationHeight();
1582
1583     sequence.addAlignmentAnnotation(an);
1584
1585   }
1586
1587   public void editSequence_actionPerformed(ActionEvent actionEvent)
1588   {
1589     SequenceGroup sg = ap.av.getSelectionGroup();
1590
1591     if (sg != null)
1592     {
1593       if (sequence == null)
1594         sequence = (Sequence) sg.getSequenceAt(0);
1595
1596       EditNameDialog dialog = new EditNameDialog(sequence
1597               .getSequenceAsString(sg.getStartRes(), sg.getEndRes() + 1),
1598               null, "Edit Sequence ", null, "Edit Sequence");
1599
1600       if (dialog.accept)
1601       {
1602         EditCommand editCommand = new EditCommand("Edit Sequences",
1603                 EditCommand.REPLACE, dialog.getName().replace(' ',
1604                         ap.av.getGapCharacter()), sg
1605                         .getSequencesAsArray(ap.av.hiddenRepSequences), sg
1606                         .getStartRes(), sg.getEndRes() + 1, ap.av.alignment);
1607
1608         ap.alignFrame.addHistoryItem(editCommand);
1609
1610         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1611                 .getSequences());
1612       }
1613     }
1614   }
1615
1616 }