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