56948e3370b9451f91a0abe8c29cfbcdf7e03f7c
[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].setIncludeAllConsSymbols(viewport
1687                 .isIncludeAllConsensusSymbols());
1688         viewport.alignment.addGroup(gps[g]);
1689         Color col = new Color((int) (Math.random() * 255), (int) (Math
1690                 .random() * 255), (int) (Math.random() * 255));
1691         col = col.brighter();
1692         for (Enumeration sq = gps[g].getSequences(null).elements(); sq
1693                 .hasMoreElements(); viewport.setSequenceColour(
1694                 (SequenceI) sq.nextElement(), col))
1695           ;
1696       }
1697       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
1698       // alignPanel.updateAnnotation();
1699       alignPanel.paintAlignment(true);
1700     }
1701   }
1702
1703   protected void deleteGroups_actionPerformed()
1704   {
1705     viewport.alignment.deleteAllGroups();
1706     viewport.sequenceColours = null;
1707     viewport.setSelectionGroup(null);
1708
1709     alignPanel.paintAlignment(true);
1710   }
1711
1712   public void selectAllSequenceMenuItem_actionPerformed()
1713   {
1714     SequenceGroup sg = new SequenceGroup();
1715     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
1716     {
1717       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
1718     }
1719     sg.setEndRes(viewport.alignment.getWidth() - 1);
1720     viewport.setSelectionGroup(sg);
1721     alignPanel.paintAlignment(true);
1722     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1723   }
1724
1725   public void deselectAllSequenceMenuItem_actionPerformed()
1726   {
1727     if (viewport.cursorMode)
1728     {
1729       alignPanel.seqPanel.keyboardNo1 = null;
1730       alignPanel.seqPanel.keyboardNo2 = null;
1731     }
1732     viewport.setSelectionGroup(null);
1733     viewport.getColumnSelection().clear();
1734     viewport.setSelectionGroup(null);
1735     alignPanel.idPanel.idCanvas.searchResults = null;
1736     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
1737     alignPanel.paintAlignment(true);
1738     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1739   }
1740
1741   public void invertSequenceMenuItem_actionPerformed()
1742   {
1743     SequenceGroup sg = viewport.getSelectionGroup();
1744     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
1745     {
1746       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
1747     }
1748
1749     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1750   }
1751
1752   public void invertColSel_actionPerformed()
1753   {
1754     viewport.invertColumnSelection();
1755     alignPanel.paintAlignment(true);
1756     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1757   }
1758
1759   void trimAlignment(boolean trimLeft)
1760   {
1761     ColumnSelection colSel = viewport.getColumnSelection();
1762     int column;
1763
1764     if (colSel.size() > 0)
1765     {
1766       if (trimLeft)
1767       {
1768         column = colSel.getMin();
1769       }
1770       else
1771       {
1772         column = colSel.getMax();
1773       }
1774
1775       SequenceI[] seqs;
1776       if (viewport.getSelectionGroup() != null)
1777       {
1778         seqs = viewport.getSelectionGroup().getSequencesAsArray(
1779                 viewport.hiddenRepSequences);
1780       }
1781       else
1782       {
1783         seqs = viewport.alignment.getSequencesArray();
1784       }
1785
1786       TrimRegionCommand trimRegion;
1787       if (trimLeft)
1788       {
1789         trimRegion = new TrimRegionCommand("Remove Left",
1790                 TrimRegionCommand.TRIM_LEFT, seqs, column,
1791                 viewport.alignment, viewport.colSel,
1792                 viewport.selectionGroup);
1793         viewport.setStartRes(0);
1794       }
1795       else
1796       {
1797         trimRegion = new TrimRegionCommand("Remove Right",
1798                 TrimRegionCommand.TRIM_RIGHT, seqs, column,
1799                 viewport.alignment, viewport.colSel,
1800                 viewport.selectionGroup);
1801       }
1802
1803       statusBar.setText("Removed " + trimRegion.getSize() + " columns.");
1804
1805       addHistoryItem(trimRegion);
1806
1807       Vector groups = viewport.alignment.getGroups();
1808
1809       for (int i = 0; i < groups.size(); i++)
1810       {
1811         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
1812
1813         if ((trimLeft && !sg.adjustForRemoveLeft(column))
1814                 || (!trimLeft && !sg.adjustForRemoveRight(column)))
1815         {
1816           viewport.alignment.deleteGroup(sg);
1817         }
1818       }
1819
1820       viewport.firePropertyChange("alignment", null, viewport
1821               .getAlignment().getSequences());
1822     }
1823   }
1824
1825   public void removeGappedColumnMenuItem_actionPerformed()
1826   {
1827     int start = 0, end = viewport.alignment.getWidth() - 1;
1828
1829     SequenceI[] seqs;
1830     if (viewport.getSelectionGroup() != null)
1831     {
1832       seqs = viewport.getSelectionGroup().getSequencesAsArray(
1833               viewport.hiddenRepSequences);
1834       start = viewport.getSelectionGroup().getStartRes();
1835       end = viewport.getSelectionGroup().getEndRes();
1836     }
1837     else
1838     {
1839       seqs = viewport.alignment.getSequencesArray();
1840     }
1841
1842     RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
1843             "Remove Gapped Columns", seqs, start, end, viewport.alignment);
1844
1845     addHistoryItem(removeGapCols);
1846
1847     statusBar.setText("Removed " + removeGapCols.getSize()
1848             + " empty columns.");
1849
1850     // This is to maintain viewport position on first residue
1851     // of first sequence
1852     SequenceI seq = viewport.alignment.getSequenceAt(0);
1853     int startRes = seq.findPosition(viewport.startRes);
1854     // ShiftList shifts;
1855     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
1856     // edit.alColumnChanges=shifts.getInverse();
1857     // if (viewport.hasHiddenColumns)
1858     // viewport.getColumnSelection().compensateForEdits(shifts);
1859     viewport.setStartRes(seq.findIndex(startRes) - 1);
1860     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
1861             .getSequences());
1862
1863   }
1864
1865   public void removeAllGapsMenuItem_actionPerformed()
1866   {
1867     int start = 0, end = viewport.alignment.getWidth() - 1;
1868
1869     SequenceI[] seqs;
1870     if (viewport.getSelectionGroup() != null)
1871     {
1872       seqs = viewport.getSelectionGroup().getSequencesAsArray(
1873               viewport.hiddenRepSequences);
1874       start = viewport.getSelectionGroup().getStartRes();
1875       end = viewport.getSelectionGroup().getEndRes();
1876     }
1877     else
1878     {
1879       seqs = viewport.alignment.getSequencesArray();
1880     }
1881
1882     // This is to maintain viewport position on first residue
1883     // of first sequence
1884     SequenceI seq = viewport.alignment.getSequenceAt(0);
1885     int startRes = seq.findPosition(viewport.startRes);
1886
1887     addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
1888             viewport.alignment));
1889
1890     viewport.setStartRes(seq.findIndex(startRes) - 1);
1891
1892     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
1893             .getSequences());
1894
1895   }
1896
1897   public void findMenuItem_actionPerformed()
1898   {
1899     new Finder(alignPanel);
1900   }
1901
1902   /**
1903    * create a new view derived from the current view
1904    * 
1905    * @param viewtitle
1906    * @return frame for the new view
1907    */
1908   public AlignFrame newView(String viewtitle)
1909   {
1910     AlignmentI newal;
1911     if (viewport.hasHiddenRows)
1912     {
1913       newal = new Alignment(viewport.getAlignment().getHiddenSequences()
1914               .getFullAlignment().getSequencesArray());
1915     }
1916     else
1917     {
1918       newal = new Alignment(viewport.alignment.getSequencesArray());
1919     }
1920
1921     if (viewport.alignment.getAlignmentAnnotation() != null)
1922     {
1923       for (int i = 0; i < viewport.alignment.getAlignmentAnnotation().length; i++)
1924       {
1925         if (!viewport.alignment.getAlignmentAnnotation()[i].autoCalculated)
1926         {
1927           newal
1928                   .addAnnotation(viewport.alignment
1929                           .getAlignmentAnnotation()[i]);
1930         }
1931       }
1932     }
1933
1934     AlignFrame newaf = new AlignFrame(newal, viewport.applet, "", false);
1935
1936     newaf.viewport.sequenceSetID = alignPanel.av.getSequenceSetId();
1937     PaintRefresher.Register(alignPanel, alignPanel.av.getSequenceSetId());
1938     PaintRefresher.Register(newaf.alignPanel, newaf.alignPanel.av
1939             .getSequenceSetId());
1940
1941     PaintRefresher.Register(newaf.alignPanel.idPanel.idCanvas,
1942             newaf.alignPanel.av.getSequenceSetId());
1943     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,
1944             newaf.alignPanel.av.getSequenceSetId());
1945
1946     Vector comps = (Vector) PaintRefresher.components.get(viewport
1947             .getSequenceSetId());
1948     int viewSize = -1;
1949     for (int i = 0; i < comps.size(); i++)
1950     {
1951       if (comps.elementAt(i) instanceof AlignmentPanel)
1952       {
1953         viewSize++;
1954       }
1955     }
1956
1957     String title = new String(this.getTitle());
1958     if (viewtitle != null)
1959     {
1960       title = viewtitle + " ( " + title + ")";
1961     }
1962     else
1963     {
1964       if (title.indexOf("(View") > -1)
1965       {
1966         title = title.substring(0, title.indexOf("(View"));
1967       }
1968       title += "(View " + viewSize + ")";
1969     }
1970
1971     newaf.setTitle(title.toString());
1972
1973     newaf.viewport.historyList = viewport.historyList;
1974     newaf.viewport.redoList = viewport.redoList;
1975     return newaf;
1976   }
1977
1978   /**
1979    * 
1980    * @return list of feature groups on the view
1981    */
1982   public String[] getFeatureGroups()
1983   {
1984     FeatureRenderer fr = null;
1985     if (alignPanel != null
1986             && (fr = alignPanel.getFeatureRenderer()) != null)
1987     {
1988       return fr.getGroups();
1989     }
1990     return null;
1991   }
1992
1993   /**
1994    * get sequence feature groups that are hidden or shown
1995    * 
1996    * @param visible
1997    *          true is visible
1998    * @return list
1999    */
2000   public String[] getFeatureGroupsOfState(boolean visible)
2001   {
2002     FeatureRenderer fr = null;
2003     if (alignPanel != null
2004             && (fr = alignPanel.getFeatureRenderer()) != null)
2005     {
2006       return fr.getGroups(visible);
2007     }
2008     return null;
2009   }
2010
2011   /**
2012    * Change the display state for the given feature groups
2013    * 
2014    * @param groups
2015    *          list of group strings
2016    * @param state
2017    *          visible or invisible
2018    */
2019   public void setFeatureGroupState(String[] groups, boolean state)
2020   {
2021     FeatureRenderer fr = null;
2022     this.sequenceFeatures.setState(true);
2023     viewport.showSequenceFeatures(true);
2024     if (alignPanel != null
2025             && (fr = alignPanel.getFeatureRenderer()) != null)
2026     {
2027       fr.setGroupState(groups, state);
2028       alignPanel.seqPanel.seqCanvas.repaint();
2029       if (alignPanel.overviewPanel != null)
2030       {
2031         alignPanel.overviewPanel.updateOverviewImage();
2032       }
2033     }
2034   }
2035
2036   public void seqLimits_itemStateChanged()
2037   {
2038     viewport.setShowJVSuffix(seqLimits.getState());
2039     alignPanel.fontChanged();
2040     alignPanel.paintAlignment(true);
2041   }
2042
2043   protected void colourTextMenuItem_actionPerformed()
2044   {
2045     viewport.setColourText(colourTextMenuItem.getState());
2046     alignPanel.paintAlignment(true);
2047   }
2048
2049   protected void displayNonconservedMenuItem_actionPerformed()
2050   {
2051     viewport.setShowunconserved(displayNonconservedMenuItem.getState());
2052     alignPanel.paintAlignment(true);
2053   }
2054
2055   protected void wrapMenuItem_actionPerformed()
2056   {
2057     viewport.setWrapAlignment(wrapMenuItem.getState());
2058     alignPanel.setWrapAlignment(wrapMenuItem.getState());
2059     scaleAbove.setEnabled(wrapMenuItem.getState());
2060     scaleLeft.setEnabled(wrapMenuItem.getState());
2061     scaleRight.setEnabled(wrapMenuItem.getState());
2062     alignPanel.paintAlignment(true);
2063   }
2064
2065   public void overviewMenuItem_actionPerformed()
2066   {
2067     if (alignPanel.overviewPanel != null)
2068     {
2069       return;
2070     }
2071
2072     Frame frame = new Frame();
2073     OverviewPanel overview = new OverviewPanel(alignPanel);
2074     frame.add(overview);
2075     // +50 must allow for applet frame window
2076     jalview.bin.JalviewLite.addFrame(frame, "Overview " + this.getTitle(),
2077             overview.getPreferredSize().width,
2078             overview.getPreferredSize().height + 50);
2079
2080     frame.pack();
2081     frame.addWindowListener(new WindowAdapter()
2082     {
2083       public void windowClosing(WindowEvent e)
2084       {
2085         alignPanel.setOverviewPanel(null);
2086       };
2087     });
2088
2089     alignPanel.setOverviewPanel(overview);
2090
2091   }
2092
2093   void changeColour(ColourSchemeI cs)
2094   {
2095     int threshold = 0;
2096
2097     if (cs != null)
2098     {
2099       if (viewport.getAbovePIDThreshold())
2100       {
2101         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
2102                 "Background");
2103
2104         cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
2105
2106         viewport.setGlobalColourScheme(cs);
2107       }
2108       else
2109       {
2110         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2111       }
2112
2113       if (viewport.getConservationSelected())
2114       {
2115
2116         Alignment al = (Alignment) viewport.alignment;
2117         Conservation c = new Conservation("All",
2118                 ResidueProperties.propHash, 3, al.getSequences(), 0, al
2119                         .getWidth() - 1);
2120
2121         c.calculate();
2122         c.verdict(false, viewport.ConsPercGaps);
2123
2124         cs.setConservation(c);
2125
2126         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,
2127                 cs, "Background"));
2128
2129       }
2130       else
2131       {
2132         cs.setConservation(null);
2133       }
2134
2135       cs.setConsensus(viewport.hconsensus);
2136
2137     }
2138     viewport.setGlobalColourScheme(cs);
2139
2140     if (viewport.getColourAppliesToAllGroups())
2141     {
2142       Vector groups = viewport.alignment.getGroups();
2143       for (int i = 0; i < groups.size(); i++)
2144       {
2145         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2146
2147         if (cs == null)
2148         {
2149           sg.cs = null;
2150           continue;
2151         }
2152         if (cs instanceof ClustalxColourScheme)
2153         {
2154           sg.cs = new ClustalxColourScheme(sg
2155                   .getSequences(viewport.hiddenRepSequences), sg.getWidth());
2156         }
2157         else
2158         {
2159           try
2160           {
2161             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2162           } catch (Exception ex)
2163           {
2164             ex.printStackTrace();
2165             sg.cs = cs;
2166           }
2167         }
2168
2169         if (viewport.getAbovePIDThreshold()
2170                 || cs instanceof PIDColourScheme
2171                 || cs instanceof Blosum62ColourScheme)
2172         {
2173           sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
2174           sg.cs.setConsensus(AAFrequency.calculate(sg
2175                   .getSequences(viewport.hiddenRepSequences), 0, sg
2176                   .getWidth()));
2177         }
2178         else
2179         {
2180           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2181         }
2182
2183         if (viewport.getConservationSelected())
2184         {
2185           Conservation c = new Conservation("Group",
2186                   ResidueProperties.propHash, 3, sg
2187                           .getSequences(viewport.hiddenRepSequences), 0,
2188                   viewport.alignment.getWidth() - 1);
2189           c.calculate();
2190           c.verdict(false, viewport.ConsPercGaps);
2191           sg.cs.setConservation(c);
2192         }
2193         else
2194         {
2195           sg.cs.setConservation(null);
2196           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2197         }
2198
2199       }
2200     }
2201
2202     if (alignPanel.getOverviewPanel() != null)
2203     {
2204       alignPanel.getOverviewPanel().updateOverviewImage();
2205     }
2206
2207     jalview.structure.StructureSelectionManager
2208             .getStructureSelectionManager().sequenceColoursChanged(
2209                     alignPanel);
2210
2211     alignPanel.paintAlignment(true);
2212   }
2213
2214   protected void modifyPID_actionPerformed()
2215   {
2216     if (viewport.getAbovePIDThreshold()
2217             && viewport.globalColourScheme != null)
2218     {
2219       SliderPanel.setPIDSliderSource(alignPanel, viewport
2220               .getGlobalColourScheme(), "Background");
2221       SliderPanel.showPIDSlider();
2222     }
2223   }
2224
2225   protected void modifyConservation_actionPerformed()
2226   {
2227     if (viewport.getConservationSelected()
2228             && viewport.globalColourScheme != null)
2229     {
2230       SliderPanel.setConservationSlider(alignPanel,
2231               viewport.globalColourScheme, "Background");
2232       SliderPanel.showConservationSlider();
2233     }
2234   }
2235
2236   protected void conservationMenuItem_actionPerformed()
2237   {
2238     viewport.setConservationSelected(conservationMenuItem.getState());
2239
2240     viewport.setAbovePIDThreshold(false);
2241     abovePIDThreshold.setState(false);
2242
2243     changeColour(viewport.getGlobalColourScheme());
2244
2245     modifyConservation_actionPerformed();
2246   }
2247
2248   public void abovePIDThreshold_actionPerformed()
2249   {
2250     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());
2251
2252     conservationMenuItem.setState(false);
2253     viewport.setConservationSelected(false);
2254
2255     changeColour(viewport.getGlobalColourScheme());
2256
2257     modifyPID_actionPerformed();
2258   }
2259
2260   public void sortPairwiseMenuItem_actionPerformed()
2261   {
2262     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2263     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
2264             .getAlignment().getSequenceAt(0), null);
2265
2266     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2267             viewport.alignment));
2268     alignPanel.paintAlignment(true);
2269   }
2270
2271   public void sortIDMenuItem_actionPerformed()
2272   {
2273     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2274     AlignmentSorter.sortByID(viewport.getAlignment());
2275     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
2276     alignPanel.paintAlignment(true);
2277   }
2278
2279   public void sortLengthMenuItem_actionPerformed()
2280   {
2281     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2282     AlignmentSorter.sortByLength(viewport.getAlignment());
2283     addHistoryItem(new OrderCommand("Length Sort", oldOrder, viewport.alignment));
2284     alignPanel.paintAlignment(true);
2285   }
2286
2287   public void sortGroupMenuItem_actionPerformed()
2288   {
2289     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2290     AlignmentSorter.sortByGroup(viewport.getAlignment());
2291     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
2292             viewport.alignment));
2293     alignPanel.paintAlignment(true);
2294
2295   }
2296
2297   public void removeRedundancyMenuItem_actionPerformed()
2298   {
2299     new RedundancyPanel(alignPanel);
2300   }
2301
2302   public void pairwiseAlignmentMenuItem_actionPerformed()
2303   {
2304     if (viewport.getSelectionGroup() != null
2305             && viewport.getSelectionGroup().getSize() > 1)
2306     {
2307       Frame frame = new Frame();
2308       frame.add(new PairwiseAlignPanel(alignPanel));
2309       jalview.bin.JalviewLite.addFrame(frame, "Pairwise Alignment", 600,
2310               500);
2311     }
2312   }
2313
2314   public void PCAMenuItem_actionPerformed()
2315   {
2316     // are the sequences aligned?
2317     if (!viewport.alignment.isAligned(false))
2318     {
2319       SequenceI current;
2320       int Width = viewport.getAlignment().getWidth();
2321
2322       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2323       {
2324         current = viewport.getAlignment().getSequenceAt(i);
2325
2326         if (current.getLength() < Width)
2327         {
2328           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2329         }
2330       }
2331       alignPanel.paintAlignment(true);
2332     }
2333
2334     if ((viewport.getSelectionGroup() != null
2335             && viewport.getSelectionGroup().getSize() < 4 && viewport
2336             .getSelectionGroup().getSize() > 0)
2337             || viewport.getAlignment().getHeight() < 4)
2338     {
2339       return;
2340     }
2341
2342     try
2343     {
2344       new PCAPanel(viewport);
2345     } catch (java.lang.OutOfMemoryError ex)
2346     {
2347     }
2348
2349   }
2350
2351   public void averageDistanceTreeMenuItem_actionPerformed()
2352   {
2353     NewTreePanel("AV", "PID", "Average distance tree using PID");
2354   }
2355
2356   public void neighbourTreeMenuItem_actionPerformed()
2357   {
2358     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2359   }
2360
2361   protected void njTreeBlosumMenuItem_actionPerformed()
2362   {
2363     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2364   }
2365
2366   protected void avTreeBlosumMenuItem_actionPerformed()
2367   {
2368     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2369   }
2370
2371   void NewTreePanel(String type, String pwType, String title)
2372   {
2373     // are the sequences aligned?
2374     if (!viewport.alignment.isAligned(false))
2375     {
2376       SequenceI current;
2377       int Width = viewport.getAlignment().getWidth();
2378
2379       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2380       {
2381         current = viewport.getAlignment().getSequenceAt(i);
2382
2383         if (current.getLength() < Width)
2384         {
2385           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2386         }
2387       }
2388       alignPanel.paintAlignment(true);
2389
2390     }
2391
2392     if ((viewport.getSelectionGroup() != null && viewport
2393             .getSelectionGroup().getSize() > 1)
2394             || (viewport.getSelectionGroup() == null && viewport.alignment
2395                     .getHeight() > 1))
2396     {
2397       final TreePanel tp = new TreePanel(viewport, type, pwType);
2398
2399       addTreeMenuItem(tp, title);
2400
2401       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);
2402     }
2403   }
2404
2405   void loadTree_actionPerformed()
2406   {
2407     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
2408     cap.setText("Paste your Newick tree file here.");
2409     cap.setTreeImport();
2410     Frame frame = new Frame();
2411     frame.add(cap);
2412     jalview.bin.JalviewLite.addFrame(frame, "Paste Newick file ", 400, 300);
2413   }
2414
2415   public void loadTree(jalview.io.NewickFile tree, String treeFile)
2416   {
2417     TreePanel tp = new TreePanel(viewport, treeFile, "From File - ", tree);
2418     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);
2419     addTreeMenuItem(tp, treeFile);
2420   }
2421
2422   /**
2423    * sort the alignment using the given treePanel
2424    * 
2425    * @param treePanel
2426    *          tree used to sort view
2427    * @param title
2428    *          string used for undo event name
2429    */
2430   public void sortByTree(TreePanel treePanel, String title)
2431   {
2432     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2433     AlignmentSorter
2434             .sortByTree(viewport.getAlignment(), treePanel.getTree());
2435     // addHistoryItem(new HistoryItem("Sort", viewport.alignment,
2436     // HistoryItem.SORT));
2437     addHistoryItem(new OrderCommand("Order by " + title, oldOrder,
2438             viewport.alignment));
2439     alignPanel.paintAlignment(true);
2440   }
2441
2442   /**
2443    * Do any automatic reordering of the alignment and add the necessary bits to
2444    * the menu structure for the new tree
2445    * 
2446    * @param treePanel
2447    * @param title
2448    */
2449   protected void addTreeMenuItem(final TreePanel treePanel,
2450           final String title)
2451   {
2452     final MenuItem item = new MenuItem(title);
2453     sortByTreeMenu.add(item);
2454     item.addActionListener(new java.awt.event.ActionListener()
2455     {
2456       public void actionPerformed(ActionEvent evt)
2457       {
2458         sortByTree(treePanel, title); // treePanel.getTitle());
2459       }
2460     });
2461
2462     treePanel.addWindowListener(new WindowAdapter()
2463     {
2464       public void windowOpened(WindowEvent e)
2465       {
2466         if (viewport.sortByTree)
2467         {
2468           sortByTree(treePanel, title);
2469         }
2470         super.windowOpened(e);
2471       }
2472
2473       public void windowClosing(WindowEvent e)
2474       {
2475         sortByTreeMenu.remove(item);
2476       };
2477     });
2478   }
2479
2480   protected void documentation_actionPerformed()
2481   {
2482     showURL("http://www.jalview.org/help.html", "HELP");
2483   }
2484
2485   protected void about_actionPerformed()
2486   {
2487
2488     class AboutPanel extends Canvas
2489     {
2490       String version;
2491
2492       String builddate;
2493
2494       public AboutPanel(String version, String builddate)
2495       {
2496         this.version = version;
2497         this.builddate = builddate;
2498       }
2499
2500       public void paint(Graphics g)
2501       {
2502         g.setColor(Color.white);
2503         g.fillRect(0, 0, getSize().width, getSize().height);
2504         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2505         FontMetrics fm = g.getFontMetrics();
2506         int fh = fm.getHeight();
2507         int y = 5, x = 7;
2508         g.setColor(Color.black);
2509         // TODO: update this text for each release or centrally store it for
2510         // lite and application
2511         g.setFont(new Font("Helvetica", Font.BOLD, 14));
2512         g.drawString("JalviewLite - Release " + version, x, y += fh);
2513         g.setFont(new Font("Helvetica", Font.BOLD, 12));
2514         g.drawString("Build date: " + builddate, x, y += fh);
2515         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2516         g
2517                 .drawString(
2518                         "Authors:  Andrew Waterhouse, Jim Procter, Michele Clamp, James Cuff, Steve Searle,",
2519                         x, y += fh * 1.5);
2520         g.drawString("David Martin & Geoff Barton.", x + 50, y += fh);
2521         g
2522                 .drawString(
2523                         "Development managed by The Barton Group, University of Dundee, Scotland, UK.",
2524                         x, y += fh);
2525         g
2526                 .drawString(
2527                         "For help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list",
2528                         x, y += fh);
2529         g.drawString("If  you use Jalview, please cite:", x, y += fh + 8);
2530         g
2531                 .drawString(
2532                         "Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)",
2533                         x, y += fh);
2534         g
2535                 .drawString(
2536                         "Jalview Version 2 - a multiple sequence alignment editor and analysis workbench",
2537                         x, y += fh);
2538         g.drawString("Bioinformatics doi: 10.1093/bioinformatics/btp033",
2539                 x, y += fh);
2540       }
2541     }
2542
2543     Frame frame = new Frame();
2544     frame.add(new AboutPanel(JalviewLite.getVersion(), JalviewLite
2545             .getBuildDate()));
2546     jalview.bin.JalviewLite.addFrame(frame, "Jalview", 580, 220);
2547
2548   }
2549
2550   public void showURL(String url, String target)
2551   {
2552     if (viewport.applet == null)
2553     {
2554       System.out.println("Not running as applet - no browser available.");
2555     }
2556     else
2557     {
2558       try
2559       {
2560         if (url.indexOf(":") == -1)
2561         {
2562           // TODO: verify (Bas Vroling bug) prepend codebase or server URL to
2563           // form valid URL
2564           if (url.indexOf("/") == 0)
2565           {
2566             String codebase = viewport.applet.getCodeBase().toString();
2567             url = codebase.substring(0, codebase.length()
2568                     - viewport.applet.getCodeBase().getFile().length())
2569                     + url;
2570           }
2571           else
2572           {
2573             url = viewport.applet.getCodeBase() + url;
2574           }
2575           System.out.println("Show url (prepended codebase): " + url);
2576         }
2577         else
2578         {
2579           System.out.println("Show url: " + url);
2580         }
2581         viewport.applet.getAppletContext().showDocument(
2582                 new java.net.URL(url), target);
2583       } catch (Exception ex)
2584       {
2585         ex.printStackTrace();
2586       }
2587     }
2588   }
2589
2590   // ////////////////////////////////////////////////////////////////////////////////
2591   // JBuilder Graphics here
2592
2593   MenuBar alignFrameMenuBar = new MenuBar();
2594
2595   Menu fileMenu = new Menu("File");
2596
2597   MenuItem loadApplication = new MenuItem("View in Full Application");
2598
2599   MenuItem loadTree = new MenuItem("Load Associated Tree ...");
2600
2601   MenuItem loadAnnotations = new MenuItem("Load Features/Annotations ...");
2602
2603   MenuItem outputFeatures = new MenuItem("Export Features ...");
2604
2605   MenuItem outputAnnotations = new MenuItem("Export Annotations ...");
2606
2607   MenuItem closeMenuItem = new MenuItem("Close");
2608
2609   Menu editMenu = new Menu("Edit");
2610
2611   Menu viewMenu = new Menu("View");
2612
2613   Menu colourMenu = new Menu("Colour");
2614
2615   Menu calculateMenu = new Menu("Calculate");
2616
2617   MenuItem selectAllSequenceMenuItem = new MenuItem("Select all");
2618
2619   MenuItem deselectAllSequenceMenuItem = new MenuItem("Deselect All");
2620
2621   MenuItem invertSequenceMenuItem = new MenuItem("Invert Selection");
2622
2623   MenuItem remove2LeftMenuItem = new MenuItem();
2624
2625   MenuItem remove2RightMenuItem = new MenuItem();
2626
2627   MenuItem removeGappedColumnMenuItem = new MenuItem();
2628
2629   MenuItem removeAllGapsMenuItem = new MenuItem();
2630
2631   CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();
2632
2633   CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();
2634
2635   MenuItem sortPairwiseMenuItem = new MenuItem();
2636
2637   MenuItem sortIDMenuItem = new MenuItem();
2638
2639   MenuItem sortLengthMenuItem = new MenuItem();
2640
2641   MenuItem sortGroupMenuItem = new MenuItem();
2642
2643   MenuItem removeRedundancyMenuItem = new MenuItem();
2644
2645   MenuItem pairwiseAlignmentMenuItem = new MenuItem();
2646
2647   MenuItem PCAMenuItem = new MenuItem();
2648
2649   MenuItem averageDistanceTreeMenuItem = new MenuItem();
2650
2651   MenuItem neighbourTreeMenuItem = new MenuItem();
2652
2653   BorderLayout borderLayout1 = new BorderLayout();
2654
2655   public Label statusBar = new Label();
2656
2657   Menu outputTextboxMenu = new Menu();
2658
2659   MenuItem clustalColour = new MenuItem();
2660
2661   MenuItem zappoColour = new MenuItem();
2662
2663   MenuItem taylorColour = new MenuItem();
2664
2665   MenuItem hydrophobicityColour = new MenuItem();
2666
2667   MenuItem helixColour = new MenuItem();
2668
2669   MenuItem strandColour = new MenuItem();
2670
2671   MenuItem turnColour = new MenuItem();
2672
2673   MenuItem buriedColour = new MenuItem();
2674
2675   MenuItem userDefinedColour = new MenuItem();
2676
2677   MenuItem PIDColour = new MenuItem();
2678
2679   MenuItem BLOSUM62Colour = new MenuItem();
2680
2681   MenuItem njTreeBlosumMenuItem = new MenuItem();
2682
2683   MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();
2684
2685   CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();
2686
2687   CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();
2688
2689   CheckboxMenuItem displayNonconservedMenuItem = new CheckboxMenuItem();
2690
2691   MenuItem alProperties = new MenuItem("Alignment Properties...");
2692
2693   MenuItem overviewMenuItem = new MenuItem();
2694
2695   MenuItem undoMenuItem = new MenuItem();
2696
2697   MenuItem redoMenuItem = new MenuItem();
2698
2699   CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
2700
2701   MenuItem noColourmenuItem = new MenuItem();
2702
2703   CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();
2704
2705   CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();
2706
2707   MenuItem findMenuItem = new MenuItem();
2708
2709   CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();
2710
2711   MenuItem nucleotideColour = new MenuItem();
2712
2713   MenuItem deleteGroups = new MenuItem();
2714
2715   MenuItem grpsFromSelection = new MenuItem();
2716
2717   MenuItem delete = new MenuItem();
2718
2719   MenuItem copy = new MenuItem();
2720
2721   MenuItem cut = new MenuItem();
2722
2723   Menu pasteMenu = new Menu();
2724
2725   MenuItem pasteNew = new MenuItem();
2726
2727   MenuItem pasteThis = new MenuItem();
2728
2729   CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();
2730
2731   MenuItem font = new MenuItem();
2732
2733   CheckboxMenuItem scaleAbove = new CheckboxMenuItem();
2734
2735   CheckboxMenuItem scaleLeft = new CheckboxMenuItem();
2736
2737   CheckboxMenuItem scaleRight = new CheckboxMenuItem();
2738
2739   MenuItem modifyPID = new MenuItem();
2740
2741   MenuItem modifyConservation = new MenuItem();
2742
2743   CheckboxMenuItem autoCalculate = new CheckboxMenuItem(
2744           "Autocalculate Consensus", true);
2745
2746   Menu sortByTreeMenu = new Menu();
2747
2748   Menu sort = new Menu();
2749
2750   Menu calculate = new Menu();
2751
2752   MenuItem inputText = new MenuItem();
2753
2754   Menu helpMenu = new Menu();
2755
2756   MenuItem documentation = new MenuItem();
2757
2758   MenuItem about = new MenuItem();
2759
2760   CheckboxMenuItem seqLimits = new CheckboxMenuItem();
2761
2762   CheckboxMenuItem centreColumnLabelFlag = new CheckboxMenuItem();
2763
2764   CheckboxMenuItem followMouseOverFlag = new CheckboxMenuItem();
2765
2766   private void jbInit() throws Exception
2767   {
2768
2769     setMenuBar(alignFrameMenuBar);
2770
2771     MenuItem item;
2772
2773     // dynamically fill save as menu with available formats
2774     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)
2775     {
2776
2777       item = new MenuItem(
2778               jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);
2779
2780       item.addActionListener(new java.awt.event.ActionListener()
2781       {
2782         public void actionPerformed(ActionEvent e)
2783         {
2784           outputText_actionPerformed(e);
2785         }
2786       });
2787
2788       outputTextboxMenu.add(item);
2789     }
2790     closeMenuItem.addActionListener(this);
2791     loadApplication.addActionListener(this);
2792
2793     loadTree.addActionListener(this);
2794     loadAnnotations.addActionListener(this);
2795     outputFeatures.addActionListener(this);
2796     outputAnnotations.addActionListener(this);
2797     selectAllSequenceMenuItem.addActionListener(this);
2798     deselectAllSequenceMenuItem.addActionListener(this);
2799     invertSequenceMenuItem.addActionListener(this);
2800     remove2LeftMenuItem.setLabel("Remove Left");
2801     remove2LeftMenuItem.addActionListener(this);
2802     remove2RightMenuItem.setLabel("Remove Right");
2803     remove2RightMenuItem.addActionListener(this);
2804     removeGappedColumnMenuItem.setLabel("Remove Empty Columns");
2805     removeGappedColumnMenuItem.addActionListener(this);
2806     removeAllGapsMenuItem.setLabel("Remove All Gaps");
2807     removeAllGapsMenuItem.addActionListener(this);
2808     viewBoxesMenuItem.setLabel("Boxes");
2809     viewBoxesMenuItem.setState(true);
2810     viewBoxesMenuItem.addItemListener(this);
2811     viewTextMenuItem.setLabel("Text");
2812     viewTextMenuItem.setState(true);
2813     viewTextMenuItem.addItemListener(this);
2814     sortPairwiseMenuItem.setLabel("by Pairwise Identity");
2815     sortPairwiseMenuItem.addActionListener(this);
2816     sortIDMenuItem.setLabel("by ID");
2817     sortIDMenuItem.addActionListener(this);
2818     sortLengthMenuItem.setLabel("by Length");
2819     sortLengthMenuItem.addActionListener(this);
2820     sortGroupMenuItem.setLabel("by Group");
2821     sortGroupMenuItem.addActionListener(this);
2822     removeRedundancyMenuItem.setLabel("Remove Redundancy...");
2823     removeRedundancyMenuItem.addActionListener(this);
2824     pairwiseAlignmentMenuItem.setLabel("Pairwise Alignments...");
2825     pairwiseAlignmentMenuItem.addActionListener(this);
2826     PCAMenuItem.setLabel("Principal Component Analysis");
2827     PCAMenuItem.addActionListener(this);
2828     averageDistanceTreeMenuItem
2829             .setLabel("Average Distance Using % Identity");
2830     averageDistanceTreeMenuItem.addActionListener(this);
2831     neighbourTreeMenuItem.setLabel("Neighbour Joining Using % Identity");
2832     neighbourTreeMenuItem.addActionListener(this);
2833     statusBar.setBackground(Color.white);
2834     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
2835     statusBar.setText("Status bar");
2836     outputTextboxMenu.setLabel("Output to Textbox");
2837     clustalColour.setLabel("Clustalx");
2838
2839     clustalColour.addActionListener(this);
2840     zappoColour.setLabel("Zappo");
2841     zappoColour.addActionListener(this);
2842     taylorColour.setLabel("Taylor");
2843     taylorColour.addActionListener(this);
2844     hydrophobicityColour.setLabel("Hydrophobicity");
2845     hydrophobicityColour.addActionListener(this);
2846     helixColour.setLabel("Helix Propensity");
2847     helixColour.addActionListener(this);
2848     strandColour.setLabel("Strand Propensity");
2849     strandColour.addActionListener(this);
2850     turnColour.setLabel("Turn Propensity");
2851     turnColour.addActionListener(this);
2852     buriedColour.setLabel("Buried Index");
2853     buriedColour.addActionListener(this);
2854     userDefinedColour.setLabel("User Defined...");
2855     userDefinedColour.addActionListener(this);
2856     PIDColour.setLabel("Percentage Identity");
2857     PIDColour.addActionListener(this);
2858     BLOSUM62Colour.setLabel("BLOSUM62 Score");
2859     BLOSUM62Colour.addActionListener(this);
2860     avDistanceTreeBlosumMenuItem
2861             .setLabel("Average Distance Using BLOSUM62");
2862     avDistanceTreeBlosumMenuItem.addActionListener(this);
2863     njTreeBlosumMenuItem.setLabel("Neighbour Joining Using BLOSUM62");
2864     njTreeBlosumMenuItem.addActionListener(this);
2865     annotationPanelMenuItem.setLabel("Show Annotations");
2866     annotationPanelMenuItem.addItemListener(this);
2867     colourTextMenuItem.setLabel("Colour Text");
2868     colourTextMenuItem.addItemListener(this);
2869     displayNonconservedMenuItem.setLabel("Show non-conserved");
2870     displayNonconservedMenuItem.addItemListener(this);
2871     alProperties.addActionListener(this);
2872     overviewMenuItem.setLabel("Overview Window");
2873     overviewMenuItem.addActionListener(this);
2874     undoMenuItem.setEnabled(false);
2875     undoMenuItem.setLabel("Undo");
2876     undoMenuItem.addActionListener(this);
2877     redoMenuItem.setEnabled(false);
2878     redoMenuItem.setLabel("Redo");
2879     redoMenuItem.addActionListener(this);
2880     conservationMenuItem.setLabel("by Conservation");
2881     conservationMenuItem.addItemListener(this);
2882     noColourmenuItem.setLabel("None");
2883     noColourmenuItem.addActionListener(this);
2884     wrapMenuItem.setLabel("Wrap");
2885     wrapMenuItem.addItemListener(this);
2886     renderGapsMenuItem.setLabel("Show Gaps");
2887     renderGapsMenuItem.setState(true);
2888     renderGapsMenuItem.addItemListener(this);
2889     findMenuItem.setLabel("Find...");
2890     findMenuItem.addActionListener(this);
2891     abovePIDThreshold.setLabel("Above Identity Threshold");
2892     abovePIDThreshold.addItemListener(this);
2893     nucleotideColour.setLabel("Nucleotide");
2894     nucleotideColour.addActionListener(this);
2895     deleteGroups.setLabel("Undefine Groups");
2896     deleteGroups.addActionListener(this);
2897     grpsFromSelection.setLabel("Make Groups for selection");
2898     grpsFromSelection.addActionListener(this);
2899     copy.setLabel("Copy");
2900     copy.addActionListener(this);
2901     cut.setLabel("Cut");
2902     cut.addActionListener(this);
2903     delete.setLabel("Delete");
2904     delete.addActionListener(this);
2905     pasteMenu.setLabel("Paste");
2906     pasteNew.setLabel("To New Alignment");
2907     pasteNew.addActionListener(this);
2908     pasteThis.setLabel("Add To This Alignment");
2909     pasteThis.addActionListener(this);
2910     applyToAllGroups.setLabel("Apply Colour To All Groups");
2911     applyToAllGroups.setState(true);
2912     applyToAllGroups.addItemListener(this);
2913     font.setLabel("Font...");
2914     font.addActionListener(this);
2915     scaleAbove.setLabel("Scale Above");
2916     scaleAbove.setState(true);
2917     scaleAbove.setEnabled(false);
2918     scaleAbove.addItemListener(this);
2919     scaleLeft.setEnabled(false);
2920     scaleLeft.setState(true);
2921     scaleLeft.setLabel("Scale Left");
2922     scaleLeft.addItemListener(this);
2923     scaleRight.setEnabled(false);
2924     scaleRight.setState(true);
2925     scaleRight.setLabel("Scale Right");
2926     scaleRight.addItemListener(this);
2927     modifyPID.setLabel("Modify Identity Threshold...");
2928     modifyPID.addActionListener(this);
2929     modifyConservation.setLabel("Modify Conservation Threshold...");
2930     modifyConservation.addActionListener(this);
2931     sortByTreeMenu.setLabel("By Tree Order");
2932     sort.setLabel("Sort");
2933     calculate.setLabel("Calculate Tree");
2934     autoCalculate.addItemListener(this);
2935     inputText.setLabel("Input from textbox");
2936     inputText.addActionListener(this);
2937     centreColumnLabelFlag.setLabel("Centre column labels");
2938     centreColumnLabelFlag.addItemListener(this);
2939     followMouseOverFlag.setLabel("Automatic Scrolling");
2940     followMouseOverFlag.addItemListener(this);
2941     helpMenu.setLabel("Help");
2942     documentation.setLabel("Documentation");
2943     documentation.addActionListener(this);
2944
2945     about.setLabel("About...");
2946     about.addActionListener(this);
2947     seqLimits.setState(true);
2948     seqLimits.setLabel("Show Sequence Limits");
2949     seqLimits.addItemListener(this);
2950     featureSettings.setLabel("Feature Settings...");
2951     featureSettings.addActionListener(this);
2952     sequenceFeatures.setLabel("Sequence Features");
2953     sequenceFeatures.addItemListener(this);
2954     sequenceFeatures.setState(false);
2955     annotationColour.setLabel("by Annotation...");
2956     annotationColour.addActionListener(this);
2957     invertSequenceMenuItem.setLabel("Invert Sequence Selection");
2958     invertColSel.setLabel("Invert Column Selection");
2959     menu1.setLabel("Show");
2960     showColumns.setLabel("All Columns ");
2961     showSeqs.setLabel("All Sequences");
2962     menu2.setLabel("Hide");
2963     hideColumns.setLabel("Selected Columns");
2964     hideSequences.setLabel("Selected Sequences");
2965     hideAllButSelection.setLabel("All but Selected Region (Shift+Ctrl+H)");
2966     hideAllSelection.setLabel("Selected Region");
2967     showAllHidden.setLabel("All Sequences and Columns");
2968     invertColSel.addActionListener(this);
2969     showColumns.addActionListener(this);
2970     showSeqs.addActionListener(this);
2971     hideColumns.addActionListener(this);
2972     hideSequences.addActionListener(this);
2973     hideAllButSelection.addActionListener(this);
2974     hideAllSelection.addActionListener(this);
2975     showAllHidden.addActionListener(this);
2976     formatMenu.setLabel("Format");
2977     selectMenu.setLabel("Select");
2978     newView.setLabel("New View");
2979     newView.addActionListener(this);
2980     alignFrameMenuBar.add(fileMenu);
2981     alignFrameMenuBar.add(editMenu);
2982     alignFrameMenuBar.add(selectMenu);
2983     alignFrameMenuBar.add(viewMenu);
2984     alignFrameMenuBar.add(formatMenu);
2985     alignFrameMenuBar.add(colourMenu);
2986     alignFrameMenuBar.add(calculateMenu);
2987     alignFrameMenuBar.add(helpMenu);
2988
2989     fileMenu.add(inputText);
2990     fileMenu.add(loadTree);
2991     fileMenu.add(loadAnnotations);
2992
2993     fileMenu.addSeparator();
2994     fileMenu.add(outputTextboxMenu);
2995     fileMenu.add(outputFeatures);
2996     fileMenu.add(outputAnnotations);
2997
2998     if (jalviewServletURL != null)
2999     {
3000       fileMenu.add(loadApplication);
3001     }
3002
3003     fileMenu.addSeparator();
3004     fileMenu.add(closeMenuItem);
3005
3006     editMenu.add(undoMenuItem);
3007     editMenu.add(redoMenuItem);
3008     editMenu.add(cut);
3009     editMenu.add(copy);
3010     editMenu.add(pasteMenu);
3011     editMenu.add(delete);
3012     editMenu.addSeparator();
3013     editMenu.add(remove2LeftMenuItem);
3014     editMenu.add(remove2RightMenuItem);
3015     editMenu.add(removeGappedColumnMenuItem);
3016     editMenu.add(removeAllGapsMenuItem);
3017     editMenu.add(removeRedundancyMenuItem);
3018     viewMenu.add(newView);
3019     viewMenu.addSeparator();
3020     viewMenu.add(menu1);
3021     viewMenu.add(menu2);
3022     viewMenu.addSeparator();
3023     viewMenu.add(followMouseOverFlag);
3024     viewMenu.add(annotationPanelMenuItem);
3025     viewMenu.addSeparator();
3026     viewMenu.add(sequenceFeatures);
3027     viewMenu.add(featureSettings);
3028     viewMenu.addSeparator();
3029     viewMenu.add(alProperties);
3030     viewMenu.addSeparator();
3031     viewMenu.add(overviewMenuItem);
3032     colourMenu.add(applyToAllGroups);
3033     colourMenu.addSeparator();
3034     colourMenu.add(noColourmenuItem);
3035     colourMenu.add(clustalColour);
3036     colourMenu.add(BLOSUM62Colour);
3037     colourMenu.add(PIDColour);
3038     colourMenu.add(zappoColour);
3039     colourMenu.add(taylorColour);
3040     colourMenu.add(hydrophobicityColour);
3041     colourMenu.add(helixColour);
3042     colourMenu.add(strandColour);
3043     colourMenu.add(turnColour);
3044     colourMenu.add(buriedColour);
3045     colourMenu.add(nucleotideColour);
3046     colourMenu.add(userDefinedColour);
3047     colourMenu.addSeparator();
3048     colourMenu.add(conservationMenuItem);
3049     colourMenu.add(modifyConservation);
3050     colourMenu.add(abovePIDThreshold);
3051     colourMenu.add(modifyPID);
3052     colourMenu.add(annotationColour);
3053     calculateMenu.add(sort);
3054     calculateMenu.add(calculate);
3055     calculateMenu.addSeparator();
3056     calculateMenu.add(pairwiseAlignmentMenuItem);
3057     calculateMenu.add(PCAMenuItem);
3058     calculateMenu.add(autoCalculate);
3059     this.add(statusBar, BorderLayout.SOUTH);
3060     pasteMenu.add(pasteNew);
3061     pasteMenu.add(pasteThis);
3062     sort.add(sortIDMenuItem);
3063     sort.add(sortLengthMenuItem);
3064     sort.add(sortByTreeMenu);
3065     sort.add(sortGroupMenuItem);
3066     sort.add(sortPairwiseMenuItem);
3067     calculate.add(averageDistanceTreeMenuItem);
3068     calculate.add(neighbourTreeMenuItem);
3069     calculate.add(avDistanceTreeBlosumMenuItem);
3070     calculate.add(njTreeBlosumMenuItem);
3071     helpMenu.add(documentation);
3072     helpMenu.add(about);
3073     menu1.add(showColumns);
3074     menu1.add(showSeqs);
3075     menu1.add(showAllHidden);
3076     menu2.add(hideColumns);
3077     menu2.add(hideSequences);
3078     menu2.add(hideAllSelection);
3079     menu2.add(hideAllButSelection);
3080     formatMenu.add(font);
3081     formatMenu.add(seqLimits);
3082     formatMenu.add(wrapMenuItem);
3083     formatMenu.add(scaleAbove);
3084     formatMenu.add(scaleLeft);
3085     formatMenu.add(scaleRight);
3086     formatMenu.add(viewBoxesMenuItem);
3087     formatMenu.add(viewTextMenuItem);
3088     formatMenu.add(colourTextMenuItem);
3089     formatMenu.add(displayNonconservedMenuItem);
3090     formatMenu.add(renderGapsMenuItem);
3091     formatMenu.add(centreColumnLabelFlag);
3092     selectMenu.add(findMenuItem);
3093     selectMenu.addSeparator();
3094     selectMenu.add(selectAllSequenceMenuItem);
3095     selectMenu.add(deselectAllSequenceMenuItem);
3096     selectMenu.add(invertSequenceMenuItem);
3097     selectMenu.add(invertColSel);
3098     selectMenu.add(grpsFromSelection);
3099     selectMenu.add(deleteGroups);
3100
3101   }
3102
3103   MenuItem featureSettings = new MenuItem();
3104
3105   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();
3106
3107   MenuItem annotationColour = new MenuItem();
3108
3109   MenuItem invertColSel = new MenuItem();
3110
3111   Menu menu1 = new Menu();
3112
3113   MenuItem showColumns = new MenuItem();
3114
3115   MenuItem showSeqs = new MenuItem();
3116
3117   Menu menu2 = new Menu();
3118
3119   MenuItem hideColumns = new MenuItem();
3120
3121   MenuItem hideSequences = new MenuItem();
3122
3123   MenuItem hideAllButSelection = new MenuItem();
3124
3125   MenuItem hideAllSelection = new MenuItem();
3126
3127   MenuItem showAllHidden = new MenuItem();
3128
3129   Menu formatMenu = new Menu();
3130
3131   Menu selectMenu = new Menu();
3132
3133   MenuItem newView = new MenuItem();
3134
3135   /**
3136    * Attach the alignFrame panels after embedding menus, if necessary. This used
3137    * to be called setEmbedded, but is now creates the dropdown menus in a
3138    * platform independent manner to avoid OSX/Mac menu appendage daftness.
3139    * 
3140    * @param reallyEmbedded
3141    *          true to attach the view to the applet area on the page rather than
3142    *          in a new window
3143    */
3144   public void createAlignFrameWindow(boolean reallyEmbedded, String title)
3145   {
3146     if (reallyEmbedded)
3147     {
3148       // ////
3149       // Explicly build the embedded menu panel for the on-page applet
3150       //
3151       // view cannot be closed if its actually on the page
3152       fileMenu.remove(closeMenuItem);
3153       fileMenu.remove(3); // Remove Seperator
3154       embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, "Arial",
3155               Font.PLAIN, 10, false); // use our own fonts.
3156       // and actually add the components to the applet area
3157       viewport.applet.setLayout(new BorderLayout());
3158       viewport.applet.add(embeddedMenu, BorderLayout.NORTH);
3159       viewport.applet.add(statusBar, BorderLayout.SOUTH);
3160       alignPanel.setSize(viewport.applet.getSize().width, viewport.applet
3161               .getSize().height
3162               - embeddedMenu.HEIGHT - statusBar.HEIGHT);
3163       viewport.applet.add(alignPanel, BorderLayout.CENTER);
3164       viewport.applet.validate();
3165     }
3166     else
3167     {
3168       // //////
3169       // test and embed menu bar if necessary.
3170       //
3171       if (embedMenuIfNeeded(alignPanel))
3172       {
3173         // adjust for status bar height too
3174         alignPanel.setSize(getSize().width, getSize().height
3175                 - statusBar.HEIGHT);
3176       }
3177       add(statusBar, BorderLayout.SOUTH);
3178       add(alignPanel, BorderLayout.CENTER);
3179       // and register with the applet so it can pass external API calls to us
3180       jalview.bin.JalviewLite.addFrame(this, title, DEFAULT_WIDTH,
3181               DEFAULT_HEIGHT);
3182     }
3183   }
3184 }