Merge branch 'JAL-1445' into develop
[jalview.git] / src / jalview / gui / PopupMenu.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3  * Copyright (C) 2014 The Jalview Authors
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  * The Jalview Authors are detailed in the 'AUTHORS' file.
18  */
19 package jalview.gui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25
26 import javax.swing.*;
27
28 import jalview.analysis.*;
29 import jalview.commands.*;
30 import jalview.datamodel.*;
31 import jalview.io.*;
32 import jalview.schemes.*;
33 import jalview.util.GroupUrlLink;
34 import jalview.util.GroupUrlLink.UrlStringTooLongException;
35 import jalview.util.MessageManager;\r
36 import jalview.util.UrlLink;
37
38 /**
39  * DOCUMENT ME!
40  * 
41  * @author $author$
42  * @version $Revision: 1.118 $
43  */
44 public class PopupMenu extends JPopupMenu
45 {
46   JMenu groupMenu = new JMenu();
47
48   JMenuItem groupName = new JMenuItem();
49
50   protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
51
52   protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
53
54   protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
55
56   protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
57
58   protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
59
60   protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
61
62   protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
63
64   protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
65
66   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
67
68   protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
69
70   protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
71
72   protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
73
74   protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
75   protected JRadioButtonMenuItem RNAInteractionColour = new JRadioButtonMenuItem();
76
77   // protected JRadioButtonMenuItem covariationColour = new
78   // JRadioButtonMenuItem();
79
80   JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
81
82   protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
83
84   AlignmentPanel ap;
85
86   JMenu sequenceMenu = new JMenu();
87
88   JMenuItem sequenceName = new JMenuItem();
89
90   JMenuItem sequenceDetails = new JMenuItem();
91
92   JMenuItem sequenceSelDetails = new JMenuItem();
93
94   SequenceI sequence;
95   JMenuItem createGroupMenuItem = new JMenuItem();
96   JMenuItem unGroupMenuItem = new JMenuItem();
97
98   JMenuItem outline = new JMenuItem();
99
100   JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
101
102   JMenu colourMenu = new JMenu();
103
104   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
105
106   JCheckBoxMenuItem showText = new JCheckBoxMenuItem();
107
108   JCheckBoxMenuItem showColourText = new JCheckBoxMenuItem();
109
110   JCheckBoxMenuItem displayNonconserved = new JCheckBoxMenuItem();
111
112   JMenu editMenu = new JMenu();
113
114   JMenuItem cut = new JMenuItem();
115
116   JMenuItem copy = new JMenuItem();
117
118   JMenuItem upperCase = new JMenuItem();
119
120   JMenuItem lowerCase = new JMenuItem();
121
122   JMenuItem toggle = new JMenuItem();
123
124   JMenu pdbMenu = new JMenu();
125
126   JMenuItem pdbFromFile = new JMenuItem();
127     // JBPNote: Commented these out - Should add these services via the web services menu system.
128     // JMenuItem ContraFold = new JMenuItem();
129   
130     // JMenuItem RNAFold = new JMenuItem();
131   
132   JMenuItem enterPDB = new JMenuItem();
133
134   JMenuItem discoverPDB = new JMenuItem();
135
136   JMenu outputMenu = new JMenu();
137
138   JMenuItem sequenceFeature = new JMenuItem();
139
140   JMenuItem textColour = new JMenuItem();
141
142   JMenu jMenu1 = new JMenu();
143
144   JMenu structureMenu = new JMenu();
145
146   JMenu viewStructureMenu = new JMenu();
147
148   // JMenu colStructureMenu = new JMenu();
149   JMenuItem editSequence = new JMenuItem();
150
151   // JMenuItem annotationMenuItem = new JMenuItem();
152
153   JMenu groupLinksMenu;
154
155   /**
156    * Creates a new PopupMenu object.
157    * 
158    * @param ap
159    *          DOCUMENT ME!
160    * @param seq
161    *          DOCUMENT ME!
162    */
163   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
164   {
165     this(ap, seq, links, null);
166   }
167
168   /**
169    * 
170    * @param ap
171    * @param seq
172    * @param links
173    * @param groupLinks
174    */
175   public PopupMenu(final AlignmentPanel ap, final SequenceI seq,
176           Vector links, Vector groupLinks)
177   {
178     // /////////////////////////////////////////////////////////
179     // If this is activated from the sequence panel, the user may want to
180     // edit or annotate a particular residue. Therefore display the residue menu
181     //
182     // If from the IDPanel, we must display the sequence menu
183     // ////////////////////////////////////////////////////////
184     this.ap = ap;
185     sequence = seq;
186
187     ButtonGroup colours = new ButtonGroup();
188     colours.add(noColourmenuItem);
189     colours.add(clustalColour);
190     colours.add(zappoColour);
191     colours.add(taylorColour);
192     colours.add(hydrophobicityColour);
193     colours.add(helixColour);
194     colours.add(strandColour);
195     colours.add(turnColour);
196     colours.add(buriedColour);
197     colours.add(abovePIDColour);
198     colours.add(userDefinedColour);
199     colours.add(PIDColour);
200     colours.add(BLOSUM62Colour);
201     colours.add(purinePyrimidineColour);
202     colours.add(RNAInteractionColour);
203     // colours.add(covariationColour);
204
205     for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
206     {
207       JMenuItem item = new JMenuItem(
208               jalview.io.FormatAdapter.WRITEABLE_FORMATS[i]);
209
210       item.addActionListener(new java.awt.event.ActionListener()
211       {
212         public void actionPerformed(ActionEvent e)
213         {
214           outputText_actionPerformed(e);
215         }
216       });
217
218       outputMenu.add(item);
219     }
220
221     try
222     {
223       jbInit();
224     } catch (Exception e)
225     {
226       e.printStackTrace();
227     }
228
229     JMenuItem menuItem;
230     if (seq != null)
231     {
232       sequenceMenu.setText(sequence.getName());
233
234       if (seq.getDatasetSequence().getPDBId() != null
235               && seq.getDatasetSequence().getPDBId().size() > 0)
236       {
237         java.util.Enumeration e = seq.getDatasetSequence().getPDBId()
238                 .elements();
239
240         while (e.hasMoreElements())
241         {
242           final PDBEntry pdb = (PDBEntry) e.nextElement();
243
244           menuItem = new JMenuItem();
245           menuItem.setText(pdb.getId());
246           menuItem.addActionListener(new java.awt.event.ActionListener()
247           {
248             public void actionPerformed(ActionEvent e)
249             {
250               // TODO re JAL-860: optionally open dialog or provide a menu entry
251               // allowing user to open just one structure per sequence
252               new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[]
253               { pdb })[0], null, ap);
254               // new PDBViewer(pdb, seqs2, null, ap, AppletFormatAdapter.FILE);
255             }
256
257           });
258           viewStructureMenu.add(menuItem);
259
260           /*
261            * menuItem = new JMenuItem(); menuItem.setText(pdb.getId());
262            * menuItem.addActionListener(new java.awt.event.ActionListener() {
263            * public void actionPerformed(ActionEvent e) {
264            * colourByStructure(pdb.getId()); } });
265            * colStructureMenu.add(menuItem);
266            */
267         }
268       }
269       else
270       {
271         if (ap.av.getAlignment().isNucleotide() == false)
272         {
273           structureMenu.remove(viewStructureMenu);
274         }
275         // structureMenu.remove(colStructureMenu);
276       }
277
278       if (ap.av.getAlignment().isNucleotide() == true)
279       {
280         AlignmentAnnotation[] aa = ap.av.getAlignment()
281                 .getAlignmentAnnotation();
282         for (int i = 0; i < aa.length; i++)
283         {
284           if (aa[i].getRNAStruc() != null)
285           {
286             final String rnastruc = aa[i].getRNAStruc();
287             final String structureLine = aa[i].label;
288             menuItem = new JMenuItem();
289             menuItem.setText(MessageManager.formatMessage("label.2d_rna_structure_line", new String[]{structureLine}));\r
290             menuItem.addActionListener(new java.awt.event.ActionListener()
291             
292             {
293               public void actionPerformed(ActionEvent e)
294               {
295                         //System.out.println("1:"+structureLine);
296                         System.out.println("1:sname"+seq.getName());
297                         System.out.println("2:seq"+seq);
298                 
299                         //System.out.println("3:"+seq.getSequenceAsString());
300                         System.out.println("3:strucseq"+rnastruc);
301                         //System.out.println("4:struc"+seq.getRNA());
302                         System.out.println("5:name"+seq.getName());
303                         System.out.println("6:ap"+ap);
304                         new AppVarna(structureLine, seq, seq.getSequenceAsString(), rnastruc, seq
305                             .getName(), ap);
306                         //new AppVarna(seq.getName(),seq,rnastruc,seq.getRNA(), seq.getName(), ap);
307                         System.out.println("end");
308               }
309             });
310             viewStructureMenu.add(menuItem);
311           }
312         }
313
314         // SequenceFeatures[] test = seq.getSequenceFeatures();
315
316         if (seq.getAnnotation() != null)
317         {
318           AlignmentAnnotation seqAnno[] = seq.getAnnotation();
319           for (int i = 0; i < seqAnno.length; i++)
320           {
321             if (seqAnno[i].getRNAStruc() != null)
322             {
323               final String rnastruc = seqAnno[i].getRNAStruc();
324
325               // TODO: make rnastrucF a bit more nice
326               menuItem = new JMenuItem();
327               menuItem.setText(MessageManager.formatMessage("label.2d_rna_sequence_name", new String[]{seq.getName()}));\r
328               menuItem.addActionListener(new java.awt.event.ActionListener()
329               {
330                 public void actionPerformed(ActionEvent e)
331                 {
332                   // TODO: VARNA does'nt print gaps in the sequence
333                 
334                   new AppVarna(seq.getName() + " structure", seq, seq
335                           .getSequenceAsString(), rnastruc, seq.getName(),
336                           ap);
337                 }
338               });
339               viewStructureMenu.add(menuItem);
340             }
341           }
342         }
343
344       }
345
346       menuItem = new JMenuItem(MessageManager.getString("action.hide_sequences"));\r
347       menuItem.addActionListener(new java.awt.event.ActionListener()
348       {
349         public void actionPerformed(ActionEvent e)
350         {
351           hideSequences(false);
352         }
353       });
354       add(menuItem);
355
356       if (ap.av.getSelectionGroup() != null
357               && ap.av.getSelectionGroup().getSize() > 1)
358       {
359         menuItem = new JMenuItem(MessageManager.formatMessage("label.represent_group_with", new String[]{seq.getName()}));\r
360         menuItem.addActionListener(new java.awt.event.ActionListener()
361         {
362           public void actionPerformed(ActionEvent e)
363           {
364             hideSequences(true);
365           }
366         });
367         sequenceMenu.add(menuItem);
368       }
369
370       if (ap.av.hasHiddenRows())
371       {
372         final int index = ap.av.getAlignment().findIndex(seq);
373
374         if (ap.av.adjustForHiddenSeqs(index)
375                 - ap.av.adjustForHiddenSeqs(index - 1) > 1)
376         {
377           menuItem = new JMenuItem(MessageManager.getString("action.reveal_sequences"));\r
378           menuItem.addActionListener(new ActionListener()
379           {
380             public void actionPerformed(ActionEvent e)
381             {
382               ap.av.showSequence(index);
383               if (ap.overviewPanel != null)
384               {
385                 ap.overviewPanel.updateOverviewImage();
386               }
387             }
388           });
389           add(menuItem);
390         }
391       }
392     }
393     // for the case when no sequences are even visible
394     if (ap.av.hasHiddenRows())
395     {
396       {
397         menuItem = new JMenuItem(MessageManager.getString("action.reveal_all"));\r
398         menuItem.addActionListener(new ActionListener()
399         {
400           public void actionPerformed(ActionEvent e)
401           {
402             ap.av.showAllHiddenSeqs();
403             if (ap.overviewPanel != null)
404             {
405               ap.overviewPanel.updateOverviewImage();
406             }
407           }
408         });
409
410         add(menuItem);
411       }
412
413     }
414
415     SequenceGroup sg = ap.av.getSelectionGroup();
416     boolean isDefinedGroup = (sg!=null) ? ap.av.getAlignment().getGroups().contains(sg) : false;
417
418     if (sg != null && sg.getSize() > 0)
419     {      
420       groupName.setText(MessageManager.formatMessage("label.name_param", new String[]{sg.getName()}));\r
421       groupName.setText(MessageManager.getString("label.edit_name_and_description_current_group"));\r
422
423       if (sg.cs instanceof ZappoColourScheme)
424       {
425         zappoColour.setSelected(true);
426       }
427       else if (sg.cs instanceof TaylorColourScheme)
428       {
429         taylorColour.setSelected(true);
430       }
431       else if (sg.cs instanceof PIDColourScheme)
432       {
433         PIDColour.setSelected(true);
434       }
435       else if (sg.cs instanceof Blosum62ColourScheme)
436       {
437         BLOSUM62Colour.setSelected(true);
438       }
439       else if (sg.cs instanceof UserColourScheme)
440       {
441         userDefinedColour.setSelected(true);
442       }
443       else if (sg.cs instanceof HydrophobicColourScheme)
444       {
445         hydrophobicityColour.setSelected(true);
446       }
447       else if (sg.cs instanceof HelixColourScheme)
448       {
449         helixColour.setSelected(true);
450       }
451       else if (sg.cs instanceof StrandColourScheme)
452       {
453         strandColour.setSelected(true);
454       }
455       else if (sg.cs instanceof TurnColourScheme)
456       {
457         turnColour.setSelected(true);
458       }
459       else if (sg.cs instanceof BuriedColourScheme)
460       {
461         buriedColour.setSelected(true);
462       }
463       else if (sg.cs instanceof ClustalxColourScheme)
464       {
465         clustalColour.setSelected(true);
466       }
467       else if (sg.cs instanceof PurinePyrimidineColourScheme)
468       {
469         purinePyrimidineColour.setSelected(true);
470       }
471       
472    
473       /*
474        * else if (sg.cs instanceof CovariationColourScheme) {
475        * covariationColour.setSelected(true); }
476        */
477       else
478       {
479         noColourmenuItem.setSelected(true);
480       }
481
482       if (sg.cs != null && sg.cs.conservationApplied())
483       {
484         conservationMenuItem.setSelected(true);
485       }
486       displayNonconserved.setSelected(sg.getShowNonconserved());
487       showText.setSelected(sg.getDisplayText());
488       showColourText.setSelected(sg.getColourText());
489       showBoxes.setSelected(sg.getDisplayBoxes());
490       // add any groupURLs to the groupURL submenu and make it visible
491       if (groupLinks != null && groupLinks.size() > 0)
492       {
493         buildGroupURLMenu(sg, groupLinks);
494       }
495       // Add a 'show all structures' for the current selection
496       Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>();
497       SequenceI sqass = null;
498       for (SequenceI sq : ap.av.getSequenceSelection())
499       {
500         Vector<PDBEntry> pes = (Vector<PDBEntry>) sq.getDatasetSequence()
501                 .getPDBId();
502         if (pes != null)
503         {
504           for (PDBEntry pe : pes)
505           {
506             pdbe.put(pe.getId(), pe);
507             if (sqass == null)
508             {
509               sqass = sq;
510             }
511           }
512         }
513       }
514       if (pdbe.size() > 0)
515       {
516         final PDBEntry[] pe = pdbe.values().toArray(
517                 new PDBEntry[pdbe.size()]);
518         final JMenuItem gpdbview;
519         if (pdbe.size() == 1)
520         {
521           structureMenu.add(gpdbview = new JMenuItem(MessageManager.formatMessage("label.view_structure_for", new String[]{sqass.getDisplayId(false)})));\r
522         }
523         else
524         {
525           structureMenu.add(gpdbview = new JMenuItem(MessageManager.formatMessage("label.view_all_structures", new String[]{new Integer(pdbe.size()).toString()})));\r
526         }
527         gpdbview.setToolTipText(MessageManager.getString("label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment"));\r
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(MessageManager.getString("action.edit_new_group"));\r
550     } else {
551       createGroupMenuItem.setVisible(false);
552       unGroupMenuItem.setVisible(true);
553       jMenu1.setText(MessageManager.getString("action.edit_group"));\r
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(MessageManager.getString("action.link"));\r
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(MessageManager.getString("action.group_link"));\r
693     JMenu[] linkMenus = new JMenu[]
694     { null, new JMenu(MessageManager.getString("action.ids")), new JMenu(MessageManager.getString("action.sequences")),\r
695         new JMenu(MessageManager.getString("action.ids_sequences")) }; // three types of url that might be\r
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(MessageManager.getString("action.group_link"));\r
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(MessageManager.formatMessage("label.open_url_param", new String[]{url}));\r
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(MessageManager.formatMessage("label.open_url_seqs_param", new Object[]{urlgenerator.getUrl_prefix(),urlgenerator.getNumberInvolved(urlstub)}));\r
880     // TODO: put in info about what is being sent.\r
881     item.addActionListener(new java.awt.event.ActionListener()
882     {
883       public void actionPerformed(ActionEvent e)
884       {
885         new Thread(new Runnable()
886         {
887
888           public void run()
889           {
890             try
891             {
892               showLink(urlgenerator.constructFrom(urlstub));
893             } catch (UrlStringTooLongException e)
894             {
895             }
896           }
897
898         }).start();
899       }
900     });
901
902     linkMenu.add(item);
903   }
904
905   /**
906    * DOCUMENT ME!
907    * 
908    * @throws Exception
909    *           DOCUMENT ME!
910    */
911   private void jbInit() throws Exception
912   {
913     groupMenu.setText(MessageManager.getString("label.group"));\r
914     groupMenu.setText(MessageManager.getString("label.selection"));\r
915     groupName.setText(MessageManager.getString("label.name"));\r
916     groupName.addActionListener(new java.awt.event.ActionListener()
917     {
918       public void actionPerformed(ActionEvent e)
919       {
920         groupName_actionPerformed();
921       }
922     });
923     sequenceMenu.setText(MessageManager.getString("label.sequence"));\r
924     sequenceName.setText(MessageManager.getString("label.edit_name_description"));\r
925     sequenceName.addActionListener(new java.awt.event.ActionListener()
926     {
927       public void actionPerformed(ActionEvent e)
928       {
929         sequenceName_actionPerformed();
930       }
931     });
932     sequenceDetails.setText(MessageManager.getString("label.sequence_details") + "...");\r
933     sequenceDetails.addActionListener(new java.awt.event.ActionListener()
934     {
935       public void actionPerformed(ActionEvent e)
936       {
937         sequenceDetails_actionPerformed();
938       }
939     });
940     sequenceSelDetails.setText(MessageManager.getString("label.sequence_details") + "...");\r
941     sequenceSelDetails
942             .addActionListener(new java.awt.event.ActionListener()
943             {
944               public void actionPerformed(ActionEvent e)
945               {
946                 sequenceSelectionDetails_actionPerformed();
947               }
948             });
949     PIDColour.setFocusPainted(false);
950     unGroupMenuItem.setText(MessageManager.getString("action.remove_group"));\r
951     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
952     {
953       public void actionPerformed(ActionEvent e)
954       {
955         unGroupMenuItem_actionPerformed();
956       }
957     });
958     createGroupMenuItem.setText(MessageManager.getString("action.create_group"));\r
959     createGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
960     {
961       public void actionPerformed(ActionEvent e)
962       {
963         createGroupMenuItem_actionPerformed();
964       }
965     });
966
967     outline.setText(MessageManager.getString("action.border_colour"));\r
968     outline.addActionListener(new java.awt.event.ActionListener()
969     {
970       public void actionPerformed(ActionEvent e)
971       {
972         outline_actionPerformed();
973       }
974     });
975     nucleotideMenuItem.setText(MessageManager.getString("label.nucleotide"));\r
976     nucleotideMenuItem.addActionListener(new ActionListener()
977     {
978       public void actionPerformed(ActionEvent e)
979       {
980         nucleotideMenuItem_actionPerformed();
981       }
982     });
983     colourMenu.setText(MessageManager.getString("label.group_colour"));\r
984     showBoxes.setText(MessageManager.getString("action.boxes"));\r
985     showBoxes.setState(true);
986     showBoxes.addActionListener(new ActionListener()
987     {
988       public void actionPerformed(ActionEvent e)
989       {
990         showBoxes_actionPerformed();
991       }
992     });
993     showText.setText(MessageManager.getString("action.text"));\r
994     showText.setState(true);
995     showText.addActionListener(new ActionListener()
996     {
997       public void actionPerformed(ActionEvent e)
998       {
999         showText_actionPerformed();
1000       }
1001     });
1002     showColourText.setText(MessageManager.getString("label.colour_text"));\r
1003     showColourText.addActionListener(new ActionListener()
1004     {
1005       public void actionPerformed(ActionEvent e)
1006       {
1007         showColourText_actionPerformed();
1008       }
1009     });
1010     displayNonconserved.setText(MessageManager.getString("label.show_non_conversed"));\r
1011     displayNonconserved.setState(true);
1012     displayNonconserved.addActionListener(new ActionListener()
1013     {
1014       public void actionPerformed(ActionEvent e)
1015       {
1016         showNonconserved_actionPerformed();
1017       }
1018     });
1019     editMenu.setText(MessageManager.getString("action.edit"));\r
1020     cut.setText(MessageManager.getString("action.cut"));\r
1021     cut.addActionListener(new ActionListener()
1022     {
1023       public void actionPerformed(ActionEvent e)
1024       {
1025         cut_actionPerformed();
1026       }
1027     });
1028     upperCase.setText(MessageManager.getString("label.to_upper_case"));\r
1029     upperCase.addActionListener(new ActionListener()
1030     {
1031       public void actionPerformed(ActionEvent e)
1032       {
1033         changeCase(e);
1034       }
1035     });
1036     copy.setText(MessageManager.getString("action.copy"));\r
1037     copy.addActionListener(new ActionListener()
1038     {
1039       public void actionPerformed(ActionEvent e)
1040       {
1041         copy_actionPerformed();
1042       }
1043     });
1044     lowerCase.setText(MessageManager.getString("label.to_lower_case"));\r
1045     lowerCase.addActionListener(new ActionListener()
1046     {
1047       public void actionPerformed(ActionEvent e)
1048       {
1049         changeCase(e);
1050       }
1051     });
1052     toggle.setText(MessageManager.getString("label.toggle_case"));\r
1053     toggle.addActionListener(new ActionListener()
1054     {
1055       public void actionPerformed(ActionEvent e)
1056       {
1057         changeCase(e);
1058       }
1059     });
1060     pdbMenu.setText(MessageManager.getString("label.associate_structure_with_sequence"));\r
1061     pdbFromFile.setText(MessageManager.getString("label.from_file"));\r
1062     pdbFromFile.addActionListener(new ActionListener()
1063     {
1064       public void actionPerformed(ActionEvent e)
1065       {
1066         pdbFromFile_actionPerformed();
1067       }
1068     });
1069 //    RNAFold.setText("From RNA Fold with predict2D");
1070 //    RNAFold.addActionListener(new ActionListener()
1071 //    {
1072 //      public void actionPerformed(ActionEvent e)
1073 //      {
1074 //        try {
1075 //                      RNAFold_actionPerformed();
1076 //              } catch (Exception e1) {
1077 //                      // TODO Auto-generated catch block
1078 //                      e1.printStackTrace();
1079 //              }
1080 //      }   
1081 //    });
1082 //    ContraFold.setText("From Contra Fold with predict2D");
1083 //    ContraFold.addActionListener(new ActionListener()
1084 //    {
1085 //      public void actionPerformed(ActionEvent e)
1086 //      {
1087 //        try {
1088 //                      ContraFold_actionPerformed();
1089 //              } catch (Exception e1) {
1090 //                      // TODO Auto-generated catch block
1091 //                      e1.printStackTrace();
1092 //              }
1093 //      }   
1094 //    });
1095     enterPDB.setText(MessageManager.getString("label.enter_pdb_id"));\r
1096     enterPDB.addActionListener(new ActionListener()
1097     {
1098       public void actionPerformed(ActionEvent e)
1099       {
1100         enterPDB_actionPerformed();
1101       }
1102     });
1103     discoverPDB.setText(MessageManager.getString("label.discover_pdb_ids"));\r
1104     discoverPDB.addActionListener(new ActionListener()
1105     {
1106       public void actionPerformed(ActionEvent e)
1107       {
1108         discoverPDB_actionPerformed();
1109       }
1110     });
1111     outputMenu.setText(MessageManager.getString("label.out_to_textbox") + "...");\r
1112     sequenceFeature.setText(MessageManager.getString("label.create_sequence_feature"));\r
1113     sequenceFeature.addActionListener(new ActionListener()
1114     {
1115       public void actionPerformed(ActionEvent e)
1116       {
1117         sequenceFeature_actionPerformed();
1118       }
1119     });
1120     textColour.setText(MessageManager.getString("label.text_colour"));\r
1121     textColour.addActionListener(new ActionListener()
1122     {
1123       public void actionPerformed(ActionEvent e)
1124       {
1125         textColour_actionPerformed();
1126       }
1127     });
1128     jMenu1.setText(MessageManager.getString("label.group"));\r
1129     structureMenu.setText(MessageManager.getString("label.structure"));\r
1130     viewStructureMenu.setText(MessageManager.getString("label.view_structure"));\r
1131     // colStructureMenu.setText("Colour By Structure");
1132     editSequence.setText(MessageManager.getString("label.edit_sequence") + "...");\r
1133     editSequence.addActionListener(new ActionListener()
1134     {
1135       public void actionPerformed(ActionEvent actionEvent)
1136       {
1137         editSequence_actionPerformed(actionEvent);
1138       }
1139     });
1140
1141     /*
1142      * annotationMenuItem.setText("By Annotation");
1143      * annotationMenuItem.addActionListener(new ActionListener() { public void
1144      * actionPerformed(ActionEvent actionEvent) {
1145      * annotationMenuItem_actionPerformed(actionEvent); } });
1146      */
1147     groupMenu.add(sequenceSelDetails);
1148     add(groupMenu);
1149     add(sequenceMenu);
1150     this.add(structureMenu);
1151     groupMenu.add(editMenu);
1152     groupMenu.add(outputMenu);
1153     groupMenu.add(sequenceFeature);
1154     groupMenu.add(createGroupMenuItem);
1155     groupMenu.add(unGroupMenuItem);
1156     groupMenu.add(jMenu1);
1157     sequenceMenu.add(sequenceName);
1158     sequenceMenu.add(sequenceDetails);
1159     colourMenu.add(textColour);
1160     colourMenu.add(noColourmenuItem);
1161     colourMenu.add(clustalColour);
1162     colourMenu.add(BLOSUM62Colour);
1163     colourMenu.add(PIDColour);
1164     colourMenu.add(zappoColour);
1165     colourMenu.add(taylorColour);
1166     colourMenu.add(hydrophobicityColour);
1167     colourMenu.add(helixColour);
1168     colourMenu.add(strandColour);
1169     colourMenu.add(turnColour);
1170     colourMenu.add(buriedColour);
1171     colourMenu.add(nucleotideMenuItem);
1172     if (ap.getAlignment().isNucleotide()) {
1173         // JBPNote - commented since the colourscheme isn't functional
1174         //  colourMenu.add(RNAInteractionColour);
1175         colourMenu.add(purinePyrimidineColour);
1176     }
1177     // colourMenu.add(covariationColour);
1178     colourMenu.add(userDefinedColour);
1179
1180     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
1181     {
1182       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
1183               .getUserColourSchemes().keys();
1184
1185       while (userColours.hasMoreElements())
1186       {
1187         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
1188         item.addActionListener(new ActionListener()
1189         {
1190           public void actionPerformed(ActionEvent evt)
1191           {
1192             userDefinedColour_actionPerformed(evt);
1193           }
1194         });
1195         colourMenu.add(item);
1196       }
1197     }
1198
1199     colourMenu.addSeparator();
1200     colourMenu.add(abovePIDColour);
1201     colourMenu.add(conservationMenuItem);
1202     // colourMenu.add(annotationMenuItem);
1203     editMenu.add(copy);
1204     editMenu.add(cut);
1205     editMenu.add(editSequence);
1206     editMenu.add(upperCase);
1207     editMenu.add(lowerCase);
1208     editMenu.add(toggle);
1209     pdbMenu.add(pdbFromFile);
1210     // JBPNote: These shouldn't be added here - should appear in a generic 'apply web service to this sequence menu'
1211     //    pdbMenu.add(RNAFold);
1212     //    pdbMenu.add(ContraFold);
1213     pdbMenu.add(enterPDB);
1214     pdbMenu.add(discoverPDB);
1215     jMenu1.add(groupName);
1216     jMenu1.add(colourMenu);
1217     jMenu1.add(showBoxes);
1218     jMenu1.add(showText);
1219     jMenu1.add(showColourText);
1220     jMenu1.add(outline);
1221     jMenu1.add(displayNonconserved);
1222     structureMenu.add(pdbMenu);
1223     structureMenu.add(viewStructureMenu);
1224     // structureMenu.add(colStructureMenu);
1225     noColourmenuItem.setText(MessageManager.getString("label.none"));\r
1226     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
1227     {
1228       public void actionPerformed(ActionEvent e)
1229       {
1230         noColourmenuItem_actionPerformed();
1231       }
1232     });
1233
1234     clustalColour.setText(MessageManager.getString("label.clustalx_colours"));\r
1235     clustalColour.addActionListener(new java.awt.event.ActionListener()
1236     {
1237       public void actionPerformed(ActionEvent e)
1238       {
1239         clustalColour_actionPerformed();
1240       }
1241     });
1242     zappoColour.setText(MessageManager.getString("label.zappo"));\r
1243     zappoColour.addActionListener(new java.awt.event.ActionListener()
1244     {
1245       public void actionPerformed(ActionEvent e)
1246       {
1247         zappoColour_actionPerformed();
1248       }
1249     });
1250     taylorColour.setText(MessageManager.getString("label.taylor"));\r
1251     taylorColour.addActionListener(new java.awt.event.ActionListener()
1252     {
1253       public void actionPerformed(ActionEvent e)
1254       {
1255         taylorColour_actionPerformed();
1256       }
1257     });
1258     hydrophobicityColour.setText(MessageManager.getString("label.hydrophobicity"));\r
1259     hydrophobicityColour
1260             .addActionListener(new java.awt.event.ActionListener()
1261             {
1262               public void actionPerformed(ActionEvent e)
1263               {
1264                 hydrophobicityColour_actionPerformed();
1265               }
1266             });
1267     helixColour.setText(MessageManager.getString("label.helix_propensity"));\r
1268     helixColour.addActionListener(new java.awt.event.ActionListener()
1269     {
1270       public void actionPerformed(ActionEvent e)
1271       {
1272         helixColour_actionPerformed();
1273       }
1274     });
1275     strandColour.setText(MessageManager.getString("label.strand_propensity"));\r
1276     strandColour.addActionListener(new java.awt.event.ActionListener()
1277     {
1278       public void actionPerformed(ActionEvent e)
1279       {
1280         strandColour_actionPerformed();
1281       }
1282     });
1283     turnColour.setText(MessageManager.getString("label.turn_propensity"));\r
1284     turnColour.addActionListener(new java.awt.event.ActionListener()
1285     {
1286       public void actionPerformed(ActionEvent e)
1287       {
1288         turnColour_actionPerformed();
1289       }
1290     });
1291     buriedColour.setText(MessageManager.getString("label.buried_index"));\r
1292     buriedColour.addActionListener(new java.awt.event.ActionListener()
1293     {
1294       public void actionPerformed(ActionEvent e)
1295       {
1296         buriedColour_actionPerformed();
1297       }
1298     });
1299     abovePIDColour.setText(MessageManager.getString("label.above_identity_percentage"));\r
1300     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
1301     {
1302       public void actionPerformed(ActionEvent e)
1303       {
1304         abovePIDColour_actionPerformed();
1305       }
1306     });
1307     userDefinedColour.setText(MessageManager.getString("action.user_defined"));\r
1308     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
1309     {
1310       public void actionPerformed(ActionEvent e)
1311       {
1312         userDefinedColour_actionPerformed(e);
1313       }
1314     });
1315     PIDColour.setText(MessageManager.getString("label.percentage_identity"));\r
1316     PIDColour.addActionListener(new java.awt.event.ActionListener()
1317     {
1318       public void actionPerformed(ActionEvent e)
1319       {
1320         PIDColour_actionPerformed();
1321       }
1322     });
1323     BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));\r
1324     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
1325     {
1326       public void actionPerformed(ActionEvent e)
1327       {
1328         BLOSUM62Colour_actionPerformed();
1329       }
1330     });
1331     purinePyrimidineColour.setText(MessageManager.getString("label.purine_pyrimidine"));\r
1332     purinePyrimidineColour
1333             .addActionListener(new java.awt.event.ActionListener()
1334             {
1335               public void actionPerformed(ActionEvent e)
1336               {
1337                 purinePyrimidineColour_actionPerformed();
1338               }
1339             });
1340     
1341    
1342     /*
1343      * covariationColour.addActionListener(new java.awt.event.ActionListener() {
1344      * public void actionPerformed(ActionEvent e) {
1345      * covariationColour_actionPerformed(); } });
1346      */
1347
1348     conservationMenuItem.setText(MessageManager.getString("label.conservation"));\r
1349     conservationMenuItem
1350             .addActionListener(new java.awt.event.ActionListener()
1351             {
1352               public void actionPerformed(ActionEvent e)
1353               {
1354                 conservationMenuItem_actionPerformed();
1355               }
1356             });
1357   }
1358
1359   protected void sequenceSelectionDetails_actionPerformed()
1360   {
1361     createSequenceDetailsReport(ap.av.getSequenceSelection());
1362   }
1363
1364   protected void sequenceDetails_actionPerformed()
1365   {
1366     createSequenceDetailsReport(new SequenceI[]
1367     { sequence });
1368   }
1369
1370   public void createSequenceDetailsReport(SequenceI[] sequences)
1371   {
1372     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
1373     StringBuffer contents = new StringBuffer();
1374     for (SequenceI seq : sequences)
1375     {
1376       contents.append("<p><h2>" + MessageManager.formatMessage("label.create_sequence_details_report_annotation_for", new String[]{seq.getDisplayId(true)})\r
1377               + "</h2></p><p>");
1378       new SequenceAnnotationReport(null)
1379               .createSequenceAnnotationReport(
1380                       contents,
1381                       seq,
1382                       true,
1383                       true,
1384                       false,
1385                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
1386                               : null);
1387       contents.append("</p>");
1388     }
1389     cap.setText("<html>" + contents.toString() + "</html>");
1390
1391     Desktop.instance.addInternalFrame(cap, MessageManager.formatMessage("label.sequece_details_for", (sequences.length == 1 ? new String[]{sequences[0].getDisplayId(true)}: new String[]{MessageManager.getString("label.selection")}))\r
1392                 ,500, 400);\r
1393
1394   }
1395
1396   protected void showNonconserved_actionPerformed()
1397   {
1398     getGroup().setShowNonconserved(displayNonconserved.isSelected());
1399     refresh();
1400   }
1401
1402   /**
1403    * call to refresh view after settings change
1404    */
1405   void refresh()
1406   {
1407     ap.updateAnnotation();
1408     ap.paintAlignment(true);
1409
1410     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
1411   }
1412
1413   /**
1414    * DOCUMENT ME!
1415    * 
1416    * @param e
1417    *          DOCUMENT ME!
1418    */
1419   protected void clustalColour_actionPerformed()
1420   {
1421     SequenceGroup sg = getGroup();
1422     sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
1423     refresh();
1424   }
1425
1426   /**
1427    * DOCUMENT ME!
1428    * 
1429    * @param e
1430    *          DOCUMENT ME!
1431    */
1432   protected void zappoColour_actionPerformed()
1433   {
1434     getGroup().cs = new ZappoColourScheme();
1435     refresh();
1436   }
1437
1438   /**
1439    * DOCUMENT ME!
1440    * 
1441    * @param e
1442    *          DOCUMENT ME!
1443    */
1444   protected void taylorColour_actionPerformed()
1445   {
1446     getGroup().cs = new TaylorColourScheme();
1447     refresh();
1448   }
1449
1450   /**
1451    * DOCUMENT ME!
1452    * 
1453    * @param e
1454    *          DOCUMENT ME!
1455    */
1456   protected void hydrophobicityColour_actionPerformed()
1457   {
1458     getGroup().cs = new HydrophobicColourScheme();
1459     refresh();
1460   }
1461
1462   /**
1463    * DOCUMENT ME!
1464    * 
1465    * @param e
1466    *          DOCUMENT ME!
1467    */
1468   protected void helixColour_actionPerformed()
1469   {
1470     getGroup().cs = new HelixColourScheme();
1471     refresh();
1472   }
1473
1474   /**
1475    * DOCUMENT ME!
1476    * 
1477    * @param e
1478    *          DOCUMENT ME!
1479    */
1480   protected void strandColour_actionPerformed()
1481   {
1482     getGroup().cs = new StrandColourScheme();
1483     refresh();
1484   }
1485
1486   /**
1487    * DOCUMENT ME!
1488    * 
1489    * @param e
1490    *          DOCUMENT ME!
1491    */
1492   protected void turnColour_actionPerformed()
1493   {
1494     getGroup().cs = new TurnColourScheme();
1495     refresh();
1496   }
1497
1498   /**
1499    * DOCUMENT ME!
1500    * 
1501    * @param e
1502    *          DOCUMENT ME!
1503    */
1504   protected void buriedColour_actionPerformed()
1505   {
1506     getGroup().cs = new BuriedColourScheme();
1507     refresh();
1508   }
1509
1510   /**
1511    * DOCUMENT ME!
1512    * 
1513    * @param e
1514    *          DOCUMENT ME!
1515    */
1516   public void nucleotideMenuItem_actionPerformed()
1517   {
1518     getGroup().cs = new NucleotideColourScheme();
1519     refresh();
1520   }
1521
1522   protected void purinePyrimidineColour_actionPerformed()
1523   {
1524     getGroup().cs = new PurinePyrimidineColourScheme();
1525     refresh();
1526   }
1527
1528
1529   /*
1530    * protected void covariationColour_actionPerformed() { getGroup().cs = new
1531    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
1532    */
1533   /**
1534    * DOCUMENT ME!
1535    * 
1536    * @param e
1537    *          DOCUMENT ME!
1538    */
1539   protected void abovePIDColour_actionPerformed()
1540   {
1541     SequenceGroup sg = getGroup();
1542     if (sg.cs == null)
1543     {
1544       return;
1545     }
1546
1547     if (abovePIDColour.isSelected())
1548     {
1549       sg.cs.setConsensus(AAFrequency.calculate(
1550               sg.getSequences(ap.av.getHiddenRepSequences()),
1551               sg.getStartRes(), sg.getEndRes() + 1));
1552
1553       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1554               .getName());
1555
1556       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1557
1558       SliderPanel.showPIDSlider();
1559     }
1560     else
1561     // remove PIDColouring
1562     {
1563       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1564     }
1565
1566     refresh();
1567   }
1568
1569   /**
1570    * DOCUMENT ME!
1571    * 
1572    * @param e
1573    *          DOCUMENT ME!
1574    */
1575   protected void userDefinedColour_actionPerformed(ActionEvent e)
1576   {
1577     SequenceGroup sg = getGroup();
1578
1579     if (e.getSource().equals(userDefinedColour))\r
1580     {
1581       new UserDefinedColours(ap, sg);
1582     }
1583     else
1584     {
1585       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1586               .getUserColourSchemes().get(e.getActionCommand());
1587
1588       sg.cs = udc;
1589     }
1590     refresh();
1591   }
1592
1593   /**
1594    * DOCUMENT ME!
1595    * 
1596    * @param e
1597    *          DOCUMENT ME!
1598    */
1599   protected void PIDColour_actionPerformed()
1600   {
1601     SequenceGroup sg = getGroup();
1602     sg.cs = new PIDColourScheme();
1603     sg.cs.setConsensus(AAFrequency.calculate(
1604             sg.getSequences(ap.av.getHiddenRepSequences()),
1605             sg.getStartRes(), sg.getEndRes() + 1));
1606     refresh();
1607   }
1608
1609   /**
1610    * DOCUMENT ME!
1611    * 
1612    * @param e
1613    *          DOCUMENT ME!
1614    */
1615   protected void BLOSUM62Colour_actionPerformed()
1616   {
1617     SequenceGroup sg = getGroup();
1618
1619     sg.cs = new Blosum62ColourScheme();
1620
1621     sg.cs.setConsensus(AAFrequency.calculate(
1622             sg.getSequences(ap.av.getHiddenRepSequences()),
1623             sg.getStartRes(), sg.getEndRes() + 1));
1624
1625     refresh();
1626   }
1627
1628   /**
1629    * DOCUMENT ME!
1630    * 
1631    * @param e
1632    *          DOCUMENT ME!
1633    */
1634   protected void noColourmenuItem_actionPerformed()
1635   {
1636     getGroup().cs = null;
1637     refresh();
1638   }
1639
1640   /**
1641    * DOCUMENT ME!
1642    * 
1643    * @param e
1644    *          DOCUMENT ME!
1645    */
1646   protected void conservationMenuItem_actionPerformed()
1647   {
1648     SequenceGroup sg = getGroup();
1649     if (sg.cs == null)
1650     {
1651       return;
1652     }
1653
1654     if (conservationMenuItem.isSelected())
1655     {
1656     // JBPNote: Conservation name shouldn't be i18n translated
1657       Conservation c = new Conservation("Group",
1658               ResidueProperties.propHash, 3, sg.getSequences(ap.av
1659                       .getHiddenRepSequences()), sg.getStartRes(),
1660               sg.getEndRes() + 1);
1661
1662       c.calculate();
1663       c.verdict(false, ap.av.getConsPercGaps());
1664
1665       sg.cs.setConservation(c);
1666
1667       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1668       SliderPanel.showConservationSlider();
1669     }
1670     else
1671     // remove ConservationColouring
1672     {
1673       sg.cs.setConservation(null);
1674     }
1675
1676     refresh();
1677   }
1678
1679   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1680   {
1681     SequenceGroup sg = getGroup();
1682     if (sg == null)
1683     {
1684       return;
1685     }
1686
1687     AnnotationColourGradient acg = new AnnotationColourGradient(
1688             sequence.getAnnotation()[0], null,
1689             AnnotationColourGradient.NO_THRESHOLD);
1690
1691     acg.setPredefinedColours(true);
1692     sg.cs = acg;
1693
1694     refresh();
1695   }
1696
1697   /**
1698    * DOCUMENT ME!
1699    * 
1700    * @param e
1701    *          DOCUMENT ME!
1702    */
1703   protected void groupName_actionPerformed()
1704   {
1705
1706     SequenceGroup sg = getGroup();
1707     EditNameDialog dialog = new EditNameDialog(sg.getName(),
1708             sg.getDescription(), "       " + MessageManager.getString("label.group_name") + " ",\r
1709             MessageManager.getString("label.group_description") + " ", MessageManager.getString("label.edit_group_name_description"),\r
1710             ap.alignFrame);
1711
1712     if (!dialog.accept)
1713     {
1714       return;
1715     }
1716
1717     sg.setName(dialog.getName());
1718     sg.setDescription(dialog.getDescription());
1719     refresh();
1720   }
1721
1722   /**
1723    * Get selection group - adding it to the alignment if necessary.
1724    * 
1725    * @return sequence group to operate on
1726    */
1727   SequenceGroup getGroup()
1728   {
1729     SequenceGroup sg = ap.av.getSelectionGroup();
1730     // this method won't add a new group if it already exists
1731     if (sg != null)
1732     {
1733       ap.av.getAlignment().addGroup(sg);
1734     }
1735
1736     return sg;
1737   }
1738
1739   /**
1740    * DOCUMENT ME!
1741    * 
1742    * @param e
1743    *          DOCUMENT ME!
1744    */
1745   void sequenceName_actionPerformed()
1746   {
1747     EditNameDialog dialog = new EditNameDialog(sequence.getName(),
1748             sequence.getDescription(), "       " + MessageManager.getString("label.sequence_name") + " ",\r
1749             MessageManager.getString("label.sequence_description") + " ", MessageManager.getString("label.edit_sequence_name_description"),\r
1750             ap.alignFrame);
1751
1752     if (!dialog.accept)
1753     {
1754       return;
1755     }
1756
1757     if (dialog.getName() != null)
1758     {
1759       if (dialog.getName().indexOf(" ") > -1)
1760       {
1761         JOptionPane.showMessageDialog(ap,
1762                 MessageManager.getString("label.spaces_converted_to_backslashes"),\r
1763                 MessageManager.getString("label.no_spaces_allowed_sequence_name"),\r
1764                 JOptionPane.WARNING_MESSAGE);
1765       }
1766
1767       sequence.setName(dialog.getName().replace(' ', '_'));
1768       ap.paintAlignment(false);
1769     }
1770
1771     sequence.setDescription(dialog.getDescription());
1772
1773     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1774             .getSequences());
1775
1776   }
1777
1778   /**
1779    * DOCUMENT ME!
1780    * 
1781    * @param e
1782    *          DOCUMENT ME!
1783    */
1784   void unGroupMenuItem_actionPerformed()
1785   {
1786     SequenceGroup sg = ap.av.getSelectionGroup();
1787     ap.av.getAlignment().deleteGroup(sg);
1788     ap.av.setSelectionGroup(null);
1789     refresh();
1790   }
1791   void createGroupMenuItem_actionPerformed()
1792   {
1793     getGroup(); // implicitly creates group - note - should apply defaults / use standard alignment window logic for this
1794     refresh();
1795   }
1796
1797   /**
1798    * DOCUMENT ME!
1799    * 
1800    * @param e
1801    *          DOCUMENT ME!
1802    */
1803   protected void outline_actionPerformed()
1804   {
1805     SequenceGroup sg = getGroup();
1806     Color col = JColorChooser.showDialog(this, MessageManager.getString("label.select_outline_colour"),\r
1807             Color.BLUE);
1808
1809     if (col != null)
1810     {
1811       sg.setOutlineColour(col);
1812     }
1813
1814     refresh();
1815   }
1816
1817   /**
1818    * DOCUMENT ME!
1819    * 
1820    * @param e
1821    *          DOCUMENT ME!
1822    */
1823   public void showBoxes_actionPerformed()
1824   {
1825     getGroup().setDisplayBoxes(showBoxes.isSelected());
1826     refresh();
1827   }
1828
1829   /**
1830    * DOCUMENT ME!
1831    * 
1832    * @param e
1833    *          DOCUMENT ME!
1834    */
1835   public void showText_actionPerformed()
1836   {
1837     getGroup().setDisplayText(showText.isSelected());
1838     refresh();
1839   }
1840
1841   /**
1842    * DOCUMENT ME!
1843    * 
1844    * @param e
1845    *          DOCUMENT ME!
1846    */
1847   public void showColourText_actionPerformed()
1848   {
1849     getGroup().setColourText(showColourText.isSelected());
1850     refresh();
1851   }
1852
1853   public void showLink(String url)
1854   {
1855     try
1856     {
1857       jalview.util.BrowserLauncher.openURL(url);
1858     } catch (Exception ex)
1859     {
1860       JOptionPane
1861               .showInternalMessageDialog(
1862                       Desktop.desktop,
1863                       MessageManager.getString("label.web_browser_not_found_unix"),\r
1864                       MessageManager.getString("label.web_browser_not_found"), JOptionPane.WARNING_MESSAGE);\r
1865
1866       ex.printStackTrace();
1867     }
1868   }
1869
1870   void hideSequences(boolean representGroup)
1871   {
1872     SequenceGroup sg = ap.av.getSelectionGroup();
1873     if (sg == null || sg.getSize() < 1)
1874     {
1875       ap.av.hideSequence(new SequenceI[]
1876       { sequence });
1877       return;
1878     }
1879
1880     ap.av.setSelectionGroup(null);
1881
1882     if (representGroup)
1883     {
1884       ap.av.hideRepSequences(sequence, sg);
1885
1886       return;
1887     }
1888
1889     int gsize = sg.getSize();
1890     SequenceI[] hseqs;
1891
1892     hseqs = new SequenceI[gsize];
1893
1894     int index = 0;
1895     for (int i = 0; i < gsize; i++)
1896     {
1897       hseqs[index++] = sg.getSequenceAt(i);
1898     }
1899
1900     ap.av.hideSequence(hseqs);
1901     // refresh(); TODO: ? needed ?
1902     ap.av.sendSelection();
1903   }
1904
1905   public void copy_actionPerformed()
1906   {
1907     ap.alignFrame.copy_actionPerformed(null);
1908   }
1909
1910   public void cut_actionPerformed()
1911   {
1912     ap.alignFrame.cut_actionPerformed(null);
1913   }
1914
1915   void changeCase(ActionEvent e)
1916   {
1917     Object source = e.getSource();
1918     SequenceGroup sg = ap.av.getSelectionGroup();
1919
1920     if (sg != null)
1921     {
1922       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1923               sg.getEndRes() + 1);
1924
1925       String description;
1926       int caseChange;
1927
1928       if (source == toggle)
1929       {
1930         description = MessageManager.getString("label.toggle_case");\r
1931         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1932       }
1933       else if (source == upperCase)
1934       {
1935         description = MessageManager.getString("label.to_upper_case");\r
1936         caseChange = ChangeCaseCommand.TO_UPPER;
1937       }
1938       else
1939       {
1940         description = MessageManager.getString("label.to_lower_case");\r
1941         caseChange = ChangeCaseCommand.TO_LOWER;
1942       }
1943
1944       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
1945               sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
1946               startEnd, caseChange);
1947
1948       ap.alignFrame.addHistoryItem(caseCommand);
1949
1950       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1951               .getSequences());
1952
1953     }
1954   }
1955
1956   public void outputText_actionPerformed(ActionEvent e)
1957   {
1958     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1959     cap.setForInput(null);
1960     Desktop.addInternalFrame(cap,
1961             MessageManager.formatMessage("label.alignment_output_command", new String[]{e.getActionCommand()}), 600, 500);\r
1962
1963     String[] omitHidden = null;
1964
1965     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1966     // or we simply trust the user wants
1967     // wysiwig behaviour
1968     SequenceGroup sg = ap.av.getSelectionGroup();
1969     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1970     omitHidden = ap.av.getViewAsString(true);
1971     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1972     AlignmentAnnotation[] nala = ap.av.getAlignment()
1973             .getAlignmentAnnotation();
1974     if (nala != null)
1975     {
1976       for (int i = 0; i < nala.length; i++)
1977       {
1978         AlignmentAnnotation na = nala[i];
1979         oal.addAnnotation(na);
1980       }
1981     }
1982     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1983             oal, omitHidden, csel, sg));
1984     oal = null;
1985   }
1986
1987   public void pdbFromFile_actionPerformed()
1988   {
1989     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1990             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1991     chooser.setFileView(new jalview.io.JalviewFileView());
1992     chooser.setDialogTitle(MessageManager.formatMessage("label.select_pdb_file_for", new String[]{sequence.getDisplayId(false)}));\r
1993     chooser.setToolTipText(MessageManager.formatMessage("label.load_pdb_file_associate_with_sequence", new String[]{new Integer(sequence.getDisplayId(false)).toString()}));\r
1994
1995     int value = chooser.showOpenDialog(null);
1996
1997     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1998     {
1999       String choice = chooser.getSelectedFile().getPath();
2000       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2001       new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
2002               jalview.io.AppletFormatAdapter.FILE, sequence, true);
2003     }
2004
2005   }
2006     // JBNote: commented out - these won't be instantiated here...!  
2007 //  public void RNAFold_actionPerformed() throws Exception
2008 //  {
2009 //        Predict2D P2D = new Predict2D();
2010 //        P2D.getStructure2DFromRNAFold("toto");
2011 //  }
2012 //  
2013 //  public void ContraFold_actionPerformed() throws Exception
2014 //  {
2015 //        Predict2D P2D = new Predict2D();
2016 //        P2D.getStructure2DFromContraFold("toto");
2017 //  }
2018   public void enterPDB_actionPerformed()
2019   {
2020     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
2021             MessageManager.getString("label.enter_pdb_id"), MessageManager.getString("label.enter_pdb_id"), JOptionPane.QUESTION_MESSAGE);\r
2022
2023     if (id != null && id.length() > 0)
2024     {
2025       PDBEntry entry = new PDBEntry();
2026       entry.setId(id.toUpperCase());
2027       sequence.getDatasetSequence().addPDBId(entry);
2028     }
2029   }
2030
2031   public void discoverPDB_actionPerformed()
2032   {
2033
2034     final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
2035     { sequence }
2036             : ap.av.getSequenceSelection());
2037     Thread discpdb = new Thread(new Runnable()
2038     {
2039       public void run()
2040       {
2041
2042         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
2043                 .fetchDBRefs(false);
2044       }
2045
2046     });
2047     discpdb.start();
2048   }
2049
2050   public void sequenceFeature_actionPerformed()
2051   {
2052     SequenceGroup sg = ap.av.getSelectionGroup();
2053     if (sg == null)
2054     {
2055       return;
2056     }
2057
2058     int rsize = 0, gSize = sg.getSize();
2059     SequenceI[] rseqs, seqs = new SequenceI[gSize];
2060     SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
2061
2062     for (int i = 0; i < gSize; i++)
2063     {
2064       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
2065       int end = sg.findEndRes(sg.getSequenceAt(i));
2066       if (start <= end)
2067       {
2068         seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
2069         features[rsize] = new SequenceFeature(null, null, null, start, end,
2070                 "Jalview");
2071         rsize++;
2072       }
2073     }
2074     rseqs = new SequenceI[rsize];
2075     tfeatures = new SequenceFeature[rsize];
2076     System.arraycopy(seqs, 0, rseqs, 0, rsize);
2077     System.arraycopy(features, 0, tfeatures, 0, rsize);
2078     features = tfeatures;
2079     seqs = rseqs;
2080     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
2081             features, true, ap))
2082     {
2083       ap.alignFrame.setShowSeqFeatures(true);
2084       ap.highlightSearchResults(null);
2085     }
2086   }
2087
2088   public void textColour_actionPerformed()
2089   {
2090     SequenceGroup sg = getGroup();
2091     if (sg != null)
2092     {
2093       new TextColourChooser().chooseColour(ap, sg);
2094     }
2095   }
2096
2097   public void colourByStructure(String pdbid)
2098   {
2099     Annotation[] anots = ap.av.getStructureSelectionManager()
2100             .colourSequenceFromStructure(sequence, pdbid);
2101
2102     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
2103             "Coloured by " + pdbid, anots);
2104
2105     ap.av.getAlignment().addAnnotation(an);
2106     an.createSequenceMapping(sequence, 0, true);
2107     // an.adjustForAlignment();
2108     ap.av.getAlignment().setAnnotationIndex(an, 0);
2109
2110     ap.adjustAnnotationHeight();
2111
2112     sequence.addAlignmentAnnotation(an);
2113
2114   }
2115
2116   public void editSequence_actionPerformed(ActionEvent actionEvent)
2117   {
2118     SequenceGroup sg = ap.av.getSelectionGroup();
2119
2120     if (sg != null)
2121     {
2122       if (sequence == null)
2123         sequence = (Sequence) sg.getSequenceAt(0);
2124
2125       EditNameDialog dialog = new EditNameDialog(
2126               sequence.getSequenceAsString(sg.getStartRes(),
2127                       sg.getEndRes() + 1), null, MessageManager.getString("label.edit_sequence"), null,\r
2128                       MessageManager.getString("label.edit_sequence"), ap.alignFrame);\r
2129
2130       if (dialog.accept)
2131       {
2132         EditCommand editCommand = new EditCommand(MessageManager.getString("label.edit_sequences"),\r
2133                 EditCommand.REPLACE, dialog.getName().replace(' ',
2134                         ap.av.getGapCharacter()),
2135                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
2136                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
2137
2138         ap.alignFrame.addHistoryItem(editCommand);
2139
2140         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2141                 .getSequences());
2142       }
2143     }
2144   }
2145
2146 }