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