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