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