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