Use visible id for sorting
[jalview.git] / src / jalview / gui / AlignFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Softwarechang\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import java.beans.*;\r
22 import java.io.*;\r
23 import java.util.*;\r
24 \r
25 import java.awt.*;\r
26 import java.awt.datatransfer.*;\r
27 import java.awt.event.*;\r
28 import java.awt.print.*;\r
29 import javax.swing.*;\r
30 \r
31 import jalview.analysis.*;\r
32 import jalview.datamodel.*;\r
33 import jalview.io.*;\r
34 import jalview.jbgui.*;\r
35 import jalview.schemes.*;\r
36 import jalview.ws.*;\r
37 \r
38 /**\r
39  * DOCUMENT ME!\r
40  *\r
41  * @author $author$\r
42  * @version $Revision$\r
43  */\r
44 public class AlignFrame\r
45     extends GAlignFrame implements ClipboardOwner\r
46 {\r
47   /** DOCUMENT ME!! */\r
48   public static final int NEW_WINDOW_WIDTH = 700;\r
49 \r
50   /** DOCUMENT ME!! */\r
51   public static final int NEW_WINDOW_HEIGHT = 500;\r
52   AlignmentPanel alignPanel;\r
53   AlignViewport viewport;\r
54 \r
55   Vector viewports = new Vector();\r
56   Vector alignPanels = new Vector();\r
57 \r
58   /** DOCUMENT ME!! */\r
59   public String currentFileFormat = null;\r
60   Stack historyList = new Stack();\r
61   Stack redoList = new Stack();\r
62   private int treeCount = 0;\r
63 \r
64   /**\r
65    * Creates a new AlignFrame object.\r
66    *\r
67    * @param al DOCUMENT ME!\r
68    */\r
69   public AlignFrame(AlignmentI al)\r
70   {\r
71     viewport = new AlignViewport(al);\r
72     viewports.add(viewport);\r
73 \r
74 \r
75     if(viewport.vconsensus==null)\r
76     {\r
77       //Out of memory calculating consensus.\r
78       BLOSUM62Colour.setEnabled(false);\r
79       PIDColour.setEnabled(false);\r
80       conservationMenuItem.setEnabled(false);\r
81       modifyConservation.setEnabled(false);\r
82       abovePIDThreshold.setEnabled(false);\r
83       modifyPID.setEnabled(false);\r
84     }\r
85 \r
86     alignPanel = new AlignmentPanel(this, viewport);\r
87     alignPanels.add(alignPanel);\r
88 \r
89     String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT", "No sort");\r
90 \r
91     if(sortby.equals("Id"))\r
92       sortIDMenuItem_actionPerformed(null);\r
93     else if(sortby.equals("Pairwise Identity"))\r
94       sortPairwiseMenuItem_actionPerformed(null);\r
95 \r
96     tabbedPane.add(al.isNucleotide() ? "DNA":"Protein", alignPanel);\r
97 \r
98     ///Dataset tab\r
99     /////////////////////////\r
100 \r
101     if(al.getDataset()==null)\r
102     {\r
103       al.setDataset(null);\r
104     }\r
105 \r
106     AlignViewport ds = new AlignViewport(al.getDataset(), true);\r
107     AlignmentPanel dap = new AlignmentPanel(this, ds);\r
108     tabbedPane.add("Dataset", dap);\r
109     viewports.add(ds);\r
110     alignPanels.add(dap);\r
111     /////////////////////////\r
112 \r
113 \r
114     viewport.addPropertyChangeListener(new PropertyChangeListener()\r
115     {\r
116      public void propertyChange(PropertyChangeEvent evt)\r
117      {\r
118        if (evt.getPropertyName().equals("alignment"))\r
119        {\r
120          alignmentChanged();\r
121        }\r
122      }\r
123    });\r
124 \r
125 \r
126         if(Desktop.desktop!=null)\r
127     addServiceListeners();\r
128   }\r
129 \r
130   /* Set up intrinsic listeners for dynamically generated GUI bits. */\r
131   private void addServiceListeners()\r
132   {\r
133     final java.beans.PropertyChangeListener thisListener;\r
134     // Do this once to get current state\r
135     BuildWebServiceMenu();\r
136     Desktop.discoverer.addPropertyChangeListener(\r
137         thisListener = new java.beans.PropertyChangeListener()\r
138     {\r
139       public void propertyChange(PropertyChangeEvent evt)\r
140       {\r
141         // System.out.println("Discoverer property change.");\r
142         if (evt.getPropertyName().equals("services"))\r
143         {\r
144           // System.out.println("Rebuilding web service menu");\r
145           BuildWebServiceMenu();\r
146         }\r
147       }\r
148     });\r
149     addInternalFrameListener(new javax.swing.event.\r
150                              InternalFrameAdapter()\r
151     {\r
152       public void internalFrameClosed(\r
153           javax.swing.event.InternalFrameEvent evt)\r
154       {\r
155         // System.out.println("deregistering discoverer listener");\r
156         Desktop.discoverer.removePropertyChangeListener(thisListener);\r
157         closeMenuItem_actionPerformed(null);\r
158       }\r
159       ;\r
160     });\r
161 \r
162   }\r
163 \r
164   public AlignViewport getViewport()\r
165   {\r
166     return viewport;\r
167   }\r
168 \r
169 \r
170   /**\r
171    * DOCUMENT ME!\r
172    *\r
173    * @param String DOCUMENT ME!\r
174    */\r
175 \r
176   public void parseGroupsFile(String file)\r
177   {\r
178     try\r
179     {\r
180       BufferedReader in = new BufferedReader(new FileReader(file));\r
181       SequenceI seq = null;\r
182       String line, type, desc, token;\r
183 \r
184       int index, start, end;\r
185       StringTokenizer st;\r
186       SequenceFeature sf;\r
187       FeatureRenderer fr = alignPanel.seqPanel.seqCanvas.getFeatureRenderer();\r
188       int lineNo = 0;\r
189       while ( (line = in.readLine()) != null)\r
190       {\r
191         lineNo++;\r
192         st = new StringTokenizer(line, "\t");\r
193         if (st.countTokens() == 2)\r
194         {\r
195           type = st.nextToken();\r
196           UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
197           fr.setColour(type, ucs.findColour("A"));\r
198           continue;\r
199         }\r
200 \r
201         while (st.hasMoreElements())\r
202         {\r
203           desc = st.nextToken();\r
204           token = st.nextToken();\r
205           if (!token.equals("ID_NOT_SPECIFIED"))\r
206           {\r
207             index = viewport.alignment.findIndex(viewport.alignment.findName(\r
208                 token));\r
209             st.nextToken();\r
210           }\r
211           else\r
212           {\r
213             index = Integer.parseInt(st.nextToken());\r
214           }\r
215 \r
216           start = Integer.parseInt(st.nextToken());\r
217           end = Integer.parseInt(st.nextToken());\r
218 \r
219           seq = viewport.alignment.getSequenceAt(index);\r
220           start = seq.findIndex(start) - 1;\r
221           end = seq.findIndex(end) - 1;\r
222 \r
223           type = st.nextToken();\r
224 \r
225           if (fr.getColour(type) == null)\r
226           {\r
227             // Probably the old style groups file\r
228             UserColourScheme ucs = new UserColourScheme(type);\r
229             fr.setColour(type, ucs.findColour("A"));\r
230           }\r
231 \r
232 \r
233           sf = new SequenceFeature(type, desc, "", start, end);\r
234 \r
235           seq.addSequenceFeature(sf);\r
236 \r
237 \r
238          // sg = new SequenceGroup(text, ucs, true, true, false, start, end);\r
239          // sg.addSequence(seq, false);\r
240 \r
241          // viewport.alignment.addGroup(sg);\r
242 \r
243         }\r
244       }\r
245 \r
246       viewport.showSequenceFeatures = true;\r
247       ((Alignment)viewport.alignment).featuresAdded = true;\r
248 \r
249       alignPanel.repaint();\r
250 \r
251     }\r
252     catch (Exception ex)\r
253     {\r
254       System.out.println("Error parsing groups file: " + ex);\r
255     }\r
256   }\r
257 \r
258   /**\r
259    * DOCUMENT ME!\r
260    *\r
261    * @param e DOCUMENT ME!\r
262    */\r
263   public void saveAlignmentMenu_actionPerformed(ActionEvent e)\r
264   {\r
265     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
266         getProperty(\r
267             "LAST_DIRECTORY"),\r
268         new String[]\r
269         {\r
270         "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc",\r
271         "jar"\r
272     },\r
273         new String[]\r
274         {\r
275         "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"\r
276     }, currentFileFormat);\r
277 \r
278     chooser.setAcceptAllFileFilterUsed(false);\r
279     chooser.setFileView(new JalviewFileView());\r
280     chooser.setDialogTitle("Save Alignment to file");\r
281     chooser.setToolTipText("Save");\r
282 \r
283     int value = chooser.showSaveDialog(this);\r
284 \r
285     if (value == JalviewFileChooser.APPROVE_OPTION)\r
286     {\r
287         currentFileFormat = chooser.getSelectedFormat();\r
288 \r
289         if (currentFileFormat == null)\r
290         {\r
291           JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
292                                                 "You must select a file format before saving!",\r
293                                                 "File format not specified",\r
294                                                 JOptionPane.WARNING_MESSAGE);\r
295           value = chooser.showSaveDialog(this);\r
296           return;\r
297         }\r
298 \r
299       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",\r
300                                     currentFileFormat);\r
301 \r
302       String choice = chooser.getSelectedFile().getPath();\r
303       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
304 \r
305       saveAlignment(choice, currentFileFormat);\r
306     }\r
307   }\r
308 \r
309   public boolean saveAlignment(String file, String format)\r
310   {\r
311     if (format.equalsIgnoreCase("Jalview"))\r
312     {\r
313       String shortName = title;\r
314 \r
315       if (shortName.indexOf(java.io.File.separatorChar) > -1)\r
316       {\r
317         shortName = shortName.substring(shortName.lastIndexOf(\r
318             java.io.File.separatorChar) + 1);\r
319       }\r
320 \r
321       Jalview2XML.SaveAlignment(this, file, shortName);\r
322 \r
323       // USE Jalview2XML to save this file\r
324       return true;\r
325     }\r
326     else\r
327     {\r
328       String output = new FormatAdapter().formatSequences(format,\r
329           viewport.getAlignment().\r
330           getSequences());\r
331       if (output == null)\r
332       {\r
333         return false;\r
334       }\r
335 \r
336       try\r
337       {\r
338         java.io.PrintWriter out = new java.io.PrintWriter(\r
339             new java.io.FileWriter(file));\r
340 \r
341         out.print(output);\r
342         out.close();\r
343         return true;\r
344       }\r
345       catch (Exception ex)\r
346       {\r
347         ex.printStackTrace();\r
348       }\r
349     }\r
350     return false;\r
351   }\r
352 \r
353   /**\r
354    * DOCUMENT ME!\r
355    *\r
356    * @param e DOCUMENT ME!\r
357    */\r
358   protected void outputText_actionPerformed(ActionEvent e)\r
359   {\r
360     CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
361     Desktop.addInternalFrame(cap,\r
362                              "Alignment output - " + e.getActionCommand(), 600,\r
363                              500);\r
364     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),\r
365                                               viewport.getAlignment().\r
366                                               getSequences()));\r
367   }\r
368 \r
369   /**\r
370    * DOCUMENT ME!\r
371    *\r
372    * @param e DOCUMENT ME!\r
373    */\r
374   protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
375   {\r
376     new HTMLOutput(viewport);\r
377   }\r
378 \r
379   public void createImageMap(File file, String image)\r
380   {\r
381     alignPanel.makePNGImageMap(file, image);\r
382   }\r
383 \r
384   /**\r
385    * DOCUMENT ME!\r
386    *\r
387    * @param e DOCUMENT ME!\r
388    */\r
389   public void createPNG(File f)\r
390   {\r
391     alignPanel.makePNG(f);\r
392   }\r
393 \r
394   /**\r
395    * DOCUMENT ME!\r
396    *\r
397    * @param e DOCUMENT ME!\r
398    */\r
399   public void createEPS(File f)\r
400   {\r
401     alignPanel.makeEPS(f);\r
402   }\r
403 \r
404   /**\r
405    * DOCUMENT ME!\r
406    *\r
407    * @param e DOCUMENT ME!\r
408    */\r
409   public void printMenuItem_actionPerformed(ActionEvent e)\r
410   {\r
411     //Putting in a thread avoids Swing painting problems\r
412     PrintThread thread = new PrintThread();\r
413     thread.start();\r
414   }\r
415 \r
416   /**\r
417    * DOCUMENT ME!\r
418    *\r
419    * @param e DOCUMENT ME!\r
420    */\r
421   public void closeMenuItem_actionPerformed(ActionEvent e)\r
422   {\r
423     try\r
424     {\r
425       PaintRefresher.components.remove(viewport.alignment);\r
426       this.setClosed(true);\r
427     }\r
428     catch (Exception ex)\r
429     {\r
430     }\r
431   }\r
432 \r
433   /**\r
434    * DOCUMENT ME!\r
435    */\r
436   void updateEditMenuBar()\r
437   {\r
438     if (historyList.size() > 0)\r
439     {\r
440       undoMenuItem.setEnabled(true);\r
441 \r
442       HistoryItem hi = (HistoryItem) historyList.peek();\r
443       undoMenuItem.setText("Undo " + hi.getDescription());\r
444     }\r
445     else\r
446     {\r
447       undoMenuItem.setEnabled(false);\r
448       undoMenuItem.setText("Undo");\r
449     }\r
450 \r
451     if (redoList.size() > 0)\r
452     {\r
453       redoMenuItem.setEnabled(true);\r
454 \r
455       HistoryItem hi = (HistoryItem) redoList.peek();\r
456       redoMenuItem.setText("Redo " + hi.getDescription());\r
457     }\r
458     else\r
459     {\r
460       redoMenuItem.setEnabled(false);\r
461       redoMenuItem.setText("Redo");\r
462     }\r
463   }\r
464 \r
465   /**\r
466    * DOCUMENT ME!\r
467    *\r
468    * @param hi DOCUMENT ME!\r
469    */\r
470   public void addHistoryItem(HistoryItem hi)\r
471   {\r
472     historyList.push(hi);\r
473     updateEditMenuBar();\r
474   }\r
475 \r
476   /**\r
477    * DOCUMENT ME!\r
478    *\r
479    * @param e DOCUMENT ME!\r
480    */\r
481   protected void undoMenuItem_actionPerformed(ActionEvent e)\r
482   {\r
483     HistoryItem hi = (HistoryItem) historyList.pop();\r
484     redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment,\r
485                                   HistoryItem.HIDE));\r
486     restoreHistoryItem(hi);\r
487     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
488   }\r
489 \r
490   /**\r
491    * DOCUMENT ME!\r
492    *\r
493    * @param e DOCUMENT ME!\r
494    */\r
495   protected void redoMenuItem_actionPerformed(ActionEvent e)\r
496   {\r
497     HistoryItem hi = (HistoryItem) redoList.pop();\r
498     restoreHistoryItem(hi);\r
499     updateEditMenuBar();\r
500     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
501   }\r
502 \r
503   // used by undo and redo\r
504   void restoreHistoryItem(HistoryItem hi)\r
505   {\r
506     if (hi.getType() == HistoryItem.SORT)\r
507     {\r
508       for (int i = 0; i < hi.getSequences().size(); i++)\r
509       {\r
510         viewport.alignment.getSequences().setElementAt(hi.getSequences()\r
511             .elementAt(i),\r
512             i);\r
513       }\r
514     }\r
515     else\r
516     {\r
517       for (int i = 0; i < hi.getSequences().size(); i++)\r
518       {\r
519         SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);\r
520 \r
521         if (restore.getLength() == 0)\r
522         {\r
523           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
524           viewport.alignment.getSequences().insertElementAt(restore,\r
525               hi.getAlignIndex(i));\r
526         }\r
527         else\r
528         {\r
529           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
530         }\r
531       }\r
532 \r
533       if (hi.getType() == HistoryItem.PASTE)\r
534       {\r
535         for (int i = viewport.alignment.getHeight() - 1;\r
536              i > (hi.getSequences().size() - 1); i--)\r
537         {\r
538           viewport.alignment.deleteSequence(i);\r
539         }\r
540       }\r
541     }\r
542 \r
543     updateEditMenuBar();\r
544 \r
545     viewport.firePropertyChange("alignment", null,\r
546                                 viewport.getAlignment().getSequences());\r
547   }\r
548 \r
549   /**\r
550    * DOCUMENT ME!\r
551    *\r
552    * @param up DOCUMENT ME!\r
553    */\r
554   public void moveSelectedSequences(boolean up)\r
555   {\r
556     SequenceGroup sg = viewport.getSelectionGroup();\r
557 \r
558     if (sg == null)\r
559     {\r
560       return;\r
561     }\r
562 \r
563     if (up)\r
564     {\r
565       for (int i = 1; i < viewport.alignment.getHeight(); i++)\r
566       {\r
567         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
568 \r
569         if (!sg.sequences.contains(seq))\r
570         {\r
571           continue;\r
572         }\r
573 \r
574         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);\r
575 \r
576         if (sg.sequences.contains(temp))\r
577         {\r
578           continue;\r
579         }\r
580 \r
581         viewport.alignment.getSequences().setElementAt(temp, i);\r
582         viewport.alignment.getSequences().setElementAt(seq, i - 1);\r
583       }\r
584     }\r
585     else\r
586     {\r
587       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)\r
588       {\r
589         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
590 \r
591         if (!sg.sequences.contains(seq))\r
592         {\r
593           continue;\r
594         }\r
595 \r
596         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);\r
597 \r
598         if (sg.sequences.contains(temp))\r
599         {\r
600           continue;\r
601         }\r
602 \r
603         viewport.alignment.getSequences().setElementAt(temp, i);\r
604         viewport.alignment.getSequences().setElementAt(seq, i + 1);\r
605       }\r
606     }\r
607 \r
608     alignPanel.repaint();\r
609   }\r
610 \r
611   public void lostOwnership(Clipboard clipboard, Transferable contents)\r
612   {\r
613     Desktop.jalviewClipboard = null;\r
614   }\r
615 \r
616 \r
617   /**\r
618    * DOCUMENT ME!\r
619    *\r
620    * @param e DOCUMENT ME!\r
621    */\r
622   protected void copy_actionPerformed(ActionEvent e)\r
623   {\r
624     if (viewport.getSelectionGroup() == null)\r
625     {\r
626       return;\r
627     }\r
628 \r
629     SequenceGroup sg = viewport.getSelectionGroup();\r
630 \r
631     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
632 \r
633     Hashtable orderedSeqs = new Hashtable();\r
634     SequenceI[] seqs = new SequenceI[sg.getSize()];\r
635 \r
636     for (int i = 0; i < sg.getSize(); i++)\r
637     {\r
638       SequenceI seq = sg.getSequenceAt(i);\r
639       int index = viewport.alignment.findIndex(seq);\r
640       orderedSeqs.put(index + "", seq);\r
641     }\r
642 \r
643     int index = 0, startRes, endRes;\r
644     char ch;\r
645 \r
646     for (int i = 0; i < sg.getSize(); i++)\r
647     {\r
648       SequenceI seq = null;\r
649 \r
650       while (seq == null)\r
651       {\r
652         if (orderedSeqs.containsKey(index + ""))\r
653         {\r
654           seq = (SequenceI) orderedSeqs.get(index + "");\r
655           index++;\r
656 \r
657           break;\r
658         }\r
659         else\r
660         {\r
661           index++;\r
662         }\r
663       }\r
664 \r
665       //FIND START RES\r
666       //Returns residue following index if gap\r
667       startRes = seq.findPosition(sg.getStartRes());\r
668 \r
669       //FIND END RES\r
670       //Need to find the residue preceeding index if gap\r
671       endRes = 0;\r
672 \r
673       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)\r
674       {\r
675         ch = seq.getCharAt(j);\r
676         if (!jalview.util.Comparison.isGap( (ch)))\r
677         {\r
678           endRes++;\r
679         }\r
680       }\r
681 \r
682       if (endRes > 0)\r
683       {\r
684         endRes += seq.getStart() - 1;\r
685       }\r
686 \r
687       seqs[i] = new Sequence(seq.getName(),\r
688                              seq.getSequence(sg.getStartRes(), sg.getEndRes() + 1),\r
689                              startRes,\r
690                              endRes);\r
691       seqs[i].setDescription(seq.getDescription());\r
692       seqs[i].setDBRef(seq.getDBRef());\r
693       seqs[i].setSequenceFeatures(seq.getSequenceFeatures());\r
694       seqs[i].setDatasetSequence(seq.getDatasetSequence());\r
695 \r
696     }\r
697 \r
698     FastaFile ff = new FastaFile();\r
699     ff.addDBPrefix( viewport.showDBPrefix );\r
700     ff.addJVSuffix( viewport.showJVSuffix );\r
701     c.setContents(new StringSelection( ff.print(seqs)), this);\r
702     Desktop.jalviewClipboard = new Object[]{seqs,  viewport.alignment.getDataset()};\r
703   }\r
704 \r
705   /**\r
706    * DOCUMENT ME!\r
707    *\r
708    * @param e DOCUMENT ME!\r
709    */\r
710   protected void pasteNew_actionPerformed(ActionEvent e)\r
711   {\r
712     paste(true);\r
713   }\r
714 \r
715   /**\r
716    * DOCUMENT ME!\r
717    *\r
718    * @param e DOCUMENT ME!\r
719    */\r
720   protected void pasteThis_actionPerformed(ActionEvent e)\r
721   {\r
722     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment,\r
723                                    HistoryItem.PASTE));\r
724     paste(false);\r
725   }\r
726 \r
727   /**\r
728    * DOCUMENT ME!\r
729    *\r
730    * @param newAlignment DOCUMENT ME!\r
731    */\r
732   void paste(boolean newAlignment)\r
733   {\r
734     try\r
735     {\r
736       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
737       Transferable contents = c.getContents(this);\r
738 \r
739       if (contents == null)\r
740       {\r
741         return;\r
742       }\r
743 \r
744       String str = (String) contents.getTransferData(DataFlavor.stringFlavor);\r
745       if(str.length()<1)\r
746         return;\r
747 \r
748       String format = IdentifyFile.Identify(str, "Paste");\r
749       SequenceI[] sequences;\r
750 \r
751      if(Desktop.jalviewClipboard!=null)\r
752      {\r
753        // The clipboard was filled from within Jalview, we must use the sequences\r
754        // And dataset from the copied alignment\r
755        sequences = (SequenceI[])Desktop.jalviewClipboard[0];\r
756      }\r
757      else\r
758      {\r
759        sequences = new FormatAdapter().readFile(str, "Paste", format);\r
760      }\r
761 \r
762       if (newAlignment)\r
763       {\r
764 \r
765         Alignment alignment = new Alignment(sequences);\r
766 \r
767         if(Desktop.jalviewClipboard!=null)\r
768            alignment.setDataset( (Alignment)Desktop.jalviewClipboard[1] );\r
769         else\r
770            alignment.setDataset( null );\r
771 \r
772 \r
773         AlignFrame af = new AlignFrame(alignment);\r
774         String newtitle = new String("Copied sequences");\r
775 \r
776         if (title.startsWith("Copied sequences"))\r
777         {\r
778           newtitle = title;\r
779         }\r
780         else\r
781         {\r
782           newtitle = newtitle.concat("- from " + title);\r
783         }\r
784 \r
785         Desktop.addInternalFrame(af, newtitle, NEW_WINDOW_WIDTH,\r
786                                  NEW_WINDOW_HEIGHT);\r
787       }\r
788       else\r
789       {\r
790         //!newAlignment\r
791         for (int i = 0; i < sequences.length; i++)\r
792         {\r
793           viewport.alignment.addSequence(sequences[i]);\r
794           if(sequences[i].getDatasetSequence()==null)\r
795           {\r
796              ////////////////////////////\r
797             //Datset needs extension;\r
798             /////////////////////////////\r
799             Sequence ds = new Sequence(sequences[i].getName(),\r
800                                        AlignSeq.extractGaps("-. ", sequences[i].getSequence()),\r
801                                        sequences[i].getStart(),\r
802                                        sequences[i].getEnd());\r
803             sequences[i].setDatasetSequence(ds);\r
804             viewport.alignment.getDataset().addSequence(ds);\r
805 \r
806 \r
807           }\r
808 \r
809         }\r
810         viewport.setEndSeq(viewport.alignment.getHeight());\r
811         viewport.alignment.getWidth();\r
812         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
813       }\r
814     }\r
815     catch (Exception ex)\r
816     {\r
817         // could be anything being pasted in here\r
818     }\r
819 \r
820 \r
821   }\r
822 \r
823   /**\r
824    * DOCUMENT ME!\r
825    *\r
826    * @param e DOCUMENT ME!\r
827    */\r
828   protected void cut_actionPerformed(ActionEvent e)\r
829   {\r
830     copy_actionPerformed(null);\r
831     delete_actionPerformed(null);\r
832   }\r
833 \r
834   /**\r
835    * DOCUMENT ME!\r
836    *\r
837    * @param e DOCUMENT ME!\r
838    */\r
839   protected void delete_actionPerformed(ActionEvent e)\r
840   {\r
841 \r
842     if (viewport.getSelectionGroup() == null)\r
843     {\r
844       return;\r
845     }\r
846 \r
847     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment,\r
848                                    HistoryItem.HIDE));\r
849 \r
850     SequenceGroup sg = viewport.getSelectionGroup();\r
851     boolean allSequences = false;\r
852     if (sg.sequences.size() == viewport.alignment.getHeight())\r
853     {\r
854       allSequences = true;\r
855     }\r
856 \r
857     for (int i = 0; i < sg.sequences.size(); i++)\r
858     {\r
859       SequenceI seq = sg.getSequenceAt(i);\r
860       int index = viewport.getAlignment().findIndex(seq);\r
861       seq.deleteChars(sg.getStartRes(), sg.getEndRes() + 1);\r
862 \r
863       // If the cut affects all sequences, remove highlighted columns\r
864       if (allSequences)\r
865       {\r
866         viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
867             sg.getEndRes() + 1);\r
868       }\r
869 \r
870       if (seq.getSequence().length() < 1)\r
871       {\r
872         viewport.getAlignment().deleteSequence(seq);\r
873       }\r
874       else\r
875       {\r
876         viewport.getAlignment().getSequences().setElementAt(seq, index);\r
877       }\r
878     }\r
879 \r
880     viewport.setSelectionGroup(null);\r
881     viewport.alignment.deleteGroup(sg);\r
882 \r
883     viewport.firePropertyChange("alignment", null,\r
884                                   viewport.getAlignment().getSequences());\r
885 \r
886 \r
887 \r
888     if (viewport.getAlignment().getHeight() < 1)\r
889     {\r
890       try\r
891       {\r
892         this.setClosed(true);\r
893       }\r
894       catch (Exception ex)\r
895       {\r
896       }\r
897     }\r
898   }\r
899 \r
900   /**\r
901    * DOCUMENT ME!\r
902    *\r
903    * @param e DOCUMENT ME!\r
904    */\r
905   protected void deleteGroups_actionPerformed(ActionEvent e)\r
906   {\r
907     viewport.alignment.deleteAllGroups();\r
908     viewport.setSelectionGroup(null);\r
909     alignPanel.repaint();\r
910   }\r
911 \r
912   /**\r
913    * DOCUMENT ME!\r
914    *\r
915    * @param e DOCUMENT ME!\r
916    */\r
917   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
918   {\r
919     SequenceGroup sg = new SequenceGroup();\r
920 \r
921     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
922          i++)\r
923     {\r
924       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
925     }\r
926 \r
927     sg.setEndRes(viewport.alignment.getWidth() - 1);\r
928     viewport.setSelectionGroup(sg);\r
929     PaintRefresher.Refresh(null, viewport.alignment);\r
930   }\r
931 \r
932   /**\r
933    * DOCUMENT ME!\r
934    *\r
935    * @param e DOCUMENT ME!\r
936    */\r
937   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
938   {\r
939     viewport.setSelectionGroup(null);\r
940     viewport.getColumnSelection().clear();\r
941     viewport.setSelectionGroup(null);\r
942     alignPanel.annotationPanel.activeRes = null;\r
943     PaintRefresher.Refresh(null, viewport.alignment);\r
944   }\r
945 \r
946   /**\r
947    * DOCUMENT ME!\r
948    *\r
949    * @param e DOCUMENT ME!\r
950    */\r
951   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
952   {\r
953     SequenceGroup sg = viewport.getSelectionGroup();\r
954 \r
955     if (sg == null)\r
956     {\r
957       selectAllSequenceMenuItem_actionPerformed(null);\r
958 \r
959       return;\r
960     }\r
961 \r
962     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
963          i++)\r
964     {\r
965       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
966     }\r
967 \r
968     PaintRefresher.Refresh(null, viewport.alignment);\r
969   }\r
970 \r
971   /**\r
972    * DOCUMENT ME!\r
973    *\r
974    * @param e DOCUMENT ME!\r
975    */\r
976   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
977   {\r
978     ColumnSelection colSel = viewport.getColumnSelection();\r
979 \r
980     if (colSel.size() > 0)\r
981     {\r
982       addHistoryItem(new HistoryItem("Remove Left", viewport.alignment,\r
983                                      HistoryItem.HIDE));\r
984 \r
985       int min = colSel.getMin();\r
986       viewport.getAlignment().trimLeft(min);\r
987       colSel.compensateForEdit(0, min);\r
988 \r
989       if (viewport.getSelectionGroup() != null)\r
990       {\r
991         viewport.getSelectionGroup().adjustForRemoveLeft(min);\r
992       }\r
993 \r
994       Vector groups = viewport.alignment.getGroups();\r
995 \r
996       for (int i = 0; i < groups.size(); i++)\r
997       {\r
998         SequenceGroup sg = (SequenceGroup) groups.get(i);\r
999 \r
1000         if (!sg.adjustForRemoveLeft(min))\r
1001         {\r
1002           viewport.alignment.deleteGroup(sg);\r
1003         }\r
1004       }\r
1005 \r
1006       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1007     }\r
1008   }\r
1009 \r
1010   /**\r
1011    * DOCUMENT ME!\r
1012    *\r
1013    * @param e DOCUMENT ME!\r
1014    */\r
1015   public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
1016   {\r
1017     ColumnSelection colSel = viewport.getColumnSelection();\r
1018 \r
1019     if (colSel.size() > 0)\r
1020     {\r
1021       addHistoryItem(new HistoryItem("Remove Right", viewport.alignment,\r
1022                                      HistoryItem.HIDE));\r
1023 \r
1024       int max = colSel.getMax();\r
1025       viewport.getAlignment().trimRight(max);\r
1026 \r
1027       if (viewport.getSelectionGroup() != null)\r
1028       {\r
1029         viewport.getSelectionGroup().adjustForRemoveRight(max);\r
1030       }\r
1031 \r
1032       Vector groups = viewport.alignment.getGroups();\r
1033 \r
1034       for (int i = 0; i < groups.size(); i++)\r
1035       {\r
1036         SequenceGroup sg = (SequenceGroup) groups.get(i);\r
1037 \r
1038         if (!sg.adjustForRemoveRight(max))\r
1039         {\r
1040           viewport.alignment.deleteGroup(sg);\r
1041         }\r
1042       }\r
1043 \r
1044       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1045     }\r
1046   }\r
1047 \r
1048   /**\r
1049    * DOCUMENT ME!\r
1050    *\r
1051    * @param e DOCUMENT ME!\r
1052    */\r
1053   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
1054   {\r
1055     addHistoryItem(new HistoryItem("Remove Gapped Columns",\r
1056                                    viewport.alignment, HistoryItem.HIDE));\r
1057 \r
1058     //This is to maintain viewport position on first residue\r
1059     //of first sequence\r
1060     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
1061     int startRes = seq.findPosition(viewport.startRes);\r
1062 \r
1063     viewport.getAlignment().removeGaps();\r
1064 \r
1065     viewport.setStartRes(seq.findIndex(startRes)-1);\r
1066 \r
1067    viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1068   }\r
1069 \r
1070   /**\r
1071    * DOCUMENT ME!\r
1072    *\r
1073    * @param e DOCUMENT ME!\r
1074    */\r
1075   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
1076   {\r
1077     addHistoryItem(new HistoryItem("Remove Gaps", viewport.alignment,\r
1078                                    HistoryItem.HIDE));\r
1079 \r
1080     //This is to maintain viewport position on first residue\r
1081     //of first sequence\r
1082     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
1083     int startRes = seq.findPosition(viewport.startRes);\r
1084 \r
1085 \r
1086     SequenceI current;\r
1087     int jSize;\r
1088 \r
1089     Vector seqs = null;\r
1090 \r
1091     int start = 0;\r
1092     int end = viewport.alignment.getWidth();\r
1093 \r
1094     if (viewport.getSelectionGroup() != null\r
1095         && viewport.getSelectionGroup().sequences != null\r
1096         && viewport.getSelectionGroup().sequences.size() > 0)\r
1097     {\r
1098       seqs = viewport.getSelectionGroup().sequences;\r
1099       start = viewport.getSelectionGroup().getStartRes();\r
1100       end = viewport.getSelectionGroup().getEndRes()+1;\r
1101     }\r
1102     else\r
1103     {\r
1104       seqs = viewport.alignment.getSequences();\r
1105     }\r
1106 \r
1107     for (int i = 0; i < seqs.size(); i++)\r
1108     {\r
1109       current = (SequenceI) seqs.elementAt(i);\r
1110       jSize = current.getLength();\r
1111 \r
1112       // Removing a range is much quicker than removing gaps\r
1113       // one by one for long sequences\r
1114       int j = start;\r
1115       int rangeStart=-1, rangeEnd=-1;\r
1116 \r
1117       do\r
1118       {\r
1119         if (jalview.util.Comparison.isGap(current.getCharAt(j)))\r
1120         {\r
1121           if(rangeStart==-1)\r
1122            {\r
1123              rangeStart = j;\r
1124              rangeEnd = j+1;\r
1125            }\r
1126            else\r
1127            {\r
1128              rangeEnd++;\r
1129            }\r
1130            j++;\r
1131         }\r
1132         else\r
1133         {\r
1134           if(rangeStart>-1)\r
1135           {\r
1136             current.deleteChars(rangeStart, rangeEnd);\r
1137             j-=rangeEnd-rangeStart;\r
1138             jSize-=rangeEnd-rangeStart;\r
1139             rangeStart = -1;\r
1140             rangeEnd = -1;\r
1141           }\r
1142           else\r
1143             j++;\r
1144         }\r
1145       }\r
1146       while (j < end && j < jSize);\r
1147       if(rangeStart>-1)\r
1148       {\r
1149        current.deleteChars(rangeStart, rangeEnd);\r
1150       }\r
1151     }\r
1152 \r
1153     viewport.setStartRes(seq.findIndex(startRes)-1);\r
1154 \r
1155     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1156   }\r
1157 \r
1158  public void alignmentChanged()\r
1159  {\r
1160    if(viewport.vconsensus!=null)\r
1161    {\r
1162      viewport.updateConsensus();\r
1163      viewport.updateConservation();\r
1164    }\r
1165    resetAllColourSchemes();\r
1166    if(alignPanel.overviewPanel!=null)\r
1167      alignPanel.overviewPanel.updateOverviewImage();\r
1168 \r
1169   Provenance prov = viewport.alignment.getProvenance();\r
1170   if(prov == null)\r
1171    {\r
1172      prov = new Provenance();\r
1173      viewport.alignment.setProvenance(prov);\r
1174    }\r
1175 \r
1176    prov.addEntry("Me",\r
1177        "Edited in Jalview", new java.util.Date(), "myID");\r
1178 \r
1179    alignPanel.repaint();\r
1180  }\r
1181 \r
1182   void resetAllColourSchemes()\r
1183   {\r
1184     ColourSchemeI cs = viewport.globalColourScheme;\r
1185     if(cs!=null)\r
1186     {\r
1187       if (cs instanceof ClustalxColourScheme)\r
1188       {\r
1189         ( (ClustalxColourScheme) viewport.getGlobalColourScheme()).\r
1190             resetClustalX(viewport.alignment.getSequences(),\r
1191                           viewport.alignment.getWidth());\r
1192       }\r
1193 \r
1194       cs.setConsensus(viewport.vconsensus);\r
1195       if (cs.conservationApplied())\r
1196       {\r
1197         Alignment al = (Alignment) viewport.alignment;\r
1198         Conservation c = new Conservation("All",\r
1199                                           ResidueProperties.propHash, 3,\r
1200                                           al.getSequences(), 0,\r
1201                                           al.getWidth() - 1);\r
1202         c.calculate();\r
1203         c.verdict(false, viewport.ConsPercGaps);\r
1204 \r
1205         cs.setConservation(c);\r
1206       }\r
1207     }\r
1208 \r
1209     int s, sSize = viewport.alignment.getGroups().size();\r
1210     for(s=0; s<sSize; s++)\r
1211     {\r
1212       SequenceGroup sg = (SequenceGroup)viewport.alignment.getGroups().elementAt(s);\r
1213       if(sg.cs!=null && sg.cs instanceof ClustalxColourScheme)\r
1214       {\r
1215         ((ClustalxColourScheme)sg.cs).resetClustalX(sg.sequences, sg.getWidth());\r
1216       }\r
1217       sg.recalcConservation();\r
1218     }\r
1219   }\r
1220 \r
1221   /**\r
1222    * DOCUMENT ME!\r
1223    *\r
1224    * @param e DOCUMENT ME!\r
1225    */\r
1226   public void padGapsMenuitem_actionPerformed(ActionEvent e)\r
1227   {\r
1228     addHistoryItem(new HistoryItem("Pad Gaps", viewport.alignment,\r
1229                                    HistoryItem.HIDE));\r
1230 \r
1231     SequenceI current;\r
1232     int Width = viewport.getAlignment().getWidth();\r
1233 \r
1234     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1235          i++)\r
1236     {\r
1237       current = viewport.getAlignment().getSequenceAt(i);\r
1238 \r
1239       if (current.getLength() < Width)\r
1240       {\r
1241         current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1242       }\r
1243     }\r
1244 \r
1245     alignmentChanged();\r
1246   }\r
1247 \r
1248   /**\r
1249    * DOCUMENT ME!\r
1250    *\r
1251    * @param e DOCUMENT ME!\r
1252    */\r
1253   public void findMenuItem_actionPerformed(ActionEvent e)\r
1254   {\r
1255     JInternalFrame frame = new JInternalFrame();\r
1256     Finder finder = new Finder(viewport, alignPanel, frame);\r
1257     frame.setContentPane(finder);\r
1258     Desktop.addInternalFrame(frame, "Find", 340, 110);\r
1259     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
1260   }\r
1261 \r
1262   /**\r
1263    * DOCUMENT ME!\r
1264    *\r
1265    * @param e DOCUMENT ME!\r
1266    */\r
1267   public void font_actionPerformed(ActionEvent e)\r
1268   {\r
1269     new FontChooser(alignPanel);\r
1270   }\r
1271 \r
1272   /**\r
1273    * DOCUMENT ME!\r
1274    *\r
1275    * @param e DOCUMENT ME!\r
1276    */\r
1277   protected void seqLimit_actionPerformed(ActionEvent e)\r
1278   {\r
1279     viewport.setShowJVSuffix(seqLimits.isSelected());\r
1280 \r
1281     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());\r
1282     alignPanel.repaint();\r
1283   }\r
1284 \r
1285   public void seqDBRef_actionPerformed(ActionEvent e)\r
1286   {\r
1287     viewport.setShowDBPrefix(seqDBRef.isSelected());\r
1288 \r
1289     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());\r
1290     alignPanel.repaint();\r
1291   }\r
1292 \r
1293 \r
1294   /**\r
1295    * DOCUMENT ME!\r
1296    *\r
1297    * @param e DOCUMENT ME!\r
1298    */\r
1299   protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
1300   {\r
1301     viewport.setColourText(colourTextMenuItem.isSelected());\r
1302     alignPanel.repaint();\r
1303   }\r
1304 \r
1305   /**\r
1306    * DOCUMENT ME!\r
1307    *\r
1308    * @param e DOCUMENT ME!\r
1309    */\r
1310   protected void wrapMenuItem_actionPerformed(ActionEvent e)\r
1311   {\r
1312     viewport.setWrapAlignment(wrapMenuItem.isSelected());\r
1313     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());\r
1314     scaleAbove.setVisible(wrapMenuItem.isSelected());\r
1315     scaleLeft.setVisible(wrapMenuItem.isSelected());\r
1316     scaleRight.setVisible(wrapMenuItem.isSelected());\r
1317     alignPanel.repaint();\r
1318   }\r
1319 \r
1320   /**\r
1321    * DOCUMENT ME!\r
1322    *\r
1323    * @param e DOCUMENT ME!\r
1324    */\r
1325   protected void scaleAbove_actionPerformed(ActionEvent e)\r
1326   {\r
1327     viewport.setScaleAboveWrapped(scaleAbove.isSelected());\r
1328     alignPanel.repaint();\r
1329   }\r
1330 \r
1331   /**\r
1332    * DOCUMENT ME!\r
1333    *\r
1334    * @param e DOCUMENT ME!\r
1335    */\r
1336   protected void scaleLeft_actionPerformed(ActionEvent e)\r
1337   {\r
1338     viewport.setScaleLeftWrapped(scaleLeft.isSelected());\r
1339     alignPanel.repaint();\r
1340   }\r
1341 \r
1342   /**\r
1343    * DOCUMENT ME!\r
1344    *\r
1345    * @param e DOCUMENT ME!\r
1346    */\r
1347   protected void scaleRight_actionPerformed(ActionEvent e)\r
1348   {\r
1349     viewport.setScaleRightWrapped(scaleRight.isSelected());\r
1350     alignPanel.repaint();\r
1351   }\r
1352 \r
1353   /**\r
1354    * DOCUMENT ME!\r
1355    *\r
1356    * @param e DOCUMENT ME!\r
1357    */\r
1358   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
1359   {\r
1360     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());\r
1361     alignPanel.repaint();\r
1362   }\r
1363 \r
1364   /**\r
1365    * DOCUMENT ME!\r
1366    *\r
1367    * @param e DOCUMENT ME!\r
1368    */\r
1369   public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
1370   {\r
1371     viewport.setShowText(viewTextMenuItem.isSelected());\r
1372     alignPanel.repaint();\r
1373   }\r
1374 \r
1375   /**\r
1376    * DOCUMENT ME!\r
1377    *\r
1378    * @param e DOCUMENT ME!\r
1379    */\r
1380   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)\r
1381   {\r
1382     viewport.setRenderGaps(renderGapsMenuItem.isSelected());\r
1383     alignPanel.repaint();\r
1384   }\r
1385 \r
1386   /**\r
1387    * DOCUMENT ME!\r
1388    *\r
1389    * @param evt DOCUMENT ME!\r
1390    */\r
1391   public void sequenceFeatures_actionPerformed(ActionEvent evt)\r
1392   {\r
1393     viewport.showSequenceFeatures(sequenceFeatures.isSelected());\r
1394 \r
1395     if (viewport.showSequenceFeatures &&\r
1396         ! ( (Alignment) viewport.alignment.getDataset()).featuresAdded)\r
1397     {\r
1398       System.out.println("new fetcher");\r
1399       new SequenceFeatureFetcher(viewport.\r
1400          alignment,\r
1401           alignPanel);\r
1402     }\r
1403 \r
1404     featureSettings.setEnabled(true);\r
1405 \r
1406     alignPanel.repaint();\r
1407   }\r
1408 \r
1409   /**\r
1410    * DOCUMENT ME!\r
1411    *\r
1412    * @param e DOCUMENT ME!\r
1413    */\r
1414   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)\r
1415   {\r
1416     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());\r
1417     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());\r
1418   }\r
1419 \r
1420   /**\r
1421    * DOCUMENT ME!\r
1422    *\r
1423    * @param e DOCUMENT ME!\r
1424    */\r
1425   public void overviewMenuItem_actionPerformed(ActionEvent e)\r
1426   {\r
1427     if (alignPanel.overviewPanel != null)\r
1428     {\r
1429       return;\r
1430     }\r
1431 \r
1432     JInternalFrame frame = new JInternalFrame();\r
1433     OverviewPanel overview = new OverviewPanel(alignPanel);\r
1434     frame.setContentPane(overview);\r
1435     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),\r
1436                              frame.getWidth(), frame.getHeight());\r
1437     frame.pack();\r
1438     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
1439     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
1440     {\r
1441       public void internalFrameClosed(\r
1442           javax.swing.event.InternalFrameEvent evt)\r
1443       {\r
1444         alignPanel.setOverviewPanel(null);\r
1445       }\r
1446       ;\r
1447     });\r
1448 \r
1449     alignPanel.setOverviewPanel(overview);\r
1450   }\r
1451 \r
1452   /**\r
1453    * DOCUMENT ME!\r
1454    *\r
1455    * @param e DOCUMENT ME!\r
1456    */\r
1457   protected void noColourmenuItem_actionPerformed(ActionEvent e)\r
1458   {\r
1459     changeColour(null);\r
1460   }\r
1461 \r
1462   /**\r
1463    * DOCUMENT ME!\r
1464    *\r
1465    * @param e DOCUMENT ME!\r
1466    */\r
1467   public void clustalColour_actionPerformed(ActionEvent e)\r
1468   {\r
1469     changeColour(new ClustalxColourScheme(\r
1470         viewport.alignment.getSequences(), viewport.alignment.getWidth()));\r
1471   }\r
1472 \r
1473   /**\r
1474    * DOCUMENT ME!\r
1475    *\r
1476    * @param e DOCUMENT ME!\r
1477    */\r
1478   public void zappoColour_actionPerformed(ActionEvent e)\r
1479   {\r
1480     changeColour(new ZappoColourScheme());\r
1481   }\r
1482 \r
1483   /**\r
1484    * DOCUMENT ME!\r
1485    *\r
1486    * @param e DOCUMENT ME!\r
1487    */\r
1488   public void taylorColour_actionPerformed(ActionEvent e)\r
1489   {\r
1490     changeColour(new TaylorColourScheme());\r
1491   }\r
1492 \r
1493   /**\r
1494    * DOCUMENT ME!\r
1495    *\r
1496    * @param e DOCUMENT ME!\r
1497    */\r
1498   public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
1499   {\r
1500     changeColour(new HydrophobicColourScheme());\r
1501   }\r
1502 \r
1503   /**\r
1504    * DOCUMENT ME!\r
1505    *\r
1506    * @param e DOCUMENT ME!\r
1507    */\r
1508   public void helixColour_actionPerformed(ActionEvent e)\r
1509   {\r
1510     changeColour(new HelixColourScheme());\r
1511   }\r
1512 \r
1513   /**\r
1514    * DOCUMENT ME!\r
1515    *\r
1516    * @param e DOCUMENT ME!\r
1517    */\r
1518   public void strandColour_actionPerformed(ActionEvent e)\r
1519   {\r
1520     changeColour(new StrandColourScheme());\r
1521   }\r
1522 \r
1523   /**\r
1524    * DOCUMENT ME!\r
1525    *\r
1526    * @param e DOCUMENT ME!\r
1527    */\r
1528   public void turnColour_actionPerformed(ActionEvent e)\r
1529   {\r
1530     changeColour(new TurnColourScheme());\r
1531   }\r
1532 \r
1533   /**\r
1534    * DOCUMENT ME!\r
1535    *\r
1536    * @param e DOCUMENT ME!\r
1537    */\r
1538   public void buriedColour_actionPerformed(ActionEvent e)\r
1539   {\r
1540     changeColour(new BuriedColourScheme());\r
1541   }\r
1542 \r
1543   /**\r
1544    * DOCUMENT ME!\r
1545    *\r
1546    * @param e DOCUMENT ME!\r
1547    */\r
1548   public void nucleotideColour_actionPerformed(ActionEvent e)\r
1549   {\r
1550     changeColour(new NucleotideColourScheme());\r
1551   }\r
1552 \r
1553   /**\r
1554    * DOCUMENT ME!\r
1555    *\r
1556    * @param e DOCUMENT ME!\r
1557    */\r
1558   protected void applyToAllGroups_actionPerformed(ActionEvent e)\r
1559   {\r
1560     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());\r
1561   }\r
1562 \r
1563   /**\r
1564    * DOCUMENT ME!\r
1565    *\r
1566    * @param cs DOCUMENT ME!\r
1567    */\r
1568   void changeColour(ColourSchemeI cs)\r
1569   {\r
1570     int threshold = 0;\r
1571 \r
1572     if(cs!=null)\r
1573     {\r
1574       if (viewport.getAbovePIDThreshold())\r
1575       {\r
1576         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,\r
1577                                                    "Background");\r
1578 \r
1579         cs.setThreshold(threshold,\r
1580                         viewport.getIgnoreGapsConsensus());\r
1581 \r
1582         viewport.setGlobalColourScheme(cs);\r
1583       }\r
1584       else\r
1585       {\r
1586         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1587       }\r
1588 \r
1589       if (viewport.getConservationSelected())\r
1590       {\r
1591 \r
1592         Alignment al = (Alignment) viewport.alignment;\r
1593         Conservation c = new Conservation("All",\r
1594                                           ResidueProperties.propHash, 3,\r
1595                                           al.getSequences(), 0,\r
1596                                           al.getWidth() - 1);\r
1597 \r
1598         c.calculate();\r
1599         c.verdict(false, viewport.ConsPercGaps);\r
1600 \r
1601         cs.setConservation(c);\r
1602 \r
1603         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,\r
1604             "Background"));\r
1605       }\r
1606       else\r
1607       {\r
1608         cs.setConservation(null);\r
1609       }\r
1610 \r
1611       cs.setConsensus(viewport.vconsensus);\r
1612     }\r
1613 \r
1614     viewport.setGlobalColourScheme(cs);\r
1615 \r
1616     if (viewport.getColourAppliesToAllGroups())\r
1617     {\r
1618       Vector groups = viewport.alignment.getGroups();\r
1619 \r
1620       for (int i = 0; i < groups.size(); i++)\r
1621       {\r
1622         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
1623 \r
1624         if (cs == null)\r
1625         {\r
1626           sg.cs = null;\r
1627           continue;\r
1628         }\r
1629 \r
1630         if (cs instanceof ClustalxColourScheme)\r
1631         {\r
1632           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());\r
1633         }\r
1634         else if (cs instanceof UserColourScheme)\r
1635         {\r
1636           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());\r
1637         }\r
1638         else\r
1639         {\r
1640           try\r
1641           {\r
1642             sg.cs = (ColourSchemeI) cs.getClass().newInstance();\r
1643           }\r
1644           catch (Exception ex)\r
1645           {\r
1646           }\r
1647         }\r
1648 \r
1649         if (viewport.getAbovePIDThreshold()\r
1650             || cs instanceof PIDColourScheme\r
1651             || cs instanceof Blosum62ColourScheme)\r
1652         {\r
1653          sg.cs.setThreshold(threshold,\r
1654                 viewport.getIgnoreGapsConsensus());\r
1655 \r
1656           sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0,\r
1657               sg.getWidth()));\r
1658         }\r
1659         else\r
1660           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1661 \r
1662 \r
1663         if (viewport.getConservationSelected())\r
1664         {\r
1665           Conservation c = new Conservation("Group",\r
1666                                             ResidueProperties.propHash, 3,\r
1667                                             sg.sequences, 0,\r
1668                                             viewport.alignment.getWidth() - 1);\r
1669           c.calculate();\r
1670           c.verdict(false, viewport.ConsPercGaps);\r
1671           sg.cs.setConservation(c);\r
1672         }\r
1673         else\r
1674           sg.cs.setConservation(null);\r
1675       }\r
1676     }\r
1677 \r
1678     if (alignPanel.getOverviewPanel() != null)\r
1679     {\r
1680       alignPanel.getOverviewPanel().updateOverviewImage();\r
1681     }\r
1682 \r
1683     alignPanel.repaint();\r
1684   }\r
1685 \r
1686   /**\r
1687    * DOCUMENT ME!\r
1688    *\r
1689    * @param e DOCUMENT ME!\r
1690    */\r
1691   protected void modifyPID_actionPerformed(ActionEvent e)\r
1692   {\r
1693     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)\r
1694     {\r
1695       SliderPanel.setPIDSliderSource(alignPanel,\r
1696                                      viewport.getGlobalColourScheme(),\r
1697                                      "Background");\r
1698       SliderPanel.showPIDSlider();\r
1699     }\r
1700   }\r
1701 \r
1702   /**\r
1703    * DOCUMENT ME!\r
1704    *\r
1705    * @param e DOCUMENT ME!\r
1706    */\r
1707   protected void modifyConservation_actionPerformed(ActionEvent e)\r
1708   {\r
1709     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)\r
1710     {\r
1711       SliderPanel.setConservationSlider(alignPanel,\r
1712                                         viewport.globalColourScheme,\r
1713                                         "Background");\r
1714       SliderPanel.showConservationSlider();\r
1715     }\r
1716   }\r
1717 \r
1718   /**\r
1719    * DOCUMENT ME!\r
1720    *\r
1721    * @param e DOCUMENT ME!\r
1722    */\r
1723   protected void conservationMenuItem_actionPerformed(ActionEvent e)\r
1724   {\r
1725     viewport.setConservationSelected(conservationMenuItem.isSelected());\r
1726 \r
1727     viewport.setAbovePIDThreshold(false);\r
1728     abovePIDThreshold.setSelected(false);\r
1729 \r
1730     changeColour(viewport.getGlobalColourScheme());\r
1731 \r
1732     modifyConservation_actionPerformed(null);\r
1733   }\r
1734 \r
1735   /**\r
1736    * DOCUMENT ME!\r
1737    *\r
1738    * @param e DOCUMENT ME!\r
1739    */\r
1740   public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
1741   {\r
1742     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());\r
1743 \r
1744     conservationMenuItem.setSelected(false);\r
1745     viewport.setConservationSelected(false);\r
1746 \r
1747     changeColour(viewport.getGlobalColourScheme());\r
1748 \r
1749     modifyPID_actionPerformed(null);\r
1750   }\r
1751 \r
1752   /**\r
1753    * DOCUMENT ME!\r
1754    *\r
1755    * @param e DOCUMENT ME!\r
1756    */\r
1757   public void userDefinedColour_actionPerformed(ActionEvent e)\r
1758   {\r
1759     if (e.getActionCommand().equals("User Defined..."))\r
1760     {\r
1761       new UserDefinedColours(alignPanel, null);\r
1762     }\r
1763     else\r
1764     {\r
1765       UserColourScheme udc = (UserColourScheme) UserDefinedColours.\r
1766           getUserColourSchemes().get(e.getActionCommand());\r
1767 \r
1768       changeColour(udc);\r
1769     }\r
1770   }\r
1771 \r
1772   public void updateUserColourMenu()\r
1773   {\r
1774 \r
1775     Component[] menuItems = colourMenu.getMenuComponents();\r
1776     int i, iSize = menuItems.length;\r
1777     for (i = 0; i < iSize; i++)\r
1778     {\r
1779       if (menuItems[i].getName() != null &&\r
1780           menuItems[i].getName().equals("USER_DEFINED"))\r
1781       {\r
1782         colourMenu.remove(menuItems[i]);\r
1783         iSize--;\r
1784       }\r
1785     }\r
1786     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)\r
1787     {\r
1788       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.\r
1789           getUserColourSchemes().keys();\r
1790 \r
1791       while (userColours.hasMoreElements())\r
1792       {\r
1793         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(userColours.\r
1794             nextElement().toString());\r
1795         radioItem.setName("USER_DEFINED");\r
1796         radioItem.addMouseListener(new MouseAdapter()\r
1797             {\r
1798               public void mousePressed(MouseEvent evt)\r
1799               {\r
1800                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))\r
1801                 {\r
1802                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);\r
1803 \r
1804                   int option = JOptionPane.showInternalConfirmDialog(jalview.gui.Desktop.desktop,\r
1805                       "Remove from default list?",\r
1806                       "Remove user defined colour",\r
1807                       JOptionPane.YES_NO_OPTION);\r
1808                   if(option == JOptionPane.YES_OPTION)\r
1809                   {\r
1810                     jalview.gui.UserDefinedColours.removeColourFromDefaults(radioItem.getText());\r
1811                     colourMenu.remove(radioItem);\r
1812                   }\r
1813                   else\r
1814                     radioItem.addActionListener(new ActionListener()\r
1815                     {\r
1816                       public void actionPerformed(ActionEvent evt)\r
1817                       {\r
1818                         userDefinedColour_actionPerformed(evt);\r
1819                       }\r
1820                     });\r
1821                 }\r
1822               }\r
1823             });\r
1824         radioItem.addActionListener(new ActionListener()\r
1825         {\r
1826           public void actionPerformed(ActionEvent evt)\r
1827           {\r
1828             userDefinedColour_actionPerformed(evt);\r
1829           }\r
1830         });\r
1831 \r
1832         colourMenu.insert(radioItem, 15);\r
1833         colours.add(radioItem);\r
1834       }\r
1835     }\r
1836   }\r
1837 \r
1838   /**\r
1839    * DOCUMENT ME!\r
1840    *\r
1841    * @param e DOCUMENT ME!\r
1842    */\r
1843   public void PIDColour_actionPerformed(ActionEvent e)\r
1844   {\r
1845     changeColour(new PIDColourScheme());\r
1846   }\r
1847 \r
1848   /**\r
1849    * DOCUMENT ME!\r
1850    *\r
1851    * @param e DOCUMENT ME!\r
1852    */\r
1853   public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
1854   {\r
1855     changeColour(new Blosum62ColourScheme());\r
1856   }\r
1857 \r
1858   /**\r
1859    * DOCUMENT ME!\r
1860    *\r
1861    * @param e DOCUMENT ME!\r
1862    */\r
1863   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
1864   {\r
1865     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment,\r
1866                                    HistoryItem.SORT));\r
1867     AlignmentSorter.sortByPID(viewport.getAlignment(),\r
1868                               viewport.getAlignment().getSequenceAt(0));\r
1869     alignPanel.repaint();\r
1870   }\r
1871 \r
1872   /**\r
1873    * DOCUMENT ME!\r
1874    *\r
1875    * @param e DOCUMENT ME!\r
1876    */\r
1877   public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
1878   {\r
1879     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment,\r
1880                                    HistoryItem.SORT));\r
1881     AlignmentSorter.sortByID(viewport.getAlignment(), viewport.showDBPrefix);\r
1882     alignPanel.repaint();\r
1883   }\r
1884 \r
1885   /**\r
1886    * DOCUMENT ME!\r
1887    *\r
1888    * @param e DOCUMENT ME!\r
1889    */\r
1890   public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
1891   {\r
1892     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment,\r
1893                                    HistoryItem.SORT));\r
1894 \r
1895     AlignmentSorter.sortByGroup(viewport.getAlignment());\r
1896     alignPanel.repaint();\r
1897   }\r
1898 \r
1899   /**\r
1900    * DOCUMENT ME!\r
1901    *\r
1902    * @param e DOCUMENT ME!\r
1903    */\r
1904   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
1905   {\r
1906     RedundancyPanel sp = new RedundancyPanel(alignPanel, this);\r
1907     JInternalFrame frame = new JInternalFrame();\r
1908     frame.setContentPane(sp);\r
1909     Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400,\r
1910                              100, false);\r
1911   }\r
1912 \r
1913   /**\r
1914    * DOCUMENT ME!\r
1915    *\r
1916    * @param e DOCUMENT ME!\r
1917    */\r
1918   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
1919   {\r
1920     if ( (viewport.getSelectionGroup() == null) ||\r
1921         (viewport.getSelectionGroup().getSize() < 2))\r
1922     {\r
1923       JOptionPane.showInternalMessageDialog(this,\r
1924                                             "You must select at least 2 sequences.",\r
1925                                             "Invalid Selection",\r
1926                                             JOptionPane.WARNING_MESSAGE);\r
1927     }\r
1928     else\r
1929     {\r
1930       JInternalFrame frame = new JInternalFrame();\r
1931       frame.setContentPane(new PairwiseAlignPanel(viewport));\r
1932       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);\r
1933     }\r
1934   }\r
1935 \r
1936   /**\r
1937    * DOCUMENT ME!\r
1938    *\r
1939    * @param e DOCUMENT ME!\r
1940    */\r
1941   public void PCAMenuItem_actionPerformed(ActionEvent e)\r
1942   {\r
1943     if ( ( (viewport.getSelectionGroup() != null) &&\r
1944           (viewport.getSelectionGroup().getSize() < 4) &&\r
1945           (viewport.getSelectionGroup().getSize() > 0)) ||\r
1946         (viewport.getAlignment().getHeight() < 4))\r
1947     {\r
1948       JOptionPane.showInternalMessageDialog(this,\r
1949                                             "Principal component analysis must take\n" +\r
1950                                             "at least 4 input sequences.",\r
1951                                             "Sequence selection insufficient",\r
1952                                             JOptionPane.WARNING_MESSAGE);\r
1953 \r
1954       return;\r
1955     }\r
1956 \r
1957      new PCAPanel(viewport);\r
1958   }\r
1959 \r
1960   /**\r
1961    * DOCUMENT ME!\r
1962    *\r
1963    * @param e DOCUMENT ME!\r
1964    */\r
1965   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
1966   {\r
1967     NewTreePanel("AV", "PID", "Average distance tree using PID");\r
1968   }\r
1969 \r
1970   /**\r
1971    * DOCUMENT ME!\r
1972    *\r
1973    * @param e DOCUMENT ME!\r
1974    */\r
1975   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
1976   {\r
1977     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
1978   }\r
1979 \r
1980   /**\r
1981    * DOCUMENT ME!\r
1982    *\r
1983    * @param e DOCUMENT ME!\r
1984    */\r
1985   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1986   {\r
1987     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
1988   }\r
1989 \r
1990   /**\r
1991    * DOCUMENT ME!\r
1992    *\r
1993    * @param e DOCUMENT ME!\r
1994    */\r
1995   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1996   {\r
1997     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");\r
1998   }\r
1999 \r
2000   /**\r
2001    * DOCUMENT ME!\r
2002    *\r
2003    * @param type DOCUMENT ME!\r
2004    * @param pwType DOCUMENT ME!\r
2005    * @param title DOCUMENT ME!\r
2006    */\r
2007   void NewTreePanel(String type, String pwType, String title)\r
2008   {\r
2009     final TreePanel tp;\r
2010 \r
2011     if ( (viewport.getSelectionGroup() != null) &&\r
2012         (viewport.getSelectionGroup().getSize() > 3))\r
2013     {\r
2014       int s = 0;\r
2015       SequenceGroup sg = viewport.getSelectionGroup();\r
2016 \r
2017       /* Decide if the selection is a column region */\r
2018       while (s < sg.sequences.size())\r
2019       {\r
2020         if ( ( (SequenceI) sg.sequences.elementAt(s++)).getLength() <\r
2021             sg.getEndRes())\r
2022         {\r
2023           JOptionPane.showMessageDialog(Desktop.desktop,\r
2024                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +\r
2025                                         "Try using the Pad function in the edit menu,\n" +\r
2026                                         "or one of the multiple sequence alignment web services.",\r
2027                                         "Sequences in selection are not aligned",\r
2028                                         JOptionPane.WARNING_MESSAGE);\r
2029 \r
2030           return;\r
2031         }\r
2032       }\r
2033 \r
2034       title = title + " on region";\r
2035       tp = new TreePanel(viewport,\r
2036                          viewport.getSelectionGroup().sequences, type, pwType,\r
2037                          sg.getStartRes(), sg.getEndRes());\r
2038     }\r
2039     else\r
2040     {\r
2041       //are the sequences aligned?\r
2042       if (!viewport.alignment.isAligned())\r
2043       {\r
2044         JOptionPane.showMessageDialog(Desktop.desktop,\r
2045                                       "The sequences must be aligned before creating a tree.\n" +\r
2046                                       "Try using the Pad function in the edit menu,\n" +\r
2047                                       "or one of the multiple sequence alignment web services.",\r
2048                                       "Sequences not aligned",\r
2049                                       JOptionPane.WARNING_MESSAGE);\r
2050 \r
2051         return;\r
2052       }\r
2053 \r
2054       tp = new TreePanel(viewport,\r
2055                          viewport.getAlignment().getSequences(), type, pwType,\r
2056                          0,\r
2057                          viewport.alignment.getWidth());\r
2058     }\r
2059 \r
2060     addTreeMenuItem(tp, title);\r
2061     viewport.setCurrentTree(tp.getTree());\r
2062 \r
2063     Desktop.addInternalFrame(tp, title + " from " + this.title, 600, 500);\r
2064   }\r
2065 \r
2066   /**\r
2067    * DOCUMENT ME!\r
2068    *\r
2069    * @param title DOCUMENT ME!\r
2070    * @param order DOCUMENT ME!\r
2071    */\r
2072   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)\r
2073   {\r
2074     final JMenuItem item = new JMenuItem("by " + title);\r
2075     sort.add(item);\r
2076     item.addActionListener(new java.awt.event.ActionListener()\r
2077     {\r
2078       public void actionPerformed(ActionEvent e)\r
2079       {\r
2080         addHistoryItem(new HistoryItem("Sort", viewport.alignment,\r
2081                                        HistoryItem.SORT));\r
2082 \r
2083         // TODO: JBPNote - have to map order entries to curent SequenceI pointers\r
2084         AlignmentSorter.sortBy(viewport.getAlignment(), order);\r
2085         alignPanel.repaint();\r
2086       }\r
2087     });\r
2088   }\r
2089 \r
2090   /**\r
2091    * Maintain the Order by->Displayed Tree menu.\r
2092    * Creates a new menu item for a TreePanel with an appropriate\r
2093    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added\r
2094    * to remove the menu item when the treePanel is closed, and adjust\r
2095    * the tree leaf to sequence mapping when the alignment is modified.\r
2096    * @param treePanel Displayed tree window.\r
2097    * @param title SortBy menu item title.\r
2098    */\r
2099   void addTreeMenuItem(final TreePanel treePanel, String title)\r
2100   {\r
2101     final JMenuItem item = new JMenuItem(title);\r
2102 \r
2103     treeCount++;\r
2104 \r
2105     if (treeCount == 1)\r
2106     {\r
2107       sort.add(sortByTreeMenu);\r
2108     }\r
2109 \r
2110     sortByTreeMenu.add(item);\r
2111     item.addActionListener(new java.awt.event.ActionListener()\r
2112     {\r
2113       public void actionPerformed(ActionEvent e)\r
2114       {\r
2115         addHistoryItem(new HistoryItem("Tree Sort",\r
2116                                        viewport.alignment, HistoryItem.SORT));\r
2117         AlignmentSorter.sortByTree(viewport.getAlignment(),\r
2118                                    treePanel.getTree());\r
2119         alignPanel.repaint();\r
2120       }\r
2121     });\r
2122 \r
2123     treePanel.addInternalFrameListener(new javax.swing.event.\r
2124                                        InternalFrameAdapter()\r
2125     {\r
2126       public void internalFrameClosed(\r
2127           javax.swing.event.InternalFrameEvent evt)\r
2128       {\r
2129         treeCount--;\r
2130         sortByTreeMenu.remove(item);\r
2131 \r
2132         if (treeCount == 0)\r
2133         {\r
2134           sort.remove(sortByTreeMenu);\r
2135         }\r
2136       }\r
2137       ;\r
2138     });\r
2139   }\r
2140 \r
2141   /**\r
2142    * Work out whether the whole set of sequences\r
2143    * or just the selected set will be submitted for multiple alignment.\r
2144    *\r
2145    */\r
2146   private SequenceI[] gatherSequencesForAlignment()\r
2147   {\r
2148     // Now, check we have enough sequences\r
2149     SequenceI[] msa = null;\r
2150 \r
2151     if ( (viewport.getSelectionGroup() != null) &&\r
2152         (viewport.getSelectionGroup().getSize() > 1))\r
2153     {\r
2154       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!\r
2155       SequenceGroup seqs = viewport.getSelectionGroup();\r
2156       int sz;\r
2157       msa = new SequenceI[sz = seqs.getSize()];\r
2158 \r
2159       for (int i = 0; i < sz; i++)\r
2160       {\r
2161         msa[i] = (SequenceI) seqs.getSequenceAt(i);\r
2162       }\r
2163     }\r
2164     else\r
2165     {\r
2166       Vector seqs = viewport.getAlignment().getSequences();\r
2167 \r
2168       if (seqs.size() > 1)\r
2169       {\r
2170         msa = new SequenceI[seqs.size()];\r
2171 \r
2172         for (int i = 0; i < seqs.size(); i++)\r
2173         {\r
2174           msa[i] = (SequenceI) seqs.elementAt(i);\r
2175         }\r
2176       }\r
2177     }\r
2178     return msa;\r
2179   }\r
2180 \r
2181   /**\r
2182    * Decides what is submitted to a secondary structure prediction service,\r
2183    * the currently selected sequence, or the currently selected alignment\r
2184    * (where the first sequence in the set is the one that the prediction\r
2185    * will be for).\r
2186    */\r
2187   SequenceI[] gatherSeqOrMsaForSecStrPrediction()\r
2188   {\r
2189     SequenceI seq = null;\r
2190     SequenceI[] msa = null;\r
2191 \r
2192     if ( (viewport.getSelectionGroup() != null) &&\r
2193         (viewport.getSelectionGroup().getSize() > 0))\r
2194     {\r
2195       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!\r
2196       SequenceGroup seqs = viewport.getSelectionGroup();\r
2197 \r
2198       if ( (seqs.getSize() == 1) || !viewport.alignment.isAligned())\r
2199       {\r
2200         seq = (SequenceI) seqs.getSequenceAt(0);\r
2201       }\r
2202       else\r
2203       {\r
2204         int sz;\r
2205         msa = new SequenceI[sz = seqs.getSize()];\r
2206 \r
2207         for (int i = 0; i < sz; i++)\r
2208         {\r
2209           msa[i] = (SequenceI) seqs.getSequenceAt(i);\r
2210         }\r
2211       }\r
2212     }\r
2213     else\r
2214     {\r
2215       Vector seqs = viewport.getAlignment().getSequences();\r
2216 \r
2217       if ( (seqs.size() == 1) || !viewport.alignment.isAligned())\r
2218       {\r
2219         seq = (SequenceI) seqs.elementAt(0);\r
2220       }\r
2221       else\r
2222       {\r
2223         msa = new SequenceI[seqs.size()];\r
2224 \r
2225         for (int i = 0; i < seqs.size(); i++)\r
2226         {\r
2227           msa[i] = (SequenceI) seqs.elementAt(i);\r
2228         }\r
2229       }\r
2230     }\r
2231     if (msa != null)\r
2232     {\r
2233       return msa;\r
2234     }\r
2235     else\r
2236     {\r
2237       if (seq != null)\r
2238       {\r
2239         return new SequenceI[]\r
2240             {\r
2241             seq};\r
2242       }\r
2243     }\r
2244     return null;\r
2245   }\r
2246   /**\r
2247    * DOCUMENT ME!\r
2248    *\r
2249    * @param e DOCUMENT ME!\r
2250    */\r
2251   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)\r
2252   {\r
2253     // Pick the tree file\r
2254     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
2255         getProperty(\r
2256             "LAST_DIRECTORY"));\r
2257     chooser.setFileView(new JalviewFileView());\r
2258     chooser.setDialogTitle("Select a newick-like tree file");\r
2259     chooser.setToolTipText("Load a tree file");\r
2260 \r
2261     int value = chooser.showOpenDialog(null);\r
2262 \r
2263     if (value == JalviewFileChooser.APPROVE_OPTION)\r
2264     {\r
2265       String choice = chooser.getSelectedFile().getPath();\r
2266       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
2267 \r
2268       try\r
2269       {\r
2270         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,\r
2271             "File");\r
2272         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());\r
2273       }\r
2274       catch (Exception ex)\r
2275       {\r
2276         JOptionPane.showMessageDialog(Desktop.desktop,\r
2277                                       "Problem reading tree file",\r
2278                                       ex.getMessage(),\r
2279                                       JOptionPane.WARNING_MESSAGE);\r
2280         ex.printStackTrace();\r
2281       }\r
2282     }\r
2283   }\r
2284 \r
2285 \r
2286   public TreePanel ShowNewickTree(NewickFile nf, String title)\r
2287   {\r
2288     return ShowNewickTree(nf,title,600,500,4,5);\r
2289   }\r
2290   /**\r
2291    * DOCUMENT ME!\r
2292    *\r
2293    * @param nf DOCUMENT ME!\r
2294    * @param title DOCUMENT ME!\r
2295    *\r
2296    * @return DOCUMENT ME!\r
2297    */\r
2298   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y)\r
2299   {\r
2300     TreePanel tp = null;\r
2301 \r
2302     try\r
2303     {\r
2304       nf.parse();\r
2305 \r
2306       if (nf.getTree() != null)\r
2307       {\r
2308         tp = new TreePanel(viewport,\r
2309                            viewport.getAlignment().getSequences(), nf,\r
2310                            "FromFile",\r
2311                            title);\r
2312 \r
2313         tp.setSize(w,h);\r
2314 \r
2315         if(x>0 && y>0)\r
2316           tp.setLocation(x,y);\r
2317 \r
2318 \r
2319         Desktop.addInternalFrame(tp, title, w, h);\r
2320         addTreeMenuItem(tp, title);\r
2321       }\r
2322     }\r
2323     catch (Exception ex)\r
2324     {\r
2325       ex.printStackTrace();\r
2326     }\r
2327 \r
2328     return tp;\r
2329   }\r
2330 \r
2331   class PrintThread\r
2332       extends Thread\r
2333   {\r
2334     public void run()\r
2335     {\r
2336       PrinterJob printJob = PrinterJob.getPrinterJob();\r
2337       PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
2338       printJob.setPrintable(alignPanel, pf);\r
2339 \r
2340       if (printJob.printDialog())\r
2341       {\r
2342         try\r
2343         {\r
2344           printJob.print();\r
2345         }\r
2346         catch (Exception PrintException)\r
2347         {\r
2348           PrintException.printStackTrace();\r
2349         }\r
2350       }\r
2351     }\r
2352   }\r
2353 \r
2354   /**\r
2355    * Generates menu items and listener event actions for web service clients\r
2356    *\r
2357    */\r
2358   public void BuildWebServiceMenu()\r
2359   {\r
2360     if ( (Discoverer.services != null)\r
2361         && (Discoverer.services.size() > 0))\r
2362     {\r
2363       Vector msaws = (Vector) Discoverer.services.get("MsaWS");\r
2364       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");\r
2365       Vector wsmenu = new Vector();\r
2366       if (msaws != null)\r
2367       {\r
2368         // Add any Multiple Sequence Alignment Services\r
2369         final JMenu msawsmenu = new JMenu("Alignment");\r
2370         for (int i = 0, j = msaws.size(); i < j; i++)\r
2371         {\r
2372           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.\r
2373               get(i);\r
2374           final JMenuItem method = new JMenuItem(sh.getName());\r
2375           method.addActionListener(new ActionListener()\r
2376           {\r
2377             public void actionPerformed(ActionEvent e)\r
2378             {\r
2379               SequenceI[] msa = gatherSequencesForAlignment();\r
2380               new jalview.ws.MsaWSClient(sh, title, msa,\r
2381                   false, true, viewport.getAlignment().getDataset());\r
2382 \r
2383             }\r
2384 \r
2385           });\r
2386           msawsmenu.add(method);\r
2387           // Deal with services that we know accept partial alignments.\r
2388           if (sh.getName().indexOf("lustal") > -1)\r
2389           {\r
2390             // We know that ClustalWS can accept partial alignments for refinement.\r
2391             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");\r
2392             methodR.addActionListener(new ActionListener()\r
2393             {\r
2394               public void actionPerformed(ActionEvent e)\r
2395               {\r
2396                 SequenceI[] msa = gatherSequencesForAlignment();\r
2397                 new jalview.ws.MsaWSClient(sh, title, msa,\r
2398                     true, true, viewport.getAlignment().getDataset());\r
2399 \r
2400               }\r
2401 \r
2402             });\r
2403             msawsmenu.add(methodR);\r
2404 \r
2405           }\r
2406         }\r
2407         wsmenu.add(msawsmenu);\r
2408       }\r
2409       if (secstrpr != null)\r
2410       {\r
2411         // Add any secondary structure prediction services\r
2412         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");\r
2413         for (int i = 0, j = secstrpr.size(); i < j; i++)\r
2414         {\r
2415           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)\r
2416               secstrpr.get(i);\r
2417           final JMenuItem method = new JMenuItem(sh.getName());\r
2418           method.addActionListener(new ActionListener()\r
2419           {\r
2420             public void actionPerformed(ActionEvent e)\r
2421             {\r
2422               SequenceI[] msa = gatherSeqOrMsaForSecStrPrediction();\r
2423               if (msa.length == 1)\r
2424               {\r
2425                 // Single Sequence prediction\r
2426                 new jalview.ws.JPredClient(sh,title, msa[0]);\r
2427               }\r
2428               else\r
2429               {\r
2430                 if (msa.length > 1)\r
2431                 {\r
2432                   // Single Sequence prediction\r
2433                   jalview.ws.JPredClient ct = new jalview.ws.JPredClient(sh,\r
2434                       title, msa);\r
2435                 }\r
2436               }\r
2437             }\r
2438           });\r
2439           secstrmenu.add(method);\r
2440         }\r
2441         wsmenu.add(secstrmenu);\r
2442       }\r
2443       this.webService.removeAll();\r
2444       for (int i = 0, j = wsmenu.size(); i < j; i++)\r
2445       {\r
2446         webService.add( (JMenu) wsmenu.get(i));\r
2447       }\r
2448     }\r
2449     else\r
2450     {\r
2451       this.webService.removeAll();\r
2452       this.webService.add(this.webServiceNoServices);\r
2453     }\r
2454     // TODO: add in rediscovery function\r
2455     // TODO: reduce code redundancy.\r
2456     // TODO: group services by location as well as function.\r
2457   }\r
2458 \r
2459   public void vamsasStore_actionPerformed(ActionEvent e)\r
2460   {\r
2461     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
2462         getProperty("LAST_DIRECTORY"));\r
2463 \r
2464     chooser.setFileView(new JalviewFileView());\r
2465     chooser.setDialogTitle("Export to Vamsas file");\r
2466     chooser.setToolTipText("Export");\r
2467 \r
2468     int value = chooser.showSaveDialog(this);\r
2469 \r
2470     if (value == JalviewFileChooser.APPROVE_OPTION)\r
2471     {\r
2472       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);\r
2473       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );\r
2474       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);\r
2475     }\r
2476   }\r
2477 \r
2478   public void featureSettings_actionPerformed(ActionEvent e)\r
2479   {\r
2480     new FeatureSettings(viewport, alignPanel);\r
2481   }\r
2482 \r
2483 \r
2484 \r
2485 public void showTranslation_actionPerformed(ActionEvent e)\r
2486 {\r
2487 \r
2488   if(!viewport.alignment.isNucleotide())\r
2489     return;\r
2490 \r
2491   viewport.showTranslation(showTranslation.isSelected());\r
2492 \r
2493   if(!viewport.alignment.isNucleotide())\r
2494     return;\r
2495 \r
2496   int s, sSize = viewport.alignment.getHeight();\r
2497   SequenceI [] newSeq = new SequenceI[sSize];\r
2498 \r
2499   int res, resSize;\r
2500   StringBuffer protein;\r
2501   SequenceI seq;\r
2502   for(s=0; s<sSize; s++)\r
2503   {\r
2504     protein = new StringBuffer();\r
2505     seq = (SequenceI)viewport.alignment.getSequenceAt(s);\r
2506     resSize = seq.getLength();\r
2507     for(res = 0; res < resSize; res+=3)\r
2508     {\r
2509       String codon = seq.getSequence(res, res+3);\r
2510       codon = codon.replace('U', 'T');\r
2511       String aa = ResidueProperties.codonTranslate(codon);\r
2512       if(aa==null)\r
2513         protein.append(viewport.getGapCharacter());\r
2514       else if(aa.equals("STOP"))\r
2515         protein.append("X");\r
2516       else\r
2517         protein.append( aa );\r
2518     }\r
2519     newSeq[s] = new Sequence(seq.getName(), protein.toString());\r
2520   }\r
2521 \r
2522 \r
2523   AlignmentI al = new Alignment(newSeq);\r
2524   al.setDataset(null);\r
2525 \r
2526 \r
2527   ////////////////////////////////\r
2528   // Copy annotations across\r
2529   jalview.datamodel.AlignmentAnnotation[] annotations\r
2530       = viewport.alignment.getAlignmentAnnotation();\r
2531   int a, aSize;\r
2532   for (int i = 0; i < annotations.length; i++)\r
2533   {\r
2534 \r
2535     if (annotations[i].label.equals("Quality") ||\r
2536         annotations[i].label.equals("Conservation") ||\r
2537         annotations[i].label.equals("Consensus"))\r
2538     {\r
2539       continue;\r
2540     }\r
2541 \r
2542 \r
2543     aSize = viewport.alignment.getWidth()/3;\r
2544     jalview.datamodel.Annotation [] anots =\r
2545         new jalview.datamodel.Annotation[aSize];\r
2546 \r
2547     for(a=0; a<viewport.alignment.getWidth(); a++)\r
2548     {\r
2549      if( annotations[i].annotations[a]==null\r
2550       || annotations[i].annotations[a]==null)\r
2551        continue;\r
2552 \r
2553       anots[a/3] = new Annotation(\r
2554      annotations[i].annotations[a].displayCharacter,\r
2555      annotations[i].annotations[a].description,\r
2556      annotations[i].annotations[a].secondaryStructure,\r
2557      annotations[i].annotations[a].value,\r
2558      annotations[i].annotations[a].colour);\r
2559     }\r
2560 \r
2561     jalview.datamodel.AlignmentAnnotation aa\r
2562           = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,\r
2563        annotations[i].description, anots );\r
2564      al.addAnnotation(aa);\r
2565   }\r
2566 \r
2567 \r
2568    // Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),\r
2569     //                         NEW_WINDOW_WIDTH,\r
2570      //                        NEW_WINDOW_HEIGHT);\r
2571 \r
2572     AlignViewport newViewport = new AlignViewport(al);\r
2573     AlignmentPanel ap = new AlignmentPanel(this, newViewport);\r
2574     tabbedPane.add("Protein", ap);\r
2575     viewports.add(newViewport);\r
2576     alignPanels.add(ap);\r
2577 \r
2578     ///Dataset tab\r
2579   /////////////////////////\r
2580 \r
2581     AlignViewport ds = new AlignViewport(al.getDataset());\r
2582     ds.setDataset(true);\r
2583     AlignmentPanel dap = new AlignmentPanel(this, ds);\r
2584     tabbedPane.add("Dataset", dap);\r
2585     viewports.add(ds);\r
2586     alignPanels.add(dap);\r
2587   /////////////////////////\r
2588 \r
2589 \r
2590 }\r
2591 \r
2592 public void tabSelected()\r
2593 {\r
2594   int index = tabbedPane.getSelectedIndex();\r
2595   viewport = (AlignViewport)viewports.elementAt(index);\r
2596   alignPanel = (AlignmentPanel)alignPanels.elementAt(index);\r
2597 }\r
2598 \r
2599 }\r