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