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