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