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