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