e688177442f652a79a4a8e01b23513c554d860e9
[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.Vector;
60
61 public class APopupMenu extends java.awt.PopupMenu implements
62         ActionListener, ItemListener
63 {
64   Menu groupMenu = new Menu();
65
66   MenuItem editGroupName = new MenuItem();
67
68   protected MenuItem clustalColour = new MenuItem();
69
70   protected MenuItem zappoColour = new MenuItem();
71
72   protected MenuItem taylorColour = new MenuItem();
73
74   protected MenuItem hydrophobicityColour = new MenuItem();
75
76   protected MenuItem helixColour = new MenuItem();
77
78   protected MenuItem strandColour = new MenuItem();
79
80   protected MenuItem turnColour = new MenuItem();
81
82   protected MenuItem buriedColour = new MenuItem();
83
84   protected CheckboxMenuItem abovePIDColour = new CheckboxMenuItem();
85
86   protected MenuItem userDefinedColour = new MenuItem();
87
88   protected MenuItem PIDColour = new MenuItem();
89
90   protected MenuItem BLOSUM62Colour = new MenuItem();
91
92   MenuItem noColourmenuItem = new MenuItem();
93
94   protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
95
96   final AlignmentPanel ap;
97
98   MenuItem unGroupMenuItem = new MenuItem();
99
100   MenuItem createGroupMenuItem = new MenuItem();
101
102   MenuItem nucleotideMenuItem = new MenuItem();
103
104   Menu colourMenu = new Menu();
105
106   CheckboxMenuItem showBoxes = new CheckboxMenuItem();
107
108   CheckboxMenuItem showText = new CheckboxMenuItem();
109
110   CheckboxMenuItem showColourText = new CheckboxMenuItem();
111
112   CheckboxMenuItem displayNonconserved = new CheckboxMenuItem();
113
114   Menu editMenu = new Menu(MessageManager.getString("action.edit"));
115
116   MenuItem copy = new MenuItem(
117           MessageManager.getString("label.jalview_copy"));
118
119   MenuItem cut = new MenuItem(MessageManager.getString("label.jalview_cut"));
120
121   MenuItem toUpper = new MenuItem(
122           MessageManager.getString("label.to_upper_case"));
123
124   MenuItem toLower = new MenuItem(
125           MessageManager.getString("label.to_lower_case"));
126
127   MenuItem toggleCase = new MenuItem(
128           MessageManager.getString("label.toggle_case"));
129
130   Menu outputmenu = new Menu();
131
132   Menu seqMenu = new Menu();
133
134   MenuItem pdb = new MenuItem();
135
136   MenuItem hideSeqs = new MenuItem();
137
138   MenuItem repGroup = new MenuItem();
139
140   MenuItem sequenceName = new MenuItem(
141           MessageManager.getString("label.edit_name_description"));
142
143   MenuItem sequenceFeature = new MenuItem(
144           MessageManager.getString("label.create_sequence_feature"));
145
146   MenuItem editSequence = new MenuItem(
147           MessageManager.getString("label.edit_sequence"));
148
149   MenuItem sequenceDetails = new MenuItem(
150           MessageManager.getString("label.sequence_details") + "...");
151
152   MenuItem selSeqDetails = new MenuItem(
153           MessageManager.getString("label.sequence_details") + "...");
154
155   MenuItem makeReferenceSeq = new MenuItem();
156   
157   Sequence seq;
158
159   MenuItem revealAll = new MenuItem();
160
161   MenuItem revealSeq = new MenuItem();
162
163   /**
164    * index of sequence to be revealed
165    */
166   int revealSeq_index = -1;
167
168   Menu menu1 = new Menu();
169
170   public APopupMenu(AlignmentPanel apanel, final Sequence seq, Vector links)
171   {
172     // /////////////////////////////////////////////////////////
173     // If this is activated from the sequence panel, the user may want to
174     // edit or annotate a particular residue. Therefore display the residue menu
175     //
176     // If from the IDPanel, we must display the sequence menu
177     // ////////////////////////////////////////////////////////
178
179     this.ap = apanel;
180     this.seq = seq;
181
182     try
183     {
184       jbInit();
185     } catch (Exception e)
186     {
187       e.printStackTrace();
188     }
189
190     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)
191     {
192       MenuItem item = new MenuItem(
193               jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);
194
195       item.addActionListener(this);
196       outputmenu.add(item);
197     }
198
199     SequenceGroup sg = ap.av.getSelectionGroup();
200
201     if (sg != null && sg.getSize() > 0)
202     {
203       editGroupName.setLabel(MessageManager.formatMessage(
204               "label.name_param", new String[]
205               { sg.getName() }));
206       showText.setState(sg.getDisplayText());
207       showColourText.setState(sg.getColourText());
208       showBoxes.setState(sg.getDisplayBoxes());
209       displayNonconserved.setState(sg.getShowNonconserved());
210       if (!ap.av.getAlignment().getGroups().contains(sg))
211       {
212         menu1.setLabel(MessageManager.getString("action.edit_new_group"));
213         groupMenu.remove(unGroupMenuItem);
214       }
215       else
216       {
217         menu1.setLabel(MessageManager.getString("action.edit_group"));
218         groupMenu.remove(createGroupMenuItem);
219       }
220
221     }
222     else
223     {
224       remove(hideSeqs);
225       remove(groupMenu);
226     }
227
228     if (links != null && links.size() > 0)
229     {
230       Menu linkMenu = new Menu(MessageManager.getString("action.link"));
231       String link;
232       for (int i = 0; i < links.size(); i++)
233       {
234         link = links.elementAt(i).toString();
235         UrlLink urlLink = new UrlLink(link);
236         if (!urlLink.isValid())
237         {
238           System.err.println(urlLink.getInvalidMessage());
239           continue;
240         }
241         final String target = urlLink.getTarget(); // link.substring(0,
242         // link.indexOf("|"));
243         final String label = urlLink.getLabel();
244         if (seq != null && urlLink.isDynamic())
245         {
246
247           // collect matching db-refs
248           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
249                   seq.getDBRef(), new String[]
250                   { target });
251           // collect id string too
252           String id = seq.getName();
253           String descr = seq.getDescription();
254           if (descr != null && descr.length() < 1)
255           {
256             descr = null;
257           }
258           if (dbr != null)
259           {
260             for (int r = 0; r < dbr.length; r++)
261             {
262               if (id != null && dbr[r].getAccessionId().equals(id))
263               {
264                 // suppress duplicate link creation for the bare sequence ID
265                 // string with this link
266                 id = null;
267               }
268               // create Bare ID link for this RUL
269               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
270                       true);
271               if (urls != null)
272               {
273                 for (int u = 0; u < urls.length; u += 2)
274                 {
275                   addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
276                 }
277               }
278             }
279           }
280           if (id != null)
281           {
282             // create Bare ID link for this RUL
283             String[] urls = urlLink.makeUrls(id, true);
284             if (urls != null)
285             {
286               for (int u = 0; u < urls.length; u += 2)
287               {
288                 addshowLink(linkMenu, label, urls[u + 1]);
289               }
290             }
291             // addshowLink(linkMenu, target, url_pref + id + url_suff);
292           }
293           // Now construct URLs from description but only try to do it for regex
294           // URL links
295           if (descr != null && urlLink.getRegexReplace() != null)
296           {
297             // create link for this URL from description only if regex matches
298             String[] urls = urlLink.makeUrls(descr, true);
299             if (urls != null)
300             {
301               for (int u = 0; u < urls.length; u += 2)
302               {
303                 addshowLink(linkMenu, label, urls[u + 1]);
304               }
305             }
306           }
307         }
308         else
309         {
310           addshowLink(linkMenu, target, urlLink.getUrl_prefix()); // link.substring(link.lastIndexOf("|")+1));
311         }
312         /*
313          * final String url;
314          * 
315          * if (link.indexOf("$SEQUENCE_ID$") > -1) { // Substitute SEQUENCE_ID
316          * string and any matching database reference accessions String url_pref
317          * = link.substring(link.indexOf("|") + 1,
318          * link.indexOf("$SEQUENCE_ID$"));
319          * 
320          * String url_suff = link.substring(link.indexOf("$SEQUENCE_ID$") + 13);
321          * // collect matching db-refs DBRefEntry[] dbr =
322          * jalview.util.DBRefUtils.selectRefs(seq.getDBRef(), new
323          * String[]{target}); // collect id string too String id =
324          * seq.getName(); if (id.indexOf("|") > -1) { id =
325          * id.substring(id.lastIndexOf("|") + 1); } if (dbr!=null) { for (int
326          * r=0;r<dbr.length; r++) { if (dbr[r].getAccessionId().equals(id)) { //
327          * suppress duplicate link creation for the bare sequence ID string with
328          * this link id = null; } addshowLink(linkMenu,
329          * dbr[r].getSource()+"|"+dbr[r].getAccessionId(), target,
330          * url_pref+dbr[r].getAccessionId()+url_suff); } } if (id!=null) { //
331          * create Bare ID link for this RUL addshowLink(linkMenu, target,
332          * url_pref + id + url_suff); } } else { addshowLink(linkMenu, target,
333          * link.substring(link.lastIndexOf("|")+1)); }
334          */
335       }
336       if (linkMenu.getItemCount() > 0)
337       {
338         if (seq != null)
339         {
340           seqMenu.add(linkMenu);
341         }
342         else
343         {
344           add(linkMenu);
345         }
346       }
347     }
348     // TODO: add group link menu entry here
349     if (seq != null)
350     {
351       seqMenu.setLabel(seq.getName());
352       if (seq == ap.av.getAlignment().getSeqrep())
353       {
354         makeReferenceSeq.setLabel(MessageManager
355                 .getString("action.unmark_as_reference"));// Unmark
356                                                           // representative");
357       }
358       else
359       {
360         makeReferenceSeq.setLabel(MessageManager
361                 .getString("action.set_as_reference")); // );
362       }
363       repGroup.setLabel(MessageManager.formatMessage(
364               "label.represent_group_with", new String[]
365               { seq.getName() }));
366     }
367     else
368     {
369       remove(seqMenu);
370     }
371
372     if (!ap.av.hasHiddenRows())
373     {
374       remove(revealAll);
375       remove(revealSeq);
376     }
377     else
378     {
379       final int index = ap.av.getAlignment().findIndex(seq);
380
381       if (ap.av.adjustForHiddenSeqs(index)
382               - ap.av.adjustForHiddenSeqs(index - 1) > 1)
383       {
384         revealSeq_index = index;
385       }
386       else
387       {
388         remove(revealSeq);
389       }
390     }
391   }
392
393   /**
394    * add a show URL menu item to the given linkMenu
395    * 
396    * @param linkMenu
397    * @param target
398    *          - menu label string
399    * @param url
400    *          - url to open
401    */
402   private void addshowLink(Menu linkMenu, final String target,
403           final String url)
404   {
405     addshowLink(linkMenu, target, target, url);
406   }
407
408   /**
409    * add a show URL menu item to the given linkMenu
410    * 
411    * @param linkMenu
412    * @param target
413    *          - URL target window
414    * @param label
415    *          - menu label string
416    * @param url
417    *          - url to open
418    */
419   private void addshowLink(Menu linkMenu, final String target,
420           final String label, final String url)
421   {
422     MenuItem item = new MenuItem(label);
423     item.addActionListener(new java.awt.event.ActionListener()
424     {
425       public void actionPerformed(ActionEvent e)
426       {
427         ap.alignFrame.showURL(url, target);
428       }
429     });
430     linkMenu.add(item);
431   }
432
433   public void itemStateChanged(ItemEvent evt)
434   {
435     if (evt.getSource() == abovePIDColour)
436     {
437       abovePIDColour_itemStateChanged();
438     }
439     else if (evt.getSource() == showColourText)
440     {
441       showColourText_itemStateChanged();
442     }
443     else if (evt.getSource() == showText)
444     {
445       showText_itemStateChanged();
446     }
447     else if (evt.getSource() == showBoxes)
448     {
449       showBoxes_itemStateChanged();
450     }
451     else if (evt.getSource() == displayNonconserved)
452     {
453       this.showNonconserved_itemStateChanged();
454     }
455   }
456
457   public void actionPerformed(ActionEvent evt)
458   {
459     Object source = evt.getSource();
460     if (source == clustalColour)
461     {
462       clustalColour_actionPerformed();
463     }
464     else if (source == zappoColour)
465     {
466       zappoColour_actionPerformed();
467     }
468     else if (source == taylorColour)
469     {
470       taylorColour_actionPerformed();
471     }
472     else if (source == hydrophobicityColour)
473     {
474       hydrophobicityColour_actionPerformed();
475     }
476     else if (source == helixColour)
477     {
478       helixColour_actionPerformed();
479     }
480     else if (source == strandColour)
481     {
482       strandColour_actionPerformed();
483     }
484     else if (source == turnColour)
485     {
486       turnColour_actionPerformed();
487     }
488     else if (source == buriedColour)
489     {
490       buriedColour_actionPerformed();
491     }
492     else if (source == nucleotideMenuItem)
493     {
494       nucleotideMenuItem_actionPerformed();
495     }
496
497     else if (source == userDefinedColour)
498     {
499       userDefinedColour_actionPerformed();
500     }
501     else if (source == PIDColour)
502     {
503       PIDColour_actionPerformed();
504     }
505     else if (source == BLOSUM62Colour)
506     {
507       BLOSUM62Colour_actionPerformed();
508     }
509     else if (source == noColourmenuItem)
510     {
511       noColourmenuItem_actionPerformed();
512     }
513     else if (source == conservationMenuItem)
514     {
515       conservationMenuItem_itemStateChanged();
516     }
517     else if (source == unGroupMenuItem)
518     {
519       unGroupMenuItem_actionPerformed();
520     }
521
522     else if (source == createGroupMenuItem)
523     {
524       createGroupMenuItem_actionPerformed();
525     }
526
527     else if (source == sequenceName)
528     {
529       editName();
530     }
531     else if (source == makeReferenceSeq)
532     {
533       makeReferenceSeq_actionPerformed();
534     }
535     else if (source == sequenceDetails)
536     {
537       showSequenceDetails();
538     }
539     else if (source == selSeqDetails)
540     {
541       showSequenceSelectionDetails();
542     }
543     else if (source == pdb)
544     {
545       addPDB();
546     }
547     else if (source == hideSeqs)
548     {
549       hideSequences(false);
550     }
551     else if (source == repGroup)
552     {
553       hideSequences(true);
554     }
555     else if (source == revealSeq)
556     {
557       ap.av.showSequence(revealSeq_index);
558     }
559     else if (source == revealAll)
560     {
561       ap.av.showAllHiddenSeqs();
562     }
563
564     else if (source == editGroupName)
565     {
566       EditNameDialog dialog = new EditNameDialog(getGroup().getName(),
567               getGroup().getDescription(), "       Group Name",
568               "Group Description", ap.alignFrame,
569               "Edit Group Name / Description", 500, 100, true);
570
571       if (dialog.accept)
572       {
573         getGroup().setName(dialog.getName().replace(' ', '_'));
574         getGroup().setDescription(dialog.getDescription());
575       }
576
577     }
578     else if (source == copy)
579     {
580       ap.alignFrame.copy_actionPerformed();
581     }
582     else if (source == cut)
583     {
584       ap.alignFrame.cut_actionPerformed();
585     }
586     else if (source == editSequence)
587     {
588       SequenceGroup sg = ap.av.getSelectionGroup();
589
590       if (sg != null)
591       {
592         if (seq == null)
593         {
594           seq = (Sequence) sg.getSequenceAt(0);
595         }
596
597         EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString(
598                 sg.getStartRes(), sg.getEndRes() + 1), null,
599                 "Edit Sequence ", null,
600
601                 ap.alignFrame, "Edit Sequence", 500, 100, true);
602
603         if (dialog.accept)
604         {
605           EditCommand editCommand = new EditCommand(MessageManager.getString("label.edit_sequences"),
606                   Action.REPLACE, dialog.getName().replace(' ',
607                           ap.av.getGapCharacter()),
608                   sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
609                   sg.getStartRes(), sg.getEndRes() + 1,
610                   ap.av.getAlignment());
611
612           ap.alignFrame.addHistoryItem(editCommand);
613
614           ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
615                   .getSequences());
616         }
617       }
618     }
619     else if (source == toUpper || source == toLower || source == toggleCase)
620     {
621       SequenceGroup sg = ap.av.getSelectionGroup();
622       Vector regions = new Vector();
623       if (sg != null)
624       {
625         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.getIgnoreGapsConsensus());
1027
1028       SliderPanel.showPIDSlider();
1029
1030     }
1031     else
1032     // remove PIDColouring
1033     {
1034       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
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 }