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