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