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