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