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