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