patch for JAL-542
[jalview.git] / src / jalview / gui / PopupMenu.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.gui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24 import javax.swing.*;
25
26 import MCview.*;
27 import jalview.analysis.*;
28 import jalview.commands.*;
29 import jalview.datamodel.*;
30 import jalview.io.*;
31 import jalview.schemes.*;
32 import jalview.util.GroupUrlLink;
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   JCheckBoxMenuItem displayNonconserved = new JCheckBoxMenuItem();
98
99   JMenu editMenu = new JMenu();
100
101   JMenuItem cut = new JMenuItem();
102
103   JMenuItem copy = new JMenuItem();
104
105   JMenuItem upperCase = new JMenuItem();
106
107   JMenuItem lowerCase = new JMenuItem();
108
109   JMenuItem toggle = new JMenuItem();
110
111   JMenu pdbMenu = new JMenu();
112
113   JMenuItem pdbFromFile = new JMenuItem();
114
115   JMenuItem enterPDB = new JMenuItem();
116
117   JMenuItem discoverPDB = new JMenuItem();
118
119   JMenu outputMenu = new JMenu();
120
121   JMenuItem sequenceFeature = new JMenuItem();
122
123   JMenuItem textColour = new JMenuItem();
124
125   JMenu jMenu1 = new JMenu();
126
127   JMenu structureMenu = new JMenu();
128
129   JMenu viewStructureMenu = new JMenu();
130
131   // JMenu colStructureMenu = new JMenu();
132   JMenuItem editSequence = new JMenuItem();
133
134   // JMenuItem annotationMenuItem = new JMenuItem();
135
136   JMenu groupLinksMenu;
137
138   /**
139    * Creates a new PopupMenu object.
140    * 
141    * @param ap
142    *          DOCUMENT ME!
143    * @param seq
144    *          DOCUMENT ME!
145    */
146   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
147   {
148     this(ap, seq, links, null);
149   }
150
151   /**
152    * 
153    * @param ap
154    * @param seq
155    * @param links
156    * @param groupLinks
157    */
158   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links,
159           Vector groupLinks)
160   {
161     // /////////////////////////////////////////////////////////
162     // If this is activated from the sequence panel, the user may want to
163     // edit or annotate a particular residue. Therefore display the residue menu
164     //
165     // If from the IDPanel, we must display the sequence menu
166     // ////////////////////////////////////////////////////////
167     this.ap = ap;
168     sequence = seq;
169
170     ButtonGroup colours = new ButtonGroup();
171     colours.add(noColourmenuItem);
172     colours.add(clustalColour);
173     colours.add(zappoColour);
174     colours.add(taylorColour);
175     colours.add(hydrophobicityColour);
176     colours.add(helixColour);
177     colours.add(strandColour);
178     colours.add(turnColour);
179     colours.add(buriedColour);
180     colours.add(abovePIDColour);
181     colours.add(userDefinedColour);
182     colours.add(PIDColour);
183     colours.add(BLOSUM62Colour);
184
185     for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
186     {
187       JMenuItem item = new JMenuItem(
188               jalview.io.FormatAdapter.WRITEABLE_FORMATS[i]);
189
190       item.addActionListener(new java.awt.event.ActionListener()
191       {
192         public void actionPerformed(ActionEvent e)
193         {
194           outputText_actionPerformed(e);
195         }
196       });
197
198       outputMenu.add(item);
199     }
200
201     try
202     {
203       jbInit();
204     } catch (Exception e)
205     {
206       e.printStackTrace();
207     }
208
209     if (seq != null)
210     {
211       sequenceMenu.setText(sequence.getName());
212
213       JMenuItem menuItem;
214       if (seq.getDatasetSequence().getPDBId() != null
215               && seq.getDatasetSequence().getPDBId().size() > 0)
216       {
217         java.util.Enumeration e = seq.getDatasetSequence().getPDBId()
218                 .elements();
219
220         while (e.hasMoreElements())
221         {
222           final PDBEntry pdb = (PDBEntry) e.nextElement();
223
224           menuItem = new JMenuItem();
225           menuItem.setText(pdb.getId());
226           menuItem.addActionListener(new java.awt.event.ActionListener()
227           {
228             public void actionPerformed(ActionEvent e)
229             {
230               Vector seqs = new Vector();
231               for (int i = 0; i < ap.av.alignment.getHeight(); i++)
232               {
233                 Vector pdbs = ap.av.alignment.getSequenceAt(i)
234                         .getDatasetSequence().getPDBId();
235                 if (pdbs == null)
236                   continue;
237
238                 for (int p = 0; p < pdbs.size(); p++)
239                 {
240                   PDBEntry p1 = (PDBEntry) pdbs.elementAt(p);
241                   if (p1.getId().equals(pdb.getId()))
242                   {
243                     if (!seqs.contains(ap.av.alignment.getSequenceAt(i)))
244                       seqs.addElement(ap.av.alignment.getSequenceAt(i));
245
246                     continue;
247                   }
248                 }
249               }
250
251               SequenceI[] seqs2 = new SequenceI[seqs.size()];
252               seqs.toArray(seqs2);
253
254               new AppJmol(pdb, seqs2, null, ap);
255               // new PDBViewer(pdb, seqs2, null, ap, AppletFormatAdapter.FILE);
256             }
257           });
258           viewStructureMenu.add(menuItem);
259
260           /*
261            * menuItem = new JMenuItem(); menuItem.setText(pdb.getId());
262            * menuItem.addActionListener(new java.awt.event.ActionListener() {
263            * public void actionPerformed(ActionEvent e) {
264            * colourByStructure(pdb.getId()); } });
265            * colStructureMenu.add(menuItem);
266            */
267         }
268       }
269       else
270       {
271         structureMenu.remove(viewStructureMenu);
272         // structureMenu.remove(colStructureMenu);
273       }
274
275       menuItem = new JMenuItem("Hide Sequences");
276       menuItem.addActionListener(new java.awt.event.ActionListener()
277       {
278         public void actionPerformed(ActionEvent e)
279         {
280           hideSequences(false);
281         }
282       });
283       add(menuItem);
284
285       if (ap.av.getSelectionGroup() != null
286               && ap.av.getSelectionGroup().getSize() > 1)
287       {
288         menuItem = new JMenuItem("Represent Group with " + seq.getName());
289         menuItem.addActionListener(new java.awt.event.ActionListener()
290         {
291           public void actionPerformed(ActionEvent e)
292           {
293             hideSequences(true);
294           }
295         });
296         sequenceMenu.add(menuItem);
297       }
298
299       if (ap.av.hasHiddenRows)
300       {
301         final int index = ap.av.alignment.findIndex(seq);
302
303         if (ap.av.adjustForHiddenSeqs(index)
304                 - ap.av.adjustForHiddenSeqs(index - 1) > 1)
305         {
306           menuItem = new JMenuItem("Reveal Sequences");
307           menuItem.addActionListener(new ActionListener()
308           {
309             public void actionPerformed(ActionEvent e)
310             {
311               ap.av.showSequence(index);
312               if (ap.overviewPanel != null)
313               {
314                 ap.overviewPanel.updateOverviewImage();
315               }
316             }
317           });
318           add(menuItem);
319         }
320
321         menuItem = new JMenuItem("Reveal All");
322         menuItem.addActionListener(new ActionListener()
323         {
324           public void actionPerformed(ActionEvent e)
325           {
326             ap.av.showAllHiddenSeqs();
327             if (ap.overviewPanel != null)
328             {
329               ap.overviewPanel.updateOverviewImage();
330             }
331           }
332         });
333
334         add(menuItem);
335       }
336
337     }
338
339     SequenceGroup sg = ap.av.getSelectionGroup();
340
341     if (sg != null)
342     {
343       groupName.setText(sg.getName());
344
345       if (sg.cs instanceof ZappoColourScheme)
346       {
347         zappoColour.setSelected(true);
348       }
349       else if (sg.cs instanceof TaylorColourScheme)
350       {
351         taylorColour.setSelected(true);
352       }
353       else if (sg.cs instanceof PIDColourScheme)
354       {
355         PIDColour.setSelected(true);
356       }
357       else if (sg.cs instanceof Blosum62ColourScheme)
358       {
359         BLOSUM62Colour.setSelected(true);
360       }
361       else if (sg.cs instanceof UserColourScheme)
362       {
363         userDefinedColour.setSelected(true);
364       }
365       else if (sg.cs instanceof HydrophobicColourScheme)
366       {
367         hydrophobicityColour.setSelected(true);
368       }
369       else if (sg.cs instanceof HelixColourScheme)
370       {
371         helixColour.setSelected(true);
372       }
373       else if (sg.cs instanceof StrandColourScheme)
374       {
375         strandColour.setSelected(true);
376       }
377       else if (sg.cs instanceof TurnColourScheme)
378       {
379         turnColour.setSelected(true);
380       }
381       else if (sg.cs instanceof BuriedColourScheme)
382       {
383         buriedColour.setSelected(true);
384       }
385       else if (sg.cs instanceof ClustalxColourScheme)
386       {
387         clustalColour.setSelected(true);
388       }
389       else
390       {
391         noColourmenuItem.setSelected(true);
392       }
393
394       if (sg.cs != null && sg.cs.conservationApplied())
395       {
396         conservationMenuItem.setSelected(true);
397       }
398       displayNonconserved.setSelected(sg.getShowNonconserved());
399       showText.setSelected(sg.getDisplayText());
400       showColourText.setSelected(sg.getColourText());
401       showBoxes.setSelected(sg.getDisplayBoxes());
402       // add any groupURLs to the groupURL submenu and make it visible
403       if (groupLinks != null && groupLinks.size() > 0)
404       {
405         buildGroupURLMenu(sg, groupLinks);
406       }
407     }
408     else
409     {
410       groupMenu.setVisible(false);
411       editMenu.setVisible(false);
412     }
413
414     if (!ap.av.alignment.getGroups().contains(sg))
415     {
416       unGroupMenuItem.setVisible(false);
417     }
418
419     if (seq == null)
420     {
421       sequenceMenu.setVisible(false);
422       structureMenu.setVisible(false);
423     }
424
425     if (links != null && links.size() > 0)
426     {
427
428       JMenu linkMenu = new JMenu("Link");
429       Vector linkset = new Vector();
430       for (int i = 0; i < links.size(); i++)
431       {
432         String link = links.elementAt(i).toString();
433         UrlLink urlLink = null;
434         try
435         {
436           urlLink = new UrlLink(link);
437         } catch (Exception foo)
438         {
439           jalview.bin.Cache.log.error("Exception for URLLink '" + link
440                   + "'", foo);
441           continue;
442         }
443         ;
444         if (!urlLink.isValid())
445         {
446           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
447           continue;
448         }
449         final String label = urlLink.getLabel();
450         if (urlLink.isDynamic())
451         {
452
453           // collect matching db-refs
454           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq
455                   .getDBRef(), new String[]
456           { urlLink.getTarget() });
457           // collect id string too
458           String id = seq.getName();
459           String descr = seq.getDescription();
460           if (descr != null && descr.length() < 1)
461           {
462             descr = null;
463           }
464
465           if (dbr != null)
466           {
467             for (int r = 0; r < dbr.length; r++)
468             {
469               if (id != null && dbr[r].getAccessionId().equals(id))
470               {
471                 // suppress duplicate link creation for the bare sequence ID
472                 // string with this link
473                 id = null;
474               }
475               // create Bare ID link for this RUL
476               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
477                       true);
478               if (urls != null)
479               {
480                 for (int u = 0; u < urls.length; u += 2)
481                 {
482                   if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
483                   {
484                     linkset.addElement(urls[u] + "|" + urls[u + 1]);
485                     addshowLink(linkMenu, label + "|" + urls[u],
486                             urls[u + 1]);
487                   }
488                 }
489               }
490             }
491           }
492           if (id != null)
493           {
494             // create Bare ID link for this RUL
495             String[] urls = urlLink.makeUrls(id, true);
496             if (urls != null)
497             {
498               for (int u = 0; u < urls.length; u += 2)
499               {
500                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
501                 {
502                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
503                   addshowLink(linkMenu, label, urls[u + 1]);
504                 }
505               }
506             }
507           }
508           // Create urls from description but only for URL links which are regex
509           // links
510           if (descr != null && urlLink.getRegexReplace() != null)
511           {
512             // create link for this URL from description where regex matches
513             String[] urls = urlLink.makeUrls(descr, true);
514             if (urls != null)
515             {
516               for (int u = 0; u < urls.length; u += 2)
517               {
518                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
519                 {
520                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
521                   addshowLink(linkMenu, label, urls[u + 1]);
522                 }
523               }
524             }
525           }
526         }
527         else
528         {
529           if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
530           {
531             linkset.addElement(label + "|" + urlLink.getUrl_prefix());
532             // Add a non-dynamic link
533             addshowLink(linkMenu, label, urlLink.getUrl_prefix());
534           }
535         }
536       }
537       if (sequence != null)
538       {
539         sequenceMenu.add(linkMenu);
540       }
541       else
542       {
543         add(linkMenu);
544       }
545     }
546   }
547
548   private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
549   {
550
551     // TODO: usability: thread off the generation of group url content so root
552     // menu appears asap
553     // sequence only URLs
554     // ID/regex match URLs
555     groupLinksMenu = new JMenu("Group Link");
556     JMenu[] linkMenus = new JMenu[]
557     { null, new JMenu("IDS"), new JMenu("Sequences"),
558         new JMenu("IDS and Sequences") }; // three types of url that might be
559                                           // created.
560     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
561     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
562     Hashtable commonDbrefs = new Hashtable();
563     for (int sq = 0; sq < seqs.length; sq++)
564     {
565
566       int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
567               .findPosition(sg.getEndRes());
568       // just collect ids from dataset sequence
569       // TODO: check if IDs collected from selecton group intersects with the
570       // current selection, too
571       SequenceI sqi = seqs[sq];
572       while (sqi.getDatasetSequence() != null)
573       {
574         sqi = sqi.getDatasetSequence();
575       }
576       DBRefEntry[] dbr = sqi.getDBRef();
577       if (dbr != null && dbr.length > 0)
578       {
579         for (int d = 0; d < dbr.length; d++)
580         {
581           String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
582           Object[] sarray = (Object[]) commonDbrefs.get(src);
583           if (sarray == null)
584           {
585             sarray = new Object[2];
586             sarray[0] = new int[]
587             { 0 };
588             sarray[1] = new String[seqs.length];
589
590             commonDbrefs.put(src, sarray);
591           }
592
593           if (((String[]) sarray[1])[sq] == null)
594           {
595             if (!dbr[d].hasMap()
596                     || (dbr[d].getMap().locateMappedRange(start, end) != null))
597             {
598               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
599               ((int[]) sarray[0])[0]++;
600             }
601           }
602         }
603       }
604     }
605     // now create group links for all distinct ID/sequence sets.
606     boolean addMenu = false; // indicates if there are any group links to give
607                              // to user
608     for (int i = 0; i < groupLinks.size(); i++)
609     {
610       String link = groupLinks.elementAt(i).toString();
611       GroupUrlLink urlLink = null;
612       try
613       {
614         urlLink = new GroupUrlLink(link);
615       } catch (Exception foo)
616       {
617         jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
618                 + "'", foo);
619         continue;
620       }
621       ;
622       if (!urlLink.isValid())
623       {
624         jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
625         continue;
626       }
627       final String label = urlLink.getLabel();
628       boolean usingNames = false;
629       // Now see which parts of the group apply for this URL
630       String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
631       Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
632       String[] seqstr, ids; // input to makeUrl
633       if (idset != null)
634       {
635         int numinput = ((int[]) idset[0])[0];
636         String[] allids = ((String[]) idset[1]);
637         seqstr = new String[numinput];
638         ids = new String[numinput];
639         for (int sq = 0, idcount = 0; sq < seqs.length; sq++)
640         {
641           if (allids[sq] != null)
642           {
643             ids[idcount] = allids[sq];
644             seqstr[idcount++] = idandseqs[1][sq];
645           }
646         }
647       }
648       else
649       {
650         // just use the id/seq set
651         seqstr = idandseqs[1];
652         ids = idandseqs[0];
653         usingNames = true;
654       }
655       // and try and make the groupURL!
656
657       Object[] urlset = urlLink.makeUrlStubs(ids, seqstr, "FromJalview"
658               + System.currentTimeMillis(), false);
659       if (urlset != null)
660       {
661         int type = urlLink.getGroupURLType() & 3;
662         // System.out.println(urlLink.getGroupURLType()
663         // +" "+((String[])urlset[3])[0]);
664         // first two bits ofurlLink type bitfield are sequenceids and sequences
665         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
666         addshowLink(linkMenus[type], label
667                 + (((type & 1) == 1) ? ("("
668                         + (usingNames ? "Names" : ltarget) + ")") : ""),
669                 urlLink, urlset);
670         addMenu = true;
671       }
672     }
673     if (addMenu)
674     {
675       groupLinksMenu = new JMenu("Group Links");
676       for (int m = 0; m < linkMenus.length; m++)
677       {
678         if (linkMenus[m] != null
679                 && linkMenus[m].getMenuComponentCount() > 0)
680         {
681           groupLinksMenu.add(linkMenus[m]);
682         }
683       }
684
685       groupMenu.add(groupLinksMenu);
686     }
687   }
688
689   /**
690    * add a show URL menu item to the given linkMenu
691    * 
692    * @param linkMenu
693    * @param label
694    *          - menu label string
695    * @param url
696    *          - url to open
697    */
698   private void addshowLink(JMenu linkMenu, String label, final String url)
699   {
700     JMenuItem item = new JMenuItem(label);
701     item.setToolTipText("open URL: " + url);
702     item.addActionListener(new java.awt.event.ActionListener()
703     {
704       public void actionPerformed(ActionEvent e)
705       {
706         new Thread(new Runnable()
707         {
708
709           public void run()
710           {
711             showLink(url);
712           }
713
714         }).start();
715       }
716     });
717
718     linkMenu.add(item);
719   }
720
721   /**
722    * add a late bound groupURL item to the given linkMenu
723    * 
724    * @param linkMenu
725    * @param label
726    *          - menu label string
727    * @param urlgenerator
728    *          GroupURLLink used to generate URL
729    * @param urlstub
730    *          Object array returned from the makeUrlStubs function.
731    */
732   private void addshowLink(JMenu linkMenu, String label,
733           final GroupUrlLink urlgenerator, final Object[] urlstub)
734   {
735     JMenuItem item = new JMenuItem(label);
736     item.setToolTipText("open URL (" + urlgenerator.getUrl_prefix()
737             + "..) (" + urlgenerator.getNumberInvolved(urlstub) + " seqs)"); // TODO:
738                                                                              // put
739                                                                              // in
740                                                                              // info
741                                                                              // about
742                                                                              // what
743                                                                              // is
744                                                                              // being
745                                                                              // sent.
746     item.addActionListener(new java.awt.event.ActionListener()
747     {
748       public void actionPerformed(ActionEvent e)
749       {
750         new Thread(new Runnable()
751         {
752
753           public void run()
754           {
755             showLink(urlgenerator.constructFrom(urlstub));
756           }
757
758         }).start();
759       }
760     });
761
762     linkMenu.add(item);
763   }
764
765   /**
766    * DOCUMENT ME!
767    * 
768    * @throws Exception
769    *           DOCUMENT ME!
770    */
771   private void jbInit() throws Exception
772   {
773     groupMenu.setText("Group");
774     groupMenu.setText("Selection");
775     groupName.setText("Name");
776     groupName.addActionListener(new java.awt.event.ActionListener()
777     {
778       public void actionPerformed(ActionEvent e)
779       {
780         groupName_actionPerformed();
781       }
782     });
783     sequenceMenu.setText("Sequence");
784     sequenceName.setText("Edit Name/Description");
785     sequenceName.addActionListener(new java.awt.event.ActionListener()
786     {
787       public void actionPerformed(ActionEvent e)
788       {
789         sequenceName_actionPerformed();
790       }
791     });
792     PIDColour.setFocusPainted(false);
793     unGroupMenuItem.setText("Remove Group");
794     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
795     {
796       public void actionPerformed(ActionEvent e)
797       {
798         unGroupMenuItem_actionPerformed();
799       }
800     });
801
802     outline.setText("Border colour");
803     outline.addActionListener(new java.awt.event.ActionListener()
804     {
805       public void actionPerformed(ActionEvent e)
806       {
807         outline_actionPerformed();
808       }
809     });
810     nucleotideMenuItem.setText("Nucleotide");
811     nucleotideMenuItem.addActionListener(new ActionListener()
812     {
813       public void actionPerformed(ActionEvent e)
814       {
815         nucleotideMenuItem_actionPerformed();
816       }
817     });
818     colourMenu.setText("Group Colour");
819     showBoxes.setText("Boxes");
820     showBoxes.setState(true);
821     showBoxes.addActionListener(new ActionListener()
822     {
823       public void actionPerformed(ActionEvent e)
824       {
825         showBoxes_actionPerformed();
826       }
827     });
828     showText.setText("Text");
829     showText.setState(true);
830     showText.addActionListener(new ActionListener()
831     {
832       public void actionPerformed(ActionEvent e)
833       {
834         showText_actionPerformed();
835       }
836     });
837     showColourText.setText("Colour Text");
838     showColourText.addActionListener(new ActionListener()
839     {
840       public void actionPerformed(ActionEvent e)
841       {
842         showColourText_actionPerformed();
843       }
844     });
845     displayNonconserved.setText("Show Nonconserved");
846     displayNonconserved.setState(true);
847     displayNonconserved.addActionListener(new ActionListener()
848     {
849       public void actionPerformed(ActionEvent e)
850       {
851         showNonconserved_actionPerformed();
852       }
853     });
854     editMenu.setText("Edit");
855     cut.setText("Cut");
856     cut.addActionListener(new ActionListener()
857     {
858       public void actionPerformed(ActionEvent e)
859       {
860         cut_actionPerformed();
861       }
862     });
863     upperCase.setText("To Upper Case");
864     upperCase.addActionListener(new ActionListener()
865     {
866       public void actionPerformed(ActionEvent e)
867       {
868         changeCase(e);
869       }
870     });
871     copy.setText("Copy");
872     copy.addActionListener(new ActionListener()
873     {
874       public void actionPerformed(ActionEvent e)
875       {
876         copy_actionPerformed();
877       }
878     });
879     lowerCase.setText("To Lower Case");
880     lowerCase.addActionListener(new ActionListener()
881     {
882       public void actionPerformed(ActionEvent e)
883       {
884         changeCase(e);
885       }
886     });
887     toggle.setText("Toggle Case");
888     toggle.addActionListener(new ActionListener()
889     {
890       public void actionPerformed(ActionEvent e)
891       {
892         changeCase(e);
893       }
894     });
895     pdbMenu.setText("Associate Structure with Sequence");
896     pdbFromFile.setText("From File");
897     pdbFromFile.addActionListener(new ActionListener()
898     {
899       public void actionPerformed(ActionEvent e)
900       {
901         pdbFromFile_actionPerformed();
902       }
903     });
904     enterPDB.setText("Enter PDB Id");
905     enterPDB.addActionListener(new ActionListener()
906     {
907       public void actionPerformed(ActionEvent e)
908       {
909         enterPDB_actionPerformed();
910       }
911     });
912     discoverPDB.setText("Discover PDB ids");
913     discoverPDB.addActionListener(new ActionListener()
914     {
915       public void actionPerformed(ActionEvent e)
916       {
917         discoverPDB_actionPerformed();
918       }
919     });
920     outputMenu.setText("Output to Textbox...");
921     sequenceFeature.setText("Create Sequence Feature");
922     sequenceFeature.addActionListener(new ActionListener()
923     {
924       public void actionPerformed(ActionEvent e)
925       {
926         sequenceFeature_actionPerformed();
927       }
928     });
929     textColour.setText("Text Colour");
930     textColour.addActionListener(new ActionListener()
931     {
932       public void actionPerformed(ActionEvent e)
933       {
934         textColour_actionPerformed();
935       }
936     });
937     jMenu1.setText("Group");
938     structureMenu.setText("Structure");
939     viewStructureMenu.setText("View Structure");
940     // colStructureMenu.setText("Colour By Structure");
941     editSequence.setText("Edit Sequence...");
942     editSequence.addActionListener(new ActionListener()
943     {
944       public void actionPerformed(ActionEvent actionEvent)
945       {
946         editSequence_actionPerformed(actionEvent);
947       }
948     });
949     /*
950      * annotationMenuItem.setText("By Annotation");
951      * annotationMenuItem.addActionListener(new ActionListener() { public void
952      * actionPerformed(ActionEvent actionEvent) {
953      * annotationMenuItem_actionPerformed(actionEvent); } });
954      */
955
956     add(groupMenu);
957
958     add(sequenceMenu);
959     this.add(structureMenu);
960     groupMenu.add(editMenu);
961     groupMenu.add(outputMenu);
962     groupMenu.add(sequenceFeature);
963     groupMenu.add(jMenu1);
964     sequenceMenu.add(sequenceName);
965     colourMenu.add(textColour);
966     colourMenu.add(noColourmenuItem);
967     colourMenu.add(clustalColour);
968     colourMenu.add(BLOSUM62Colour);
969     colourMenu.add(PIDColour);
970     colourMenu.add(zappoColour);
971     colourMenu.add(taylorColour);
972     colourMenu.add(hydrophobicityColour);
973     colourMenu.add(helixColour);
974     colourMenu.add(strandColour);
975     colourMenu.add(turnColour);
976     colourMenu.add(buriedColour);
977     colourMenu.add(nucleotideMenuItem);
978     colourMenu.add(userDefinedColour);
979
980     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
981     {
982       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
983               .getUserColourSchemes().keys();
984
985       while (userColours.hasMoreElements())
986       {
987         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
988         item.addActionListener(new ActionListener()
989         {
990           public void actionPerformed(ActionEvent evt)
991           {
992             userDefinedColour_actionPerformed(evt);
993           }
994         });
995         colourMenu.add(item);
996       }
997     }
998
999     colourMenu.addSeparator();
1000     colourMenu.add(abovePIDColour);
1001     colourMenu.add(conservationMenuItem);
1002     // colourMenu.add(annotationMenuItem);
1003     editMenu.add(copy);
1004     editMenu.add(cut);
1005     editMenu.add(editSequence);
1006     editMenu.add(upperCase);
1007     editMenu.add(lowerCase);
1008     editMenu.add(toggle);
1009     pdbMenu.add(pdbFromFile);
1010     pdbMenu.add(enterPDB);
1011     pdbMenu.add(discoverPDB);
1012     jMenu1.add(groupName);
1013     jMenu1.add(unGroupMenuItem);
1014     jMenu1.add(colourMenu);
1015     jMenu1.add(showBoxes);
1016     jMenu1.add(showText);
1017     jMenu1.add(showColourText);
1018     jMenu1.add(outline);
1019     jMenu1.add(displayNonconserved);
1020     structureMenu.add(pdbMenu);
1021     structureMenu.add(viewStructureMenu);
1022     // structureMenu.add(colStructureMenu);
1023     noColourmenuItem.setText("None");
1024     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
1025     {
1026       public void actionPerformed(ActionEvent e)
1027       {
1028         noColourmenuItem_actionPerformed();
1029       }
1030     });
1031
1032     clustalColour.setText("Clustalx colours");
1033     clustalColour.addActionListener(new java.awt.event.ActionListener()
1034     {
1035       public void actionPerformed(ActionEvent e)
1036       {
1037         clustalColour_actionPerformed();
1038       }
1039     });
1040     zappoColour.setText("Zappo");
1041     zappoColour.addActionListener(new java.awt.event.ActionListener()
1042     {
1043       public void actionPerformed(ActionEvent e)
1044       {
1045         zappoColour_actionPerformed();
1046       }
1047     });
1048     taylorColour.setText("Taylor");
1049     taylorColour.addActionListener(new java.awt.event.ActionListener()
1050     {
1051       public void actionPerformed(ActionEvent e)
1052       {
1053         taylorColour_actionPerformed();
1054       }
1055     });
1056     hydrophobicityColour.setText("Hydrophobicity");
1057     hydrophobicityColour
1058             .addActionListener(new java.awt.event.ActionListener()
1059             {
1060               public void actionPerformed(ActionEvent e)
1061               {
1062                 hydrophobicityColour_actionPerformed();
1063               }
1064             });
1065     helixColour.setText("Helix propensity");
1066     helixColour.addActionListener(new java.awt.event.ActionListener()
1067     {
1068       public void actionPerformed(ActionEvent e)
1069       {
1070         helixColour_actionPerformed();
1071       }
1072     });
1073     strandColour.setText("Strand propensity");
1074     strandColour.addActionListener(new java.awt.event.ActionListener()
1075     {
1076       public void actionPerformed(ActionEvent e)
1077       {
1078         strandColour_actionPerformed();
1079       }
1080     });
1081     turnColour.setText("Turn propensity");
1082     turnColour.addActionListener(new java.awt.event.ActionListener()
1083     {
1084       public void actionPerformed(ActionEvent e)
1085       {
1086         turnColour_actionPerformed();
1087       }
1088     });
1089     buriedColour.setText("Buried Index");
1090     buriedColour.addActionListener(new java.awt.event.ActionListener()
1091     {
1092       public void actionPerformed(ActionEvent e)
1093       {
1094         buriedColour_actionPerformed();
1095       }
1096     });
1097     abovePIDColour.setText("Above % Identity");
1098     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
1099     {
1100       public void actionPerformed(ActionEvent e)
1101       {
1102         abovePIDColour_actionPerformed();
1103       }
1104     });
1105     userDefinedColour.setText("User Defined...");
1106     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
1107     {
1108       public void actionPerformed(ActionEvent e)
1109       {
1110         userDefinedColour_actionPerformed(e);
1111       }
1112     });
1113     PIDColour.setText("Percentage Identity");
1114     PIDColour.addActionListener(new java.awt.event.ActionListener()
1115     {
1116       public void actionPerformed(ActionEvent e)
1117       {
1118         PIDColour_actionPerformed();
1119       }
1120     });
1121     BLOSUM62Colour.setText("BLOSUM62");
1122     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
1123     {
1124       public void actionPerformed(ActionEvent e)
1125       {
1126         BLOSUM62Colour_actionPerformed();
1127       }
1128     });
1129     conservationMenuItem.setText("Conservation");
1130     conservationMenuItem
1131             .addActionListener(new java.awt.event.ActionListener()
1132             {
1133               public void actionPerformed(ActionEvent e)
1134               {
1135                 conservationMenuItem_actionPerformed();
1136               }
1137             });
1138   }
1139
1140   protected void showNonconserved_actionPerformed()
1141   {
1142     getGroup().setShowNonconserved(displayNonconserved.isSelected());
1143     refresh();
1144   }
1145
1146   /**
1147    * call to refresh view after settings change
1148    */
1149   void refresh()
1150   {
1151     ap.updateAnnotation();
1152     ap.paintAlignment(true);
1153
1154     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
1155   }
1156
1157   /**
1158    * DOCUMENT ME!
1159    * 
1160    * @param e
1161    *          DOCUMENT ME!
1162    */
1163   protected void clustalColour_actionPerformed()
1164   {
1165     SequenceGroup sg = getGroup();
1166     sg.cs = new ClustalxColourScheme(sg
1167             .getSequences(ap.av.hiddenRepSequences), ap.av.alignment
1168             .getWidth());
1169     refresh();
1170   }
1171
1172   /**
1173    * DOCUMENT ME!
1174    * 
1175    * @param e
1176    *          DOCUMENT ME!
1177    */
1178   protected void zappoColour_actionPerformed()
1179   {
1180     getGroup().cs = new ZappoColourScheme();
1181     refresh();
1182   }
1183
1184   /**
1185    * DOCUMENT ME!
1186    * 
1187    * @param e
1188    *          DOCUMENT ME!
1189    */
1190   protected void taylorColour_actionPerformed()
1191   {
1192     getGroup().cs = new TaylorColourScheme();
1193     refresh();
1194   }
1195
1196   /**
1197    * DOCUMENT ME!
1198    * 
1199    * @param e
1200    *          DOCUMENT ME!
1201    */
1202   protected void hydrophobicityColour_actionPerformed()
1203   {
1204     getGroup().cs = new HydrophobicColourScheme();
1205     refresh();
1206   }
1207
1208   /**
1209    * DOCUMENT ME!
1210    * 
1211    * @param e
1212    *          DOCUMENT ME!
1213    */
1214   protected void helixColour_actionPerformed()
1215   {
1216     getGroup().cs = new HelixColourScheme();
1217     refresh();
1218   }
1219
1220   /**
1221    * DOCUMENT ME!
1222    * 
1223    * @param e
1224    *          DOCUMENT ME!
1225    */
1226   protected void strandColour_actionPerformed()
1227   {
1228     getGroup().cs = new StrandColourScheme();
1229     refresh();
1230   }
1231
1232   /**
1233    * DOCUMENT ME!
1234    * 
1235    * @param e
1236    *          DOCUMENT ME!
1237    */
1238   protected void turnColour_actionPerformed()
1239   {
1240     getGroup().cs = new TurnColourScheme();
1241     refresh();
1242   }
1243
1244   /**
1245    * DOCUMENT ME!
1246    * 
1247    * @param e
1248    *          DOCUMENT ME!
1249    */
1250   protected void buriedColour_actionPerformed()
1251   {
1252     getGroup().cs = new BuriedColourScheme();
1253     refresh();
1254   }
1255
1256   /**
1257    * DOCUMENT ME!
1258    * 
1259    * @param e
1260    *          DOCUMENT ME!
1261    */
1262   public void nucleotideMenuItem_actionPerformed()
1263   {
1264     getGroup().cs = new NucleotideColourScheme();
1265     refresh();
1266   }
1267
1268   /**
1269    * DOCUMENT ME!
1270    * 
1271    * @param e
1272    *          DOCUMENT ME!
1273    */
1274   protected void abovePIDColour_actionPerformed()
1275   {
1276     SequenceGroup sg = getGroup();
1277     if (sg.cs == null)
1278     {
1279       return;
1280     }
1281
1282     if (abovePIDColour.isSelected())
1283     {
1284       sg.cs.setConsensus(AAFrequency.calculate(sg
1285               .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1286               .getEndRes() + 1));
1287
1288       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1289               .getName());
1290
1291       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1292
1293       SliderPanel.showPIDSlider();
1294     }
1295     else
1296     // remove PIDColouring
1297     {
1298       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1299     }
1300
1301     refresh();
1302   }
1303
1304   /**
1305    * DOCUMENT ME!
1306    * 
1307    * @param e
1308    *          DOCUMENT ME!
1309    */
1310   protected void userDefinedColour_actionPerformed(ActionEvent e)
1311   {
1312     SequenceGroup sg = getGroup();
1313
1314     if (e.getActionCommand().equals("User Defined..."))
1315     {
1316       new UserDefinedColours(ap, sg);
1317     }
1318     else
1319     {
1320       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1321               .getUserColourSchemes().get(e.getActionCommand());
1322
1323       sg.cs = udc;
1324     }
1325     refresh();
1326   }
1327
1328   /**
1329    * DOCUMENT ME!
1330    * 
1331    * @param e
1332    *          DOCUMENT ME!
1333    */
1334   protected void PIDColour_actionPerformed()
1335   {
1336     SequenceGroup sg = getGroup();
1337     sg.cs = new PIDColourScheme();
1338     sg.cs.setConsensus(AAFrequency.calculate(sg
1339             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1340             .getEndRes() + 1));
1341     refresh();
1342   }
1343
1344   /**
1345    * DOCUMENT ME!
1346    * 
1347    * @param e
1348    *          DOCUMENT ME!
1349    */
1350   protected void BLOSUM62Colour_actionPerformed()
1351   {
1352     SequenceGroup sg = getGroup();
1353
1354     sg.cs = new Blosum62ColourScheme();
1355
1356     sg.cs.setConsensus(AAFrequency.calculate(sg
1357             .getSequences(ap.av.hiddenRepSequences), sg.getStartRes(), sg
1358             .getEndRes() + 1));
1359
1360     refresh();
1361   }
1362
1363   /**
1364    * DOCUMENT ME!
1365    * 
1366    * @param e
1367    *          DOCUMENT ME!
1368    */
1369   protected void noColourmenuItem_actionPerformed()
1370   {
1371     getGroup().cs = null;
1372     refresh();
1373   }
1374
1375   /**
1376    * DOCUMENT ME!
1377    * 
1378    * @param e
1379    *          DOCUMENT ME!
1380    */
1381   protected void conservationMenuItem_actionPerformed()
1382   {
1383     SequenceGroup sg = getGroup();
1384     if (sg.cs == null)
1385     {
1386       return;
1387     }
1388
1389     if (conservationMenuItem.isSelected())
1390     {
1391       Conservation c = new Conservation("Group",
1392               ResidueProperties.propHash, 3, sg
1393                       .getSequences(ap.av.hiddenRepSequences), sg
1394                       .getStartRes(), sg.getEndRes() + 1);
1395
1396       c.calculate();
1397       c.verdict(false, ap.av.ConsPercGaps);
1398
1399       sg.cs.setConservation(c);
1400
1401       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1402       SliderPanel.showConservationSlider();
1403     }
1404     else
1405     // remove ConservationColouring
1406     {
1407       sg.cs.setConservation(null);
1408     }
1409
1410     refresh();
1411   }
1412
1413   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1414   {
1415     SequenceGroup sg = getGroup();
1416     if (sg == null)
1417     {
1418       return;
1419     }
1420
1421     AnnotationColourGradient acg = new AnnotationColourGradient(sequence
1422             .getAnnotation()[0], null,
1423             AnnotationColourGradient.NO_THRESHOLD);
1424
1425     acg.predefinedColours = true;
1426     sg.cs = acg;
1427
1428     refresh();
1429   }
1430
1431   /**
1432    * DOCUMENT ME!
1433    * 
1434    * @param e
1435    *          DOCUMENT ME!
1436    */
1437   protected void groupName_actionPerformed()
1438   {
1439
1440     SequenceGroup sg = getGroup();
1441     EditNameDialog dialog = new EditNameDialog(sg.getName(), sg
1442             .getDescription(), "       Group Name ", "Group Description ",
1443             "Edit Group Name/Description", ap.alignFrame);
1444
1445     if (!dialog.accept)
1446     {
1447       return;
1448     }
1449
1450     sg.setName(dialog.getName());
1451     sg.setDescription(dialog.getDescription());
1452     refresh();
1453   }
1454
1455   /**
1456    * Get selection group - adding it to the alignment if necessary.
1457    * 
1458    * @return sequence group to operate on
1459    */
1460   SequenceGroup getGroup()
1461   {
1462     SequenceGroup sg = ap.av.getSelectionGroup();
1463     // this method won't add a new group if it already exists
1464     if (sg != null)
1465     {
1466       ap.av.alignment.addGroup(sg);
1467     }
1468
1469     return sg;
1470   }
1471
1472   /**
1473    * DOCUMENT ME!
1474    * 
1475    * @param e
1476    *          DOCUMENT ME!
1477    */
1478   void sequenceName_actionPerformed()
1479   {
1480     EditNameDialog dialog = new EditNameDialog(sequence.getName(), sequence
1481             .getDescription(), "       Sequence Name ",
1482             "Sequence Description ", "Edit Sequence Name/Description", ap.alignFrame);
1483
1484     if (!dialog.accept)
1485     {
1486       return;
1487     }
1488
1489     if (dialog.getName() != null)
1490     {
1491       if (dialog.getName().indexOf(" ") > -1)
1492       {
1493         JOptionPane.showMessageDialog(ap,
1494                 "Spaces have been converted to \"_\"",
1495                 "No spaces allowed in Sequence Name",
1496                 JOptionPane.WARNING_MESSAGE);
1497       }
1498
1499       sequence.setName(dialog.getName().replace(' ', '_'));
1500       ap.paintAlignment(false);
1501     }
1502
1503     sequence.setDescription(dialog.getDescription());
1504
1505     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1506             .getSequences());
1507
1508   }
1509
1510   /**
1511    * DOCUMENT ME!
1512    * 
1513    * @param e
1514    *          DOCUMENT ME!
1515    */
1516   void unGroupMenuItem_actionPerformed()
1517   {
1518     SequenceGroup sg = ap.av.getSelectionGroup();
1519     ap.av.alignment.deleteGroup(sg);
1520     ap.av.setSelectionGroup(null);
1521     refresh();
1522   }
1523
1524   /**
1525    * DOCUMENT ME!
1526    * 
1527    * @param e
1528    *          DOCUMENT ME!
1529    */
1530   protected void outline_actionPerformed()
1531   {
1532     SequenceGroup sg = getGroup();
1533     Color col = JColorChooser.showDialog(this, "Select Outline Colour",
1534             Color.BLUE);
1535
1536     if (col != null)
1537     {
1538       sg.setOutlineColour(col);
1539     }
1540
1541     refresh();
1542   }
1543
1544   /**
1545    * DOCUMENT ME!
1546    * 
1547    * @param e
1548    *          DOCUMENT ME!
1549    */
1550   public void showBoxes_actionPerformed()
1551   {
1552     getGroup().setDisplayBoxes(showBoxes.isSelected());
1553     refresh();
1554   }
1555
1556   /**
1557    * DOCUMENT ME!
1558    * 
1559    * @param e
1560    *          DOCUMENT ME!
1561    */
1562   public void showText_actionPerformed()
1563   {
1564     getGroup().setDisplayText(showText.isSelected());
1565     refresh();
1566   }
1567
1568   /**
1569    * DOCUMENT ME!
1570    * 
1571    * @param e
1572    *          DOCUMENT ME!
1573    */
1574   public void showColourText_actionPerformed()
1575   {
1576     getGroup().setColourText(showColourText.isSelected());
1577     refresh();
1578   }
1579
1580   public void showLink(String url)
1581   {
1582     try
1583     {
1584       jalview.util.BrowserLauncher.openURL(url);
1585     } catch (Exception ex)
1586     {
1587       JOptionPane
1588               .showInternalMessageDialog(
1589                       Desktop.desktop,
1590                       "Unixers: Couldn't find default web browser."
1591                               + "\nAdd the full path to your browser in Preferences.",
1592                       "Web browser not found", JOptionPane.WARNING_MESSAGE);
1593
1594       ex.printStackTrace();
1595     }
1596   }
1597
1598   void hideSequences(boolean representGroup)
1599   {
1600     SequenceGroup sg = ap.av.getSelectionGroup();
1601     if (sg == null || sg.getSize() < 1)
1602     {
1603       ap.av.hideSequence(new SequenceI[]
1604       { sequence });
1605       return;
1606     }
1607
1608     ap.av.setSelectionGroup(null);
1609
1610     if (representGroup)
1611     {
1612       ap.av.hideRepSequences(sequence, sg);
1613
1614       return;
1615     }
1616
1617     int gsize = sg.getSize();
1618     SequenceI[] hseqs;
1619
1620     hseqs = new SequenceI[gsize];
1621
1622     int index = 0;
1623     for (int i = 0; i < gsize; i++)
1624     {
1625       hseqs[index++] = sg.getSequenceAt(i);
1626     }
1627
1628     ap.av.hideSequence(hseqs);
1629     // refresh(); TODO: ? needed ?
1630     ap.av.sendSelection();
1631   }
1632
1633   public void copy_actionPerformed()
1634   {
1635     ap.alignFrame.copy_actionPerformed(null);
1636   }
1637
1638   public void cut_actionPerformed()
1639   {
1640     ap.alignFrame.cut_actionPerformed(null);
1641   }
1642
1643   void changeCase(ActionEvent e)
1644   {
1645     Object source = e.getSource();
1646     SequenceGroup sg = ap.av.getSelectionGroup();
1647
1648     if (sg != null)
1649     {
1650       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1651               sg.getEndRes() + 1);
1652
1653       String description;
1654       int caseChange;
1655
1656       if (source == toggle)
1657       {
1658         description = "Toggle Case";
1659         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1660       }
1661       else if (source == upperCase)
1662       {
1663         description = "To Upper Case";
1664         caseChange = ChangeCaseCommand.TO_UPPER;
1665       }
1666       else
1667       {
1668         description = "To Lower Case";
1669         caseChange = ChangeCaseCommand.TO_LOWER;
1670       }
1671
1672       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description, sg
1673               .getSequencesAsArray(ap.av.hiddenRepSequences), startEnd,
1674               caseChange);
1675
1676       ap.alignFrame.addHistoryItem(caseCommand);
1677
1678       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1679               .getSequences());
1680
1681     }
1682   }
1683
1684   public void outputText_actionPerformed(ActionEvent e)
1685   {
1686     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1687     cap.setForInput(null);
1688     Desktop.addInternalFrame(cap, "Alignment output - "
1689             + e.getActionCommand(), 600, 500);
1690
1691     String[] omitHidden = null;
1692
1693     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1694     // or we simply trust the user wants
1695     // wysiwig behaviour
1696     SequenceGroup sg = ap.av.getSelectionGroup();
1697     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1698     omitHidden = ap.av.getViewAsString(true);
1699     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1700     AlignmentAnnotation[] nala = ap.av.alignment.getAlignmentAnnotation();
1701     if (nala!=null) {
1702       for (int i = 0; i < nala.length; i++)
1703       {
1704         AlignmentAnnotation na = nala[i];
1705         oal.addAnnotation(na);
1706       }
1707     }
1708     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1709             oal, omitHidden, csel, sg));
1710     oal = null;
1711   }
1712
1713   public void pdbFromFile_actionPerformed()
1714   {
1715     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1716             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1717     chooser.setFileView(new jalview.io.JalviewFileView());
1718     chooser.setDialogTitle("Select a PDB file");
1719     chooser.setToolTipText("Load a PDB file");
1720
1721     int value = chooser.showOpenDialog(null);
1722
1723     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1724     {
1725       PDBEntry entry = new PDBEntry();
1726       String choice = chooser.getSelectedFile().getPath();
1727       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1728       try
1729       {
1730         MCview.PDBfile pdbfile = new MCview.PDBfile(choice,
1731                 jalview.io.AppletFormatAdapter.FILE);
1732
1733         if (pdbfile.id == null)
1734         {
1735           String reply = JOptionPane
1736                   .showInternalInputDialog(
1737                           Desktop.desktop,
1738                           "Couldn't find a PDB id in the file supplied."
1739                                   + "Please enter an Id to identify this structure.",
1740                           "No PDB Id in File", JOptionPane.QUESTION_MESSAGE);
1741           if (reply == null)
1742           {
1743             return;
1744           }
1745
1746           entry.setId(reply);
1747         }
1748         else
1749         {
1750           entry.setId(pdbfile.id);
1751         }
1752       } catch (java.io.IOException ex)
1753       {
1754         ex.printStackTrace();
1755       }
1756
1757       entry.setFile(choice);
1758       sequence.getDatasetSequence().addPDBId(entry);
1759     }
1760
1761   }
1762
1763   public void enterPDB_actionPerformed()
1764   {
1765     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
1766             "Enter PDB Id", "Enter PDB Id", JOptionPane.QUESTION_MESSAGE);
1767
1768     if (id != null && id.length() > 0)
1769     {
1770       PDBEntry entry = new PDBEntry();
1771       entry.setId(id.toUpperCase());
1772       sequence.getDatasetSequence().addPDBId(entry);
1773     }
1774   }
1775
1776   public void discoverPDB_actionPerformed()
1777   {
1778
1779     final SequenceI[] sequences = ((ap.av.selectionGroup == null) ? new Sequence[]
1780     { sequence }
1781             : ap.av.selectionGroup.getSequencesInOrder(ap.av.alignment));
1782     Thread discpdb = new Thread(new Runnable()
1783     {
1784       public void run()
1785       {
1786
1787         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
1788                 .fetchDBRefs(false);
1789       }
1790
1791     });
1792     discpdb.start();
1793   }
1794
1795   public void sequenceFeature_actionPerformed()
1796   {
1797     SequenceGroup sg = ap.av.getSelectionGroup();
1798     if (sg == null)
1799     {
1800       return;
1801     }
1802
1803     int rsize = 0, gSize = sg.getSize();
1804     SequenceI[] rseqs, seqs = new SequenceI[gSize];
1805     SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
1806
1807     for (int i = 0; i < gSize; i++)
1808     {
1809       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
1810       int end = sg.findEndRes(sg.getSequenceAt(i));
1811       if (start <= end)
1812       {
1813         seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
1814         features[rsize] = new SequenceFeature(null, null, null, start, end,
1815                 "Jalview");
1816         rsize++;
1817       }
1818     }
1819     rseqs = new SequenceI[rsize];
1820     tfeatures = new SequenceFeature[rsize];
1821     System.arraycopy(seqs, 0, rseqs, 0, rsize);
1822     System.arraycopy(features, 0, tfeatures, 0, rsize);
1823     features = tfeatures;
1824     seqs = rseqs;
1825     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
1826             features, true, ap))
1827     {
1828       ap.alignFrame.setShowSeqFeatures(true);
1829       ap.highlightSearchResults(null);
1830     }
1831   }
1832
1833   public void textColour_actionPerformed()
1834   {
1835     SequenceGroup sg = getGroup();
1836     if (sg != null)
1837     {
1838       new TextColourChooser().chooseColour(ap, sg);
1839     }
1840   }
1841
1842   public void colourByStructure(String pdbid)
1843   {
1844     Annotation[] anots = jalview.structure.StructureSelectionManager
1845             .getStructureSelectionManager().colourSequenceFromStructure(
1846                     sequence, pdbid);
1847
1848     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
1849             "Coloured by " + pdbid, anots);
1850
1851     ap.av.alignment.addAnnotation(an);
1852     an.createSequenceMapping(sequence, 0, true);
1853     // an.adjustForAlignment();
1854     ap.av.alignment.setAnnotationIndex(an, 0);
1855
1856     ap.adjustAnnotationHeight();
1857
1858     sequence.addAlignmentAnnotation(an);
1859
1860   }
1861
1862   public void editSequence_actionPerformed(ActionEvent actionEvent)
1863   {
1864     SequenceGroup sg = ap.av.getSelectionGroup();
1865
1866     if (sg != null)
1867     {
1868       if (sequence == null)
1869         sequence = (Sequence) sg.getSequenceAt(0);
1870
1871       EditNameDialog dialog = new EditNameDialog(sequence
1872               .getSequenceAsString(sg.getStartRes(), sg.getEndRes() + 1),
1873               null, "Edit Sequence ", null, "Edit Sequence", ap.alignFrame);
1874
1875       if (dialog.accept)
1876       {
1877         EditCommand editCommand = new EditCommand("Edit Sequences",
1878                 EditCommand.REPLACE, dialog.getName().replace(' ',
1879                         ap.av.getGapCharacter()), sg
1880                         .getSequencesAsArray(ap.av.hiddenRepSequences), sg
1881                         .getStartRes(), sg.getEndRes() + 1, ap.av.alignment);
1882
1883         ap.alignFrame.addHistoryItem(editCommand);
1884
1885         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1886                 .getSequences());
1887       }
1888     }
1889   }
1890
1891 }