Add support RNAML format
[jalview.git] / src / jalview / appletgui / AlignFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle\r
4  *\r
5  * This file is part of Jalview.\r
6  *\r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License\r
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
10  *\r
11  * Jalview is distributed in the hope that it will be useful, but\r
12  * WITHOUT ANY WARRANTY; without even the implied warranty\r
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
14  * PURPOSE.  See the GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package jalview.appletgui;\r
19 \r
20 import jalview.analysis.AAFrequency;\r
21 import jalview.analysis.AlignmentSorter;\r
22 import jalview.analysis.Conservation;\r
23 import jalview.api.SequenceStructureBinding;\r
24 import jalview.bin.JalviewLite;\r
25 import jalview.commands.CommandI;\r
26 import jalview.commands.EditCommand;\r
27 import jalview.commands.OrderCommand;\r
28 import jalview.commands.RemoveGapColCommand;\r
29 import jalview.commands.RemoveGapsCommand;\r
30 import jalview.commands.SlideSequencesCommand;\r
31 import jalview.commands.TrimRegionCommand;\r
32 import jalview.datamodel.Alignment;\r
33 import jalview.datamodel.AlignmentI;\r
34 import jalview.datamodel.AlignmentOrder;\r
35 import jalview.datamodel.ColumnSelection;\r
36 import jalview.datamodel.PDBEntry;\r
37 import jalview.datamodel.Sequence;\r
38 import jalview.datamodel.SequenceCollectionI;\r
39 import jalview.datamodel.SequenceGroup;\r
40 import jalview.datamodel.SequenceI;\r
41 import jalview.io.AnnotationFile;\r
42 import jalview.io.AppletFormatAdapter;\r
43 import jalview.io.FeaturesFile;\r
44 import jalview.io.TCoffeeScoreFile;\r
45 import jalview.schemes.Blosum62ColourScheme;\r
46 import jalview.schemes.BuriedColourScheme;\r
47 import jalview.schemes.ClustalxColourScheme;\r
48 import jalview.schemes.ColourSchemeI;\r
49 import jalview.schemes.HelixColourScheme;\r
50 import jalview.schemes.HydrophobicColourScheme;\r
51 import jalview.schemes.NucleotideColourScheme;\r
52 import jalview.schemes.PIDColourScheme;\r
53 import jalview.schemes.PurinePyrimidineColourScheme;\r
54 import jalview.schemes.RNAHelicesColourChooser;\r
55 import jalview.schemes.ResidueProperties;\r
56 import jalview.schemes.StrandColourScheme;\r
57 import jalview.schemes.TCoffeeColourScheme;\r
58 import jalview.schemes.TaylorColourScheme;\r
59 import jalview.schemes.TurnColourScheme;\r
60 import jalview.schemes.ZappoColourScheme;\r
61 import jalview.structure.StructureSelectionManager;\r
62 \r
63 import java.awt.BorderLayout;\r
64 import java.awt.Canvas;\r
65 import java.awt.CheckboxMenuItem;\r
66 import java.awt.Color;\r
67 import java.awt.Font;\r
68 import java.awt.FontMetrics;\r
69 import java.awt.Frame;\r
70 import java.awt.Graphics;\r
71 import java.awt.Label;\r
72 import java.awt.Menu;\r
73 import java.awt.MenuBar;\r
74 import java.awt.MenuItem;\r
75 import java.awt.event.ActionEvent;\r
76 import java.awt.event.ActionListener;\r
77 import java.awt.event.FocusEvent;\r
78 import java.awt.event.FocusListener;\r
79 import java.awt.event.ItemEvent;\r
80 import java.awt.event.ItemListener;\r
81 import java.awt.event.KeyEvent;\r
82 import java.awt.event.KeyListener;\r
83 import java.awt.event.WindowAdapter;\r
84 import java.awt.event.WindowEvent;\r
85 import java.io.IOException;\r
86 import java.io.InputStreamReader;\r
87 import java.net.URL;\r
88 import java.net.URLEncoder;\r
89 import java.util.Enumeration;\r
90 import java.util.Hashtable;\r
91 import java.util.List;\r
92 import java.util.StringTokenizer;\r
93 import java.util.Vector;\r
94 \r
95 import javax.xml.parsers.ParserConfigurationException;\r
96 \r
97 import org.xml.sax.SAXException;\r
98 \r
99 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;\r
100 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;\r
101 import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;\r
102 \r
103 public class AlignFrame extends EmbmenuFrame implements ActionListener,  ItemListener, KeyListener\r
104 {\r
105   public AlignmentPanel alignPanel;\r
106 \r
107   public AlignViewport viewport;\r
108 \r
109   int DEFAULT_WIDTH = 700;\r
110 \r
111   int DEFAULT_HEIGHT = 500;\r
112 \r
113   String jalviewServletURL;\r
114 \r
115 \r
116   public AlignFrame(AlignmentI al, jalview.bin.JalviewLite applet, String title, boolean embedded)\r
117   {\r
118     if (applet != null)\r
119     {\r
120       jalviewServletURL = applet.getParameter("APPLICATION_URL");\r
121     }\r
122 \r
123     try\r
124     {\r
125       jbInit();\r
126     } catch (Exception ex)\r
127     {\r
128       ex.printStackTrace();\r
129     }\r
130 \r
131     viewport = new AlignViewport(al, applet);\r
132     alignPanel = new AlignmentPanel(this, viewport);\r
133 \r
134     viewport.updateConservation(alignPanel);\r
135     viewport.updateConsensus(alignPanel);\r
136 \r
137     annotationPanelMenuItem.setState(viewport.showAnnotation);\r
138     displayNonconservedMenuItem.setState(viewport.getShowUnconserved());\r
139     followMouseOverFlag.setState(viewport.getFollowHighlight());\r
140     showGroupConsensus.setState(viewport.isShowGroupConsensus());\r
141     showGroupConservation.setState(viewport.isShowGroupConservation());\r
142     showConsensusHistogram.setState(viewport.isShowConsensusHistogram());\r
143     showSequenceLogo.setState(viewport.isShowSequenceLogo());\r
144 \r
145     seqLimits.setState(viewport.showJVSuffix);\r
146 \r
147     if (applet != null)\r
148     {\r
149       String param = applet.getParameter("sortBy");\r
150       if (param != null)\r
151       {\r
152         if (param.equalsIgnoreCase("Id"))\r
153         {\r
154           sortIDMenuItem_actionPerformed();\r
155         }\r
156         else if (param.equalsIgnoreCase("Pairwise Identity"))\r
157         {\r
158           sortPairwiseMenuItem_actionPerformed();\r
159         }\r
160         else if (param.equalsIgnoreCase("Length"))\r
161         {\r
162           sortLengthMenuItem_actionPerformed();\r
163         }\r
164       }\r
165 \r
166       param = applet.getParameter("wrap");\r
167       if (param != null)\r
168       {\r
169         if (param.equalsIgnoreCase("true"))\r
170         {\r
171           wrapMenuItem.setState(true);\r
172           wrapMenuItem_actionPerformed();\r
173         }\r
174       }\r
175       param = applet.getParameter("centrecolumnlabels");\r
176       if (param != null)\r
177       {\r
178         centreColumnLabelFlag.setState(true);\r
179         centreColumnLabelFlag_stateChanged();\r
180       }\r
181       try\r
182       {\r
183         param = applet.getParameter("windowWidth");\r
184         if (param != null)\r
185         {\r
186           int width = Integer.parseInt(param);\r
187           DEFAULT_WIDTH = width;\r
188         }\r
189         param = applet.getParameter("windowHeight");\r
190         if (param != null)\r
191         {\r
192           int height = Integer.parseInt(param);\r
193           DEFAULT_HEIGHT = height;\r
194         }\r
195       } catch (Exception ex)\r
196       {\r
197       }\r
198 \r
199     }\r
200     if (viewport.getAlignment().isNucleotide())\r
201     {\r
202       viewport.updateStrucConsensus(alignPanel);\r
203       if (viewport.getAlignment().hasRNAStructure())\r
204       {\r
205         RNAHelixColour.setEnabled(true);\r
206       }\r
207       else {\r
208         RNAHelixColour.setEnabled(false);\r
209       }\r
210     } else {\r
211       RNAHelixColour.setEnabled(false);\r
212       purinePyrimidineColour.setEnabled(false);\r
213     }\r
214     // Some JVMS send keyevents to Top frame or lowest panel,\r
215     // Havent worked out why yet. So add to both this frame and seqCanvas for\r
216     // now\r
217     this.addKeyListener(this);\r
218     alignPanel.seqPanel.seqCanvas.addKeyListener(this);\r
219     alignPanel.idPanel.idCanvas.addKeyListener(this);\r
220     alignPanel.scalePanel.addKeyListener(this);\r
221     alignPanel.annotationPanel.addKeyListener(this);\r
222     alignPanel.annotationPanelHolder.addKeyListener(this);\r
223     alignPanel.annotationSpaceFillerHolder.addKeyListener(this);\r
224     alignPanel.alabels.addKeyListener(this);\r
225     createAlignFrameWindow(embedded, title);\r
226 \r
227     validate();\r
228     alignPanel.adjustAnnotationHeight();\r
229     alignPanel.paintAlignment(true);\r
230   }\r
231 \r
232   public AlignViewport getAlignViewport()\r
233   {\r
234     return viewport;\r
235   }\r
236 \r
237   public SeqCanvas getSeqcanvas()\r
238   {\r
239     return alignPanel.seqPanel.seqCanvas;\r
240   }\r
241 \r
242   /**\r
243    * Load a features file onto the alignment\r
244    *\r
245    * @param file file URL, content, or other resolvable path\r
246    * @param type is protocol for accessing data referred to by file\r
247    */\r
248 \r
249   public boolean parseFeaturesFile(String file, String type)\r
250   {\r
251     return parseFeaturesFile(file, type, true);\r
252   }\r
253 \r
254   /**\r
255    * Load a features file onto the alignment\r
256    *\r
257    * @param file file URL, content, or other resolvable path\r
258    * @param type is protocol for accessing data referred to by file\r
259    * @param autoenabledisplay when true, display features flag will be automatically enabled if features are loaded\r
260    * @return true if data parsed as a features file\r
261    */\r
262   public boolean parseFeaturesFile(String file, String type, boolean autoenabledisplay)\r
263   {\r
264     // TODO: test if importing a features file onto an alignment which already has features with links overwrites the original links.\r
265 \r
266     Hashtable featureLinks = new Hashtable();\r
267     boolean featuresFile = false;\r
268     try\r
269     {\r
270       featuresFile = new jalview.io.FeaturesFile(file, type)\r
271               .parse(viewport.getAlignment(),\r
272                       alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureColours,\r
273                       featureLinks, true, viewport.applet.getDefaultParameter("relaxedidmatch", false));\r
274     } catch (Exception ex)\r
275     {\r
276       ex.printStackTrace();\r
277     }\r
278 \r
279     if (featuresFile)\r
280     {\r
281       if (featureLinks.size() > 0)\r
282       {\r
283         alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureLinks = featureLinks;\r
284       }\r
285       if (autoenabledisplay)\r
286       {\r
287         viewport.showSequenceFeatures = true;\r
288         sequenceFeatures.setState(true);\r
289       }\r
290       if (viewport.featureSettings != null)\r
291       {\r
292         viewport.featureSettings.refreshTable();\r
293       }\r
294       alignPanel.paintAlignment(true);\r
295       statusBar.setText("Successfully added features to alignment.");\r
296     }\r
297     return featuresFile;\r
298   }\r
299 \r
300   @Override\r
301   public void keyPressed(KeyEvent evt)\r
302   {\r
303     if (viewport.cursorMode\r
304             && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt\r
305                     .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt\r
306                     .getKeyCode() <= KeyEvent.VK_NUMPAD9))\r
307             && Character.isDigit(evt.getKeyChar()))\r
308       alignPanel.seqPanel.numberPressed(evt.getKeyChar());\r
309 \r
310     switch (evt.getKeyCode())\r
311     {\r
312     case 27: // escape key\r
313       deselectAllSequenceMenuItem_actionPerformed();\r
314 \r
315       alignPanel.alabels.cancelDrag();\r
316       break;\r
317     case KeyEvent.VK_X:\r
318       if (evt.isControlDown() || evt.isMetaDown())\r
319       {\r
320         cut_actionPerformed();\r
321       }\r
322       break;\r
323     case KeyEvent.VK_C:\r
324       if (viewport.cursorMode && !evt.isControlDown())\r
325       {\r
326         alignPanel.seqPanel.setCursorColumn();\r
327       }\r
328       if (evt.isControlDown() || evt.isMetaDown())\r
329       {\r
330         copy_actionPerformed();\r
331       }\r
332       break;\r
333     case KeyEvent.VK_V:\r
334       if (evt.isControlDown())\r
335       {\r
336         paste(evt.isShiftDown());\r
337       }\r
338       break;\r
339     case KeyEvent.VK_A:\r
340       if (evt.isControlDown() || evt.isMetaDown())\r
341       {\r
342         selectAllSequenceMenuItem_actionPerformed();\r
343       }\r
344       break;\r
345     case KeyEvent.VK_DOWN:\r
346       if (viewport.cursorMode)\r
347       {\r
348         alignPanel.seqPanel.moveCursor(0, 1);\r
349       }\r
350       else\r
351       {\r
352         moveSelectedSequences(false);\r
353       }\r
354       break;\r
355 \r
356     case KeyEvent.VK_UP:\r
357       if (viewport.cursorMode)\r
358       {\r
359         alignPanel.seqPanel.moveCursor(0, -1);\r
360       }\r
361       else\r
362       {\r
363         moveSelectedSequences(true);\r
364       }\r
365       break;\r
366 \r
367     case KeyEvent.VK_LEFT:\r
368       if (evt.isAltDown() || !viewport.cursorMode)\r
369         slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());\r
370       else\r
371         alignPanel.seqPanel.moveCursor(-1, 0);\r
372       break;\r
373 \r
374     case KeyEvent.VK_RIGHT:\r
375       if (evt.isAltDown() || !viewport.cursorMode)\r
376         slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());\r
377       else\r
378         alignPanel.seqPanel.moveCursor(1, 0);\r
379       break;\r
380 \r
381     case KeyEvent.VK_SPACE:\r
382       if (viewport.cursorMode)\r
383       {\r
384         alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()\r
385                 || evt.isShiftDown() || evt.isAltDown());\r
386       }\r
387       break;\r
388 \r
389     case KeyEvent.VK_DELETE:\r
390     case KeyEvent.VK_BACK_SPACE:\r
391       if (viewport.cursorMode)\r
392       {\r
393         alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()\r
394                 || evt.isShiftDown() || evt.isAltDown());\r
395       }\r
396       else\r
397       {\r
398         cut_actionPerformed();\r
399         alignPanel.seqPanel.seqCanvas.repaint();\r
400       }\r
401       break;\r
402 \r
403     case KeyEvent.VK_S:\r
404       if (viewport.cursorMode)\r
405       {\r
406         alignPanel.seqPanel.setCursorRow();\r
407       }\r
408       break;\r
409     case KeyEvent.VK_P:\r
410       if (viewport.cursorMode)\r
411       {\r
412         alignPanel.seqPanel.setCursorPosition();\r
413       }\r
414       break;\r
415 \r
416     case KeyEvent.VK_ENTER:\r
417     case KeyEvent.VK_COMMA:\r
418       if (viewport.cursorMode)\r
419       {\r
420         alignPanel.seqPanel.setCursorRowAndColumn();\r
421       }\r
422       break;\r
423 \r
424     case KeyEvent.VK_Q:\r
425       if (viewport.cursorMode)\r
426       {\r
427         alignPanel.seqPanel.setSelectionAreaAtCursor(true);\r
428       }\r
429       break;\r
430     case KeyEvent.VK_M:\r
431       if (viewport.cursorMode)\r
432       {\r
433         alignPanel.seqPanel.setSelectionAreaAtCursor(false);\r
434       }\r
435       break;\r
436 \r
437     case KeyEvent.VK_F2:\r
438       viewport.cursorMode = !viewport.cursorMode;\r
439       statusBar.setText("Keyboard editing mode is "\r
440               + (viewport.cursorMode ? "on" : "off"));\r
441       if (viewport.cursorMode)\r
442       {\r
443         alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;\r
444         alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;\r
445       }\r
446       break;\r
447 \r
448     case KeyEvent.VK_F:\r
449       if (evt.isControlDown())\r
450       {\r
451         findMenuItem_actionPerformed();\r
452       }\r
453       break;\r
454 \r
455     case KeyEvent.VK_H:\r
456     {\r
457       boolean toggleSeqs = !evt.isControlDown();\r
458       boolean toggleCols = !evt.isShiftDown();\r
459       toggleHiddenRegions(toggleSeqs, toggleCols);\r
460       break;\r
461     }\r
462 \r
463     case KeyEvent.VK_PAGE_UP:\r
464       if (viewport.wrapAlignment)\r
465       {\r
466         alignPanel.scrollUp(true);\r
467       }\r
468       else\r
469       {\r
470         alignPanel.setScrollValues(viewport.startRes, viewport.startSeq\r
471                 - viewport.endSeq + viewport.startSeq);\r
472       }\r
473       break;\r
474 \r
475     case KeyEvent.VK_PAGE_DOWN:\r
476       if (viewport.wrapAlignment)\r
477       {\r
478         alignPanel.scrollUp(false);\r
479       }\r
480       else\r
481       {\r
482         alignPanel.setScrollValues(viewport.startRes, viewport.startSeq\r
483                 + viewport.endSeq - viewport.startSeq);\r
484       }\r
485       break;\r
486 \r
487     case KeyEvent.VK_Z:\r
488       if (evt.isControlDown())\r
489       {\r
490         undoMenuItem_actionPerformed();\r
491       }\r
492       break;\r
493 \r
494     case KeyEvent.VK_Y:\r
495       if (evt.isControlDown())\r
496       {\r
497         redoMenuItem_actionPerformed();\r
498       }\r
499       break;\r
500 \r
501     case KeyEvent.VK_L:\r
502       if (evt.isControlDown())\r
503       {\r
504         trimAlignment(true);\r
505       }\r
506       break;\r
507 \r
508     case KeyEvent.VK_R:\r
509       if (evt.isControlDown())\r
510       {\r
511         trimAlignment(false);\r
512       }\r
513       break;\r
514 \r
515     case KeyEvent.VK_E:\r
516       if (evt.isControlDown())\r
517       {\r
518         if (evt.isShiftDown())\r
519         {\r
520           this.removeAllGapsMenuItem_actionPerformed();\r
521         }\r
522         else\r
523         {\r
524           removeGappedColumnMenuItem_actionPerformed();\r
525         }\r
526       }\r
527       break;\r
528     case KeyEvent.VK_I:\r
529       if (evt.isControlDown())\r
530       {\r
531         if (evt.isAltDown())\r
532         {\r
533           invertColSel_actionPerformed();\r
534         }\r
535         else\r
536         {\r
537           invertSequenceMenuItem_actionPerformed();\r
538         }\r
539       }\r
540       break;\r
541 \r
542     case KeyEvent.VK_U:\r
543       if (evt.isControlDown())\r
544       {\r
545         this.deleteGroups_actionPerformed();\r
546       }\r
547       break;\r
548 \r
549     case KeyEvent.VK_T:\r
550       if (evt.isControlDown())\r
551       {\r
552         newView(null);\r
553       }\r
554       break;\r
555 \r
556     }\r
557     alignPanel.paintAlignment(true);\r
558   }\r
559 \r
560   /**\r
561    * called by key handler and the hide all/show all menu items\r
562    *\r
563    * @param toggleSeqs\r
564    * @param toggleCols\r
565    */\r
566   private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)\r
567   {\r
568     boolean hide = false;\r
569     SequenceGroup sg = viewport.getSelectionGroup();\r
570     if (!toggleSeqs && !toggleCols)\r
571     {\r
572       // Hide everything by the current selection - this is a hack - we do the\r
573       // invert and then hide\r
574       // first check that there will be visible columns after the invert.\r
575       if ((viewport.getColumnSelection() != null && viewport.getColumnSelection().getSelected() != null && viewport.getColumnSelection()\r
576               .getSelected().size() > 0)\r
577               || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg\r
578                       .getEndRes()))\r
579       {\r
580         // now invert the sequence set, if required - empty selection implies\r
581         // that no hiding is required.\r
582         if (sg != null)\r
583         {\r
584           invertSequenceMenuItem_actionPerformed();\r
585           sg = viewport.getSelectionGroup();\r
586           toggleSeqs = true;\r
587 \r
588         }\r
589         viewport.expandColSelection(sg, true);\r
590         // finally invert the column selection and get the new sequence\r
591         // selection and indicate it should be hidden.\r
592         invertColSel_actionPerformed();\r
593         toggleCols = true;\r
594       }\r
595     }\r
596 \r
597     if (toggleSeqs)\r
598     {\r
599       if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())\r
600       {\r
601         hide = true;\r
602         viewport.hideAllSelectedSeqs();\r
603       }\r
604       else if (!(toggleCols && viewport.getColumnSelection().getSelected().size() > 0))\r
605       {\r
606         viewport.showAllHiddenSeqs();\r
607       }\r
608     }\r
609 \r
610     if (toggleCols)\r
611     {\r
612       if (viewport.getColumnSelection().getSelected().size() > 0)\r
613       {\r
614         viewport.hideSelectedColumns();\r
615         if (!toggleSeqs)\r
616         {\r
617           viewport.setSelectionGroup(sg);\r
618         }\r
619       }\r
620       else if (!hide)\r
621       {\r
622         viewport.showAllHiddenColumns();\r
623       }\r
624     }\r
625   }\r
626 \r
627   @Override\r
628   public void keyReleased(KeyEvent evt)\r
629   {\r
630   }\r
631 \r
632   @Override\r
633   public void keyTyped(KeyEvent evt)\r
634   {\r
635   }\r
636 \r
637   @Override\r
638   public void itemStateChanged(ItemEvent evt)\r
639   {\r
640     if (evt.getSource() == displayNonconservedMenuItem)\r
641     {\r
642       displayNonconservedMenuItem_actionPerformed();\r
643     }\r
644     else if (evt.getSource() == colourTextMenuItem)\r
645     {\r
646       colourTextMenuItem_actionPerformed();\r
647     }\r
648     else if (evt.getSource() == wrapMenuItem)\r
649     {\r
650       wrapMenuItem_actionPerformed();\r
651     }\r
652     else if (evt.getSource() == scaleAbove)\r
653     {\r
654       viewport.setScaleAboveWrapped(scaleAbove.getState());\r
655     }\r
656     else if (evt.getSource() == scaleLeft)\r
657     {\r
658       viewport.setScaleLeftWrapped(scaleLeft.getState());\r
659     }\r
660     else if (evt.getSource() == scaleRight)\r
661     {\r
662       viewport.setScaleRightWrapped(scaleRight.getState());\r
663     }\r
664     else if (evt.getSource() == seqLimits)\r
665     {\r
666       seqLimits_itemStateChanged();\r
667     }\r
668     else if (evt.getSource() == viewBoxesMenuItem)\r
669     {\r
670       viewport.setShowBoxes(viewBoxesMenuItem.getState());\r
671     }\r
672     else if (evt.getSource() == viewTextMenuItem)\r
673     {\r
674       viewport.setShowText(viewTextMenuItem.getState());\r
675     }\r
676     else if (evt.getSource() == renderGapsMenuItem)\r
677     {\r
678       viewport.setRenderGaps(renderGapsMenuItem.getState());\r
679     }\r
680     else if (evt.getSource() == annotationPanelMenuItem)\r
681     {\r
682       viewport.setShowAnnotation(annotationPanelMenuItem.getState());\r
683       alignPanel.setAnnotationVisible(annotationPanelMenuItem.getState());\r
684     }\r
685     else if (evt.getSource() == sequenceFeatures)\r
686     {\r
687       viewport.showSequenceFeatures(sequenceFeatures.getState());\r
688       alignPanel.seqPanel.seqCanvas.repaint();\r
689     }\r
690     else if (evt.getSource() == conservationMenuItem)\r
691     {\r
692       conservationMenuItem_actionPerformed();\r
693     }\r
694     else if (evt.getSource() == abovePIDThreshold)\r
695     {\r
696       abovePIDThreshold_actionPerformed();\r
697     }\r
698     else if (evt.getSource() == applyToAllGroups)\r
699     {\r
700       viewport.setColourAppliesToAllGroups(applyToAllGroups.getState());\r
701     }\r
702     else if (evt.getSource() == autoCalculate)\r
703     {\r
704       viewport.autoCalculateConsensus = autoCalculate.getState();\r
705     }\r
706     else if (evt.getSource() == sortByTree)\r
707     {\r
708       viewport.sortByTree = sortByTree.getState();\r
709     }\r
710     else if (evt.getSource() == this.centreColumnLabelFlag)\r
711     {\r
712       centreColumnLabelFlag_stateChanged();\r
713     }\r
714     else if (evt.getSource() == this.followMouseOverFlag)\r
715     {\r
716       mouseOverFlag_stateChanged();\r
717     }\r
718     else if (evt.getSource() == showGroupConsensus)\r
719     {\r
720       showGroupConsensus_actionPerformed();\r
721     }\r
722     else if (evt.getSource() == showGroupConservation)\r
723     {\r
724       showGroupConservation_actionPerformed();\r
725     }\r
726     else if (evt.getSource() == showSequenceLogo)\r
727     {\r
728       showSequenceLogo_actionPerformed();\r
729     }\r
730     else if (evt.getSource() == showConsensusHistogram)\r
731     {\r
732       showConsensusHistogram_actionPerformed();\r
733     }\r
734     else if (evt.getSource() == applyAutoAnnotationSettings)\r
735     {\r
736       applyAutoAnnotationSettings_actionPerformed();\r
737     }\r
738     alignPanel.paintAlignment(true);\r
739   }\r
740 \r
741   private void mouseOverFlag_stateChanged()\r
742   {\r
743     viewport.followHighlight = followMouseOverFlag.getState();\r
744     // TODO: could kick the scrollTo mechanism to reset view for current\r
745     // searchresults.\r
746   }\r
747 \r
748   private void centreColumnLabelFlag_stateChanged()\r
749   {\r
750     viewport.centreColumnLabels = centreColumnLabelFlag.getState();\r
751     this.alignPanel.annotationPanel.repaint();\r
752   }\r
753 \r
754   @Override\r
755   public void actionPerformed(ActionEvent evt)\r
756   {\r
757     Object source = evt.getSource();\r
758 \r
759     if (source == inputText)\r
760     {\r
761       inputText_actionPerformed();\r
762     }\r
763     else if (source == loadTree)\r
764     {\r
765       loadTree_actionPerformed();\r
766     }\r
767     else if (source == loadApplication)\r
768     {\r
769       launchFullApplication();\r
770     }\r
771     else if (source == loadAnnotations)\r
772     {\r
773       loadAnnotations();\r
774     }\r
775     else if (source == outputAnnotations)\r
776     {\r
777       outputAnnotations(true);\r
778     }\r
779     else if (source == outputFeatures)\r
780     {\r
781       outputFeatures(true, "Jalview");\r
782     }\r
783     else if (source == closeMenuItem)\r
784     {\r
785       closeMenuItem_actionPerformed();\r
786     }\r
787     else if (source == copy)\r
788     {\r
789       copy_actionPerformed();\r
790     }\r
791     else if (source == undoMenuItem)\r
792     {\r
793       undoMenuItem_actionPerformed();\r
794     }\r
795     else if (source == redoMenuItem)\r
796     {\r
797       redoMenuItem_actionPerformed();\r
798     }\r
799     else if (source == inputText)\r
800     {\r
801       inputText_actionPerformed();\r
802     }\r
803     else if (source == closeMenuItem)\r
804     {\r
805       closeMenuItem_actionPerformed();\r
806     }\r
807     else if (source == undoMenuItem)\r
808     {\r
809       undoMenuItem_actionPerformed();\r
810     }\r
811     else if (source == redoMenuItem)\r
812     {\r
813       redoMenuItem_actionPerformed();\r
814     }\r
815     else if (source == copy)\r
816     {\r
817       copy_actionPerformed();\r
818     }\r
819     else if (source == pasteNew)\r
820     {\r
821       pasteNew_actionPerformed();\r
822     }\r
823     else if (source == pasteThis)\r
824     {\r
825       pasteThis_actionPerformed();\r
826     }\r
827     else if (source == cut)\r
828     {\r
829       cut_actionPerformed();\r
830     }\r
831     else if (source == delete)\r
832     {\r
833       delete_actionPerformed();\r
834     }\r
835     else if (source == grpsFromSelection)\r
836     {\r
837       makeGrpsFromSelection_actionPerformed();\r
838     }\r
839     else if (source == deleteGroups)\r
840     {\r
841       deleteGroups_actionPerformed();\r
842     }\r
843     else if (source == selectAllSequenceMenuItem)\r
844     {\r
845       selectAllSequenceMenuItem_actionPerformed();\r
846     }\r
847     else if (source == deselectAllSequenceMenuItem)\r
848     {\r
849       deselectAllSequenceMenuItem_actionPerformed();\r
850     }\r
851     else if (source == invertSequenceMenuItem)\r
852     {\r
853       invertSequenceMenuItem_actionPerformed();\r
854     }\r
855     else if (source == invertColSel)\r
856     {\r
857       viewport.invertColumnSelection();\r
858       alignPanel.paintAlignment(true);\r
859     }\r
860     else if (source == remove2LeftMenuItem)\r
861     {\r
862       trimAlignment(true);\r
863     }\r
864     else if (source == remove2RightMenuItem)\r
865     {\r
866       trimAlignment(false);\r
867     }\r
868     else if (source == removeGappedColumnMenuItem)\r
869     {\r
870       removeGappedColumnMenuItem_actionPerformed();\r
871     }\r
872     else if (source == removeAllGapsMenuItem)\r
873     {\r
874       removeAllGapsMenuItem_actionPerformed();\r
875     }\r
876     else if (source == findMenuItem)\r
877     {\r
878       findMenuItem_actionPerformed();\r
879     }\r
880     else if (source == font)\r
881     {\r
882       new FontChooser(alignPanel);\r
883     }\r
884     else if (source == newView)\r
885     {\r
886       newView(null);\r
887     }\r
888     else if (source == showColumns)\r
889     {\r
890       viewport.showAllHiddenColumns();\r
891       alignPanel.paintAlignment(true);\r
892     }\r
893     else if (source == showSeqs)\r
894     {\r
895       viewport.showAllHiddenSeqs();\r
896       alignPanel.paintAlignment(true);\r
897     }\r
898     else if (source == hideColumns)\r
899     {\r
900       viewport.hideSelectedColumns();\r
901       alignPanel.paintAlignment(true);\r
902     }\r
903     else if (source == hideSequences\r
904             && viewport.getSelectionGroup() != null)\r
905     {\r
906       viewport.hideAllSelectedSeqs();\r
907       alignPanel.paintAlignment(true);\r
908     }\r
909     else if (source == hideAllButSelection)\r
910     {\r
911       toggleHiddenRegions(false, false);\r
912       alignPanel.paintAlignment(true);\r
913     }\r
914     else if (source == hideAllSelection)\r
915     {\r
916       SequenceGroup sg = viewport.getSelectionGroup();\r
917       viewport.expandColSelection(sg, false);\r
918       viewport.hideAllSelectedSeqs();\r
919       viewport.hideSelectedColumns();\r
920       alignPanel.paintAlignment(true);\r
921     }\r
922     else if (source == showAllHidden)\r
923     {\r
924       viewport.showAllHiddenColumns();\r
925       viewport.showAllHiddenSeqs();\r
926       alignPanel.paintAlignment(true);\r
927     }\r
928     else if (source == showGroupConsensus)\r
929     {\r
930       showGroupConsensus_actionPerformed();\r
931     }\r
932     else if (source == showGroupConservation)\r
933     {\r
934       showGroupConservation_actionPerformed();\r
935     }\r
936     else if (source == showSequenceLogo)\r
937     {\r
938       showSequenceLogo_actionPerformed();\r
939     }\r
940     else if (source == showConsensusHistogram)\r
941     {\r
942       showConsensusHistogram_actionPerformed();\r
943     }\r
944     else if (source == applyAutoAnnotationSettings)\r
945     {\r
946       applyAutoAnnotationSettings_actionPerformed();\r
947     }\r
948     else if (source == featureSettings)\r
949     {\r
950       new FeatureSettings(alignPanel);\r
951     }\r
952     else if (source == alProperties)\r
953     {\r
954       StringBuffer contents = new jalview.io.AlignmentProperties(\r
955               viewport.getAlignment()).formatAsString();\r
956       CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this);\r
957       cap.setText(contents.toString());\r
958       Frame frame = new Frame();\r
959       frame.add(cap);\r
960       jalview.bin.JalviewLite.addFrame(frame, "Alignment Properties: "\r
961               + getTitle(), 400, 250);\r
962     }\r
963     else if (source == overviewMenuItem)\r
964     {\r
965       overviewMenuItem_actionPerformed();\r
966     }\r
967     else if (source == noColourmenuItem)\r
968     {\r
969       changeColour(null);\r
970     }\r
971     else if (source == clustalColour)\r
972     {\r
973       abovePIDThreshold.setState(false);\r
974       changeColour(new ClustalxColourScheme(viewport.getAlignment(),null));\r
975     }\r
976     else if (source == zappoColour)\r
977     {\r
978       changeColour(new ZappoColourScheme());\r
979     }\r
980     else if (source == taylorColour)\r
981     {\r
982       changeColour(new TaylorColourScheme());\r
983     }\r
984     else if (source == hydrophobicityColour)\r
985     {\r
986       changeColour(new HydrophobicColourScheme());\r
987     }\r
988     else if (source == helixColour)\r
989     {\r
990       changeColour(new HelixColourScheme());\r
991     }\r
992     else if (source == strandColour)\r
993     {\r
994       changeColour(new StrandColourScheme());\r
995     }\r
996     else if (source == turnColour)\r
997     {\r
998       changeColour(new TurnColourScheme());\r
999     }\r
1000     else if (source == buriedColour)\r
1001     {\r
1002       changeColour(new BuriedColourScheme());\r
1003     }\r
1004     else if (source == nucleotideColour)\r
1005     {\r
1006       changeColour(new NucleotideColourScheme());\r
1007     }\r
1008     else if (source == purinePyrimidineColour)\r
1009     {\r
1010       changeColour(new PurinePyrimidineColourScheme());\r
1011     }\r
1012     else if (source == RNAHelixColour)\r
1013     {\r
1014       new RNAHelicesColourChooser(viewport, alignPanel);\r
1015     }\r
1016     else if (source == modifyPID)\r
1017     {\r
1018       modifyPID_actionPerformed();\r
1019     }\r
1020     else if (source == modifyConservation)\r
1021     {\r
1022       modifyConservation_actionPerformed();\r
1023     }\r
1024     else if (source == userDefinedColour)\r
1025     {\r
1026       new UserDefinedColours(alignPanel, null);\r
1027     }\r
1028     else if (source == PIDColour)\r
1029     {\r
1030       changeColour(new PIDColourScheme());\r
1031     }\r
1032     else if (source == BLOSUM62Colour)\r
1033     {\r
1034       changeColour(new Blosum62ColourScheme());\r
1035     }\r
1036     else if (source == tcoffeeColour) {\r
1037         changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));\r
1038     }\r
1039     else if (source == annotationColour)\r
1040     {\r
1041       new AnnotationColourChooser(viewport, alignPanel);\r
1042     }\r
1043     else if (source == sortPairwiseMenuItem)\r
1044     {\r
1045       sortPairwiseMenuItem_actionPerformed();\r
1046     }\r
1047     else if (source == sortIDMenuItem)\r
1048     {\r
1049       sortIDMenuItem_actionPerformed();\r
1050     }\r
1051     else if (source == sortLengthMenuItem)\r
1052     {\r
1053       sortLengthMenuItem_actionPerformed();\r
1054     }\r
1055     else if (source == sortGroupMenuItem)\r
1056     {\r
1057       sortGroupMenuItem_actionPerformed();\r
1058     }\r
1059     else if (source == removeRedundancyMenuItem)\r
1060     {\r
1061       removeRedundancyMenuItem_actionPerformed();\r
1062     }\r
1063     else if (source == pairwiseAlignmentMenuItem)\r
1064     {\r
1065       pairwiseAlignmentMenuItem_actionPerformed();\r
1066     }\r
1067     else if (source == PCAMenuItem)\r
1068     {\r
1069       PCAMenuItem_actionPerformed();\r
1070     }\r
1071     else if (source == averageDistanceTreeMenuItem)\r
1072     {\r
1073       averageDistanceTreeMenuItem_actionPerformed();\r
1074     }\r
1075     else if (source == neighbourTreeMenuItem)\r
1076     {\r
1077       neighbourTreeMenuItem_actionPerformed();\r
1078     }\r
1079     else if (source == njTreeBlosumMenuItem)\r
1080     {\r
1081       njTreeBlosumMenuItem_actionPerformed();\r
1082     }\r
1083     else if (source == avDistanceTreeBlosumMenuItem)\r
1084     {\r
1085       avTreeBlosumMenuItem_actionPerformed();\r
1086     }\r
1087     else if (source == documentation)\r
1088     {\r
1089       documentation_actionPerformed();\r
1090     }\r
1091     else if (source == about)\r
1092     {\r
1093       about_actionPerformed();\r
1094     }\r
1095 \r
1096   }\r
1097 \r
1098   public void inputText_actionPerformed()\r
1099   {\r
1100     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
1101     Frame frame = new Frame();\r
1102     frame.add(cap);\r
1103     jalview.bin.JalviewLite.addFrame(frame, "Cut & Paste Input", 500, 500);\r
1104   }\r
1105 \r
1106   protected void outputText_actionPerformed(ActionEvent e)\r
1107   {\r
1108     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
1109     Frame frame = new Frame();\r
1110     frame.add(cap);\r
1111     jalview.bin.JalviewLite.addFrame(frame,\r
1112             "Alignment output - " + e.getActionCommand(), 600, 500);\r
1113     cap.setText(new AppletFormatAdapter().formatSequences(\r
1114             e.getActionCommand(), viewport.getAlignment(),\r
1115             viewport.showJVSuffix));\r
1116   }\r
1117 \r
1118   public void loadAnnotations()\r
1119   {\r
1120     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
1121     cap.setText("Paste your features / annotations / T-coffee score file here.");\r
1122     cap.setAnnotationImport();\r
1123     Frame frame = new Frame();\r
1124     frame.add(cap);\r
1125     jalview.bin.JalviewLite.addFrame(frame, "Paste Annotations ", 400, 300);\r
1126 \r
1127   }\r
1128 \r
1129   public String outputAnnotations(boolean displayTextbox)\r
1130   {\r
1131     String annotation = new AnnotationFile().printAnnotations(\r
1132             viewport.showAnnotation ? viewport.getAlignment()\r
1133                     .getAlignmentAnnotation() : null, viewport.getAlignment()\r
1134                     .getGroups(),\r
1135             ((Alignment) viewport.getAlignment()).alignmentProperties);\r
1136 \r
1137     if (displayTextbox)\r
1138     {\r
1139       CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this);\r
1140       Frame frame = new Frame();\r
1141       frame.add(cap);\r
1142       jalview.bin.JalviewLite.addFrame(frame, "Annotations", 600, 500);\r
1143       cap.setText(annotation);\r
1144     }\r
1145 \r
1146     return annotation;\r
1147   }\r
1148 \r
1149   private Hashtable getDisplayedFeatureCols()\r
1150   {\r
1151     if (alignPanel.getFeatureRenderer() != null && viewport.featuresDisplayed!=null)\r
1152     {\r
1153       FeatureRenderer fr = alignPanel.getFeatureRenderer();\r
1154       Hashtable fcols = new Hashtable();\r
1155       Enumeration en = viewport.featuresDisplayed.keys();\r
1156       while (en.hasMoreElements())\r
1157       {\r
1158         Object col = en.nextElement();\r
1159         fcols.put(col, fr.featureColours.get(col));\r
1160       }\r
1161       return fcols;\r
1162     }\r
1163     return null;\r
1164   }\r
1165 \r
1166   public String outputFeatures(boolean displayTextbox, String format)\r
1167   {\r
1168     String features;\r
1169     if (format.equalsIgnoreCase("Jalview"))\r
1170     {\r
1171       features = new FeaturesFile().printJalviewFormat(\r
1172               viewport.getAlignment().getSequencesArray(),\r
1173               getDisplayedFeatureCols());\r
1174     }\r
1175     else\r
1176     {\r
1177       features = new FeaturesFile().printGFFFormat(\r
1178               viewport.getAlignment().getSequencesArray(),\r
1179               getDisplayedFeatureCols());\r
1180     }\r
1181 \r
1182     if (displayTextbox)\r
1183     {\r
1184       boolean frimport=false;\r
1185       if (features==null || features.equals("No Features Visible"))\r
1186       {\r
1187         features = "# No features visible - paste some and import them here.";\r
1188         frimport=true;\r
1189       }\r
1190 \r
1191       CutAndPasteTransfer cap = new CutAndPasteTransfer(frimport, this);\r
1192       if (frimport)\r
1193       {\r
1194         cap.setAnnotationImport();\r
1195       }\r
1196       Frame frame = new Frame();\r
1197       frame.add(cap);\r
1198       jalview.bin.JalviewLite.addFrame(frame, "Features", 600, 500);\r
1199       cap.setText(features);\r
1200     } else {\r
1201       if (features==null)\r
1202         features = "";\r
1203     }\r
1204 \r
1205     return features;\r
1206   }\r
1207 \r
1208   void launchFullApplication()\r
1209   {\r
1210     StringBuffer url = new StringBuffer(jalviewServletURL);\r
1211 \r
1212     url.append("?open="\r
1213             + appendProtocol(viewport.applet.getParameter("file")));\r
1214 \r
1215     if (viewport.applet.getParameter("features") != null)\r
1216     {\r
1217       url.append("&features=");\r
1218       url.append(appendProtocol(viewport.applet.getParameter("features")));\r
1219     }\r
1220 \r
1221     if (viewport.applet.getParameter("annotations") != null)\r
1222     {\r
1223       url.append("&annotations=");\r
1224       url.append(appendProtocol(viewport.applet.getParameter("annotations")));\r
1225     }\r
1226 \r
1227     if (viewport.applet.getParameter("jnetfile") != null)\r
1228     {\r
1229       url.append("&annotations=");\r
1230       url.append(appendProtocol(viewport.applet.getParameter("jnetfile")));\r
1231     }\r
1232 \r
1233     if (viewport.applet.getParameter("defaultColour") != null)\r
1234     {\r
1235       url.append("&colour="\r
1236               + removeWhiteSpace(viewport.applet\r
1237                       .getParameter("defaultColour")));\r
1238     }\r
1239 \r
1240     if (viewport.applet.getParameter("userDefinedColour") != null)\r
1241     {\r
1242       url.append("&colour="\r
1243               + removeWhiteSpace(viewport.applet\r
1244                       .getParameter("userDefinedColour")));\r
1245     }\r
1246     if (viewport.applet.getParameter("tree") != null)\r
1247     {\r
1248       url.append("&tree="\r
1249               + appendProtocol(viewport.applet.getParameter("tree")));\r
1250     }\r
1251     if (viewport.applet.getParameter("treeFile") != null)\r
1252     {\r
1253       url.append("&tree="\r
1254               + appendProtocol(viewport.applet.getParameter("treeFile")));\r
1255     }\r
1256 \r
1257     showURL(url.toString(), "FULL_APP");\r
1258   }\r
1259 \r
1260   String removeWhiteSpace(String colour)\r
1261   {\r
1262     StringBuffer sb = new StringBuffer();\r
1263     for (int i = 0; i < colour.length(); i++)\r
1264     {\r
1265       if (Character.isWhitespace(colour.charAt(i)))\r
1266       {\r
1267         sb.append("%20");\r
1268       }\r
1269       else\r
1270       {\r
1271         sb.append(colour.charAt(i));\r
1272       }\r
1273     }\r
1274 \r
1275     return sb.toString();\r
1276   }\r
1277 \r
1278   String appendProtocol(String url)\r
1279   {\r
1280     try\r
1281     {\r
1282       new URL(url);\r
1283       url = URLEncoder.encode(url);\r
1284     }\r
1285     /*\r
1286      * When we finally deprecate 1.1 compatibility, we can start to use\r
1287      * URLEncoder.encode(url,"UTF-8") and then we'll need this catch: catch\r
1288      * (UnsupportedEncodingException ex) { System.err.println("WARNING -\r
1289      * IMPLEMENTATION ERROR - UNSUPPORTED ENCODING EXCEPTION FOR "+url);\r
1290      * ex.printStackTrace(); }\r
1291      */\r
1292     catch (java.net.MalformedURLException ex)\r
1293     {\r
1294       url = viewport.applet.getCodeBase() + url;\r
1295     }\r
1296     return url;\r
1297   }\r
1298 \r
1299   public void closeMenuItem_actionPerformed()\r
1300   {\r
1301     PaintRefresher.RemoveComponent(alignPanel);\r
1302     if (alignPanel.seqPanel!=null && alignPanel.seqPanel.seqCanvas!=null)\r
1303     {\r
1304       PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);\r
1305     }\r
1306     if (alignPanel.idPanel!=null && alignPanel.idPanel.idCanvas!=null) {\r
1307       PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);\r
1308     }\r
1309 \r
1310     if (PaintRefresher.components.size() == 0 && viewport.applet == null)\r
1311     {\r
1312       System.exit(0);\r
1313     } else {\r
1314     }\r
1315     viewport = null;\r
1316     alignPanel = null;\r
1317     this.dispose();\r
1318   }\r
1319 \r
1320   /**\r
1321    * TODO: JAL-1104\r
1322    */\r
1323   void updateEditMenuBar()\r
1324   {\r
1325 \r
1326     if (viewport.historyList.size() > 0)\r
1327     {\r
1328       undoMenuItem.setEnabled(true);\r
1329       CommandI command = (CommandI) viewport.historyList.peek();\r
1330       undoMenuItem.setLabel("Undo " + command.getDescription());\r
1331     }\r
1332     else\r
1333     {\r
1334       undoMenuItem.setEnabled(false);\r
1335       undoMenuItem.setLabel("Undo");\r
1336     }\r
1337 \r
1338     if (viewport.redoList.size() > 0)\r
1339     {\r
1340       redoMenuItem.setEnabled(true);\r
1341 \r
1342       CommandI command = (CommandI) viewport.redoList.peek();\r
1343       redoMenuItem.setLabel("Redo " + command.getDescription());\r
1344     }\r
1345     else\r
1346     {\r
1347       redoMenuItem.setEnabled(false);\r
1348       redoMenuItem.setLabel("Redo");\r
1349     }\r
1350   }\r
1351 \r
1352   /**\r
1353    * TODO: JAL-1104\r
1354    */\r
1355   public void addHistoryItem(CommandI command)\r
1356   {\r
1357     if (command.getSize() > 0)\r
1358     {\r
1359       viewport.historyList.push(command);\r
1360       viewport.redoList.removeAllElements();\r
1361       updateEditMenuBar();\r
1362       viewport.updateHiddenColumns();\r
1363     }\r
1364   }\r
1365 \r
1366   /**\r
1367    * TODO: JAL-1104\r
1368    * DOCUMENT ME!\r
1369    *\r
1370    * @param e\r
1371    *          DOCUMENT ME!\r
1372    */\r
1373   protected void undoMenuItem_actionPerformed()\r
1374   {\r
1375     if (viewport.historyList.size() < 1)\r
1376     {\r
1377       return;\r
1378     }\r
1379 \r
1380     CommandI command = (CommandI) viewport.historyList.pop();\r
1381     viewport.redoList.push(command);\r
1382     command.undoCommand(null);\r
1383 \r
1384     AlignViewport originalSource = getOriginatingSource(command);\r
1385     // JBPNote Test\r
1386     if (originalSource!=viewport) {\r
1387       System.err.println("Warning: Viewport object mismatch whilst undoing");\r
1388     }\r
1389     originalSource.updateHiddenColumns(); //    originalSource.hasHiddenColumns = viewport.getColumnSelection().getHiddenColumns() != null;\r
1390     updateEditMenuBar();\r
1391     originalSource.firePropertyChange("alignment", null,\r
1392             originalSource.getAlignment().getSequences());\r
1393   }\r
1394 \r
1395   /**\r
1396    * TODO: JAL-1104\r
1397    * DOCUMENT ME!\r
1398    *\r
1399    * @param e\r
1400    *          DOCUMENT ME!\r
1401    */\r
1402   protected void redoMenuItem_actionPerformed()\r
1403   {\r
1404     if (viewport.redoList.size() < 1)\r
1405     {\r
1406       return;\r
1407     }\r
1408 \r
1409     CommandI command = (CommandI) viewport.redoList.pop();\r
1410     viewport.historyList.push(command);\r
1411     command.doCommand(null);\r
1412 \r
1413     AlignViewport originalSource = getOriginatingSource(command);\r
1414     // JBPNote Test\r
1415     if (originalSource!=viewport) {\r
1416       System.err.println("Warning: Viewport object mismatch whilst re-doing");\r
1417     }\r
1418     originalSource.updateHiddenColumns(); //sethasHiddenColumns(); = viewport.getColumnSelection().getHiddenColumns() != null;\r
1419 \r
1420     updateEditMenuBar();\r
1421     originalSource.firePropertyChange("alignment", null,\r
1422             originalSource.getAlignment().getSequences());\r
1423   }\r
1424 \r
1425   AlignViewport getOriginatingSource(CommandI command)\r
1426   {\r
1427     AlignViewport originalSource = null;\r
1428     // For sequence removal and addition, we need to fire\r
1429     // the property change event FROM the viewport where the\r
1430     // original alignment was altered\r
1431     AlignmentI al = null;\r
1432     if (command instanceof EditCommand)\r
1433     {\r
1434       EditCommand editCommand = (EditCommand) command;\r
1435       al = editCommand.getAlignment();\r
1436       Vector comps = (Vector) PaintRefresher.components.get(viewport\r
1437               .getSequenceSetId());\r
1438       for (int i = 0; i < comps.size(); i++)\r
1439       {\r
1440         if (comps.elementAt(i) instanceof AlignmentPanel)\r
1441         {\r
1442           if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())\r
1443           {\r
1444             originalSource = ((AlignmentPanel) comps.elementAt(i)).av;\r
1445             break;\r
1446           }\r
1447         }\r
1448       }\r
1449     }\r
1450 \r
1451     if (originalSource == null)\r
1452     {\r
1453       // The original view is closed, we must validate\r
1454       // the current view against the closed view first\r
1455       if (al != null)\r
1456       {\r
1457         PaintRefresher.validateSequences(al, viewport.getAlignment());\r
1458       }\r
1459 \r
1460       originalSource = viewport;\r
1461     }\r
1462 \r
1463     return originalSource;\r
1464   }\r
1465 \r
1466   public void moveSelectedSequences(boolean up)\r
1467   {\r
1468     SequenceGroup sg = viewport.getSelectionGroup();\r
1469     if (sg == null)\r
1470     {\r
1471       return;\r
1472     }\r
1473     viewport.getAlignment().moveSelectedSequencesByOne(sg, up ? null : viewport.getHiddenRepSequences(), up);\r
1474     alignPanel.paintAlignment(true);\r
1475   }\r
1476 \r
1477   synchronized void slideSequences(boolean right, int size)\r
1478   {\r
1479     List<SequenceI>sg = new Vector<SequenceI>();\r
1480     if (viewport.cursorMode)\r
1481     {\r
1482       sg.add(viewport.getAlignment()\r
1483               .getSequenceAt(alignPanel.seqPanel.seqCanvas.cursorY));\r
1484     }\r
1485     else if (viewport.getSelectionGroup() != null\r
1486             && viewport.getSelectionGroup().getSize() != viewport.getAlignment()\r
1487                     .getHeight())\r
1488     {\r
1489       sg = viewport.getSelectionGroup().getSequences(\r
1490               viewport.getHiddenRepSequences());\r
1491     }\r
1492 \r
1493     if (sg.size() < 1)\r
1494     {\r
1495       return;\r
1496     }\r
1497 \r
1498     Vector<SequenceI> invertGroup = new Vector();\r
1499 \r
1500     for (int i = 0; i < viewport.getAlignment().getHeight(); i++)\r
1501     {\r
1502       if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))\r
1503         invertGroup.addElement(viewport.getAlignment().getSequenceAt(i));\r
1504     }\r
1505 \r
1506     SequenceI[] seqs1 = sg.toArray(new SequenceI[sg.size()]);\r
1507 \r
1508     SequenceI[] seqs2 = invertGroup.toArray(new SequenceI[invertGroup.size()]);\r
1509     for (int i = 0; i < invertGroup.size(); i++)\r
1510       seqs2[i] = invertGroup.elementAt(i);\r
1511 \r
1512     SlideSequencesCommand ssc;\r
1513     if (right)\r
1514       ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,\r
1515               size, viewport.getGapCharacter());\r
1516     else\r
1517       ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,\r
1518               size, viewport.getGapCharacter());\r
1519 \r
1520     int groupAdjustment = 0;\r
1521     if (ssc.getGapsInsertedBegin() && right)\r
1522     {\r
1523       if (viewport.cursorMode)\r
1524         alignPanel.seqPanel.moveCursor(size, 0);\r
1525       else\r
1526         groupAdjustment = size;\r
1527     }\r
1528     else if (!ssc.getGapsInsertedBegin() && !right)\r
1529     {\r
1530       if (viewport.cursorMode)\r
1531         alignPanel.seqPanel.moveCursor(-size, 0);\r
1532       else\r
1533         groupAdjustment = -size;\r
1534     }\r
1535 \r
1536     if (groupAdjustment != 0)\r
1537     {\r
1538       viewport.getSelectionGroup().setStartRes(\r
1539               viewport.getSelectionGroup().getStartRes() + groupAdjustment);\r
1540       viewport.getSelectionGroup().setEndRes(\r
1541               viewport.getSelectionGroup().getEndRes() + groupAdjustment);\r
1542     }\r
1543 \r
1544     boolean appendHistoryItem = false;\r
1545     if (viewport.historyList != null && viewport.historyList.size() > 0\r
1546             && viewport.historyList.peek() instanceof SlideSequencesCommand)\r
1547     {\r
1548       appendHistoryItem = ssc\r
1549               .appendSlideCommand((SlideSequencesCommand) viewport.historyList\r
1550                       .peek());\r
1551     }\r
1552 \r
1553     if (!appendHistoryItem)\r
1554       addHistoryItem(ssc);\r
1555 \r
1556     repaint();\r
1557   }\r
1558 \r
1559   static StringBuffer copiedSequences;\r
1560 \r
1561   static Vector copiedHiddenColumns;\r
1562 \r
1563   protected void copy_actionPerformed()\r
1564   {\r
1565     if (viewport.getSelectionGroup() == null)\r
1566     {\r
1567       return;\r
1568     }\r
1569 \r
1570     SequenceGroup sg = viewport.getSelectionGroup();\r
1571     copiedSequences = new StringBuffer();\r
1572     Hashtable orderedSeqs = new Hashtable();\r
1573     for (int i = 0; i < sg.getSize(); i++)\r
1574     {\r
1575       SequenceI seq = sg.getSequenceAt(i);\r
1576       int index = viewport.getAlignment().findIndex(seq);\r
1577       orderedSeqs.put(index + "", seq);\r
1578     }\r
1579 \r
1580     int index = 0, startRes, endRes;\r
1581     char ch;\r
1582 \r
1583     if (viewport.hasHiddenColumns() && viewport.getSelectionGroup() != null)\r
1584     {\r
1585       copiedHiddenColumns = new Vector();\r
1586       int hiddenOffset = viewport.getSelectionGroup().getStartRes();\r
1587       for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns()\r
1588               .size(); i++)\r
1589       {\r
1590         int[] region = (int[]) viewport.getColumnSelection()\r
1591                 .getHiddenColumns().elementAt(i);\r
1592 \r
1593         copiedHiddenColumns.addElement(new int[]\r
1594         { region[0] - hiddenOffset, region[1] - hiddenOffset });\r
1595       }\r
1596     }\r
1597     else\r
1598     {\r
1599       copiedHiddenColumns = null;\r
1600     }\r
1601 \r
1602     for (int i = 0; i < sg.getSize(); i++)\r
1603     {\r
1604       SequenceI seq = null;\r
1605 \r
1606       while (seq == null)\r
1607       {\r
1608         if (orderedSeqs.containsKey(index + ""))\r
1609         {\r
1610           seq = (SequenceI) orderedSeqs.get(index + "");\r
1611           index++;\r
1612 \r
1613           break;\r
1614         }\r
1615         else\r
1616         {\r
1617           index++;\r
1618         }\r
1619       }\r
1620 \r
1621       // FIND START RES\r
1622       // Returns residue following index if gap\r
1623       startRes = seq.findPosition(sg.getStartRes());\r
1624 \r
1625       // FIND END RES\r
1626       // Need to find the residue preceeding index if gap\r
1627       endRes = 0;\r
1628 \r
1629       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)\r
1630       {\r
1631         ch = seq.getCharAt(j);\r
1632         if (!jalview.util.Comparison.isGap((ch)))\r
1633         {\r
1634           endRes++;\r
1635         }\r
1636       }\r
1637 \r
1638       if (endRes > 0)\r
1639       {\r
1640         endRes += seq.getStart() - 1;\r
1641       }\r
1642 \r
1643       copiedSequences.append(seq.getName()\r
1644               + "\t"\r
1645               + startRes\r
1646               + "\t"\r
1647               + endRes\r
1648               + "\t"\r
1649               + seq.getSequenceAsString(sg.getStartRes(),\r
1650                       sg.getEndRes() + 1) + "\n");\r
1651     }\r
1652 \r
1653   }\r
1654 \r
1655   protected void pasteNew_actionPerformed()\r
1656   {\r
1657     paste(true);\r
1658   }\r
1659 \r
1660   protected void pasteThis_actionPerformed()\r
1661   {\r
1662     paste(false);\r
1663   }\r
1664 \r
1665   void paste(boolean newAlignment)\r
1666   {\r
1667     try\r
1668     {\r
1669 \r
1670       if (copiedSequences == null)\r
1671       {\r
1672         return;\r
1673       }\r
1674 \r
1675       StringTokenizer st = new StringTokenizer(copiedSequences.toString());\r
1676       Vector seqs = new Vector();\r
1677       while (st.hasMoreElements())\r
1678       {\r
1679         String name = st.nextToken();\r
1680         int start = Integer.parseInt(st.nextToken());\r
1681         int end = Integer.parseInt(st.nextToken());\r
1682         seqs.addElement(new Sequence(name, st.nextToken(), start, end));\r
1683       }\r
1684       SequenceI[] newSeqs = new SequenceI[seqs.size()];\r
1685       for (int i = 0; i < seqs.size(); i++)\r
1686       {\r
1687         newSeqs[i] = (SequenceI) seqs.elementAt(i);\r
1688       }\r
1689 \r
1690       if (newAlignment)\r
1691       {\r
1692         String newtitle = new String("Copied sequences");\r
1693         if (getTitle().startsWith("Copied sequences"))\r
1694         {\r
1695           newtitle = getTitle();\r
1696         }\r
1697         else\r
1698         {\r
1699           newtitle = newtitle.concat("- from " + getTitle());\r
1700         }\r
1701         AlignFrame af = new AlignFrame(new Alignment(newSeqs),\r
1702                 viewport.applet, newtitle, false);\r
1703         if (copiedHiddenColumns != null)\r
1704         {\r
1705           for (int i = 0; i < copiedHiddenColumns.size(); i++)\r
1706           {\r
1707             int[] region = (int[]) copiedHiddenColumns.elementAt(i);\r
1708             af.viewport.hideColumns(region[0], region[1]);\r
1709           }\r
1710         }\r
1711 \r
1712         jalview.bin.JalviewLite.addFrame(af, newtitle, DEFAULT_WIDTH,\r
1713                 DEFAULT_HEIGHT);\r
1714       }\r
1715       else\r
1716       {\r
1717         addSequences(newSeqs);\r
1718       }\r
1719 \r
1720     } catch (Exception ex)\r
1721     {\r
1722     } // could be anything being pasted in here\r
1723 \r
1724   }\r
1725 \r
1726   void addSequences(SequenceI[] seqs)\r
1727   {\r
1728     for (int i = 0; i < seqs.length; i++)\r
1729     {\r
1730       viewport.getAlignment().addSequence(seqs[i]);\r
1731     }\r
1732 \r
1733     // !newAlignment\r
1734     addHistoryItem(new EditCommand("Add sequences", EditCommand.PASTE,\r
1735             seqs, 0, viewport.getAlignment().getWidth(), viewport.getAlignment()));\r
1736 \r
1737     viewport.setEndSeq(viewport.getAlignment().getHeight());\r
1738     viewport.getAlignment().getWidth();\r
1739     viewport.firePropertyChange("alignment", null,\r
1740             viewport.getAlignment().getSequences());\r
1741 \r
1742   }\r
1743 \r
1744   protected void cut_actionPerformed()\r
1745   {\r
1746     copy_actionPerformed();\r
1747     delete_actionPerformed();\r
1748   }\r
1749 \r
1750   protected void delete_actionPerformed()\r
1751   {\r
1752 \r
1753     SequenceGroup sg = viewport.getSelectionGroup();\r
1754     if (sg == null)\r
1755     {\r
1756       return;\r
1757     }\r
1758 \r
1759     Vector seqs = new Vector();\r
1760     SequenceI seq;\r
1761     for (int i = 0; i < sg.getSize(); i++)\r
1762     {\r
1763       seq = sg.getSequenceAt(i);\r
1764       seqs.addElement(seq);\r
1765     }\r
1766 \r
1767     // If the cut affects all sequences, remove highlighted columns\r
1768     if (sg.getSize() == viewport.getAlignment().getHeight())\r
1769     {\r
1770       viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
1771               sg.getEndRes() + 1);\r
1772     }\r
1773 \r
1774     SequenceI[] cut = new SequenceI[seqs.size()];\r
1775     for (int i = 0; i < seqs.size(); i++)\r
1776     {\r
1777       cut[i] = (SequenceI) seqs.elementAt(i);\r
1778     }\r
1779 \r
1780     /*\r
1781      * //ADD HISTORY ITEM\r
1782      */\r
1783     addHistoryItem(new EditCommand("Cut Sequences", EditCommand.CUT, cut,\r
1784             sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,\r
1785             viewport.getAlignment()));\r
1786 \r
1787     viewport.setSelectionGroup(null);\r
1788     viewport.getAlignment().deleteGroup(sg);\r
1789 \r
1790     viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
1791             .getSequences());\r
1792 \r
1793     if (viewport.getAlignment().getHeight() < 1)\r
1794     {\r
1795       this.setVisible(false);\r
1796     }\r
1797     viewport.sendSelection();\r
1798   }\r
1799 \r
1800   /**\r
1801    * group consensus toggled\r
1802    *\r
1803    */\r
1804   protected void showGroupConsensus_actionPerformed()\r
1805   {\r
1806     viewport.setShowGroupConsensus(showGroupConsensus.getState());\r
1807     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
1808 \r
1809   }\r
1810 \r
1811   /**\r
1812    * group conservation toggled.\r
1813    */\r
1814   protected void showGroupConservation_actionPerformed()\r
1815   {\r
1816     viewport.setShowGroupConservation(showGroupConservation.getState());\r
1817     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
1818   }\r
1819 \r
1820   /*\r
1821    * (non-Javadoc)\r
1822    *\r
1823    * @see\r
1824    * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt\r
1825    * .event.ActionEvent)\r
1826    */\r
1827   protected void showConsensusHistogram_actionPerformed()\r
1828   {\r
1829     viewport.setShowConsensusHistogram(showConsensusHistogram.getState());\r
1830     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
1831   }\r
1832   /*\r
1833    * (non-Javadoc)\r
1834    *\r
1835    * @see\r
1836    * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt\r
1837    * .event.ActionEvent)\r
1838    */\r
1839   protected void showSequenceLogo_actionPerformed()\r
1840   {\r
1841     viewport.setShowSequenceLogo(showSequenceLogo.getState());\r
1842     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
1843   }\r
1844 \r
1845   protected void applyAutoAnnotationSettings_actionPerformed()\r
1846   {\r
1847     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
1848   }\r
1849 \r
1850   protected void makeGrpsFromSelection_actionPerformed()\r
1851   {\r
1852     if (viewport.getSelectionGroup() != null)\r
1853     {\r
1854       SequenceGroup[] gps = jalview.analysis.Grouping.makeGroupsFrom(\r
1855               viewport.getSequenceSelection(),\r
1856               viewport.getAlignmentView(true).getSequenceStrings(\r
1857                       viewport.getGapCharacter()),\r
1858               viewport.getAlignment().getGroups());\r
1859       viewport.getAlignment().deleteAllGroups();\r
1860       viewport.sequenceColours = null;\r
1861       viewport.setSelectionGroup(null);\r
1862       // set view properties for each group\r
1863       for (int g = 0; g < gps.length; g++)\r
1864       {\r
1865         // gps[g].setShowunconserved(viewport.getShowUnconserved());\r
1866         gps[g].setshowSequenceLogo(viewport.isShowSequenceLogo());\r
1867         viewport.getAlignment().addGroup(gps[g]);\r
1868         Color col = new Color((int) (Math.random() * 255),\r
1869                 (int) (Math.random() * 255), (int) (Math.random() * 255));\r
1870         col = col.brighter();\r
1871         for (SequenceI sq : gps[g].getSequences(null))\r
1872           viewport.setSequenceColour(\r
1873                 sq, col)\r
1874           ;\r
1875       }\r
1876       PaintRefresher.Refresh(this, viewport.getSequenceSetId());\r
1877       alignPanel.updateAnnotation();\r
1878       alignPanel.paintAlignment(true);\r
1879     }\r
1880   }\r
1881 \r
1882   protected void deleteGroups_actionPerformed()\r
1883   {\r
1884     viewport.getAlignment().deleteAllGroups();\r
1885     viewport.sequenceColours = null;\r
1886     viewport.setSelectionGroup(null);\r
1887 \r
1888     alignPanel.paintAlignment(true);\r
1889   }\r
1890 \r
1891   public void selectAllSequenceMenuItem_actionPerformed()\r
1892   {\r
1893     SequenceGroup sg = new SequenceGroup();\r
1894     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
1895     {\r
1896       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
1897     }\r
1898     sg.setEndRes(viewport.getAlignment().getWidth() - 1);\r
1899     viewport.setSelectionGroup(sg);\r
1900     alignPanel.paintAlignment(true);\r
1901     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
1902     viewport.sendSelection();\r
1903   }\r
1904 \r
1905   public void deselectAllSequenceMenuItem_actionPerformed()\r
1906   {\r
1907     if (viewport.cursorMode)\r
1908     {\r
1909       alignPanel.seqPanel.keyboardNo1 = null;\r
1910       alignPanel.seqPanel.keyboardNo2 = null;\r
1911     }\r
1912     viewport.setSelectionGroup(null);\r
1913     viewport.getColumnSelection().clear();\r
1914     viewport.setSelectionGroup(null);\r
1915     alignPanel.idPanel.idCanvas.searchResults = null;\r
1916     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);\r
1917     alignPanel.paintAlignment(true);\r
1918     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
1919     viewport.sendSelection();\r
1920   }\r
1921 \r
1922   public void invertSequenceMenuItem_actionPerformed()\r
1923   {\r
1924     SequenceGroup sg = viewport.getSelectionGroup();\r
1925     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
1926     {\r
1927       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
1928     }\r
1929 \r
1930     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
1931     viewport.sendSelection();\r
1932   }\r
1933 \r
1934   public void invertColSel_actionPerformed()\r
1935   {\r
1936     viewport.invertColumnSelection();\r
1937     alignPanel.paintAlignment(true);\r
1938     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
1939     viewport.sendSelection();\r
1940   }\r
1941 \r
1942   void trimAlignment(boolean trimLeft)\r
1943   {\r
1944     ColumnSelection colSel = viewport.getColumnSelection();\r
1945     int column;\r
1946 \r
1947     if (colSel.size() > 0)\r
1948     {\r
1949       if (trimLeft)\r
1950       {\r
1951         column = colSel.getMin();\r
1952       }\r
1953       else\r
1954       {\r
1955         column = colSel.getMax();\r
1956       }\r
1957 \r
1958       SequenceI[] seqs;\r
1959       if (viewport.getSelectionGroup() != null)\r
1960       {\r
1961         seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
1962                 viewport.getHiddenRepSequences());\r
1963       }\r
1964       else\r
1965       {\r
1966         seqs = viewport.getAlignment().getSequencesArray();\r
1967       }\r
1968 \r
1969       TrimRegionCommand trimRegion;\r
1970       if (trimLeft)\r
1971       {\r
1972         trimRegion = new TrimRegionCommand("Remove Left",\r
1973                 TrimRegionCommand.TRIM_LEFT, seqs, column,\r
1974                 viewport.getAlignment(), viewport.getColumnSelection(),\r
1975                 viewport.getSelectionGroup());\r
1976         viewport.setStartRes(0);\r
1977       }\r
1978       else\r
1979       {\r
1980         trimRegion = new TrimRegionCommand("Remove Right",\r
1981                 TrimRegionCommand.TRIM_RIGHT, seqs, column,\r
1982                 viewport.getAlignment(), viewport.getColumnSelection(),\r
1983                 viewport.getSelectionGroup());\r
1984       }\r
1985 \r
1986       statusBar.setText("Removed " + trimRegion.getSize() + " columns.");\r
1987 \r
1988       addHistoryItem(trimRegion);\r
1989 \r
1990 \r
1991 \r
1992       for (SequenceGroup sg:viewport.getAlignment().getGroups())\r
1993       {\r
1994         if ((trimLeft && !sg.adjustForRemoveLeft(column))\r
1995                 || (!trimLeft && !sg.adjustForRemoveRight(column)))\r
1996         {\r
1997           viewport.getAlignment().deleteGroup(sg);\r
1998         }\r
1999       }\r
2000 \r
2001       viewport.firePropertyChange("alignment", null, viewport\r
2002               .getAlignment().getSequences());\r
2003     }\r
2004   }\r
2005 \r
2006   public void removeGappedColumnMenuItem_actionPerformed()\r
2007   {\r
2008     int start = 0, end = viewport.getAlignment().getWidth() - 1;\r
2009 \r
2010     SequenceI[] seqs;\r
2011     if (viewport.getSelectionGroup() != null)\r
2012     {\r
2013       seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
2014               viewport.getHiddenRepSequences());\r
2015       start = viewport.getSelectionGroup().getStartRes();\r
2016       end = viewport.getSelectionGroup().getEndRes();\r
2017     }\r
2018     else\r
2019     {\r
2020       seqs = viewport.getAlignment().getSequencesArray();\r
2021     }\r
2022 \r
2023     RemoveGapColCommand removeGapCols = new RemoveGapColCommand(\r
2024             "Remove Gapped Columns", seqs, start, end, viewport.getAlignment());\r
2025 \r
2026     addHistoryItem(removeGapCols);\r
2027 \r
2028     statusBar.setText("Removed " + removeGapCols.getSize()\r
2029             + " empty columns.");\r
2030 \r
2031     // This is to maintain viewport position on first residue\r
2032     // of first sequence\r
2033     SequenceI seq = viewport.getAlignment().getSequenceAt(0);\r
2034     int startRes = seq.findPosition(viewport.startRes);\r
2035     // ShiftList shifts;\r
2036     // viewport.getAlignment().removeGaps(shifts=new ShiftList());\r
2037     // edit.alColumnChanges=shifts.getInverse();\r
2038     // if (viewport.hasHiddenColumns)\r
2039     // viewport.getColumnSelection().compensateForEdits(shifts);\r
2040     viewport.setStartRes(seq.findIndex(startRes) - 1);\r
2041     viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
2042             .getSequences());\r
2043 \r
2044   }\r
2045 \r
2046   public void removeAllGapsMenuItem_actionPerformed()\r
2047   {\r
2048     int start = 0, end = viewport.getAlignment().getWidth() - 1;\r
2049 \r
2050     SequenceI[] seqs;\r
2051     if (viewport.getSelectionGroup() != null)\r
2052     {\r
2053       seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
2054               viewport.getHiddenRepSequences());\r
2055       start = viewport.getSelectionGroup().getStartRes();\r
2056       end = viewport.getSelectionGroup().getEndRes();\r
2057     }\r
2058     else\r
2059     {\r
2060       seqs = viewport.getAlignment().getSequencesArray();\r
2061     }\r
2062 \r
2063     // This is to maintain viewport position on first residue\r
2064     // of first sequence\r
2065     SequenceI seq = viewport.getAlignment().getSequenceAt(0);\r
2066     int startRes = seq.findPosition(viewport.startRes);\r
2067 \r
2068     addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,\r
2069             viewport.getAlignment()));\r
2070 \r
2071     viewport.setStartRes(seq.findIndex(startRes) - 1);\r
2072 \r
2073     viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
2074             .getSequences());\r
2075 \r
2076   }\r
2077 \r
2078   public void findMenuItem_actionPerformed()\r
2079   {\r
2080     new Finder(alignPanel);\r
2081   }\r
2082 \r
2083   /**\r
2084    * create a new view derived from the current view\r
2085    *\r
2086    * @param viewtitle\r
2087    * @return frame for the new view\r
2088    */\r
2089   public AlignFrame newView(String viewtitle)\r
2090   {\r
2091     AlignmentI newal;\r
2092     if (viewport.hasHiddenRows())\r
2093     {\r
2094       newal = new Alignment(viewport.getAlignment().getHiddenSequences()\r
2095               .getFullAlignment().getSequencesArray());\r
2096     }\r
2097     else\r
2098     {\r
2099       newal = new Alignment(viewport.getAlignment().getSequencesArray());\r
2100     }\r
2101 \r
2102     if (viewport.getAlignment().getAlignmentAnnotation() != null)\r
2103     {\r
2104       for (int i = 0; i < viewport.getAlignment().getAlignmentAnnotation().length; i++)\r
2105       {\r
2106         if (!viewport.getAlignment().getAlignmentAnnotation()[i].autoCalculated)\r
2107         {\r
2108           newal.addAnnotation(viewport.getAlignment().getAlignmentAnnotation()[i]);\r
2109         }\r
2110       }\r
2111     }\r
2112 \r
2113     AlignFrame newaf = new AlignFrame(newal, viewport.applet, "", false);\r
2114 \r
2115     newaf.viewport.setSequenceSetId(alignPanel.av.getSequenceSetId());\r
2116     PaintRefresher.Register(alignPanel, alignPanel.av.getSequenceSetId());\r
2117     PaintRefresher.Register(newaf.alignPanel,\r
2118             newaf.alignPanel.av.getSequenceSetId());\r
2119 \r
2120     PaintRefresher.Register(newaf.alignPanel.idPanel.idCanvas,\r
2121             newaf.alignPanel.av.getSequenceSetId());\r
2122     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,\r
2123             newaf.alignPanel.av.getSequenceSetId());\r
2124 \r
2125     Vector comps = (Vector) PaintRefresher.components.get(viewport\r
2126             .getSequenceSetId());\r
2127     int viewSize = -1;\r
2128     for (int i = 0; i < comps.size(); i++)\r
2129     {\r
2130       if (comps.elementAt(i) instanceof AlignmentPanel)\r
2131       {\r
2132         viewSize++;\r
2133       }\r
2134     }\r
2135 \r
2136     String title = new String(this.getTitle());\r
2137     if (viewtitle != null)\r
2138     {\r
2139       title = viewtitle + " ( " + title + ")";\r
2140     }\r
2141     else\r
2142     {\r
2143       if (title.indexOf("(View") > -1)\r
2144       {\r
2145         title = title.substring(0, title.indexOf("(View"));\r
2146       }\r
2147       title += "(View " + viewSize + ")";\r
2148     }\r
2149 \r
2150     newaf.setTitle(title.toString());\r
2151 \r
2152     newaf.viewport.historyList = viewport.historyList;\r
2153     newaf.viewport.redoList = viewport.redoList;\r
2154     return newaf;\r
2155   }\r
2156 \r
2157   /**\r
2158    *\r
2159    * @return list of feature groups on the view\r
2160    */\r
2161   public String[] getFeatureGroups()\r
2162   {\r
2163     FeatureRenderer fr = null;\r
2164     if (alignPanel != null\r
2165             && (fr = alignPanel.getFeatureRenderer()) != null)\r
2166     {\r
2167       return fr.getGroups();\r
2168     }\r
2169     return null;\r
2170   }\r
2171 \r
2172   /**\r
2173    * get sequence feature groups that are hidden or shown\r
2174    *\r
2175    * @param visible\r
2176    *          true is visible\r
2177    * @return list\r
2178    */\r
2179   public String[] getFeatureGroupsOfState(boolean visible)\r
2180   {\r
2181     FeatureRenderer fr = null;\r
2182     if (alignPanel != null\r
2183             && (fr = alignPanel.getFeatureRenderer()) != null)\r
2184     {\r
2185       return fr.getGroups(visible);\r
2186     }\r
2187     return null;\r
2188   }\r
2189 \r
2190   /**\r
2191    * Change the display state for the given feature groups\r
2192    *\r
2193    * @param groups\r
2194    *          list of group strings\r
2195    * @param state\r
2196    *          visible or invisible\r
2197    */\r
2198   public void setFeatureGroupState(String[] groups, boolean state)\r
2199   {\r
2200     FeatureRenderer fr = null;\r
2201     this.sequenceFeatures.setState(true);\r
2202     viewport.showSequenceFeatures(true);\r
2203     if (alignPanel != null\r
2204             && (fr = alignPanel.getFeatureRenderer()) != null)\r
2205     {\r
2206       fr.setGroupState(groups, state);\r
2207       alignPanel.seqPanel.seqCanvas.repaint();\r
2208       if (alignPanel.overviewPanel != null)\r
2209       {\r
2210         alignPanel.overviewPanel.updateOverviewImage();\r
2211       }\r
2212     }\r
2213   }\r
2214 \r
2215   public void seqLimits_itemStateChanged()\r
2216   {\r
2217     viewport.setShowJVSuffix(seqLimits.getState());\r
2218     alignPanel.fontChanged();\r
2219     alignPanel.paintAlignment(true);\r
2220   }\r
2221 \r
2222   protected void colourTextMenuItem_actionPerformed()\r
2223   {\r
2224     viewport.setColourText(colourTextMenuItem.getState());\r
2225     alignPanel.paintAlignment(true);\r
2226   }\r
2227 \r
2228   protected void displayNonconservedMenuItem_actionPerformed()\r
2229   {\r
2230     viewport.setShowunconserved(displayNonconservedMenuItem.getState());\r
2231     alignPanel.paintAlignment(true);\r
2232   }\r
2233 \r
2234   protected void wrapMenuItem_actionPerformed()\r
2235   {\r
2236     viewport.setWrapAlignment(wrapMenuItem.getState());\r
2237     alignPanel.setWrapAlignment(wrapMenuItem.getState());\r
2238     scaleAbove.setEnabled(wrapMenuItem.getState());\r
2239     scaleLeft.setEnabled(wrapMenuItem.getState());\r
2240     scaleRight.setEnabled(wrapMenuItem.getState());\r
2241     alignPanel.paintAlignment(true);\r
2242   }\r
2243 \r
2244   public void overviewMenuItem_actionPerformed()\r
2245   {\r
2246     if (alignPanel.overviewPanel != null)\r
2247     {\r
2248       return;\r
2249     }\r
2250 \r
2251     Frame frame = new Frame();\r
2252     OverviewPanel overview = new OverviewPanel(alignPanel);\r
2253     frame.add(overview);\r
2254     // +50 must allow for applet frame window\r
2255     jalview.bin.JalviewLite.addFrame(frame, "Overview " + this.getTitle(),\r
2256             overview.getPreferredSize().width,\r
2257             overview.getPreferredSize().height + 50);\r
2258 \r
2259     frame.pack();\r
2260     final AlignmentPanel ap=alignPanel;\r
2261     frame.addWindowListener(new WindowAdapter()\r
2262     {\r
2263       @Override\r
2264       public void windowClosing(WindowEvent e)\r
2265       {\r
2266         if (ap!=null) {\r
2267           ap.setOverviewPanel(null);\r
2268         }\r
2269       };\r
2270     });\r
2271 \r
2272     alignPanel.setOverviewPanel(overview);\r
2273 \r
2274   }\r
2275 \r
2276   void changeColour(ColourSchemeI cs)\r
2277   {\r
2278     int threshold = 0;\r
2279 \r
2280     if (cs != null)\r
2281     {\r
2282       if (viewport.getAbovePIDThreshold())\r
2283       {\r
2284         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,\r
2285                 "Background");\r
2286 \r
2287         cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
2288 \r
2289         viewport.setGlobalColourScheme(cs);\r
2290       }\r
2291       else\r
2292       {\r
2293         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
2294       }\r
2295 \r
2296       if (viewport.getConservationSelected())\r
2297       {\r
2298 \r
2299         Alignment al = (Alignment) viewport.getAlignment();\r
2300         Conservation c = new Conservation("All",\r
2301                 ResidueProperties.propHash, 3, al.getSequences(), 0,\r
2302                 al.getWidth() - 1);\r
2303 \r
2304         c.calculate();\r
2305         c.verdict(false, viewport.getConsPercGaps());\r
2306 \r
2307         cs.setConservation(c);\r
2308 \r
2309         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,\r
2310                 cs, "Background"));\r
2311 \r
2312       }\r
2313       else\r
2314       {\r
2315         cs.setConservation(null);\r
2316       }\r
2317 \r
2318       cs.setConsensus(viewport.getSequenceConsensusHash());\r
2319 \r
2320     }\r
2321     viewport.setGlobalColourScheme(cs);\r
2322 \r
2323 \r
2324     if (alignPanel.getOverviewPanel() != null)\r
2325     {\r
2326       alignPanel.getOverviewPanel().updateOverviewImage();\r
2327     }\r
2328 \r
2329     jalview.structure.StructureSelectionManager\r
2330             .getStructureSelectionManager(viewport.applet).sequenceColoursChanged(\r
2331                     alignPanel);\r
2332 \r
2333     alignPanel.paintAlignment(true);\r
2334   }\r
2335 \r
2336   protected void modifyPID_actionPerformed()\r
2337   {\r
2338     if (viewport.getAbovePIDThreshold()\r
2339             && viewport.getGlobalColourScheme() != null)\r
2340     {\r
2341       SliderPanel.setPIDSliderSource(alignPanel,\r
2342               viewport.getGlobalColourScheme(), "Background");\r
2343       SliderPanel.showPIDSlider();\r
2344     }\r
2345   }\r
2346 \r
2347   protected void modifyConservation_actionPerformed()\r
2348   {\r
2349     if (viewport.getConservationSelected()\r
2350             && viewport.getGlobalColourScheme() != null)\r
2351     {\r
2352       SliderPanel.setConservationSlider(alignPanel,\r
2353               viewport.getGlobalColourScheme(), "Background");\r
2354       SliderPanel.showConservationSlider();\r
2355     }\r
2356   }\r
2357 \r
2358   protected void conservationMenuItem_actionPerformed()\r
2359   {\r
2360     viewport.setConservationSelected(conservationMenuItem.getState());\r
2361 \r
2362     viewport.setAbovePIDThreshold(false);\r
2363     abovePIDThreshold.setState(false);\r
2364 \r
2365     changeColour(viewport.getGlobalColourScheme());\r
2366 \r
2367     modifyConservation_actionPerformed();\r
2368   }\r
2369 \r
2370   public void abovePIDThreshold_actionPerformed()\r
2371   {\r
2372     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());\r
2373 \r
2374     conservationMenuItem.setState(false);\r
2375     viewport.setConservationSelected(false);\r
2376 \r
2377     changeColour(viewport.getGlobalColourScheme());\r
2378 \r
2379     modifyPID_actionPerformed();\r
2380   }\r
2381 \r
2382   public void sortPairwiseMenuItem_actionPerformed()\r
2383   {\r
2384     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
2385     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport\r
2386             .getAlignment().getSequenceAt(0), null);\r
2387 \r
2388     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,\r
2389             viewport.getAlignment()));\r
2390     alignPanel.paintAlignment(true);\r
2391   }\r
2392 \r
2393   public void sortIDMenuItem_actionPerformed()\r
2394   {\r
2395     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
2396     AlignmentSorter.sortByID(viewport.getAlignment());\r
2397     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));\r
2398     alignPanel.paintAlignment(true);\r
2399   }\r
2400 \r
2401   public void sortLengthMenuItem_actionPerformed()\r
2402   {\r
2403     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
2404     AlignmentSorter.sortByLength(viewport.getAlignment());\r
2405     addHistoryItem(new OrderCommand("Length Sort", oldOrder,\r
2406             viewport.getAlignment()));\r
2407     alignPanel.paintAlignment(true);\r
2408   }\r
2409 \r
2410   public void sortGroupMenuItem_actionPerformed()\r
2411   {\r
2412     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
2413     AlignmentSorter.sortByGroup(viewport.getAlignment());\r
2414     addHistoryItem(new OrderCommand("Group Sort", oldOrder,\r
2415             viewport.getAlignment()));\r
2416     alignPanel.paintAlignment(true);\r
2417 \r
2418   }\r
2419 \r
2420   public void removeRedundancyMenuItem_actionPerformed()\r
2421   {\r
2422     new RedundancyPanel(alignPanel);\r
2423   }\r
2424 \r
2425   public void pairwiseAlignmentMenuItem_actionPerformed()\r
2426   {\r
2427     if (viewport.getSelectionGroup() != null\r
2428             && viewport.getSelectionGroup().getSize() > 1)\r
2429     {\r
2430       Frame frame = new Frame();\r
2431       frame.add(new PairwiseAlignPanel(alignPanel));\r
2432       jalview.bin.JalviewLite.addFrame(frame, "Pairwise Alignment", 600,\r
2433               500);\r
2434     }\r
2435   }\r
2436 \r
2437   public void PCAMenuItem_actionPerformed()\r
2438   {\r
2439     // are the sequences aligned?\r
2440     if (!viewport.getAlignment().isAligned(false))\r
2441     {\r
2442       SequenceI current;\r
2443       int Width = viewport.getAlignment().getWidth();\r
2444 \r
2445       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
2446       {\r
2447         current = viewport.getAlignment().getSequenceAt(i);\r
2448 \r
2449         if (current.getLength() < Width)\r
2450         {\r
2451           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
2452         }\r
2453       }\r
2454       alignPanel.paintAlignment(true);\r
2455     }\r
2456 \r
2457     if ((viewport.getSelectionGroup() != null\r
2458             && viewport.getSelectionGroup().getSize() < 4 && viewport\r
2459             .getSelectionGroup().getSize() > 0)\r
2460             || viewport.getAlignment().getHeight() < 4)\r
2461     {\r
2462       return;\r
2463     }\r
2464 \r
2465     try\r
2466     {\r
2467       new PCAPanel(viewport);\r
2468     } catch (java.lang.OutOfMemoryError ex)\r
2469     {\r
2470     }\r
2471 \r
2472   }\r
2473 \r
2474   public void averageDistanceTreeMenuItem_actionPerformed()\r
2475   {\r
2476     NewTreePanel("AV", "PID", "Average distance tree using PID");\r
2477   }\r
2478 \r
2479   public void neighbourTreeMenuItem_actionPerformed()\r
2480   {\r
2481     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
2482   }\r
2483 \r
2484   protected void njTreeBlosumMenuItem_actionPerformed()\r
2485   {\r
2486     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
2487   }\r
2488 \r
2489   protected void avTreeBlosumMenuItem_actionPerformed()\r
2490   {\r
2491     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");\r
2492   }\r
2493 \r
2494   void NewTreePanel(String type, String pwType, String title)\r
2495   {\r
2496     // are the sequences aligned?\r
2497     if (!viewport.getAlignment().isAligned(false))\r
2498     {\r
2499       SequenceI current;\r
2500       int Width = viewport.getAlignment().getWidth();\r
2501 \r
2502       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
2503       {\r
2504         current = viewport.getAlignment().getSequenceAt(i);\r
2505 \r
2506         if (current.getLength() < Width)\r
2507         {\r
2508           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
2509         }\r
2510       }\r
2511       alignPanel.paintAlignment(true);\r
2512 \r
2513     }\r
2514 \r
2515     if ((viewport.getSelectionGroup() != null && viewport\r
2516             .getSelectionGroup().getSize() > 1)\r
2517             || (viewport.getSelectionGroup() == null && viewport.getAlignment()\r
2518                     .getHeight() > 1))\r
2519     {\r
2520       final TreePanel tp = new TreePanel(alignPanel, type, pwType);\r
2521 \r
2522       addTreeMenuItem(tp, title);\r
2523 \r
2524       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);\r
2525     }\r
2526   }\r
2527 \r
2528   void loadTree_actionPerformed()\r
2529   {\r
2530     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
2531     cap.setText("Paste your Newick tree file here.");\r
2532     cap.setTreeImport();\r
2533     Frame frame = new Frame();\r
2534     frame.add(cap);\r
2535     jalview.bin.JalviewLite.addFrame(frame, "Paste Newick file ", 400, 300);\r
2536   }\r
2537 \r
2538   public void loadTree(jalview.io.NewickFile tree, String treeFile)\r
2539   {\r
2540     TreePanel tp = new TreePanel(alignPanel, treeFile, "From File - ", tree);\r
2541     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);\r
2542     addTreeMenuItem(tp, treeFile);\r
2543   }\r
2544 \r
2545   /**\r
2546    * sort the alignment using the given treePanel\r
2547    *\r
2548    * @param treePanel\r
2549    *          tree used to sort view\r
2550    * @param title\r
2551    *          string used for undo event name\r
2552    */\r
2553   public void sortByTree(TreePanel treePanel, String title)\r
2554   {\r
2555     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
2556     AlignmentSorter\r
2557             .sortByTree(viewport.getAlignment(), treePanel.getTree());\r
2558     // addHistoryItem(new HistoryItem("Sort", viewport.alignment,\r
2559     // HistoryItem.SORT));\r
2560     addHistoryItem(new OrderCommand("Order by " + title, oldOrder,\r
2561             viewport.getAlignment()));\r
2562     alignPanel.paintAlignment(true);\r
2563   }\r
2564 \r
2565   /**\r
2566    * Do any automatic reordering of the alignment and add the necessary bits to\r
2567    * the menu structure for the new tree\r
2568    *\r
2569    * @param treePanel\r
2570    * @param title\r
2571    */\r
2572   protected void addTreeMenuItem(final TreePanel treePanel,\r
2573           final String title)\r
2574   {\r
2575     final MenuItem item = new MenuItem(title);\r
2576     sortByTreeMenu.add(item);\r
2577     item.addActionListener(new java.awt.event.ActionListener()\r
2578     {\r
2579       @Override\r
2580       public void actionPerformed(ActionEvent evt)\r
2581       {\r
2582         sortByTree(treePanel, title); // treePanel.getTitle());\r
2583       }\r
2584     });\r
2585 \r
2586     treePanel.addWindowListener(new WindowAdapter()\r
2587     {\r
2588       @Override\r
2589       public void windowOpened(WindowEvent e)\r
2590       {\r
2591         if (viewport.sortByTree)\r
2592         {\r
2593           sortByTree(treePanel, title);\r
2594         }\r
2595         super.windowOpened(e);\r
2596       }\r
2597 \r
2598       @Override\r
2599       public void windowClosing(WindowEvent e)\r
2600       {\r
2601         sortByTreeMenu.remove(item);\r
2602       };\r
2603     });\r
2604   }\r
2605   public boolean sortBy(AlignmentOrder alorder, String undoname)\r
2606   {\r
2607     SequenceI[] oldOrder = viewport.getAlignment()\r
2608     .getSequencesArray();\r
2609     if (viewport.applet.debug)\r
2610     {\r
2611       System.err.println("Sorting "+alorder.getOrder().size()+" in alignment '"+getTitle()+"'");\r
2612     }\r
2613     AlignmentSorter.sortBy(viewport.getAlignment(), alorder);\r
2614     if (undoname!=null)\r
2615     {\r
2616       addHistoryItem(new OrderCommand(undoname, oldOrder, viewport.getAlignment()));\r
2617     }\r
2618     alignPanel.paintAlignment(true);\r
2619     return true;\r
2620   }\r
2621 \r
2622   protected void documentation_actionPerformed()\r
2623   {\r
2624     alignPanel.av.applet.openJalviewHelpUrl();\r
2625   }\r
2626 \r
2627   protected void about_actionPerformed()\r
2628   {\r
2629 \r
2630     class AboutPanel extends Canvas\r
2631     {\r
2632       String version;\r
2633 \r
2634       String builddate;\r
2635 \r
2636       public AboutPanel(String version, String builddate)\r
2637       {\r
2638         this.version = version;\r
2639         this.builddate = builddate;\r
2640       }\r
2641 \r
2642       @Override\r
2643       public void paint(Graphics g)\r
2644       {\r
2645         g.setColor(Color.white);\r
2646         g.fillRect(0, 0, getSize().width, getSize().height);\r
2647         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
2648         FontMetrics fm = g.getFontMetrics();\r
2649         int fh = fm.getHeight();\r
2650         int y = 5, x = 7;\r
2651         g.setColor(Color.black);\r
2652         // TODO: update this text for each release or centrally store it for\r
2653         // lite and application\r
2654         g.setFont(new Font("Helvetica", Font.BOLD, 14));\r
2655         g.drawString("JalviewLite - Release " + version, x, y += fh);\r
2656         g.setFont(new Font("Helvetica", Font.BOLD, 12));\r
2657         g.drawString("Build date: " + builddate, x, y += fh);\r
2658         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
2659         g.drawString(\r
2660                 "Authors:  Jim Procter, Andrew Waterhouse, Michele Clamp, James Cuff, Steve Searle,",\r
2661                 x, y += fh * 1.5);\r
2662         g.drawString("David Martin & Geoff Barton.", x + 50, y += fh);\r
2663         g.drawString(\r
2664                 "Development managed by The Barton Group, University of Dundee, Scotland, UK.",\r
2665                 x, y += fh);\r
2666         g.drawString(\r
2667                 "For help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list",\r
2668                 x, y += fh);\r
2669         g.drawString("If  you use Jalview, please cite:", x, y += fh + 8);\r
2670         g.drawString(\r
2671                 "Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)",\r
2672                 x, y += fh);\r
2673         g.drawString(\r
2674                 "Jalview Version 2 - a multiple sequence alignment editor and analysis workbench",\r
2675                 x, y += fh);\r
2676         g.drawString("Bioinformatics doi: 10.1093/bioinformatics/btp033",\r
2677                 x, y += fh);\r
2678       }\r
2679     }\r
2680 \r
2681     Frame frame = new Frame();\r
2682     frame.add(new AboutPanel(JalviewLite.getVersion(), JalviewLite\r
2683             .getBuildDate()));\r
2684     jalview.bin.JalviewLite.addFrame(frame, "Jalview", 580, 220);\r
2685 \r
2686   }\r
2687 \r
2688   public void showURL(String url, String target)\r
2689   {\r
2690     if (viewport.applet == null)\r
2691     {\r
2692       System.out.println("Not running as applet - no browser available.");\r
2693     }\r
2694     else\r
2695     {\r
2696       viewport.applet.showURL(url, target);\r
2697     }\r
2698   }\r
2699 \r
2700   // ////////////////////////////////////////////////////////////////////////////////\r
2701   // JBuilder Graphics here\r
2702 \r
2703   MenuBar alignFrameMenuBar = new MenuBar();\r
2704 \r
2705   Menu fileMenu = new Menu("File");\r
2706 \r
2707   MenuItem loadApplication = new MenuItem("View in Full Application");\r
2708 \r
2709   MenuItem loadTree = new MenuItem("Load Associated Tree ...");\r
2710 \r
2711   MenuItem loadAnnotations = new MenuItem("Load Features/Annotations ...");\r
2712 \r
2713   MenuItem outputFeatures = new MenuItem("Export Features ...");\r
2714 \r
2715   MenuItem outputAnnotations = new MenuItem("Export Annotations ...");\r
2716 \r
2717   MenuItem closeMenuItem = new MenuItem("Close");\r
2718 \r
2719   Menu editMenu = new Menu("Edit");\r
2720 \r
2721   Menu viewMenu = new Menu("View");\r
2722 \r
2723   Menu colourMenu = new Menu("Colour");\r
2724 \r
2725   Menu calculateMenu = new Menu("Calculate");\r
2726 \r
2727   MenuItem selectAllSequenceMenuItem = new MenuItem("Select all");\r
2728 \r
2729   MenuItem deselectAllSequenceMenuItem = new MenuItem("Deselect All");\r
2730 \r
2731   MenuItem invertSequenceMenuItem = new MenuItem("Invert Selection");\r
2732 \r
2733   MenuItem remove2LeftMenuItem = new MenuItem();\r
2734 \r
2735   MenuItem remove2RightMenuItem = new MenuItem();\r
2736 \r
2737   MenuItem removeGappedColumnMenuItem = new MenuItem();\r
2738 \r
2739   MenuItem removeAllGapsMenuItem = new MenuItem();\r
2740 \r
2741   CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();\r
2742 \r
2743   CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();\r
2744 \r
2745   MenuItem sortPairwiseMenuItem = new MenuItem();\r
2746 \r
2747   MenuItem sortIDMenuItem = new MenuItem();\r
2748 \r
2749   MenuItem sortLengthMenuItem = new MenuItem();\r
2750 \r
2751   MenuItem sortGroupMenuItem = new MenuItem();\r
2752 \r
2753   MenuItem removeRedundancyMenuItem = new MenuItem();\r
2754 \r
2755   MenuItem pairwiseAlignmentMenuItem = new MenuItem();\r
2756 \r
2757   MenuItem PCAMenuItem = new MenuItem();\r
2758 \r
2759   MenuItem averageDistanceTreeMenuItem = new MenuItem();\r
2760 \r
2761   MenuItem neighbourTreeMenuItem = new MenuItem();\r
2762 \r
2763   BorderLayout borderLayout1 = new BorderLayout();\r
2764 \r
2765   public Label statusBar = new Label();\r
2766 \r
2767   Menu outputTextboxMenu = new Menu();\r
2768 \r
2769   MenuItem clustalColour = new MenuItem();\r
2770 \r
2771   MenuItem zappoColour = new MenuItem();\r
2772 \r
2773   MenuItem taylorColour = new MenuItem();\r
2774 \r
2775   MenuItem hydrophobicityColour = new MenuItem();\r
2776 \r
2777   MenuItem helixColour = new MenuItem();\r
2778 \r
2779   MenuItem strandColour = new MenuItem();\r
2780 \r
2781   MenuItem turnColour = new MenuItem();\r
2782 \r
2783   MenuItem buriedColour = new MenuItem();\r
2784 \r
2785   MenuItem purinePyrimidineColour = new MenuItem();\r
2786   MenuItem RNAHelixColour = new MenuItem();\r
2787 \r
2788   MenuItem userDefinedColour = new MenuItem();\r
2789 \r
2790   MenuItem PIDColour = new MenuItem();\r
2791 \r
2792   MenuItem BLOSUM62Colour = new MenuItem();\r
2793 \r
2794   MenuItem tcoffeeColour = new MenuItem();\r
2795 \r
2796   MenuItem njTreeBlosumMenuItem = new MenuItem();\r
2797 \r
2798   MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();\r
2799 \r
2800   CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();\r
2801 \r
2802   CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();\r
2803 \r
2804   CheckboxMenuItem displayNonconservedMenuItem = new CheckboxMenuItem();\r
2805 \r
2806   MenuItem alProperties = new MenuItem("Alignment Properties...");\r
2807 \r
2808   MenuItem overviewMenuItem = new MenuItem();\r
2809 \r
2810   MenuItem undoMenuItem = new MenuItem();\r
2811 \r
2812   MenuItem redoMenuItem = new MenuItem();\r
2813 \r
2814   CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();\r
2815 \r
2816   MenuItem noColourmenuItem = new MenuItem();\r
2817 \r
2818   CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();\r
2819 \r
2820   CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();\r
2821 \r
2822   MenuItem findMenuItem = new MenuItem();\r
2823 \r
2824   CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();\r
2825 \r
2826   MenuItem nucleotideColour = new MenuItem();\r
2827 \r
2828   MenuItem deleteGroups = new MenuItem();\r
2829 \r
2830   MenuItem grpsFromSelection = new MenuItem();\r
2831 \r
2832   MenuItem delete = new MenuItem();\r
2833 \r
2834   MenuItem copy = new MenuItem();\r
2835 \r
2836   MenuItem cut = new MenuItem();\r
2837 \r
2838   Menu pasteMenu = new Menu();\r
2839 \r
2840   MenuItem pasteNew = new MenuItem();\r
2841 \r
2842   MenuItem pasteThis = new MenuItem();\r
2843 \r
2844   CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();\r
2845 \r
2846   MenuItem font = new MenuItem();\r
2847 \r
2848   CheckboxMenuItem scaleAbove = new CheckboxMenuItem();\r
2849 \r
2850   CheckboxMenuItem scaleLeft = new CheckboxMenuItem();\r
2851 \r
2852   CheckboxMenuItem scaleRight = new CheckboxMenuItem();\r
2853 \r
2854   MenuItem modifyPID = new MenuItem();\r
2855 \r
2856   MenuItem modifyConservation = new MenuItem();\r
2857 \r
2858   CheckboxMenuItem autoCalculate = new CheckboxMenuItem(\r
2859           "Autocalculate Consensus", true);\r
2860 \r
2861   CheckboxMenuItem sortByTree = new CheckboxMenuItem(\r
2862           "Sort Alignment With New Tree", true);\r
2863 \r
2864   Menu sortByTreeMenu = new Menu();\r
2865 \r
2866   Menu sort = new Menu();\r
2867 \r
2868   Menu calculate = new Menu();\r
2869 \r
2870   MenuItem inputText = new MenuItem();\r
2871 \r
2872   Menu helpMenu = new Menu();\r
2873 \r
2874   MenuItem documentation = new MenuItem();\r
2875 \r
2876   MenuItem about = new MenuItem();\r
2877 \r
2878   CheckboxMenuItem seqLimits = new CheckboxMenuItem();\r
2879 \r
2880   CheckboxMenuItem centreColumnLabelFlag = new CheckboxMenuItem();\r
2881 \r
2882   CheckboxMenuItem followMouseOverFlag = new CheckboxMenuItem();\r
2883   Menu autoAnnMenu=new Menu();\r
2884   CheckboxMenuItem showSequenceLogo= new CheckboxMenuItem();\r
2885   CheckboxMenuItem applyAutoAnnotationSettings = new CheckboxMenuItem();\r
2886   CheckboxMenuItem showConsensusHistogram = new CheckboxMenuItem();\r
2887   CheckboxMenuItem showGroupConsensus = new CheckboxMenuItem();\r
2888   CheckboxMenuItem showGroupConservation = new CheckboxMenuItem();\r
2889 \r
2890   private void jbInit() throws Exception\r
2891   {\r
2892 \r
2893     setMenuBar(alignFrameMenuBar);\r
2894 \r
2895     MenuItem item;\r
2896 \r
2897     // dynamically fill save as menu with available formats\r
2898     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)\r
2899     {\r
2900 \r
2901       item = new MenuItem(\r
2902               jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);\r
2903 \r
2904       item.addActionListener(new java.awt.event.ActionListener()\r
2905       {\r
2906         @Override\r
2907         public void actionPerformed(ActionEvent e)\r
2908         {\r
2909           outputText_actionPerformed(e);\r
2910         }\r
2911       });\r
2912 \r
2913       outputTextboxMenu.add(item);\r
2914     }\r
2915     closeMenuItem.addActionListener(this);\r
2916     loadApplication.addActionListener(this);\r
2917 \r
2918     loadTree.addActionListener(this);\r
2919     loadAnnotations.addActionListener(this);\r
2920     outputFeatures.addActionListener(this);\r
2921     outputAnnotations.addActionListener(this);\r
2922     selectAllSequenceMenuItem.addActionListener(this);\r
2923     deselectAllSequenceMenuItem.addActionListener(this);\r
2924     invertSequenceMenuItem.addActionListener(this);\r
2925     remove2LeftMenuItem.setLabel("Remove Left");\r
2926     remove2LeftMenuItem.addActionListener(this);\r
2927     remove2RightMenuItem.setLabel("Remove Right");\r
2928     remove2RightMenuItem.addActionListener(this);\r
2929     removeGappedColumnMenuItem.setLabel("Remove Empty Columns");\r
2930     removeGappedColumnMenuItem.addActionListener(this);\r
2931     removeAllGapsMenuItem.setLabel("Remove All Gaps");\r
2932     removeAllGapsMenuItem.addActionListener(this);\r
2933     viewBoxesMenuItem.setLabel("Boxes");\r
2934     viewBoxesMenuItem.setState(true);\r
2935     viewBoxesMenuItem.addItemListener(this);\r
2936     viewTextMenuItem.setLabel("Text");\r
2937     viewTextMenuItem.setState(true);\r
2938     viewTextMenuItem.addItemListener(this);\r
2939     sortPairwiseMenuItem.setLabel("by Pairwise Identity");\r
2940     sortPairwiseMenuItem.addActionListener(this);\r
2941     sortIDMenuItem.setLabel("by ID");\r
2942     sortIDMenuItem.addActionListener(this);\r
2943     sortLengthMenuItem.setLabel("by Length");\r
2944     sortLengthMenuItem.addActionListener(this);\r
2945     sortGroupMenuItem.setLabel("by Group");\r
2946     sortGroupMenuItem.addActionListener(this);\r
2947     removeRedundancyMenuItem.setLabel("Remove Redundancy...");\r
2948     removeRedundancyMenuItem.addActionListener(this);\r
2949     pairwiseAlignmentMenuItem.setLabel("Pairwise Alignments...");\r
2950     pairwiseAlignmentMenuItem.addActionListener(this);\r
2951     PCAMenuItem.setLabel("Principal Component Analysis");\r
2952     PCAMenuItem.addActionListener(this);\r
2953     averageDistanceTreeMenuItem\r
2954             .setLabel("Average Distance Using % Identity");\r
2955     averageDistanceTreeMenuItem.addActionListener(this);\r
2956     neighbourTreeMenuItem.setLabel("Neighbour Joining Using % Identity");\r
2957     neighbourTreeMenuItem.addActionListener(this);\r
2958     statusBar.setBackground(Color.white);\r
2959     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));\r
2960     statusBar.setText("Status bar");\r
2961     outputTextboxMenu.setLabel("Output to Textbox");\r
2962     clustalColour.setLabel("Clustalx");\r
2963 \r
2964     clustalColour.addActionListener(this);\r
2965     zappoColour.setLabel("Zappo");\r
2966     zappoColour.addActionListener(this);\r
2967     taylorColour.setLabel("Taylor");\r
2968     taylorColour.addActionListener(this);\r
2969     hydrophobicityColour.setLabel("Hydrophobicity");\r
2970     hydrophobicityColour.addActionListener(this);\r
2971     helixColour.setLabel("Helix Propensity");\r
2972     helixColour.addActionListener(this);\r
2973     strandColour.setLabel("Strand Propensity");\r
2974     strandColour.addActionListener(this);\r
2975     turnColour.setLabel("Turn Propensity");\r
2976     turnColour.addActionListener(this);\r
2977     buriedColour.setLabel("Buried Index");\r
2978     buriedColour.addActionListener(this);\r
2979     purinePyrimidineColour.setLabel("Purine/Pyrimidine");\r
2980     purinePyrimidineColour.addActionListener(this);\r
2981     RNAHelixColour.setLabel("by RNA Helices");\r
2982     RNAHelixColour.addActionListener(this);\r
2983     userDefinedColour.setLabel("User Defined...");\r
2984     userDefinedColour.addActionListener(this);\r
2985     PIDColour.setLabel("Percentage Identity");\r
2986     PIDColour.addActionListener(this);\r
2987     BLOSUM62Colour.setLabel("BLOSUM62 Score");\r
2988     BLOSUM62Colour.addActionListener(this);\r
2989     tcoffeeColour.setLabel("T-Coffee Scores");\r
2990     tcoffeeColour.setEnabled(false);    // it will enabled only if a score file is provided\r
2991     tcoffeeColour.addActionListener(this);\r
2992     avDistanceTreeBlosumMenuItem .setLabel("Average Distance Using BLOSUM62");\r
2993     avDistanceTreeBlosumMenuItem.addActionListener(this);\r
2994     njTreeBlosumMenuItem.setLabel("Neighbour Joining Using BLOSUM62");\r
2995     njTreeBlosumMenuItem.addActionListener(this);\r
2996     annotationPanelMenuItem.setLabel("Show Annotations");\r
2997     annotationPanelMenuItem.addItemListener(this);\r
2998     colourTextMenuItem.setLabel("Colour Text");\r
2999     colourTextMenuItem.addItemListener(this);\r
3000     displayNonconservedMenuItem.setLabel("Show nonconserved");\r
3001     displayNonconservedMenuItem.addItemListener(this);\r
3002     alProperties.addActionListener(this);\r
3003     overviewMenuItem.setLabel("Overview Window");\r
3004     overviewMenuItem.addActionListener(this);\r
3005     undoMenuItem.setEnabled(false);\r
3006     undoMenuItem.setLabel("Undo");\r
3007     undoMenuItem.addActionListener(this);\r
3008     redoMenuItem.setEnabled(false);\r
3009     redoMenuItem.setLabel("Redo");\r
3010     redoMenuItem.addActionListener(this);\r
3011     conservationMenuItem.setLabel("by Conservation");\r
3012     conservationMenuItem.addItemListener(this);\r
3013     noColourmenuItem.setLabel("None");\r
3014     noColourmenuItem.addActionListener(this);\r
3015     wrapMenuItem.setLabel("Wrap");\r
3016     wrapMenuItem.addItemListener(this);\r
3017     renderGapsMenuItem.setLabel("Show Gaps");\r
3018     renderGapsMenuItem.setState(true);\r
3019     renderGapsMenuItem.addItemListener(this);\r
3020     findMenuItem.setLabel("Find...");\r
3021     findMenuItem.addActionListener(this);\r
3022     abovePIDThreshold.setLabel("Above Identity Threshold");\r
3023     abovePIDThreshold.addItemListener(this);\r
3024     nucleotideColour.setLabel("Nucleotide");\r
3025     nucleotideColour.addActionListener(this);\r
3026     deleteGroups.setLabel("Undefine Groups");\r
3027     deleteGroups.addActionListener(this);\r
3028     grpsFromSelection.setLabel("Make Groups for selection");\r
3029     grpsFromSelection.addActionListener(this);\r
3030     copy.setLabel("Copy");\r
3031     copy.addActionListener(this);\r
3032     cut.setLabel("Cut");\r
3033     cut.addActionListener(this);\r
3034     delete.setLabel("Delete");\r
3035     delete.addActionListener(this);\r
3036     pasteMenu.setLabel("Paste");\r
3037     pasteNew.setLabel("To New Alignment");\r
3038     pasteNew.addActionListener(this);\r
3039     pasteThis.setLabel("Add To This Alignment");\r
3040     pasteThis.addActionListener(this);\r
3041     applyToAllGroups.setLabel("Apply Colour To All Groups");\r
3042     applyToAllGroups.setState(true);\r
3043     applyToAllGroups.addItemListener(this);\r
3044     font.setLabel("Font...");\r
3045     font.addActionListener(this);\r
3046     scaleAbove.setLabel("Scale Above");\r
3047     scaleAbove.setState(true);\r
3048     scaleAbove.setEnabled(false);\r
3049     scaleAbove.addItemListener(this);\r
3050     scaleLeft.setEnabled(false);\r
3051     scaleLeft.setState(true);\r
3052     scaleLeft.setLabel("Scale Left");\r
3053     scaleLeft.addItemListener(this);\r
3054     scaleRight.setEnabled(false);\r
3055     scaleRight.setState(true);\r
3056     scaleRight.setLabel("Scale Right");\r
3057     scaleRight.addItemListener(this);\r
3058     modifyPID.setLabel("Modify Identity Threshold...");\r
3059     modifyPID.addActionListener(this);\r
3060     modifyConservation.setLabel("Modify Conservation Threshold...");\r
3061     modifyConservation.addActionListener(this);\r
3062     sortByTreeMenu.setLabel("By Tree Order");\r
3063     sort.setLabel("Sort");\r
3064     calculate.setLabel("Calculate Tree");\r
3065     autoCalculate.addItemListener(this);\r
3066     sortByTree.addItemListener(this);\r
3067     inputText.setLabel("Input from textbox");\r
3068     inputText.addActionListener(this);\r
3069     centreColumnLabelFlag.setLabel("Centre column labels");\r
3070     centreColumnLabelFlag.addItemListener(this);\r
3071     followMouseOverFlag.setLabel("Automatic Scrolling");\r
3072     followMouseOverFlag.addItemListener(this);\r
3073     helpMenu.setLabel("Help");\r
3074     documentation.setLabel("Documentation");\r
3075     documentation.addActionListener(this);\r
3076 \r
3077     about.setLabel("About...");\r
3078     about.addActionListener(this);\r
3079     seqLimits.setState(true);\r
3080     seqLimits.setLabel("Show Sequence Limits");\r
3081     seqLimits.addItemListener(this);\r
3082     featureSettings.setLabel("Feature Settings...");\r
3083     featureSettings.addActionListener(this);\r
3084     sequenceFeatures.setLabel("Sequence Features");\r
3085     sequenceFeatures.addItemListener(this);\r
3086     sequenceFeatures.setState(false);\r
3087     annotationColour.setLabel("by Annotation...");\r
3088     annotationColour.addActionListener(this);\r
3089     invertSequenceMenuItem.setLabel("Invert Sequence Selection");\r
3090     invertColSel.setLabel("Invert Column Selection");\r
3091     menu1.setLabel("Show");\r
3092     showColumns.setLabel("All Columns ");\r
3093     showSeqs.setLabel("All Sequences");\r
3094     menu2.setLabel("Hide");\r
3095     hideColumns.setLabel("Selected Columns");\r
3096     hideSequences.setLabel("Selected Sequences");\r
3097     hideAllButSelection.setLabel("All but Selected Region (Shift+Ctrl+H)");\r
3098     hideAllSelection.setLabel("Selected Region");\r
3099     showAllHidden.setLabel("All Sequences and Columns");\r
3100     showGroupConsensus.setLabel("Group Consensus");\r
3101     showGroupConservation.setLabel("Group Conservation");\r
3102     showConsensusHistogram.setLabel("Show Consensus Histogram");\r
3103     showSequenceLogo.setLabel("Show Consensus Logo");\r
3104     applyAutoAnnotationSettings.setLabel("Apply to all groups");\r
3105     applyAutoAnnotationSettings.setState(true);\r
3106     autoAnnMenu.setLabel("Autocalculated Annotation");\r
3107 \r
3108     invertColSel.addActionListener(this);\r
3109     showColumns.addActionListener(this);\r
3110     showSeqs.addActionListener(this);\r
3111     hideColumns.addActionListener(this);\r
3112     hideSequences.addActionListener(this);\r
3113     hideAllButSelection.addActionListener(this);\r
3114     hideAllSelection.addActionListener(this);\r
3115     showAllHidden.addActionListener(this);\r
3116     showGroupConsensus.addItemListener(this);\r
3117     showGroupConservation.addItemListener(this);\r
3118     showConsensusHistogram.addItemListener(this);\r
3119     showSequenceLogo.addItemListener(this);\r
3120     applyAutoAnnotationSettings.addItemListener(this);\r
3121     formatMenu.setLabel("Format");\r
3122     selectMenu.setLabel("Select");\r
3123     newView.setLabel("New View");\r
3124     newView.addActionListener(this);\r
3125     alignFrameMenuBar.add(fileMenu);\r
3126     alignFrameMenuBar.add(editMenu);\r
3127     alignFrameMenuBar.add(selectMenu);\r
3128     alignFrameMenuBar.add(viewMenu);\r
3129     alignFrameMenuBar.add(formatMenu);\r
3130     alignFrameMenuBar.add(colourMenu);\r
3131     alignFrameMenuBar.add(calculateMenu);\r
3132     alignFrameMenuBar.add(helpMenu);\r
3133 \r
3134     fileMenu.add(inputText);\r
3135     fileMenu.add(loadTree);\r
3136     fileMenu.add(loadAnnotations);\r
3137 \r
3138     fileMenu.addSeparator();\r
3139     fileMenu.add(outputTextboxMenu);\r
3140     fileMenu.add(outputFeatures);\r
3141     fileMenu.add(outputAnnotations);\r
3142 \r
3143     if (jalviewServletURL != null)\r
3144     {\r
3145       fileMenu.add(loadApplication);\r
3146     }\r
3147 \r
3148     fileMenu.addSeparator();\r
3149     fileMenu.add(closeMenuItem);\r
3150 \r
3151     editMenu.add(undoMenuItem);\r
3152     editMenu.add(redoMenuItem);\r
3153     editMenu.add(cut);\r
3154     editMenu.add(copy);\r
3155     editMenu.add(pasteMenu);\r
3156     editMenu.add(delete);\r
3157     editMenu.addSeparator();\r
3158     editMenu.add(remove2LeftMenuItem);\r
3159     editMenu.add(remove2RightMenuItem);\r
3160     editMenu.add(removeGappedColumnMenuItem);\r
3161     editMenu.add(removeAllGapsMenuItem);\r
3162     editMenu.add(removeRedundancyMenuItem);\r
3163     viewMenu.add(newView);\r
3164     viewMenu.addSeparator();\r
3165     viewMenu.add(menu1);\r
3166     viewMenu.add(menu2);\r
3167     viewMenu.addSeparator();\r
3168     viewMenu.add(followMouseOverFlag);\r
3169     viewMenu.add(annotationPanelMenuItem);\r
3170     autoAnnMenu.add(applyAutoAnnotationSettings);\r
3171     autoAnnMenu.add(showConsensusHistogram);\r
3172     autoAnnMenu.add(showSequenceLogo);\r
3173     autoAnnMenu.addSeparator();\r
3174     autoAnnMenu.add(showGroupConservation);\r
3175     autoAnnMenu.add(showGroupConsensus);\r
3176     viewMenu.add(autoAnnMenu);\r
3177     viewMenu.addSeparator();\r
3178     viewMenu.add(sequenceFeatures);\r
3179     viewMenu.add(featureSettings);\r
3180     viewMenu.addSeparator();\r
3181     viewMenu.add(alProperties);\r
3182     viewMenu.addSeparator();\r
3183     viewMenu.add(overviewMenuItem);\r
3184     colourMenu.add(applyToAllGroups);\r
3185     colourMenu.addSeparator();\r
3186     colourMenu.add(noColourmenuItem);\r
3187     colourMenu.add(clustalColour);\r
3188     colourMenu.add(BLOSUM62Colour);\r
3189     colourMenu.add(PIDColour);\r
3190     colourMenu.add(zappoColour);\r
3191     colourMenu.add(taylorColour);\r
3192     colourMenu.add(hydrophobicityColour);\r
3193     colourMenu.add(helixColour);\r
3194     colourMenu.add(strandColour);\r
3195     colourMenu.add(turnColour);\r
3196     colourMenu.add(buriedColour);\r
3197     colourMenu.add(nucleotideColour);\r
3198     colourMenu.add(purinePyrimidineColour);\r
3199     colourMenu.add(tcoffeeColour);\r
3200     colourMenu.add(userDefinedColour);\r
3201     colourMenu.addSeparator();\r
3202     colourMenu.add(conservationMenuItem);\r
3203     colourMenu.add(modifyConservation);\r
3204     colourMenu.add(abovePIDThreshold);\r
3205     colourMenu.add(modifyPID);\r
3206     colourMenu.add(annotationColour);\r
3207     colourMenu.add(RNAHelixColour);\r
3208     calculateMenu.add(sort);\r
3209     calculateMenu.add(calculate);\r
3210     calculateMenu.addSeparator();\r
3211     calculateMenu.add(pairwiseAlignmentMenuItem);\r
3212     calculateMenu.add(PCAMenuItem);\r
3213     calculateMenu.add(autoCalculate);\r
3214     calculateMenu.add(sortByTree);\r
3215     this.add(statusBar, BorderLayout.SOUTH);\r
3216     pasteMenu.add(pasteNew);\r
3217     pasteMenu.add(pasteThis);\r
3218     sort.add(sortIDMenuItem);\r
3219     sort.add(sortLengthMenuItem);\r
3220     sort.add(sortByTreeMenu);\r
3221     sort.add(sortGroupMenuItem);\r
3222     sort.add(sortPairwiseMenuItem);\r
3223     calculate.add(averageDistanceTreeMenuItem);\r
3224     calculate.add(neighbourTreeMenuItem);\r
3225     calculate.add(avDistanceTreeBlosumMenuItem);\r
3226     calculate.add(njTreeBlosumMenuItem);\r
3227     helpMenu.add(documentation);\r
3228     helpMenu.add(about);\r
3229     menu1.add(showColumns);\r
3230     menu1.add(showSeqs);\r
3231     menu1.add(showAllHidden);\r
3232     menu2.add(hideColumns);\r
3233     menu2.add(hideSequences);\r
3234     menu2.add(hideAllSelection);\r
3235     menu2.add(hideAllButSelection);\r
3236     formatMenu.add(font);\r
3237     formatMenu.add(seqLimits);\r
3238     formatMenu.add(wrapMenuItem);\r
3239     formatMenu.add(scaleAbove);\r
3240     formatMenu.add(scaleLeft);\r
3241     formatMenu.add(scaleRight);\r
3242     formatMenu.add(viewBoxesMenuItem);\r
3243     formatMenu.add(viewTextMenuItem);\r
3244     formatMenu.add(colourTextMenuItem);\r
3245     formatMenu.add(displayNonconservedMenuItem);\r
3246     formatMenu.add(renderGapsMenuItem);\r
3247     formatMenu.add(centreColumnLabelFlag);\r
3248     selectMenu.add(findMenuItem);\r
3249     selectMenu.addSeparator();\r
3250     selectMenu.add(selectAllSequenceMenuItem);\r
3251     selectMenu.add(deselectAllSequenceMenuItem);\r
3252     selectMenu.add(invertSequenceMenuItem);\r
3253     selectMenu.add(invertColSel);\r
3254     selectMenu.add(grpsFromSelection);\r
3255     selectMenu.add(deleteGroups);\r
3256 \r
3257   }\r
3258 \r
3259   MenuItem featureSettings = new MenuItem();\r
3260 \r
3261   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();\r
3262 \r
3263   MenuItem annotationColour = new MenuItem();\r
3264 \r
3265   MenuItem invertColSel = new MenuItem();\r
3266 \r
3267   Menu menu1 = new Menu();\r
3268 \r
3269   MenuItem showColumns = new MenuItem();\r
3270 \r
3271   MenuItem showSeqs = new MenuItem();\r
3272 \r
3273   Menu menu2 = new Menu();\r
3274 \r
3275   MenuItem hideColumns = new MenuItem();\r
3276 \r
3277   MenuItem hideSequences = new MenuItem();\r
3278 \r
3279   MenuItem hideAllButSelection = new MenuItem();\r
3280 \r
3281   MenuItem hideAllSelection = new MenuItem();\r
3282 \r
3283   MenuItem showAllHidden = new MenuItem();\r
3284 \r
3285   Menu formatMenu = new Menu();\r
3286 \r
3287   Menu selectMenu = new Menu();\r
3288 \r
3289   MenuItem newView = new MenuItem();\r
3290 \r
3291   /**\r
3292    * Attach the alignFrame panels after embedding menus, if necessary. This used\r
3293    * to be called setEmbedded, but is now creates the dropdown menus in a\r
3294    * platform independent manner to avoid OSX/Mac menu appendage daftness.\r
3295    *\r
3296    * @param reallyEmbedded\r
3297    *          true to attach the view to the applet area on the page rather than\r
3298    *          in a new window\r
3299    */\r
3300   public void createAlignFrameWindow(boolean reallyEmbedded, String title)\r
3301   {\r
3302     if (reallyEmbedded)\r
3303     {\r
3304       // ////\r
3305       // Explicly build the embedded menu panel for the on-page applet\r
3306       //\r
3307       // view cannot be closed if its actually on the page\r
3308       fileMenu.remove(closeMenuItem);\r
3309       fileMenu.remove(3); // Remove Seperator\r
3310       embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, "Arial",\r
3311               Font.PLAIN, 10, false); // use our own fonts.\r
3312       // and actually add the components to the applet area\r
3313       viewport.applet.setLayout(new BorderLayout());\r
3314       viewport.applet.add(embeddedMenu, BorderLayout.NORTH);\r
3315       viewport.applet.add(statusBar, BorderLayout.SOUTH);\r
3316       alignPanel.setSize(viewport.applet.getSize().width,\r
3317               viewport.applet.getSize().height - embeddedMenu.HEIGHT\r
3318                       - statusBar.HEIGHT);\r
3319       viewport.applet.add(alignPanel, BorderLayout.CENTER);\r
3320       final AlignFrame me = this;\r
3321       viewport.applet.addFocusListener(new FocusListener()\r
3322       {\r
3323 \r
3324         @Override\r
3325         public void focusLost(FocusEvent e)\r
3326         {\r
3327           if (me.viewport.applet.currentAlignFrame==me) {\r
3328                   me.viewport.applet.currentAlignFrame = null;\r
3329         }}\r
3330 \r
3331         @Override\r
3332         public void focusGained(FocusEvent e)\r
3333         {\r
3334           me.viewport.applet.currentAlignFrame = me;\r
3335         }\r
3336       });\r
3337       viewport.applet.validate();\r
3338     }\r
3339     else\r
3340     {\r
3341       // //////\r
3342       // test and embed menu bar if necessary.\r
3343       //\r
3344       if (embedMenuIfNeeded(alignPanel))\r
3345       {\r
3346         // adjust for status bar height too\r
3347         alignPanel.setSize(getSize().width, getSize().height\r
3348                 - statusBar.HEIGHT);\r
3349       }\r
3350       add(statusBar, BorderLayout.SOUTH);\r
3351       add(alignPanel, BorderLayout.CENTER);\r
3352       // and register with the applet so it can pass external API calls to us\r
3353       jalview.bin.JalviewLite.addFrame(this, title, DEFAULT_WIDTH,\r
3354               DEFAULT_HEIGHT);\r
3355     }\r
3356   }\r
3357 \r
3358   /**\r
3359    * create a new binding between structures in an existing jmol viewer instance\r
3360    * and an alignpanel with sequences that have existing PDBFile entries. Note,\r
3361    * this does not open a new Jmol window, or modify the display of the\r
3362    * structures in the original jmol window. Note This method doesn't work\r
3363    * without an additional javascript library to exchange messages between the\r
3364    * distinct applets. See http://issues.jalview.org/browse/JAL-621\r
3365    *\r
3366    * @param viewer\r
3367    *          JmolViewer instance\r
3368    * @param sequenceIds\r
3369    *          - sequence Ids to search for associations\r
3370    */\r
3371   public SequenceStructureBinding addStructureViewInstance(\r
3372           Object jmolviewer, String[] sequenceIds)\r
3373   {\r
3374     org.jmol.api.JmolViewer viewer = null;\r
3375     try\r
3376     {\r
3377       viewer = (org.jmol.api.JmolViewer) jmolviewer;\r
3378     } catch (ClassCastException ex)\r
3379     {\r
3380       System.err.println("Unsupported viewer object :"\r
3381               + jmolviewer.getClass());\r
3382     }\r
3383     if (viewer == null)\r
3384     {\r
3385       System.err.println("Can't use this object as a structure viewer:"\r
3386               + jmolviewer.getClass());\r
3387       return null;\r
3388     }\r
3389     SequenceI[] seqs = null;\r
3390     if (sequenceIds == null || sequenceIds.length == 0)\r
3391     {\r
3392       seqs = viewport.getAlignment().getSequencesArray();\r
3393     }\r
3394     else\r
3395     {\r
3396       Vector sqi = new Vector();\r
3397       AlignmentI al = viewport.getAlignment();\r
3398       for (int sid = 0; sid < sequenceIds.length; sid++)\r
3399       {\r
3400         SequenceI sq = al.findName(sequenceIds[sid]);\r
3401         if (sq != null)\r
3402         {\r
3403           sqi.addElement(sq);\r
3404         }\r
3405       }\r
3406       if (sqi.size() > 0)\r
3407       {\r
3408         seqs = new SequenceI[sqi.size()];\r
3409         for (int sid = 0, sSize = sqi.size(); sid < sSize; sid++)\r
3410         {\r
3411           seqs[sid] = (SequenceI) sqi.elementAt(sid);\r
3412         }\r
3413       }\r
3414       else\r
3415       {\r
3416         return null;\r
3417       }\r
3418     }\r
3419     ExtJmol jmv = null;\r
3420     // TODO: search for a jmv that involves viewer\r
3421     if (jmv == null)\r
3422     { // create a new viewer/jalview binding.\r
3423       jmv = new ExtJmol(viewer, alignPanel, new SequenceI[][] {seqs});\r
3424     }\r
3425     return jmv;\r
3426 \r
3427   }\r
3428   /**\r
3429    * bind a pdb file to a sequence in the current view\r
3430    *\r
3431    * @param sequenceId\r
3432    *          - sequenceId within the dataset.\r
3433    * @param pdbEntryString\r
3434    *          - the short name for the PDB file\r
3435    * @param pdbFile\r
3436    *          - pdb file - either a URL or a valid PDB file.\r
3437    * @return true if binding was as success TODO: consider making an exception\r
3438    *         structure for indicating when PDB parsing or sequenceId location\r
3439    *         fails.\r
3440    */\r
3441   public boolean addPdbFile(String sequenceId, String pdbEntryString,\r
3442           String pdbFile)\r
3443   {\r
3444     SequenceI toaddpdb = viewport.getAlignment().findName(sequenceId);\r
3445     boolean needtoadd = false;\r
3446     if (toaddpdb != null)\r
3447     {\r
3448       Vector pdbe = toaddpdb.getPDBId();\r
3449       PDBEntry pdbentry = null;\r
3450       if (pdbe != null && pdbe.size() > 0)\r
3451       {\r
3452         for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)\r
3453         {\r
3454           pdbentry = (PDBEntry) pdbe.elementAt(pe);\r
3455           if (!pdbentry.getId().equals(pdbEntryString)\r
3456                   && !pdbentry.getFile().equals(pdbFile))\r
3457           {\r
3458             pdbentry = null;\r
3459           }\r
3460           else\r
3461           {\r
3462             continue;\r
3463           }\r
3464         }\r
3465       }\r
3466       if (pdbentry == null)\r
3467       {\r
3468         pdbentry = new PDBEntry();\r
3469         pdbentry.setId(pdbEntryString);\r
3470         pdbentry.setFile(pdbFile);\r
3471         needtoadd = true; // add this new entry to sequence.\r
3472       }\r
3473       // resolve data source\r
3474       // TODO: this code should be a refactored to an io package\r
3475       String protocol = AppletFormatAdapter.resolveProtocol(pdbFile, "PDB");\r
3476       if (protocol == null)\r
3477       {\r
3478         return false;\r
3479       }\r
3480       if (needtoadd)\r
3481       {\r
3482         // make a note of the access mode and add\r
3483         if (pdbentry.getProperty() == null)\r
3484         {\r
3485           pdbentry.setProperty(new Hashtable());\r
3486         }\r
3487         pdbentry.getProperty().put("protocol", protocol);\r
3488         toaddpdb.addPDBId(pdbentry);\r
3489       }\r
3490     }\r
3491     return true;\r
3492   }\r
3493 \r
3494   private Object[] cleanSeqChainArrays(SequenceI[] seqs, String[] chains)\r
3495   {\r
3496     if (seqs != null)\r
3497     {\r
3498       Vector sequences = new Vector();\r
3499       for (int i = 0; i < seqs.length; i++)\r
3500       {\r
3501         if (seqs[i] != null)\r
3502         {\r
3503           sequences.addElement(new Object[]\r
3504           { seqs[i], (chains != null) ? chains[i] : null });\r
3505         }\r
3506       }\r
3507       seqs = new SequenceI[sequences.size()];\r
3508       chains = new String[sequences.size()];\r
3509       for (int i = 0, isize = sequences.size(); i < isize; i++)\r
3510       {\r
3511         Object[] oj = (Object[]) sequences.elementAt(i);\r
3512 \r
3513         seqs[i] = (SequenceI) oj[0];\r
3514         chains[i] = (String) oj[1];\r
3515       }\r
3516     }\r
3517     return new Object[]\r
3518     { seqs, chains };\r
3519 \r
3520   }\r
3521 \r
3522   public void newStructureView(JalviewLite applet, PDBEntry pdb,\r
3523           SequenceI[] seqs, String[] chains, String protocol)\r
3524   {\r
3525     // Scrub any null sequences from the array\r
3526     Object[] sqch = cleanSeqChainArrays(seqs, chains);\r
3527     seqs = (SequenceI[]) sqch[0];\r
3528     chains = (String[]) sqch[1];\r
3529     if (seqs == null || seqs.length == 0)\r
3530     {\r
3531       System.err\r
3532               .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to.");\r
3533     }\r
3534     if (protocol == null || protocol.trim().length() == 0\r
3535             || protocol.equals("null"))\r
3536     {\r
3537       protocol = (String) pdb.getProperty().get("protocol");\r
3538       if (protocol == null)\r
3539       {\r
3540         System.err.println("Couldn't work out protocol to open structure: "\r
3541                 + pdb.getId());\r
3542         return;\r
3543       }\r
3544     }\r
3545     if (applet.useXtrnalSviewer)\r
3546     {\r
3547       // register the association(s) and quit, don't create any windows.\r
3548       if (StructureSelectionManager.getStructureSelectionManager(applet).setMapping(seqs, chains, pdb.getFile(), protocol)==null) {\r
3549         System.err.println("Failed to map "+pdb.getFile()+" ("+protocol+") to any sequences");\r
3550       }\r
3551       return;\r
3552     }\r
3553     if (applet.isAlignPdbStructures() && applet.jmolAvailable)\r
3554     {\r
3555       // can only do alignments with Jmol\r
3556       // find the last jmol window assigned to this alignment\r
3557       jalview.appletgui.AppletJmol ajm = null, tajm;\r
3558       Vector jmols = applet\r
3559               .getAppletWindow(jalview.appletgui.AppletJmol.class);\r
3560       for (int i = 0, iSize = jmols.size(); i < iSize; i++)\r
3561       {\r
3562         tajm = (jalview.appletgui.AppletJmol) jmols.elementAt(i);\r
3563         if (tajm.ap.alignFrame == this)\r
3564         {\r
3565           ajm = tajm;\r
3566           break;\r
3567         }\r
3568       }\r
3569       if (ajm != null)\r
3570       {\r
3571         System.err\r
3572                 .println("Incremental adding and aligning structure to existing Jmol view not yet implemented.");\r
3573         // try and add the pdb structure\r
3574         // ajm.addS\r
3575         ajm = null;\r
3576       }\r
3577     }\r
3578     // otherwise, create a new window\r
3579     if (applet.jmolAvailable)\r
3580     {\r
3581       new jalview.appletgui.AppletJmol(pdb, seqs, chains, alignPanel,\r
3582               protocol);\r
3583       applet.lastFrameX += 40;\r
3584       applet.lastFrameY += 40;\r
3585     }\r
3586     else\r
3587     {\r
3588       new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol);\r
3589     }\r
3590 \r
3591   }\r
3592 \r
3593   public void alignedStructureView(JalviewLite applet, PDBEntry[] pdb,\r
3594           SequenceI[][] seqs, String[][] chains, String[] protocols)\r
3595   {\r
3596     // TODO Auto-generated method stub\r
3597     System.err.println("Aligned Structure View: Not yet implemented.");\r
3598   }\r
3599 \r
3600   /**\r
3601    * modify the current selection, providing the user has not made a selection already.\r
3602    * @param sel - sequences from this alignment\r
3603    * @param csel - columns to be selected on the alignment\r
3604    */\r
3605   public void select(SequenceGroup sel, ColumnSelection csel)\r
3606   {\r
3607     alignPanel.seqPanel.selection(sel, csel, null);\r
3608   }\r
3609 \r
3610   public void scrollTo(int row, int column)\r
3611   {\r
3612     alignPanel.seqPanel.scrollTo(row, column);\r
3613   }\r
3614   public void scrollToRow(int row)\r
3615   {\r
3616     alignPanel.seqPanel.scrollToRow(row);\r
3617   }\r
3618   public void scrollToColumn(int column)\r
3619   {\r
3620     alignPanel.seqPanel.scrollToColumn(column);\r
3621   }\r
3622   /**\r
3623    * @return the alignments unique ID.\r
3624    */\r
3625   public String getSequenceSetId() {\r
3626     return viewport.getSequenceSetId();\r
3627   }\r
3628 \r
3629 \r
3630   /**\r
3631    * Load the (T-Coffee) score file from the specified url\r
3632    *\r
3633    * @param source File/URL/T-COFFEE score file contents\r
3634    * @throws IOException\r
3635    * @return true if alignment was annotated with data from source\r
3636  * @throws SAXException \r
3637  * @throws ParserConfigurationException \r
3638  * @throws ExceptionFileFormatOrSyntax \r
3639  * @throws ExceptionLoadingFailed \r
3640  * @throws ExceptionPermissionDenied \r
3641    */\r
3642   public boolean loadScoreFile( String source ) throws IOException, ExceptionFileFormatOrSyntax, ParserConfigurationException, SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed {\r
3643 \r
3644     TCoffeeScoreFile file = new TCoffeeScoreFile(source, AppletFormatAdapter.checkProtocol(source));\r
3645           if( !file.isValid()) {\r
3646             // TODO: raise dialog for gui\r
3647             System.err.println("Problems parsing T-Coffee scores: "+file.getWarningMessage());\r
3648             System.err.println("Origin was:\n"+source);\r
3649             return false;\r
3650           }\r
3651 \r
3652           /*\r
3653            * check that the score matrix matches the alignment dimensions\r
3654            */\r
3655           AlignmentI aln;\r
3656           if( (aln=viewport.getAlignment()) != null && (aln.getHeight() != file.getHeight() || aln.getWidth() != file.getWidth()) ) {\r
3657             // TODO: raise a dialog box here rather than bomb out.\r
3658             System.err.println("The scores matrix does not match the alignment dimensions");\r
3659 \r
3660           }\r
3661 \r
3662            // TODO add parameter to indicate if matching should be done\r
3663           if (file.annotateAlignment(alignPanel.getAlignment(), false))\r
3664           {\r
3665             alignPanel.fontChanged();\r
3666             tcoffeeColour.setEnabled(true);\r
3667                   // switch to this color\r
3668                   changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));\r
3669                   return true;\r
3670           } else {\r
3671             System.err.println("Problems resolving T-Coffee scores:");\r
3672             if (file.getWarningMessage()!=null) {\r
3673               System.err.println(file.getWarningMessage());\r
3674             }\r
3675           }\r
3676           return false;\r
3677   }\r
3678 \r
3679 \r
3680 }\r