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