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