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