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