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