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