centrecolumnlabels format menu item and parameter added to applet
[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     }
1041     catch (java.net.MalformedURLException ex)
1042     {
1043       url = viewport.applet.getCodeBase() + url;
1044     }
1045     return url;
1046   }
1047
1048   public void closeMenuItem_actionPerformed()
1049   {
1050     PaintRefresher.RemoveComponent(alignPanel);
1051     PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
1052     PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
1053
1054     if (PaintRefresher.components.size() == 0 && viewport.applet == null)
1055     {
1056       System.exit(0);
1057     }
1058
1059     this.dispose();
1060   }
1061
1062   /**
1063    * DOCUMENT ME!
1064    */
1065   void updateEditMenuBar()
1066   {
1067
1068     if (viewport.historyList.size() > 0)
1069     {
1070       undoMenuItem.setEnabled(true);
1071       CommandI command = (CommandI) viewport.historyList.peek();
1072       undoMenuItem.setLabel("Undo " + command.getDescription());
1073     }
1074     else
1075     {
1076       undoMenuItem.setEnabled(false);
1077       undoMenuItem.setLabel("Undo");
1078     }
1079
1080     if (viewport.redoList.size() > 0)
1081     {
1082       redoMenuItem.setEnabled(true);
1083
1084       CommandI command = (CommandI) viewport.redoList.peek();
1085       redoMenuItem.setLabel("Redo " + command.getDescription());
1086     }
1087     else
1088     {
1089       redoMenuItem.setEnabled(false);
1090       redoMenuItem.setLabel("Redo");
1091     }
1092   }
1093
1094   public void addHistoryItem(CommandI command)
1095   {
1096     if (command.getSize() > 0)
1097     {
1098       viewport.historyList.push(command);
1099       viewport.redoList.removeAllElements();
1100       updateEditMenuBar();
1101       viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1102     }
1103   }
1104   /**
1105    * DOCUMENT ME!
1106    *
1107    * @param e DOCUMENT ME!
1108    */
1109   protected void undoMenuItem_actionPerformed()
1110   {
1111     if (viewport.historyList.size() < 1)
1112     {
1113       return;
1114     }
1115
1116     CommandI command = (CommandI) viewport.historyList.pop();
1117     viewport.redoList.push(command);
1118     command.undoCommand(null);
1119
1120     AlignViewport originalSource = getOriginatingSource(command);
1121
1122     originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1123     updateEditMenuBar();
1124     originalSource.firePropertyChange("alignment", null,
1125                                       originalSource.alignment.getSequences());
1126   }
1127
1128   /**
1129    * DOCUMENT ME!
1130    *
1131    * @param e DOCUMENT ME!
1132    */
1133   protected void redoMenuItem_actionPerformed()
1134   {
1135     if (viewport.redoList.size() < 1)
1136     {
1137       return;
1138     }
1139
1140     CommandI command = (CommandI) viewport.redoList.pop();
1141     viewport.historyList.push(command);
1142     command.doCommand(null);
1143
1144     AlignViewport originalSource = getOriginatingSource(command);
1145     originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1146
1147     updateEditMenuBar();
1148     originalSource.firePropertyChange("alignment", null,
1149                                       originalSource.alignment.getSequences());
1150   }
1151
1152   AlignViewport getOriginatingSource(CommandI command)
1153   {
1154     AlignViewport originalSource = null;
1155     //For sequence removal and addition, we need to fire
1156     //the property change event FROM the viewport where the
1157     //original alignment was altered
1158     AlignmentI al = null;
1159     if (command instanceof EditCommand)
1160     {
1161       EditCommand editCommand = (EditCommand) command;
1162       al = editCommand.getAlignment();
1163       Vector comps = (Vector) PaintRefresher.components
1164           .get(viewport.getSequenceSetId());
1165       for (int i = 0; i < comps.size(); i++)
1166       {
1167         if (comps.elementAt(i) instanceof AlignmentPanel)
1168         {
1169           if (al == ( (AlignmentPanel) comps.elementAt(i)).av.alignment)
1170           {
1171             originalSource = ( (AlignmentPanel) comps.elementAt(i)).av;
1172             break;
1173           }
1174         }
1175       }
1176     }
1177
1178     if (originalSource == null)
1179     {
1180       //The original view is closed, we must validate
1181       //the current view against the closed view first
1182       if (al != null)
1183       {
1184         PaintRefresher.validateSequences(al, viewport.alignment);
1185       }
1186
1187       originalSource = viewport;
1188     }
1189
1190     return originalSource;
1191   }
1192
1193   public void moveSelectedSequences(boolean up)
1194   {
1195     SequenceGroup sg = viewport.getSelectionGroup();
1196     if (sg == null)
1197     {
1198       return;
1199     }
1200
1201     if (up)
1202     {
1203       for (int i = 1; i < viewport.alignment.getHeight(); i++)
1204       {
1205         SequenceI seq = viewport.alignment.getSequenceAt(i);
1206         if (!sg.getSequences(null).contains(seq))
1207         {
1208           continue;
1209         }
1210
1211         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
1212         if (sg.getSequences(null).contains(temp))
1213         {
1214           continue;
1215         }
1216
1217         viewport.alignment.getSequences().setElementAt(temp, i);
1218         viewport.alignment.getSequences().setElementAt(seq, i - 1);
1219       }
1220     }
1221     else
1222     {
1223       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
1224       {
1225         SequenceI seq = viewport.alignment.getSequenceAt(i);
1226         if (!sg.getSequences(viewport.hiddenRepSequences).contains(seq))
1227         {
1228           continue;
1229         }
1230
1231         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
1232         if (sg.getSequences(viewport.hiddenRepSequences).contains(temp))
1233         {
1234           continue;
1235         }
1236
1237         viewport.alignment.getSequences().setElementAt(temp, i);
1238         viewport.alignment.getSequences().setElementAt(seq, i + 1);
1239       }
1240     }
1241
1242     alignPanel.paintAlignment(true);
1243   }
1244
1245   synchronized void slideSequences(boolean right, int size)
1246   {
1247     Vector sg = new Vector();
1248     if(viewport.cursorMode)
1249     {
1250       sg.addElement(viewport.alignment.getSequenceAt(
1251           alignPanel.seqPanel.seqCanvas.cursorY));
1252     }
1253     else if(viewport.getSelectionGroup()!=null
1254         && viewport.getSelectionGroup().getSize()!=viewport.alignment.getHeight())
1255    {
1256      sg = viewport.getSelectionGroup().getSequences(
1257          viewport.hiddenRepSequences);
1258    }
1259
1260     if(sg.size()<1)
1261     {
1262       return;
1263     }
1264
1265     Vector invertGroup = new Vector();
1266
1267     for (int i = 0; i < viewport.alignment.getHeight(); i++)
1268     {
1269       if(!sg.contains(viewport.alignment.getSequenceAt(i)))
1270          invertGroup.addElement(viewport.alignment.getSequenceAt(i));
1271     }
1272
1273     SequenceI[] seqs1 = new SequenceI[sg.size()];
1274     for (int i = 0; i < sg.size(); i++)
1275       seqs1[i] = (SequenceI) sg.elementAt(i);
1276
1277     SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1278     for (int i = 0; i < invertGroup.size(); i++)
1279       seqs2[i] = (SequenceI) invertGroup.elementAt(i);
1280
1281     SlideSequencesCommand ssc;
1282     if (right)
1283       ssc = new SlideSequencesCommand("Slide Sequences",
1284                                       seqs2, seqs1, size,
1285                                       viewport.getGapCharacter()
1286           );
1287     else
1288       ssc = new SlideSequencesCommand("Slide Sequences",
1289                                       seqs1, seqs2, size,
1290                                       viewport.getGapCharacter()
1291           );
1292
1293     int groupAdjustment = 0;
1294     if (ssc.getGapsInsertedBegin() && right)
1295     {
1296       if (viewport.cursorMode)
1297         alignPanel.seqPanel.moveCursor(size, 0);
1298       else
1299         groupAdjustment = size;
1300     }
1301     else if (!ssc.getGapsInsertedBegin() && !right)
1302     {
1303       if (viewport.cursorMode)
1304         alignPanel.seqPanel.moveCursor( -size, 0);
1305       else
1306         groupAdjustment = -size;
1307     }
1308
1309     if (groupAdjustment != 0)
1310     {
1311       viewport.getSelectionGroup().setStartRes(
1312           viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1313       viewport.getSelectionGroup().setEndRes(
1314           viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1315     }
1316
1317
1318     boolean appendHistoryItem = false;
1319     if(viewport.historyList!=null
1320        && viewport.historyList.size()>0
1321       && viewport.historyList.peek() instanceof SlideSequencesCommand)
1322     {
1323       appendHistoryItem = ssc.appendSlideCommand(
1324           (SlideSequencesCommand)viewport.historyList.peek())
1325           ;
1326     }
1327
1328     if(!appendHistoryItem)
1329       addHistoryItem(ssc);
1330
1331     repaint();
1332   }
1333
1334   static StringBuffer copiedSequences;
1335   static Vector copiedHiddenColumns;
1336   protected void copy_actionPerformed()
1337   {
1338     if (viewport.getSelectionGroup() == null)
1339     {
1340       return;
1341     }
1342
1343     SequenceGroup sg = viewport.getSelectionGroup();
1344     copiedSequences = new StringBuffer();
1345     Hashtable orderedSeqs = new Hashtable();
1346     for (int i = 0; i < sg.getSize(); i++)
1347     {
1348       SequenceI seq = sg.getSequenceAt(i);
1349       int index = viewport.alignment.findIndex(seq);
1350       orderedSeqs.put(index + "", seq);
1351     }
1352
1353     int index = 0, startRes, endRes;
1354     char ch;
1355
1356     if (viewport.hasHiddenColumns && viewport.getSelectionGroup() != null)
1357     {
1358       copiedHiddenColumns = new Vector();
1359       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
1360       for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns().size();
1361            i++)
1362       {
1363         int[] region = (int[])
1364             viewport.getColumnSelection().getHiddenColumns().elementAt(i);
1365
1366         copiedHiddenColumns.addElement(new int[]
1367                                        {region[0] - hiddenOffset,
1368                                        region[1] - hiddenOffset});
1369       }
1370     }
1371     else
1372     {
1373       copiedHiddenColumns = null;
1374     }
1375
1376     for (int i = 0; i < sg.getSize(); i++)
1377     {
1378       SequenceI seq = null;
1379
1380       while (seq == null)
1381       {
1382         if (orderedSeqs.containsKey(index + ""))
1383         {
1384           seq = (SequenceI) orderedSeqs.get(index + "");
1385           index++;
1386
1387           break;
1388         }
1389         else
1390         {
1391           index++;
1392         }
1393       }
1394
1395       //FIND START RES
1396       //Returns residue following index if gap
1397       startRes = seq.findPosition(sg.getStartRes());
1398
1399       //FIND END RES
1400       //Need to find the residue preceeding index if gap
1401       endRes = 0;
1402
1403       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)
1404       {
1405         ch = seq.getCharAt(j);
1406         if (!jalview.util.Comparison.isGap( (ch)))
1407         {
1408           endRes++;
1409         }
1410       }
1411
1412       if (endRes > 0)
1413       {
1414         endRes += seq.getStart() - 1;
1415       }
1416
1417       copiedSequences.append(seq.getName() + "\t" +
1418                              startRes + "\t" +
1419                              endRes + "\t" +
1420                              seq.getSequenceAsString(sg.getStartRes(),
1421           sg.getEndRes() + 1) + "\n");
1422     }
1423
1424   }
1425
1426   protected void pasteNew_actionPerformed()
1427   {
1428     paste(true);
1429   }
1430
1431   protected void pasteThis_actionPerformed()
1432   {
1433     paste(false);
1434   }
1435
1436   void paste(boolean newAlignment)
1437   {
1438     try
1439     {
1440
1441       if (copiedSequences == null)
1442       {
1443         return;
1444       }
1445
1446       StringTokenizer st = new StringTokenizer(copiedSequences.toString());
1447       Vector seqs = new Vector();
1448       while (st.hasMoreElements())
1449       {
1450         String name = st.nextToken();
1451         int start = Integer.parseInt(st.nextToken());
1452         int end = Integer.parseInt(st.nextToken());
1453         seqs.addElement(new Sequence(name, st.nextToken(), start, end));
1454       }
1455       SequenceI[] newSeqs = new SequenceI[seqs.size()];
1456       for (int i = 0; i < seqs.size(); i++)
1457       {
1458         newSeqs[i] = (SequenceI) seqs.elementAt(i);
1459       }
1460
1461       if (newAlignment)
1462       {
1463         String newtitle = new String("Copied sequences");
1464         if (getTitle().startsWith("Copied sequences"))
1465         {
1466           newtitle = getTitle();
1467         }
1468         else
1469         {
1470           newtitle = newtitle.concat("- from " + getTitle());
1471         }
1472         AlignFrame af = new AlignFrame(new Alignment(newSeqs),
1473                                        viewport.applet,
1474                                        newtitle,
1475                                        false);
1476         if (copiedHiddenColumns != null)
1477         {
1478           for (int i = 0; i < copiedHiddenColumns.size(); i++)
1479           {
1480             int[] region = (int[]) copiedHiddenColumns.elementAt(i);
1481             af.viewport.hideColumns(region[0], region[1]);
1482           }
1483         }
1484
1485         jalview.bin.JalviewLite.addFrame(af, newtitle, DEFAULT_WIDTH,
1486                                          DEFAULT_HEIGHT);
1487       }
1488       else
1489       {
1490         addSequences(newSeqs);
1491       }
1492
1493     }
1494     catch (Exception ex)
1495     {} // could be anything being pasted in here
1496
1497   }
1498
1499   void addSequences(SequenceI[] seqs)
1500   {
1501     for (int i = 0; i < seqs.length; i++)
1502     {
1503       viewport.alignment.addSequence(seqs[i]);
1504     }
1505
1506     //!newAlignment
1507     addHistoryItem(new EditCommand(
1508         "Add sequences",
1509         EditCommand.PASTE,
1510         seqs,
1511         0,
1512         viewport.alignment.getWidth(),
1513         viewport.alignment)
1514         );
1515
1516     viewport.setEndSeq(viewport.alignment.getHeight());
1517     viewport.alignment.getWidth();
1518     viewport.firePropertyChange("alignment", null,
1519                                 viewport.alignment.getSequences());
1520
1521   }
1522
1523   protected void cut_actionPerformed()
1524   {
1525     copy_actionPerformed();
1526     delete_actionPerformed();
1527   }
1528
1529   protected void delete_actionPerformed()
1530   {
1531
1532     SequenceGroup sg = viewport.getSelectionGroup();
1533     if (sg == null)
1534     {
1535       return;
1536     }
1537
1538     Vector seqs = new Vector();
1539     SequenceI seq;
1540     for (int i = 0; i < sg.getSize(); i++)
1541     {
1542       seq = sg.getSequenceAt(i);
1543       seqs.addElement(seq);
1544     }
1545
1546     // If the cut affects all sequences, remove highlighted columns
1547     if (sg.getSize() == viewport.alignment.getHeight())
1548     {
1549       viewport.getColumnSelection().removeElements(sg.getStartRes(),
1550           sg.getEndRes() + 1);
1551     }
1552
1553     SequenceI[] cut = new SequenceI[seqs.size()];
1554     for (int i = 0; i < seqs.size(); i++)
1555     {
1556       cut[i] = (SequenceI) seqs.elementAt(i);
1557     }
1558
1559     /*
1560          //ADD HISTORY ITEM
1561      */
1562     addHistoryItem(new EditCommand("Cut Sequences",
1563                                    EditCommand.CUT,
1564                                    cut,
1565                                    sg.getStartRes(),
1566                                    sg.getEndRes() - sg.getStartRes() + 1,
1567                                    viewport.alignment));
1568
1569     viewport.setSelectionGroup(null);
1570     viewport.alignment.deleteGroup(sg);
1571
1572     viewport.firePropertyChange("alignment", null,
1573                                 viewport.getAlignment().getSequences());
1574
1575     if (viewport.getAlignment().getHeight() < 1)
1576     {
1577       this.setVisible(false);
1578     }
1579   }
1580
1581   protected void deleteGroups_actionPerformed()
1582   {
1583     viewport.alignment.deleteAllGroups();
1584     viewport.sequenceColours = null;
1585     viewport.setSelectionGroup(null);
1586
1587     alignPanel.paintAlignment(true);
1588   }
1589
1590   public void selectAllSequenceMenuItem_actionPerformed()
1591   {
1592     SequenceGroup sg = new SequenceGroup();
1593     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
1594     {
1595       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
1596     }
1597     sg.setEndRes(viewport.alignment.getWidth() - 1);
1598     viewport.setSelectionGroup(sg);
1599     alignPanel.paintAlignment(true);
1600     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1601   }
1602
1603   public void deselectAllSequenceMenuItem_actionPerformed()
1604   {
1605     if (viewport.cursorMode)
1606     {
1607       alignPanel.seqPanel.keyboardNo1 = null;
1608       alignPanel.seqPanel.keyboardNo2 = null;
1609     }
1610     viewport.setSelectionGroup(null);
1611     viewport.getColumnSelection().clear();
1612     viewport.setSelectionGroup(null);
1613     alignPanel.idPanel.idCanvas.searchResults = null;
1614     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
1615     alignPanel.paintAlignment(true);
1616     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1617   }
1618
1619   public void invertSequenceMenuItem_actionPerformed()
1620   {
1621     SequenceGroup sg = viewport.getSelectionGroup();
1622     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
1623     {
1624       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
1625     }
1626
1627     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1628   }
1629
1630   void trimAlignment(boolean trimLeft)
1631   {
1632     ColumnSelection colSel = viewport.getColumnSelection();
1633     int column;
1634
1635     if (colSel.size() > 0)
1636     {
1637       if (trimLeft)
1638       {
1639         column = colSel.getMin();
1640       }
1641       else
1642       {
1643         column = colSel.getMax();
1644       }
1645
1646       SequenceI[] seqs;
1647       if (viewport.getSelectionGroup() != null)
1648       {
1649         seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1650             hiddenRepSequences);
1651       }
1652       else
1653       {
1654         seqs = viewport.alignment.getSequencesArray();
1655       }
1656
1657       TrimRegionCommand trimRegion;
1658       if (trimLeft)
1659       {
1660         trimRegion = new TrimRegionCommand("Remove Left",
1661                                            TrimRegionCommand.TRIM_LEFT,
1662                                            seqs,
1663                                            column,
1664                                            viewport.alignment,
1665                                            viewport.colSel,
1666                                            viewport.selectionGroup);
1667         viewport.setStartRes(0);
1668       }
1669       else
1670       {
1671         trimRegion = new TrimRegionCommand("Remove Right",
1672                                            TrimRegionCommand.TRIM_RIGHT,
1673                                            seqs,
1674                                            column,
1675                                            viewport.alignment,
1676                                            viewport.colSel,
1677                                            viewport.selectionGroup);
1678       }
1679
1680       statusBar.setText("Removed " + trimRegion.getSize() + " columns.");
1681
1682       addHistoryItem(trimRegion);
1683
1684       Vector groups = viewport.alignment.getGroups();
1685
1686       for (int i = 0; i < groups.size(); i++)
1687       {
1688         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
1689
1690         if ( (trimLeft && !sg.adjustForRemoveLeft(column))
1691             || (!trimLeft && !sg.adjustForRemoveRight(column)))
1692         {
1693           viewport.alignment.deleteGroup(sg);
1694         }
1695       }
1696
1697       viewport.firePropertyChange("alignment", null,
1698                                   viewport.getAlignment().getSequences());
1699     }
1700   }
1701
1702   public void removeGappedColumnMenuItem_actionPerformed()
1703   {
1704     int start = 0, end = viewport.alignment.getWidth() - 1;
1705
1706     SequenceI[] seqs;
1707     if (viewport.getSelectionGroup() != null)
1708     {
1709       seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1710           hiddenRepSequences);
1711       start = viewport.getSelectionGroup().getStartRes();
1712       end = viewport.getSelectionGroup().getEndRes();
1713     }
1714     else
1715     {
1716       seqs = viewport.alignment.getSequencesArray();
1717     }
1718
1719     RemoveGapColCommand removeGapCols =
1720         new RemoveGapColCommand("Remove Gapped Columns",
1721                                 seqs,
1722                                 start, end,
1723                                 viewport.alignment);
1724
1725     addHistoryItem(removeGapCols);
1726
1727     statusBar.setText("Removed " + removeGapCols.getSize() + " empty columns.");
1728
1729     //This is to maintain viewport position on first residue
1730     //of first sequence
1731     SequenceI seq = viewport.alignment.getSequenceAt(0);
1732     int startRes = seq.findPosition(viewport.startRes);
1733     // ShiftList shifts;
1734     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
1735     // edit.alColumnChanges=shifts.getInverse();
1736     // if (viewport.hasHiddenColumns)
1737     //   viewport.getColumnSelection().compensateForEdits(shifts);
1738     viewport.setStartRes(seq.findIndex(startRes) - 1);
1739     viewport.firePropertyChange("alignment", null,
1740                                 viewport.getAlignment().getSequences());
1741
1742   }
1743
1744   public void removeAllGapsMenuItem_actionPerformed()
1745   {
1746     int start = 0, end = viewport.alignment.getWidth() - 1;
1747
1748     SequenceI[] seqs;
1749     if (viewport.getSelectionGroup() != null)
1750     {
1751       seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1752           hiddenRepSequences);
1753       start = viewport.getSelectionGroup().getStartRes();
1754       end = viewport.getSelectionGroup().getEndRes();
1755     }
1756     else
1757     {
1758       seqs = viewport.alignment.getSequencesArray();
1759     }
1760
1761     //This is to maintain viewport position on first residue
1762     //of first sequence
1763     SequenceI seq = viewport.alignment.getSequenceAt(0);
1764     int startRes = seq.findPosition(viewport.startRes);
1765
1766     addHistoryItem(new RemoveGapsCommand("Remove Gaps",
1767                                          seqs,
1768                                          start, end,
1769                                          viewport.alignment));
1770
1771     viewport.setStartRes(seq.findIndex(startRes) - 1);
1772
1773     viewport.firePropertyChange("alignment", null,
1774                                 viewport.getAlignment().getSequences());
1775
1776   }
1777
1778   public void findMenuItem_actionPerformed()
1779   {
1780     new Finder(alignPanel);
1781   }
1782   /**
1783    * create a new view derived from the current view
1784    * @param viewtitle
1785    * @return frame for the new view
1786    */
1787   public AlignFrame newView(String viewtitle)
1788   {
1789     AlignmentI newal;
1790     if (viewport.hasHiddenRows)
1791     {
1792       newal = new Alignment(viewport.getAlignment().
1793                             getHiddenSequences()
1794                             .getFullAlignment().
1795                             getSequencesArray());
1796     }
1797     else
1798     {
1799       newal = new Alignment(viewport.alignment.getSequencesArray());
1800     }
1801
1802     if (viewport.alignment.getAlignmentAnnotation() != null)
1803     {
1804       for (int i = 0; i < viewport.alignment.getAlignmentAnnotation().length; i++)
1805       {
1806         if (!viewport.alignment.getAlignmentAnnotation()[i].autoCalculated)
1807         {
1808           newal.addAnnotation(viewport.alignment.getAlignmentAnnotation()[i]);
1809         }
1810       }
1811     }
1812
1813     AlignFrame newaf = new AlignFrame(newal,
1814                                       viewport.applet,
1815                                       "",
1816                                       false);
1817
1818     newaf.viewport.sequenceSetID = alignPanel.av.getSequenceSetId();
1819     PaintRefresher.Register(alignPanel, alignPanel.av.getSequenceSetId());
1820     PaintRefresher.Register(newaf.alignPanel,
1821                             newaf.alignPanel.av.getSequenceSetId());
1822
1823     PaintRefresher.Register(newaf.alignPanel.idPanel.idCanvas,
1824                             newaf.alignPanel.av.getSequenceSetId());
1825     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,
1826                             newaf.alignPanel.av.getSequenceSetId());
1827
1828     Vector comps = (Vector) PaintRefresher.components.get(viewport.
1829         getSequenceSetId());
1830     int viewSize = -1;
1831     for (int i = 0; i < comps.size(); i++)
1832     {
1833       if (comps.elementAt(i) instanceof AlignmentPanel)
1834       {
1835         viewSize++;
1836       }
1837     }
1838
1839     String title = new String(this.getTitle());
1840     if (viewtitle!=null)
1841     {
1842       title = viewtitle+" ( "+title+")";
1843     } else {
1844       if (title.indexOf("(View") > -1)
1845       {
1846         title = title.substring(0, title.indexOf("(View"));
1847       }
1848       title += "(View " + viewSize + ")";
1849     }
1850
1851     newaf.setTitle(title.toString());
1852
1853     newaf.viewport.historyList = viewport.historyList;
1854     newaf.viewport.redoList = viewport.redoList;
1855     return newaf;
1856   }
1857   /**
1858    * 
1859    * @return list of feature groups on the view
1860    */
1861   public String[] getFeatureGroups()
1862   {
1863     FeatureRenderer fr = null;
1864     if (alignPanel!=null && (fr=alignPanel.getFeatureRenderer())!=null)
1865     {
1866       return fr.getGroups();
1867     }
1868     return null;
1869   }
1870   /**
1871    * get sequence feature groups that are hidden or shown
1872    * @param visible true is visible
1873    * @return list
1874    */
1875   public String[] getFeatureGroupsOfState(boolean visible)
1876   {
1877     FeatureRenderer fr = null;
1878     if (alignPanel!=null && (fr=alignPanel.getFeatureRenderer())!=null)
1879     {
1880       return fr.getGroups(visible);
1881     }
1882     return null;
1883   }
1884   /**
1885    * Change the display state for the given feature groups
1886    * @param groups list of group strings
1887    * @param state visible or invisible
1888    */
1889   public void setFeatureGroupState(String[] groups, boolean state) {
1890     FeatureRenderer fr = null;
1891     this.sequenceFeatures.setState(true);
1892     viewport.showSequenceFeatures(true);
1893     if (alignPanel!=null && (fr=alignPanel.getFeatureRenderer())!=null)
1894     {
1895       fr.setGroupState(groups, state);
1896       alignPanel.seqPanel.seqCanvas.repaint();
1897       if (alignPanel.overviewPanel != null)
1898       {
1899         alignPanel.overviewPanel.updateOverviewImage();
1900       }
1901     }
1902   }
1903   public void seqLimits_itemStateChanged()
1904   {
1905     viewport.setShowJVSuffix(seqLimits.getState());
1906     alignPanel.fontChanged();
1907     alignPanel.paintAlignment(true);
1908   }
1909
1910   protected void colourTextMenuItem_actionPerformed()
1911   {
1912     viewport.setColourText(colourTextMenuItem.getState());
1913     alignPanel.paintAlignment(true);
1914   }
1915
1916   protected void wrapMenuItem_actionPerformed()
1917   {
1918     viewport.setWrapAlignment(wrapMenuItem.getState());
1919     alignPanel.setWrapAlignment(wrapMenuItem.getState());
1920     scaleAbove.setEnabled(wrapMenuItem.getState());
1921     scaleLeft.setEnabled(wrapMenuItem.getState());
1922     scaleRight.setEnabled(wrapMenuItem.getState());
1923     alignPanel.paintAlignment(true);
1924   }
1925
1926   public void overviewMenuItem_actionPerformed()
1927   {
1928     if (alignPanel.overviewPanel != null)
1929     {
1930       return;
1931     }
1932
1933     Frame frame = new Frame();
1934     OverviewPanel overview = new OverviewPanel(alignPanel);
1935     frame.add(overview);
1936     // +50 must allow for applet frame window
1937     jalview.bin.JalviewLite.addFrame(frame, "Overview " + this.getTitle(),
1938                                      overview.getPreferredSize().width,
1939                                      overview.getPreferredSize().height + 50);
1940
1941     frame.pack();
1942     frame.addWindowListener(new WindowAdapter()
1943     {
1944       public void windowClosing(WindowEvent e)
1945       {
1946         alignPanel.setOverviewPanel(null);
1947       };
1948     });
1949
1950     alignPanel.setOverviewPanel(overview);
1951
1952   }
1953
1954   void changeColour(ColourSchemeI cs)
1955   {
1956     int threshold = 0;
1957
1958     if (cs != null)
1959     {
1960       if (viewport.getAbovePIDThreshold())
1961       {
1962         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");
1963
1964         cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
1965
1966         viewport.setGlobalColourScheme(cs);
1967       }
1968       else
1969       {
1970         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
1971       }
1972
1973       if (viewport.getConservationSelected())
1974       {
1975
1976         Alignment al = (Alignment) viewport.alignment;
1977         Conservation c = new Conservation("All",
1978                                           ResidueProperties.propHash, 3,
1979                                           al.getSequences(), 0,
1980                                           al.getWidth() - 1);
1981
1982         c.calculate();
1983         c.verdict(false, viewport.ConsPercGaps);
1984
1985         cs.setConservation(c);
1986
1987         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
1988             "Background"));
1989
1990       }
1991       else
1992       {
1993         cs.setConservation(null);
1994       }
1995
1996       cs.setConsensus(viewport.hconsensus);
1997
1998     }
1999     viewport.setGlobalColourScheme(cs);
2000
2001     if (viewport.getColourAppliesToAllGroups())
2002     {
2003       Vector groups = viewport.alignment.getGroups();
2004       for (int i = 0; i < groups.size(); i++)
2005       {
2006         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2007
2008         if (cs == null)
2009         {
2010           sg.cs = null;
2011           continue;
2012         }
2013         if (cs instanceof ClustalxColourScheme)
2014         {
2015           sg.cs = new ClustalxColourScheme(
2016               sg.getSequences(viewport.hiddenRepSequences),
2017               sg.getWidth());
2018         }
2019         else
2020         {
2021           try
2022           {
2023             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2024           }
2025           catch (Exception ex)
2026           {
2027             ex.printStackTrace();
2028             sg.cs = cs;
2029           }
2030         }
2031
2032         if (viewport.getAbovePIDThreshold()
2033             || cs instanceof PIDColourScheme
2034             || cs instanceof Blosum62ColourScheme)
2035         {
2036           sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
2037           sg.cs.setConsensus(AAFrequency.calculate(
2038               sg.getSequences(viewport.hiddenRepSequences), 0, sg.getWidth()));
2039         }
2040         else
2041         {
2042           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2043         }
2044
2045         if (viewport.getConservationSelected())
2046         {
2047           Conservation c = new Conservation("Group",
2048                                             ResidueProperties.propHash, 3,
2049                                             sg.getSequences(viewport.
2050               hiddenRepSequences), 0,
2051                                             viewport.alignment.getWidth() - 1);
2052           c.calculate();
2053           c.verdict(false, viewport.ConsPercGaps);
2054           sg.cs.setConservation(c);
2055         }
2056         else
2057         {
2058           sg.cs.setConservation(null);
2059           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2060         }
2061
2062       }
2063     }
2064
2065     if (alignPanel.getOverviewPanel() != null)
2066     {
2067       alignPanel.getOverviewPanel().updateOverviewImage();
2068     }
2069
2070     jalview.structure.StructureSelectionManager.getStructureSelectionManager()
2071         .sequenceColoursChanged(alignPanel);
2072
2073     alignPanel.paintAlignment(true);
2074   }
2075
2076   protected void modifyPID_actionPerformed()
2077   {
2078     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme != null)
2079     {
2080       SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),
2081                                      "Background");
2082       SliderPanel.showPIDSlider();
2083     }
2084   }
2085
2086   protected void modifyConservation_actionPerformed()
2087   {
2088     if (viewport.getConservationSelected() && viewport.globalColourScheme != null)
2089     {
2090       SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,
2091                                         "Background");
2092       SliderPanel.showConservationSlider();
2093     }
2094   }
2095
2096   protected void conservationMenuItem_actionPerformed()
2097   {
2098     viewport.setConservationSelected(conservationMenuItem.getState());
2099
2100     viewport.setAbovePIDThreshold(false);
2101     abovePIDThreshold.setState(false);
2102
2103     changeColour(viewport.getGlobalColourScheme());
2104
2105     modifyConservation_actionPerformed();
2106   }
2107
2108   public void abovePIDThreshold_actionPerformed()
2109   {
2110     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());
2111
2112     conservationMenuItem.setState(false);
2113     viewport.setConservationSelected(false);
2114
2115     changeColour(viewport.getGlobalColourScheme());
2116
2117     modifyPID_actionPerformed();
2118   }
2119
2120   public void sortPairwiseMenuItem_actionPerformed()
2121   {
2122     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2123     AlignmentSorter.sortByPID(viewport.getAlignment(),
2124                               viewport.getAlignment().getSequenceAt(0), null);
2125     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2126                                     viewport.alignment));
2127     alignPanel.paintAlignment(true);
2128   }
2129
2130   public void sortIDMenuItem_actionPerformed()
2131   {
2132     //  addHistoryItem(new HistoryItem("ID Sort", viewport.alignment,
2133     //                                HistoryItem.SORT));
2134     AlignmentSorter.sortByID(viewport.getAlignment());
2135     alignPanel.paintAlignment(true);
2136   }
2137
2138   public void sortGroupMenuItem_actionPerformed()
2139   {
2140     //  addHistoryItem(new HistoryItem("Group Sort", viewport.alignment,
2141     //                                 HistoryItem.SORT));
2142     AlignmentSorter.sortByGroup(viewport.getAlignment());
2143     alignPanel.paintAlignment(true);
2144
2145   }
2146
2147   public void removeRedundancyMenuItem_actionPerformed()
2148   {
2149     new RedundancyPanel(alignPanel);
2150   }
2151
2152   public void pairwiseAlignmentMenuItem_actionPerformed()
2153   {
2154     if (viewport.getSelectionGroup() != null
2155         && viewport.getSelectionGroup().getSize() > 1)
2156     {
2157       Frame frame = new Frame();
2158       frame.add(new PairwiseAlignPanel(alignPanel));
2159       jalview.bin.JalviewLite.addFrame(frame, "Pairwise Alignment", 600, 500);
2160     }
2161   }
2162
2163   public void PCAMenuItem_actionPerformed()
2164   {
2165     //are the sequences aligned?
2166     if (!viewport.alignment.isAligned())
2167     {
2168       SequenceI current;
2169       int Width = viewport.getAlignment().getWidth();
2170
2171       for (int i = 0; i < viewport.getAlignment().getSequences().size();
2172            i++)
2173       {
2174         current = viewport.getAlignment().getSequenceAt(i);
2175
2176         if (current.getLength() < Width)
2177         {
2178           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2179         }
2180       }
2181       alignPanel.paintAlignment(true);
2182     }
2183
2184     if ( (viewport.getSelectionGroup() != null &&
2185           viewport.getSelectionGroup().getSize() < 4 &&
2186           viewport.getSelectionGroup().getSize() > 0)
2187         || viewport.getAlignment().getHeight() < 4)
2188     {
2189       return;
2190     }
2191
2192     try
2193     {
2194       new PCAPanel(viewport);
2195     }
2196     catch (java.lang.OutOfMemoryError ex)
2197     {
2198     }
2199
2200   }
2201
2202   public void averageDistanceTreeMenuItem_actionPerformed()
2203   {
2204     NewTreePanel("AV", "PID", "Average distance tree using PID");
2205   }
2206
2207   public void neighbourTreeMenuItem_actionPerformed()
2208   {
2209     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2210   }
2211
2212   protected void njTreeBlosumMenuItem_actionPerformed()
2213   {
2214     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2215   }
2216
2217   protected void avTreeBlosumMenuItem_actionPerformed()
2218   {
2219     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2220   }
2221
2222   void NewTreePanel(String type, String pwType, String title)
2223   {
2224     //are the sequences aligned?
2225     if (!viewport.alignment.isAligned())
2226     {
2227       SequenceI current;
2228       int Width = viewport.getAlignment().getWidth();
2229
2230       for (int i = 0; i < viewport.getAlignment().getSequences().size();
2231            i++)
2232       {
2233         current = viewport.getAlignment().getSequenceAt(i);
2234
2235         if (current.getLength() < Width)
2236         {
2237           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2238         }
2239       }
2240       alignPanel.paintAlignment(true);
2241
2242     }
2243
2244     if ( (viewport.getSelectionGroup() != null &&
2245           viewport.getSelectionGroup().getSize() > 1)
2246         || (viewport.getSelectionGroup() == null
2247             && viewport.alignment.getHeight() > 1))
2248     {
2249       final TreePanel tp = new TreePanel(viewport,
2250                                          type,
2251                                          pwType);
2252
2253       addTreeMenuItem(tp, title);
2254
2255       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);
2256     }
2257   }
2258
2259   void loadTree_actionPerformed()
2260   {
2261     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
2262     cap.setText("Paste your Newick tree file here.");
2263     cap.setTreeImport();
2264     Frame frame = new Frame();
2265     frame.add(cap);
2266     jalview.bin.JalviewLite.addFrame(frame, "Paste Newick file ", 400, 300);
2267   }
2268
2269   public void loadTree(jalview.io.NewickFile tree, String treeFile)
2270   {
2271     TreePanel tp = new TreePanel(viewport,
2272                                  treeFile,
2273                                  "From File - ",
2274                                  tree);
2275     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);
2276     addTreeMenuItem(tp, treeFile);
2277   }
2278
2279   void addTreeMenuItem(final TreePanel treePanel, String title)
2280   {
2281     final MenuItem item = new MenuItem(title);
2282     sortByTreeMenu.add(item);
2283     item.addActionListener(new java.awt.event.ActionListener()
2284     {
2285       public void actionPerformed(ActionEvent evt)
2286       {
2287         //  addHistoryItem(new HistoryItem("Sort", viewport.alignment,
2288         //                                 HistoryItem.SORT));
2289         AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());
2290         alignPanel.paintAlignment(true);
2291       }
2292     });
2293
2294     treePanel.addWindowListener(new WindowAdapter()
2295     {
2296       public void windowClosing(WindowEvent e)
2297       {
2298         sortByTreeMenu.remove(item);
2299       };
2300     });
2301   }
2302
2303   protected void documentation_actionPerformed()
2304   {
2305     showURL("http://www.jalview.org/help.html", "HELP");
2306   }
2307
2308   protected void about_actionPerformed()
2309   {
2310
2311     class AboutPanel
2312         extends Canvas
2313     {
2314       String version;
2315       public AboutPanel(String version)
2316       {
2317         this.version = version;
2318       }
2319
2320       public void paint(Graphics g)
2321       {
2322         g.setColor(Color.white);
2323         g.fillRect(0, 0, getSize().width, getSize().height);
2324         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2325         FontMetrics fm = g.getFontMetrics();
2326         int fh = fm.getHeight();
2327         int y = 5, x = 7;
2328         g.setColor(Color.black);
2329         g.setFont(new Font("Helvetica", Font.BOLD, 14));
2330         g.drawString("Jalview - Release " + version, 200, y += fh);
2331         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2332         g.drawString("Authors:  Michele Clamp, James Cuff, Steve Searle, Andrew Waterhouse, Jim Procter & Geoff Barton.",
2333                      x, y += fh * 2);
2334         g.drawString("Current development managed by Andrew Waterhouse; Barton Group, University of Dundee.",
2335                      x, y += fh);
2336         g.drawString(
2337             "For any issues relating to Jalview, email help@jalview.org", x,
2338             y += fh);
2339         g.drawString("If  you use JalView, please cite:", x, y += fh + 8);
2340         g.drawString("\"Clamp, M., Cuff, J., Searle, S. M. and Barton, G. J. (2004), The Jalview Java Alignment Editor\"",
2341                      x, y += fh);
2342         g.drawString("Bioinformatics,  2004 20;426-7.", x, y += fh);
2343       }
2344     }
2345
2346     String version = "test";
2347     java.net.URL url = getClass().getResource("/.build_properties");
2348     if (url != null)
2349     {
2350       try
2351       {
2352         BufferedReader reader = new BufferedReader(new InputStreamReader(
2353             url.openStream()));
2354         String line;
2355         while ( (line = reader.readLine()) != null)
2356         {
2357           if (line.indexOf("VERSION") > -1)
2358           {
2359             version = line.substring(line.indexOf("=") + 1);
2360           }
2361         }
2362       }
2363       catch (Exception ex)
2364       {
2365         ex.printStackTrace();
2366       }
2367     }
2368
2369     Frame frame = new Frame();
2370     frame.add(new AboutPanel(version));
2371     jalview.bin.JalviewLite.addFrame(frame, "Jalview", 580, 200);
2372
2373   }
2374
2375   public void showURL(String url, String target)
2376   {
2377     if (viewport.applet == null)
2378     {
2379       System.out.println("Not running as applet - no browser available.");
2380     }
2381     else
2382     {
2383       try
2384       {
2385         System.out.println("Show url: " + url);
2386         viewport.applet.getAppletContext().showDocument(new java.net.URL(url),
2387             target);
2388       }
2389       catch (Exception ex)
2390       {
2391         ex.printStackTrace();
2392       }
2393     }
2394   }
2395
2396   //////////////////////////////////////////////////////////////////////////////////
2397   //JBuilder Graphics here
2398
2399    MenuBar alignFrameMenuBar = new MenuBar();
2400    Menu fileMenu = new Menu("File");
2401    MenuItem loadApplication = new MenuItem("View in Full Application");
2402    MenuItem loadTree = new MenuItem("Load Associated Tree ...");
2403    MenuItem loadAnnotations = new MenuItem(
2404       "Load Features/Annotations ...");
2405    MenuItem outputFeatures = new MenuItem("Export Features ...");
2406    MenuItem outputAnnotations = new MenuItem("Export Annotations ...");
2407
2408    MenuItem closeMenuItem = new MenuItem("Close");
2409    Menu editMenu = new Menu("Edit");
2410    Menu viewMenu = new Menu("View");
2411    Menu colourMenu = new Menu("Colour");
2412    Menu calculateMenu = new Menu("Calculate");
2413    MenuItem selectAllSequenceMenuItem = new MenuItem("Select all");
2414    MenuItem deselectAllSequenceMenuItem = new MenuItem("Deselect All");
2415    MenuItem invertSequenceMenuItem = new MenuItem("Invert Selection");
2416    MenuItem remove2LeftMenuItem = new MenuItem();
2417    MenuItem remove2RightMenuItem = new MenuItem();
2418    MenuItem removeGappedColumnMenuItem = new MenuItem();
2419    MenuItem removeAllGapsMenuItem = new MenuItem();
2420    CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();
2421    CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();
2422    MenuItem sortPairwiseMenuItem = new MenuItem();
2423    MenuItem sortIDMenuItem = new MenuItem();
2424    MenuItem sortGroupMenuItem = new MenuItem();
2425    MenuItem removeRedundancyMenuItem = new MenuItem();
2426    MenuItem pairwiseAlignmentMenuItem = new MenuItem();
2427    MenuItem PCAMenuItem = new MenuItem();
2428    MenuItem averageDistanceTreeMenuItem = new MenuItem();
2429    MenuItem neighbourTreeMenuItem = new MenuItem();
2430   BorderLayout borderLayout1 = new BorderLayout();
2431   public Label statusBar = new Label();
2432    Menu outputTextboxMenu = new Menu();
2433    MenuItem clustalColour = new MenuItem();
2434    MenuItem zappoColour = new MenuItem();
2435    MenuItem taylorColour = new MenuItem();
2436    MenuItem hydrophobicityColour = new MenuItem();
2437    MenuItem helixColour = new MenuItem();
2438    MenuItem strandColour = new MenuItem();
2439    MenuItem turnColour = new MenuItem();
2440    MenuItem buriedColour = new MenuItem();
2441    MenuItem userDefinedColour = new MenuItem();
2442    MenuItem PIDColour = new MenuItem();
2443    MenuItem BLOSUM62Colour = new MenuItem();
2444   MenuItem njTreeBlosumMenuItem = new MenuItem();
2445   MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();
2446    CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();
2447    CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();
2448    MenuItem alProperties = new MenuItem("Alignment Properties...");
2449   MenuItem overviewMenuItem = new MenuItem();
2450    MenuItem undoMenuItem = new MenuItem();
2451    MenuItem redoMenuItem = new MenuItem();
2452    CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
2453   MenuItem noColourmenuItem = new MenuItem();
2454    CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();
2455    CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();
2456   MenuItem findMenuItem = new MenuItem();
2457    CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();
2458    MenuItem nucleotideColour = new MenuItem();
2459   MenuItem deleteGroups = new MenuItem();
2460   MenuItem delete = new MenuItem();
2461   MenuItem copy = new MenuItem();
2462   MenuItem cut = new MenuItem();
2463   Menu pasteMenu = new Menu();
2464   MenuItem pasteNew = new MenuItem();
2465   MenuItem pasteThis = new MenuItem();
2466    CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();
2467    MenuItem font = new MenuItem();
2468    CheckboxMenuItem scaleAbove = new CheckboxMenuItem();
2469    CheckboxMenuItem scaleLeft = new CheckboxMenuItem();
2470    CheckboxMenuItem scaleRight = new CheckboxMenuItem();
2471   MenuItem modifyPID = new MenuItem();
2472   MenuItem modifyConservation = new MenuItem();
2473    CheckboxMenuItem autoCalculate
2474       = new CheckboxMenuItem("Autocalculate Consensus", true);
2475    Menu sortByTreeMenu = new Menu();
2476   Menu sort = new Menu();
2477   Menu calculate = new Menu();
2478   MenuItem inputText = new MenuItem();
2479   Menu helpMenu = new Menu();
2480   MenuItem documentation = new MenuItem();
2481   MenuItem about = new MenuItem();
2482    CheckboxMenuItem seqLimits = new CheckboxMenuItem();
2483    CheckboxMenuItem centreColumnLabelFlag = new CheckboxMenuItem();
2484
2485   private void jbInit()
2486       throws Exception
2487   {
2488
2489     setMenuBar(alignFrameMenuBar);
2490
2491     MenuItem item;
2492
2493     // dynamically fill save as menu with available formats
2494     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length;
2495          i++)
2496     {
2497
2498       item = new MenuItem(jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);
2499
2500       item.addActionListener(new java.awt.event.ActionListener()
2501       {
2502         public void actionPerformed(ActionEvent e)
2503         {
2504           outputText_actionPerformed(e);
2505         }
2506       });
2507
2508       outputTextboxMenu.add(item);
2509     }
2510     closeMenuItem.addActionListener(this);
2511     loadApplication.addActionListener(this);
2512
2513     loadTree.addActionListener(this);
2514     loadAnnotations.addActionListener(this);
2515     outputFeatures.addActionListener(this);
2516     outputAnnotations.addActionListener(this);
2517     selectAllSequenceMenuItem.addActionListener(this);
2518     deselectAllSequenceMenuItem.addActionListener(this);
2519     invertSequenceMenuItem.addActionListener(this);
2520     remove2LeftMenuItem.setLabel("Remove Left");
2521     remove2LeftMenuItem.addActionListener(this);
2522     remove2RightMenuItem.setLabel("Remove Right");
2523     remove2RightMenuItem.addActionListener(this);
2524     removeGappedColumnMenuItem.setLabel("Remove Empty Columns");
2525     removeGappedColumnMenuItem.addActionListener(this);
2526     removeAllGapsMenuItem.setLabel("Remove All Gaps");
2527     removeAllGapsMenuItem.addActionListener(this);
2528     viewBoxesMenuItem.setLabel("Boxes");
2529     viewBoxesMenuItem.setState(true);
2530     viewBoxesMenuItem.addItemListener(this);
2531     viewTextMenuItem.setLabel("Text");
2532     viewTextMenuItem.setState(true);
2533     viewTextMenuItem.addItemListener(this);
2534     sortPairwiseMenuItem.setLabel("by Pairwise Identity");
2535     sortPairwiseMenuItem.addActionListener(this);
2536     sortIDMenuItem.setLabel("by ID");
2537     sortIDMenuItem.addActionListener(this);
2538     sortGroupMenuItem.setLabel("by Group");
2539     sortGroupMenuItem.addActionListener(this);
2540     removeRedundancyMenuItem.setLabel("Remove Redundancy...");
2541     removeRedundancyMenuItem.addActionListener(this);
2542     pairwiseAlignmentMenuItem.setLabel("Pairwise Alignments...");
2543     pairwiseAlignmentMenuItem.addActionListener(this);
2544     PCAMenuItem.setLabel("Principal Component Analysis");
2545     PCAMenuItem.addActionListener(this);
2546     averageDistanceTreeMenuItem.setLabel(
2547         "Average Distance Using % Identity");
2548     averageDistanceTreeMenuItem.addActionListener(this);
2549     neighbourTreeMenuItem.setLabel("Neighbour Joining Using % Identity");
2550     neighbourTreeMenuItem.addActionListener(this);
2551     statusBar.setBackground(Color.white);
2552     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
2553     statusBar.setText("Status bar");
2554     outputTextboxMenu.setLabel("Output to Textbox");
2555     clustalColour.setLabel("Clustalx");
2556
2557     clustalColour.addActionListener(this);
2558     zappoColour.setLabel("Zappo");
2559     zappoColour.addActionListener(this);
2560     taylorColour.setLabel("Taylor");
2561     taylorColour.addActionListener(this);
2562     hydrophobicityColour.setLabel("Hydrophobicity");
2563     hydrophobicityColour.addActionListener(this);
2564     helixColour.setLabel("Helix Propensity");
2565     helixColour.addActionListener(this);
2566     strandColour.setLabel("Strand Propensity");
2567     strandColour.addActionListener(this);
2568     turnColour.setLabel("Turn Propensity");
2569     turnColour.addActionListener(this);
2570     buriedColour.setLabel("Buried Index");
2571     buriedColour.addActionListener(this);
2572     userDefinedColour.setLabel("User Defined...");
2573     userDefinedColour.addActionListener(this);
2574     PIDColour.setLabel("Percentage Identity");
2575     PIDColour.addActionListener(this);
2576     BLOSUM62Colour.setLabel("BLOSUM62 Score");
2577     BLOSUM62Colour.addActionListener(this);
2578     avDistanceTreeBlosumMenuItem.setLabel(
2579         "Average Distance Using BLOSUM62");
2580     avDistanceTreeBlosumMenuItem.addActionListener(this);
2581     njTreeBlosumMenuItem.setLabel("Neighbour Joining Using BLOSUM62");
2582     njTreeBlosumMenuItem.addActionListener(this);
2583     annotationPanelMenuItem.setLabel("Show Annotations");
2584     annotationPanelMenuItem.addItemListener(this);
2585     colourTextMenuItem.setLabel("Colour Text");
2586     colourTextMenuItem.addItemListener(this);
2587     alProperties.addActionListener(this);
2588     overviewMenuItem.setLabel("Overview Window");
2589     overviewMenuItem.addActionListener(this);
2590     undoMenuItem.setEnabled(false);
2591     undoMenuItem.setLabel("Undo");
2592     undoMenuItem.addActionListener(this);
2593     redoMenuItem.setEnabled(false);
2594     redoMenuItem.setLabel("Redo");
2595     redoMenuItem.addActionListener(this);
2596     conservationMenuItem.setLabel("by Conservation");
2597     conservationMenuItem.addItemListener(this);
2598     noColourmenuItem.setLabel("None");
2599     noColourmenuItem.addActionListener(this);
2600     wrapMenuItem.setLabel("Wrap");
2601     wrapMenuItem.addItemListener(this);
2602     renderGapsMenuItem.setLabel("Show Gaps");
2603     renderGapsMenuItem.setState(true);
2604     renderGapsMenuItem.addItemListener(this);
2605     findMenuItem.setLabel("Find...");
2606     findMenuItem.addActionListener(this);
2607     abovePIDThreshold.setLabel("Above Identity Threshold");
2608     abovePIDThreshold.addItemListener(this);
2609     nucleotideColour.setLabel("Nucleotide");
2610     nucleotideColour.addActionListener(this);
2611     deleteGroups.setLabel("Undefine Groups");
2612     deleteGroups.addActionListener(this);
2613     copy.setLabel("Copy");
2614     copy.addActionListener(this);
2615     cut.setLabel("Cut");
2616     cut.addActionListener(this);
2617     delete.setLabel("Delete");
2618     delete.addActionListener(this);
2619     pasteMenu.setLabel("Paste");
2620     pasteNew.setLabel("To New Alignment");
2621     pasteNew.addActionListener(this);
2622     pasteThis.setLabel("Add To This Alignment");
2623     pasteThis.addActionListener(this);
2624     applyToAllGroups.setLabel("Apply Colour To All Groups");
2625     applyToAllGroups.setState(true);
2626     applyToAllGroups.addItemListener(this);
2627     font.setLabel("Font...");
2628     font.addActionListener(this);
2629     scaleAbove.setLabel("Scale Above");
2630     scaleAbove.setState(true);
2631     scaleAbove.setEnabled(false);
2632     scaleAbove.addItemListener(this);
2633     scaleLeft.setEnabled(false);
2634     scaleLeft.setState(true);
2635     scaleLeft.setLabel("Scale Left");
2636     scaleLeft.addItemListener(this);
2637     scaleRight.setEnabled(false);
2638     scaleRight.setState(true);
2639     scaleRight.setLabel("Scale Right");
2640     scaleRight.addItemListener(this);
2641     modifyPID.setLabel("Modify Identity Threshold...");
2642     modifyPID.addActionListener(this);
2643     modifyConservation.setLabel("Modify Conservation Threshold...");
2644     modifyConservation.addActionListener(this);
2645     sortByTreeMenu.setLabel("By Tree Order");
2646     sort.setLabel("Sort");
2647     calculate.setLabel("Calculate Tree");
2648     autoCalculate.addItemListener(this);
2649     inputText.setLabel("Input from textbox");
2650     inputText.addActionListener(this);
2651     centreColumnLabelFlag.setLabel("Centre column labels");
2652     centreColumnLabelFlag.addItemListener(this);
2653     
2654     helpMenu.setLabel("Help");
2655     documentation.setLabel("Documentation");
2656     documentation.addActionListener(this);
2657
2658     about.setLabel("About...");
2659     about.addActionListener(this);
2660     seqLimits.setState(true);
2661     seqLimits.setLabel("Show Sequence Limits");
2662     seqLimits.addItemListener(this);
2663     featureSettings.setLabel("Feature Settings...");
2664     featureSettings.addActionListener(this);
2665     sequenceFeatures.setLabel("Sequence Features");
2666     sequenceFeatures.addItemListener(this);
2667     sequenceFeatures.setState(false);
2668     annotationColour.setLabel("by Annotation...");
2669     annotationColour.addActionListener(this);
2670     invertSequenceMenuItem.setLabel("Invert Sequence Selection");
2671     invertColSel.setLabel("Invert Column Selection");
2672     menu1.setLabel("Show");
2673     showColumns.setLabel("All Columns ");
2674     showSeqs.setLabel("All Sequences");
2675     menu2.setLabel("Hide");
2676     hideColumns.setLabel("Selected Columns");
2677     hideSequences.setLabel("Selected Sequences");
2678     invertColSel.addActionListener(this);
2679     showColumns.addActionListener(this);
2680     showSeqs.addActionListener(this);
2681     hideColumns.addActionListener(this);
2682     hideSequences.addActionListener(this);
2683     formatMenu.setLabel("Format");
2684     selectMenu.setLabel("Select");
2685     newView.setLabel("New View");
2686     newView.addActionListener(this);
2687     alignFrameMenuBar.add(fileMenu);
2688     alignFrameMenuBar.add(editMenu);
2689     alignFrameMenuBar.add(selectMenu);
2690     alignFrameMenuBar.add(viewMenu);
2691     alignFrameMenuBar.add(formatMenu);
2692     alignFrameMenuBar.add(colourMenu);
2693     alignFrameMenuBar.add(calculateMenu);
2694     alignFrameMenuBar.add(helpMenu);
2695
2696     fileMenu.add(inputText);
2697     fileMenu.add(loadTree);
2698     fileMenu.add(loadAnnotations);
2699
2700     fileMenu.addSeparator();
2701     fileMenu.add(outputTextboxMenu);
2702     fileMenu.add(outputFeatures);
2703     fileMenu.add(outputAnnotations);
2704
2705     if (jalviewServletURL != null)
2706     {
2707       fileMenu.add(loadApplication);
2708     }
2709
2710     fileMenu.addSeparator();
2711     fileMenu.add(closeMenuItem);
2712
2713     editMenu.add(undoMenuItem);
2714     editMenu.add(redoMenuItem);
2715     editMenu.add(cut);
2716     editMenu.add(copy);
2717     editMenu.add(pasteMenu);
2718     editMenu.add(delete);
2719     editMenu.addSeparator();
2720     editMenu.add(remove2LeftMenuItem);
2721     editMenu.add(remove2RightMenuItem);
2722     editMenu.add(removeGappedColumnMenuItem);
2723     editMenu.add(removeAllGapsMenuItem);
2724     editMenu.add(removeRedundancyMenuItem);
2725     viewMenu.add(newView);
2726     viewMenu.addSeparator();
2727     viewMenu.add(menu1);
2728     viewMenu.add(menu2);
2729     viewMenu.addSeparator();
2730     viewMenu.add(annotationPanelMenuItem);
2731     viewMenu.addSeparator();
2732     viewMenu.add(sequenceFeatures);
2733     viewMenu.add(featureSettings);
2734     viewMenu.addSeparator();
2735     viewMenu.add(alProperties);
2736     viewMenu.addSeparator();
2737     viewMenu.add(overviewMenuItem);
2738     colourMenu.add(applyToAllGroups);
2739     colourMenu.addSeparator();
2740     colourMenu.add(noColourmenuItem);
2741     colourMenu.add(clustalColour);
2742     colourMenu.add(BLOSUM62Colour);
2743     colourMenu.add(PIDColour);
2744     colourMenu.add(zappoColour);
2745     colourMenu.add(taylorColour);
2746     colourMenu.add(hydrophobicityColour);
2747     colourMenu.add(helixColour);
2748     colourMenu.add(strandColour);
2749     colourMenu.add(turnColour);
2750     colourMenu.add(buriedColour);
2751     colourMenu.add(nucleotideColour);
2752     colourMenu.add(userDefinedColour);
2753     colourMenu.addSeparator();
2754     colourMenu.add(conservationMenuItem);
2755     colourMenu.add(modifyConservation);
2756     colourMenu.add(abovePIDThreshold);
2757     colourMenu.add(modifyPID);
2758     colourMenu.add(annotationColour);
2759     calculateMenu.add(sort);
2760     calculateMenu.add(calculate);
2761     calculateMenu.addSeparator();
2762     calculateMenu.add(pairwiseAlignmentMenuItem);
2763     calculateMenu.add(PCAMenuItem);
2764     calculateMenu.add(autoCalculate);
2765     this.add(statusBar, BorderLayout.SOUTH);
2766     pasteMenu.add(pasteNew);
2767     pasteMenu.add(pasteThis);
2768     sort.add(sortIDMenuItem);
2769     sort.add(sortByTreeMenu);
2770     sort.add(sortGroupMenuItem);
2771     sort.add(sortPairwiseMenuItem);
2772     calculate.add(averageDistanceTreeMenuItem);
2773     calculate.add(neighbourTreeMenuItem);
2774     calculate.add(avDistanceTreeBlosumMenuItem);
2775     calculate.add(njTreeBlosumMenuItem);
2776     helpMenu.add(documentation);
2777     helpMenu.add(about);
2778     menu1.add(showColumns);
2779     menu1.add(showSeqs);
2780     menu2.add(hideColumns);
2781     menu2.add(hideSequences);
2782     formatMenu.add(font);
2783     formatMenu.add(seqLimits);
2784     formatMenu.add(wrapMenuItem);
2785     formatMenu.add(scaleAbove);
2786     formatMenu.add(scaleLeft);
2787     formatMenu.add(scaleRight);
2788     formatMenu.add(viewBoxesMenuItem);
2789     formatMenu.add(viewTextMenuItem);
2790     formatMenu.add(colourTextMenuItem);
2791     formatMenu.add(renderGapsMenuItem);
2792     formatMenu.add(centreColumnLabelFlag);
2793     selectMenu.add(findMenuItem);
2794     selectMenu.addSeparator();
2795     selectMenu.add(selectAllSequenceMenuItem);
2796     selectMenu.add(deselectAllSequenceMenuItem);
2797     selectMenu.add(invertSequenceMenuItem);
2798     selectMenu.add(invertColSel);
2799     selectMenu.add(deleteGroups);
2800   }
2801   MenuItem featureSettings = new MenuItem();
2802   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();
2803   MenuItem annotationColour = new MenuItem();
2804   MenuItem invertColSel = new MenuItem();
2805   Menu menu1 = new Menu();
2806   MenuItem showColumns = new MenuItem();
2807   MenuItem showSeqs = new MenuItem();
2808   Menu menu2 = new Menu();
2809   MenuItem hideColumns = new MenuItem();
2810   MenuItem hideSequences = new MenuItem();
2811   Menu formatMenu = new Menu();
2812   Menu selectMenu = new Menu();
2813   MenuItem newView = new MenuItem();
2814
2815   /**
2816    * Attach the alignFrame panels after embedding menus, if necessary.
2817    * This used to be called setEmbedded, but is now creates the 
2818    * dropdown menus in a platform independent manner
2819    * to avoid OSX/Mac menu appendage daftness.
2820    *  
2821    * @param reallyEmbedded true to attach the view to the applet area on the page rather than in a new window
2822    */
2823   public void createAlignFrameWindow(boolean reallyEmbedded, String title)
2824   {
2825     if (reallyEmbedded)
2826     {
2827       //////
2828       // Explicly build the embedded menu panel for the on-page applet
2829       //
2830       // view cannot be closed if its actually on the page
2831       fileMenu.remove(closeMenuItem);
2832       fileMenu.remove(3); // Remove Seperator
2833       embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, "Arial", Font.PLAIN, 10, false); // use our own fonts.
2834       // and actually add the components to the applet area
2835       viewport.applet.setLayout(new BorderLayout());
2836       viewport.applet.add(embeddedMenu, BorderLayout.NORTH);
2837       viewport.applet.add(statusBar, BorderLayout.SOUTH);
2838       alignPanel.setSize(viewport.applet.getSize().width,
2839               viewport.applet.getSize().height
2840               - embeddedMenu.HEIGHT - statusBar.HEIGHT);
2841       viewport.applet.add(alignPanel, BorderLayout.CENTER);
2842       viewport.applet.validate();
2843     } else {
2844       ////////
2845       // test and embed menu bar if necessary.
2846       //
2847       if (embedMenuIfNeeded(alignPanel)) {
2848         // adjust for status bar height too
2849         alignPanel.setSize(getSize().width,
2850               getSize().height
2851                 - statusBar.HEIGHT);
2852       }
2853       add(statusBar, BorderLayout.SOUTH);
2854       add(alignPanel, BorderLayout.CENTER);
2855       // and register with the applet so it can pass external API calls to us
2856       jalview.bin.JalviewLite.addFrame(this, title, DEFAULT_WIDTH,
2857                                          DEFAULT_HEIGHT);
2858     }
2859   }
2860 }