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