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