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