regular expression based URL link generation
[jalview.git] / src / jalview / gui / PopupMenu.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 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.gui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import javax.swing.*;
26
27 import MCview.*;
28 import jalview.analysis.*;
29 import jalview.commands.*;
30 import jalview.datamodel.*;
31 import jalview.io.*;
32 import jalview.schemes.*;
33 import jalview.util.UrlLink;
34
35 /**
36  * DOCUMENT ME!
37  *
38  * @author $author$
39  * @version $Revision$
40  */
41 public class PopupMenu
42     extends JPopupMenu
43 {
44   JMenu groupMenu = new JMenu();
45   JMenuItem groupName = new JMenuItem();
46   protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
47   protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
48   protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
49   protected JRadioButtonMenuItem hydrophobicityColour = new
50       JRadioButtonMenuItem();
51   protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
52   protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
53   protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
54   protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
55   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
56   protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
57   protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
58   protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
59   JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
60   protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
61   AlignmentPanel ap;
62   JMenu sequenceMenu = new JMenu();
63   JMenuItem sequenceName = new JMenuItem();
64   Sequence sequence;
65   JMenuItem unGroupMenuItem = new JMenuItem();
66   JMenuItem outline = new JMenuItem();
67   JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
68   JMenu colourMenu = new JMenu();
69   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
70   JCheckBoxMenuItem showText = new JCheckBoxMenuItem();
71   JCheckBoxMenuItem showColourText = new JCheckBoxMenuItem();
72   JMenu editMenu = new JMenu();
73   JMenuItem cut = new JMenuItem();
74   JMenuItem copy = new JMenuItem();
75   JMenuItem upperCase = new JMenuItem();
76   JMenuItem lowerCase = new JMenuItem();
77   JMenuItem toggle = new JMenuItem();
78   JMenu pdbMenu = new JMenu();
79   JMenuItem pdbFromFile = new JMenuItem();
80   JMenuItem enterPDB = new JMenuItem();
81   JMenuItem discoverPDB = new JMenuItem();
82   JMenu outputMenu = new JMenu();
83   JMenuItem sequenceFeature = new JMenuItem();
84   JMenuItem textColour = new JMenuItem();
85   JMenu jMenu1 = new JMenu();
86   JMenu structureMenu = new JMenu();
87   JMenu viewStructureMenu = new JMenu();
88  // JMenu colStructureMenu = new JMenu();
89   JMenuItem editSequence = new JMenuItem();
90  // JMenuItem annotationMenuItem = new JMenuItem();
91
92   /**
93    * Creates a new PopupMenu object.
94    *
95    * @param ap DOCUMENT ME!
96    * @param seq DOCUMENT ME!
97    */
98   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
99   {
100     ///////////////////////////////////////////////////////////
101     // If this is activated from the sequence panel, the user may want to
102     // edit or annotate a particular residue. Therefore display the residue menu
103     //
104     // If from the IDPanel, we must display the sequence menu
105     //////////////////////////////////////////////////////////
106     this.ap = ap;
107     sequence = seq;
108
109     ButtonGroup colours = new ButtonGroup();
110     colours.add(noColourmenuItem);
111     colours.add(clustalColour);
112     colours.add(zappoColour);
113     colours.add(taylorColour);
114     colours.add(hydrophobicityColour);
115     colours.add(helixColour);
116     colours.add(strandColour);
117     colours.add(turnColour);
118     colours.add(buriedColour);
119     colours.add(abovePIDColour);
120     colours.add(userDefinedColour);
121     colours.add(PIDColour);
122     colours.add(BLOSUM62Colour);
123
124     for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
125     {
126       JMenuItem item = new JMenuItem(jalview.io.FormatAdapter.WRITEABLE_FORMATS[
127                                      i]);
128
129       item.addActionListener(new java.awt.event.ActionListener()
130       {
131         public void actionPerformed(ActionEvent e)
132         {
133           outputText_actionPerformed(e);
134         }
135       });
136
137       outputMenu.add(item);
138     }
139
140     try
141     {
142       jbInit();
143     }
144     catch (Exception e)
145     {
146       e.printStackTrace();
147     }
148
149     if (seq != null)
150     {
151       sequenceMenu.setText(sequence.getName());
152
153       JMenuItem menuItem;
154       if (seq.getDatasetSequence().getPDBId() != null
155           && seq.getDatasetSequence().getPDBId().size()>0)
156       {
157         java.util.Enumeration e = seq.getDatasetSequence().getPDBId().
158             elements();
159
160         while (e.hasMoreElements())
161         {
162           final PDBEntry pdb = (PDBEntry) e.nextElement();
163
164           menuItem = new JMenuItem();
165           menuItem.setText(pdb.getId());
166           menuItem.addActionListener(new java.awt.event.ActionListener()
167           {
168             public void actionPerformed(ActionEvent e)
169             {
170               Vector seqs = new Vector();
171               for (int i = 0; i < ap.av.alignment.getHeight(); i++)
172               {
173                 Vector pdbs = ap.av.alignment.getSequenceAt(i).getDatasetSequence().getPDBId();
174                 if(pdbs==null)
175                   continue;
176
177                 for(int p=0; p<pdbs.size(); p++)
178                 {
179                   PDBEntry p1 = (PDBEntry)pdbs.elementAt(p);
180                   if(p1.getId().equals(pdb.getId()))
181                   {
182                     if (!seqs.contains(ap.av.alignment.getSequenceAt(i)))
183                         seqs.addElement(ap.av.alignment.getSequenceAt(i));
184
185                       continue;
186                   }
187                 }
188               }
189
190               SequenceI [] seqs2 = new SequenceI[seqs.size()];
191               seqs.toArray(seqs2);
192
193               new AppJmol(pdb, seqs2, null, ap);
194               //  new PDBViewer(pdb, seqs2, null, ap, AppletFormatAdapter.FILE);
195             }
196           });
197           viewStructureMenu.add(menuItem);
198
199        /*   menuItem = new JMenuItem();
200           menuItem.setText(pdb.getId());
201           menuItem.addActionListener(new java.awt.event.ActionListener()
202           {
203             public void actionPerformed(ActionEvent e)
204             {
205               colourByStructure(pdb.getId());
206             }
207           });
208           colStructureMenu.add(menuItem);*/
209         }
210       }
211       else
212       {
213         structureMenu.remove(viewStructureMenu);
214        // structureMenu.remove(colStructureMenu);
215       }
216
217       menuItem = new JMenuItem("Hide Sequences");
218       menuItem.addActionListener(new java.awt.event.ActionListener()
219       {
220         public void actionPerformed(ActionEvent e)
221         {
222           hideSequences(false);
223         }
224       });
225       add(menuItem);
226
227       if (ap.av.getSelectionGroup() != null
228           && ap.av.getSelectionGroup().getSize() > 1)
229       {
230         menuItem = new JMenuItem("Represent Group with " + seq.getName());
231         menuItem.addActionListener(new java.awt.event.ActionListener()
232         {
233           public void actionPerformed(ActionEvent e)
234           {
235             hideSequences(true);
236           }
237         });
238         sequenceMenu.add(menuItem);
239       }
240
241       if (ap.av.hasHiddenRows)
242       {
243         final int index = ap.av.alignment.findIndex(seq);
244
245         if (ap.av.adjustForHiddenSeqs(index) -
246             ap.av.adjustForHiddenSeqs(index - 1) > 1)
247         {
248           menuItem = new JMenuItem("Reveal Sequences");
249           menuItem.addActionListener(new ActionListener()
250           {
251             public void actionPerformed(ActionEvent e)
252             {
253               ap.av.showSequence(index);
254               if (ap.overviewPanel != null)
255               {
256                 ap.overviewPanel.updateOverviewImage();
257               }
258             }
259           });
260           add(menuItem);
261         }
262
263         menuItem = new JMenuItem("Reveal All");
264         menuItem.addActionListener(new ActionListener()
265         {
266           public void actionPerformed(ActionEvent e)
267           {
268             ap.av.showAllHiddenSeqs();
269             if (ap.overviewPanel != null)
270             {
271               ap.overviewPanel.updateOverviewImage();
272             }
273           }
274         });
275
276         add(menuItem);
277       }
278
279     }
280
281     SequenceGroup sg = ap.av.getSelectionGroup();
282
283     if (sg != null)
284     {
285       groupName.setText(sg.getName());
286
287       if (sg.cs instanceof ZappoColourScheme)
288       {
289         zappoColour.setSelected(true);
290       }
291       else if (sg.cs instanceof TaylorColourScheme)
292       {
293         taylorColour.setSelected(true);
294       }
295       else if (sg.cs instanceof PIDColourScheme)
296       {
297         PIDColour.setSelected(true);
298       }
299       else if (sg.cs instanceof Blosum62ColourScheme)
300       {
301         BLOSUM62Colour.setSelected(true);
302       }
303       else if (sg.cs instanceof UserColourScheme)
304       {
305         userDefinedColour.setSelected(true);
306       }
307       else if (sg.cs instanceof HydrophobicColourScheme)
308       {
309         hydrophobicityColour.setSelected(true);
310       }
311       else if (sg.cs instanceof HelixColourScheme)
312       {
313         helixColour.setSelected(true);
314       }
315       else if (sg.cs instanceof StrandColourScheme)
316       {
317         strandColour.setSelected(true);
318       }
319       else if (sg.cs instanceof TurnColourScheme)
320       {
321         turnColour.setSelected(true);
322       }
323       else if (sg.cs instanceof BuriedColourScheme)
324       {
325         buriedColour.setSelected(true);
326       }
327       else if (sg.cs instanceof ClustalxColourScheme)
328       {
329         clustalColour.setSelected(true);
330       }
331       else
332       {
333         noColourmenuItem.setSelected(true);
334       }
335
336       if (sg.cs != null && sg.cs.conservationApplied())
337       {
338         conservationMenuItem.setSelected(true);
339       }
340
341       showText.setSelected(sg.getDisplayText());
342       showColourText.setSelected(sg.getColourText());
343       showBoxes.setSelected(sg.getDisplayBoxes());
344     }
345     else
346     {
347       groupMenu.setVisible(false);
348       editMenu.setVisible(false);
349     }
350
351     if (!ap.av.alignment.getGroups().contains(sg))
352     {
353       unGroupMenuItem.setVisible(false);
354     }
355
356     if (seq == null)
357     {
358       sequenceMenu.setVisible(false);
359       structureMenu.setVisible(false);
360     }
361
362     if (links != null && links.size() > 0)
363     {
364       JMenu linkMenu = new JMenu("Link");
365
366       for (int i = 0; i < links.size(); i++)
367       {
368         String link = links.elementAt(i).toString();
369         UrlLink urlLink = new UrlLink(link);
370         if (!urlLink.isValid())
371         {
372           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
373           continue;
374         }
375         final String label = urlLink.getLabel();
376         if (urlLink.isDynamic())
377         {
378
379           // collect matching db-refs
380           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq.getDBRef(), new String[]{urlLink.getTarget()});
381           // collect id string too
382           String id = seq.getName();
383           if (dbr!=null)
384           {
385             for (int r=0;r<dbr.length; r++)
386             {
387               if (id!=null && dbr[r].getAccessionId().equals(id))
388               {
389                 // suppress duplicate link creation for the bare sequence ID string with this link
390                 id = null;
391               }
392               // create Bare ID link for this RUL
393               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
394               if (urls!=null)
395               {
396                 for (int u=0; u<urls.length; u+=2)
397                 {
398                   addshowLink(linkMenu, label+"|"+urls[u],urls[u+1]); 
399                 }
400               }
401             }
402           }
403           if (id!=null)
404           {
405             // create Bare ID link for this RUL
406             String[] urls = urlLink.makeUrls(id, true);
407             if (urls!=null)
408             {
409               for (int u=0; u<urls.length; u+=2)
410               {
411                 addshowLink(linkMenu, label,  urls[u+1]);
412               }
413             }
414           }
415         } else
416         {
417           // Add a non-dynamic link
418           addshowLink(linkMenu, label, urlLink.getUrl_prefix());
419         }
420       }
421       if (sequence != null)
422       {
423         sequenceMenu.add(linkMenu);
424       }
425       else
426       {
427         add(linkMenu);
428       }
429     }
430   }
431
432   /**
433    * add a show URL menu item to the given linkMenu
434    * @param linkMenu
435    * @param label - menu label string
436    * @param url - url to open
437    */
438   private void addshowLink(JMenu linkMenu, String label, final String url)
439   {
440     JMenuItem item = new JMenuItem(label);
441     item.setToolTipText("open URL: "+url);
442     item.addActionListener(new java.awt.event.ActionListener()
443     {
444       public void actionPerformed(ActionEvent e)
445       {
446         new Thread(new Runnable() {
447
448           public void run()
449           {
450             showLink(url);
451           }
452           
453         }).start();
454       }
455     });
456
457     linkMenu.add(item);    
458   }
459
460   /**
461    * DOCUMENT ME!
462    *
463    * @throws Exception DOCUMENT ME!
464    */
465   private void jbInit()
466       throws Exception
467   {
468     groupMenu.setText("Group");
469     groupMenu.setText("Selection");
470     groupName.setText("Name");
471     groupName.addActionListener(new java.awt.event.ActionListener()
472     {
473       public void actionPerformed(ActionEvent e)
474       {
475         groupName_actionPerformed();
476       }
477     });
478     sequenceMenu.setText("Sequence");
479     sequenceName.setText("Edit Name/Description");
480     sequenceName.addActionListener(new java.awt.event.ActionListener()
481     {
482       public void actionPerformed(ActionEvent e)
483       {
484         sequenceName_actionPerformed();
485       }
486     });
487     PIDColour.setFocusPainted(false);
488     unGroupMenuItem.setText("Remove Group");
489     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
490     {
491       public void actionPerformed(ActionEvent e)
492       {
493         unGroupMenuItem_actionPerformed();
494       }
495     });
496
497     outline.setText("Border colour");
498     outline.addActionListener(new java.awt.event.ActionListener()
499     {
500       public void actionPerformed(ActionEvent e)
501       {
502         outline_actionPerformed();
503       }
504     });
505     nucleotideMenuItem.setText("Nucleotide");
506     nucleotideMenuItem.addActionListener(new ActionListener()
507     {
508       public void actionPerformed(ActionEvent e)
509       {
510         nucleotideMenuItem_actionPerformed();
511       }
512     });
513     colourMenu.setText("Group Colour");
514     showBoxes.setText("Boxes");
515     showBoxes.setState(true);
516     showBoxes.addActionListener(new ActionListener()
517     {
518       public void actionPerformed(ActionEvent e)
519       {
520         showBoxes_actionPerformed();
521       }
522     });
523     showText.setText("Text");
524     showText.setState(true);
525     showText.addActionListener(new ActionListener()
526     {
527       public void actionPerformed(ActionEvent e)
528       {
529         showText_actionPerformed();
530       }
531     });
532     showColourText.setText("Colour Text");
533     showColourText.addActionListener(new ActionListener()
534     {
535       public void actionPerformed(ActionEvent e)
536       {
537         showColourText_actionPerformed();
538       }
539     });
540     editMenu.setText("Edit");
541     cut.setText("Cut");
542     cut.addActionListener(new ActionListener()
543     {
544       public void actionPerformed(ActionEvent e)
545       {
546         cut_actionPerformed();
547       }
548     });
549     upperCase.setText("To Upper Case");
550     upperCase.addActionListener(new ActionListener()
551     {
552       public void actionPerformed(ActionEvent e)
553       {
554         changeCase(e);
555       }
556     });
557     copy.setText("Copy");
558     copy.addActionListener(new ActionListener()
559     {
560       public void actionPerformed(ActionEvent e)
561       {
562         copy_actionPerformed();
563       }
564     });
565     lowerCase.setText("To Lower Case");
566     lowerCase.addActionListener(new ActionListener()
567     {
568       public void actionPerformed(ActionEvent e)
569       {
570         changeCase(e);
571       }
572     });
573     toggle.setText("Toggle Case");
574     toggle.addActionListener(new ActionListener()
575     {
576       public void actionPerformed(ActionEvent e)
577       {
578         changeCase(e);
579       }
580     });
581     pdbMenu.setText("Associate Structure with Sequence");
582     pdbFromFile.setText("From File");
583     pdbFromFile.addActionListener(new ActionListener()
584     {
585       public void actionPerformed(ActionEvent e)
586       {
587         pdbFromFile_actionPerformed();
588       }
589     });
590     enterPDB.setText("Enter PDB Id");
591     enterPDB.addActionListener(new ActionListener()
592     {
593       public void actionPerformed(ActionEvent e)
594       {
595         enterPDB_actionPerformed();
596       }
597     });
598     discoverPDB.setText("Discover PDB ids");
599     discoverPDB.addActionListener(new ActionListener()
600     {
601       public void actionPerformed(ActionEvent e)
602       {
603         discoverPDB_actionPerformed();
604       }
605     });
606     outputMenu.setText("Output to Textbox...");
607     sequenceFeature.setText("Create Sequence Feature");
608     sequenceFeature.addActionListener(new ActionListener()
609     {
610       public void actionPerformed(ActionEvent e)
611       {
612         sequenceFeature_actionPerformed();
613       }
614     });
615     textColour.setText("Text Colour");
616     textColour.addActionListener(new ActionListener()
617     {
618       public void actionPerformed(ActionEvent e)
619       {
620         textColour_actionPerformed();
621       }
622     });
623     jMenu1.setText("Group");
624     structureMenu.setText("Structure");
625     viewStructureMenu.setText("View Structure");
626   //  colStructureMenu.setText("Colour By Structure");
627     editSequence.setText("Edit Sequence...");
628     editSequence.addActionListener(new ActionListener()
629     {
630       public void actionPerformed(ActionEvent actionEvent)
631       {
632         editSequence_actionPerformed(actionEvent);
633       }
634     });
635    /* annotationMenuItem.setText("By Annotation");
636     annotationMenuItem.addActionListener(new ActionListener()
637     {
638       public void actionPerformed(ActionEvent actionEvent)
639       {
640         annotationMenuItem_actionPerformed(actionEvent);
641       }
642     });*/
643
644     add(groupMenu);
645
646     add(sequenceMenu);
647     this.add(structureMenu);
648     groupMenu.add(editMenu);
649     groupMenu.add(outputMenu);
650     groupMenu.add(sequenceFeature);
651     groupMenu.add(jMenu1);
652     sequenceMenu.add(sequenceName);
653     colourMenu.add(textColour);
654     colourMenu.add(noColourmenuItem);
655     colourMenu.add(clustalColour);
656     colourMenu.add(BLOSUM62Colour);
657     colourMenu.add(PIDColour);
658     colourMenu.add(zappoColour);
659     colourMenu.add(taylorColour);
660     colourMenu.add(hydrophobicityColour);
661     colourMenu.add(helixColour);
662     colourMenu.add(strandColour);
663     colourMenu.add(turnColour);
664     colourMenu.add(buriedColour);
665     colourMenu.add(nucleotideMenuItem);
666     colourMenu.add(userDefinedColour);
667
668     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
669     {
670       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.
671           getUserColourSchemes().keys();
672
673       while (userColours.hasMoreElements())
674       {
675         JMenuItem item = new JMenuItem(userColours.
676                                        nextElement().toString());
677         item.addActionListener(new ActionListener()
678         {
679           public void actionPerformed(ActionEvent evt)
680           {
681             userDefinedColour_actionPerformed(evt);
682           }
683         });
684         colourMenu.add(item);
685       }
686     }
687
688     colourMenu.addSeparator();
689     colourMenu.add(abovePIDColour);
690     colourMenu.add(conservationMenuItem);
691     //colourMenu.add(annotationMenuItem);
692     editMenu.add(copy);
693     editMenu.add(cut);
694     editMenu.add(editSequence);
695     editMenu.add(upperCase);
696     editMenu.add(lowerCase);
697     editMenu.add(toggle);
698     pdbMenu.add(pdbFromFile);
699     pdbMenu.add(enterPDB);
700     pdbMenu.add(discoverPDB);
701     jMenu1.add(groupName);
702     jMenu1.add(unGroupMenuItem);
703     jMenu1.add(colourMenu);
704     jMenu1.add(showBoxes);
705     jMenu1.add(showText);
706     jMenu1.add(showColourText);
707     jMenu1.add(outline);
708     structureMenu.add(pdbMenu);
709     structureMenu.add(viewStructureMenu);
710    // structureMenu.add(colStructureMenu);
711     noColourmenuItem.setText("None");
712     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
713     {
714       public void actionPerformed(ActionEvent e)
715       {
716         noColourmenuItem_actionPerformed();
717       }
718     });
719
720     clustalColour.setText("Clustalx colours");
721     clustalColour.addActionListener(new java.awt.event.ActionListener()
722     {
723       public void actionPerformed(ActionEvent e)
724       {
725         clustalColour_actionPerformed();
726       }
727     });
728     zappoColour.setText("Zappo");
729     zappoColour.addActionListener(new java.awt.event.ActionListener()
730     {
731       public void actionPerformed(ActionEvent e)
732       {
733         zappoColour_actionPerformed();
734       }
735     });
736     taylorColour.setText("Taylor");
737     taylorColour.addActionListener(new java.awt.event.ActionListener()
738     {
739       public void actionPerformed(ActionEvent e)
740       {
741         taylorColour_actionPerformed();
742       }
743     });
744     hydrophobicityColour.setText("Hydrophobicity");
745     hydrophobicityColour.addActionListener(new java.awt.event.ActionListener()
746     {
747       public void actionPerformed(ActionEvent e)
748       {
749         hydrophobicityColour_actionPerformed();
750       }
751     });
752     helixColour.setText("Helix propensity");
753     helixColour.addActionListener(new java.awt.event.ActionListener()
754     {
755       public void actionPerformed(ActionEvent e)
756       {
757         helixColour_actionPerformed();
758       }
759     });
760     strandColour.setText("Strand propensity");
761     strandColour.addActionListener(new java.awt.event.ActionListener()
762     {
763       public void actionPerformed(ActionEvent e)
764       {
765         strandColour_actionPerformed();
766       }
767     });
768     turnColour.setText("Turn propensity");
769     turnColour.addActionListener(new java.awt.event.ActionListener()
770     {
771       public void actionPerformed(ActionEvent e)
772       {
773         turnColour_actionPerformed();
774       }
775     });
776     buriedColour.setText("Buried Index");
777     buriedColour.addActionListener(new java.awt.event.ActionListener()
778     {
779       public void actionPerformed(ActionEvent e)
780       {
781         buriedColour_actionPerformed();
782       }
783     });
784     abovePIDColour.setText("Above % Identity");
785     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
786     {
787       public void actionPerformed(ActionEvent e)
788       {
789         abovePIDColour_actionPerformed();
790       }
791     });
792     userDefinedColour.setText("User Defined...");
793     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
794     {
795       public void actionPerformed(ActionEvent e)
796       {
797         userDefinedColour_actionPerformed(e);
798       }
799     });
800     PIDColour.setText("Percentage Identity");
801     PIDColour.addActionListener(new java.awt.event.ActionListener()
802     {
803       public void actionPerformed(ActionEvent e)
804       {
805         PIDColour_actionPerformed();
806       }
807     });
808     BLOSUM62Colour.setText("BLOSUM62");
809     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
810     {
811       public void actionPerformed(ActionEvent e)
812       {
813         BLOSUM62Colour_actionPerformed();
814       }
815     });
816     conservationMenuItem.setText("Conservation");
817     conservationMenuItem.addActionListener(new java.awt.event.ActionListener()
818     {
819       public void actionPerformed(ActionEvent e)
820       {
821         conservationMenuItem_actionPerformed();
822       }
823     });
824   }
825
826   /**
827    * DOCUMENT ME!
828    */
829   void refresh()
830   {
831     ap.paintAlignment(true);
832
833     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
834   }
835
836   /**
837    * DOCUMENT ME!
838    *
839    * @param e DOCUMENT ME!
840    */
841   protected void clustalColour_actionPerformed()
842   {
843     SequenceGroup sg = getGroup();
844     sg.cs = new ClustalxColourScheme(sg.getSequences(ap.av.hiddenRepSequences),
845                                      ap.av.alignment.getWidth());
846     refresh();
847   }
848
849   /**
850    * DOCUMENT ME!
851    *
852    * @param e DOCUMENT ME!
853    */
854   protected void zappoColour_actionPerformed()
855   {
856     getGroup().cs = new ZappoColourScheme();
857     refresh();
858   }
859
860   /**
861    * DOCUMENT ME!
862    *
863    * @param e DOCUMENT ME!
864    */
865   protected void taylorColour_actionPerformed()
866   {
867     getGroup().cs = new TaylorColourScheme();
868     refresh();
869   }
870
871   /**
872    * DOCUMENT ME!
873    *
874    * @param e DOCUMENT ME!
875    */
876   protected void hydrophobicityColour_actionPerformed()
877   {
878     getGroup().cs = new HydrophobicColourScheme();
879     refresh();
880   }
881
882   /**
883    * DOCUMENT ME!
884    *
885    * @param e DOCUMENT ME!
886    */
887   protected void helixColour_actionPerformed()
888   {
889     getGroup().cs = new HelixColourScheme();
890     refresh();
891   }
892
893   /**
894    * DOCUMENT ME!
895    *
896    * @param e DOCUMENT ME!
897    */
898   protected void strandColour_actionPerformed()
899   {
900     getGroup().cs = new StrandColourScheme();
901     refresh();
902   }
903
904   /**
905    * DOCUMENT ME!
906    *
907    * @param e DOCUMENT ME!
908    */
909   protected void turnColour_actionPerformed()
910   {
911     getGroup().cs = new TurnColourScheme();
912     refresh();
913   }
914
915   /**
916    * DOCUMENT ME!
917    *
918    * @param e DOCUMENT ME!
919    */
920   protected void buriedColour_actionPerformed()
921   {
922     getGroup().cs = new BuriedColourScheme();
923     refresh();
924   }
925
926   /**
927    * DOCUMENT ME!
928    *
929    * @param e DOCUMENT ME!
930    */
931   public void nucleotideMenuItem_actionPerformed()
932   {
933     getGroup().cs = new NucleotideColourScheme();
934     refresh();
935   }
936
937   /**
938    * DOCUMENT ME!
939    *
940    * @param e DOCUMENT ME!
941    */
942   protected void abovePIDColour_actionPerformed()
943   {
944     SequenceGroup sg = getGroup();
945     if (sg.cs == null)
946     {
947       return;
948     }
949
950     if (abovePIDColour.isSelected())
951     {
952       sg.cs.setConsensus(AAFrequency.calculate(
953           sg.getSequences(ap.av.hiddenRepSequences), sg.getStartRes(),
954           sg.getEndRes() + 1));
955
956       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs,
957           getGroup().getName());
958
959       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
960
961       SliderPanel.showPIDSlider();
962     }
963     else // remove PIDColouring
964     {
965       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
966     }
967
968     refresh();
969   }
970
971   /**
972    * DOCUMENT ME!
973    *
974    * @param e DOCUMENT ME!
975    */
976   protected void userDefinedColour_actionPerformed(ActionEvent e)
977   {
978     SequenceGroup sg = getGroup();
979
980     if (e.getActionCommand().equals("User Defined..."))
981     {
982       new UserDefinedColours(ap, sg);
983     }
984     else
985     {
986       UserColourScheme udc = (UserColourScheme) UserDefinedColours.
987           getUserColourSchemes().get(e.getActionCommand());
988
989       sg.cs = udc;
990     }
991     refresh();
992   }
993
994   /**
995    * DOCUMENT ME!
996    *
997    * @param e DOCUMENT ME!
998    */
999   protected void PIDColour_actionPerformed()
1000   {
1001     SequenceGroup sg = getGroup();
1002     sg.cs = new PIDColourScheme();
1003     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av.
1004         hiddenRepSequences),
1005                                              sg.getStartRes(),
1006                                              sg.getEndRes() + 1));
1007     refresh();
1008   }
1009
1010   /**
1011    * DOCUMENT ME!
1012    *
1013    * @param e DOCUMENT ME!
1014    */
1015   protected void BLOSUM62Colour_actionPerformed()
1016   {
1017     SequenceGroup sg = getGroup();
1018
1019     sg.cs = new Blosum62ColourScheme();
1020
1021     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av.
1022         hiddenRepSequences),
1023                                              sg.getStartRes(),
1024                                              sg.getEndRes() + 1));
1025
1026     refresh();
1027   }
1028
1029   /**
1030    * DOCUMENT ME!
1031    *
1032    * @param e DOCUMENT ME!
1033    */
1034   protected void noColourmenuItem_actionPerformed()
1035   {
1036     getGroup().cs = null;
1037     refresh();
1038   }
1039
1040   /**
1041    * DOCUMENT ME!
1042    *
1043    * @param e DOCUMENT ME!
1044    */
1045   protected void conservationMenuItem_actionPerformed()
1046   {
1047     SequenceGroup sg = getGroup();
1048     if (sg.cs == null)
1049     {
1050       return;
1051     }
1052
1053     if (conservationMenuItem.isSelected())
1054     {
1055       Conservation c = new Conservation("Group",
1056                                         ResidueProperties.propHash, 3,
1057                                         sg.getSequences(ap.av.
1058           hiddenRepSequences),
1059                                         sg.getStartRes(),
1060                                         sg.getEndRes() + 1);
1061
1062       c.calculate();
1063       c.verdict(false, ap.av.ConsPercGaps);
1064
1065       sg.cs.setConservation(c);
1066
1067       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1068       SliderPanel.showConservationSlider();
1069     }
1070     else // remove ConservationColouring
1071     {
1072       sg.cs.setConservation(null);
1073     }
1074
1075     refresh();
1076   }
1077
1078   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1079   {
1080     SequenceGroup sg = getGroup();
1081     if (sg == null)
1082     {
1083       return;
1084     }
1085
1086     AnnotationColourGradient acg = new AnnotationColourGradient(
1087         sequence.getAnnotation()[0], null, AnnotationColourGradient.NO_THRESHOLD);
1088
1089     acg.predefinedColours = true;
1090     sg.cs = acg;
1091
1092     refresh();
1093   }
1094
1095   /**
1096    * DOCUMENT ME!
1097    *
1098    * @param e DOCUMENT ME!
1099    */
1100   protected void groupName_actionPerformed()
1101   {
1102
1103     SequenceGroup sg = getGroup();
1104     EditNameDialog dialog = new EditNameDialog(sg.getName(),
1105                                                sg.getDescription(),
1106                                                "       Group Name ",
1107                                                "Group Description ",
1108                                                "Edit Group Name/Description");
1109
1110     if (!dialog.accept)
1111     {
1112       return;
1113     }
1114
1115     sg.setName(dialog.getName());
1116     sg.setDescription(dialog.getDescription());
1117   }
1118
1119   /**
1120    * DOCUMENT ME!
1121    *
1122    * @return DOCUMENT ME!
1123    */
1124   SequenceGroup getGroup()
1125   {
1126     SequenceGroup sg = ap.av.getSelectionGroup();
1127     // this method won't add a new group if it already exists
1128     if (sg != null)
1129     {
1130       ap.av.alignment.addGroup(sg);
1131     }
1132
1133     return sg;
1134   }
1135
1136   /**
1137    * DOCUMENT ME!
1138    *
1139    * @param e DOCUMENT ME!
1140    */
1141   void sequenceName_actionPerformed()
1142   {
1143     EditNameDialog dialog = new EditNameDialog(sequence.getName(),
1144                                                sequence.getDescription(),
1145                                                "       Sequence Name ",
1146                                                "Sequence Description ",
1147                                                "Edit Sequence Name/Description");
1148
1149     if (!dialog.accept)
1150     {
1151       return;
1152     }
1153
1154     if (dialog.getName() != null)
1155     {
1156       if (dialog.getName().indexOf(" ") > -1)
1157       {
1158         JOptionPane.showMessageDialog(ap,
1159                                       "Spaces have been converted to \"_\"",
1160                                       "No spaces allowed in Sequence Name",
1161                                       JOptionPane.WARNING_MESSAGE);
1162       }
1163
1164       sequence.setName(dialog.getName().replace(' ', '_'));
1165       ap.paintAlignment(false);
1166     }
1167
1168     sequence.setDescription(dialog.getDescription());
1169
1170     ap.av.firePropertyChange("alignment", null,
1171                              ap.av.getAlignment().getSequences());
1172
1173   }
1174
1175   /**
1176    * DOCUMENT ME!
1177    *
1178    * @param e DOCUMENT ME!
1179    */
1180   void unGroupMenuItem_actionPerformed()
1181   {
1182     SequenceGroup sg = ap.av.getSelectionGroup();
1183     ap.av.alignment.deleteGroup(sg);
1184     ap.av.setSelectionGroup(null);
1185     refresh();
1186   }
1187
1188   /**
1189    * DOCUMENT ME!
1190    *
1191    * @param e DOCUMENT ME!
1192    */
1193   protected void outline_actionPerformed()
1194   {
1195     SequenceGroup sg = getGroup();
1196     Color col = JColorChooser.showDialog(this, "Select Outline Colour",
1197                                          Color.BLUE);
1198
1199     if (col != null)
1200     {
1201       sg.setOutlineColour(col);
1202     }
1203
1204     refresh();
1205   }
1206
1207   /**
1208    * DOCUMENT ME!
1209    *
1210    * @param e DOCUMENT ME!
1211    */
1212   public void showBoxes_actionPerformed()
1213   {
1214     getGroup().setDisplayBoxes(showBoxes.isSelected());
1215     refresh();
1216   }
1217
1218   /**
1219    * DOCUMENT ME!
1220    *
1221    * @param e DOCUMENT ME!
1222    */
1223   public void showText_actionPerformed()
1224   {
1225     getGroup().setDisplayText(showText.isSelected());
1226     refresh();
1227   }
1228
1229   /**
1230    * DOCUMENT ME!
1231    *
1232    * @param e DOCUMENT ME!
1233    */
1234   public void showColourText_actionPerformed()
1235   {
1236     getGroup().setColourText(showColourText.isSelected());
1237     refresh();
1238   }
1239
1240   public void showLink(String url)
1241   {
1242     try
1243     {
1244       jalview.util.BrowserLauncher.openURL(url);
1245     }
1246     catch (Exception ex)
1247     {
1248       JOptionPane.showInternalMessageDialog(Desktop.desktop,
1249                                             "Unixers: Couldn't find default web browser."
1250                                             +
1251           "\nAdd the full path to your browser in Preferences.",
1252                                             "Web browser not found",
1253                                             JOptionPane.WARNING_MESSAGE);
1254
1255       ex.printStackTrace();
1256     }
1257   }
1258
1259   void hideSequences(boolean representGroup)
1260   {
1261     SequenceGroup sg = ap.av.getSelectionGroup();
1262     if (sg == null || sg.getSize() < 1)
1263     {
1264       ap.av.hideSequence(new SequenceI[]
1265                          {sequence});
1266       return;
1267     }
1268
1269     ap.av.setSelectionGroup(null);
1270
1271     if (representGroup)
1272     {
1273       ap.av.hideRepSequences(sequence, sg);
1274
1275       return;
1276     }
1277
1278     int gsize = sg.getSize();
1279     SequenceI[] hseqs;
1280
1281     hseqs = new SequenceI[gsize];
1282
1283     int index = 0;
1284     for (int i = 0; i < gsize; i++)
1285     {
1286       hseqs[index++] = sg.getSequenceAt(i);
1287     }
1288
1289     ap.av.hideSequence(hseqs);
1290   }
1291
1292   public void copy_actionPerformed()
1293   {
1294     ap.alignFrame.copy_actionPerformed(null);
1295   }
1296
1297   public void cut_actionPerformed()
1298   {
1299     ap.alignFrame.cut_actionPerformed(null);
1300   }
1301
1302   void changeCase(ActionEvent e)
1303   {
1304     Object source = e.getSource();
1305     SequenceGroup sg = ap.av.getSelectionGroup();
1306
1307     if (sg != null)
1308     {
1309       int[][] startEnd = ap.av.getVisibleRegionBoundaries(
1310           sg.getStartRes(), sg.getEndRes() + 1);
1311
1312       String description;
1313       int caseChange;
1314
1315       if (source == toggle)
1316       {
1317         description = "Toggle Case";
1318         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1319       }
1320       else if (source == upperCase)
1321       {
1322         description = "To Upper Case";
1323         caseChange = ChangeCaseCommand.TO_UPPER;
1324       }
1325       else
1326       {
1327         description = "To Lower Case";
1328         caseChange = ChangeCaseCommand.TO_LOWER;
1329       }
1330
1331       ChangeCaseCommand caseCommand = new ChangeCaseCommand(
1332           description, sg.getSequencesAsArray(ap.av.hiddenRepSequences),
1333           startEnd, caseChange
1334           );
1335
1336       ap.alignFrame.addHistoryItem(caseCommand);
1337
1338       ap.av.firePropertyChange("alignment", null,
1339                                ap.av.getAlignment().getSequences());
1340
1341     }
1342   }
1343
1344   public void outputText_actionPerformed(ActionEvent e)
1345   {
1346     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1347     cap.setForInput(null);
1348     Desktop.addInternalFrame(cap,
1349                              "Alignment output - " + e.getActionCommand(), 600,
1350                              500);
1351
1352     String[] omitHidden = null;
1353
1354     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens or we simply trust the user wants wysiwig behaviour
1355     SequenceGroup sg = ap.av.getSelectionGroup();
1356     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1357     omitHidden = ap.av.getViewAsString(true);
1358     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1359     AlignmentAnnotation[] nala = ap.av.alignment.getAlignmentAnnotation();
1360     for (int i=0; i<nala.length; i++)
1361     {
1362       AlignmentAnnotation na =nala[i];
1363       oal.addAnnotation(na);
1364     }
1365     cap.setText(new FormatAdapter().formatSequences(
1366             e.getActionCommand(),
1367             oal,
1368             omitHidden, csel, sg));
1369     oal=null;
1370   }
1371
1372   public void pdbFromFile_actionPerformed()
1373   {
1374     jalview.io.JalviewFileChooser chooser
1375         = new jalview.io.JalviewFileChooser(jalview.bin.Cache.
1376                                             getProperty(
1377                                                 "LAST_DIRECTORY"));
1378     chooser.setFileView(new jalview.io.JalviewFileView());
1379     chooser.setDialogTitle("Select a PDB file");
1380     chooser.setToolTipText("Load a PDB file");
1381
1382     int value = chooser.showOpenDialog(null);
1383
1384     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
1385     {
1386       PDBEntry entry = new PDBEntry();
1387       String choice = chooser.getSelectedFile().getPath();
1388       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1389       try
1390       {
1391         MCview.PDBfile pdbfile = new MCview.PDBfile(choice,
1392             jalview.io.AppletFormatAdapter.FILE);
1393
1394         if (pdbfile.id == null)
1395         {
1396           String reply = JOptionPane.showInternalInputDialog(
1397               Desktop.desktop,
1398               "Couldn't find a PDB id in the file supplied."
1399               + "Please enter an Id to identify this structure.",
1400               "No PDB Id in File", JOptionPane.QUESTION_MESSAGE);
1401           if (reply == null)
1402           {
1403             return;
1404           }
1405
1406           entry.setId(reply);
1407         }
1408         else
1409         {
1410           entry.setId(pdbfile.id);
1411         }
1412       }
1413       catch (java.io.IOException ex)
1414       {
1415         ex.printStackTrace();
1416       }
1417
1418       entry.setFile(choice);
1419       sequence.getDatasetSequence().addPDBId(entry);
1420     }
1421
1422   }
1423
1424   public void enterPDB_actionPerformed()
1425   {
1426     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
1427         "Enter PDB Id", "Enter PDB Id", JOptionPane.QUESTION_MESSAGE);
1428
1429     if (id != null && id.length() > 0)
1430     {
1431       PDBEntry entry = new PDBEntry();
1432       entry.setId(id.toUpperCase());
1433       sequence.getDatasetSequence()
1434           .addPDBId(entry);
1435     }
1436   }
1437
1438   public void discoverPDB_actionPerformed()
1439   {
1440     SequenceI[] sequences =
1441          ap.av.selectionGroup == null ?
1442            new Sequence[]{sequence}
1443          : ap.av.selectionGroup.getSequencesInOrder(ap.av.alignment);
1444
1445     new jalview.ws.DBRefFetcher(sequences,
1446         ap.alignFrame).fetchDBRefs(false);
1447   }
1448
1449   public void sequenceFeature_actionPerformed()
1450   {
1451     SequenceGroup sg = ap.av.getSelectionGroup();
1452     if (sg == null)
1453     {
1454       return;
1455     }
1456
1457     int gSize = sg.getSize();
1458     SequenceI[] seqs = new SequenceI[gSize];
1459     SequenceFeature[] features = new SequenceFeature[gSize];
1460
1461     for (int i = 0; i < gSize; i++)
1462     {
1463       seqs[i] = sg.getSequenceAt(i).getDatasetSequence();
1464       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
1465       int end = sg.findEndRes(sg.getSequenceAt(i));
1466       features[i] = new SequenceFeature(null, null, null, start, end, "Jalview");
1467     }
1468
1469     if (ap.seqPanel.seqCanvas.getFeatureRenderer()
1470         .amendFeatures(seqs, features, true, ap))
1471     {
1472       ap.alignFrame.showSeqFeatures.setSelected(true);
1473       ap.av.setShowSequenceFeatures(true);
1474       ap.highlightSearchResults(null);
1475     }
1476   }
1477
1478   public void textColour_actionPerformed()
1479   {
1480     SequenceGroup sg = getGroup();
1481     if (sg != null)
1482     {
1483       new TextColourChooser().chooseColour(ap, sg);
1484     }
1485   }
1486
1487   public void colourByStructure(String pdbid)
1488   {
1489     Annotation [] anots = jalview.structure.StructureSelectionManager.getStructureSelectionManager()
1490         .colourSequenceFromStructure(sequence, pdbid);
1491
1492     AlignmentAnnotation an = new AlignmentAnnotation(
1493       "Structure", "Coloured by "+pdbid, anots);
1494
1495     ap.av.alignment.addAnnotation(an);
1496     an.createSequenceMapping(sequence, 0, true);
1497     //an.adjustForAlignment();
1498     ap.av.alignment.setAnnotationIndex(an,0);
1499
1500     ap.adjustAnnotationHeight();
1501
1502     sequence.addAlignmentAnnotation(an);
1503
1504     }
1505
1506   public void editSequence_actionPerformed(ActionEvent actionEvent)
1507   {
1508       SequenceGroup sg = ap.av.getSelectionGroup();
1509
1510       if(sg!=null)
1511       {
1512         if (sequence == null)
1513           sequence = (Sequence) sg.getSequenceAt(0);
1514
1515         EditNameDialog dialog = new EditNameDialog(
1516             sequence.getSequenceAsString(
1517                 sg.getStartRes(),
1518                 sg.getEndRes() + 1),
1519             null,
1520             "Edit Sequence ",
1521             null,
1522             "Edit Sequence");
1523
1524         if (dialog.accept)
1525         {
1526           EditCommand editCommand = new EditCommand(
1527               "Edit Sequences", EditCommand.REPLACE,
1528               dialog.getName().replace(' ', ap.av.getGapCharacter()),
1529               sg.getSequencesAsArray(ap.av.hiddenRepSequences),
1530               sg.getStartRes(), sg.getEndRes() + 1, ap.av.alignment
1531               );
1532
1533           ap.alignFrame.addHistoryItem(editCommand);
1534
1535           ap.av.firePropertyChange("alignment", null,
1536                                    ap.av.getAlignment().getSequences());
1537         }
1538       }
1539   }
1540
1541
1542 }