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