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