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