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