fe1700b904f9ee46a3200f9a0bf6e6c10f568aec
[jalview.git] / src / jalview / appletgui / APopupMenu.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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.appletgui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import jalview.analysis.*;
26 import jalview.commands.*;
27 import jalview.datamodel.*;
28 import jalview.schemes.*;
29 import jalview.util.UrlLink;
30 import jalview.io.AppletFormatAdapter;
31 import jalview.io.SequenceAnnotationReport;
32
33 public class APopupMenu extends java.awt.PopupMenu implements
34         ActionListener, ItemListener
35 {
36   Menu groupMenu = new Menu();
37
38   MenuItem editGroupName = new MenuItem();
39
40   protected MenuItem clustalColour = new MenuItem();
41
42   protected MenuItem zappoColour = new MenuItem();
43
44   protected MenuItem taylorColour = new MenuItem();
45
46   protected MenuItem hydrophobicityColour = new MenuItem();
47
48   protected MenuItem helixColour = new MenuItem();
49
50   protected MenuItem strandColour = new MenuItem();
51
52   protected MenuItem turnColour = new MenuItem();
53
54   protected MenuItem buriedColour = new MenuItem();
55
56   protected CheckboxMenuItem abovePIDColour = new CheckboxMenuItem();
57
58   protected MenuItem userDefinedColour = new MenuItem();
59
60   protected MenuItem PIDColour = new MenuItem();
61
62   protected MenuItem BLOSUM62Colour = new MenuItem();
63
64   MenuItem noColourmenuItem = new MenuItem();
65
66   protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
67
68   final AlignmentPanel ap;
69
70   MenuItem unGroupMenuItem = new MenuItem();
71
72   MenuItem nucleotideMenuItem = new MenuItem();
73
74   Menu colourMenu = new Menu();
75
76   CheckboxMenuItem showBoxes = new CheckboxMenuItem();
77
78   CheckboxMenuItem showText = new CheckboxMenuItem();
79
80   CheckboxMenuItem showColourText = new CheckboxMenuItem();
81
82   CheckboxMenuItem displayNonconserved = new CheckboxMenuItem();
83
84   Menu editMenu = new Menu("Edit");
85
86   MenuItem copy = new MenuItem("Copy (Jalview Only)");
87
88   MenuItem cut = new MenuItem("Cut (Jalview Only)");
89
90   MenuItem toUpper = new MenuItem("To Upper Case");
91
92   MenuItem toLower = new MenuItem("To Lower Case");
93
94   MenuItem toggleCase = new MenuItem("Toggle Case");
95
96   Menu outputmenu = new Menu();
97
98   Menu seqMenu = new Menu();
99
100   MenuItem pdb = new MenuItem();
101
102   MenuItem hideSeqs = new MenuItem();
103
104   MenuItem repGroup = new MenuItem();
105
106   MenuItem sequenceName = new MenuItem("Edit Name/Description");
107
108   MenuItem sequenceFeature = new MenuItem("Create Sequence Feature");
109
110   MenuItem editSequence = new MenuItem("Edit Sequence");
111   
112   MenuItem sequenceDetails = new MenuItem("Sequence Details ...");
113
114   MenuItem selSeqDetails = new MenuItem("Sequence Details ...");
115   
116   Sequence seq;
117
118   MenuItem revealAll = new MenuItem();
119
120   MenuItem revealSeq = new MenuItem();
121   /**
122    * index of sequence to be revealed
123    */
124   int revealSeq_index=-1;
125   Menu menu1 = new Menu();
126
127   public APopupMenu(AlignmentPanel apanel, final Sequence seq, Vector links)
128   {
129     // /////////////////////////////////////////////////////////
130     // If this is activated from the sequence panel, the user may want to
131     // edit or annotate a particular residue. Therefore display the residue menu
132     //
133     // If from the IDPanel, we must display the sequence menu
134     // ////////////////////////////////////////////////////////
135
136     this.ap = apanel;
137     this.seq = seq;
138
139     try
140     {
141       jbInit();
142     } catch (Exception e)
143     {
144       e.printStackTrace();
145     }
146
147     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)
148     {
149       MenuItem item = new MenuItem(
150               jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);
151
152       item.addActionListener(this);
153       outputmenu.add(item);
154     }
155
156     SequenceGroup sg = ap.av.getSelectionGroup();
157
158     if (sg != null && sg.getSize() > 0)
159     {
160       editGroupName.setLabel("Name: "+sg.getName());
161       showText.setState(sg.getDisplayText());
162       showColourText.setState(sg.getColourText());
163       showBoxes.setState(sg.getDisplayBoxes());
164       displayNonconserved.setState(sg.getShowNonconserved());
165       if (!ap.av.getAlignment().getGroups().contains(sg))
166       {
167         groupMenu.remove(unGroupMenuItem);
168       }
169
170     }
171     else
172     {
173       remove(hideSeqs);
174       remove(groupMenu);
175     }
176
177     if (links != null && links.size() > 0)
178     {
179       Menu linkMenu = new Menu("Link");
180       String link;
181       for (int i = 0; i < links.size(); i++)
182       {
183         link = links.elementAt(i).toString();
184         UrlLink urlLink = new UrlLink(link);
185         if (!urlLink.isValid())
186         {
187           System.err.println(urlLink.getInvalidMessage());
188           continue;
189         }
190         final String target = urlLink.getTarget(); // link.substring(0,
191         // link.indexOf("|"));
192         final String label = urlLink.getLabel();
193         if (seq!=null && urlLink.isDynamic())
194         {
195
196           // collect matching db-refs
197           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
198                   seq.getDBRef(), new String[]
199                   { target });
200           // collect id string too
201           String id = seq.getName();
202           String descr = seq.getDescription();
203           if (descr != null && descr.length() < 1)
204           {
205             descr = null;
206           }
207           if (dbr != null)
208           {
209             for (int r = 0; r < dbr.length; r++)
210             {
211               if (id != null && dbr[r].getAccessionId().equals(id))
212               {
213                 // suppress duplicate link creation for the bare sequence ID
214                 // string with this link
215                 id = null;
216               }
217               // create Bare ID link for this RUL
218               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
219                       true);
220               if (urls != null)
221               {
222                 for (int u = 0; u < urls.length; u += 2)
223                 {
224                   addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
225                 }
226               }
227             }
228           }
229           if (id != null)
230           {
231             // create Bare ID link for this RUL
232             String[] urls = urlLink.makeUrls(id, true);
233             if (urls != null)
234             {
235               for (int u = 0; u < urls.length; u += 2)
236               {
237                 addshowLink(linkMenu, label, urls[u + 1]);
238               }
239             }
240             // addshowLink(linkMenu, target, url_pref + id + url_suff);
241           }
242           // Now construct URLs from description but only try to do it for regex
243           // URL links
244           if (descr != null && urlLink.getRegexReplace() != null)
245           {
246             // create link for this URL from description only if regex matches
247             String[] urls = urlLink.makeUrls(descr, true);
248             if (urls != null)
249             {
250               for (int u = 0; u < urls.length; u += 2)
251               {
252                 addshowLink(linkMenu, label, urls[u + 1]);
253               }
254             }
255           }
256         }
257         else
258         {
259           addshowLink(linkMenu, target, urlLink.getUrl_prefix()); // link.substring(link.lastIndexOf("|")+1));
260         }
261         /*
262          * final String url;
263          * 
264          * if (link.indexOf("$SEQUENCE_ID$") > -1) { // Substitute SEQUENCE_ID
265          * string and any matching database reference accessions String url_pref
266          * = link.substring(link.indexOf("|") + 1,
267          * link.indexOf("$SEQUENCE_ID$"));
268          * 
269          * String url_suff = link.substring(link.indexOf("$SEQUENCE_ID$") + 13);
270          * // collect matching db-refs DBRefEntry[] dbr =
271          * jalview.util.DBRefUtils.selectRefs(seq.getDBRef(), new
272          * String[]{target}); // collect id string too String id =
273          * seq.getName(); if (id.indexOf("|") > -1) { id =
274          * id.substring(id.lastIndexOf("|") + 1); } if (dbr!=null) { for (int
275          * r=0;r<dbr.length; r++) { if (dbr[r].getAccessionId().equals(id)) { //
276          * suppress duplicate link creation for the bare sequence ID string with
277          * this link id = null; } addshowLink(linkMenu,
278          * dbr[r].getSource()+"|"+dbr[r].getAccessionId(), target,
279          * url_pref+dbr[r].getAccessionId()+url_suff); } } if (id!=null) { //
280          * create Bare ID link for this RUL addshowLink(linkMenu, target,
281          * url_pref + id + url_suff); } } else { addshowLink(linkMenu, target,
282          * link.substring(link.lastIndexOf("|")+1)); }
283          */
284       }
285       if (linkMenu.getItemCount() > 0)
286       {
287         if (seq != null)
288         {
289           seqMenu.add(linkMenu);
290         }
291         else
292         {
293           add(linkMenu);
294         }
295       }
296     }
297     // TODO: add group link menu entry here
298     if (seq != null)
299     {
300       seqMenu.setLabel(seq.getName());
301       repGroup.setLabel("Represent Group with " + seq.getName());
302     }
303     else
304     {
305       remove(seqMenu);
306     }
307
308     if (!ap.av.hasHiddenRows())
309     {
310       remove(revealAll);
311       remove(revealSeq);
312     } else {
313       final int index = ap.av.getAlignment().findIndex(seq);
314
315       if (ap.av.adjustForHiddenSeqs(index)
316               - ap.av.adjustForHiddenSeqs(index - 1) > 1)
317       {
318         revealSeq_index=index;
319       } else {
320         remove(revealSeq);
321       }
322     }
323   }
324
325   /**
326    * add a show URL menu item to the given linkMenu
327    * 
328    * @param linkMenu
329    * @param target
330    *          - menu label string
331    * @param url
332    *          - url to open
333    */
334   private void addshowLink(Menu linkMenu, final String target,
335           final String url)
336   {
337     addshowLink(linkMenu, target, target, url);
338   }
339
340   /**
341    * add a show URL menu item to the given linkMenu
342    * 
343    * @param linkMenu
344    * @param target
345    *          - URL target window
346    * @param label
347    *          - menu label string
348    * @param url
349    *          - url to open
350    */
351   private void addshowLink(Menu linkMenu, final String target,
352           final String label, final String url)
353   {
354     MenuItem item = new MenuItem(label);
355     item.addActionListener(new java.awt.event.ActionListener()
356     {
357       public void actionPerformed(ActionEvent e)
358       {
359         ap.alignFrame.showURL(url, target);
360       }
361     });
362     linkMenu.add(item);
363   }
364
365   public void itemStateChanged(ItemEvent evt)
366   {
367     if (evt.getSource() == abovePIDColour)
368     {
369       abovePIDColour_itemStateChanged();
370     }
371     else if (evt.getSource() == showColourText)
372     {
373       showColourText_itemStateChanged();
374     }
375     else if (evt.getSource() == showText)
376     {
377       showText_itemStateChanged();
378     }
379     else if (evt.getSource() == showBoxes)
380     {
381       showBoxes_itemStateChanged();
382     }
383     else if (evt.getSource() == displayNonconserved)
384     {
385       this.showNonconserved_itemStateChanged();
386     }
387   }
388
389   public void actionPerformed(ActionEvent evt)
390   {
391     Object source = evt.getSource();
392     if (source == clustalColour)
393     {
394       clustalColour_actionPerformed();
395     }
396     else if (source == zappoColour)
397     {
398       zappoColour_actionPerformed();
399     }
400     else if (source == taylorColour)
401     {
402       taylorColour_actionPerformed();
403     }
404     else if (source == hydrophobicityColour)
405     {
406       hydrophobicityColour_actionPerformed();
407     }
408     else if (source == helixColour)
409     {
410       helixColour_actionPerformed();
411     }
412     else if (source == strandColour)
413     {
414       strandColour_actionPerformed();
415     }
416     else if (source == turnColour)
417     {
418       turnColour_actionPerformed();
419     }
420     else if (source == buriedColour)
421     {
422       buriedColour_actionPerformed();
423     }
424     else if (source == nucleotideMenuItem)
425     {
426       nucleotideMenuItem_actionPerformed();
427     }
428
429     else if (source == userDefinedColour)
430     {
431       userDefinedColour_actionPerformed();
432     }
433     else if (source == PIDColour)
434     {
435       PIDColour_actionPerformed();
436     }
437     else if (source == BLOSUM62Colour)
438     {
439       BLOSUM62Colour_actionPerformed();
440     }
441     else if (source == noColourmenuItem)
442     {
443       noColourmenuItem_actionPerformed();
444     }
445     else if (source == conservationMenuItem)
446     {
447       conservationMenuItem_itemStateChanged();
448     }
449     else if (source == unGroupMenuItem)
450     {
451       unGroupMenuItem_actionPerformed();
452     }
453
454     else if (source == sequenceName)
455     {
456       editName();
457     }
458     else if (source == sequenceDetails)
459     {
460       showSequenceDetails();
461     }
462     else if (source == selSeqDetails)
463     {
464       showSequenceSelectionDetails();
465     }
466     else if (source == pdb)
467     {
468       addPDB();
469     }
470     else if (source == hideSeqs)
471     {
472       hideSequences(false);
473     }
474     else if (source == repGroup)
475     {
476       hideSequences(true);
477     }
478     else if (source == revealSeq)
479     {
480       ap.av.showSequence(revealSeq_index);
481     }
482     else if (source == revealAll)
483     {
484       ap.av.showAllHiddenSeqs();
485     }
486
487     else if (source == editGroupName)
488     {
489       EditNameDialog dialog = new EditNameDialog(getGroup().getName(),
490               getGroup().getDescription(), "       Group Name",
491               "Group Description", ap.alignFrame,
492               "Edit Group Name / Description", 500, 100, true);
493
494       if (dialog.accept)
495       {
496         getGroup().setName(dialog.getName().replace(' ', '_'));
497         getGroup().setDescription(dialog.getDescription());
498       }
499
500     }
501     else if (source == copy)
502     {
503       ap.alignFrame.copy_actionPerformed();
504     }
505     else if (source == cut)
506     {
507       ap.alignFrame.cut_actionPerformed();
508     }
509     else if (source == editSequence)
510     {
511       SequenceGroup sg = ap.av.getSelectionGroup();
512
513       if (sg != null)
514       {
515         if (seq == null)
516           seq = (Sequence) sg.getSequenceAt(0);
517
518         EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString(
519                 sg.getStartRes(), sg.getEndRes() + 1), null,
520                 "Edit Sequence ", null,
521
522                 ap.alignFrame, "Edit Sequence", 500, 100, true);
523
524         if (dialog.accept)
525         {
526           EditCommand editCommand = new EditCommand("Edit Sequences",
527                   EditCommand.REPLACE, dialog.getName().replace(' ',
528                           ap.av.getGapCharacter()),
529                   sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
530                   sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
531
532           ap.alignFrame.addHistoryItem(editCommand);
533
534           ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
535                   .getSequences());
536         }
537       }
538     }
539     else if (source == toUpper || source == toLower || source == toggleCase)
540     {
541       SequenceGroup sg = ap.av.getSelectionGroup();
542       Vector regions = new Vector();
543       if (sg != null)
544       {
545         int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
546                 sg.getEndRes() + 1);
547
548         String description;
549         int caseChange;
550
551         if (source == toggleCase)
552         {
553           description = "Toggle Case";
554           caseChange = ChangeCaseCommand.TOGGLE_CASE;
555         }
556         else if (source == toUpper)
557         {
558           description = "To Upper Case";
559           caseChange = ChangeCaseCommand.TO_UPPER;
560         }
561         else
562         {
563           description = "To Lower Case";
564           caseChange = ChangeCaseCommand.TO_LOWER;
565         }
566
567         ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
568                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()), startEnd,
569                 caseChange);
570
571         ap.alignFrame.addHistoryItem(caseCommand);
572
573         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
574                 .getSequences());
575
576       }
577     }
578     else if (source == sequenceFeature)
579     {
580       SequenceGroup sg = ap.av.getSelectionGroup();
581       if (sg == null)
582       {
583         return;
584       }
585
586       int rsize = 0, gSize = sg.getSize();
587       SequenceI[] rseqs, seqs = new SequenceI[gSize];
588       SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
589
590       for (int i = 0; i < gSize; i++)
591       {
592         int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
593         int end = sg.findEndRes(sg.getSequenceAt(i));
594         if (start <= end)
595         {
596           seqs[rsize] = sg.getSequenceAt(i);
597           features[rsize] = new SequenceFeature(null, null, null, start,
598                   end, "Jalview");
599           rsize++;
600         }
601       }
602       rseqs = new SequenceI[rsize];
603       tfeatures = new SequenceFeature[rsize];
604       System.arraycopy(seqs, 0, rseqs, 0, rsize);
605       System.arraycopy(features, 0, tfeatures, 0, rsize);
606       features = tfeatures;
607       seqs = rseqs;
608
609       if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
610               features, true, ap))
611       {
612         ap.alignFrame.sequenceFeatures.setState(true);
613         ap.av.showSequenceFeatures(true);
614         ap.highlightSearchResults(null);
615       }
616     }
617     else
618     {
619       outputText(evt);
620     }
621
622   }
623
624
625   void outputText(ActionEvent e)
626   {
627     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);
628
629     Frame frame = new Frame();
630     frame.add(cap);
631     jalview.bin.JalviewLite.addFrame(frame,
632             "Selection output - " + e.getActionCommand(), 600, 500);
633     // JBPNote: getSelectionAsNewSequence behaviour has changed - this method now returns a full copy of sequence data
634     // TODO consider using getSequenceSelection instead here
635
636     cap.setText(new jalview.io.AppletFormatAdapter().formatSequences(
637             e.getActionCommand(),
638             new Alignment(ap.av.getSelectionAsNewSequence()),
639             ap.av.showJVSuffix));
640
641   }
642   protected void showSequenceSelectionDetails()
643   {
644     createSequenceDetailsReport(ap.av.getSequenceSelection());
645   }
646
647   protected void showSequenceDetails()
648   {
649     createSequenceDetailsReport(new SequenceI[]{seq});
650   }
651   public void createSequenceDetailsReport(SequenceI[] sequences)
652   {
653
654     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
655     
656     StringBuffer contents = new StringBuffer();
657     for (SequenceI seq:sequences)
658     {
659     contents.append("<p><h2>Annotation for "+seq.getDisplayId(true)+"</h2></p><p>");
660     new SequenceAnnotationReport(null)
661             .createSequenceAnnotationReport(
662                     contents,
663                     seq,
664                     true,
665                     true,false, 
666                     (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
667                             : null);
668     contents.append("</p>");
669     }
670     Frame frame = new Frame();
671     frame.add(cap);
672     jalview.bin.JalviewLite.addFrame(frame,
673             "Sequence Details for " + (sequences.length==1 ? sequences[0].getDisplayId(true) : "Selection")
674             , 600, 500);
675     cap.setText("<html>" + contents.toString() + "</html>");
676   }
677
678   void editName()
679   {
680     EditNameDialog dialog = new EditNameDialog(seq.getName(),
681             seq.getDescription(), "       Sequence Name",
682             "Sequence Description", ap.alignFrame,
683             "Edit Sequence Name / Description", 500, 100, true);
684
685     if (dialog.accept)
686     {
687       seq.setName(dialog.getName());
688       seq.setDescription(dialog.getDescription());
689       ap.paintAlignment(false);
690     }
691   }
692
693   void addPDB()
694   {
695     if (seq.getPDBId() != null)
696     {
697       PDBEntry entry = (PDBEntry) seq.getPDBId().firstElement();
698
699       if (ap.av.applet.jmolAvailable)
700         new jalview.appletgui.AppletJmol(entry, new Sequence[]
701         { seq }, null, ap, AppletFormatAdapter.URL);
702       else
703         new MCview.AppletPDBViewer(entry, new Sequence[]
704         { seq }, null, ap, AppletFormatAdapter.URL);
705
706     }
707     else
708     {
709       CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);
710       cap.setText("Paste your PDB file here.");
711       cap.setPDBImport(seq);
712       Frame frame = new Frame();
713       frame.add(cap);
714       jalview.bin.JalviewLite.addFrame(frame, "Paste PDB file for sequence "+seq.getName(), 400, 300);
715     }
716   }
717
718   private void jbInit() throws Exception
719   {
720     groupMenu.setLabel("Group");
721     groupMenu.setLabel("Selection");
722     sequenceFeature.addActionListener(this);
723
724     editGroupName.addActionListener(this);
725     unGroupMenuItem.setLabel("Remove Group");
726     unGroupMenuItem.addActionListener(this);
727
728     nucleotideMenuItem.setLabel("Nucleotide");
729     nucleotideMenuItem.addActionListener(this);
730     conservationMenuItem.addItemListener(this);
731     abovePIDColour.addItemListener(this);
732     colourMenu.setLabel("Group Colour");
733     showBoxes.setLabel("Boxes");
734     showBoxes.setState(true);
735     showBoxes.addItemListener(this);
736     sequenceName.addActionListener(this);
737     sequenceDetails.addActionListener(this);
738     selSeqDetails.addActionListener(this);
739     displayNonconserved.setLabel("Show Nonconserved");
740     displayNonconserved.setState(false);
741     displayNonconserved.addItemListener(this);
742     showText.setLabel("Text");
743     showText.addItemListener(this);
744     showColourText.setLabel("Colour Text");
745     showColourText.addItemListener(this);
746     outputmenu.setLabel("Output to Textbox...");
747     seqMenu.setLabel("Sequence");
748     pdb.setLabel("View PDB Structure");
749     hideSeqs.setLabel("Hide Sequences");
750     repGroup.setLabel("Represent Group with");
751     revealAll.setLabel("Reveal All");
752     revealSeq.setLabel("Reveal Sequences");
753     menu1.setLabel("Group");
754     add(groupMenu);
755     this.add(seqMenu);
756     this.add(hideSeqs);
757     this.add(revealSeq);
758     this.add(revealAll);
759     // groupMenu.add(selSeqDetails);
760     groupMenu.add(editGroupName);
761     groupMenu.add(editMenu);
762     groupMenu.add(outputmenu);
763     groupMenu.add(sequenceFeature);
764     groupMenu.add(menu1);
765
766     colourMenu.add(noColourmenuItem);
767     colourMenu.add(clustalColour);
768     colourMenu.add(BLOSUM62Colour);
769     colourMenu.add(PIDColour);
770     colourMenu.add(zappoColour);
771     colourMenu.add(taylorColour);
772     colourMenu.add(hydrophobicityColour);
773     colourMenu.add(helixColour);
774     colourMenu.add(strandColour);
775     colourMenu.add(turnColour);
776     colourMenu.add(buriedColour);
777     colourMenu.add(nucleotideMenuItem);
778     colourMenu.add(userDefinedColour);
779     colourMenu.addSeparator();
780     colourMenu.add(abovePIDColour);
781     colourMenu.add(conservationMenuItem);
782
783     noColourmenuItem.setLabel("None");
784     noColourmenuItem.addActionListener(this);
785
786     clustalColour.setLabel("Clustalx colours");
787     clustalColour.addActionListener(this);
788     zappoColour.setLabel("Zappo");
789     zappoColour.addActionListener(this);
790     taylorColour.setLabel("Taylor");
791     taylorColour.addActionListener(this);
792     hydrophobicityColour.setLabel("Hydrophobicity");
793     hydrophobicityColour.addActionListener(this);
794     helixColour.setLabel("Helix propensity");
795     helixColour.addActionListener(this);
796     strandColour.setLabel("Strand propensity");
797     strandColour.addActionListener(this);
798     turnColour.setLabel("Turn propensity");
799     turnColour.addActionListener(this);
800     buriedColour.setLabel("Buried Index");
801     buriedColour.addActionListener(this);
802     abovePIDColour.setLabel("Above % Identity");
803
804     userDefinedColour.setLabel("User Defined");
805     userDefinedColour.addActionListener(this);
806     PIDColour.setLabel("Percentage Identity");
807     PIDColour.addActionListener(this);
808     BLOSUM62Colour.setLabel("BLOSUM62");
809     BLOSUM62Colour.addActionListener(this);
810     conservationMenuItem.setLabel("Conservation");
811
812     editMenu.add(copy);
813     copy.addActionListener(this);
814     editMenu.add(cut);
815     cut.addActionListener(this);
816
817     editMenu.add(editSequence);
818     editSequence.addActionListener(this);
819
820     editMenu.add(toUpper);
821     toUpper.addActionListener(this);
822     editMenu.add(toLower);
823     toLower.addActionListener(this);
824     editMenu.add(toggleCase);
825     seqMenu.add(sequenceName);
826     // seqMenu.add(sequenceDetails);
827     
828     if (!ap.av.applet.useXtrnalSviewer)
829     {
830       seqMenu.add(pdb);
831     }
832     seqMenu.add(repGroup);
833     menu1.add(unGroupMenuItem);
834     menu1.add(colourMenu);
835     menu1.add(showBoxes);
836     menu1.add(showText);
837     menu1.add(showColourText);
838     menu1.add(displayNonconserved);
839     toggleCase.addActionListener(this);
840     pdb.addActionListener(this);
841     hideSeqs.addActionListener(this);
842     repGroup.addActionListener(this);
843     revealAll.addActionListener(this);
844     revealSeq.addActionListener(this);
845   }
846
847   void refresh()
848   {
849     ap.paintAlignment(true);
850   }
851
852   protected void clustalColour_actionPerformed()
853   {
854     SequenceGroup sg = getGroup();
855     sg.cs = new ClustalxColourScheme(
856             sg,ap.av.getHiddenRepSequences());
857     refresh();
858   }
859
860   protected void zappoColour_actionPerformed()
861   {
862     getGroup().cs = new ZappoColourScheme();
863     refresh();
864   }
865
866   protected void taylorColour_actionPerformed()
867   {
868     getGroup().cs = new TaylorColourScheme();
869     refresh();
870   }
871
872   protected void hydrophobicityColour_actionPerformed()
873   {
874     getGroup().cs = new HydrophobicColourScheme();
875     refresh();
876   }
877
878   protected void helixColour_actionPerformed()
879   {
880     getGroup().cs = new HelixColourScheme();
881     refresh();
882   }
883
884   protected void strandColour_actionPerformed()
885   {
886     getGroup().cs = new StrandColourScheme();
887     refresh();
888   }
889
890   protected void turnColour_actionPerformed()
891   {
892     getGroup().cs = new TurnColourScheme();
893     refresh();
894   }
895
896   protected void buriedColour_actionPerformed()
897   {
898     getGroup().cs = new BuriedColourScheme();
899     refresh();
900   }
901
902   public void nucleotideMenuItem_actionPerformed()
903   {
904     getGroup().cs = new NucleotideColourScheme();
905     refresh();
906   }
907
908   protected void abovePIDColour_itemStateChanged()
909   {
910     SequenceGroup sg = getGroup();
911     if (sg.cs == null)
912     {
913       return;
914     }
915
916     if (abovePIDColour.getState())
917     {
918       sg.cs.setConsensus(AAFrequency.calculate(
919               sg.getSequences(ap.av.getHiddenRepSequences()), 0,
920               ap.av.getAlignment().getWidth()));
921       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
922               .getName());
923
924       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
925
926       SliderPanel.showPIDSlider();
927
928     }
929     else
930     // remove PIDColouring
931     {
932       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
933     }
934
935     refresh();
936
937   }
938
939   protected void userDefinedColour_actionPerformed()
940   {
941     new UserDefinedColours(ap, getGroup());
942   }
943
944   protected void PIDColour_actionPerformed()
945   {
946     SequenceGroup sg = getGroup();
947     sg.cs = new PIDColourScheme();
948     sg.cs.setConsensus(AAFrequency.calculate(
949             sg.getSequences(ap.av.getHiddenRepSequences()), 0,
950             ap.av.getAlignment().getWidth()));
951     refresh();
952   }
953
954   protected void BLOSUM62Colour_actionPerformed()
955   {
956     SequenceGroup sg = getGroup();
957
958     sg.cs = new Blosum62ColourScheme();
959
960     sg.cs.setConsensus(AAFrequency.calculate(
961             sg.getSequences(ap.av.getHiddenRepSequences()), 0,
962             ap.av.getAlignment().getWidth()));
963
964     refresh();
965   }
966
967   protected void noColourmenuItem_actionPerformed()
968   {
969     getGroup().cs = null;
970     refresh();
971   }
972
973   protected void conservationMenuItem_itemStateChanged()
974   {
975     SequenceGroup sg = getGroup();
976     if (sg.cs == null)
977     {
978       return;
979     }
980
981     if (conservationMenuItem.getState())
982     {
983
984       sg.cs.setConservation(Conservation.calculateConservation("Group",
985               ResidueProperties.propHash, 3,
986               sg.getSequences(ap.av.getHiddenRepSequences()), 0,
987               ap.av.getAlignment().getWidth(),
988               false, ap.av.getConsPercGaps(),false));
989       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
990       SliderPanel.showConservationSlider();
991     }
992     else
993     // remove ConservationColouring
994     {
995       sg.cs.setConservation(null);
996     }
997
998     refresh();
999   }
1000
1001   SequenceGroup getGroup()
1002   {
1003     SequenceGroup sg = ap.av.getSelectionGroup();
1004
1005     // this method won't add a new group if it already exists
1006     if (sg != null)
1007     {
1008       ap.av.getAlignment().addGroup(sg);
1009     }
1010
1011     return sg;
1012   }
1013
1014   void unGroupMenuItem_actionPerformed()
1015   {
1016     SequenceGroup sg = ap.av.getSelectionGroup();
1017     ap.av.getAlignment().deleteGroup(sg);
1018     ap.av.setSelectionGroup(null);
1019     ap.paintAlignment(true);
1020   }
1021
1022   public void showColourText_itemStateChanged()
1023   {
1024     getGroup().setColourText(showColourText.getState());
1025     refresh();
1026   }
1027
1028   public void showText_itemStateChanged()
1029   {
1030     getGroup().setDisplayText(showText.getState());
1031     refresh();
1032   }
1033
1034   public void showNonconserved_itemStateChanged()
1035   {
1036     getGroup().setShowNonconserved(this.displayNonconserved.getState());
1037     refresh();
1038   }
1039
1040   public void showBoxes_itemStateChanged()
1041   {
1042     getGroup().setDisplayBoxes(showBoxes.getState());
1043     refresh();
1044   }
1045
1046   void hideSequences(boolean representGroup)
1047   {
1048     SequenceGroup sg = ap.av.getSelectionGroup();
1049     if (sg == null || sg.getSize() < 1)
1050     {
1051       ap.av.hideSequence(new SequenceI[]
1052       { seq });
1053       return;
1054     }
1055
1056     ap.av.setSelectionGroup(null);
1057
1058     if (representGroup)
1059     {
1060       ap.av.hideRepSequences(seq, sg);
1061
1062       return;
1063     }
1064
1065     int gsize = sg.getSize();
1066     SequenceI[] hseqs;
1067
1068     hseqs = new SequenceI[gsize];
1069
1070     int index = 0;
1071     for (int i = 0; i < gsize; i++)
1072     {
1073       hseqs[index++] = sg.getSequenceAt(i);
1074     }
1075
1076     ap.av.hideSequence(hseqs);
1077     ap.av.sendSelection();
1078   }
1079
1080 }