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