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