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