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