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