JAL-1503 update version in GPL header
[jalview.git] / src / jalview / gui / PopupMenu.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
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>(),reppdb=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           reppdb.put(pes.get(0).getId(),pes.get(0));
484           for (PDBEntry pe : pes)
485           {
486             pdbe.put(pe.getId(), pe);
487             if (sqass == null)
488             {
489               sqass = sq;
490             }
491           }
492         }
493       }
494       if (pdbe.size() > 0)
495       {
496         final PDBEntry[] pe = pdbe.values().toArray(
497                 new PDBEntry[pdbe.size()]),pr = reppdb.values().toArray(
498                         new PDBEntry[reppdb.size()]);
499         final JMenuItem gpdbview,rpdbview;
500         if (pdbe.size() == 1)
501         {
502           structureMenu.add(gpdbview = new JMenuItem(MessageManager.formatMessage("label.view_structure_for", new String[]{sqass.getDisplayId(false)})));\r
503         }
504         else
505         {
506           structureMenu.add(gpdbview = new JMenuItem(MessageManager.formatMessage("label.view_all_structures", new String[]{new Integer(pdbe.size()).toString()})));          \r
507         }
508         gpdbview.setToolTipText(MessageManager.getString("label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment"));\r
509         gpdbview.addActionListener(new ActionListener()
510         {
511
512           @Override
513           public void actionPerformed(ActionEvent e)
514           {
515             new AppJmol(ap, pe, ap.av.collateForPDB(pe));
516           }
517         });
518         if (reppdb.size()>1 && reppdb.size()<pdbe.size())
519         {
520           structureMenu.add(rpdbview = new JMenuItem(MessageManager.formatMessage("label.view_all_representative_structures", new String[]{new Integer(reppdb.size()).toString()})));
521           rpdbview.setToolTipText(MessageManager.getString("label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment"));
522           rpdbview.addActionListener(new ActionListener()
523           {
524
525             @Override
526             public void actionPerformed(ActionEvent e)
527             {
528               new AppJmol(ap, pr, ap.av.collateForPDB(pr));
529             }
530           });
531         }
532       }
533     }
534     else
535     {
536       groupMenu.setVisible(false);
537       editMenu.setVisible(false);
538     }
539
540     if (!isDefinedGroup)
541     {
542       createGroupMenuItem.setVisible(true);
543       unGroupMenuItem.setVisible(false);
544       jMenu1.setText(MessageManager.getString("action.edit_new_group"));\r
545     } else {
546       createGroupMenuItem.setVisible(false);
547       unGroupMenuItem.setVisible(true);
548       jMenu1.setText(MessageManager.getString("action.edit_group"));\r
549     }
550
551     if (seq == null)
552     {
553       sequenceMenu.setVisible(false);
554       structureMenu.setVisible(false);
555     }
556
557     if (links != null && links.size() > 0)
558     {
559
560       JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));\r
561       Vector linkset = new Vector();
562       for (int i = 0; i < links.size(); i++)
563       {
564         String link = links.elementAt(i).toString();
565         UrlLink urlLink = null;
566         try
567         {
568           urlLink = new UrlLink(link);
569         } catch (Exception foo)
570         {
571           jalview.bin.Cache.log.error("Exception for URLLink '" + link
572                   + "'", foo);
573           continue;
574         }
575         ;
576         if (!urlLink.isValid())
577         {
578           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
579           continue;
580         }
581         final String label = urlLink.getLabel();
582         if (seq != null && urlLink.isDynamic())
583         {
584
585           // collect matching db-refs
586           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
587                   seq.getDBRef(), new String[]
588                   { urlLink.getTarget() });
589           // collect id string too
590           String id = seq.getName();
591           String descr = seq.getDescription();
592           if (descr != null && descr.length() < 1)
593           {
594             descr = null;
595           }
596
597           if (dbr != null)
598           {
599             for (int r = 0; r < dbr.length; r++)
600             {
601               if (id != null && dbr[r].getAccessionId().equals(id))
602               {
603                 // suppress duplicate link creation for the bare sequence ID
604                 // string with this link
605                 id = null;
606               }
607               // create Bare ID link for this RUL
608               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
609                       true);
610               if (urls != null)
611               {
612                 for (int u = 0; u < urls.length; u += 2)
613                 {
614                   if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
615                   {
616                     linkset.addElement(urls[u] + "|" + urls[u + 1]);
617                     addshowLink(linkMenu, label + "|" + urls[u],
618                             urls[u + 1]);
619                   }
620                 }
621               }
622             }
623           }
624           if (id != null)
625           {
626             // create Bare ID link for this RUL
627             String[] urls = urlLink.makeUrls(id, true);
628             if (urls != null)
629             {
630               for (int u = 0; u < urls.length; u += 2)
631               {
632                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
633                 {
634                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
635                   addshowLink(linkMenu, label, urls[u + 1]);
636                 }
637               }
638             }
639           }
640           // Create urls from description but only for URL links which are regex
641           // links
642           if (descr != null && urlLink.getRegexReplace() != null)
643           {
644             // create link for this URL from description where regex matches
645             String[] urls = urlLink.makeUrls(descr, true);
646             if (urls != null)
647             {
648               for (int u = 0; u < urls.length; u += 2)
649               {
650                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
651                 {
652                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
653                   addshowLink(linkMenu, label, urls[u + 1]);
654                 }
655               }
656             }
657           }
658         }
659         else
660         {
661           if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
662           {
663             linkset.addElement(label + "|" + urlLink.getUrl_prefix());
664             // Add a non-dynamic link
665             addshowLink(linkMenu, label, urlLink.getUrl_prefix());
666           }
667         }
668       }
669       if (sequence != null)
670       {
671         sequenceMenu.add(linkMenu);
672       }
673       else
674       {
675         add(linkMenu);
676       }
677     }
678   }
679
680   private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
681   {
682
683     // TODO: usability: thread off the generation of group url content so root
684     // menu appears asap
685     // sequence only URLs
686     // ID/regex match URLs
687     groupLinksMenu = new JMenu(MessageManager.getString("action.group_link"));\r
688     JMenu[] linkMenus = new JMenu[]
689     { null, new JMenu(MessageManager.getString("action.ids")), new JMenu(MessageManager.getString("action.sequences")),\r
690         new JMenu(MessageManager.getString("action.ids_sequences")) }; // three types of url that might be\r
691                                           // created.
692     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
693     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
694     Hashtable commonDbrefs = new Hashtable();
695     for (int sq = 0; sq < seqs.length; sq++)
696     {
697
698       int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
699               .findPosition(sg.getEndRes());
700       // just collect ids from dataset sequence
701       // TODO: check if IDs collected from selecton group intersects with the
702       // current selection, too
703       SequenceI sqi = seqs[sq];
704       while (sqi.getDatasetSequence() != null)
705       {
706         sqi = sqi.getDatasetSequence();
707       }
708       DBRefEntry[] dbr = sqi.getDBRef();
709       if (dbr != null && dbr.length > 0)
710       {
711         for (int d = 0; d < dbr.length; d++)
712         {
713           String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
714           Object[] sarray = (Object[]) commonDbrefs.get(src);
715           if (sarray == null)
716           {
717             sarray = new Object[2];
718             sarray[0] = new int[]
719             { 0 };
720             sarray[1] = new String[seqs.length];
721
722             commonDbrefs.put(src, sarray);
723           }
724
725           if (((String[]) sarray[1])[sq] == null)
726           {
727             if (!dbr[d].hasMap()
728                     || (dbr[d].getMap().locateMappedRange(start, end) != null))
729             {
730               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
731               ((int[]) sarray[0])[0]++;
732             }
733           }
734         }
735       }
736     }
737     // now create group links for all distinct ID/sequence sets.
738     boolean addMenu = false; // indicates if there are any group links to give
739                              // to user
740     for (int i = 0; i < groupLinks.size(); i++)
741     {
742       String link = groupLinks.elementAt(i).toString();
743       GroupUrlLink urlLink = null;
744       try
745       {
746         urlLink = new GroupUrlLink(link);
747       } catch (Exception foo)
748       {
749         jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
750                 + "'", foo);
751         continue;
752       }
753       ;
754       if (!urlLink.isValid())
755       {
756         jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
757         continue;
758       }
759       final String label = urlLink.getLabel();
760       boolean usingNames = false;
761       // Now see which parts of the group apply for this URL
762       String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
763       Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
764       String[] seqstr, ids; // input to makeUrl
765       if (idset != null)
766       {
767         int numinput = ((int[]) idset[0])[0];
768         String[] allids = ((String[]) idset[1]);
769         seqstr = new String[numinput];
770         ids = new String[numinput];
771         for (int sq = 0, idcount = 0; sq < seqs.length; sq++)
772         {
773           if (allids[sq] != null)
774           {
775             ids[idcount] = allids[sq];
776             seqstr[idcount++] = idandseqs[1][sq];
777           }
778         }
779       }
780       else
781       {
782         // just use the id/seq set
783         seqstr = idandseqs[1];
784         ids = idandseqs[0];
785         usingNames = true;
786       }
787       // and try and make the groupURL!
788
789       Object[] urlset = null;
790       try
791       {
792         urlset = urlLink.makeUrlStubs(ids, seqstr,
793                 "FromJalview" + System.currentTimeMillis(), false);
794       } catch (UrlStringTooLongException e)
795       {
796       }
797       if (urlset != null)
798       {
799         int type = urlLink.getGroupURLType() & 3;
800         // System.out.println(urlLink.getGroupURLType()
801         // +" "+((String[])urlset[3])[0]);
802         // first two bits ofurlLink type bitfield are sequenceids and sequences
803         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
804         addshowLink(linkMenus[type], label
805                 + (((type & 1) == 1) ? ("("
806                         + (usingNames ? "Names" : ltarget) + ")") : ""),
807                 urlLink, urlset);
808         addMenu = true;
809       }
810     }
811     if (addMenu)
812     {
813       groupLinksMenu = new JMenu(MessageManager.getString("action.group_link"));\r
814       for (int m = 0; m < linkMenus.length; m++)
815       {
816         if (linkMenus[m] != null
817                 && linkMenus[m].getMenuComponentCount() > 0)
818         {
819           groupLinksMenu.add(linkMenus[m]);
820         }
821       }
822
823       groupMenu.add(groupLinksMenu);
824     }
825   }
826
827   /**
828    * add a show URL menu item to the given linkMenu
829    * 
830    * @param linkMenu
831    * @param label
832    *          - menu label string
833    * @param url
834    *          - url to open
835    */
836   private void addshowLink(JMenu linkMenu, String label, final String url)
837   {
838     JMenuItem item = new JMenuItem(label);
839     item.setToolTipText(MessageManager.formatMessage("label.open_url_param", new String[]{url}));\r
840     item.addActionListener(new java.awt.event.ActionListener()
841     {
842       public void actionPerformed(ActionEvent e)
843       {
844         new Thread(new Runnable()
845         {
846
847           public void run()
848           {
849             showLink(url);
850           }
851
852         }).start();
853       }
854     });
855
856     linkMenu.add(item);
857   }
858
859   /**
860    * add a late bound groupURL item to the given linkMenu
861    * 
862    * @param linkMenu
863    * @param label
864    *          - menu label string
865    * @param urlgenerator
866    *          GroupURLLink used to generate URL
867    * @param urlstub
868    *          Object array returned from the makeUrlStubs function.
869    */
870   private void addshowLink(JMenu linkMenu, String label,
871           final GroupUrlLink urlgenerator, final Object[] urlstub)
872   {
873     JMenuItem item = new JMenuItem(label);
874     item.setToolTipText(MessageManager.formatMessage("label.open_url_seqs_param", new Object[]{urlgenerator.getUrl_prefix(),urlgenerator.getNumberInvolved(urlstub)}));\r
875     // TODO: put in info about what is being sent.\r
876     item.addActionListener(new java.awt.event.ActionListener()
877     {
878       public void actionPerformed(ActionEvent e)
879       {
880         new Thread(new Runnable()
881         {
882
883           public void run()
884           {
885             try
886             {
887               showLink(urlgenerator.constructFrom(urlstub));
888             } catch (UrlStringTooLongException e)
889             {
890             }
891           }
892
893         }).start();
894       }
895     });
896
897     linkMenu.add(item);
898   }
899
900   /**
901    * DOCUMENT ME!
902    * 
903    * @throws Exception
904    *           DOCUMENT ME!
905    */
906   private void jbInit() throws Exception
907   {
908     groupMenu.setText(MessageManager.getString("label.group"));\r
909     groupMenu.setText(MessageManager.getString("label.selection"));\r
910     groupName.setText(MessageManager.getString("label.name"));\r
911     groupName.addActionListener(new java.awt.event.ActionListener()
912     {
913       public void actionPerformed(ActionEvent e)
914       {
915         groupName_actionPerformed();
916       }
917     });
918     sequenceMenu.setText(MessageManager.getString("label.sequence"));\r
919     sequenceName.setText(MessageManager.getString("label.edit_name_description"));\r
920     sequenceName.addActionListener(new java.awt.event.ActionListener()
921     {
922       public void actionPerformed(ActionEvent e)
923       {
924         sequenceName_actionPerformed();
925       }
926     });
927     sequenceDetails.setText(MessageManager.getString("label.sequence_details") + "...");\r
928     sequenceDetails.addActionListener(new java.awt.event.ActionListener()
929     {
930       public void actionPerformed(ActionEvent e)
931       {
932         sequenceDetails_actionPerformed();
933       }
934     });
935     sequenceSelDetails.setText(MessageManager.getString("label.sequence_details") + "...");\r
936     sequenceSelDetails
937             .addActionListener(new java.awt.event.ActionListener()
938             {
939               public void actionPerformed(ActionEvent e)
940               {
941                 sequenceSelectionDetails_actionPerformed();
942               }
943             });
944     PIDColour.setFocusPainted(false);
945     unGroupMenuItem.setText(MessageManager.getString("action.remove_group"));\r
946     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
947     {
948       public void actionPerformed(ActionEvent e)
949       {
950         unGroupMenuItem_actionPerformed();
951       }
952     });
953     createGroupMenuItem.setText(MessageManager.getString("action.create_group"));\r
954     createGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
955     {
956       public void actionPerformed(ActionEvent e)
957       {
958         createGroupMenuItem_actionPerformed();
959       }
960     });
961
962     outline.setText(MessageManager.getString("action.border_colour"));\r
963     outline.addActionListener(new java.awt.event.ActionListener()
964     {
965       public void actionPerformed(ActionEvent e)
966       {
967         outline_actionPerformed();
968       }
969     });
970     nucleotideMenuItem.setText(MessageManager.getString("label.nucleotide"));\r
971     nucleotideMenuItem.addActionListener(new ActionListener()
972     {
973       public void actionPerformed(ActionEvent e)
974       {
975         nucleotideMenuItem_actionPerformed();
976       }
977     });
978     colourMenu.setText(MessageManager.getString("label.group_colour"));\r
979     showBoxes.setText(MessageManager.getString("action.boxes"));\r
980     showBoxes.setState(true);
981     showBoxes.addActionListener(new ActionListener()
982     {
983       public void actionPerformed(ActionEvent e)
984       {
985         showBoxes_actionPerformed();
986       }
987     });
988     showText.setText(MessageManager.getString("action.text"));\r
989     showText.setState(true);
990     showText.addActionListener(new ActionListener()
991     {
992       public void actionPerformed(ActionEvent e)
993       {
994         showText_actionPerformed();
995       }
996     });
997     showColourText.setText(MessageManager.getString("label.colour_text"));\r
998     showColourText.addActionListener(new ActionListener()
999     {
1000       public void actionPerformed(ActionEvent e)
1001       {
1002         showColourText_actionPerformed();
1003       }
1004     });
1005     displayNonconserved.setText(MessageManager.getString("label.show_non_conversed"));\r
1006     displayNonconserved.setState(true);
1007     displayNonconserved.addActionListener(new ActionListener()
1008     {
1009       public void actionPerformed(ActionEvent e)
1010       {
1011         showNonconserved_actionPerformed();
1012       }
1013     });
1014     editMenu.setText(MessageManager.getString("action.edit"));\r
1015     cut.setText(MessageManager.getString("action.cut"));\r
1016     cut.addActionListener(new ActionListener()
1017     {
1018       public void actionPerformed(ActionEvent e)
1019       {
1020         cut_actionPerformed();
1021       }
1022     });
1023     upperCase.setText(MessageManager.getString("label.to_upper_case"));\r
1024     upperCase.addActionListener(new ActionListener()
1025     {
1026       public void actionPerformed(ActionEvent e)
1027       {
1028         changeCase(e);
1029       }
1030     });
1031     copy.setText(MessageManager.getString("action.copy"));\r
1032     copy.addActionListener(new ActionListener()
1033     {
1034       public void actionPerformed(ActionEvent e)
1035       {
1036         copy_actionPerformed();
1037       }
1038     });
1039     lowerCase.setText(MessageManager.getString("label.to_lower_case"));\r
1040     lowerCase.addActionListener(new ActionListener()
1041     {
1042       public void actionPerformed(ActionEvent e)
1043       {
1044         changeCase(e);
1045       }
1046     });
1047     toggle.setText(MessageManager.getString("label.toggle_case"));\r
1048     toggle.addActionListener(new ActionListener()
1049     {
1050       public void actionPerformed(ActionEvent e)
1051       {
1052         changeCase(e);
1053       }
1054     });
1055     pdbMenu.setText(MessageManager.getString("label.associate_structure_with_sequence"));\r
1056     pdbFromFile.setText(MessageManager.getString("label.from_file"));\r
1057     pdbFromFile.addActionListener(new ActionListener()
1058     {
1059       public void actionPerformed(ActionEvent e)
1060       {
1061         pdbFromFile_actionPerformed();
1062       }
1063     });
1064     enterPDB.setText(MessageManager.getString("label.enter_pdb_id"));\r
1065     enterPDB.addActionListener(new ActionListener()
1066     {
1067       public void actionPerformed(ActionEvent e)
1068       {
1069         enterPDB_actionPerformed();
1070       }
1071     });
1072     discoverPDB.setText(MessageManager.getString("label.discover_pdb_ids"));\r
1073     discoverPDB.addActionListener(new ActionListener()
1074     {
1075       public void actionPerformed(ActionEvent e)
1076       {
1077         discoverPDB_actionPerformed();
1078       }
1079     });
1080     outputMenu.setText(MessageManager.getString("label.out_to_textbox") + "...");\r
1081     sequenceFeature.setText(MessageManager.getString("label.create_sequence_feature"));\r
1082     sequenceFeature.addActionListener(new ActionListener()
1083     {
1084       public void actionPerformed(ActionEvent e)
1085       {
1086         sequenceFeature_actionPerformed();
1087       }
1088     });
1089     textColour.setText(MessageManager.getString("label.text_colour"));\r
1090     textColour.addActionListener(new ActionListener()
1091     {
1092       public void actionPerformed(ActionEvent e)
1093       {
1094         textColour_actionPerformed();
1095       }
1096     });
1097     jMenu1.setText(MessageManager.getString("label.group"));\r
1098     structureMenu.setText(MessageManager.getString("label.structure"));\r
1099     viewStructureMenu.setText(MessageManager.getString("label.view_structure"));\r
1100     // colStructureMenu.setText("Colour By Structure");
1101     editSequence.setText(MessageManager.getString("label.edit_sequence") + "...");\r
1102     editSequence.addActionListener(new ActionListener()
1103     {
1104       public void actionPerformed(ActionEvent actionEvent)
1105       {
1106         editSequence_actionPerformed(actionEvent);
1107       }
1108     });
1109
1110     /*
1111      * annotationMenuItem.setText("By Annotation");
1112      * annotationMenuItem.addActionListener(new ActionListener() { public void
1113      * actionPerformed(ActionEvent actionEvent) {
1114      * annotationMenuItem_actionPerformed(actionEvent); } });
1115      */
1116     groupMenu.add(sequenceSelDetails);
1117     add(groupMenu);
1118     add(sequenceMenu);
1119     this.add(structureMenu);
1120     groupMenu.add(editMenu);
1121     groupMenu.add(outputMenu);
1122     groupMenu.add(sequenceFeature);
1123     groupMenu.add(createGroupMenuItem);
1124     groupMenu.add(unGroupMenuItem);
1125     groupMenu.add(jMenu1);
1126     sequenceMenu.add(sequenceName);
1127     sequenceMenu.add(sequenceDetails);
1128     colourMenu.add(textColour);
1129     colourMenu.add(noColourmenuItem);
1130     colourMenu.add(clustalColour);
1131     colourMenu.add(BLOSUM62Colour);
1132     colourMenu.add(PIDColour);
1133     colourMenu.add(zappoColour);
1134     colourMenu.add(taylorColour);
1135     colourMenu.add(hydrophobicityColour);
1136     colourMenu.add(helixColour);
1137     colourMenu.add(strandColour);
1138     colourMenu.add(turnColour);
1139     colourMenu.add(buriedColour);
1140     colourMenu.add(nucleotideMenuItem);
1141     if (ap.getAlignment().isNucleotide())
1142     {
1143       colourMenu.add(purinePyrimidineColour);
1144     }
1145     // colourMenu.add(covariationColour);
1146     colourMenu.add(userDefinedColour);
1147
1148     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
1149     {
1150       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
1151               .getUserColourSchemes().keys();
1152
1153       while (userColours.hasMoreElements())
1154       {
1155         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
1156         item.addActionListener(new ActionListener()
1157         {
1158           public void actionPerformed(ActionEvent evt)
1159           {
1160             userDefinedColour_actionPerformed(evt);
1161           }
1162         });
1163         colourMenu.add(item);
1164       }
1165     }
1166
1167     colourMenu.addSeparator();
1168     colourMenu.add(abovePIDColour);
1169     colourMenu.add(conservationMenuItem);
1170     // colourMenu.add(annotationMenuItem);
1171     editMenu.add(copy);
1172     editMenu.add(cut);
1173     editMenu.add(editSequence);
1174     editMenu.add(upperCase);
1175     editMenu.add(lowerCase);
1176     editMenu.add(toggle);
1177     pdbMenu.add(pdbFromFile);
1178     pdbMenu.add(enterPDB);
1179     pdbMenu.add(discoverPDB);
1180     jMenu1.add(groupName);
1181     jMenu1.add(colourMenu);
1182     jMenu1.add(showBoxes);
1183     jMenu1.add(showText);
1184     jMenu1.add(showColourText);
1185     jMenu1.add(outline);
1186     jMenu1.add(displayNonconserved);
1187     structureMenu.add(pdbMenu);
1188     structureMenu.add(viewStructureMenu);
1189     // structureMenu.add(colStructureMenu);
1190     noColourmenuItem.setText(MessageManager.getString("label.none"));\r
1191     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
1192     {
1193       public void actionPerformed(ActionEvent e)
1194       {
1195         noColourmenuItem_actionPerformed();
1196       }
1197     });
1198
1199     clustalColour.setText(MessageManager.getString("label.clustalx_colours"));\r
1200     clustalColour.addActionListener(new java.awt.event.ActionListener()
1201     {
1202       public void actionPerformed(ActionEvent e)
1203       {
1204         clustalColour_actionPerformed();
1205       }
1206     });
1207     zappoColour.setText(MessageManager.getString("label.zappo"));\r
1208     zappoColour.addActionListener(new java.awt.event.ActionListener()
1209     {
1210       public void actionPerformed(ActionEvent e)
1211       {
1212         zappoColour_actionPerformed();
1213       }
1214     });
1215     taylorColour.setText(MessageManager.getString("label.taylor"));\r
1216     taylorColour.addActionListener(new java.awt.event.ActionListener()
1217     {
1218       public void actionPerformed(ActionEvent e)
1219       {
1220         taylorColour_actionPerformed();
1221       }
1222     });
1223     hydrophobicityColour.setText(MessageManager.getString("label.hydrophobicity"));\r
1224     hydrophobicityColour
1225             .addActionListener(new java.awt.event.ActionListener()
1226             {
1227               public void actionPerformed(ActionEvent e)
1228               {
1229                 hydrophobicityColour_actionPerformed();
1230               }
1231             });
1232     helixColour.setText(MessageManager.getString("label.helix_propensity"));\r
1233     helixColour.addActionListener(new java.awt.event.ActionListener()
1234     {
1235       public void actionPerformed(ActionEvent e)
1236       {
1237         helixColour_actionPerformed();
1238       }
1239     });
1240     strandColour.setText(MessageManager.getString("label.strand_propensity"));\r
1241     strandColour.addActionListener(new java.awt.event.ActionListener()
1242     {
1243       public void actionPerformed(ActionEvent e)
1244       {
1245         strandColour_actionPerformed();
1246       }
1247     });
1248     turnColour.setText(MessageManager.getString("label.turn_propensity"));\r
1249     turnColour.addActionListener(new java.awt.event.ActionListener()
1250     {
1251       public void actionPerformed(ActionEvent e)
1252       {
1253         turnColour_actionPerformed();
1254       }
1255     });
1256     buriedColour.setText(MessageManager.getString("label.buried_index"));\r
1257     buriedColour.addActionListener(new java.awt.event.ActionListener()
1258     {
1259       public void actionPerformed(ActionEvent e)
1260       {
1261         buriedColour_actionPerformed();
1262       }
1263     });
1264     abovePIDColour.setText(MessageManager.getString("label.above_identity_percentage"));\r
1265     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
1266     {
1267       public void actionPerformed(ActionEvent e)
1268       {
1269         abovePIDColour_actionPerformed();
1270       }
1271     });
1272     userDefinedColour.setText(MessageManager.getString("action.user_defined"));\r
1273     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
1274     {
1275       public void actionPerformed(ActionEvent e)
1276       {
1277         userDefinedColour_actionPerformed(e);
1278       }
1279     });
1280     PIDColour.setText(MessageManager.getString("label.percentage_identity"));\r
1281     PIDColour.addActionListener(new java.awt.event.ActionListener()
1282     {
1283       public void actionPerformed(ActionEvent e)
1284       {
1285         PIDColour_actionPerformed();
1286       }
1287     });
1288     BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));\r
1289     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
1290     {
1291       public void actionPerformed(ActionEvent e)
1292       {
1293         BLOSUM62Colour_actionPerformed();
1294       }
1295     });
1296     purinePyrimidineColour.setText(MessageManager.getString("label.purine_pyrimidine"));\r
1297     purinePyrimidineColour
1298             .addActionListener(new java.awt.event.ActionListener()
1299             {
1300               public void actionPerformed(ActionEvent e)
1301               {
1302                 purinePyrimidineColour_actionPerformed();
1303               }
1304             });
1305     /*
1306      * covariationColour.addActionListener(new java.awt.event.ActionListener() {
1307      * public void actionPerformed(ActionEvent e) {
1308      * covariationColour_actionPerformed(); } });
1309      */
1310
1311     conservationMenuItem.setText(MessageManager.getString("label.conservation"));\r
1312     conservationMenuItem
1313             .addActionListener(new java.awt.event.ActionListener()
1314             {
1315               public void actionPerformed(ActionEvent e)
1316               {
1317                 conservationMenuItem_actionPerformed();
1318               }
1319             });
1320   }
1321
1322   protected void sequenceSelectionDetails_actionPerformed()
1323   {
1324     createSequenceDetailsReport(ap.av.getSequenceSelection());
1325   }
1326
1327   protected void sequenceDetails_actionPerformed()
1328   {
1329     createSequenceDetailsReport(new SequenceI[]
1330     { sequence });
1331   }
1332
1333   public void createSequenceDetailsReport(SequenceI[] sequences)
1334   {
1335     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
1336     StringBuffer contents = new StringBuffer();
1337     for (SequenceI seq : sequences)
1338     {
1339       contents.append("<p><h2>" + MessageManager.formatMessage("label.create_sequence_details_report_annotation_for", new String[]{seq.getDisplayId(true)})\r
1340               + "</h2></p><p>");
1341       new SequenceAnnotationReport(null)
1342               .createSequenceAnnotationReport(
1343                       contents,
1344                       seq,
1345                       true,
1346                       true,
1347                       false,
1348                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
1349                               : null);
1350       contents.append("</p>");
1351     }
1352     cap.setText("<html>" + contents.toString() + "</html>");
1353
1354     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
1355                 ,500, 400);\r
1356
1357   }
1358
1359   protected void showNonconserved_actionPerformed()
1360   {
1361     getGroup().setShowNonconserved(displayNonconserved.isSelected());
1362     refresh();
1363   }
1364
1365   /**
1366    * call to refresh view after settings change
1367    */
1368   void refresh()
1369   {
1370     ap.updateAnnotation();
1371     ap.paintAlignment(true);
1372
1373     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
1374   }
1375
1376   /**
1377    * DOCUMENT ME!
1378    * 
1379    * @param e
1380    *          DOCUMENT ME!
1381    */
1382   protected void clustalColour_actionPerformed()
1383   {
1384     SequenceGroup sg = getGroup();
1385     sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
1386     refresh();
1387   }
1388
1389   /**
1390    * DOCUMENT ME!
1391    * 
1392    * @param e
1393    *          DOCUMENT ME!
1394    */
1395   protected void zappoColour_actionPerformed()
1396   {
1397     getGroup().cs = new ZappoColourScheme();
1398     refresh();
1399   }
1400
1401   /**
1402    * DOCUMENT ME!
1403    * 
1404    * @param e
1405    *          DOCUMENT ME!
1406    */
1407   protected void taylorColour_actionPerformed()
1408   {
1409     getGroup().cs = new TaylorColourScheme();
1410     refresh();
1411   }
1412
1413   /**
1414    * DOCUMENT ME!
1415    * 
1416    * @param e
1417    *          DOCUMENT ME!
1418    */
1419   protected void hydrophobicityColour_actionPerformed()
1420   {
1421     getGroup().cs = new HydrophobicColourScheme();
1422     refresh();
1423   }
1424
1425   /**
1426    * DOCUMENT ME!
1427    * 
1428    * @param e
1429    *          DOCUMENT ME!
1430    */
1431   protected void helixColour_actionPerformed()
1432   {
1433     getGroup().cs = new HelixColourScheme();
1434     refresh();
1435   }
1436
1437   /**
1438    * DOCUMENT ME!
1439    * 
1440    * @param e
1441    *          DOCUMENT ME!
1442    */
1443   protected void strandColour_actionPerformed()
1444   {
1445     getGroup().cs = new StrandColourScheme();
1446     refresh();
1447   }
1448
1449   /**
1450    * DOCUMENT ME!
1451    * 
1452    * @param e
1453    *          DOCUMENT ME!
1454    */
1455   protected void turnColour_actionPerformed()
1456   {
1457     getGroup().cs = new TurnColourScheme();
1458     refresh();
1459   }
1460
1461   /**
1462    * DOCUMENT ME!
1463    * 
1464    * @param e
1465    *          DOCUMENT ME!
1466    */
1467   protected void buriedColour_actionPerformed()
1468   {
1469     getGroup().cs = new BuriedColourScheme();
1470     refresh();
1471   }
1472
1473   /**
1474    * DOCUMENT ME!
1475    * 
1476    * @param e
1477    *          DOCUMENT ME!
1478    */
1479   public void nucleotideMenuItem_actionPerformed()
1480   {
1481     getGroup().cs = new NucleotideColourScheme();
1482     refresh();
1483   }
1484
1485   protected void purinePyrimidineColour_actionPerformed()
1486   {
1487     getGroup().cs = new PurinePyrimidineColourScheme();
1488     refresh();
1489   }
1490
1491   /*
1492    * protected void covariationColour_actionPerformed() { getGroup().cs = new
1493    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
1494    */
1495   /**
1496    * DOCUMENT ME!
1497    * 
1498    * @param e
1499    *          DOCUMENT ME!
1500    */
1501   protected void abovePIDColour_actionPerformed()
1502   {
1503     SequenceGroup sg = getGroup();
1504     if (sg.cs == null)
1505     {
1506       return;
1507     }
1508
1509     if (abovePIDColour.isSelected())
1510     {
1511       sg.cs.setConsensus(AAFrequency.calculate(
1512               sg.getSequences(ap.av.getHiddenRepSequences()),
1513               sg.getStartRes(), sg.getEndRes() + 1));
1514
1515       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1516               .getName());
1517
1518       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1519
1520       SliderPanel.showPIDSlider();
1521     }
1522     else
1523     // remove PIDColouring
1524     {
1525       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1526     }
1527
1528     refresh();
1529   }
1530
1531   /**
1532    * DOCUMENT ME!
1533    * 
1534    * @param e
1535    *          DOCUMENT ME!
1536    */
1537   protected void userDefinedColour_actionPerformed(ActionEvent e)
1538   {
1539     SequenceGroup sg = getGroup();
1540
1541     if (e.getSource().equals(userDefinedColour))\r
1542     {
1543       new UserDefinedColours(ap, sg);
1544     }
1545     else
1546     {
1547       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1548               .getUserColourSchemes().get(e.getActionCommand());
1549
1550       sg.cs = udc;
1551     }
1552     refresh();
1553   }
1554
1555   /**
1556    * DOCUMENT ME!
1557    * 
1558    * @param e
1559    *          DOCUMENT ME!
1560    */
1561   protected void PIDColour_actionPerformed()
1562   {
1563     SequenceGroup sg = getGroup();
1564     sg.cs = new PIDColourScheme();
1565     sg.cs.setConsensus(AAFrequency.calculate(
1566             sg.getSequences(ap.av.getHiddenRepSequences()),
1567             sg.getStartRes(), sg.getEndRes() + 1));
1568     refresh();
1569   }
1570
1571   /**
1572    * DOCUMENT ME!
1573    * 
1574    * @param e
1575    *          DOCUMENT ME!
1576    */
1577   protected void BLOSUM62Colour_actionPerformed()
1578   {
1579     SequenceGroup sg = getGroup();
1580
1581     sg.cs = new Blosum62ColourScheme();
1582
1583     sg.cs.setConsensus(AAFrequency.calculate(
1584             sg.getSequences(ap.av.getHiddenRepSequences()),
1585             sg.getStartRes(), sg.getEndRes() + 1));
1586
1587     refresh();
1588   }
1589
1590   /**
1591    * DOCUMENT ME!
1592    * 
1593    * @param e
1594    *          DOCUMENT ME!
1595    */
1596   protected void noColourmenuItem_actionPerformed()
1597   {
1598     getGroup().cs = null;
1599     refresh();
1600   }
1601
1602   /**
1603    * DOCUMENT ME!
1604    * 
1605    * @param e
1606    *          DOCUMENT ME!
1607    */
1608   protected void conservationMenuItem_actionPerformed()
1609   {
1610     SequenceGroup sg = getGroup();
1611     if (sg.cs == null)
1612     {
1613       return;
1614     }
1615
1616     if (conservationMenuItem.isSelected())
1617     {
1618     // JBPNote: Conservation name shouldn't be i18n translated
1619       Conservation c = new Conservation("Group",
1620               ResidueProperties.propHash, 3, sg.getSequences(ap.av
1621                       .getHiddenRepSequences()), sg.getStartRes(),
1622               sg.getEndRes() + 1);
1623
1624       c.calculate();
1625       c.verdict(false, ap.av.getConsPercGaps());
1626
1627       sg.cs.setConservation(c);
1628
1629       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1630       SliderPanel.showConservationSlider();
1631     }
1632     else
1633     // remove ConservationColouring
1634     {
1635       sg.cs.setConservation(null);
1636     }
1637
1638     refresh();
1639   }
1640
1641   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1642   {
1643     SequenceGroup sg = getGroup();
1644     if (sg == null)
1645     {
1646       return;
1647     }
1648
1649     AnnotationColourGradient acg = new AnnotationColourGradient(
1650             sequence.getAnnotation()[0], null,
1651             AnnotationColourGradient.NO_THRESHOLD);
1652
1653     acg.setPredefinedColours(true);
1654     sg.cs = acg;
1655
1656     refresh();
1657   }
1658
1659   /**
1660    * DOCUMENT ME!
1661    * 
1662    * @param e
1663    *          DOCUMENT ME!
1664    */
1665   protected void groupName_actionPerformed()
1666   {
1667
1668     SequenceGroup sg = getGroup();
1669     EditNameDialog dialog = new EditNameDialog(sg.getName(),
1670             sg.getDescription(), "       " + MessageManager.getString("label.group_name") + " ",\r
1671             MessageManager.getString("label.group_description") + " ", MessageManager.getString("label.edit_group_name_description"),\r
1672             ap.alignFrame);
1673
1674     if (!dialog.accept)
1675     {
1676       return;
1677     }
1678
1679     sg.setName(dialog.getName());
1680     sg.setDescription(dialog.getDescription());
1681     refresh();
1682   }
1683
1684   /**
1685    * Get selection group - adding it to the alignment if necessary.
1686    * 
1687    * @return sequence group to operate on
1688    */
1689   SequenceGroup getGroup()
1690   {
1691     SequenceGroup sg = ap.av.getSelectionGroup();
1692     // this method won't add a new group if it already exists
1693     if (sg != null)
1694     {
1695       ap.av.getAlignment().addGroup(sg);
1696     }
1697
1698     return sg;
1699   }
1700
1701   /**
1702    * DOCUMENT ME!
1703    * 
1704    * @param e
1705    *          DOCUMENT ME!
1706    */
1707   void sequenceName_actionPerformed()
1708   {
1709     EditNameDialog dialog = new EditNameDialog(sequence.getName(),
1710             sequence.getDescription(), "       " + MessageManager.getString("label.sequence_name") + " ",\r
1711             MessageManager.getString("label.sequence_description") + " ", MessageManager.getString("label.edit_sequence_name_description"),\r
1712             ap.alignFrame);
1713
1714     if (!dialog.accept)
1715     {
1716       return;
1717     }
1718
1719     if (dialog.getName() != null)
1720     {
1721       if (dialog.getName().indexOf(" ") > -1)
1722       {
1723         JOptionPane.showMessageDialog(ap,
1724                 MessageManager.getString("label.spaces_converted_to_backslashes"),\r
1725                 MessageManager.getString("label.no_spaces_allowed_sequence_name"),\r
1726                 JOptionPane.WARNING_MESSAGE);
1727       }
1728
1729       sequence.setName(dialog.getName().replace(' ', '_'));
1730       ap.paintAlignment(false);
1731     }
1732
1733     sequence.setDescription(dialog.getDescription());
1734
1735     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1736             .getSequences());
1737
1738   }
1739
1740   /**
1741    * DOCUMENT ME!
1742    * 
1743    * @param e
1744    *          DOCUMENT ME!
1745    */
1746   void unGroupMenuItem_actionPerformed()
1747   {
1748     SequenceGroup sg = ap.av.getSelectionGroup();
1749     ap.av.getAlignment().deleteGroup(sg);
1750     ap.av.setSelectionGroup(null);
1751     refresh();
1752   }
1753   void createGroupMenuItem_actionPerformed()
1754   {
1755     getGroup(); // implicitly creates group - note - should apply defaults / use standard alignment window logic for this
1756     refresh();
1757   }
1758
1759   /**
1760    * DOCUMENT ME!
1761    * 
1762    * @param e
1763    *          DOCUMENT ME!
1764    */
1765   protected void outline_actionPerformed()
1766   {
1767     SequenceGroup sg = getGroup();
1768     Color col = JColorChooser.showDialog(this, MessageManager.getString("label.select_outline_colour"),\r
1769             Color.BLUE);
1770
1771     if (col != null)
1772     {
1773       sg.setOutlineColour(col);
1774     }
1775
1776     refresh();
1777   }
1778
1779   /**
1780    * DOCUMENT ME!
1781    * 
1782    * @param e
1783    *          DOCUMENT ME!
1784    */
1785   public void showBoxes_actionPerformed()
1786   {
1787     getGroup().setDisplayBoxes(showBoxes.isSelected());
1788     refresh();
1789   }
1790
1791   /**
1792    * DOCUMENT ME!
1793    * 
1794    * @param e
1795    *          DOCUMENT ME!
1796    */
1797   public void showText_actionPerformed()
1798   {
1799     getGroup().setDisplayText(showText.isSelected());
1800     refresh();
1801   }
1802
1803   /**
1804    * DOCUMENT ME!
1805    * 
1806    * @param e
1807    *          DOCUMENT ME!
1808    */
1809   public void showColourText_actionPerformed()
1810   {
1811     getGroup().setColourText(showColourText.isSelected());
1812     refresh();
1813   }
1814
1815   public void showLink(String url)
1816   {
1817     try
1818     {
1819       jalview.util.BrowserLauncher.openURL(url);
1820     } catch (Exception ex)
1821     {
1822       JOptionPane
1823               .showInternalMessageDialog(
1824                       Desktop.desktop,
1825                       MessageManager.getString("label.web_browser_not_found_unix"),\r
1826                       MessageManager.getString("label.web_browser_not_found"), JOptionPane.WARNING_MESSAGE);\r
1827
1828       ex.printStackTrace();
1829     }
1830   }
1831
1832   void hideSequences(boolean representGroup)
1833   {
1834     SequenceGroup sg = ap.av.getSelectionGroup();
1835     if (sg == null || sg.getSize() < 1)
1836     {
1837       ap.av.hideSequence(new SequenceI[]
1838       { sequence });
1839       return;
1840     }
1841
1842     ap.av.setSelectionGroup(null);
1843
1844     if (representGroup)
1845     {
1846       ap.av.hideRepSequences(sequence, sg);
1847
1848       return;
1849     }
1850
1851     int gsize = sg.getSize();
1852     SequenceI[] hseqs;
1853
1854     hseqs = new SequenceI[gsize];
1855
1856     int index = 0;
1857     for (int i = 0; i < gsize; i++)
1858     {
1859       hseqs[index++] = sg.getSequenceAt(i);
1860     }
1861
1862     ap.av.hideSequence(hseqs);
1863     // refresh(); TODO: ? needed ?
1864     ap.av.sendSelection();
1865   }
1866
1867   public void copy_actionPerformed()
1868   {
1869     ap.alignFrame.copy_actionPerformed(null);
1870   }
1871
1872   public void cut_actionPerformed()
1873   {
1874     ap.alignFrame.cut_actionPerformed(null);
1875   }
1876
1877   void changeCase(ActionEvent e)
1878   {
1879     Object source = e.getSource();
1880     SequenceGroup sg = ap.av.getSelectionGroup();
1881
1882     if (sg != null)
1883     {
1884       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1885               sg.getEndRes() + 1);
1886
1887       String description;
1888       int caseChange;
1889
1890       if (source == toggle)
1891       {
1892         description = MessageManager.getString("label.toggle_case");\r
1893         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1894       }
1895       else if (source == upperCase)
1896       {
1897         description = MessageManager.getString("label.to_upper_case");\r
1898         caseChange = ChangeCaseCommand.TO_UPPER;
1899       }
1900       else
1901       {
1902         description = MessageManager.getString("label.to_lower_case");\r
1903         caseChange = ChangeCaseCommand.TO_LOWER;
1904       }
1905
1906       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
1907               sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
1908               startEnd, caseChange);
1909
1910       ap.alignFrame.addHistoryItem(caseCommand);
1911
1912       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1913               .getSequences());
1914
1915     }
1916   }
1917
1918   public void outputText_actionPerformed(ActionEvent e)
1919   {
1920     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1921     cap.setForInput(null);
1922     Desktop.addInternalFrame(cap,
1923             MessageManager.formatMessage("label.alignment_output_command", new String[]{e.getActionCommand()}), 600, 500);\r
1924
1925     String[] omitHidden = null;
1926
1927     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1928     // or we simply trust the user wants
1929     // wysiwig behaviour
1930     SequenceGroup sg = ap.av.getSelectionGroup();
1931     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1932     omitHidden = ap.av.getViewAsString(true);
1933     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1934     AlignmentAnnotation[] nala = ap.av.getAlignment()
1935             .getAlignmentAnnotation();
1936     if (nala != null)
1937     {
1938       for (int i = 0; i < nala.length; i++)
1939       {
1940         AlignmentAnnotation na = nala[i];
1941         oal.addAnnotation(na);
1942       }
1943     }
1944     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1945             oal, omitHidden, csel, sg));
1946     oal = null;
1947   }
1948
1949   public void pdbFromFile_actionPerformed()
1950   {
1951     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1952             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1953     chooser.setFileView(new jalview.io.JalviewFileView());
1954     chooser.setDialogTitle(MessageManager.formatMessage("label.select_pdb_file_for", new String[]{sequence.getDisplayId(false)}));\r
1955     chooser.setToolTipText(MessageManager.formatMessage("label.load_pdb_file_associate_with_sequence", new String[]{new Integer(sequence.getDisplayId(false)).toString()}));\r
1956
1957     int value = chooser.showOpenDialog(null);
1958
1959     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1960     {
1961       String choice = chooser.getSelectedFile().getPath();
1962       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1963       new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
1964               jalview.io.AppletFormatAdapter.FILE, sequence, true);
1965     }
1966
1967   }
1968
1969   public void enterPDB_actionPerformed()
1970   {
1971     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
1972             MessageManager.getString("label.enter_pdb_id"), MessageManager.getString("label.enter_pdb_id"), JOptionPane.QUESTION_MESSAGE);\r
1973
1974     if (id != null && id.length() > 0)
1975     {
1976       PDBEntry entry = new PDBEntry();
1977       entry.setId(id.toUpperCase());
1978       sequence.getDatasetSequence().addPDBId(entry);
1979     }
1980   }
1981
1982   public void discoverPDB_actionPerformed()
1983   {
1984
1985     final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
1986     { sequence }
1987             : ap.av.getSequenceSelection());
1988     Thread discpdb = new Thread(new Runnable()
1989     {
1990       public void run()
1991       {
1992
1993         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
1994                 .fetchDBRefs(false);
1995       }
1996
1997     });
1998     discpdb.start();
1999   }
2000
2001   public void sequenceFeature_actionPerformed()
2002   {
2003     SequenceGroup sg = ap.av.getSelectionGroup();
2004     if (sg == null)
2005     {
2006       return;
2007     }
2008
2009     int rsize = 0, gSize = sg.getSize();
2010     SequenceI[] rseqs, seqs = new SequenceI[gSize];
2011     SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
2012
2013     for (int i = 0; i < gSize; i++)
2014     {
2015       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
2016       int end = sg.findEndRes(sg.getSequenceAt(i));
2017       if (start <= end)
2018       {
2019         seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
2020         features[rsize] = new SequenceFeature(null, null, null, start, end,
2021                 "Jalview");
2022         rsize++;
2023       }
2024     }
2025     rseqs = new SequenceI[rsize];
2026     tfeatures = new SequenceFeature[rsize];
2027     System.arraycopy(seqs, 0, rseqs, 0, rsize);
2028     System.arraycopy(features, 0, tfeatures, 0, rsize);
2029     features = tfeatures;
2030     seqs = rseqs;
2031     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
2032             features, true, ap))
2033     {
2034       ap.alignFrame.setShowSeqFeatures(true);
2035       ap.highlightSearchResults(null);
2036     }
2037   }
2038
2039   public void textColour_actionPerformed()
2040   {
2041     SequenceGroup sg = getGroup();
2042     if (sg != null)
2043     {
2044       new TextColourChooser().chooseColour(ap, sg);
2045     }
2046   }
2047
2048   public void colourByStructure(String pdbid)
2049   {
2050     Annotation[] anots = ap.av.getStructureSelectionManager()
2051             .colourSequenceFromStructure(sequence, pdbid);
2052
2053     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
2054             "Coloured by " + pdbid, anots);
2055
2056     ap.av.getAlignment().addAnnotation(an);
2057     an.createSequenceMapping(sequence, 0, true);
2058     // an.adjustForAlignment();
2059     ap.av.getAlignment().setAnnotationIndex(an, 0);
2060
2061     ap.adjustAnnotationHeight();
2062
2063     sequence.addAlignmentAnnotation(an);
2064
2065   }
2066
2067   public void editSequence_actionPerformed(ActionEvent actionEvent)
2068   {
2069     SequenceGroup sg = ap.av.getSelectionGroup();
2070
2071     if (sg != null)
2072     {
2073       if (sequence == null)
2074         sequence = (Sequence) sg.getSequenceAt(0);
2075
2076       EditNameDialog dialog = new EditNameDialog(
2077               sequence.getSequenceAsString(sg.getStartRes(),
2078                       sg.getEndRes() + 1), null, MessageManager.getString("label.edit_sequence"), null,\r
2079                       MessageManager.getString("label.edit_sequence"), ap.alignFrame);\r
2080
2081       if (dialog.accept)
2082       {
2083         EditCommand editCommand = new EditCommand(MessageManager.getString("label.edit_sequences"),\r
2084                 EditCommand.REPLACE, dialog.getName().replace(' ',
2085                         ap.av.getGapCharacter()),
2086                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
2087                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
2088
2089         ap.alignFrame.addHistoryItem(editCommand);
2090
2091         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2092                 .getSequences());
2093       }
2094     }
2095   }
2096
2097 }