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