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