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