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