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