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