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