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