JAL-1367 entry in sequence ID popup menu to set/unset sequence as representative
[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 import java.awt.*;
22 import java.awt.event.*;
23
24 import jalview.analysis.*;
25 import jalview.commands.*;
26 import jalview.datamodel.*;
27 import jalview.schemes.*;
28 import jalview.util.UrlLink;
29 import jalview.io.AppletFormatAdapter;
30 import jalview.io.SequenceAnnotationReport;
31
32 public class APopupMenu extends java.awt.PopupMenu implements
33         ActionListener, ItemListener
34 {
35   Menu groupMenu = new Menu();
36
37   MenuItem editGroupName = new MenuItem();
38
39   protected MenuItem clustalColour = new MenuItem();
40
41   protected MenuItem zappoColour = new MenuItem();
42
43   protected MenuItem taylorColour = new MenuItem();
44
45   protected MenuItem hydrophobicityColour = new MenuItem();
46
47   protected MenuItem helixColour = new MenuItem();
48
49   protected MenuItem strandColour = new MenuItem();
50
51   protected MenuItem turnColour = new MenuItem();
52
53   protected MenuItem buriedColour = new MenuItem();
54
55   protected CheckboxMenuItem abovePIDColour = new CheckboxMenuItem();
56
57   protected MenuItem userDefinedColour = new MenuItem();
58
59   protected MenuItem PIDColour = new MenuItem();
60
61   protected MenuItem BLOSUM62Colour = new MenuItem();
62
63   MenuItem noColourmenuItem = new MenuItem();
64
65   protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
66
67   final AlignmentPanel ap;
68
69   MenuItem unGroupMenuItem = new MenuItem();
70
71   MenuItem nucleotideMenuItem = new MenuItem();
72
73   Menu colourMenu = new Menu();
74
75   CheckboxMenuItem showBoxes = new CheckboxMenuItem();
76
77   CheckboxMenuItem showText = new CheckboxMenuItem();
78
79   CheckboxMenuItem showColourText = new CheckboxMenuItem();
80
81   CheckboxMenuItem displayNonconserved = new CheckboxMenuItem();
82
83   Menu editMenu = new Menu("Edit");
84
85   MenuItem copy = new MenuItem("Copy (Jalview Only)");
86
87   MenuItem cut = new MenuItem("Cut (Jalview Only)");
88
89   MenuItem toUpper = new MenuItem("To Upper Case");
90
91   MenuItem toLower = new MenuItem("To Lower Case");
92
93   MenuItem toggleCase = new MenuItem("Toggle Case");
94
95   Menu outputmenu = new Menu();
96
97   Menu seqMenu = new Menu();
98
99   MenuItem pdb = new MenuItem();
100
101   MenuItem hideSeqs = new MenuItem();
102
103   MenuItem repGroup = new MenuItem();
104
105   MenuItem sequenceName = new MenuItem("Edit Name/Description");
106
107   MenuItem sequenceFeature = new MenuItem("Create Sequence Feature");
108
109   MenuItem editSequence = new MenuItem("Edit Sequence");
110
111   MenuItem sequenceDetails = new MenuItem("Sequence Details ...");
112
113   MenuItem selSeqDetails = new MenuItem("Sequence Details ...");
114
115   MenuItem makeReferenceSeq = new MenuItem();
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       if (seq == ap.av.getAlignment().getSeqrep())
305       {
306         makeReferenceSeq.setLabel("Unmark representative");
307       } else {
308         makeReferenceSeq.setLabel("Mark as representative");
309       }
310       repGroup.setLabel("Represent Group with " + seq.getName());
311     }
312     else
313     {
314       remove(seqMenu);
315     }
316
317     if (!ap.av.hasHiddenRows())
318     {
319       remove(revealAll);
320       remove(revealSeq);
321     }
322     else
323     {
324       final int index = ap.av.getAlignment().findIndex(seq);
325
326       if (ap.av.adjustForHiddenSeqs(index)
327               - ap.av.adjustForHiddenSeqs(index - 1) > 1)
328       {
329         revealSeq_index = index;
330       }
331       else
332       {
333         remove(revealSeq);
334       }
335     }
336   }
337
338   /**
339    * add a show URL menu item to the given linkMenu
340    * 
341    * @param linkMenu
342    * @param target
343    *          - menu label string
344    * @param url
345    *          - url to open
346    */
347   private void addshowLink(Menu linkMenu, final String target,
348           final String url)
349   {
350     addshowLink(linkMenu, target, target, url);
351   }
352
353   /**
354    * add a show URL menu item to the given linkMenu
355    * 
356    * @param linkMenu
357    * @param target
358    *          - URL target window
359    * @param label
360    *          - menu label string
361    * @param url
362    *          - url to open
363    */
364   private void addshowLink(Menu linkMenu, final String target,
365           final String label, final String url)
366   {
367     MenuItem item = new MenuItem(label);
368     item.addActionListener(new java.awt.event.ActionListener()
369     {
370       public void actionPerformed(ActionEvent e)
371       {
372         ap.alignFrame.showURL(url, target);
373       }
374     });
375     linkMenu.add(item);
376   }
377
378   public void itemStateChanged(ItemEvent evt)
379   {
380     if (evt.getSource() == abovePIDColour)
381     {
382       abovePIDColour_itemStateChanged();
383     }
384     else if (evt.getSource() == showColourText)
385     {
386       showColourText_itemStateChanged();
387     }
388     else if (evt.getSource() == showText)
389     {
390       showText_itemStateChanged();
391     }
392     else if (evt.getSource() == showBoxes)
393     {
394       showBoxes_itemStateChanged();
395     }
396     else if (evt.getSource() == displayNonconserved)
397     {
398       this.showNonconserved_itemStateChanged();
399     }
400   }
401
402   public void actionPerformed(ActionEvent evt)
403   {
404     Object source = evt.getSource();
405     if (source == clustalColour)
406     {
407       clustalColour_actionPerformed();
408     }
409     else if (source == zappoColour)
410     {
411       zappoColour_actionPerformed();
412     }
413     else if (source == taylorColour)
414     {
415       taylorColour_actionPerformed();
416     }
417     else if (source == hydrophobicityColour)
418     {
419       hydrophobicityColour_actionPerformed();
420     }
421     else if (source == helixColour)
422     {
423       helixColour_actionPerformed();
424     }
425     else if (source == strandColour)
426     {
427       strandColour_actionPerformed();
428     }
429     else if (source == turnColour)
430     {
431       turnColour_actionPerformed();
432     }
433     else if (source == buriedColour)
434     {
435       buriedColour_actionPerformed();
436     }
437     else if (source == nucleotideMenuItem)
438     {
439       nucleotideMenuItem_actionPerformed();
440     }
441
442     else if (source == userDefinedColour)
443     {
444       userDefinedColour_actionPerformed();
445     }
446     else if (source == PIDColour)
447     {
448       PIDColour_actionPerformed();
449     }
450     else if (source == BLOSUM62Colour)
451     {
452       BLOSUM62Colour_actionPerformed();
453     }
454     else if (source == noColourmenuItem)
455     {
456       noColourmenuItem_actionPerformed();
457     }
458     else if (source == conservationMenuItem)
459     {
460       conservationMenuItem_itemStateChanged();
461     }
462     else if (source == unGroupMenuItem)
463     {
464       unGroupMenuItem_actionPerformed();
465     }
466
467     else if (source == sequenceName)
468     {
469       editName();
470     }
471     else if (source == makeReferenceSeq)
472     {
473       makeReferenceSeq_actionPerformed();
474     }
475     else if (source == sequenceDetails)
476     {
477       showSequenceDetails();
478     }
479     else if (source == selSeqDetails)
480     {
481       showSequenceSelectionDetails();
482     }
483     else if (source == pdb)
484     {
485       addPDB();
486     }
487     else if (source == hideSeqs)
488     {
489       hideSequences(false);
490     }
491     else if (source == repGroup)
492     {
493       hideSequences(true);
494     }
495     else if (source == revealSeq)
496     {
497       ap.av.showSequence(revealSeq_index);
498     }
499     else if (source == revealAll)
500     {
501       ap.av.showAllHiddenSeqs();
502     }
503
504     else if (source == editGroupName)
505     {
506       EditNameDialog dialog = new EditNameDialog(getGroup().getName(),
507               getGroup().getDescription(), "       Group Name",
508               "Group Description", ap.alignFrame,
509               "Edit Group Name / Description", 500, 100, true);
510
511       if (dialog.accept)
512       {
513         getGroup().setName(dialog.getName().replace(' ', '_'));
514         getGroup().setDescription(dialog.getDescription());
515       }
516
517     }
518     else if (source == copy)
519     {
520       ap.alignFrame.copy_actionPerformed();
521     }
522     else if (source == cut)
523     {
524       ap.alignFrame.cut_actionPerformed();
525     }
526     else if (source == editSequence)
527     {
528       SequenceGroup sg = ap.av.getSelectionGroup();
529
530       if (sg != null)
531       {
532         if (seq == null)
533           seq = (Sequence) sg.getSequenceAt(0);
534
535         EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString(
536                 sg.getStartRes(), sg.getEndRes() + 1), null,
537                 "Edit Sequence ", null,
538
539                 ap.alignFrame, "Edit Sequence", 500, 100, true);
540
541         if (dialog.accept)
542         {
543           EditCommand editCommand = new EditCommand("Edit Sequences",
544                   EditCommand.REPLACE, dialog.getName().replace(' ',
545                           ap.av.getGapCharacter()),
546                   sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
547                   sg.getStartRes(), sg.getEndRes() + 1,
548                   ap.av.getAlignment());
549
550           ap.alignFrame.addHistoryItem(editCommand);
551
552           ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
553                   .getSequences());
554         }
555       }
556     }
557     else if (source == toUpper || source == toLower || source == toggleCase)
558     {
559       SequenceGroup sg = ap.av.getSelectionGroup();
560       Vector regions = new Vector();
561       if (sg != null)
562       {
563         int[][] startEnd = ap.av.getVisibleRegionBoundaries(
564                 sg.getStartRes(), sg.getEndRes() + 1);
565
566         String description;
567         int caseChange;
568
569         if (source == toggleCase)
570         {
571           description = "Toggle Case";
572           caseChange = ChangeCaseCommand.TOGGLE_CASE;
573         }
574         else if (source == toUpper)
575         {
576           description = "To Upper Case";
577           caseChange = ChangeCaseCommand.TO_UPPER;
578         }
579         else
580         {
581           description = "To Lower Case";
582           caseChange = ChangeCaseCommand.TO_LOWER;
583         }
584
585         ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
586                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
587                 startEnd, caseChange);
588
589         ap.alignFrame.addHistoryItem(caseCommand);
590
591         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
592                 .getSequences());
593
594       }
595     }
596     else if (source == sequenceFeature)
597     {
598       SequenceGroup sg = ap.av.getSelectionGroup();
599       if (sg == null)
600       {
601         return;
602       }
603
604       int rsize = 0, gSize = sg.getSize();
605       SequenceI[] rseqs, seqs = new SequenceI[gSize];
606       SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
607
608       for (int i = 0; i < gSize; i++)
609       {
610         int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
611         int end = sg.findEndRes(sg.getSequenceAt(i));
612         if (start <= end)
613         {
614           seqs[rsize] = sg.getSequenceAt(i);
615           features[rsize] = new SequenceFeature(null, null, null, start,
616                   end, "Jalview");
617           rsize++;
618         }
619       }
620       rseqs = new SequenceI[rsize];
621       tfeatures = new SequenceFeature[rsize];
622       System.arraycopy(seqs, 0, rseqs, 0, rsize);
623       System.arraycopy(features, 0, tfeatures, 0, rsize);
624       features = tfeatures;
625       seqs = rseqs;
626
627       if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
628               features, true, ap))
629       {
630         ap.alignFrame.sequenceFeatures.setState(true);
631         ap.av.showSequenceFeatures(true);
632         ap.highlightSearchResults(null);
633       }
634     }
635     else
636     {
637       outputText(evt);
638     }
639
640   }
641
642   void outputText(ActionEvent e)
643   {
644     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);
645
646     Frame frame = new Frame();
647     frame.add(cap);
648     jalview.bin.JalviewLite.addFrame(frame,
649             "Selection output - " + e.getActionCommand(), 600, 500);
650     // JBPNote: getSelectionAsNewSequence behaviour has changed - this method
651     // now returns a full copy of sequence data
652     // TODO consider using getSequenceSelection instead here
653
654     cap.setText(new jalview.io.AppletFormatAdapter().formatSequences(
655             e.getActionCommand(),
656             new Alignment(ap.av.getSelectionAsNewSequence()),
657             ap.av.showJVSuffix));
658
659   }
660
661   protected void showSequenceSelectionDetails()
662   {
663     createSequenceDetailsReport(ap.av.getSequenceSelection());
664   }
665
666   protected void showSequenceDetails()
667   {
668     createSequenceDetailsReport(new SequenceI[]
669     { seq });
670   }
671
672   public void createSequenceDetailsReport(SequenceI[] sequences)
673   {
674
675     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
676
677     StringBuffer contents = new StringBuffer();
678     for (SequenceI seq : sequences)
679     {
680       contents.append("<p><h2>Annotation for " + seq.getDisplayId(true)
681               + "</h2></p><p>");
682       new SequenceAnnotationReport(null)
683               .createSequenceAnnotationReport(
684                       contents,
685                       seq,
686                       true,
687                       true,
688                       false,
689                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
690                               : null);
691       contents.append("</p>");
692     }
693     Frame frame = new Frame();
694     frame.add(cap);
695     jalview.bin.JalviewLite.addFrame(frame, "Sequence Details for "
696             + (sequences.length == 1 ? sequences[0].getDisplayId(true)
697                     : "Selection"), 600, 500);
698     cap.setText("<html>" + contents.toString() + "</html>");
699   }
700
701   void editName()
702   {
703     EditNameDialog dialog = new EditNameDialog(seq.getName(),
704             seq.getDescription(), "       Sequence Name",
705             "Sequence Description", ap.alignFrame,
706             "Edit Sequence Name / Description", 500, 100, true);
707
708     if (dialog.accept)
709     {
710       seq.setName(dialog.getName());
711       seq.setDescription(dialog.getDescription());
712       ap.paintAlignment(false);
713     }
714   }
715
716   void addPDB()
717   {
718     if (seq.getPDBId() != null)
719     {
720       PDBEntry entry = (PDBEntry) seq.getPDBId().firstElement();
721
722       if (ap.av.applet.jmolAvailable)
723         new jalview.appletgui.AppletJmol(entry, new Sequence[]
724         { seq }, null, ap, AppletFormatAdapter.URL);
725       else
726         new MCview.AppletPDBViewer(entry, new Sequence[]
727         { seq }, null, ap, AppletFormatAdapter.URL);
728
729     }
730     else
731     {
732       CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);
733       cap.setText("Paste your PDB file here.");
734       cap.setPDBImport(seq);
735       Frame frame = new Frame();
736       frame.add(cap);
737       jalview.bin.JalviewLite.addFrame(frame,
738               "Paste PDB file for sequence " + seq.getName(), 400, 300);
739     }
740   }
741
742   private void jbInit() throws Exception
743   {
744     groupMenu.setLabel("Group");
745     groupMenu.setLabel("Selection");
746     sequenceFeature.addActionListener(this);
747
748     editGroupName.addActionListener(this);
749     unGroupMenuItem.setLabel("Remove Group");
750     unGroupMenuItem.addActionListener(this);
751
752     nucleotideMenuItem.setLabel("Nucleotide");
753     nucleotideMenuItem.addActionListener(this);
754     conservationMenuItem.addItemListener(this);
755     abovePIDColour.addItemListener(this);
756     colourMenu.setLabel("Group Colour");
757     showBoxes.setLabel("Boxes");
758     showBoxes.setState(true);
759     showBoxes.addItemListener(this);
760     sequenceName.addActionListener(this);
761     sequenceDetails.addActionListener(this);
762     selSeqDetails.addActionListener(this);
763     displayNonconserved.setLabel("Show Nonconserved");
764     displayNonconserved.setState(false);
765     displayNonconserved.addItemListener(this);
766     showText.setLabel("Text");
767     showText.addItemListener(this);
768     showColourText.setLabel("Colour Text");
769     showColourText.addItemListener(this);
770     outputmenu.setLabel("Output to Textbox...");
771     seqMenu.setLabel("Sequence");
772     pdb.setLabel("View PDB Structure");
773     hideSeqs.setLabel("Hide Sequences");
774     repGroup.setLabel("Represent Group with");
775     revealAll.setLabel("Reveal All");
776     revealSeq.setLabel("Reveal Sequences");
777     menu1.setLabel("Group");
778     add(groupMenu);
779     this.add(seqMenu);
780     this.add(hideSeqs);
781     this.add(revealSeq);
782     this.add(revealAll);
783     // groupMenu.add(selSeqDetails);
784     groupMenu.add(editGroupName);
785     groupMenu.add(editMenu);
786     groupMenu.add(outputmenu);
787     groupMenu.add(sequenceFeature);
788     groupMenu.add(menu1);
789
790     colourMenu.add(noColourmenuItem);
791     colourMenu.add(clustalColour);
792     colourMenu.add(BLOSUM62Colour);
793     colourMenu.add(PIDColour);
794     colourMenu.add(zappoColour);
795     colourMenu.add(taylorColour);
796     colourMenu.add(hydrophobicityColour);
797     colourMenu.add(helixColour);
798     colourMenu.add(strandColour);
799     colourMenu.add(turnColour);
800     colourMenu.add(buriedColour);
801     colourMenu.add(nucleotideMenuItem);
802     colourMenu.add(userDefinedColour);
803     colourMenu.addSeparator();
804     colourMenu.add(abovePIDColour);
805     colourMenu.add(conservationMenuItem);
806
807     noColourmenuItem.setLabel("None");
808     noColourmenuItem.addActionListener(this);
809
810     clustalColour.setLabel("Clustalx colours");
811     clustalColour.addActionListener(this);
812     zappoColour.setLabel("Zappo");
813     zappoColour.addActionListener(this);
814     taylorColour.setLabel("Taylor");
815     taylorColour.addActionListener(this);
816     hydrophobicityColour.setLabel("Hydrophobicity");
817     hydrophobicityColour.addActionListener(this);
818     helixColour.setLabel("Helix propensity");
819     helixColour.addActionListener(this);
820     strandColour.setLabel("Strand propensity");
821     strandColour.addActionListener(this);
822     turnColour.setLabel("Turn propensity");
823     turnColour.addActionListener(this);
824     buriedColour.setLabel("Buried Index");
825     buriedColour.addActionListener(this);
826     abovePIDColour.setLabel("Above % Identity");
827
828     userDefinedColour.setLabel("User Defined");
829     userDefinedColour.addActionListener(this);
830     PIDColour.setLabel("Percentage Identity");
831     PIDColour.addActionListener(this);
832     BLOSUM62Colour.setLabel("BLOSUM62");
833     BLOSUM62Colour.addActionListener(this);
834     conservationMenuItem.setLabel("Conservation");
835
836     editMenu.add(copy);
837     copy.addActionListener(this);
838     editMenu.add(cut);
839     cut.addActionListener(this);
840
841     editMenu.add(editSequence);
842     editSequence.addActionListener(this);
843
844     editMenu.add(toUpper);
845     toUpper.addActionListener(this);
846     editMenu.add(toLower);
847     toLower.addActionListener(this);
848     editMenu.add(toggleCase);
849     seqMenu.add(sequenceName);
850     seqMenu.add(makeReferenceSeq);
851     // seqMenu.add(sequenceDetails);
852
853     if (!ap.av.applet.useXtrnalSviewer)
854     {
855       seqMenu.add(pdb);
856     }
857     seqMenu.add(repGroup);
858     menu1.add(unGroupMenuItem);
859     menu1.add(colourMenu);
860     menu1.add(showBoxes);
861     menu1.add(showText);
862     menu1.add(showColourText);
863     menu1.add(displayNonconserved);
864     toggleCase.addActionListener(this);
865     pdb.addActionListener(this);
866     hideSeqs.addActionListener(this);
867     repGroup.addActionListener(this);
868     revealAll.addActionListener(this);
869     revealSeq.addActionListener(this);
870     makeReferenceSeq.addActionListener(this);
871   }
872
873   void refresh()
874   {
875     ap.paintAlignment(true);
876   }
877
878   protected void clustalColour_actionPerformed()
879   {
880     SequenceGroup sg = getGroup();
881     sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
882     refresh();
883   }
884
885   protected void zappoColour_actionPerformed()
886   {
887     getGroup().cs = new ZappoColourScheme();
888     refresh();
889   }
890
891   protected void taylorColour_actionPerformed()
892   {
893     getGroup().cs = new TaylorColourScheme();
894     refresh();
895   }
896
897   protected void hydrophobicityColour_actionPerformed()
898   {
899     getGroup().cs = new HydrophobicColourScheme();
900     refresh();
901   }
902
903   protected void helixColour_actionPerformed()
904   {
905     getGroup().cs = new HelixColourScheme();
906     refresh();
907   }
908
909   protected void strandColour_actionPerformed()
910   {
911     getGroup().cs = new StrandColourScheme();
912     refresh();
913   }
914
915   protected void turnColour_actionPerformed()
916   {
917     getGroup().cs = new TurnColourScheme();
918     refresh();
919   }
920
921   protected void buriedColour_actionPerformed()
922   {
923     getGroup().cs = new BuriedColourScheme();
924     refresh();
925   }
926
927   public void nucleotideMenuItem_actionPerformed()
928   {
929     getGroup().cs = new NucleotideColourScheme();
930     refresh();
931   }
932
933   protected void abovePIDColour_itemStateChanged()
934   {
935     SequenceGroup sg = getGroup();
936     if (sg.cs == null)
937     {
938       return;
939     }
940
941     if (abovePIDColour.getState())
942     {
943       sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
944               .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
945       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
946               .getName());
947
948       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
949
950       SliderPanel.showPIDSlider();
951
952     }
953     else
954     // remove PIDColouring
955     {
956       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
957     }
958
959     refresh();
960
961   }
962
963   protected void userDefinedColour_actionPerformed()
964   {
965     new UserDefinedColours(ap, getGroup());
966   }
967
968   protected void PIDColour_actionPerformed()
969   {
970     SequenceGroup sg = getGroup();
971     sg.cs = new PIDColourScheme();
972     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
973             .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
974     refresh();
975   }
976
977   protected void BLOSUM62Colour_actionPerformed()
978   {
979     SequenceGroup sg = getGroup();
980
981     sg.cs = new Blosum62ColourScheme();
982
983     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
984             .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
985
986     refresh();
987   }
988
989   protected void noColourmenuItem_actionPerformed()
990   {
991     getGroup().cs = null;
992     refresh();
993   }
994
995   protected void conservationMenuItem_itemStateChanged()
996   {
997     SequenceGroup sg = getGroup();
998     if (sg.cs == null)
999     {
1000       return;
1001     }
1002
1003     if (conservationMenuItem.getState())
1004     {
1005
1006       sg.cs.setConservation(Conservation.calculateConservation("Group",
1007               ResidueProperties.propHash, 3, sg.getSequences(ap.av
1008                       .getHiddenRepSequences()), 0, ap.av.getAlignment()
1009                       .getWidth(), false, ap.av.getConsPercGaps(), false));
1010       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1011       SliderPanel.showConservationSlider();
1012     }
1013     else
1014     // remove ConservationColouring
1015     {
1016       sg.cs.setConservation(null);
1017     }
1018
1019     refresh();
1020   }
1021
1022   SequenceGroup getGroup()
1023   {
1024     SequenceGroup sg = ap.av.getSelectionGroup();
1025
1026     // this method won't add a new group if it already exists
1027     if (sg != null)
1028     {
1029       ap.av.getAlignment().addGroup(sg);
1030     }
1031
1032     return sg;
1033   }
1034
1035   void unGroupMenuItem_actionPerformed()
1036   {
1037     SequenceGroup sg = ap.av.getSelectionGroup();
1038     ap.av.getAlignment().deleteGroup(sg);
1039     ap.av.setSelectionGroup(null);
1040     ap.paintAlignment(true);
1041   }
1042
1043   public void showColourText_itemStateChanged()
1044   {
1045     getGroup().setColourText(showColourText.getState());
1046     refresh();
1047   }
1048
1049   public void showText_itemStateChanged()
1050   {
1051     getGroup().setDisplayText(showText.getState());
1052     refresh();
1053   }
1054   public void makeReferenceSeq_actionPerformed()
1055   {
1056     if (!ap.av.getAlignment().hasSeqrep())
1057     {
1058       // initialise the display flags so the user sees something happen
1059       ap.av.setDisplayReferenceSeq(true);
1060       ap.av.setColourByReferenceSeq(true);
1061       ap.av.getAlignment().setSeqrep(seq);
1062     }
1063     else
1064     {
1065       if (ap.av.getAlignment().getSeqrep() == seq)
1066       {
1067         ap.av.getAlignment().setSeqrep(null);
1068       }
1069       else
1070       {
1071         ap.av.getAlignment().setSeqrep(seq);
1072       }
1073     }
1074     refresh();
1075   }
1076
1077   public void showNonconserved_itemStateChanged()
1078   {
1079     getGroup().setShowNonconserved(this.displayNonconserved.getState());
1080     refresh();
1081   }
1082
1083   public void showBoxes_itemStateChanged()
1084   {
1085     getGroup().setDisplayBoxes(showBoxes.getState());
1086     refresh();
1087   }
1088
1089   void hideSequences(boolean representGroup)
1090   {
1091     SequenceGroup sg = ap.av.getSelectionGroup();
1092     if (sg == null || sg.getSize() < 1)
1093     {
1094       ap.av.hideSequence(new SequenceI[]
1095       { seq });
1096       return;
1097     }
1098
1099     ap.av.setSelectionGroup(null);
1100
1101     if (representGroup)
1102     {
1103       ap.av.hideRepSequences(seq, sg);
1104
1105       return;
1106     }
1107
1108     int gsize = sg.getSize();
1109     SequenceI[] hseqs;
1110
1111     hseqs = new SequenceI[gsize];
1112
1113     int index = 0;
1114     for (int i = 0; i < gsize; i++)
1115     {
1116       hseqs[index++] = sg.getSequenceAt(i);
1117     }
1118
1119     ap.av.hideSequence(hseqs);
1120     ap.av.sendSelection();
1121   }
1122
1123 }