d98084f7ae430531914e335c72a20acefd03b123
[jalview.git] / src / jalview / gui / AlignFrame.java
1 /********************
2  * 2004 Jalview Reengineered
3  * Barton Group
4  * Dundee University
5  *
6  * AM Waterhouse
7  *******************/
8
9
10
11
12 package jalview.gui;
13
14 import java.util.*;
15
16 import java.awt.*;
17 import java.awt.datatransfer.*;
18 import java.awt.event.*;
19 import java.awt.print.*;
20 import javax.swing.*;
21 import javax.swing.event.*;
22
23 import jalview.analysis.*;
24 import jalview.datamodel.*;
25 import jalview.io.*;
26 import jalview.jbgui.*;
27 import jalview.schemes.*;
28 import jalview.ws.*;
29 import java.beans.PropertyChangeEvent;
30
31 public class AlignFrame extends GAlignFrame
32 {
33   final AlignmentPanel alignPanel;
34   final AlignViewport viewport;
35   public static final int NEW_WINDOW_WIDTH = 700;
36   public static final int NEW_WINDOW_HEIGHT = 500;
37   public String currentFileFormat = "Jalview";
38
39   public AlignFrame(AlignmentI al)
40   {
41     viewport = new AlignViewport(al);
42
43     alignPanel = new AlignmentPanel(this, viewport);
44     alignPanel.annotationPanel.adjustPanelHeight();
45     alignPanel.annotationSpaceFillerHolder.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
46     alignPanel.annotationScroller.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
47     alignPanel.setAnnotationVisible( viewport.getShowAnnotation() );
48
49     getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);
50
51     addInternalFrameListener(new InternalFrameAdapter()
52    {
53      public void internalFrameActivated(InternalFrameEvent evt)
54      {
55           javax.swing.SwingUtilities.invokeLater(new Runnable()
56           {
57             public void run()
58             {      alignPanel.requestFocus();    }
59           });
60
61      }
62    });
63
64   }
65
66   public void saveAlignmentMenu_actionPerformed(ActionEvent e)
67   {
68     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty("LAST_DIRECTORY")
69         ,  new String[]{"fa, fasta, fastq", "aln",  "pfam", "msf", "pir","blc","jar"},
70           new String[]{"Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"},
71           currentFileFormat);
72
73     chooser.setAcceptAllFileFilterUsed(false);
74     chooser.setFileView(new JalviewFileView());
75     chooser.setDialogTitle("Save Alignment to file");
76     chooser.setToolTipText("Save");
77     int value = chooser.showSaveDialog(this);
78     if(value == JalviewFileChooser.APPROVE_OPTION)
79     {
80       currentFileFormat  = chooser.getSelectedFormat();
81       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat);
82
83       if (currentFileFormat.equals("Jalview"))
84       {
85         String shortName = title.replace('/', '_');
86         title = title.replace('\\', '_');
87         String choice = chooser.getSelectedFile().getPath();
88         Jalview2XML.SaveState(this, choice, shortName);
89         // USE Jalview2XML to save this file
90         return;
91       }
92
93       String choice =  chooser.getSelectedFile().getPath();
94       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
95       String output = FormatAdapter.formatSequences(currentFileFormat, viewport.getAlignment().getSequences());
96       try{
97         java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter( choice )  );
98         out.println(output);
99         out.close();
100       }
101       catch(Exception ex){}
102     }
103
104   }
105
106   protected void outputText_actionPerformed(ActionEvent e)
107   {
108      CutAndPasteTransfer cap = new CutAndPasteTransfer();
109      Desktop.addInternalFrame(cap, "Alignment output - "+e.getActionCommand(), 600, 500);
110      cap.setText( FormatAdapter.formatSequences(e.getActionCommand(), viewport.getAlignment().getSequences()));
111   }
112
113   protected void htmlMenuItem_actionPerformed(ActionEvent e)
114   {
115     new HTMLOutput(viewport);
116   }
117
118   protected void createPNG_actionPerformed(ActionEvent e)
119   {
120     alignPanel.makePNG();
121   }
122
123   protected void epsFile_actionPerformed(ActionEvent e)
124   {
125     alignPanel.makeEPS();
126   }
127
128
129   public void printMenuItem_actionPerformed(ActionEvent e)
130   {
131     //Putting in a thread avoids Swing painting problems
132     PrintThread thread = new PrintThread();
133     thread.start();
134   }
135
136   class PrintThread extends Thread
137   {
138     public void run()
139     {
140       PrinterJob printJob = PrinterJob.getPrinterJob();
141       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
142       printJob.setPrintable(alignPanel, pf);
143       if (printJob.printDialog())
144       {
145         try
146         {
147           printJob.print();
148         }
149         catch (Exception PrintException)
150         {
151           PrintException.printStackTrace();
152         }
153       }
154     }
155
156   }
157
158
159
160
161   public void closeMenuItem_actionPerformed(ActionEvent e)
162   {
163     try{
164       this.setClosed(true);
165     }catch(Exception ex){}
166   }
167
168   Stack historyList = new Stack();
169   Stack redoList = new Stack();
170   private int treeCount = 0;
171
172   void updateEditMenuBar()
173    {
174      if(historyList.size()>0)
175       {
176         undoMenuItem.setEnabled(true);
177         HistoryItem hi = (HistoryItem)historyList.peek();
178         undoMenuItem.setText("Undo "+hi.getDescription());
179       }
180      else
181      {
182        undoMenuItem.setEnabled(false);
183        undoMenuItem.setText("Undo");
184      }
185
186      if(redoList.size()>0)
187       {
188         redoMenuItem.setEnabled(true);
189         HistoryItem hi = (HistoryItem)redoList.peek();
190         redoMenuItem.setText("Redo "+hi.getDescription());
191       }
192      else
193      {
194        redoMenuItem.setEnabled(false);
195        redoMenuItem.setText("Redo");
196      }
197    }
198
199    public void addHistoryItem(HistoryItem hi)
200    {
201      historyList.push(hi);
202      updateEditMenuBar();
203    }
204
205    protected void undoMenuItem_actionPerformed(ActionEvent e)
206    {
207        HistoryItem hi = (HistoryItem)historyList.pop();
208        redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment, HistoryItem.HIDE));
209        restoreHistoryItem(hi);
210    }
211
212
213    protected void redoMenuItem_actionPerformed(ActionEvent e)
214    {
215       HistoryItem hi = (HistoryItem)redoList.pop();
216       restoreHistoryItem(hi);
217       updateEditMenuBar();
218       viewport.updateConsensus();
219       alignPanel.repaint();
220       alignPanel.repaint();
221    }
222
223
224    // used by undo and redo
225    void restoreHistoryItem(HistoryItem hi)
226    {
227       if(hi.getType()== HistoryItem.SORT)
228       {
229            for(int i=0; i<hi.getSequences().size(); i++)
230              viewport.alignment.getSequences().setElementAt(hi.getSequences().elementAt(i), i);
231       }
232       else
233       {
234         for (int i = 0; i < hi.getSequences().size(); i++)
235         {
236           SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);
237           if(restore.getLength()==0)
238           {
239             restore.setSequence(hi.getHidden().elementAt(i).toString());
240             viewport.alignment.getSequences().insertElementAt(
241                restore,
242                hi.getAlignIndex(i));
243           }
244           else
245             restore.setSequence(hi.getHidden().elementAt(i).toString());
246         }
247         if(hi.getType()==HistoryItem.PASTE)
248         {
249           for(int i=viewport.alignment.getHeight()-1;i>hi.getSequences().size()-1; i--)
250             viewport.alignment.deleteSequence(i);
251         }
252       }
253       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
254       updateEditMenuBar();
255
256       viewport.updateConsensus();
257       viewport.updateConservation();
258       alignPanel.repaint();
259   }
260
261   public void moveSelectedSequences(boolean up)
262   {
263     SequenceGroup sg = viewport.getSelectionGroup();
264     if (sg == null)
265       return;
266
267     if (up)
268     {
269       for (int i = 1; i < viewport.alignment.getHeight(); i++)
270       {
271         SequenceI seq = viewport.alignment.getSequenceAt(i);
272         if (!sg.sequences.contains(seq))
273           continue;
274
275         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
276         if (sg.sequences.contains(temp))
277           continue;
278
279         viewport.alignment.getSequences().setElementAt(temp, i);
280         viewport.alignment.getSequences().setElementAt(seq, i - 1);
281       }
282     }
283     else
284     {
285       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
286       {
287         SequenceI seq = viewport.alignment.getSequenceAt(i);
288         if (!sg.sequences.contains(seq))
289           continue;
290
291         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
292         if (sg.sequences.contains(temp))
293           continue;
294
295         viewport.alignment.getSequences().setElementAt(temp, i);
296         viewport.alignment.getSequences().setElementAt(seq, i + 1);
297       }
298     }
299
300     alignPanel.repaint();
301   }
302
303
304
305   protected void copy_actionPerformed(ActionEvent e)
306   {
307      if(viewport.getSelectionGroup()==null)
308        return;
309
310      SequenceGroup sg = viewport.getSelectionGroup();
311
312      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
313      StringBuffer buffer= new StringBuffer();
314
315      Hashtable orderedSeqs = new Hashtable();
316      for(int i=0; i<sg.getSize(); i++)
317      {
318         SequenceI seq = sg.getSequenceAt(i);
319         int index = viewport.alignment.findIndex(seq);
320         orderedSeqs.put(index+"", seq);
321      }
322
323      int index=0;
324      for(int i=0; i<sg.getSize(); i++)
325      {
326        SequenceI seq = null;
327        while( seq == null )
328        {
329          if(orderedSeqs.containsKey(index+""))
330          {
331            seq = (SequenceI) orderedSeqs.get(index + "");
332            index++;
333            break;
334          }
335          else
336            index++;
337        }
338
339          buffer.append( seq.getName()+"\t"+seq.findPosition( sg.getStartRes() ) +"\t"
340                         +seq.findPosition( sg.getEndRes() )+ "\t"
341                         +sg.getSequenceAt(i).getSequence(sg.getStartRes(), sg.getEndRes()+1)+"\n");
342      }
343      c.setContents( new StringSelection( buffer.toString()) , null ) ;
344
345   }
346
347
348   protected void pasteNew_actionPerformed(ActionEvent e)
349   {
350     paste(true);
351   }
352
353   protected void pasteThis_actionPerformed(ActionEvent e)
354   {
355     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment, HistoryItem.PASTE));
356     paste(false);
357   }
358
359   void paste(boolean newAlignment)
360   {
361     try{
362       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
363       Transferable contents = c.getContents(this);
364       if (contents == null)
365         return;
366
367       String str = (String) contents.getTransferData(DataFlavor.stringFlavor);
368       StringTokenizer st = new StringTokenizer(str);
369       ArrayList seqs = new ArrayList();
370       while (st.hasMoreElements())
371       {
372         String name = st.nextToken();
373         int start = Integer.parseInt(st.nextToken());
374         int end = Integer.parseInt(st.nextToken());
375         Sequence sequence = new Sequence(name,st.nextToken(), start, end);
376
377         if(!newAlignment)
378           viewport.alignment.addSequence(sequence);
379         else
380           seqs.add(sequence);
381       }
382
383       if(newAlignment)
384       {
385         SequenceI[] newSeqs = new SequenceI[seqs.size()];
386         seqs.toArray(newSeqs);
387         AlignFrame af = new AlignFrame(new Alignment(newSeqs));
388         String newtitle = new String("Copied sequences");
389         if( title.startsWith("Copied sequences"))
390          newtitle = title;
391        else
392          newtitle = newtitle.concat("- from "+title);
393
394         Desktop.addInternalFrame(af, newtitle, NEW_WINDOW_WIDTH, NEW_WINDOW_HEIGHT);
395       }
396       else
397       {
398         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
399         viewport.setEndSeq(viewport.alignment.getHeight());
400         viewport.alignment.getWidth();
401         viewport.updateConservation();
402         viewport.updateConsensus();
403         alignPanel.repaint();
404       }
405
406     }catch(Exception ex){}// could be anything being pasted in here
407
408   }
409
410
411   protected void cut_actionPerformed(ActionEvent e)
412   {
413     copy_actionPerformed(null);
414     delete_actionPerformed(null);
415   }
416
417   protected void delete_actionPerformed(ActionEvent e)
418   {
419     boolean seqsdeleted=false;
420     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, HistoryItem.HIDE));
421
422     if (viewport.getSelectionGroup() == null)
423       return;
424
425      SequenceGroup sg = viewport.getSelectionGroup();
426      for (int i=0;i < sg.sequences.size(); i++)
427      {
428        SequenceI seq = sg.getSequenceAt(i);
429        int index = viewport.getAlignment().findIndex(seq);
430        seq.deleteChars(sg.getStartRes(),sg.getEndRes()+1);
431
432        if(seq.getSequence().length()<1) {
433          seqsdeleted=true;
434          viewport.getAlignment().deleteSequence(seq);
435         } else {
436          viewport.getAlignment().getSequences().setElementAt(seq, index);
437        }
438      }
439
440      viewport.setSelectionGroup(null);
441      viewport.alignment.deleteGroup(sg);
442      if (seqsdeleted)
443        viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
444      viewport.resetSeqLimits( alignPanel.seqPanel.seqCanvas.getHeight());
445      if(viewport.getAlignment().getHeight()<1)
446      try
447      {
448        this.setClosed(true);
449      }catch(Exception ex){}
450    viewport.updateConservation();
451    viewport.updateConsensus();
452    alignPanel.repaint();
453  }
454
455
456   protected void deleteGroups_actionPerformed(ActionEvent e)
457   {
458     viewport.alignment.deleteAllGroups();
459     viewport.setSelectionGroup(null);
460     alignPanel.repaint();
461   }
462
463
464
465   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
466   {
467     SequenceGroup sg = new SequenceGroup();
468     for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)
469       sg.addSequence( viewport.getAlignment().getSequenceAt(i));
470     sg.setEndRes(viewport.alignment.getWidth());
471     viewport.setSelectionGroup(sg);
472     PaintRefresher.Refresh(null);
473   }
474
475   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
476   {
477     viewport.setSelectionGroup(null);
478     viewport.getColumnSelection().clear();
479     viewport.setSelectionGroup(null);
480     PaintRefresher.Refresh(null);
481   }
482
483   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
484   {
485     SequenceGroup sg = viewport.getSelectionGroup();
486     for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)
487       sg.addOrRemove (viewport.getAlignment().getSequenceAt(i));
488
489     PaintRefresher.Refresh(null);
490   }
491
492   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
493   {
494     ColumnSelection colSel = viewport.getColumnSelection();
495     if (colSel.size() > 0)
496     {
497       addHistoryItem(new HistoryItem("Remove Left",viewport.alignment,
498                                      HistoryItem.HIDE));
499       int min = colSel.getMin();
500       viewport.getAlignment().trimLeft(min);
501       colSel.compensateForEdit(0,min);
502
503       if(viewport.getSelectionGroup()!=null)
504         viewport.getSelectionGroup().adjustForRemoveLeft(min);
505
506       Vector groups = viewport.alignment.getGroups();
507       for(int i=0; i<groups.size(); i++)
508       {
509         SequenceGroup sg = (SequenceGroup) groups.get(i);
510         if(!sg.adjustForRemoveLeft(min))
511           viewport.alignment.deleteGroup(sg);
512       }
513
514       alignPanel.repaint();
515     }
516   }
517
518   public void remove2RightMenuItem_actionPerformed(ActionEvent e)
519   {
520     ColumnSelection colSel = viewport.getColumnSelection();
521     if (colSel.size() > 0)
522     {
523       addHistoryItem(new HistoryItem("Remove Right",viewport.alignment,
524                                      HistoryItem.HIDE));
525
526       int max = colSel.getMax();
527       viewport.getAlignment().trimRight(max);
528       if(viewport.getSelectionGroup()!=null)
529         viewport.getSelectionGroup().adjustForRemoveRight(max);
530
531       Vector groups = viewport.alignment.getGroups();
532       for(int i=0; i<groups.size(); i++)
533       {
534         SequenceGroup sg = (SequenceGroup) groups.get(i);
535         if(!sg.adjustForRemoveRight(max))
536           viewport.alignment.deleteGroup(sg);
537       }
538
539
540
541       alignPanel.repaint();
542     }
543
544   }
545
546   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
547   {
548     addHistoryItem(new HistoryItem("Remove Gapped Columns",
549                                    viewport.alignment,
550                                    HistoryItem.HIDE));
551
552     viewport.getAlignment().removeGaps();
553     viewport.updateConservation();
554     viewport.updateConsensus();
555     alignPanel.repaint();
556   }
557
558   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
559   {
560     addHistoryItem(new HistoryItem("Remove Gaps",
561                                    viewport.alignment,
562                                    HistoryItem.HIDE));
563     SequenceI current;
564     int jSize;
565     for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
566     {
567       current = viewport.getAlignment().getSequenceAt(i);
568       jSize = current.getLength();
569       for (int j=0; j < jSize; j++)
570         if(jalview.util.Comparison.isGap(current.getCharAt(j)))
571         {
572           current.deleteCharAt(j);
573           j--;
574           jSize--;
575         }
576     }
577     viewport.updateConservation();
578     viewport.updateConsensus();
579     alignPanel.repaint();
580   }
581
582
583   public void padGapsMenuitem_actionPerformed(ActionEvent e)
584     {
585       addHistoryItem(new HistoryItem("Pad Gaps",
586                                      viewport.alignment,
587                                      HistoryItem.HIDE));
588       SequenceI current;
589       int Width = viewport.getAlignment().getWidth()-1;
590       for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
591       {
592         current = viewport.getAlignment().getSequenceAt(i);
593
594         if (current.getLength()<Width)
595           current.insertCharAt(Width, viewport.getGapCharacter());
596       }
597       viewport.updateConservation();
598       viewport.updateConsensus();
599       alignPanel.repaint();
600   }
601
602
603   public void findMenuItem_actionPerformed(ActionEvent e)
604   {
605     JInternalFrame frame = new JInternalFrame();
606     Finder finder = new Finder(viewport, alignPanel, frame);
607     frame.setContentPane(finder);
608     Desktop.addInternalFrame(frame, "Find", 340,110);
609     frame.setLayer(JLayeredPane.PALETTE_LAYER);
610
611   }
612
613
614   public void font_actionPerformed(ActionEvent e)
615   {
616     FontChooser fc = new FontChooser( alignPanel );
617   }
618
619   protected void fullSeqId_actionPerformed(ActionEvent e)
620   {
621     viewport.setShowFullId( fullSeqId.isSelected() );
622
623     alignPanel.idPanel.idCanvas.setPreferredSize( alignPanel.calculateIdWidth() );
624     alignPanel.repaint();
625   }
626
627   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
628   {
629       viewport.setColourText( colourTextMenuItem.isSelected() );
630       alignPanel.repaint();
631   }
632
633   protected void wrapMenuItem_actionPerformed(ActionEvent e)
634   {
635     viewport.setWrapAlignment( wrapMenuItem.isSelected() );
636     alignPanel.setWrapAlignment( wrapMenuItem.isSelected() );
637     scaleAbove.setVisible( wrapMenuItem.isSelected() );
638     scaleLeft.setVisible( wrapMenuItem.isSelected() );
639     scaleRight.setVisible( wrapMenuItem.isSelected() );
640     alignPanel.repaint();
641   }
642
643   protected void scaleAbove_actionPerformed(ActionEvent e)
644   {
645     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
646     alignPanel.repaint();
647   }
648
649   protected void scaleLeft_actionPerformed(ActionEvent e)
650   {
651     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
652     alignPanel.repaint();
653   }
654
655   protected void scaleRight_actionPerformed(ActionEvent e)
656   {
657     viewport.setScaleRightWrapped(scaleRight.isSelected());
658     alignPanel.repaint();
659   }
660
661
662
663   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
664   {
665     viewport.setShowBoxes( viewBoxesMenuItem.isSelected() );
666     alignPanel.repaint();
667   }
668
669   public void viewTextMenuItem_actionPerformed(ActionEvent e)
670   {
671     viewport.setShowText( viewTextMenuItem.isSelected() );
672     alignPanel.repaint();
673   }
674
675
676   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
677   {
678     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
679     alignPanel.repaint();
680   }
681
682   public void sequenceFeatures_actionPerformed(ActionEvent evt)
683   {
684     viewport.showSequenceFeatures(sequenceFeatures.isSelected());
685     if(viewport.showSequenceFeatures && !((Alignment)viewport.alignment).featuresAdded)
686     {
687          SequenceFeatureFetcher sft = new SequenceFeatureFetcher(viewport.alignment, alignPanel);
688          ((Alignment)viewport.alignment).featuresAdded = true;
689     }
690     alignPanel.repaint();
691   }
692
693   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
694   {
695     if(annotationPanelMenuItem.isSelected() && viewport.getWrapAlignment())
696     {
697       annotationPanelMenuItem.setSelected(false);
698       return;
699     }
700     viewport.setShowAnnotation( annotationPanelMenuItem.isSelected() );
701     alignPanel.setAnnotationVisible( annotationPanelMenuItem.isSelected() );
702   }
703
704   public void overviewMenuItem_actionPerformed(ActionEvent e)
705   {
706     if (alignPanel.overviewPanel != null)
707       return;
708
709     JInternalFrame frame = new JInternalFrame();
710     OverviewPanel overview = new OverviewPanel(alignPanel);
711      frame.setContentPane(overview);
712     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
713                              frame.getWidth(), frame.getHeight());
714     frame.pack();
715     frame.setLayer(JLayeredPane.PALETTE_LAYER);
716     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
717     { public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)
718       {
719             alignPanel.setOverviewPanel(null);
720       };
721     });
722
723     alignPanel.setOverviewPanel( overview );
724
725
726   }
727
728   protected void noColourmenuItem_actionPerformed(ActionEvent e)
729   {
730     changeColour( null );
731   }
732
733
734   public void clustalColour_actionPerformed(ActionEvent e)
735   {
736     changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(), viewport.alignment.getWidth()));
737   }
738
739   public void zappoColour_actionPerformed(ActionEvent e)
740   {
741     changeColour(new ZappoColourScheme());
742   }
743
744   public void taylorColour_actionPerformed(ActionEvent e)
745   {
746     changeColour(new TaylorColourScheme());
747   }
748
749
750   public void hydrophobicityColour_actionPerformed(ActionEvent e)
751   {
752     changeColour( new HydrophobicColourScheme() );
753   }
754
755   public void helixColour_actionPerformed(ActionEvent e)
756   {
757     changeColour(new HelixColourScheme() );
758   }
759
760
761   public void strandColour_actionPerformed(ActionEvent e)
762   {
763     changeColour(new StrandColourScheme());
764   }
765
766
767   public void turnColour_actionPerformed(ActionEvent e)
768   {
769     changeColour(new TurnColourScheme());
770   }
771
772
773   public void buriedColour_actionPerformed(ActionEvent e)
774   {
775     changeColour(new BuriedColourScheme() );
776   }
777
778   public void nucleotideColour_actionPerformed(ActionEvent e)
779   {
780     changeColour(new NucleotideColourScheme());
781   }
782
783
784   protected void applyToAllGroups_actionPerformed(ActionEvent e)
785   {
786     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
787   }
788
789
790
791   void changeColour(ColourSchemeI cs)
792   {
793     int threshold = 0;
794
795     if ( viewport.getAbovePIDThreshold() )
796     {
797       threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");
798
799       if (cs instanceof ResidueColourScheme)
800         ( (ResidueColourScheme) cs).setThreshold(threshold);
801       else if (cs instanceof ScoreColourScheme)
802         ( (ScoreColourScheme) cs).setThreshold(threshold);
803
804       viewport.setGlobalColourScheme(cs);
805     }
806     else if (cs instanceof ResidueColourScheme)
807       ( (ResidueColourScheme) cs).setThreshold(0);
808     else if (cs instanceof ScoreColourScheme)
809       ( (ScoreColourScheme) cs).setThreshold(0);
810
811
812
813     if (viewport.getConservationSelected())
814     {
815       ConservationColourScheme ccs = null;
816
817       Alignment al = (Alignment) viewport.alignment;
818       Conservation c = new Conservation("All",
819                                         ResidueProperties.propHash, 3,
820                                         al.getSequences(), 0,
821                                         al.getWidth() - 1);
822
823       c.calculate();
824       c.verdict(false, viewport.ConsPercGaps);
825
826       ccs = new ConservationColourScheme(c, cs);
827
828       // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
829       ccs.setConsensus( viewport.vconsensus );
830       viewport.setGlobalColourScheme(ccs);
831
832       ccs.inc = SliderPanel.setConservationSlider(alignPanel, ccs, "Background");
833
834     }
835     else
836     {
837         // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
838         if (cs != null)
839           cs.setConsensus(viewport.vconsensus);
840         viewport.setGlobalColourScheme(cs);
841     }
842
843
844     if(viewport.getColourAppliesToAllGroups())
845     {
846       Vector groups = viewport.alignment.getGroups();
847       for(int i=0; i<groups.size(); i++)
848       {
849         SequenceGroup sg = (SequenceGroup)groups.elementAt(i);
850
851         if(cs==null)
852           sg.cs = null;
853         else if (cs instanceof ClustalxColourScheme)
854           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());
855         else if (cs instanceof UserColourScheme)
856           sg.cs = new UserColourScheme( ((UserColourScheme)cs).getColours());
857         else
858           try{
859             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
860           }catch(Exception ex){}
861
862         if(viewport.getAbovePIDThreshold())
863         {
864           if (sg.cs instanceof ResidueColourScheme)
865             ( (ResidueColourScheme) sg.cs).setThreshold(threshold);
866           else if (sg.cs instanceof ScoreColourScheme)
867             ( (ScoreColourScheme) sg.cs).setThreshold(threshold);
868
869            sg.cs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()) );
870         }
871
872         if( viewport.getConservationSelected() )
873         {
874           Conservation c = new Conservation("Group",
875                                             ResidueProperties.propHash, 3,
876                                             sg.sequences, 0, viewport.alignment.getWidth()-1);
877           c.calculate();
878           c.verdict(false, viewport.ConsPercGaps);
879           ConservationColourScheme ccs = new ConservationColourScheme(c, sg.cs);
880
881           // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
882           ccs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
883           sg.cs = ccs;
884         }
885         else if(cs!=null)
886         {
887           // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
888           sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
889         }
890
891       }
892     }
893
894     if(alignPanel.getOverviewPanel()!=null)
895       alignPanel.getOverviewPanel().updateOverviewImage();
896     alignPanel.repaint();
897   }
898
899   protected void modifyPID_actionPerformed(ActionEvent e)
900   {
901       if(viewport.getAbovePIDThreshold())
902       {
903         SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),
904                                    "Background");
905         SliderPanel.showPIDSlider();
906       }
907   }
908
909   protected void modifyConservation_actionPerformed(ActionEvent e)
910   {
911     if(viewport.getConservationSelected())
912     {
913       SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,
914                                         "Background");
915       SliderPanel.showConservationSlider();
916     }
917   }
918
919
920   protected  void conservationMenuItem_actionPerformed(ActionEvent e)
921   {
922     viewport.setConservationSelected(conservationMenuItem.isSelected());
923
924     viewport.setAbovePIDThreshold(false);
925     abovePIDThreshold.setSelected(false);
926
927    ColourSchemeI cs = viewport.getGlobalColourScheme();
928    if(cs instanceof ConservationColourScheme )
929      changeColour( ((ConservationColourScheme)cs).cs );
930     else
931       changeColour( cs );
932
933     modifyConservation_actionPerformed(null);
934   }
935
936   public void abovePIDThreshold_actionPerformed(ActionEvent e)
937   {
938     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
939
940     conservationMenuItem.setSelected(false);
941     viewport.setConservationSelected(false);
942
943     ColourSchemeI cs = viewport.getGlobalColourScheme();
944
945     if(cs instanceof ConservationColourScheme )
946         changeColour( ((ConservationColourScheme)cs).cs );
947     else
948         changeColour( cs );
949
950     modifyPID_actionPerformed(null);
951   }
952
953
954
955   public void userDefinedColour_actionPerformed(ActionEvent e)
956   {
957     new UserDefinedColours( alignPanel, null);
958   }
959
960   public void PIDColour_actionPerformed(ActionEvent e)
961   {
962     changeColour( new PIDColourScheme() );
963   }
964
965
966   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
967   {
968     changeColour(new Blosum62ColourScheme() );
969   }
970
971
972
973   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
974   {
975     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment, HistoryItem.SORT));
976     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport.getAlignment().getSequenceAt(0));
977     alignPanel.repaint();
978   }
979
980   public void sortIDMenuItem_actionPerformed(ActionEvent e)
981   {
982     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment, HistoryItem.SORT));
983     AlignmentSorter.sortByID( viewport.getAlignment() );
984     alignPanel.repaint();
985   }
986
987   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
988   {
989     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment, HistoryItem.SORT));
990     AlignmentSorter.sortByGroup(viewport.getAlignment());
991     AlignmentSorter.sortGroups(viewport.getAlignment());
992     alignPanel.repaint();
993   }
994
995   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
996   {
997     RedundancyPanel sp = new RedundancyPanel(alignPanel);
998     JInternalFrame frame = new JInternalFrame();
999     frame.setContentPane(sp);
1000     Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400, 100, false);
1001
1002   }
1003
1004   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
1005   {
1006     if(viewport.getSelectionGroup().getSize()<2)
1007       JOptionPane.showInternalMessageDialog(this, "You must select at least 2 sequences.", "Invalid Selection", JOptionPane.WARNING_MESSAGE);
1008     else
1009     {
1010       JInternalFrame frame = new JInternalFrame();
1011       frame.setContentPane(new PairwiseAlignPanel(viewport));
1012       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
1013     }
1014   }
1015
1016   public void PCAMenuItem_actionPerformed(ActionEvent e)
1017   {
1018
1019     if( (viewport.getSelectionGroup()!=null && viewport.getSelectionGroup().getSize()<4 && viewport.getSelectionGroup().getSize()>0)
1020        || viewport.getAlignment().getHeight()<4)
1021     {
1022       JOptionPane.showInternalMessageDialog(this, "Principal component analysis must take\n"
1023                                     +"at least 4 input sequences.",
1024                                     "Sequence selection insufficient",
1025                                     JOptionPane.WARNING_MESSAGE);
1026       return;
1027     }
1028
1029     try{
1030       PCAPanel pcaPanel = new PCAPanel(viewport, null);
1031       JInternalFrame frame = new JInternalFrame();
1032       frame.setContentPane(pcaPanel);
1033       Desktop.addInternalFrame(frame, "Principal component analysis", 400, 400);
1034    }catch(java.lang.OutOfMemoryError ex)
1035    {
1036      JOptionPane.showInternalMessageDialog(this, "Too many sequences selected\nfor Principal Component Analysis!!",
1037                                    "Out of memory", JOptionPane.WARNING_MESSAGE);
1038    }
1039
1040
1041   }
1042
1043   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
1044   {
1045     NewTreePanel("AV", "PID", "Average distance tree using PID");
1046   }
1047
1048   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
1049   {
1050     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
1051   }
1052
1053
1054   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
1055   {
1056     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
1057   }
1058
1059   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
1060   {
1061     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
1062   }
1063
1064   void NewTreePanel(String type, String pwType, String title)
1065   {
1066     //are the sequences aligned?
1067     if(!viewport.alignment.isAligned())
1068     {
1069       JOptionPane.showMessageDialog(Desktop.desktop, "The sequences must be aligned before creating a tree.\n"
1070                                    +"Try using the Pad function in the edit menu,\n"
1071                                   +"or one of the multiple sequence alignment web services.",
1072                                     "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
1073       return;
1074     }
1075
1076     final TreePanel tp;
1077     if (viewport.getSelectionGroup() != null &&
1078         viewport.getSelectionGroup().getSize() > 3)
1079     {
1080       tp = new TreePanel(viewport, viewport.getSelectionGroup().sequences, type,
1081                          pwType,
1082                          0, viewport.alignment.getWidth());
1083     }
1084     else
1085     {
1086       tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),
1087                          type, pwType, 0, viewport.alignment.getWidth());
1088     }
1089
1090    addTreeMenuItem(tp, title);
1091
1092    Desktop.addInternalFrame(tp, title, 600, 500);
1093   }
1094
1095   public void addSortByOrderMenuItem(String title, final AlignmentOrder order) {
1096     final JMenuItem item = new JMenuItem("by "+title);
1097     sort.add(item);
1098     item.addActionListener(new java.awt.event.ActionListener()
1099     {
1100       public void actionPerformed(ActionEvent e)
1101       {
1102         addHistoryItem(new HistoryItem("Sort", viewport.alignment,
1103                                        HistoryItem.SORT));
1104         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
1105         AlignmentSorter.sortBy(viewport.getAlignment(), order);
1106         alignPanel.repaint();
1107       }
1108     });
1109   }
1110
1111   void addTreeMenuItem(final TreePanel treePanel, String title)
1112   {
1113     final JMenuItem item = new JMenuItem(title);
1114
1115     treeCount++;
1116
1117     if (treeCount==1)
1118       sort.add(sortByTreeMenu);
1119
1120     sortByTreeMenu.add(item);
1121     item.addActionListener(new java.awt.event.ActionListener()
1122     {
1123       public void actionPerformed(ActionEvent e)
1124       {
1125         addHistoryItem(new HistoryItem("Tree Sort", viewport.alignment,
1126                                        HistoryItem.SORT));
1127         AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());
1128         alignPanel.repaint();
1129       }
1130     });
1131
1132     treePanel.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
1133     {
1134       public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)
1135       {
1136         treeCount--;
1137         sortByTreeMenu.remove(item);
1138         if (treeCount==0)
1139           sort.remove(sortByTreeMenu);
1140       };
1141     });
1142     viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
1143       public void propertyChange(PropertyChangeEvent evt)
1144       {
1145         if (evt.getPropertyName().equals("alignment")) {
1146           treePanel.getTree().UpdatePlaceHolders( (Vector) evt.getNewValue());
1147           treePanel.repaint();
1148         }
1149       }
1150
1151     }
1152     );
1153   }
1154
1155
1156   public void clustalAlignMenuItem_actionPerformed(ActionEvent e)
1157   {
1158       // TODO:resolve which menu item was actually selected
1159       // Now, check we have enough sequences
1160         SequenceI[] msa=null;
1161         if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
1162         {
1163           // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1164           SequenceGroup seqs = viewport.getSelectionGroup();
1165           int sz;
1166           msa = new SequenceI[sz=seqs.getSize()];
1167           for (int i = 0; i < sz; i++)
1168           {
1169             msa[i] = (SequenceI) seqs.getSequenceAt(i);
1170           }
1171
1172           }
1173         else
1174         {
1175           Vector seqs = viewport.getAlignment().getSequences();
1176
1177           if (seqs.size() > 1) {
1178             msa = new SequenceI[seqs.size()];
1179             for (int i = 0; i < seqs.size(); i++)
1180             {
1181               msa[i] = (SequenceI) seqs.elementAt(i);
1182             }
1183
1184           }
1185
1186         }
1187         if (msa!=null) {
1188           jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, true, true);
1189         }
1190   }
1191
1192   protected void jpred_actionPerformed(ActionEvent e)
1193 {
1194     SequenceI seq=null;
1195     SequenceI[] msa=null;
1196
1197     if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>0)
1198     {
1199       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1200       SequenceGroup seqs = viewport.getSelectionGroup();
1201       if (seqs.getSize() == 1 || !viewport.alignment.isAligned())
1202       {
1203         seq = (SequenceI)seqs.getSequenceAt(0);
1204       }
1205       else
1206       {
1207         int sz;
1208         msa = new SequenceI[sz=seqs.getSize()];
1209         for (int i = 0; i < sz; i++)
1210         {
1211           msa[i] = (SequenceI) seqs.getSequenceAt(i);
1212         }
1213       }
1214     }
1215     else
1216     {
1217       Vector seqs = viewport.getAlignment().getSequences();
1218
1219       if (seqs.size() == 1 || !viewport.alignment.isAligned())
1220       {
1221         seq = (SequenceI) seqs.elementAt(0);
1222       }
1223       else
1224       {
1225         msa = new SequenceI[seqs.size()];
1226         for (int i = 0; i < seqs.size(); i++)
1227         {
1228           msa[i] = (SequenceI) seqs.elementAt(i);
1229         }
1230       }
1231     }
1232     if (msa!=null) {
1233       JPredClient ct = new JPredClient(title, msa);
1234     } else
1235     if (seq!=null) {
1236       JPredClient ct = new JPredClient(title, seq);
1237     } else {
1238       System.err.print("JALVIEW ERROR! - Unexpected JPred selection state!\n");
1239     }
1240   }
1241   protected void msaAlignMenuItem_actionPerformed(ActionEvent e)
1242   {
1243     // TODO:resolve which menu item was actually selected
1244     // Now, check we have enough sequences
1245     SequenceI[] msa=null;
1246     if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
1247       {
1248         // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1249         SequenceGroup seqs = viewport.getSelectionGroup();
1250         int sz;
1251         msa = new SequenceI[sz=seqs.getSize()];
1252         for (int i = 0; i < sz; i++)
1253         {
1254           msa[i] = (SequenceI) seqs.getSequenceAt(i);
1255         }
1256
1257
1258       }
1259       else
1260       {
1261         Vector seqs = viewport.getAlignment().getSequences();
1262
1263         if (seqs.size() > 1) {
1264           msa = new SequenceI[seqs.size()];
1265           for (int i = 0; i < seqs.size(); i++)
1266           {
1267             msa[i] = (SequenceI) seqs.elementAt(i);
1268           }
1269
1270         }
1271
1272       }
1273       if (msa!=null) {
1274         MsaWSClient ct = new jalview.ws.MsaWSClient("MuscleWS",title, msa, true, true);
1275       }
1276   }
1277     protected void LoadtreeMenuItem_actionPerformed(ActionEvent e) {
1278     // Pick the tree file
1279     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1280         getProperty("LAST_DIRECTORY"));
1281     chooser.setFileView(new JalviewFileView());
1282     chooser.setDialogTitle("Select a newick-like tree file");
1283     chooser.setToolTipText("Load a tree file");
1284     int value = chooser.showOpenDialog(null);
1285     if (value == JalviewFileChooser.APPROVE_OPTION)
1286     {
1287       String choice = chooser.getSelectedFile().getPath();
1288       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1289       try
1290       {
1291         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice, "File");
1292         ShowNewickTree(fin, choice);
1293       }
1294       catch (Exception ex)
1295       {
1296         JOptionPane.showMessageDialog(Desktop.desktop,
1297                                       "Problem reading tree file",
1298                                       ex.getMessage(),
1299                                       JOptionPane.WARNING_MESSAGE);
1300         ex.printStackTrace();
1301       }
1302     }
1303   }
1304
1305   public void ShowNewickTree(NewickFile nf, String title)
1306   {
1307     try{
1308       nf.parse();
1309       if (nf.getTree() != null)
1310       {
1311         TreePanel tp = new TreePanel(viewport,
1312                                      viewport.getAlignment().getSequences(),
1313                                      nf, "FromFile", title);
1314         Desktop.addInternalFrame(tp, title, 600, 500);
1315         addTreeMenuItem(tp, title);
1316         viewport.setCurrentTree(tp.getTree());
1317       }
1318      }catch(Exception ex){ex.printStackTrace();}
1319   }
1320
1321 }