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