fee7e3faac9bd7f23acf7443be6437cce9b2c38d
[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           String descr = seq.getDescription();
437           if (descr!=null && descr.length()<1)
438           {
439             descr = null;
440           }
441
442           if (dbr != null)
443           {
444             for (int r = 0; r < dbr.length; r++)
445             {
446               if (id != null && dbr[r].getAccessionId().equals(id))
447               {
448                 // suppress duplicate link creation for the bare sequence ID
449                 // string with this link
450                 id = null;
451               }
452               // create Bare ID link for this RUL
453               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
454                       true);
455               if (urls != null)
456               {
457                 for (int u = 0; u < urls.length; u += 2)
458                 {
459                   addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
460                 }
461               }
462             }
463           }
464           if (id != null)
465           {
466             // create Bare ID link for this RUL
467             String[] urls = urlLink.makeUrls(id, true);
468             if (urls != null)
469             {
470               for (int u = 0; u < urls.length; u += 2)
471               {
472                 addshowLink(linkMenu, label, urls[u + 1]);
473               }
474             }
475           }
476           // Create urls from description but only for URL links which are regex links
477           if (descr != null && urlLink.getRegexReplace()!=null)
478           {
479             // create link for this URL from description where regex matches
480             String[] urls = urlLink.makeUrls(descr, true);
481             if (urls != null)
482             {
483               for (int u = 0; u < urls.length; u += 2)
484               {
485                 addshowLink(linkMenu, label, urls[u + 1]);
486               }
487             }
488           }
489         }
490         else
491         {
492           // Add a non-dynamic link
493           addshowLink(linkMenu, label, urlLink.getUrl_prefix());
494         }
495       }
496       if (sequence != null)
497       {
498         sequenceMenu.add(linkMenu);
499       }
500       else
501       {
502         add(linkMenu);
503       }
504     }
505   }
506
507   /**
508    * add a show URL menu item to the given linkMenu
509    * 
510    * @param linkMenu
511    * @param label -
512    *                menu label string
513    * @param url -
514    *                url to open
515    */
516   private void addshowLink(JMenu linkMenu, String label, final String url)
517   {
518     JMenuItem item = new JMenuItem(label);
519     item.setToolTipText("open URL: " + url);
520     item.addActionListener(new java.awt.event.ActionListener()
521     {
522       public void actionPerformed(ActionEvent e)
523       {
524         new Thread(new Runnable()
525         {
526
527           public void run()
528           {
529             showLink(url);
530           }
531
532         }).start();
533       }
534     });
535
536     linkMenu.add(item);
537   }
538
539   /**
540    * DOCUMENT ME!
541    * 
542    * @throws Exception
543    *                 DOCUMENT ME!
544    */
545   private void jbInit() throws Exception
546   {
547     groupMenu.setText("Group");
548     groupMenu.setText("Selection");
549     groupName.setText("Name");
550     groupName.addActionListener(new java.awt.event.ActionListener()
551     {
552       public void actionPerformed(ActionEvent e)
553       {
554         groupName_actionPerformed();
555       }
556     });
557     sequenceMenu.setText("Sequence");
558     sequenceName.setText("Edit Name/Description");
559     sequenceName.addActionListener(new java.awt.event.ActionListener()
560     {
561       public void actionPerformed(ActionEvent e)
562       {
563         sequenceName_actionPerformed();
564       }
565     });
566     PIDColour.setFocusPainted(false);
567     unGroupMenuItem.setText("Remove Group");
568     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
569     {
570       public void actionPerformed(ActionEvent e)
571       {
572         unGroupMenuItem_actionPerformed();
573       }
574     });
575
576     outline.setText("Border colour");
577     outline.addActionListener(new java.awt.event.ActionListener()
578     {
579       public void actionPerformed(ActionEvent e)
580       {
581         outline_actionPerformed();
582       }
583     });
584     nucleotideMenuItem.setText("Nucleotide");
585     nucleotideMenuItem.addActionListener(new ActionListener()
586     {
587       public void actionPerformed(ActionEvent e)
588       {
589         nucleotideMenuItem_actionPerformed();
590       }
591     });
592     colourMenu.setText("Group Colour");
593     showBoxes.setText("Boxes");
594     showBoxes.setState(true);
595     showBoxes.addActionListener(new ActionListener()
596     {
597       public void actionPerformed(ActionEvent e)
598       {
599         showBoxes_actionPerformed();
600       }
601     });
602     showText.setText("Text");
603     showText.setState(true);
604     showText.addActionListener(new ActionListener()
605     {
606       public void actionPerformed(ActionEvent e)
607       {
608         showText_actionPerformed();
609       }
610     });
611     showColourText.setText("Colour Text");
612     showColourText.addActionListener(new ActionListener()
613     {
614       public void actionPerformed(ActionEvent e)
615       {
616         showColourText_actionPerformed();
617       }
618     });
619     editMenu.setText("Edit");
620     cut.setText("Cut");
621     cut.addActionListener(new ActionListener()
622     {
623       public void actionPerformed(ActionEvent e)
624       {
625         cut_actionPerformed();
626       }
627     });
628     upperCase.setText("To Upper Case");
629     upperCase.addActionListener(new ActionListener()
630     {
631       public void actionPerformed(ActionEvent e)
632       {
633         changeCase(e);
634       }
635     });
636     copy.setText("Copy");
637     copy.addActionListener(new ActionListener()
638     {
639       public void actionPerformed(ActionEvent e)
640       {
641         copy_actionPerformed();
642       }
643     });
644     lowerCase.setText("To Lower Case");
645     lowerCase.addActionListener(new ActionListener()
646     {
647       public void actionPerformed(ActionEvent e)
648       {
649         changeCase(e);
650       }
651     });
652     toggle.setText("Toggle Case");
653     toggle.addActionListener(new ActionListener()
654     {
655       public void actionPerformed(ActionEvent e)
656       {
657         changeCase(e);
658       }
659     });
660     pdbMenu.setText("Associate Structure with Sequence");
661     pdbFromFile.setText("From File");
662     pdbFromFile.addActionListener(new ActionListener()
663     {
664       public void actionPerformed(ActionEvent e)
665       {
666         pdbFromFile_actionPerformed();
667       }
668     });
669     enterPDB.setText("Enter PDB Id");
670     enterPDB.addActionListener(new ActionListener()
671     {
672       public void actionPerformed(ActionEvent e)
673       {
674         enterPDB_actionPerformed();
675       }
676     });
677     discoverPDB.setText("Discover PDB ids");
678     discoverPDB.addActionListener(new ActionListener()
679     {
680       public void actionPerformed(ActionEvent e)
681       {
682         discoverPDB_actionPerformed();
683       }
684     });
685     outputMenu.setText("Output to Textbox...");
686     sequenceFeature.setText("Create Sequence Feature");
687     sequenceFeature.addActionListener(new ActionListener()
688     {
689       public void actionPerformed(ActionEvent e)
690       {
691         sequenceFeature_actionPerformed();
692       }
693     });
694     textColour.setText("Text Colour");
695     textColour.addActionListener(new ActionListener()
696     {
697       public void actionPerformed(ActionEvent e)
698       {
699         textColour_actionPerformed();
700       }
701     });
702     jMenu1.setText("Group");
703     structureMenu.setText("Structure");
704     viewStructureMenu.setText("View Structure");
705     // colStructureMenu.setText("Colour By Structure");
706     editSequence.setText("Edit Sequence...");
707     editSequence.addActionListener(new ActionListener()
708     {
709       public void actionPerformed(ActionEvent actionEvent)
710       {
711         editSequence_actionPerformed(actionEvent);
712       }
713     });
714     /*
715      * annotationMenuItem.setText("By Annotation");
716      * annotationMenuItem.addActionListener(new ActionListener() { public void
717      * actionPerformed(ActionEvent actionEvent) {
718      * annotationMenuItem_actionPerformed(actionEvent); } });
719      */
720
721     add(groupMenu);
722
723     add(sequenceMenu);
724     this.add(structureMenu);
725     groupMenu.add(editMenu);
726     groupMenu.add(outputMenu);
727     groupMenu.add(sequenceFeature);
728     groupMenu.add(jMenu1);
729     sequenceMenu.add(sequenceName);
730     colourMenu.add(textColour);
731     colourMenu.add(noColourmenuItem);
732     colourMenu.add(clustalColour);
733     colourMenu.add(BLOSUM62Colour);
734     colourMenu.add(PIDColour);
735     colourMenu.add(zappoColour);
736     colourMenu.add(taylorColour);
737     colourMenu.add(hydrophobicityColour);
738     colourMenu.add(helixColour);
739     colourMenu.add(strandColour);
740     colourMenu.add(turnColour);
741     colourMenu.add(buriedColour);
742     colourMenu.add(nucleotideMenuItem);
743     colourMenu.add(userDefinedColour);
744
745     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
746     {
747       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
748               .getUserColourSchemes().keys();
749
750       while (userColours.hasMoreElements())
751       {
752         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
753         item.addActionListener(new ActionListener()
754         {
755           public void actionPerformed(ActionEvent evt)
756           {
757             userDefinedColour_actionPerformed(evt);
758           }
759         });
760         colourMenu.add(item);
761       }
762     }
763
764     colourMenu.addSeparator();
765     colourMenu.add(abovePIDColour);
766     colourMenu.add(conservationMenuItem);
767     // colourMenu.add(annotationMenuItem);
768     editMenu.add(copy);
769     editMenu.add(cut);
770     editMenu.add(editSequence);
771     editMenu.add(upperCase);
772     editMenu.add(lowerCase);
773     editMenu.add(toggle);
774     pdbMenu.add(pdbFromFile);
775     pdbMenu.add(enterPDB);
776     pdbMenu.add(discoverPDB);
777     jMenu1.add(groupName);
778     jMenu1.add(unGroupMenuItem);
779     jMenu1.add(colourMenu);
780     jMenu1.add(showBoxes);
781     jMenu1.add(showText);
782     jMenu1.add(showColourText);
783     jMenu1.add(outline);
784     structureMenu.add(pdbMenu);
785     structureMenu.add(viewStructureMenu);
786     // structureMenu.add(colStructureMenu);
787     noColourmenuItem.setText("None");
788     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
789     {
790       public void actionPerformed(ActionEvent e)
791       {
792         noColourmenuItem_actionPerformed();
793       }
794     });
795
796     clustalColour.setText("Clustalx colours");
797     clustalColour.addActionListener(new java.awt.event.ActionListener()
798     {
799       public void actionPerformed(ActionEvent e)
800       {
801         clustalColour_actionPerformed();
802       }
803     });
804     zappoColour.setText("Zappo");
805     zappoColour.addActionListener(new java.awt.event.ActionListener()
806     {
807       public void actionPerformed(ActionEvent e)
808       {
809         zappoColour_actionPerformed();
810       }
811     });
812     taylorColour.setText("Taylor");
813     taylorColour.addActionListener(new java.awt.event.ActionListener()
814     {
815       public void actionPerformed(ActionEvent e)
816       {
817         taylorColour_actionPerformed();
818       }
819     });
820     hydrophobicityColour.setText("Hydrophobicity");
821     hydrophobicityColour
822             .addActionListener(new java.awt.event.ActionListener()
823             {
824               public void actionPerformed(ActionEvent e)
825               {
826                 hydrophobicityColour_actionPerformed();
827               }
828             });
829     helixColour.setText("Helix propensity");
830     helixColour.addActionListener(new java.awt.event.ActionListener()
831     {
832       public void actionPerformed(ActionEvent e)
833       {
834         helixColour_actionPerformed();
835       }
836     });
837     strandColour.setText("Strand propensity");
838     strandColour.addActionListener(new java.awt.event.ActionListener()
839     {
840       public void actionPerformed(ActionEvent e)
841       {
842         strandColour_actionPerformed();
843       }
844     });
845     turnColour.setText("Turn propensity");
846     turnColour.addActionListener(new java.awt.event.ActionListener()
847     {
848       public void actionPerformed(ActionEvent e)
849       {
850         turnColour_actionPerformed();
851       }
852     });
853     buriedColour.setText("Buried Index");
854     buriedColour.addActionListener(new java.awt.event.ActionListener()
855     {
856       public void actionPerformed(ActionEvent e)
857       {
858         buriedColour_actionPerformed();
859       }
860     });
861     abovePIDColour.setText("Above % Identity");
862     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
863     {
864       public void actionPerformed(ActionEvent e)
865       {
866         abovePIDColour_actionPerformed();
867       }
868     });
869     userDefinedColour.setText("User Defined...");
870     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
871     {
872       public void actionPerformed(ActionEvent e)
873       {
874         userDefinedColour_actionPerformed(e);
875       }
876     });
877     PIDColour.setText("Percentage Identity");
878     PIDColour.addActionListener(new java.awt.event.ActionListener()
879     {
880       public void actionPerformed(ActionEvent e)
881       {
882         PIDColour_actionPerformed();
883       }
884     });
885     BLOSUM62Colour.setText("BLOSUM62");
886     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
887     {
888       public void actionPerformed(ActionEvent e)
889       {
890         BLOSUM62Colour_actionPerformed();
891       }
892     });
893     conservationMenuItem.setText("Conservation");
894     conservationMenuItem
895             .addActionListener(new java.awt.event.ActionListener()
896             {
897               public void actionPerformed(ActionEvent e)
898               {
899                 conservationMenuItem_actionPerformed();
900               }
901             });
902   }
903
904   /**
905    * DOCUMENT ME!
906    */
907   void refresh()
908   {
909     ap.paintAlignment(true);
910
911     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
912   }
913
914   /**
915    * DOCUMENT ME!
916    * 
917    * @param e
918    *                DOCUMENT ME!
919    */
920   protected void clustalColour_actionPerformed()
921   {
922     SequenceGroup sg = getGroup();
923     sg.cs = new ClustalxColourScheme(sg
924             .getSequences(ap.av.hiddenRepSequences), ap.av.alignment
925             .getWidth());
926     refresh();
927   }
928
929   /**
930    * DOCUMENT ME!
931    * 
932    * @param e
933    *                DOCUMENT ME!
934    */
935   protected void zappoColour_actionPerformed()
936   {
937     getGroup().cs = new ZappoColourScheme();
938     refresh();
939   }
940
941   /**
942    * DOCUMENT ME!
943    * 
944    * @param e
945    *                DOCUMENT ME!
946    */
947   protected void taylorColour_actionPerformed()
948   {
949     getGroup().cs = new TaylorColourScheme();
950     refresh();
951   }
952
953   /**
954    * DOCUMENT ME!
955    * 
956    * @param e
957    *                DOCUMENT ME!
958    */
959   protected void hydrophobicityColour_actionPerformed()
960   {
961     getGroup().cs = new HydrophobicColourScheme();
962     refresh();
963   }
964
965   /**
966    * DOCUMENT ME!
967    * 
968    * @param e
969    *                DOCUMENT ME!
970    */
971   protected void helixColour_actionPerformed()
972   {
973     getGroup().cs = new HelixColourScheme();
974     refresh();
975   }
976
977   /**
978    * DOCUMENT ME!
979    * 
980    * @param e
981    *                DOCUMENT ME!
982    */
983   protected void strandColour_actionPerformed()
984   {
985     getGroup().cs = new StrandColourScheme();
986     refresh();
987   }
988
989   /**
990    * DOCUMENT ME!
991    * 
992    * @param e
993    *                DOCUMENT ME!
994    */
995   protected void turnColour_actionPerformed()
996   {
997     getGroup().cs = new TurnColourScheme();
998     refresh();
999   }
1000
1001   /**
1002    * DOCUMENT ME!
1003    * 
1004    * @param e
1005    *                DOCUMENT ME!
1006    */
1007   protected void buriedColour_actionPerformed()
1008   {
1009     getGroup().cs = new BuriedColourScheme();
1010     refresh();
1011   }
1012
1013   /**
1014    * DOCUMENT ME!
1015    * 
1016    * @param e
1017    *                DOCUMENT ME!
1018    */
1019   public void nucleotideMenuItem_actionPerformed()
1020   {
1021     getGroup().cs = new NucleotideColourScheme();
1022     refresh();
1023   }
1024
1025   /**
1026    * DOCUMENT ME!
1027    * 
1028    * @param e
1029    *                DOCUMENT ME!
1030    */
1031   protected void abovePIDColour_actionPerformed()
1032   {
1033     SequenceGroup sg = getGroup();
1034     if (sg.cs == null)
1035     {
1036       return;
1037     }
1038
1039     if (abovePIDColour.isSelected())
1040     {
1041       sg.cs.setConsensus(AAFrequency.calculate(sg
1042               .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1043               .getEndRes() + 1));
1044
1045       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1046               .getName());
1047
1048       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1049
1050       SliderPanel.showPIDSlider();
1051     }
1052     else
1053     // remove PIDColouring
1054     {
1055       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1056     }
1057
1058     refresh();
1059   }
1060
1061   /**
1062    * DOCUMENT ME!
1063    * 
1064    * @param e
1065    *                DOCUMENT ME!
1066    */
1067   protected void userDefinedColour_actionPerformed(ActionEvent e)
1068   {
1069     SequenceGroup sg = getGroup();
1070
1071     if (e.getActionCommand().equals("User Defined..."))
1072     {
1073       new UserDefinedColours(ap, sg);
1074     }
1075     else
1076     {
1077       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1078               .getUserColourSchemes().get(e.getActionCommand());
1079
1080       sg.cs = udc;
1081     }
1082     refresh();
1083   }
1084
1085   /**
1086    * DOCUMENT ME!
1087    * 
1088    * @param e
1089    *                DOCUMENT ME!
1090    */
1091   protected void PIDColour_actionPerformed()
1092   {
1093     SequenceGroup sg = getGroup();
1094     sg.cs = new PIDColourScheme();
1095     sg.cs.setConsensus(AAFrequency.calculate(sg
1096             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1097             .getEndRes() + 1));
1098     refresh();
1099   }
1100
1101   /**
1102    * DOCUMENT ME!
1103    * 
1104    * @param e
1105    *                DOCUMENT ME!
1106    */
1107   protected void BLOSUM62Colour_actionPerformed()
1108   {
1109     SequenceGroup sg = getGroup();
1110
1111     sg.cs = new Blosum62ColourScheme();
1112
1113     sg.cs.setConsensus(AAFrequency.calculate(sg
1114             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1115             .getEndRes() + 1));
1116
1117     refresh();
1118   }
1119
1120   /**
1121    * DOCUMENT ME!
1122    * 
1123    * @param e
1124    *                DOCUMENT ME!
1125    */
1126   protected void noColourmenuItem_actionPerformed()
1127   {
1128     getGroup().cs = null;
1129     refresh();
1130   }
1131
1132   /**
1133    * DOCUMENT ME!
1134    * 
1135    * @param e
1136    *                DOCUMENT ME!
1137    */
1138   protected void conservationMenuItem_actionPerformed()
1139   {
1140     SequenceGroup sg = getGroup();
1141     if (sg.cs == null)
1142     {
1143       return;
1144     }
1145
1146     if (conservationMenuItem.isSelected())
1147     {
1148       Conservation c = new Conservation("Group",
1149               ResidueProperties.propHash, 3, sg
1150                       .getSequences(ap.av.hiddenRepSequences), sg
1151                       .getStartRes(), sg.getEndRes() + 1);
1152
1153       c.calculate();
1154       c.verdict(false, ap.av.ConsPercGaps);
1155
1156       sg.cs.setConservation(c);
1157
1158       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1159       SliderPanel.showConservationSlider();
1160     }
1161     else
1162     // remove ConservationColouring
1163     {
1164       sg.cs.setConservation(null);
1165     }
1166
1167     refresh();
1168   }
1169
1170   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1171   {
1172     SequenceGroup sg = getGroup();
1173     if (sg == null)
1174     {
1175       return;
1176     }
1177
1178     AnnotationColourGradient acg = new AnnotationColourGradient(sequence
1179             .getAnnotation()[0], null,
1180             AnnotationColourGradient.NO_THRESHOLD);
1181
1182     acg.predefinedColours = true;
1183     sg.cs = acg;
1184
1185     refresh();
1186   }
1187
1188   /**
1189    * DOCUMENT ME!
1190    * 
1191    * @param e
1192    *                DOCUMENT ME!
1193    */
1194   protected void groupName_actionPerformed()
1195   {
1196
1197     SequenceGroup sg = getGroup();
1198     EditNameDialog dialog = new EditNameDialog(sg.getName(), sg
1199             .getDescription(), "       Group Name ", "Group Description ",
1200             "Edit Group Name/Description");
1201
1202     if (!dialog.accept)
1203     {
1204       return;
1205     }
1206
1207     sg.setName(dialog.getName());
1208     sg.setDescription(dialog.getDescription());
1209   }
1210
1211   /**
1212    * DOCUMENT ME!
1213    * 
1214    * @return DOCUMENT ME!
1215    */
1216   SequenceGroup getGroup()
1217   {
1218     SequenceGroup sg = ap.av.getSelectionGroup();
1219     // this method won't add a new group if it already exists
1220     if (sg != null)
1221     {
1222       ap.av.alignment.addGroup(sg);
1223     }
1224
1225     return sg;
1226   }
1227
1228   /**
1229    * DOCUMENT ME!
1230    * 
1231    * @param e
1232    *                DOCUMENT ME!
1233    */
1234   void sequenceName_actionPerformed()
1235   {
1236     EditNameDialog dialog = new EditNameDialog(sequence.getName(), sequence
1237             .getDescription(), "       Sequence Name ",
1238             "Sequence Description ", "Edit Sequence Name/Description");
1239
1240     if (!dialog.accept)
1241     {
1242       return;
1243     }
1244
1245     if (dialog.getName() != null)
1246     {
1247       if (dialog.getName().indexOf(" ") > -1)
1248       {
1249         JOptionPane.showMessageDialog(ap,
1250                 "Spaces have been converted to \"_\"",
1251                 "No spaces allowed in Sequence Name",
1252                 JOptionPane.WARNING_MESSAGE);
1253       }
1254
1255       sequence.setName(dialog.getName().replace(' ', '_'));
1256       ap.paintAlignment(false);
1257     }
1258
1259     sequence.setDescription(dialog.getDescription());
1260
1261     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1262             .getSequences());
1263
1264   }
1265
1266   /**
1267    * DOCUMENT ME!
1268    * 
1269    * @param e
1270    *                DOCUMENT ME!
1271    */
1272   void unGroupMenuItem_actionPerformed()
1273   {
1274     SequenceGroup sg = ap.av.getSelectionGroup();
1275     ap.av.alignment.deleteGroup(sg);
1276     ap.av.setSelectionGroup(null);
1277     refresh();
1278   }
1279
1280   /**
1281    * DOCUMENT ME!
1282    * 
1283    * @param e
1284    *                DOCUMENT ME!
1285    */
1286   protected void outline_actionPerformed()
1287   {
1288     SequenceGroup sg = getGroup();
1289     Color col = JColorChooser.showDialog(this, "Select Outline Colour",
1290             Color.BLUE);
1291
1292     if (col != null)
1293     {
1294       sg.setOutlineColour(col);
1295     }
1296
1297     refresh();
1298   }
1299
1300   /**
1301    * DOCUMENT ME!
1302    * 
1303    * @param e
1304    *                DOCUMENT ME!
1305    */
1306   public void showBoxes_actionPerformed()
1307   {
1308     getGroup().setDisplayBoxes(showBoxes.isSelected());
1309     refresh();
1310   }
1311
1312   /**
1313    * DOCUMENT ME!
1314    * 
1315    * @param e
1316    *                DOCUMENT ME!
1317    */
1318   public void showText_actionPerformed()
1319   {
1320     getGroup().setDisplayText(showText.isSelected());
1321     refresh();
1322   }
1323
1324   /**
1325    * DOCUMENT ME!
1326    * 
1327    * @param e
1328    *                DOCUMENT ME!
1329    */
1330   public void showColourText_actionPerformed()
1331   {
1332     getGroup().setColourText(showColourText.isSelected());
1333     refresh();
1334   }
1335
1336   public void showLink(String url)
1337   {
1338     try
1339     {
1340       jalview.util.BrowserLauncher.openURL(url);
1341     } catch (Exception ex)
1342     {
1343       JOptionPane
1344               .showInternalMessageDialog(
1345                       Desktop.desktop,
1346                       "Unixers: Couldn't find default web browser."
1347                               + "\nAdd the full path to your browser in Preferences.",
1348                       "Web browser not found", JOptionPane.WARNING_MESSAGE);
1349
1350       ex.printStackTrace();
1351     }
1352   }
1353
1354   void hideSequences(boolean representGroup)
1355   {
1356     SequenceGroup sg = ap.av.getSelectionGroup();
1357     if (sg == null || sg.getSize() < 1)
1358     {
1359       ap.av.hideSequence(new SequenceI[]
1360       { sequence });
1361       return;
1362     }
1363
1364     ap.av.setSelectionGroup(null);
1365
1366     if (representGroup)
1367     {
1368       ap.av.hideRepSequences(sequence, sg);
1369
1370       return;
1371     }
1372
1373     int gsize = sg.getSize();
1374     SequenceI[] hseqs;
1375
1376     hseqs = new SequenceI[gsize];
1377
1378     int index = 0;
1379     for (int i = 0; i < gsize; i++)
1380     {
1381       hseqs[index++] = sg.getSequenceAt(i);
1382     }
1383
1384     ap.av.hideSequence(hseqs);
1385   }
1386
1387   public void copy_actionPerformed()
1388   {
1389     ap.alignFrame.copy_actionPerformed(null);
1390   }
1391
1392   public void cut_actionPerformed()
1393   {
1394     ap.alignFrame.cut_actionPerformed(null);
1395   }
1396
1397   void changeCase(ActionEvent e)
1398   {
1399     Object source = e.getSource();
1400     SequenceGroup sg = ap.av.getSelectionGroup();
1401
1402     if (sg != null)
1403     {
1404       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1405               sg.getEndRes() + 1);
1406
1407       String description;
1408       int caseChange;
1409
1410       if (source == toggle)
1411       {
1412         description = "Toggle Case";
1413         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1414       }
1415       else if (source == upperCase)
1416       {
1417         description = "To Upper Case";
1418         caseChange = ChangeCaseCommand.TO_UPPER;
1419       }
1420       else
1421       {
1422         description = "To Lower Case";
1423         caseChange = ChangeCaseCommand.TO_LOWER;
1424       }
1425
1426       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description, sg
1427               .getSequencesAsArray(ap.av.hiddenRepSequences), startEnd,
1428               caseChange);
1429
1430       ap.alignFrame.addHistoryItem(caseCommand);
1431
1432       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1433               .getSequences());
1434
1435     }
1436   }
1437
1438   public void outputText_actionPerformed(ActionEvent e)
1439   {
1440     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1441     cap.setForInput(null);
1442     Desktop.addInternalFrame(cap, "Alignment output - "
1443             + e.getActionCommand(), 600, 500);
1444
1445     String[] omitHidden = null;
1446
1447     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1448                                             // or we simply trust the user wants
1449                                             // wysiwig behaviour
1450     SequenceGroup sg = ap.av.getSelectionGroup();
1451     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1452     omitHidden = ap.av.getViewAsString(true);
1453     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1454     AlignmentAnnotation[] nala = ap.av.alignment.getAlignmentAnnotation();
1455     for (int i = 0; i < nala.length; i++)
1456     {
1457       AlignmentAnnotation na = nala[i];
1458       oal.addAnnotation(na);
1459     }
1460     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1461             oal, omitHidden, csel, sg));
1462     oal = null;
1463   }
1464
1465   public void pdbFromFile_actionPerformed()
1466   {
1467     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1468             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1469     chooser.setFileView(new jalview.io.JalviewFileView());
1470     chooser.setDialogTitle("Select a PDB file");
1471     chooser.setToolTipText("Load a PDB file");
1472
1473     int value = chooser.showOpenDialog(null);
1474
1475     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1476     {
1477       PDBEntry entry = new PDBEntry();
1478       String choice = chooser.getSelectedFile().getPath();
1479       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1480       try
1481       {
1482         MCview.PDBfile pdbfile = new MCview.PDBfile(choice,
1483                 jalview.io.AppletFormatAdapter.FILE);
1484
1485         if (pdbfile.id == null)
1486         {
1487           String reply = JOptionPane
1488                   .showInternalInputDialog(
1489                           Desktop.desktop,
1490                           "Couldn't find a PDB id in the file supplied."
1491                                   + "Please enter an Id to identify this structure.",
1492                           "No PDB Id in File", JOptionPane.QUESTION_MESSAGE);
1493           if (reply == null)
1494           {
1495             return;
1496           }
1497
1498           entry.setId(reply);
1499         }
1500         else
1501         {
1502           entry.setId(pdbfile.id);
1503         }
1504       } catch (java.io.IOException ex)
1505       {
1506         ex.printStackTrace();
1507       }
1508
1509       entry.setFile(choice);
1510       sequence.getDatasetSequence().addPDBId(entry);
1511     }
1512
1513   }
1514
1515   public void enterPDB_actionPerformed()
1516   {
1517     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
1518             "Enter PDB Id", "Enter PDB Id", JOptionPane.QUESTION_MESSAGE);
1519
1520     if (id != null && id.length() > 0)
1521     {
1522       PDBEntry entry = new PDBEntry();
1523       entry.setId(id.toUpperCase());
1524       sequence.getDatasetSequence().addPDBId(entry);
1525     }
1526   }
1527
1528   public void discoverPDB_actionPerformed()
1529   {
1530
1531     final SequenceI[] sequences = ((ap.av.selectionGroup == null) ? new Sequence[]
1532     { sequence }
1533             : ap.av.selectionGroup.getSequencesInOrder(ap.av.alignment));
1534     Thread discpdb = new Thread(new Runnable()
1535     {
1536       public void run()
1537       {
1538
1539         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
1540                 .fetchDBRefs(false);
1541       }
1542
1543     });
1544     discpdb.start();
1545   }
1546
1547   public void sequenceFeature_actionPerformed()
1548   {
1549     SequenceGroup sg = ap.av.getSelectionGroup();
1550     if (sg == null)
1551     {
1552       return;
1553     }
1554
1555     int gSize = sg.getSize();
1556     SequenceI[] seqs = new SequenceI[gSize];
1557     SequenceFeature[] features = new SequenceFeature[gSize];
1558
1559     for (int i = 0; i < gSize; i++)
1560     {
1561       seqs[i] = sg.getSequenceAt(i).getDatasetSequence();
1562       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
1563       int end = sg.findEndRes(sg.getSequenceAt(i));
1564       features[i] = new SequenceFeature(null, null, null, start, end,
1565               "Jalview");
1566     }
1567
1568     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
1569             features, true, ap))
1570     {
1571       ap.alignFrame.showSeqFeatures.setSelected(true);
1572       ap.av.setShowSequenceFeatures(true);
1573       ap.highlightSearchResults(null);
1574     }
1575   }
1576
1577   public void textColour_actionPerformed()
1578   {
1579     SequenceGroup sg = getGroup();
1580     if (sg != null)
1581     {
1582       new TextColourChooser().chooseColour(ap, sg);
1583     }
1584   }
1585
1586   public void colourByStructure(String pdbid)
1587   {
1588     Annotation[] anots = jalview.structure.StructureSelectionManager
1589             .getStructureSelectionManager().colourSequenceFromStructure(
1590                     sequence, pdbid);
1591
1592     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
1593             "Coloured by " + pdbid, anots);
1594
1595     ap.av.alignment.addAnnotation(an);
1596     an.createSequenceMapping(sequence, 0, true);
1597     // an.adjustForAlignment();
1598     ap.av.alignment.setAnnotationIndex(an, 0);
1599
1600     ap.adjustAnnotationHeight();
1601
1602     sequence.addAlignmentAnnotation(an);
1603
1604   }
1605
1606   public void editSequence_actionPerformed(ActionEvent actionEvent)
1607   {
1608     SequenceGroup sg = ap.av.getSelectionGroup();
1609
1610     if (sg != null)
1611     {
1612       if (sequence == null)
1613         sequence = (Sequence) sg.getSequenceAt(0);
1614
1615       EditNameDialog dialog = new EditNameDialog(sequence
1616               .getSequenceAsString(sg.getStartRes(), sg.getEndRes() + 1),
1617               null, "Edit Sequence ", null, "Edit Sequence");
1618
1619       if (dialog.accept)
1620       {
1621         EditCommand editCommand = new EditCommand("Edit Sequences",
1622                 EditCommand.REPLACE, dialog.getName().replace(' ',
1623                         ap.av.getGapCharacter()), sg
1624                         .getSequencesAsArray(ap.av.hiddenRepSequences), sg
1625                         .getStartRes(), sg.getEndRes() + 1, ap.av.alignment);
1626
1627         ap.alignFrame.addHistoryItem(editCommand);
1628
1629         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1630                 .getSequences());
1631       }
1632     }
1633   }
1634
1635 }