JAL-1641 remove all refs/imports from gui package
[jalview.git] / src / jalview / appletgui / AlignFrame.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
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
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.appletgui;
22
23 import jalview.analysis.AlignmentSorter;
24 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
25 import jalview.api.AlignViewControllerGuiI;
26 import jalview.api.AlignViewControllerI;
27 import jalview.api.AlignViewportI;
28 import jalview.api.FeatureRenderer;
29 import jalview.api.SequenceStructureBinding;
30 import jalview.bin.JalviewLite;
31 import jalview.commands.CommandI;
32 import jalview.commands.EditCommand;
33 import jalview.commands.EditCommand.Action;
34 import jalview.commands.OrderCommand;
35 import jalview.commands.RemoveGapColCommand;
36 import jalview.commands.RemoveGapsCommand;
37 import jalview.commands.SlideSequencesCommand;
38 import jalview.commands.TrimRegionCommand;
39 import jalview.datamodel.Alignment;
40 import jalview.datamodel.AlignmentAnnotation;
41 import jalview.datamodel.AlignmentI;
42 import jalview.datamodel.AlignmentOrder;
43 import jalview.datamodel.ColumnSelection;
44 import jalview.datamodel.PDBEntry;
45 import jalview.datamodel.Sequence;
46 import jalview.datamodel.SequenceGroup;
47 import jalview.datamodel.SequenceI;
48 import jalview.io.AnnotationFile;
49 import jalview.io.AppletFormatAdapter;
50 import jalview.io.FeaturesFile;
51 import jalview.io.TCoffeeScoreFile;
52 import jalview.schemes.Blosum62ColourScheme;
53 import jalview.schemes.BuriedColourScheme;
54 import jalview.schemes.ClustalxColourScheme;
55 import jalview.schemes.ColourSchemeI;
56 import jalview.schemes.HelixColourScheme;
57 import jalview.schemes.HydrophobicColourScheme;
58 import jalview.schemes.NucleotideColourScheme;
59 import jalview.schemes.PIDColourScheme;
60 import jalview.schemes.PurinePyrimidineColourScheme;
61 import jalview.schemes.RNAHelicesColourChooser;
62 import jalview.schemes.RNAInteractionColourScheme;
63 import jalview.schemes.StrandColourScheme;
64 import jalview.schemes.TCoffeeColourScheme;
65 import jalview.schemes.TaylorColourScheme;
66 import jalview.schemes.TurnColourScheme;
67 import jalview.schemes.ZappoColourScheme;
68 import jalview.structure.StructureSelectionManager;
69 import jalview.structures.models.AAStructureBindingModel;
70 import jalview.util.MappingUtils;
71 import jalview.util.MessageManager;
72 import jalview.viewmodel.AlignmentViewport;
73
74 import java.awt.BorderLayout;
75 import java.awt.Canvas;
76 import java.awt.CheckboxMenuItem;
77 import java.awt.Color;
78 import java.awt.Font;
79 import java.awt.FontMetrics;
80 import java.awt.Frame;
81 import java.awt.Graphics;
82 import java.awt.Label;
83 import java.awt.Menu;
84 import java.awt.MenuBar;
85 import java.awt.MenuItem;
86 import java.awt.event.ActionEvent;
87 import java.awt.event.ActionListener;
88 import java.awt.event.FocusEvent;
89 import java.awt.event.FocusListener;
90 import java.awt.event.ItemEvent;
91 import java.awt.event.ItemListener;
92 import java.awt.event.KeyEvent;
93 import java.awt.event.KeyListener;
94 import java.awt.event.WindowAdapter;
95 import java.awt.event.WindowEvent;
96 import java.io.IOException;
97 import java.net.URL;
98 import java.net.URLEncoder;
99 import java.util.Arrays;
100 import java.util.Deque;
101 import java.util.HashMap;
102 import java.util.Hashtable;
103 import java.util.List;
104 import java.util.Map;
105 import java.util.StringTokenizer;
106 import java.util.Vector;
107
108 public class AlignFrame extends EmbmenuFrame implements ActionListener,
109         ItemListener, KeyListener, AlignViewControllerGuiI
110 {
111   public AlignViewControllerI avc;
112
113   public AlignmentPanel alignPanel;
114
115   public AlignViewport viewport;
116
117   // width and height may be overridden by applet parameters
118   int frameWidth = 700;
119
120   int frameHeight = 500;
121
122   String jalviewServletURL;
123
124   /*
125    * Flag for showing autocalculated consensus above or below other consensus
126    * rows
127    */
128   private boolean showAutoCalculatedAbove;
129
130   private SequenceAnnotationOrder annotationSortOrder;
131
132   /**
133    * Constructor that creates the frame and adds it to the display.
134    * 
135    * @param al
136    * @param applet
137    * @param title
138    * @param embedded
139    */
140   public AlignFrame(AlignmentI al, JalviewLite applet,
141           String title, boolean embedded)
142   {
143     this(al, applet, title, embedded, true);
144   }
145
146   /**
147    * Constructor that optionally allows the frame to be displayed or only
148    * created.
149    * 
150    * @param al
151    * @param applet
152    * @param title
153    * @param embedded
154    * @param addToDisplay
155    */
156   public AlignFrame(AlignmentI al, JalviewLite applet,
157           String title, boolean embedded, boolean addToDisplay)
158   {
159     if (applet != null)
160     {
161       jalviewServletURL = applet.getParameter("APPLICATION_URL");
162     }
163
164     try
165     {
166       jbInit();
167     } catch (Exception ex)
168     {
169       ex.printStackTrace();
170     }
171     // need to get window geometry before we calculate alignment layout
172     if (applet != null)
173     {
174       String param;
175       try
176       {
177         param = applet.getParameter("windowWidth");
178         if (param != null)
179         {
180           int width = Integer.parseInt(param);
181           frameWidth = width;
182         }
183         param = applet.getParameter("windowHeight");
184         if (param != null)
185         {
186           int height = Integer.parseInt(param);
187           frameHeight = height;
188         }
189       } catch (Exception ex)
190       {
191       }
192     }
193     viewport = new AlignViewport(al, applet);
194     alignPanel = new AlignmentPanel(this, viewport);
195     avc = new jalview.controller.AlignViewController(this, viewport,
196             alignPanel);
197     viewport.updateConservation(alignPanel);
198     viewport.updateConsensus(alignPanel);
199
200     displayNonconservedMenuItem.setState(viewport.getShowUnconserved());
201     followMouseOverFlag.setState(viewport.isFollowHighlight());
202     showGroupConsensus.setState(viewport.isShowGroupConsensus());
203     showGroupConservation.setState(viewport.isShowGroupConservation());
204     showConsensusHistogram.setState(viewport.isShowConsensusHistogram());
205     showSequenceLogo.setState(viewport.isShowSequenceLogo());
206     normSequenceLogo.setState(viewport.isNormaliseSequenceLogo());
207     applyToAllGroups.setState(viewport.getColourAppliesToAllGroups());
208     annotationPanelMenuItem.setState(viewport.isShowAnnotation());
209     showAlignmentAnnotations.setState(viewport.isShowAnnotation());
210     showSequenceAnnotations.setState(viewport.isShowAnnotation());
211
212     seqLimits.setState(viewport.getShowJVSuffix());
213
214     if (applet != null)
215     {
216       String param = applet.getParameter("sortBy");
217       if (param != null)
218       {
219         if (param.equalsIgnoreCase("Id"))
220         {
221           sortIDMenuItem_actionPerformed();
222         }
223         else if (param.equalsIgnoreCase("Pairwise Identity"))
224         {
225           sortPairwiseMenuItem_actionPerformed();
226         }
227         else if (param.equalsIgnoreCase("Length"))
228         {
229           sortLengthMenuItem_actionPerformed();
230         }
231       }
232
233       param = applet.getParameter("wrap");
234       if (param != null)
235       {
236         if (param.equalsIgnoreCase("true"))
237         {
238           wrapMenuItem.setState(true);
239           wrapMenuItem_actionPerformed();
240         }
241       }
242       param = applet.getParameter("centrecolumnlabels");
243       if (param != null)
244       {
245         centreColumnLabelFlag.setState(true);
246         centreColumnLabelFlag_stateChanged();
247       }
248
249     }
250     if (viewport.getAlignment().isNucleotide())
251     {
252       viewport.updateStrucConsensus(alignPanel);
253       if (viewport.getAlignment().hasRNAStructure())
254       {
255         RNAHelixColour.setEnabled(true);
256       }
257       else
258       {
259         RNAHelixColour.setEnabled(false);
260       }
261     }
262     else
263     {
264       RNAHelixColour.setEnabled(false);
265       purinePyrimidineColour.setEnabled(false);
266     }
267     // Some JVMS send keyevents to Top frame or lowest panel,
268     // Havent worked out why yet. So add to both this frame and seqCanvas for
269     // now
270     this.addKeyListener(this);
271     alignPanel.seqPanel.seqCanvas.addKeyListener(this);
272     alignPanel.idPanel.idCanvas.addKeyListener(this);
273     alignPanel.scalePanel.addKeyListener(this);
274     alignPanel.annotationPanel.addKeyListener(this);
275     alignPanel.annotationPanelHolder.addKeyListener(this);
276     alignPanel.annotationSpaceFillerHolder.addKeyListener(this);
277     alignPanel.alabels.addKeyListener(this);
278
279     if (addToDisplay)
280     {
281       addToDisplay(embedded);
282     }
283   }
284
285   /**
286    * @param embedded
287    */
288   public void addToDisplay(boolean embedded)
289   {
290     createAlignFrameWindow(embedded);
291     validate();
292     alignPanel.adjustAnnotationHeight();
293     alignPanel.paintAlignment(true);
294   }
295
296   public AlignViewport getAlignViewport()
297   {
298     return viewport;
299   }
300
301   public SeqCanvas getSeqcanvas()
302   {
303     return alignPanel.seqPanel.seqCanvas;
304   }
305
306   /**
307    * Load a features file onto the alignment
308    * 
309    * @param file
310    *          file URL, content, or other resolvable path
311    * @param type
312    *          is protocol for accessing data referred to by file
313    */
314
315   public boolean parseFeaturesFile(String file, String type)
316   {
317     return parseFeaturesFile(file, type, true);
318   }
319
320   /**
321    * Load a features file onto the alignment
322    * 
323    * @param file
324    *          file URL, content, or other resolvable path
325    * @param type
326    *          is protocol for accessing data referred to by file
327    * @param autoenabledisplay
328    *          when true, display features flag will be automatically enabled if
329    *          features are loaded
330    * @return true if data parsed as a features file
331    */
332   public boolean parseFeaturesFile(String file, String type,
333           boolean autoenabledisplay)
334   {
335     // TODO: test if importing a features file onto an alignment which already
336     // has features with links overwrites the original links.
337
338     Hashtable featureLinks = new Hashtable();
339     boolean featuresFile = false;
340     try
341     {
342       featuresFile = new jalview.io.FeaturesFile(file, type)
343               .parse(viewport.getAlignment(), alignPanel.seqPanel.seqCanvas
344                       .getFeatureRenderer().getFeatureColours(), featureLinks,
345                       true, viewport.applet.getDefaultParameter(
346                               "relaxedidmatch", false));
347     } catch (Exception ex)
348     {
349       ex.printStackTrace();
350     }
351
352     if (featuresFile)
353     {
354       if (featureLinks.size() > 0)
355       {
356         alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureLinks = featureLinks;
357       }
358       if (autoenabledisplay)
359       {
360         viewport.setShowSequenceFeatures(true);
361         sequenceFeatures.setState(true);
362       }
363       if (alignPanel.seqPanel.seqCanvas.fr != null)
364       {
365         // update the min/max ranges where necessary
366         alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true);
367       }
368       if (viewport.featureSettings != null)
369       {
370         viewport.featureSettings.refreshTable();
371       }
372       alignPanel.paintAlignment(true);
373       statusBar.setText(MessageManager
374               .getString("label.successfully_added_features_alignment"));
375     }
376     return featuresFile;
377   }
378
379   @Override
380   public void keyPressed(KeyEvent evt)
381   {
382     if (viewport.cursorMode
383             && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt
384                     .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
385                     .getKeyCode() <= KeyEvent.VK_NUMPAD9))
386             && Character.isDigit(evt.getKeyChar()))
387     {
388       alignPanel.seqPanel.numberPressed(evt.getKeyChar());
389     }
390
391     switch (evt.getKeyCode())
392     {
393     case 27: // escape key
394       deselectAllSequenceMenuItem_actionPerformed();
395
396       alignPanel.alabels.cancelDrag();
397       break;
398     case KeyEvent.VK_X:
399       if (evt.isControlDown() || evt.isMetaDown())
400       {
401         cut_actionPerformed();
402       }
403       break;
404     case KeyEvent.VK_C:
405       if (viewport.cursorMode && !evt.isControlDown())
406       {
407         alignPanel.seqPanel.setCursorColumn();
408       }
409       if (evt.isControlDown() || evt.isMetaDown())
410       {
411         copy_actionPerformed();
412       }
413       break;
414     case KeyEvent.VK_V:
415       if (evt.isControlDown())
416       {
417         paste(evt.isShiftDown());
418       }
419       break;
420     case KeyEvent.VK_A:
421       if (evt.isControlDown() || evt.isMetaDown())
422       {
423         selectAllSequenceMenuItem_actionPerformed();
424       }
425       break;
426     case KeyEvent.VK_DOWN:
427       if (viewport.cursorMode)
428       {
429         alignPanel.seqPanel.moveCursor(0, 1);
430       }
431       else
432       {
433         moveSelectedSequences(false);
434       }
435       break;
436
437     case KeyEvent.VK_UP:
438       if (viewport.cursorMode)
439       {
440         alignPanel.seqPanel.moveCursor(0, -1);
441       }
442       else
443       {
444         moveSelectedSequences(true);
445       }
446       break;
447
448     case KeyEvent.VK_LEFT:
449       if (evt.isAltDown() || !viewport.cursorMode)
450       {
451         slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());
452       }
453       else
454       {
455         alignPanel.seqPanel.moveCursor(-1, 0);
456       }
457       break;
458
459     case KeyEvent.VK_RIGHT:
460       if (evt.isAltDown() || !viewport.cursorMode)
461       {
462         slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());
463       }
464       else
465       {
466         alignPanel.seqPanel.moveCursor(1, 0);
467       }
468       break;
469
470     case KeyEvent.VK_SPACE:
471       if (viewport.cursorMode)
472       {
473         alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()
474                 || evt.isShiftDown() || evt.isAltDown());
475       }
476       break;
477
478     case KeyEvent.VK_DELETE:
479     case KeyEvent.VK_BACK_SPACE:
480       if (viewport.cursorMode)
481       {
482         alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()
483                 || evt.isShiftDown() || evt.isAltDown());
484       }
485       else
486       {
487         cut_actionPerformed();
488         alignPanel.seqPanel.seqCanvas.repaint();
489       }
490       break;
491
492     case KeyEvent.VK_S:
493       if (viewport.cursorMode)
494       {
495         alignPanel.seqPanel.setCursorRow();
496       }
497       break;
498     case KeyEvent.VK_P:
499       if (viewport.cursorMode)
500       {
501         alignPanel.seqPanel.setCursorPosition();
502       }
503       break;
504
505     case KeyEvent.VK_ENTER:
506     case KeyEvent.VK_COMMA:
507       if (viewport.cursorMode)
508       {
509         alignPanel.seqPanel.setCursorRowAndColumn();
510       }
511       break;
512
513     case KeyEvent.VK_Q:
514       if (viewport.cursorMode)
515       {
516         alignPanel.seqPanel.setSelectionAreaAtCursor(true);
517       }
518       break;
519     case KeyEvent.VK_M:
520       if (viewport.cursorMode)
521       {
522         alignPanel.seqPanel.setSelectionAreaAtCursor(false);
523       }
524       break;
525
526     case KeyEvent.VK_F2:
527       viewport.cursorMode = !viewport.cursorMode;
528       statusBar.setText(MessageManager.formatMessage(
529               "label.keyboard_editing_mode", new String[]
530               { (viewport.cursorMode ? "on" : "off") }));
531       if (viewport.cursorMode)
532       {
533         alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
534         alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
535       }
536       break;
537
538     case KeyEvent.VK_F:
539       if (evt.isControlDown())
540       {
541         findMenuItem_actionPerformed();
542       }
543       break;
544
545     case KeyEvent.VK_H:
546     {
547       boolean toggleSeqs = !evt.isControlDown();
548       boolean toggleCols = !evt.isShiftDown();
549       toggleHiddenRegions(toggleSeqs, toggleCols);
550       break;
551     }
552
553     case KeyEvent.VK_PAGE_UP:
554       if (viewport.getWrapAlignment())
555       {
556         alignPanel.scrollUp(true);
557       }
558       else
559       {
560         alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
561                 - viewport.endSeq + viewport.startSeq);
562       }
563       break;
564
565     case KeyEvent.VK_PAGE_DOWN:
566       if (viewport.getWrapAlignment())
567       {
568         alignPanel.scrollUp(false);
569       }
570       else
571       {
572         alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
573                 + viewport.endSeq - viewport.startSeq);
574       }
575       break;
576
577     case KeyEvent.VK_Z:
578       if (evt.isControlDown())
579       {
580         undoMenuItem_actionPerformed();
581       }
582       break;
583
584     case KeyEvent.VK_Y:
585       if (evt.isControlDown())
586       {
587         redoMenuItem_actionPerformed();
588       }
589       break;
590
591     case KeyEvent.VK_L:
592       if (evt.isControlDown())
593       {
594         trimAlignment(true);
595       }
596       break;
597
598     case KeyEvent.VK_R:
599       if (evt.isControlDown())
600       {
601         trimAlignment(false);
602       }
603       break;
604
605     case KeyEvent.VK_E:
606       if (evt.isControlDown())
607       {
608         if (evt.isShiftDown())
609         {
610           this.removeAllGapsMenuItem_actionPerformed();
611         }
612         else
613         {
614           removeGappedColumnMenuItem_actionPerformed();
615         }
616       }
617       break;
618     case KeyEvent.VK_I:
619       if (evt.isControlDown())
620       {
621         if (evt.isAltDown())
622         {
623           invertColSel_actionPerformed();
624         }
625         else
626         {
627           invertSequenceMenuItem_actionPerformed();
628         }
629       }
630       break;
631
632     case KeyEvent.VK_G:
633       if (evt.isControlDown())
634       {
635         if (evt.isShiftDown())
636         {
637           this.unGroup_actionPerformed();
638         }
639         else
640         {
641           this.createGroup_actionPerformed();
642         }
643       }
644       break;
645
646     case KeyEvent.VK_U:
647       if (evt.isControlDown())
648       {
649         this.deleteGroups_actionPerformed();
650       }
651       break;
652
653     case KeyEvent.VK_T:
654       if (evt.isControlDown())
655       {
656         newView(null);
657       }
658       break;
659
660     }
661     alignPanel.paintAlignment(true);
662   }
663
664   /**
665    * called by key handler and the hide all/show all menu items
666    * 
667    * @param toggleSeqs
668    * @param toggleCols
669    */
670   private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
671   {
672     boolean hide = false;
673     SequenceGroup sg = viewport.getSelectionGroup();
674     if (!toggleSeqs && !toggleCols)
675     {
676       // Hide everything by the current selection - this is a hack - we do the
677       // invert and then hide
678       // first check that there will be visible columns after the invert.
679       if ((viewport.getColumnSelection() != null
680               && viewport.getColumnSelection().getSelected() != null && viewport
681               .getColumnSelection().getSelected().size() > 0)
682               || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg
683                       .getEndRes()))
684       {
685         // now invert the sequence set, if required - empty selection implies
686         // that no hiding is required.
687         if (sg != null)
688         {
689           invertSequenceMenuItem_actionPerformed();
690           sg = viewport.getSelectionGroup();
691           toggleSeqs = true;
692
693         }
694         viewport.expandColSelection(sg, true);
695         // finally invert the column selection and get the new sequence
696         // selection and indicate it should be hidden.
697         invertColSel_actionPerformed();
698         toggleCols = true;
699       }
700     }
701
702     if (toggleSeqs)
703     {
704       if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
705       {
706         hide = true;
707         viewport.hideAllSelectedSeqs();
708       }
709       else if (!(toggleCols && viewport.getColumnSelection().getSelected()
710               .size() > 0))
711       {
712         viewport.showAllHiddenSeqs();
713       }
714     }
715
716     if (toggleCols)
717     {
718       if (viewport.getColumnSelection().getSelected().size() > 0)
719       {
720         viewport.hideSelectedColumns();
721         if (!toggleSeqs)
722         {
723           viewport.setSelectionGroup(sg);
724         }
725       }
726       else if (!hide)
727       {
728         viewport.showAllHiddenColumns();
729       }
730     }
731   }
732
733   @Override
734   public void keyReleased(KeyEvent evt)
735   {
736   }
737
738   @Override
739   public void keyTyped(KeyEvent evt)
740   {
741   }
742
743   @Override
744   public void itemStateChanged(ItemEvent evt)
745   {
746     final Object source = evt.getSource();
747     if (source == displayNonconservedMenuItem)
748     {
749       displayNonconservedMenuItem_actionPerformed();
750     }
751     else if (source == colourTextMenuItem)
752     {
753       colourTextMenuItem_actionPerformed();
754     }
755     else if (source == wrapMenuItem)
756     {
757       wrapMenuItem_actionPerformed();
758     }
759     else if (source == scaleAbove)
760     {
761       viewport.setScaleAboveWrapped(scaleAbove.getState());
762     }
763     else if (source == scaleLeft)
764     {
765       viewport.setScaleLeftWrapped(scaleLeft.getState());
766     }
767     else if (source == scaleRight)
768     {
769       viewport.setScaleRightWrapped(scaleRight.getState());
770     }
771     else if (source == seqLimits)
772     {
773       seqLimits_itemStateChanged();
774     }
775     else if (source == viewBoxesMenuItem)
776     {
777       viewport.setShowBoxes(viewBoxesMenuItem.getState());
778     }
779     else if (source == viewTextMenuItem)
780     {
781       viewport.setShowText(viewTextMenuItem.getState());
782     }
783     else if (source == renderGapsMenuItem)
784     {
785       viewport.setRenderGaps(renderGapsMenuItem.getState());
786     }
787     else if (source == annotationPanelMenuItem)
788     {
789       viewport.setShowAnnotation(annotationPanelMenuItem.getState());
790       alignPanel.setAnnotationVisible(annotationPanelMenuItem.getState());
791     }
792     else if (source == sequenceFeatures)
793     {
794       viewport.setShowSequenceFeatures(sequenceFeatures.getState());
795       alignPanel.seqPanel.seqCanvas.repaint();
796     }
797     else if (source == showAlignmentAnnotations)
798     {
799       setAnnotationsVisibility();
800     }
801     else if (source == showSequenceAnnotations)
802     {
803       setAnnotationsVisibility();
804     }
805     else if (source == sortAnnBySequence)
806     {
807       boolean newState = sortAnnBySequence.getState();
808       sortAnnByLabel.setState(false);
809       setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL
810               : SequenceAnnotationOrder.NONE);
811       setViewportAnnotationOrder();
812     }
813     else if (source == sortAnnByLabel)
814     {
815       boolean newState = sortAnnByLabel.getState();
816       sortAnnBySequence.setState(false);
817       setAnnotationSortOrder(newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE
818               : SequenceAnnotationOrder.NONE);
819       setViewportAnnotationOrder();
820     }
821     else if (source == showAutoFirst)
822     {
823       showAutoLast.setState(!showAutoFirst.getState());
824       setShowAutoCalculatedAbove(showAutoFirst.getState());
825       setViewportAnnotationOrder();
826     }
827     else if (source == showAutoLast)
828     {
829       showAutoFirst.setState(!showAutoLast.getState());
830       setShowAutoCalculatedAbove(showAutoFirst.getState());
831       setViewportAnnotationOrder();
832     }
833     else if (source == conservationMenuItem)
834     {
835       conservationMenuItem_actionPerformed();
836     }
837     else if (source == abovePIDThreshold)
838     {
839       abovePIDThreshold_actionPerformed();
840     }
841     else if (source == applyToAllGroups)
842     {
843       viewport.setColourAppliesToAllGroups(applyToAllGroups.getState());
844     }
845     else if (source == autoCalculate)
846     {
847       viewport.autoCalculateConsensus = autoCalculate.getState();
848     }
849     else if (source == sortByTree)
850     {
851       viewport.sortByTree = sortByTree.getState();
852     }
853     else if (source == this.centreColumnLabelFlag)
854     {
855       centreColumnLabelFlag_stateChanged();
856     }
857     else if (source == this.followMouseOverFlag)
858     {
859       mouseOverFlag_stateChanged();
860     }
861     else if (source == showGroupConsensus)
862     {
863       showGroupConsensus_actionPerformed();
864     }
865     else if (source == showGroupConservation)
866     {
867       showGroupConservation_actionPerformed();
868     }
869     else if (source == showSequenceLogo)
870     {
871       showSequenceLogo_actionPerformed();
872     }
873     else if (source == normSequenceLogo)
874     {
875       normSequenceLogo_actionPerformed();
876     }
877     else if (source == showConsensusHistogram)
878     {
879       showConsensusHistogram_actionPerformed();
880     }
881     else if (source == applyAutoAnnotationSettings)
882     {
883       applyAutoAnnotationSettings_actionPerformed();
884     }
885     alignPanel.paintAlignment(true);
886   }
887
888   /**
889    * Set the visibility state of sequence-related and/or alignment-related
890    * annotations depending on checkbox selections. Repaint after calling.
891    * 
892    * @param visible
893    */
894   private void setAnnotationsVisibility()
895   {
896     boolean showForAlignment = showAlignmentAnnotations.getState();
897     boolean showForSequences = showSequenceAnnotations.getState();
898     for (AlignmentAnnotation aa : alignPanel.getAlignment()
899             .getAlignmentAnnotation())
900     {
901       boolean visible = (aa.sequenceRef == null ? showForAlignment
902               : showForSequences);
903         aa.visible = visible;
904     }
905     alignPanel.validateAnnotationDimensions(false);
906   }
907
908   private void setAnnotationSortOrder(SequenceAnnotationOrder order)
909   {
910     this.annotationSortOrder = order;
911   }
912
913   /**
914    * Set flags on the viewport that control annotation ordering
915    */
916   private void setViewportAnnotationOrder()
917   {
918     this.alignPanel.av.setSortAnnotationsBy(this.annotationSortOrder);
919     this.alignPanel.av
920             .setShowAutocalculatedAbove(this.showAutoCalculatedAbove);
921   }
922
923   private void setShowAutoCalculatedAbove(boolean showAbove)
924   {
925     this.showAutoCalculatedAbove = showAbove;
926   }
927
928   private void mouseOverFlag_stateChanged()
929   {
930     viewport.setFollowHighlight(followMouseOverFlag.getState());
931     // TODO: could kick the scrollTo mechanism to reset view for current
932     // searchresults.
933   }
934
935   private void centreColumnLabelFlag_stateChanged()
936   {
937     viewport.centreColumnLabels = centreColumnLabelFlag.getState();
938     this.alignPanel.annotationPanel.repaint();
939   }
940
941   @Override
942   public void actionPerformed(ActionEvent evt)
943   {
944     Object source = evt.getSource();
945
946     if (source == inputText)
947     {
948       inputText_actionPerformed();
949     }
950     else if (source == loadTree)
951     {
952       loadTree_actionPerformed();
953     }
954     else if (source == loadApplication)
955     {
956       launchFullApplication();
957     }
958     else if (source == loadAnnotations)
959     {
960       loadAnnotations();
961     }
962     else if (source == outputAnnotations)
963     {
964       outputAnnotations(true);
965     }
966     else if (source == outputFeatures)
967     {
968       outputFeatures(true, "Jalview");
969     }
970     else if (source == closeMenuItem)
971     {
972       closeMenuItem_actionPerformed();
973     }
974     else if (source == copy)
975     {
976       copy_actionPerformed();
977     }
978     else if (source == undoMenuItem)
979     {
980       undoMenuItem_actionPerformed();
981     }
982     else if (source == redoMenuItem)
983     {
984       redoMenuItem_actionPerformed();
985     }
986     else if (source == inputText)
987     {
988       inputText_actionPerformed();
989     }
990     else if (source == closeMenuItem)
991     {
992       closeMenuItem_actionPerformed();
993     }
994     else if (source == undoMenuItem)
995     {
996       undoMenuItem_actionPerformed();
997     }
998     else if (source == redoMenuItem)
999     {
1000       redoMenuItem_actionPerformed();
1001     }
1002     else if (source == copy)
1003     {
1004       copy_actionPerformed();
1005     }
1006     else if (source == pasteNew)
1007     {
1008       pasteNew_actionPerformed();
1009     }
1010     else if (source == pasteThis)
1011     {
1012       pasteThis_actionPerformed();
1013     }
1014     else if (source == cut)
1015     {
1016       cut_actionPerformed();
1017     }
1018     else if (source == delete)
1019     {
1020       delete_actionPerformed();
1021     }
1022     else if (source == grpsFromSelection)
1023     {
1024       makeGrpsFromSelection_actionPerformed();
1025     }
1026     else if (source == deleteGroups)
1027     {
1028       deleteGroups_actionPerformed();
1029     }
1030     else if (source == selectAllSequenceMenuItem)
1031     {
1032       selectAllSequenceMenuItem_actionPerformed();
1033     }
1034     else if (source == deselectAllSequenceMenuItem)
1035     {
1036       deselectAllSequenceMenuItem_actionPerformed();
1037     }
1038     else if (source == invertSequenceMenuItem)
1039     {
1040       invertSequenceMenuItem_actionPerformed();
1041     }
1042     else if (source == invertColSel)
1043     {
1044       viewport.invertColumnSelection();
1045       alignPanel.paintAlignment(true);
1046     }
1047     else if (source == remove2LeftMenuItem)
1048     {
1049       trimAlignment(true);
1050     }
1051     else if (source == remove2RightMenuItem)
1052     {
1053       trimAlignment(false);
1054     }
1055     else if (source == removeGappedColumnMenuItem)
1056     {
1057       removeGappedColumnMenuItem_actionPerformed();
1058     }
1059     else if (source == removeAllGapsMenuItem)
1060     {
1061       removeAllGapsMenuItem_actionPerformed();
1062     }
1063     else if (source == findMenuItem)
1064     {
1065       findMenuItem_actionPerformed();
1066     }
1067     else if (source == font)
1068     {
1069       new FontChooser(alignPanel);
1070     }
1071     else if (source == newView)
1072     {
1073       newView(null);
1074     }
1075     else if (source == showColumns)
1076     {
1077       viewport.showAllHiddenColumns();
1078       alignPanel.paintAlignment(true);
1079     }
1080     else if (source == showSeqs)
1081     {
1082       viewport.showAllHiddenSeqs();
1083       alignPanel.paintAlignment(true);
1084     }
1085     else if (source == hideColumns)
1086     {
1087       viewport.hideSelectedColumns();
1088       alignPanel.paintAlignment(true);
1089     }
1090     else if (source == hideSequences
1091             && viewport.getSelectionGroup() != null)
1092     {
1093       viewport.hideAllSelectedSeqs();
1094       alignPanel.paintAlignment(true);
1095     }
1096     else if (source == hideAllButSelection)
1097     {
1098       toggleHiddenRegions(false, false);
1099       alignPanel.paintAlignment(true);
1100     }
1101     else if (source == hideAllSelection)
1102     {
1103       SequenceGroup sg = viewport.getSelectionGroup();
1104       viewport.expandColSelection(sg, false);
1105       viewport.hideAllSelectedSeqs();
1106       viewport.hideSelectedColumns();
1107       alignPanel.paintAlignment(true);
1108     }
1109     else if (source == showAllHidden)
1110     {
1111       viewport.showAllHiddenColumns();
1112       viewport.showAllHiddenSeqs();
1113       alignPanel.paintAlignment(true);
1114     }
1115     else if (source == showGroupConsensus)
1116     {
1117       showGroupConsensus_actionPerformed();
1118     }
1119     else if (source == showGroupConservation)
1120     {
1121       showGroupConservation_actionPerformed();
1122     }
1123     else if (source == showSequenceLogo)
1124     {
1125       showSequenceLogo_actionPerformed();
1126     }
1127     else if (source == normSequenceLogo)
1128     {
1129       normSequenceLogo_actionPerformed();
1130     }
1131     else if (source == showConsensusHistogram)
1132     {
1133       showConsensusHistogram_actionPerformed();
1134     }
1135     else if (source == applyAutoAnnotationSettings)
1136     {
1137       applyAutoAnnotationSettings_actionPerformed();
1138     }
1139     else if (source == featureSettings)
1140     {
1141       new FeatureSettings(alignPanel);
1142     }
1143     else if (source == alProperties)
1144     {
1145       StringBuffer contents = new jalview.io.AlignmentProperties(
1146               viewport.getAlignment()).formatAsString();
1147       CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this);
1148       cap.setText(contents.toString());
1149       Frame frame = new Frame();
1150       frame.add(cap);
1151       jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
1152               "label.alignment_properties", new String[]
1153               { getTitle() }), 400, 250);
1154     }
1155     else if (source == overviewMenuItem)
1156     {
1157       overviewMenuItem_actionPerformed();
1158     }
1159     else if (source == noColourmenuItem)
1160     {
1161       changeColour(null);
1162     }
1163     else if (source == clustalColour)
1164     {
1165       abovePIDThreshold.setState(false);
1166       changeColour(new ClustalxColourScheme(viewport.getAlignment(), null));
1167     }
1168     else if (source == zappoColour)
1169     {
1170       changeColour(new ZappoColourScheme());
1171     }
1172     else if (source == taylorColour)
1173     {
1174       changeColour(new TaylorColourScheme());
1175     }
1176     else if (source == hydrophobicityColour)
1177     {
1178       changeColour(new HydrophobicColourScheme());
1179     }
1180     else if (source == helixColour)
1181     {
1182       changeColour(new HelixColourScheme());
1183     }
1184     else if (source == strandColour)
1185     {
1186       changeColour(new StrandColourScheme());
1187     }
1188     else if (source == turnColour)
1189     {
1190       changeColour(new TurnColourScheme());
1191     }
1192     else if (source == buriedColour)
1193     {
1194       changeColour(new BuriedColourScheme());
1195     }
1196     else if (source == nucleotideColour)
1197     {
1198       changeColour(new NucleotideColourScheme());
1199     }
1200     else if (source == purinePyrimidineColour)
1201     {
1202       changeColour(new PurinePyrimidineColourScheme());
1203     }
1204     else if (source == RNAInteractionColour)
1205     {
1206       changeColour(new RNAInteractionColourScheme());
1207     }
1208     else if (source == RNAHelixColour)
1209     {
1210       new RNAHelicesColourChooser(viewport, alignPanel);
1211     }
1212     else if (source == modifyPID)
1213     {
1214       modifyPID_actionPerformed();
1215     }
1216     else if (source == modifyConservation)
1217     {
1218       modifyConservation_actionPerformed();
1219     }
1220     else if (source == userDefinedColour)
1221     {
1222       new UserDefinedColours(alignPanel, null);
1223     }
1224     else if (source == PIDColour)
1225     {
1226       changeColour(new PIDColourScheme());
1227     }
1228     else if (source == BLOSUM62Colour)
1229     {
1230       changeColour(new Blosum62ColourScheme());
1231     }
1232     else if (source == tcoffeeColour)
1233     {
1234       changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
1235     }
1236     else if (source == annotationColour)
1237     {
1238       new AnnotationColourChooser(viewport, alignPanel);
1239     }
1240     else if (source == annotationColumnSelection)
1241     {
1242       new AnnotationColumnChooser(viewport, alignPanel);
1243     }
1244     else if (source == sortPairwiseMenuItem)
1245     {
1246       sortPairwiseMenuItem_actionPerformed();
1247     }
1248     else if (source == sortIDMenuItem)
1249     {
1250       sortIDMenuItem_actionPerformed();
1251     }
1252     else if (source == sortLengthMenuItem)
1253     {
1254       sortLengthMenuItem_actionPerformed();
1255     }
1256     else if (source == sortGroupMenuItem)
1257     {
1258       sortGroupMenuItem_actionPerformed();
1259     }
1260     else if (source == removeRedundancyMenuItem)
1261     {
1262       removeRedundancyMenuItem_actionPerformed();
1263     }
1264     else if (source == pairwiseAlignmentMenuItem)
1265     {
1266       pairwiseAlignmentMenuItem_actionPerformed();
1267     }
1268     else if (source == PCAMenuItem)
1269     {
1270       PCAMenuItem_actionPerformed();
1271     }
1272     else if (source == averageDistanceTreeMenuItem)
1273     {
1274       averageDistanceTreeMenuItem_actionPerformed();
1275     }
1276     else if (source == neighbourTreeMenuItem)
1277     {
1278       neighbourTreeMenuItem_actionPerformed();
1279     }
1280     else if (source == njTreeBlosumMenuItem)
1281     {
1282       njTreeBlosumMenuItem_actionPerformed();
1283     }
1284     else if (source == avDistanceTreeBlosumMenuItem)
1285     {
1286       avTreeBlosumMenuItem_actionPerformed();
1287     }
1288     else if (source == documentation)
1289     {
1290       documentation_actionPerformed();
1291     }
1292     else if (source == about)
1293     {
1294       about_actionPerformed();
1295     }
1296
1297   }
1298
1299   public void inputText_actionPerformed()
1300   {
1301     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
1302     Frame frame = new Frame();
1303     frame.add(cap);
1304     jalview.bin.JalviewLite.addFrame(frame,
1305             MessageManager.getString("label.input_cut_paste"), 500, 500);
1306   }
1307
1308   protected void outputText_actionPerformed(ActionEvent e)
1309   {
1310     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
1311     Frame frame = new Frame();
1312     frame.add(cap);
1313     jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
1314             "label.alignment_output_command", new Object[]
1315             { e.getActionCommand() }), 600, 500);
1316     cap.setText(new AppletFormatAdapter().formatSequences(
1317             e.getActionCommand(), viewport.getAlignment(),
1318             viewport.getShowJVSuffix()));
1319   }
1320
1321   public void loadAnnotations()
1322   {
1323     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
1324     cap.setText(MessageManager
1325             .getString("label.paste_features_annotations_Tcoffee_here"));
1326     cap.setAnnotationImport();
1327     Frame frame = new Frame();
1328     frame.add(cap);
1329     jalview.bin.JalviewLite.addFrame(frame,
1330             MessageManager.getString("action.paste_annotations"), 400, 300);
1331
1332   }
1333
1334   public String outputAnnotations(boolean displayTextbox)
1335   {
1336     String annotation = new AnnotationFile()
1337             .printAnnotationsForView(viewport);
1338
1339     if (displayTextbox)
1340     {
1341       CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this);
1342       Frame frame = new Frame();
1343       frame.add(cap);
1344       jalview.bin.JalviewLite.addFrame(frame,
1345               MessageManager.getString("label.annotations"), 600, 500);
1346       cap.setText(annotation);
1347     }
1348
1349     return annotation;
1350   }
1351
1352   private Map<String,Object> getDisplayedFeatureCols()
1353   {
1354     if (alignPanel.getFeatureRenderer() != null
1355             && viewport.getFeaturesDisplayed()!= null)
1356     {
1357       return alignPanel.getFeatureRenderer().getDisplayedFeatureCols();
1358       
1359     }
1360     return null;
1361   }
1362
1363   public String outputFeatures(boolean displayTextbox, String format)
1364   {
1365     String features;
1366     if (format.equalsIgnoreCase("Jalview"))
1367     {
1368       features = new FeaturesFile().printJalviewFormat(viewport
1369               .getAlignment().getSequencesArray(),
1370               getDisplayedFeatureCols());
1371     }
1372     else
1373     {
1374       features = new FeaturesFile().printGFFFormat(viewport.getAlignment()
1375               .getSequencesArray(), getDisplayedFeatureCols());
1376     }
1377
1378     if (displayTextbox)
1379     {
1380       boolean frimport = false;
1381       if (features == null || features.equals("No Features Visible"))
1382       {
1383         features = "# No features visible - paste some and import them here.";
1384         frimport = true;
1385       }
1386
1387       CutAndPasteTransfer cap = new CutAndPasteTransfer(frimport, this);
1388       if (frimport)
1389       {
1390         cap.setAnnotationImport();
1391       }
1392       Frame frame = new Frame();
1393       frame.add(cap);
1394       jalview.bin.JalviewLite.addFrame(frame,
1395               MessageManager.getString("label.features"), 600, 500);
1396       cap.setText(features);
1397     }
1398     else
1399     {
1400       if (features == null)
1401       {
1402         features = "";
1403       }
1404     }
1405
1406     return features;
1407   }
1408
1409   void launchFullApplication()
1410   {
1411     StringBuffer url = new StringBuffer(jalviewServletURL);
1412
1413     // allow servlet parameters to be passed in applet parameter
1414     String firstSep = url.lastIndexOf("?") > url.lastIndexOf("/") ? "&"
1415             : "?";
1416     url.append(firstSep);
1417
1418     url.append("open="
1419             + appendProtocol(viewport.applet.getParameter("file")));
1420
1421     if (viewport.applet.getParameter("features") != null)
1422     {
1423       url.append("&features=");
1424       url.append(appendProtocol(viewport.applet.getParameter("features")));
1425     }
1426
1427     if (viewport.applet.getParameter("annotations") != null)
1428     {
1429       url.append("&annotations=");
1430       url.append(appendProtocol(viewport.applet.getParameter("annotations")));
1431     }
1432
1433     if (viewport.applet.getParameter("jnetfile") != null)
1434     {
1435       url.append("&annotations=");
1436       url.append(appendProtocol(viewport.applet.getParameter("jnetfile")));
1437     }
1438
1439     if (viewport.applet.getParameter("defaultColour") != null)
1440     {
1441       url.append("&colour="
1442               + removeWhiteSpace(viewport.applet
1443                       .getParameter("defaultColour")));
1444     }
1445
1446     if (viewport.applet.getParameter("userDefinedColour") != null)
1447     {
1448       url.append("&colour="
1449               + removeWhiteSpace(viewport.applet
1450                       .getParameter("userDefinedColour")));
1451     }
1452     if (viewport.applet.getParameter("tree") != null)
1453     {
1454       url.append("&tree="
1455               + appendProtocol(viewport.applet.getParameter("tree")));
1456     }
1457     if (viewport.applet.getParameter("treeFile") != null)
1458     {
1459       url.append("&tree="
1460               + appendProtocol(viewport.applet.getParameter("treeFile")));
1461     }
1462
1463     showURL(url.toString(), "FULL_APP");
1464   }
1465
1466   String removeWhiteSpace(String colour)
1467   {
1468     StringBuffer sb = new StringBuffer();
1469     for (int i = 0; i < colour.length(); i++)
1470     {
1471       if (Character.isWhitespace(colour.charAt(i)))
1472       {
1473         sb.append("%20");
1474       }
1475       else
1476       {
1477         sb.append(colour.charAt(i));
1478       }
1479     }
1480
1481     return sb.toString();
1482   }
1483
1484   String appendProtocol(String url)
1485   {
1486     try
1487     {
1488       new URL(url);
1489       url = URLEncoder.encode(url);
1490     }
1491     /*
1492      * When we finally deprecate 1.1 compatibility, we can start to use
1493      * URLEncoder.encode(url,"UTF-8") and then we'll need this catch: catch
1494      * (UnsupportedEncodingException ex) { System.err.println("WARNING -
1495      * IMPLEMENTATION ERROR - UNSUPPORTED ENCODING EXCEPTION FOR "+url);
1496      * ex.printStackTrace(); }
1497      */
1498     catch (java.net.MalformedURLException ex)
1499     {
1500       url = viewport.applet.getCodeBase() + url;
1501     }
1502     return url;
1503   }
1504
1505   public void closeMenuItem_actionPerformed()
1506   {
1507     PaintRefresher.RemoveComponent(alignPanel);
1508     if (alignPanel.seqPanel != null
1509             && alignPanel.seqPanel.seqCanvas != null)
1510     {
1511       PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
1512     }
1513     if (alignPanel.idPanel != null && alignPanel.idPanel.idCanvas != null)
1514     {
1515       PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
1516     }
1517
1518     if (PaintRefresher.components.size() == 0 && viewport.applet == null)
1519     {
1520       System.exit(0);
1521     }
1522     else
1523     {
1524     }
1525     viewport = null;
1526     alignPanel = null;
1527     this.dispose();
1528   }
1529
1530   /**
1531    * TODO: JAL-1104
1532    */
1533   void updateEditMenuBar()
1534   {
1535
1536     if (viewport.getHistoryList().size() > 0)
1537     {
1538       undoMenuItem.setEnabled(true);
1539       CommandI command = viewport.getHistoryList().peek();
1540       undoMenuItem.setLabel(MessageManager.formatMessage(
1541               "label.undo_command", new Object[]
1542               { command.getDescription() }));
1543     }
1544     else
1545     {
1546       undoMenuItem.setEnabled(false);
1547       undoMenuItem.setLabel(MessageManager.getString("action.undo"));
1548     }
1549
1550     if (viewport.getRedoList().size() > 0)
1551     {
1552       redoMenuItem.setEnabled(true);
1553
1554       CommandI command = viewport.getRedoList().peek();
1555       redoMenuItem.setLabel(MessageManager.formatMessage(
1556               "label.redo_command", new Object[]
1557               { command.getDescription() }));
1558     }
1559     else
1560     {
1561       redoMenuItem.setEnabled(false);
1562       redoMenuItem.setLabel(MessageManager.getString("action.redo"));
1563     }
1564   }
1565
1566   /**
1567    * TODO: JAL-1104
1568    */
1569   @Override
1570   public void addHistoryItem(CommandI command)
1571   {
1572     if (command.getSize() > 0)
1573     {
1574       viewport.addToHistoryList(command);
1575       viewport.clearRedoList();
1576       updateEditMenuBar();
1577       viewport.updateHiddenColumns();
1578     }
1579   }
1580
1581   /**
1582    * TODO: JAL-1104 DOCUMENT ME!
1583    * 
1584    * @param e
1585    *          DOCUMENT ME!
1586    */
1587   protected void undoMenuItem_actionPerformed()
1588   {
1589     if (viewport.getHistoryList().isEmpty())
1590     {
1591       return;
1592     }
1593
1594     CommandI command = viewport.getHistoryList().pop();
1595     viewport.addToRedoList(command);
1596     command.undoCommand(null);
1597
1598     AlignmentViewport originalSource = getOriginatingSource(command);
1599     // JBPNote Test
1600     if (originalSource != viewport)
1601     {
1602       System.err
1603               .println("Warning: Viewport object mismatch whilst undoing");
1604     }
1605     originalSource.updateHiddenColumns(); // originalSource.hasHiddenColumns =
1606                                           // viewport.getColumnSelection().getHiddenColumns()
1607                                           // != null;
1608     updateEditMenuBar();
1609     originalSource.firePropertyChange("alignment", null, originalSource
1610             .getAlignment().getSequences());
1611   }
1612
1613   /**
1614    * TODO: JAL-1104 DOCUMENT ME!
1615    * 
1616    * @param e
1617    *          DOCUMENT ME!
1618    */
1619   protected void redoMenuItem_actionPerformed()
1620   {
1621     if (viewport.getRedoList().isEmpty())
1622     {
1623       return;
1624     }
1625
1626     CommandI command = viewport.getRedoList().pop();
1627     viewport.addToHistoryList(command);
1628     command.doCommand(null);
1629
1630     AlignmentViewport originalSource = getOriginatingSource(command);
1631     // JBPNote Test
1632     if (originalSource != viewport)
1633     {
1634       System.err
1635               .println("Warning: Viewport object mismatch whilst re-doing");
1636     }
1637     originalSource.updateHiddenColumns(); // sethasHiddenColumns(); =
1638                                           // viewport.getColumnSelection().getHiddenColumns()
1639                                           // != null;
1640
1641     updateEditMenuBar();
1642     originalSource.firePropertyChange("alignment", null, originalSource
1643             .getAlignment().getSequences());
1644   }
1645
1646   AlignmentViewport getOriginatingSource(CommandI command)
1647   {
1648     AlignmentViewport originalSource = null;
1649     // For sequence removal and addition, we need to fire
1650     // the property change event FROM the viewport where the
1651     // original alignment was altered
1652     AlignmentI al = null;
1653     if (command instanceof EditCommand)
1654     {
1655       EditCommand editCommand = (EditCommand) command;
1656       al = editCommand.getAlignment();
1657       Vector comps = (Vector) PaintRefresher.components.get(viewport
1658               .getSequenceSetId());
1659       for (int i = 0; i < comps.size(); i++)
1660       {
1661         if (comps.elementAt(i) instanceof AlignmentPanel)
1662         {
1663           if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())
1664           {
1665             originalSource = ((AlignmentPanel) comps.elementAt(i)).av;
1666             break;
1667           }
1668         }
1669       }
1670     }
1671
1672     if (originalSource == null)
1673     {
1674       // The original view is closed, we must validate
1675       // the current view against the closed view first
1676       if (al != null)
1677       {
1678         PaintRefresher.validateSequences(al, viewport.getAlignment());
1679       }
1680
1681       originalSource = viewport;
1682     }
1683
1684     return originalSource;
1685   }
1686
1687   /**
1688    * Move the currently selected sequences up or down one position in the
1689    * alignment
1690    * 
1691    * @param up
1692    */
1693   public void moveSelectedSequences(boolean up)
1694   {
1695     SequenceGroup sg = viewport.getSelectionGroup();
1696     if (sg == null)
1697     {
1698       return;
1699     }
1700     viewport.getAlignment().moveSelectedSequencesByOne(sg,
1701             up ? null : viewport.getHiddenRepSequences(), up);
1702     alignPanel.paintAlignment(true);
1703
1704     /*
1705      * Also move cDNA/protein complement sequences
1706      */
1707     AlignViewportI complement = viewport.getCodingComplement();
1708     if (complement != null)
1709     {
1710       SequenceGroup mappedSelection = MappingUtils.mapSequenceGroup(sg,
1711               viewport, complement);
1712       complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
1713               up ? null : complement.getHiddenRepSequences(), up);
1714       // TODO need to trigger a repaint of the complementary panel - how?
1715       // would prefer to handle in SplitFrame but it is not overriding key
1716       // listener chiz
1717     }
1718   }
1719
1720   synchronized void slideSequences(boolean right, int size)
1721   {
1722     List<SequenceI> sg = new Vector<SequenceI>();
1723     if (viewport.cursorMode)
1724     {
1725       sg.add(viewport.getAlignment().getSequenceAt(
1726               alignPanel.seqPanel.seqCanvas.cursorY));
1727     }
1728     else if (viewport.getSelectionGroup() != null
1729             && viewport.getSelectionGroup().getSize() != viewport
1730                     .getAlignment().getHeight())
1731     {
1732       sg = viewport.getSelectionGroup().getSequences(
1733               viewport.getHiddenRepSequences());
1734     }
1735
1736     if (sg.size() < 1)
1737     {
1738       return;
1739     }
1740
1741     Vector<SequenceI> invertGroup = new Vector();
1742
1743     for (int i = 0; i < viewport.getAlignment().getHeight(); i++)
1744     {
1745       if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))
1746       {
1747         invertGroup.addElement(viewport.getAlignment().getSequenceAt(i));
1748       }
1749     }
1750
1751     SequenceI[] seqs1 = sg.toArray(new SequenceI[sg.size()]);
1752
1753     SequenceI[] seqs2 = invertGroup.toArray(new SequenceI[invertGroup
1754             .size()]);
1755     for (int i = 0; i < invertGroup.size(); i++)
1756     {
1757       seqs2[i] = invertGroup.elementAt(i);
1758     }
1759
1760     SlideSequencesCommand ssc;
1761     if (right)
1762     {
1763       ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,
1764               size, viewport.getGapCharacter());
1765     }
1766     else
1767     {
1768       ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,
1769               size, viewport.getGapCharacter());
1770     }
1771
1772     int groupAdjustment = 0;
1773     if (ssc.getGapsInsertedBegin() && right)
1774     {
1775       if (viewport.cursorMode)
1776       {
1777         alignPanel.seqPanel.moveCursor(size, 0);
1778       }
1779       else
1780       {
1781         groupAdjustment = size;
1782       }
1783     }
1784     else if (!ssc.getGapsInsertedBegin() && !right)
1785     {
1786       if (viewport.cursorMode)
1787       {
1788         alignPanel.seqPanel.moveCursor(-size, 0);
1789       }
1790       else
1791       {
1792         groupAdjustment = -size;
1793       }
1794     }
1795
1796     if (groupAdjustment != 0)
1797     {
1798       viewport.getSelectionGroup().setStartRes(
1799               viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1800       viewport.getSelectionGroup().setEndRes(
1801               viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1802     }
1803
1804     boolean appendHistoryItem = false;
1805     Deque<CommandI> historyList = viewport.getHistoryList();
1806     if (historyList != null && historyList.size() > 0
1807             && historyList.peek() instanceof SlideSequencesCommand)
1808     {
1809       appendHistoryItem = ssc
1810               .appendSlideCommand((SlideSequencesCommand) historyList
1811                       .peek());
1812     }
1813
1814     if (!appendHistoryItem)
1815     {
1816       addHistoryItem(ssc);
1817     }
1818
1819     repaint();
1820   }
1821
1822   static StringBuffer copiedSequences;
1823
1824   static Vector copiedHiddenColumns;
1825
1826   protected void copy_actionPerformed()
1827   {
1828     if (viewport.getSelectionGroup() == null)
1829     {
1830       return;
1831     }
1832
1833     SequenceGroup sg = viewport.getSelectionGroup();
1834     copiedSequences = new StringBuffer();
1835     Map<Integer, SequenceI> orderedSeqs = new HashMap<Integer, SequenceI>();
1836     for (int i = 0; i < sg.getSize(); i++)
1837     {
1838       SequenceI seq = sg.getSequenceAt(i);
1839       int index = viewport.getAlignment().findIndex(seq);
1840       orderedSeqs.put(index, seq);
1841     }
1842
1843     int index = 0, startRes, endRes;
1844     char ch;
1845
1846     if (viewport.hasHiddenColumns() && viewport.getSelectionGroup() != null)
1847     {
1848       copiedHiddenColumns = new Vector();
1849       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
1850       for (int[] region : viewport.getColumnSelection().getHiddenColumns())
1851       {
1852         copiedHiddenColumns.addElement(new int[]
1853         { region[0] - hiddenOffset, region[1] - hiddenOffset });
1854       }
1855     }
1856     else
1857     {
1858       copiedHiddenColumns = null;
1859     }
1860
1861     for (int i = 0; i < sg.getSize(); i++)
1862     {
1863       SequenceI seq = null;
1864
1865       while (seq == null)
1866       {
1867         if (orderedSeqs.containsKey(index))
1868         {
1869           seq = orderedSeqs.get(index);
1870           index++;
1871           break;
1872         }
1873         else
1874         {
1875           index++;
1876         }
1877       }
1878
1879       // FIND START RES
1880       // Returns residue following index if gap
1881       startRes = seq.findPosition(sg.getStartRes());
1882
1883       // FIND END RES
1884       // Need to find the residue preceeding index if gap
1885       endRes = 0;
1886
1887       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)
1888       {
1889         ch = seq.getCharAt(j);
1890         if (!jalview.util.Comparison.isGap((ch)))
1891         {
1892           endRes++;
1893         }
1894       }
1895
1896       if (endRes > 0)
1897       {
1898         endRes += seq.getStart() - 1;
1899       }
1900
1901       copiedSequences.append(seq.getName()
1902               + "\t"
1903               + startRes
1904               + "\t"
1905               + endRes
1906               + "\t"
1907               + seq.getSequenceAsString(sg.getStartRes(),
1908                       sg.getEndRes() + 1) + "\n");
1909     }
1910
1911   }
1912
1913   protected void pasteNew_actionPerformed()
1914   {
1915     paste(true);
1916   }
1917
1918   protected void pasteThis_actionPerformed()
1919   {
1920     paste(false);
1921   }
1922
1923   void paste(boolean newAlignment)
1924   {
1925     try
1926     {
1927
1928       if (copiedSequences == null)
1929       {
1930         return;
1931       }
1932
1933       StringTokenizer st = new StringTokenizer(copiedSequences.toString());
1934       Vector seqs = new Vector();
1935       while (st.hasMoreElements())
1936       {
1937         String name = st.nextToken();
1938         int start = Integer.parseInt(st.nextToken());
1939         int end = Integer.parseInt(st.nextToken());
1940         seqs.addElement(new Sequence(name, st.nextToken(), start, end));
1941       }
1942       SequenceI[] newSeqs = new SequenceI[seqs.size()];
1943       for (int i = 0; i < seqs.size(); i++)
1944       {
1945         newSeqs[i] = (SequenceI) seqs.elementAt(i);
1946       }
1947
1948       if (newAlignment)
1949       {
1950         String newtitle = MessageManager.getString("label.copied_sequences");
1951         if (getTitle().startsWith(MessageManager.getString("label.copied_sequences")))
1952         {
1953           newtitle = getTitle();
1954         }
1955         else
1956         {
1957           newtitle = newtitle.concat(MessageManager.formatMessage("label.from_msname", new String[]{getTitle()}));
1958         }
1959         AlignFrame af = new AlignFrame(new Alignment(newSeqs),
1960                 viewport.applet, newtitle, false);
1961         if (copiedHiddenColumns != null)
1962         {
1963           for (int i = 0; i < copiedHiddenColumns.size(); i++)
1964           {
1965             int[] region = (int[]) copiedHiddenColumns.elementAt(i);
1966             af.viewport.hideColumns(region[0], region[1]);
1967           }
1968         }
1969
1970         jalview.bin.JalviewLite.addFrame(af, newtitle, frameWidth,
1971                 frameHeight);
1972       }
1973       else
1974       {
1975         addSequences(newSeqs);
1976       }
1977
1978     } catch (Exception ex)
1979     {
1980     } // could be anything being pasted in here
1981
1982   }
1983
1984   void addSequences(SequenceI[] seqs)
1985   {
1986     for (int i = 0; i < seqs.length; i++)
1987     {
1988       viewport.getAlignment().addSequence(seqs[i]);
1989     }
1990
1991     // !newAlignment
1992     addHistoryItem(new EditCommand(
1993             MessageManager.getString("label.add_sequences"), Action.PASTE,
1994             seqs, 0, viewport.getAlignment().getWidth(),
1995             viewport.getAlignment()));
1996
1997     viewport.setEndSeq(viewport.getAlignment().getHeight());
1998     viewport.getAlignment().getWidth();
1999     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
2000             .getSequences());
2001
2002   }
2003
2004   protected void cut_actionPerformed()
2005   {
2006     copy_actionPerformed();
2007     delete_actionPerformed();
2008   }
2009
2010   protected void delete_actionPerformed()
2011   {
2012
2013     SequenceGroup sg = viewport.getSelectionGroup();
2014     if (sg == null)
2015     {
2016       return;
2017     }
2018
2019     Vector seqs = new Vector();
2020     SequenceI seq;
2021     for (int i = 0; i < sg.getSize(); i++)
2022     {
2023       seq = sg.getSequenceAt(i);
2024       seqs.addElement(seq);
2025     }
2026
2027     // If the cut affects all sequences, remove highlighted columns
2028     if (sg.getSize() == viewport.getAlignment().getHeight())
2029     {
2030       viewport.getColumnSelection().removeElements(sg.getStartRes(),
2031               sg.getEndRes() + 1);
2032     }
2033
2034     SequenceI[] cut = new SequenceI[seqs.size()];
2035     for (int i = 0; i < seqs.size(); i++)
2036     {
2037       cut[i] = (SequenceI) seqs.elementAt(i);
2038     }
2039
2040     /*
2041      * //ADD HISTORY ITEM
2042      */
2043     addHistoryItem(new EditCommand(
2044             MessageManager.getString("label.cut_sequences"), Action.CUT,
2045             cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2046             viewport.getAlignment()));
2047
2048     viewport.setSelectionGroup(null);
2049     viewport.getAlignment().deleteGroup(sg);
2050
2051     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
2052             .getSequences());
2053
2054     if (viewport.getAlignment().getHeight() < 1)
2055     {
2056       this.setVisible(false);
2057     }
2058     viewport.sendSelection();
2059   }
2060
2061   /**
2062    * group consensus toggled
2063    * 
2064    */
2065   protected void showGroupConsensus_actionPerformed()
2066   {
2067     viewport.setShowGroupConsensus(showGroupConsensus.getState());
2068     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2069
2070   }
2071
2072   /**
2073    * group conservation toggled.
2074    */
2075   protected void showGroupConservation_actionPerformed()
2076   {
2077     viewport.setShowGroupConservation(showGroupConservation.getState());
2078     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2079   }
2080
2081   /*
2082    * (non-Javadoc)
2083    * 
2084    * @see
2085    * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
2086    * .event.ActionEvent)
2087    */
2088   protected void showConsensusHistogram_actionPerformed()
2089   {
2090     viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
2091     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2092   }
2093
2094   /*
2095    * (non-Javadoc)
2096    * 
2097    * @see
2098    * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
2099    * .event.ActionEvent)
2100    */
2101   protected void showSequenceLogo_actionPerformed()
2102   {
2103     viewport.setShowSequenceLogo(showSequenceLogo.getState());
2104     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2105   }
2106
2107   protected void normSequenceLogo_actionPerformed()
2108   {
2109     showSequenceLogo.setState(true);
2110     viewport.setShowSequenceLogo(true);
2111     viewport.setNormaliseSequenceLogo(normSequenceLogo.getState());
2112     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2113   }
2114
2115   protected void applyAutoAnnotationSettings_actionPerformed()
2116   {
2117     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2118   }
2119
2120   protected void makeGrpsFromSelection_actionPerformed()
2121   {
2122     if (avc.makeGroupsFromSelection())
2123     {
2124       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2125       alignPanel.updateAnnotation();
2126       alignPanel.paintAlignment(true);
2127     }
2128   }
2129
2130   protected void createGroup_actionPerformed()
2131   {
2132     avc.createGroup();
2133   }
2134
2135   protected void unGroup_actionPerformed()
2136   {
2137     if (avc.unGroup())
2138     {
2139       alignPanel.alignmentChanged();
2140     }
2141   }
2142
2143   protected void deleteGroups_actionPerformed()
2144   {
2145     if (avc.deleteGroups())
2146     {
2147       alignPanel.alignmentChanged();
2148     }
2149   }
2150
2151   public void selectAllSequenceMenuItem_actionPerformed()
2152   {
2153     SequenceGroup sg = new SequenceGroup();
2154     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2155     {
2156       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
2157     }
2158     sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2159     viewport.setSelectionGroup(sg);
2160     alignPanel.paintAlignment(true);
2161     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2162     viewport.sendSelection();
2163   }
2164
2165   public void deselectAllSequenceMenuItem_actionPerformed()
2166   {
2167     if (viewport.cursorMode)
2168     {
2169       alignPanel.seqPanel.keyboardNo1 = null;
2170       alignPanel.seqPanel.keyboardNo2 = null;
2171     }
2172     viewport.setSelectionGroup(null);
2173     viewport.getColumnSelection().clear();
2174     viewport.setSelectionGroup(null);
2175     alignPanel.idPanel.idCanvas.searchResults = null;
2176     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
2177     alignPanel.paintAlignment(true);
2178     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2179     viewport.sendSelection();
2180   }
2181
2182   public void invertSequenceMenuItem_actionPerformed()
2183   {
2184     SequenceGroup sg = viewport.getSelectionGroup();
2185     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2186     {
2187       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2188     }
2189
2190     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2191     viewport.sendSelection();
2192   }
2193
2194   public void invertColSel_actionPerformed()
2195   {
2196     viewport.invertColumnSelection();
2197     alignPanel.paintAlignment(true);
2198     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2199     viewport.sendSelection();
2200   }
2201
2202   void trimAlignment(boolean trimLeft)
2203   {
2204     ColumnSelection colSel = viewport.getColumnSelection();
2205     int column;
2206
2207     if (colSel.size() > 0)
2208     {
2209       if (trimLeft)
2210       {
2211         column = colSel.getMin();
2212       }
2213       else
2214       {
2215         column = colSel.getMax();
2216       }
2217
2218       SequenceI[] seqs;
2219       if (viewport.getSelectionGroup() != null)
2220       {
2221         seqs = viewport.getSelectionGroup().getSequencesAsArray(
2222                 viewport.getHiddenRepSequences());
2223       }
2224       else
2225       {
2226         seqs = viewport.getAlignment().getSequencesArray();
2227       }
2228
2229       TrimRegionCommand trimRegion;
2230       if (trimLeft)
2231       {
2232         trimRegion = new TrimRegionCommand("Remove Left",
2233                 TrimRegionCommand.TRIM_LEFT, seqs, column,
2234                 viewport.getAlignment(), viewport.getColumnSelection(),
2235                 viewport.getSelectionGroup());
2236         viewport.setStartRes(0);
2237       }
2238       else
2239       {
2240         trimRegion = new TrimRegionCommand("Remove Right",
2241                 TrimRegionCommand.TRIM_RIGHT, seqs, column,
2242                 viewport.getAlignment(), viewport.getColumnSelection(),
2243                 viewport.getSelectionGroup());
2244       }
2245
2246       statusBar.setText(MessageManager.formatMessage(
2247               "label.removed_columns", new String[]
2248               { Integer.valueOf(trimRegion.getSize()).toString() }));
2249       addHistoryItem(trimRegion);
2250
2251       for (SequenceGroup sg : viewport.getAlignment().getGroups())
2252       {
2253         if ((trimLeft && !sg.adjustForRemoveLeft(column))
2254                 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2255         {
2256           viewport.getAlignment().deleteGroup(sg);
2257         }
2258       }
2259
2260       viewport.firePropertyChange("alignment", null, viewport
2261               .getAlignment().getSequences());
2262     }
2263   }
2264
2265   public void removeGappedColumnMenuItem_actionPerformed()
2266   {
2267     int start = 0, end = viewport.getAlignment().getWidth() - 1;
2268
2269     SequenceI[] seqs;
2270     if (viewport.getSelectionGroup() != null)
2271     {
2272       seqs = viewport.getSelectionGroup().getSequencesAsArray(
2273               viewport.getHiddenRepSequences());
2274       start = viewport.getSelectionGroup().getStartRes();
2275       end = viewport.getSelectionGroup().getEndRes();
2276     }
2277     else
2278     {
2279       seqs = viewport.getAlignment().getSequencesArray();
2280     }
2281
2282     RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2283             "Remove Gapped Columns", seqs, start, end,
2284             viewport.getAlignment());
2285
2286     addHistoryItem(removeGapCols);
2287
2288     statusBar.setText(MessageManager.formatMessage(
2289             "label.removed_empty_columns", new String[]
2290             { Integer.valueOf(removeGapCols.getSize()).toString() }));
2291
2292     // This is to maintain viewport position on first residue
2293     // of first sequence
2294     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2295     int startRes = seq.findPosition(viewport.startRes);
2296     // ShiftList shifts;
2297     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2298     // edit.alColumnChanges=shifts.getInverse();
2299     // if (viewport.hasHiddenColumns)
2300     // viewport.getColumnSelection().compensateForEdits(shifts);
2301     viewport.setStartRes(seq.findIndex(startRes) - 1);
2302     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
2303             .getSequences());
2304
2305   }
2306
2307   public void removeAllGapsMenuItem_actionPerformed()
2308   {
2309     int start = 0, end = viewport.getAlignment().getWidth() - 1;
2310
2311     SequenceI[] seqs;
2312     if (viewport.getSelectionGroup() != null)
2313     {
2314       seqs = viewport.getSelectionGroup().getSequencesAsArray(
2315               viewport.getHiddenRepSequences());
2316       start = viewport.getSelectionGroup().getStartRes();
2317       end = viewport.getSelectionGroup().getEndRes();
2318     }
2319     else
2320     {
2321       seqs = viewport.getAlignment().getSequencesArray();
2322     }
2323
2324     // This is to maintain viewport position on first residue
2325     // of first sequence
2326     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2327     int startRes = seq.findPosition(viewport.startRes);
2328
2329     addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2330             viewport.getAlignment()));
2331
2332     viewport.setStartRes(seq.findIndex(startRes) - 1);
2333
2334     viewport.firePropertyChange("alignment", null, viewport.getAlignment()
2335             .getSequences());
2336
2337   }
2338
2339   public void findMenuItem_actionPerformed()
2340   {
2341     new Finder(alignPanel);
2342   }
2343
2344   /**
2345    * create a new view derived from the current view
2346    * 
2347    * @param viewtitle
2348    * @return frame for the new view
2349    */
2350   public AlignFrame newView(String viewtitle)
2351   {
2352     AlignmentI newal;
2353     if (viewport.hasHiddenRows())
2354     {
2355       newal = new Alignment(viewport.getAlignment().getHiddenSequences()
2356               .getFullAlignment().getSequencesArray());
2357     }
2358     else
2359     {
2360       newal = new Alignment(viewport.getAlignment().getSequencesArray());
2361     }
2362
2363     if (viewport.getAlignment().getAlignmentAnnotation() != null)
2364     {
2365       for (int i = 0; i < viewport.getAlignment().getAlignmentAnnotation().length; i++)
2366       {
2367         if (!viewport.getAlignment().getAlignmentAnnotation()[i].autoCalculated)
2368         {
2369           newal.addAnnotation(viewport.getAlignment()
2370                   .getAlignmentAnnotation()[i]);
2371         }
2372       }
2373     }
2374
2375     AlignFrame newaf = new AlignFrame(newal, viewport.applet, "", false);
2376
2377     newaf.viewport.setSequenceSetId(alignPanel.av.getSequenceSetId());
2378     PaintRefresher.Register(alignPanel, alignPanel.av.getSequenceSetId());
2379     PaintRefresher.Register(newaf.alignPanel,
2380             newaf.alignPanel.av.getSequenceSetId());
2381
2382     PaintRefresher.Register(newaf.alignPanel.idPanel.idCanvas,
2383             newaf.alignPanel.av.getSequenceSetId());
2384     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,
2385             newaf.alignPanel.av.getSequenceSetId());
2386
2387     Vector comps = (Vector) PaintRefresher.components.get(viewport
2388             .getSequenceSetId());
2389     int viewSize = -1;
2390     for (int i = 0; i < comps.size(); i++)
2391     {
2392       if (comps.elementAt(i) instanceof AlignmentPanel)
2393       {
2394         viewSize++;
2395       }
2396     }
2397
2398     String title = new String(this.getTitle());
2399     if (viewtitle != null)
2400     {
2401       title = viewtitle + " ( " + title + ")";
2402     }
2403     else
2404     {
2405       if (title.indexOf("(View") > -1)
2406       {
2407         title = title.substring(0, title.indexOf("(View"));
2408       }
2409       title += "(View " + viewSize + ")";
2410     }
2411
2412     newaf.setTitle(title.toString());
2413
2414     newaf.viewport.setHistoryList(viewport.getHistoryList());
2415     newaf.viewport.setRedoList(viewport.getRedoList());
2416     return newaf;
2417   }
2418
2419   /**
2420    * 
2421    * @return list of feature groups on the view
2422    */
2423   public String[] getFeatureGroups()
2424   {
2425     FeatureRenderer fr = null;
2426     if (alignPanel != null
2427             && (fr = alignPanel.getFeatureRenderer()) != null)
2428     {
2429       List<String> gps = fr.getFeatureGroups();
2430       String[] _gps = gps.toArray(new String[gps.size()]);
2431       return _gps;
2432     }
2433     return null;
2434   }
2435
2436   /**
2437    * get sequence feature groups that are hidden or shown
2438    * 
2439    * @param visible
2440    *          true is visible
2441    * @return list
2442    */
2443   public String[] getFeatureGroupsOfState(boolean visible)
2444   {
2445     FeatureRenderer fr = null;
2446     if (alignPanel != null
2447             && (fr = alignPanel.getFeatureRenderer()) != null)
2448     {
2449       List<String> gps = fr.getGroups(visible);
2450       String[] _gps = gps.toArray(new String[gps.size()]);
2451       return _gps;
2452     }
2453     return null;
2454   }
2455
2456   /**
2457    * Change the display state for the given feature groups
2458    * 
2459    * @param groups
2460    *          list of group strings
2461    * @param state
2462    *          visible or invisible
2463    */
2464   public void setFeatureGroupState(String[] groups, boolean state)
2465   {
2466     FeatureRenderer fr = null;
2467     this.sequenceFeatures.setState(true);
2468     viewport.setShowSequenceFeatures(true);
2469     if (alignPanel != null
2470             && (fr = alignPanel.getFeatureRenderer()) != null)
2471     {
2472       
2473       fr.setGroupVisibility(Arrays.asList(groups), state);
2474       alignPanel.seqPanel.seqCanvas.repaint();
2475       if (alignPanel.overviewPanel != null)
2476       {
2477         alignPanel.overviewPanel.updateOverviewImage();
2478       }
2479     }
2480   }
2481
2482   public void seqLimits_itemStateChanged()
2483   {
2484     viewport.setShowJVSuffix(seqLimits.getState());
2485     alignPanel.fontChanged();
2486     alignPanel.paintAlignment(true);
2487   }
2488
2489   protected void colourTextMenuItem_actionPerformed()
2490   {
2491     viewport.setColourText(colourTextMenuItem.getState());
2492     alignPanel.paintAlignment(true);
2493   }
2494
2495   protected void displayNonconservedMenuItem_actionPerformed()
2496   {
2497     viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
2498     alignPanel.paintAlignment(true);
2499   }
2500
2501   protected void wrapMenuItem_actionPerformed()
2502   {
2503     viewport.setWrapAlignment(wrapMenuItem.getState());
2504     alignPanel.setWrapAlignment(wrapMenuItem.getState());
2505     scaleAbove.setEnabled(wrapMenuItem.getState());
2506     scaleLeft.setEnabled(wrapMenuItem.getState());
2507     scaleRight.setEnabled(wrapMenuItem.getState());
2508     alignPanel.paintAlignment(true);
2509   }
2510
2511   public void overviewMenuItem_actionPerformed()
2512   {
2513     if (alignPanel.overviewPanel != null)
2514     {
2515       return;
2516     }
2517
2518     Frame frame = new Frame();
2519     OverviewPanel overview = new OverviewPanel(alignPanel);
2520     frame.add(overview);
2521     // +50 must allow for applet frame window
2522     jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
2523             "label.overview_params", new String[]
2524             { this.getTitle() }), overview.getPreferredSize().width,
2525             overview.getPreferredSize().height + 50);
2526
2527     frame.pack();
2528     final AlignmentPanel ap = alignPanel;
2529     frame.addWindowListener(new WindowAdapter()
2530     {
2531       @Override
2532       public void windowClosing(WindowEvent e)
2533       {
2534         if (ap != null)
2535         {
2536           ap.setOverviewPanel(null);
2537         }
2538       };
2539     });
2540
2541     alignPanel.setOverviewPanel(overview);
2542
2543   }
2544
2545   public void changeColour(ColourSchemeI cs)
2546   {
2547     int threshold = 0;
2548
2549     if (cs != null)
2550     {
2551       if (viewport.getAbovePIDThreshold())
2552       {
2553         viewport.setThreshold(SliderPanel.setPIDSliderSource(alignPanel,
2554                 cs, "Background"));
2555       }
2556
2557       if (viewport.getConservationSelected())
2558       {
2559         cs.setConservationApplied(true);
2560         viewport.setIncrement(SliderPanel.setConservationSlider(alignPanel,
2561                 cs, "Background"));
2562       }
2563       else
2564       {
2565         cs.setConservationApplied(false);
2566       }
2567     }
2568     viewport.setGlobalColourScheme(cs);
2569
2570     if (alignPanel.getOverviewPanel() != null)
2571     {
2572       alignPanel.getOverviewPanel().updateOverviewImage();
2573     }
2574
2575     jalview.structure.StructureSelectionManager
2576             .getStructureSelectionManager(viewport.applet)
2577             .sequenceColoursChanged(alignPanel);
2578
2579     alignPanel.paintAlignment(true);
2580   }
2581
2582   protected void modifyPID_actionPerformed()
2583   {
2584     if (viewport.getAbovePIDThreshold()
2585             && viewport.getGlobalColourScheme() != null)
2586     {
2587       SliderPanel.setPIDSliderSource(alignPanel,
2588               viewport.getGlobalColourScheme(), "Background");
2589       SliderPanel.showPIDSlider();
2590     }
2591   }
2592
2593   protected void modifyConservation_actionPerformed()
2594   {
2595     if (viewport.getConservationSelected()
2596             && viewport.getGlobalColourScheme() != null)
2597     {
2598       SliderPanel.setConservationSlider(alignPanel,
2599               viewport.getGlobalColourScheme(), "Background");
2600       SliderPanel.showConservationSlider();
2601     }
2602   }
2603
2604   protected void conservationMenuItem_actionPerformed()
2605   {
2606     viewport.setConservationSelected(conservationMenuItem.getState());
2607
2608     viewport.setAbovePIDThreshold(false);
2609     abovePIDThreshold.setState(false);
2610
2611     changeColour(viewport.getGlobalColourScheme());
2612
2613     modifyConservation_actionPerformed();
2614   }
2615
2616   public void abovePIDThreshold_actionPerformed()
2617   {
2618     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());
2619
2620     conservationMenuItem.setState(false);
2621     viewport.setConservationSelected(false);
2622
2623     changeColour(viewport.getGlobalColourScheme());
2624
2625     modifyPID_actionPerformed();
2626   }
2627
2628   public void sortPairwiseMenuItem_actionPerformed()
2629   {
2630     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2631     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
2632             .getAlignment().getSequenceAt(0), null);
2633
2634     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2635             viewport.getAlignment()));
2636     alignPanel.paintAlignment(true);
2637   }
2638
2639   public void sortIDMenuItem_actionPerformed()
2640   {
2641     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2642     AlignmentSorter.sortByID(viewport.getAlignment());
2643     addHistoryItem(new OrderCommand("ID Sort", oldOrder,
2644             viewport.getAlignment()));
2645     alignPanel.paintAlignment(true);
2646   }
2647
2648   public void sortLengthMenuItem_actionPerformed()
2649   {
2650     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2651     AlignmentSorter.sortByLength(viewport.getAlignment());
2652     addHistoryItem(new OrderCommand("Length Sort", oldOrder,
2653             viewport.getAlignment()));
2654     alignPanel.paintAlignment(true);
2655   }
2656
2657   public void sortGroupMenuItem_actionPerformed()
2658   {
2659     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2660     AlignmentSorter.sortByGroup(viewport.getAlignment());
2661     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
2662             viewport.getAlignment()));
2663     alignPanel.paintAlignment(true);
2664
2665   }
2666
2667   public void removeRedundancyMenuItem_actionPerformed()
2668   {
2669     new RedundancyPanel(alignPanel);
2670   }
2671
2672   public void pairwiseAlignmentMenuItem_actionPerformed()
2673   {
2674     if (viewport.getSelectionGroup() != null
2675             && viewport.getSelectionGroup().getSize() > 1)
2676     {
2677       Frame frame = new Frame();
2678       frame.add(new PairwiseAlignPanel(alignPanel));
2679       jalview.bin.JalviewLite.addFrame(frame,
2680               MessageManager.getString("action.pairwise_alignment"), 600,
2681               500);
2682     }
2683   }
2684
2685   public void PCAMenuItem_actionPerformed()
2686   {
2687     // are the sequences aligned?
2688     if (!viewport.getAlignment().isAligned(false))
2689     {
2690       SequenceI current;
2691       int Width = viewport.getAlignment().getWidth();
2692
2693       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2694       {
2695         current = viewport.getAlignment().getSequenceAt(i);
2696
2697         if (current.getLength() < Width)
2698         {
2699           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2700         }
2701       }
2702       alignPanel.paintAlignment(true);
2703     }
2704
2705     if ((viewport.getSelectionGroup() != null
2706             && viewport.getSelectionGroup().getSize() < 4 && viewport
2707             .getSelectionGroup().getSize() > 0)
2708             || viewport.getAlignment().getHeight() < 4)
2709     {
2710       return;
2711     }
2712
2713     try
2714     {
2715       new PCAPanel(viewport);
2716     } catch (java.lang.OutOfMemoryError ex)
2717     {
2718     }
2719
2720   }
2721
2722   public void averageDistanceTreeMenuItem_actionPerformed()
2723   {
2724     NewTreePanel("AV", "PID", "Average distance tree using PID");
2725   }
2726
2727   public void neighbourTreeMenuItem_actionPerformed()
2728   {
2729     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2730   }
2731
2732   protected void njTreeBlosumMenuItem_actionPerformed()
2733   {
2734     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2735   }
2736
2737   protected void avTreeBlosumMenuItem_actionPerformed()
2738   {
2739     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2740   }
2741
2742   void NewTreePanel(String type, String pwType, String title)
2743   {
2744     // are the sequences aligned?
2745     if (!viewport.getAlignment().isAligned(false))
2746     {
2747       SequenceI current;
2748       int Width = viewport.getAlignment().getWidth();
2749
2750       for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2751       {
2752         current = viewport.getAlignment().getSequenceAt(i);
2753
2754         if (current.getLength() < Width)
2755         {
2756           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2757         }
2758       }
2759       alignPanel.paintAlignment(true);
2760
2761     }
2762
2763     if ((viewport.getSelectionGroup() != null && viewport
2764             .getSelectionGroup().getSize() > 1)
2765             || (viewport.getAlignment().getHeight() > 1))
2766     {
2767       final TreePanel tp = new TreePanel(alignPanel, type, pwType);
2768
2769       addTreeMenuItem(tp, title);
2770
2771       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);
2772     }
2773   }
2774
2775   void loadTree_actionPerformed()
2776   {
2777     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
2778     cap.setText(MessageManager.getString("label.paste_newick_tree_file"));
2779     cap.setTreeImport();
2780     Frame frame = new Frame();
2781     frame.add(cap);
2782     jalview.bin.JalviewLite.addFrame(frame,
2783             MessageManager.getString("label.paste_newick_file"), 400, 300);
2784   }
2785
2786   public void loadTree(jalview.io.NewickFile tree, String treeFile)
2787   {
2788     TreePanel tp = new TreePanel(alignPanel, treeFile,
2789             MessageManager.getString("label.load_tree_from_file"), tree);
2790     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);
2791     addTreeMenuItem(tp, treeFile);
2792   }
2793
2794   /**
2795    * sort the alignment using the given treePanel
2796    * 
2797    * @param treePanel
2798    *          tree used to sort view
2799    * @param title
2800    *          string used for undo event name
2801    */
2802   public void sortByTree(TreePanel treePanel, String title)
2803   {
2804     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2805     AlignmentSorter
2806             .sortByTree(viewport.getAlignment(), treePanel.getTree());
2807     // addHistoryItem(new HistoryItem("Sort", viewport.alignment,
2808     // HistoryItem.SORT));
2809     addHistoryItem(new OrderCommand(MessageManager.formatMessage(
2810             "label.order_by_params", new String[]
2811             { title }), oldOrder, viewport.getAlignment()));
2812     alignPanel.paintAlignment(true);
2813   }
2814
2815   /**
2816    * Do any automatic reordering of the alignment and add the necessary bits to
2817    * the menu structure for the new tree
2818    * 
2819    * @param treePanel
2820    * @param title
2821    */
2822   protected void addTreeMenuItem(final TreePanel treePanel,
2823           final String title)
2824   {
2825     final MenuItem item = new MenuItem(title);
2826     sortByTreeMenu.add(item);
2827     item.addActionListener(new java.awt.event.ActionListener()
2828     {
2829       @Override
2830       public void actionPerformed(ActionEvent evt)
2831       {
2832         sortByTree(treePanel, title); // treePanel.getTitle());
2833       }
2834     });
2835
2836     treePanel.addWindowListener(new WindowAdapter()
2837     {
2838       @Override
2839       public void windowOpened(WindowEvent e)
2840       {
2841         if (viewport.sortByTree)
2842         {
2843           sortByTree(treePanel, title);
2844         }
2845         super.windowOpened(e);
2846       }
2847
2848       @Override
2849       public void windowClosing(WindowEvent e)
2850       {
2851         sortByTreeMenu.remove(item);
2852       };
2853     });
2854   }
2855
2856   public boolean sortBy(AlignmentOrder alorder, String undoname)
2857   {
2858     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2859     if (viewport.applet.debug)
2860     {
2861       System.err.println("Sorting " + alorder.getOrder().size()
2862               + " in alignment '" + getTitle() + "'");
2863     }
2864     AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
2865     if (undoname != null)
2866     {
2867       addHistoryItem(new OrderCommand(undoname, oldOrder,
2868               viewport.getAlignment()));
2869     }
2870     alignPanel.paintAlignment(true);
2871     return true;
2872   }
2873
2874   protected void documentation_actionPerformed()
2875   {
2876     alignPanel.av.applet.openJalviewHelpUrl();
2877   }
2878
2879   protected void about_actionPerformed()
2880   {
2881
2882     class AboutPanel extends Canvas
2883     {
2884       String version;
2885
2886       String builddate;
2887
2888       public AboutPanel(String version, String builddate)
2889       {
2890         this.version = version;
2891         this.builddate = builddate;
2892       }
2893
2894       @Override
2895       public void paint(Graphics g)
2896       {
2897         g.setColor(Color.white);
2898         g.fillRect(0, 0, getSize().width, getSize().height);
2899         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2900         FontMetrics fm = g.getFontMetrics();
2901         int fh = fm.getHeight();
2902         int y = 5, x = 7;
2903         g.setColor(Color.black);
2904         // TODO: update this text for each release or centrally store it for
2905         // lite and application
2906         g.setFont(new Font("Helvetica", Font.BOLD, 14));
2907         g.drawString(MessageManager.formatMessage(
2908                 "label.jalviewLite_release", new String[]
2909                 { version }), x, y += fh);
2910         g.setFont(new Font("Helvetica", Font.BOLD, 12));
2911         g.drawString(MessageManager.formatMessage(
2912                 "label.jaview_build_date", new String[]
2913                 { builddate }), x, y += fh);
2914         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
2915         g.drawString(MessageManager.getString("label.jalview_authors_1"),
2916                 x, y += fh * 1.5);
2917         g.drawString(MessageManager.getString("label.jalview_authors_2"),
2918                 x + 50, y += fh + 8);
2919         g.drawString(
2920                 MessageManager.getString("label.jalview_dev_managers"), x,
2921                 y += fh);
2922         g.drawString(MessageManager
2923                 .getString("label.jalview_distribution_lists"), x, y += fh);
2924         g.drawString(MessageManager.getString("label.jalview_please_cite"),
2925                 x, y += fh + 8);
2926         g.drawString(
2927                 MessageManager.getString("label.jalview_cite_1_authors"),
2928                 x, y += fh);
2929         g.drawString(
2930                 MessageManager.getString("label.jalview_cite_1_title"), x,
2931                 y += fh);
2932         g.drawString(MessageManager.getString("label.jalview_cite_1_ref"),
2933                 x, y += fh);
2934       }
2935     }
2936
2937     Frame frame = new Frame();
2938     frame.add(new AboutPanel(JalviewLite.getVersion(), JalviewLite
2939             .getBuildDate()));
2940     jalview.bin.JalviewLite.addFrame(frame,
2941             MessageManager.getString("label.jalview"), 580, 220);
2942
2943   }
2944
2945   public void showURL(String url, String target)
2946   {
2947     if (viewport.applet == null)
2948     {
2949       System.out.println("Not running as applet - no browser available.");
2950     }
2951     else
2952     {
2953       viewport.applet.showURL(url, target);
2954     }
2955   }
2956
2957   // ////////////////////////////////////////////////////////////////////////////////
2958   // JBuilder Graphics here
2959
2960   MenuBar alignFrameMenuBar = new MenuBar();
2961
2962   Menu fileMenu = new Menu(MessageManager.getString("action.file"));
2963
2964   MenuItem loadApplication = new MenuItem(
2965           MessageManager.getString("label.view_full_application"));
2966
2967   MenuItem loadTree = new MenuItem(
2968           MessageManager.getString("label.load_associated_tree"));
2969
2970   MenuItem loadAnnotations = new MenuItem(
2971           MessageManager.getString("label.load_features_annotations"));
2972
2973   MenuItem outputFeatures = new MenuItem(
2974           MessageManager.getString("label.export_features").concat("..."));
2975
2976   MenuItem outputAnnotations = new MenuItem(
2977           MessageManager.getString("label.export_annotations").concat("..."));
2978
2979   MenuItem closeMenuItem = new MenuItem(
2980           MessageManager.getString("action.close"));
2981
2982   MenuItem selectAllSequenceMenuItem = new MenuItem(
2983           MessageManager.getString("action.select_all"));
2984
2985   MenuItem deselectAllSequenceMenuItem = new MenuItem(
2986           MessageManager.getString("action.deselect_all"));
2987
2988   MenuItem invertSequenceMenuItem = new MenuItem(
2989           MessageManager.getString("action.invert_selection"));
2990
2991   MenuItem remove2LeftMenuItem = new MenuItem();
2992
2993   MenuItem remove2RightMenuItem = new MenuItem();
2994
2995   MenuItem removeGappedColumnMenuItem = new MenuItem();
2996
2997   MenuItem removeAllGapsMenuItem = new MenuItem();
2998
2999   CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();
3000
3001   CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();
3002
3003   MenuItem sortPairwiseMenuItem = new MenuItem();
3004
3005   MenuItem sortIDMenuItem = new MenuItem();
3006
3007   MenuItem sortLengthMenuItem = new MenuItem();
3008
3009   MenuItem sortGroupMenuItem = new MenuItem();
3010
3011   MenuItem removeRedundancyMenuItem = new MenuItem();
3012
3013   MenuItem pairwiseAlignmentMenuItem = new MenuItem();
3014
3015   MenuItem PCAMenuItem = new MenuItem();
3016
3017   MenuItem averageDistanceTreeMenuItem = new MenuItem();
3018
3019   MenuItem neighbourTreeMenuItem = new MenuItem();
3020
3021   BorderLayout borderLayout1 = new BorderLayout();
3022
3023   public Label statusBar = new Label();
3024
3025   MenuItem clustalColour = new MenuItem();
3026
3027   MenuItem zappoColour = new MenuItem();
3028
3029   MenuItem taylorColour = new MenuItem();
3030
3031   MenuItem hydrophobicityColour = new MenuItem();
3032
3033   MenuItem helixColour = new MenuItem();
3034
3035   MenuItem strandColour = new MenuItem();
3036
3037   MenuItem turnColour = new MenuItem();
3038
3039   MenuItem buriedColour = new MenuItem();
3040
3041   MenuItem purinePyrimidineColour = new MenuItem();
3042
3043   MenuItem RNAInteractionColour = new MenuItem();
3044
3045   MenuItem RNAHelixColour = new MenuItem();
3046
3047   MenuItem userDefinedColour = new MenuItem();
3048
3049   MenuItem PIDColour = new MenuItem();
3050
3051   MenuItem BLOSUM62Colour = new MenuItem();
3052
3053   MenuItem tcoffeeColour = new MenuItem();
3054
3055   MenuItem njTreeBlosumMenuItem = new MenuItem();
3056
3057   MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();
3058
3059   CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();
3060
3061   CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();
3062
3063   CheckboxMenuItem displayNonconservedMenuItem = new CheckboxMenuItem();
3064
3065   MenuItem alProperties = new MenuItem(
3066           MessageManager.getString("label.alignment_props"));
3067
3068   MenuItem overviewMenuItem = new MenuItem();
3069
3070   MenuItem undoMenuItem = new MenuItem();
3071
3072   MenuItem redoMenuItem = new MenuItem();
3073
3074   CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
3075
3076   MenuItem noColourmenuItem = new MenuItem();
3077
3078   CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();
3079
3080   CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();
3081
3082   MenuItem findMenuItem = new MenuItem();
3083
3084   CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();
3085
3086   MenuItem nucleotideColour = new MenuItem();
3087
3088   MenuItem deleteGroups = new MenuItem();
3089
3090   MenuItem grpsFromSelection = new MenuItem();
3091
3092   MenuItem createGroup = new MenuItem();
3093
3094   MenuItem unGroup = new MenuItem();
3095
3096   MenuItem delete = new MenuItem();
3097
3098   MenuItem copy = new MenuItem();
3099
3100   MenuItem cut = new MenuItem();
3101
3102   Menu pasteMenu = new Menu();
3103
3104   MenuItem pasteNew = new MenuItem();
3105
3106   MenuItem pasteThis = new MenuItem();
3107
3108   CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();
3109
3110   MenuItem font = new MenuItem();
3111
3112   CheckboxMenuItem scaleAbove = new CheckboxMenuItem();
3113
3114   CheckboxMenuItem scaleLeft = new CheckboxMenuItem();
3115
3116   CheckboxMenuItem scaleRight = new CheckboxMenuItem();
3117
3118   MenuItem modifyPID = new MenuItem();
3119
3120   MenuItem modifyConservation = new MenuItem();
3121
3122   CheckboxMenuItem autoCalculate = null;
3123
3124   CheckboxMenuItem sortByTree = new CheckboxMenuItem(
3125           "Sort Alignment With New Tree", true);
3126
3127   Menu sortByTreeMenu = new Menu();
3128
3129   MenuItem inputText = new MenuItem();
3130
3131   MenuItem documentation = new MenuItem();
3132
3133   MenuItem about = new MenuItem();
3134
3135   CheckboxMenuItem seqLimits = new CheckboxMenuItem();
3136
3137   CheckboxMenuItem centreColumnLabelFlag = new CheckboxMenuItem();
3138
3139   CheckboxMenuItem followMouseOverFlag = new CheckboxMenuItem();
3140
3141   CheckboxMenuItem showSequenceLogo = new CheckboxMenuItem();
3142
3143   CheckboxMenuItem applyAutoAnnotationSettings = new CheckboxMenuItem();
3144
3145   CheckboxMenuItem showConsensusHistogram = new CheckboxMenuItem();
3146
3147   CheckboxMenuItem showGroupConsensus = new CheckboxMenuItem();
3148
3149   CheckboxMenuItem showGroupConservation = new CheckboxMenuItem();
3150
3151   CheckboxMenuItem normSequenceLogo = new CheckboxMenuItem();
3152
3153   /**
3154    * Initialise menus and other items
3155    * 
3156    * @throws Exception
3157    */
3158   private void jbInit() throws Exception
3159   {
3160     setMenuBar(alignFrameMenuBar);
3161
3162     /*
3163      * Configure File menu items and actions
3164      */
3165     inputText
3166             .setLabel(MessageManager.getString("label.input_from_textbox"));
3167     inputText.addActionListener(this);
3168     Menu outputTextboxMenu = new Menu(
3169             MessageManager.getString("label.out_to_textbox"));
3170     for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)
3171     {
3172
3173       MenuItem item = new MenuItem(
3174               jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);
3175
3176       item.addActionListener(new java.awt.event.ActionListener()
3177       {
3178         @Override
3179         public void actionPerformed(ActionEvent e)
3180         {
3181           outputText_actionPerformed(e);
3182         }
3183       });
3184
3185       outputTextboxMenu.add(item);
3186     }
3187     closeMenuItem.addActionListener(this);
3188     loadApplication.addActionListener(this);
3189     loadTree.addActionListener(this);
3190     loadAnnotations.addActionListener(this);
3191     outputFeatures.addActionListener(this);
3192     outputAnnotations.addActionListener(this);
3193
3194     /*
3195      * Configure Edit menu items and actions
3196      */
3197     undoMenuItem.setEnabled(false);
3198     undoMenuItem.setLabel(MessageManager.getString("action.undo"));
3199     undoMenuItem.addActionListener(this);
3200     redoMenuItem.setEnabled(false);
3201     redoMenuItem.setLabel(MessageManager.getString("action.redo"));
3202     redoMenuItem.addActionListener(this);
3203     copy.setLabel(MessageManager.getString("action.copy"));
3204     copy.addActionListener(this);
3205     cut.setLabel(MessageManager.getString("action.cut"));
3206     cut.addActionListener(this);
3207     delete.setLabel(MessageManager.getString("action.delete"));
3208     delete.addActionListener(this);
3209     pasteMenu.setLabel(MessageManager.getString("action.paste"));
3210     pasteNew.setLabel(MessageManager.getString("label.to_new_alignment"));
3211     pasteNew.addActionListener(this);
3212     pasteThis.setLabel(MessageManager.getString("label.to_this_alignment"));
3213     pasteThis.addActionListener(this);
3214     remove2LeftMenuItem.setLabel(MessageManager
3215             .getString("action.remove_left"));
3216     remove2LeftMenuItem.addActionListener(this);
3217     remove2RightMenuItem.setLabel(MessageManager
3218             .getString("action.remove_right"));
3219     remove2RightMenuItem.addActionListener(this);
3220     removeGappedColumnMenuItem.setLabel(MessageManager
3221             .getString("action.remove_empty_columns"));
3222     removeGappedColumnMenuItem.addActionListener(this);
3223     removeAllGapsMenuItem.setLabel(MessageManager
3224             .getString("action.remove_all_gaps"));
3225     removeAllGapsMenuItem.addActionListener(this);
3226     removeRedundancyMenuItem.setLabel(MessageManager.getString(
3227             "action.remove_redundancy").concat("..."));
3228     removeRedundancyMenuItem.addActionListener(this);
3229
3230     /*
3231      * Configure Select menu items and actions
3232      */
3233     findMenuItem.setLabel(MessageManager.getString("action.find"));
3234     findMenuItem.addActionListener(this);
3235     selectAllSequenceMenuItem.addActionListener(this);
3236     deselectAllSequenceMenuItem.addActionListener(this);
3237     invertSequenceMenuItem.setLabel(MessageManager
3238             .getString("action.invert_sequence_selection"));
3239     invertSequenceMenuItem.addActionListener(this);
3240     invertColSel.setLabel(MessageManager
3241             .getString("action.invert_column_selection"));
3242     invertColSel.addActionListener(this);
3243     deleteGroups.setLabel(MessageManager
3244             .getString("action.undefine_groups"));
3245     deleteGroups.addActionListener(this);
3246     grpsFromSelection.setLabel(MessageManager
3247             .getString("action.make_groups_selection"));
3248     grpsFromSelection.addActionListener(this);
3249     createGroup.setLabel(MessageManager.getString("action.create_group"));
3250     unGroup.setLabel(MessageManager.getString("action.remove_group"));
3251     annotationColumnSelection.setLabel("Select by Annotation");
3252     annotationColumnSelection.addActionListener(this);
3253
3254     /*
3255      * Configure View menu items and actions
3256      */
3257     newView.setLabel(MessageManager.getString("action.new_view"));
3258     newView.addActionListener(this);
3259     Menu showMenu = new Menu(MessageManager.getString("action.show"));
3260     showColumns.setLabel(MessageManager.getString("label.all_columns"));
3261     showSeqs.setLabel(MessageManager.getString("label.all_sequences"));
3262     Menu hideMenu = new Menu(MessageManager.getString("action.hide"));
3263     hideColumns
3264             .setLabel(MessageManager.getString("label.selected_columns"));
3265     hideSequences.setLabel(MessageManager
3266             .getString("label.selected_sequences"));
3267     hideAllButSelection.setLabel(MessageManager
3268             .getString("label.all_but_selected_region"));
3269     hideAllSelection.setLabel(MessageManager
3270             .getString("label.selected_region"));
3271     showAllHidden.setLabel(MessageManager
3272             .getString("label.all_sequences_columns"));
3273     showColumns.addActionListener(this);
3274     showSeqs.addActionListener(this);
3275     hideColumns.addActionListener(this);
3276     hideSequences.addActionListener(this);
3277     hideAllButSelection.addActionListener(this);
3278     hideAllSelection.addActionListener(this);
3279     showAllHidden.addActionListener(this);
3280     featureSettings.setLabel(MessageManager
3281             .getString("label.feature_settings"));
3282     featureSettings.addActionListener(this);
3283     sequenceFeatures.setLabel(MessageManager
3284             .getString("label.show_sequence_features"));
3285     sequenceFeatures.addItemListener(this);
3286     sequenceFeatures.setState(false);
3287     followMouseOverFlag.setLabel(MessageManager
3288             .getString("label.automatic_scrolling"));
3289     followMouseOverFlag.addItemListener(this);
3290     alProperties.addActionListener(this);
3291     overviewMenuItem.setLabel(MessageManager
3292             .getString("label.overview_window"));
3293     overviewMenuItem.addActionListener(this);
3294
3295     /*
3296      * Configure Annotations menu items and actions
3297      */
3298     annotationPanelMenuItem.setLabel(MessageManager
3299             .getString("label.show_annotations"));
3300     annotationPanelMenuItem.addItemListener(this);
3301     showGroupConsensus.setLabel(MessageManager
3302             .getString("label.group_consensus"));
3303     showGroupConservation.setLabel(MessageManager
3304             .getString("label.group_conservation"));
3305     showConsensusHistogram.setLabel(MessageManager
3306             .getString("label.show_consensus_histogram"));
3307     showSequenceLogo.setLabel(MessageManager
3308             .getString("label.show_consensus_logo"));
3309     normSequenceLogo.setLabel(MessageManager
3310             .getString("label.norm_consensus_logo"));
3311     applyAutoAnnotationSettings.setLabel(MessageManager
3312             .getString("label.apply_all_groups"));
3313     applyAutoAnnotationSettings.setState(true);
3314     Menu autoAnnMenu = new Menu(
3315             MessageManager.getString("label.autocalculated_annotation"));
3316     showGroupConsensus.addItemListener(this);
3317     showGroupConservation.addItemListener(this);
3318     showConsensusHistogram.addItemListener(this);
3319     showSequenceLogo.addItemListener(this);
3320     normSequenceLogo.addItemListener(this);
3321     applyAutoAnnotationSettings.addItemListener(this);
3322     showAlignmentAnnotations = new CheckboxMenuItem(
3323             MessageManager.getString("label.show_all_al_annotations"));
3324     showSequenceAnnotations = new CheckboxMenuItem(
3325             MessageManager.getString("label.show_all_seq_annotations"));
3326     sortAnnBySequence = new CheckboxMenuItem(
3327             MessageManager.getString("label.sort_annotations_by_sequence"));
3328     sortAnnByLabel = new CheckboxMenuItem(
3329             MessageManager.getString("label.sort_annotations_by_label"));
3330     showAutoFirst = new CheckboxMenuItem(
3331             MessageManager.getString("label.show_first"));
3332     showAutoLast = new CheckboxMenuItem(
3333             MessageManager.getString("label.show_last"));
3334     showAlignmentAnnotations.addItemListener(this);
3335     showSequenceAnnotations.addItemListener(this);
3336     sortAnnBySequence.addItemListener(this);
3337     sortAnnByLabel.addItemListener(this);
3338     showAutoFirst.addItemListener(this);
3339     showAutoLast.addItemListener(this);
3340
3341     /*
3342      * Configure Format menu items and actions
3343      */
3344     font.setLabel(MessageManager.getString("action.font"));
3345     font.addActionListener(this);
3346     scaleAbove.setLabel(MessageManager.getString("action.scale_above"));
3347     scaleAbove.setState(true);
3348     scaleAbove.setEnabled(false);
3349     scaleAbove.addItemListener(this);
3350     scaleLeft.setEnabled(false);
3351     scaleLeft.setState(true);
3352     scaleLeft.setLabel(MessageManager.getString("action.scale_left"));
3353     scaleLeft.addItemListener(this);
3354     scaleRight.setEnabled(false);
3355     scaleRight.setState(true);
3356     scaleRight.setLabel(MessageManager.getString("action.scale_right"));
3357     scaleRight.addItemListener(this);
3358     viewBoxesMenuItem.setLabel(MessageManager.getString("action.boxes"));
3359     viewBoxesMenuItem.setState(true);
3360     viewBoxesMenuItem.addItemListener(this);
3361     viewTextMenuItem.setLabel(MessageManager.getString("action.text"));
3362     viewTextMenuItem.setState(true);
3363     viewTextMenuItem.addItemListener(this);
3364     colourTextMenuItem.setLabel(MessageManager
3365             .getString("label.colour_text"));
3366     colourTextMenuItem.addItemListener(this);
3367     displayNonconservedMenuItem.setLabel(MessageManager
3368             .getString("label.show_non_conversed"));
3369     displayNonconservedMenuItem.addItemListener(this);
3370     wrapMenuItem.setLabel(MessageManager.getString("action.wrap"));
3371     wrapMenuItem.addItemListener(this);
3372     renderGapsMenuItem.setLabel(MessageManager
3373             .getString("action.show_gaps"));
3374     renderGapsMenuItem.setState(true);
3375     renderGapsMenuItem.addItemListener(this);
3376     centreColumnLabelFlag.setLabel(MessageManager
3377             .getString("label.centre_column_labels"));
3378     centreColumnLabelFlag.addItemListener(this);
3379     seqLimits.setState(true);
3380     seqLimits.setLabel(MessageManager
3381             .getString("label.show_sequence_limits"));
3382     seqLimits.addItemListener(this);
3383
3384     /*
3385      * Configure Colour menu items and actions
3386      */
3387     applyToAllGroups.setLabel(MessageManager
3388             .getString("label.apply_colour_to_all_groups"));
3389     applyToAllGroups.setState(true);
3390     applyToAllGroups.addItemListener(this);
3391     clustalColour.setLabel(MessageManager.getString("label.clustalx"));
3392     clustalColour.addActionListener(this);
3393     zappoColour.setLabel(MessageManager.getString("label.zappo"));
3394     zappoColour.addActionListener(this);
3395     taylorColour.setLabel(MessageManager.getString("label.taylor"));
3396     taylorColour.addActionListener(this);
3397     hydrophobicityColour.setLabel(MessageManager
3398             .getString("label.hydrophobicity"));
3399     hydrophobicityColour.addActionListener(this);
3400     helixColour
3401             .setLabel(MessageManager.getString("label.helix_propensity"));
3402     helixColour.addActionListener(this);
3403     strandColour.setLabel(MessageManager
3404             .getString("label.strand_propensity"));
3405     strandColour.addActionListener(this);
3406     turnColour.setLabel(MessageManager.getString("label.turn_propensity"));
3407     turnColour.addActionListener(this);
3408     buriedColour.setLabel(MessageManager.getString("label.buried_index"));
3409     buriedColour.addActionListener(this);
3410     purinePyrimidineColour.setLabel(MessageManager
3411             .getString("label.purine_pyrimidine"));
3412     purinePyrimidineColour.addActionListener(this);
3413     RNAInteractionColour.setLabel(MessageManager
3414             .getString("label.rna_interaction"));
3415     RNAInteractionColour.addActionListener(this);
3416     RNAHelixColour.setLabel(MessageManager
3417             .getString("action.by_rna_helixes"));
3418     RNAHelixColour.addActionListener(this);
3419     userDefinedColour.setLabel(MessageManager
3420             .getString("action.user_defined"));
3421     userDefinedColour.addActionListener(this);
3422     PIDColour.setLabel(MessageManager
3423             .getString("label.percentage_identity"));
3424     PIDColour.addActionListener(this);
3425     BLOSUM62Colour.setLabel(MessageManager
3426             .getString("label.blosum62_score"));
3427     BLOSUM62Colour.addActionListener(this);
3428     tcoffeeColour
3429             .setLabel(MessageManager.getString("label.tcoffee_scores"));
3430     // it will be enabled only if a score file is provided
3431     tcoffeeColour.setEnabled(false);
3432     tcoffeeColour.addActionListener(this);
3433     conservationMenuItem.setLabel(MessageManager
3434             .getString("action.by_conservation"));
3435     conservationMenuItem.addItemListener(this);
3436     noColourmenuItem.setLabel(MessageManager.getString("label.none"));
3437     noColourmenuItem.addActionListener(this);
3438     abovePIDThreshold.setLabel(MessageManager
3439             .getString("label.above_identity_threshold"));
3440     abovePIDThreshold.addItemListener(this);
3441     nucleotideColour.setLabel(MessageManager.getString("label.nucleotide"));
3442     nucleotideColour.addActionListener(this);
3443     modifyPID.setLabel(MessageManager
3444             .getString("label.modify_identity_thereshold"));
3445     modifyPID.addActionListener(this);
3446     modifyConservation.setLabel(MessageManager
3447             .getString("label.modify_conservation_thereshold"));
3448     modifyConservation.addActionListener(this);
3449     annotationColour.setLabel(MessageManager
3450             .getString("action.by_annotation"));
3451     annotationColour.addActionListener(this);
3452
3453     /*
3454      * Configure Calculate menu items and actions
3455      */
3456     sortPairwiseMenuItem.setLabel(MessageManager
3457             .getString("action.by_pairwise_id"));
3458     sortPairwiseMenuItem.addActionListener(this);
3459     sortIDMenuItem.setLabel(MessageManager.getString("action.by_id"));
3460     sortIDMenuItem.addActionListener(this);
3461     sortLengthMenuItem.setLabel(MessageManager
3462             .getString("action.by_length"));
3463     sortLengthMenuItem.addActionListener(this);
3464     sortGroupMenuItem.setLabel(MessageManager.getString("action.by_group"));
3465     sortGroupMenuItem.addActionListener(this);
3466     pairwiseAlignmentMenuItem.setLabel(MessageManager
3467             .getString("action.pairwise_alignment"));
3468     pairwiseAlignmentMenuItem.addActionListener(this);
3469     PCAMenuItem.setLabel(MessageManager
3470             .getString("label.principal_component_analysis"));
3471     PCAMenuItem.addActionListener(this);
3472     autoCalculate = new CheckboxMenuItem(
3473             MessageManager.getString("label.autocalculate_consensus"), true);
3474     averageDistanceTreeMenuItem.setLabel(MessageManager
3475             .getString("label.average_distance_identity"));
3476     averageDistanceTreeMenuItem.addActionListener(this);
3477     neighbourTreeMenuItem.setLabel(MessageManager
3478             .getString("label.neighbour_joining_identity"));
3479     neighbourTreeMenuItem.addActionListener(this);
3480     avDistanceTreeBlosumMenuItem.setLabel(MessageManager
3481             .getString("label.average_distance_bloslum62"));
3482     avDistanceTreeBlosumMenuItem.addActionListener(this);
3483     njTreeBlosumMenuItem.setLabel(MessageManager
3484             .getString("label.neighbour_blosum62"));
3485     njTreeBlosumMenuItem.addActionListener(this);
3486     sortByTreeMenu.setLabel(MessageManager
3487             .getString("action.by_tree_order"));
3488     Menu sortMenu = new Menu(MessageManager.getString("action.sort"));
3489     Menu calculateTreeMenu = new Menu(
3490             MessageManager.getString("action.calculate_tree"));
3491     autoCalculate.addItemListener(this);
3492     sortByTree.addItemListener(this);
3493
3494     /*
3495      * Configure Help menu items and actions
3496      */
3497     Menu helpMenu = new Menu(MessageManager.getString("action.help"));
3498     documentation.setLabel(MessageManager.getString("label.documentation"));
3499     documentation.addActionListener(this);
3500     about.setLabel(MessageManager.getString("label.about"));
3501     about.addActionListener(this);
3502
3503     /*
3504      * Add top level menus to frame
3505      */
3506     alignFrameMenuBar.add(fileMenu);
3507     Menu editMenu = new Menu(MessageManager.getString("action.edit"));
3508     alignFrameMenuBar.add(editMenu);
3509     Menu selectMenu = new Menu(MessageManager.getString("action.select"));
3510     alignFrameMenuBar.add(selectMenu);
3511     Menu viewMenu = new Menu(MessageManager.getString("action.view"));
3512     alignFrameMenuBar.add(viewMenu);
3513     Menu annotationsMenu = new Menu(
3514             MessageManager.getString("action.annotations"));
3515     alignFrameMenuBar.add(annotationsMenu);
3516     Menu formatMenu = new Menu(MessageManager.getString("action.format"));
3517     alignFrameMenuBar.add(formatMenu);
3518     Menu colourMenu = new Menu(MessageManager.getString("action.colour"));
3519     alignFrameMenuBar.add(colourMenu);
3520     Menu calculateMenu = new Menu(
3521             MessageManager.getString("action.calculate"));
3522     alignFrameMenuBar.add(calculateMenu);
3523     alignFrameMenuBar.add(helpMenu);
3524
3525     /*
3526      * File menu
3527      */
3528     fileMenu.add(inputText);
3529     fileMenu.add(loadTree);
3530     fileMenu.add(loadAnnotations);
3531     fileMenu.addSeparator();
3532     fileMenu.add(outputTextboxMenu);
3533     fileMenu.add(outputFeatures);
3534     fileMenu.add(outputAnnotations);
3535     if (jalviewServletURL != null)
3536     {
3537       fileMenu.add(loadApplication);
3538     }
3539     fileMenu.addSeparator();
3540     fileMenu.add(closeMenuItem);
3541
3542     /*
3543      * Edit menu
3544      */
3545     editMenu.add(undoMenuItem);
3546     editMenu.add(redoMenuItem);
3547     editMenu.add(cut);
3548     editMenu.add(copy);
3549     pasteMenu.add(pasteNew);
3550     pasteMenu.add(pasteThis);
3551     editMenu.add(pasteMenu);
3552     editMenu.add(delete);
3553     editMenu.addSeparator();
3554     editMenu.add(remove2LeftMenuItem);
3555     editMenu.add(remove2RightMenuItem);
3556     editMenu.add(removeGappedColumnMenuItem);
3557     editMenu.add(removeAllGapsMenuItem);
3558     editMenu.add(removeRedundancyMenuItem);
3559
3560     /*
3561      * Select menu
3562      */
3563     selectMenu.add(findMenuItem);
3564     selectMenu.addSeparator();
3565     selectMenu.add(selectAllSequenceMenuItem);
3566     selectMenu.add(deselectAllSequenceMenuItem);
3567     selectMenu.add(invertSequenceMenuItem);
3568     selectMenu.add(invertColSel);
3569     selectMenu.add(createGroup);
3570     selectMenu.add(unGroup);
3571     selectMenu.add(grpsFromSelection);
3572     selectMenu.add(deleteGroups);
3573     selectMenu.add(annotationColumnSelection);
3574
3575     /*
3576      * View menu
3577      */
3578     viewMenu.add(newView);
3579     viewMenu.addSeparator();
3580     showMenu.add(showColumns);
3581     showMenu.add(showSeqs);
3582     showMenu.add(showAllHidden);
3583     viewMenu.add(showMenu);
3584     hideMenu.add(hideColumns);
3585     hideMenu.add(hideSequences);
3586     hideMenu.add(hideAllSelection);
3587     hideMenu.add(hideAllButSelection);
3588     viewMenu.add(hideMenu);
3589     viewMenu.addSeparator();
3590     viewMenu.add(followMouseOverFlag);
3591     viewMenu.addSeparator();
3592     viewMenu.add(sequenceFeatures);
3593     viewMenu.add(featureSettings);
3594     viewMenu.addSeparator();
3595     viewMenu.add(alProperties);
3596     viewMenu.addSeparator();
3597     viewMenu.add(overviewMenuItem);
3598
3599     /*
3600      * Annotations menu
3601      */
3602     annotationsMenu.add(annotationPanelMenuItem);
3603     annotationsMenu.addSeparator();
3604     annotationsMenu.add(showAlignmentAnnotations);
3605     annotationsMenu.add(showSequenceAnnotations);
3606     annotationsMenu.add(sortAnnBySequence);
3607     annotationsMenu.add(sortAnnByLabel);
3608     annotationsMenu.addSeparator();
3609     autoAnnMenu.add(showAutoFirst);
3610     autoAnnMenu.add(showAutoLast);
3611     autoAnnMenu.addSeparator();
3612     autoAnnMenu.add(applyAutoAnnotationSettings);
3613     autoAnnMenu.add(showConsensusHistogram);
3614     autoAnnMenu.add(showSequenceLogo);
3615     autoAnnMenu.add(normSequenceLogo);
3616     autoAnnMenu.addSeparator();
3617     autoAnnMenu.add(showGroupConservation);
3618     autoAnnMenu.add(showGroupConsensus);
3619     annotationsMenu.add(autoAnnMenu);
3620
3621     /*
3622      * Format menu
3623      */
3624     formatMenu.add(font);
3625     formatMenu.add(seqLimits);
3626     formatMenu.add(wrapMenuItem);
3627     formatMenu.add(scaleAbove);
3628     formatMenu.add(scaleLeft);
3629     formatMenu.add(scaleRight);
3630     formatMenu.add(viewBoxesMenuItem);
3631     formatMenu.add(viewTextMenuItem);
3632     formatMenu.add(colourTextMenuItem);
3633     formatMenu.add(displayNonconservedMenuItem);
3634     formatMenu.add(renderGapsMenuItem);
3635     formatMenu.add(centreColumnLabelFlag);
3636
3637     /*
3638      * Colour menu
3639      */
3640     colourMenu.add(applyToAllGroups);
3641     colourMenu.addSeparator();
3642     colourMenu.add(noColourmenuItem);
3643     colourMenu.add(clustalColour);
3644     colourMenu.add(BLOSUM62Colour);
3645     colourMenu.add(PIDColour);
3646     colourMenu.add(zappoColour);
3647     colourMenu.add(taylorColour);
3648     colourMenu.add(hydrophobicityColour);
3649     colourMenu.add(helixColour);
3650     colourMenu.add(strandColour);
3651     colourMenu.add(turnColour);
3652     colourMenu.add(buriedColour);
3653     colourMenu.add(nucleotideColour);
3654     colourMenu.add(purinePyrimidineColour);
3655     // colourMenu.add(RNAInteractionColour);
3656     colourMenu.add(tcoffeeColour);
3657     colourMenu.add(userDefinedColour);
3658     colourMenu.addSeparator();
3659     colourMenu.add(conservationMenuItem);
3660     colourMenu.add(modifyConservation);
3661     colourMenu.add(abovePIDThreshold);
3662     colourMenu.add(modifyPID);
3663     colourMenu.add(annotationColour);
3664     colourMenu.add(RNAHelixColour);
3665
3666     /*
3667      * Calculate menu
3668      */
3669     sortMenu.add(sortIDMenuItem);
3670     sortMenu.add(sortLengthMenuItem);
3671     sortMenu.add(sortByTreeMenu);
3672     sortMenu.add(sortGroupMenuItem);
3673     sortMenu.add(sortPairwiseMenuItem);
3674     calculateMenu.add(sortMenu);
3675     calculateTreeMenu.add(averageDistanceTreeMenuItem);
3676     calculateTreeMenu.add(neighbourTreeMenuItem);
3677     calculateTreeMenu.add(avDistanceTreeBlosumMenuItem);
3678     calculateTreeMenu.add(njTreeBlosumMenuItem);
3679     calculateMenu.add(calculateTreeMenu);
3680     calculateMenu.addSeparator();
3681     calculateMenu.add(pairwiseAlignmentMenuItem);
3682     calculateMenu.add(PCAMenuItem);
3683     calculateMenu.add(autoCalculate);
3684     calculateMenu.add(sortByTree);
3685
3686     /*
3687      * Help menu
3688      */
3689     helpMenu.add(documentation);
3690     helpMenu.add(about);
3691
3692     /*
3693      * Status bar
3694      */
3695     statusBar.setBackground(Color.white);
3696     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
3697     statusBar.setText(MessageManager.getString("label.status_bar"));
3698     this.add(statusBar, BorderLayout.SOUTH);
3699   }
3700
3701   public void setStatus(String string)
3702   {
3703     statusBar.setText(string);
3704   };
3705
3706   MenuItem featureSettings = new MenuItem();
3707
3708   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();
3709
3710   MenuItem annotationColour = new MenuItem();
3711
3712   MenuItem annotationColumnSelection = new MenuItem();
3713
3714   MenuItem invertColSel = new MenuItem();
3715
3716   MenuItem showColumns = new MenuItem();
3717
3718   MenuItem showSeqs = new MenuItem();
3719
3720   MenuItem hideColumns = new MenuItem();
3721
3722   MenuItem hideSequences = new MenuItem();
3723
3724   MenuItem hideAllButSelection = new MenuItem();
3725
3726   MenuItem hideAllSelection = new MenuItem();
3727
3728   MenuItem showAllHidden = new MenuItem();
3729
3730   MenuItem newView = new MenuItem();
3731
3732   private CheckboxMenuItem showAlignmentAnnotations;
3733
3734   private CheckboxMenuItem showSequenceAnnotations;
3735
3736   private CheckboxMenuItem sortAnnBySequence;
3737
3738   private CheckboxMenuItem sortAnnByLabel;
3739
3740   private CheckboxMenuItem showAutoFirst;
3741
3742   private CheckboxMenuItem showAutoLast;
3743
3744   private SplitFrame splitFrame;
3745
3746   /**
3747    * Attach the alignFrame panels after embedding menus, if necessary. This used
3748    * to be called setEmbedded, but is now creates the dropdown menus in a
3749    * platform independent manner to avoid OSX/Mac menu appendage daftness.
3750    * 
3751    * @param reallyEmbedded
3752    *          true to attach the view to the applet area on the page rather than
3753    *          in a new window
3754    */
3755   public void createAlignFrameWindow(boolean reallyEmbedded)
3756   {
3757     if (reallyEmbedded)
3758     {
3759       embedAlignFrameInApplet(viewport.applet);
3760     }
3761     else
3762     {
3763       // //////
3764       // test and embed menu bar if necessary.
3765       //
3766       if (embedMenuIfNeeded(alignPanel))
3767       {
3768         /*
3769          * adjust for status bar height too. ? pointless as overridden by layout
3770          * manager
3771          */
3772         alignPanel.setSize(getSize().width,
3773                 getSize().height - statusBar.getHeight());
3774       }
3775       add(statusBar, BorderLayout.SOUTH);
3776       add(alignPanel, BorderLayout.CENTER);
3777       // and register with the applet so it can pass external API calls to us
3778       jalview.bin.JalviewLite.addFrame(this, this.getTitle(),
3779               frameWidth,
3780               frameHeight);
3781     }
3782   }
3783
3784   /**
3785    * Add the components of this AlignFrame to the applet container.
3786    * 
3787    * @param theApplet
3788    */
3789   public void embedAlignFrameInApplet(final JalviewLite theApplet)
3790   {
3791     // ////
3792     // Explicitly build the embedded menu panel for the on-page applet
3793     //
3794     // view cannot be closed if its actually on the page
3795     fileMenu.remove(closeMenuItem);
3796     fileMenu.remove(3); // Remove Separator
3797     // construct embedded menu, using default font
3798     embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, false, false);
3799     // and actually add the components to the applet area
3800     theApplet.setLayout(new BorderLayout());
3801     theApplet.add(embeddedMenu, BorderLayout.NORTH);
3802     theApplet.add(statusBar, BorderLayout.SOUTH);
3803     // TODO should size be left to the layout manager?
3804     alignPanel.setSize(theApplet.getSize().width,
3805             theApplet.getSize().height - embeddedMenu.getHeight()
3806                     - statusBar.getHeight());
3807     theApplet.add(alignPanel, BorderLayout.CENTER);
3808     final AlignFrame me = this;
3809     theApplet.addFocusListener(new FocusListener()
3810     {
3811
3812       @Override
3813       public void focusLost(FocusEvent e)
3814       {
3815         if (theApplet.currentAlignFrame == me)
3816         {
3817           theApplet.currentAlignFrame = null;
3818         }
3819       }
3820
3821       @Override
3822       public void focusGained(FocusEvent e)
3823       {
3824         theApplet.currentAlignFrame = me;
3825       }
3826     });
3827     theApplet.validate();
3828   }
3829
3830   /**
3831    * create a new binding between structures in an existing jmol viewer instance
3832    * and an alignpanel with sequences that have existing PDBFile entries. Note,
3833    * this does not open a new Jmol window, or modify the display of the
3834    * structures in the original jmol window. Note This method doesn't work
3835    * without an additional javascript library to exchange messages between the
3836    * distinct applets. See http://issues.jalview.org/browse/JAL-621
3837    * 
3838    * @param viewer
3839    *          JmolViewer instance
3840    * @param sequenceIds
3841    *          - sequence Ids to search for associations
3842    */
3843   public SequenceStructureBinding addStructureViewInstance(
3844           Object jmolviewer, String[] sequenceIds)
3845   {
3846     org.jmol.api.JmolViewer viewer = null;
3847     try
3848     {
3849       viewer = (org.jmol.api.JmolViewer) jmolviewer;
3850     } catch (ClassCastException ex)
3851     {
3852       System.err.println("Unsupported viewer object :"
3853               + jmolviewer.getClass());
3854     }
3855     if (viewer == null)
3856     {
3857       System.err.println("Can't use this object as a structure viewer:"
3858               + jmolviewer.getClass());
3859       return null;
3860     }
3861     SequenceI[] seqs = null;
3862     if (sequenceIds == null || sequenceIds.length == 0)
3863     {
3864       seqs = viewport.getAlignment().getSequencesArray();
3865     }
3866     else
3867     {
3868       Vector sqi = new Vector();
3869       AlignmentI al = viewport.getAlignment();
3870       for (int sid = 0; sid < sequenceIds.length; sid++)
3871       {
3872         SequenceI sq = al.findName(sequenceIds[sid]);
3873         if (sq != null)
3874         {
3875           sqi.addElement(sq);
3876         }
3877       }
3878       if (sqi.size() > 0)
3879       {
3880         seqs = new SequenceI[sqi.size()];
3881         for (int sid = 0, sSize = sqi.size(); sid < sSize; sid++)
3882         {
3883           seqs[sid] = (SequenceI) sqi.elementAt(sid);
3884         }
3885       }
3886       else
3887       {
3888         return null;
3889       }
3890     }
3891     AAStructureBindingModel jmv = null;
3892     // TODO: search for a jmv that involves viewer
3893     if (jmv == null)
3894     { // create a new viewer/jalview binding.
3895       jmv = new ExtJmol(viewer, alignPanel, new SequenceI[][]
3896       { seqs });
3897     }
3898     return jmv;
3899
3900   }
3901
3902   /**
3903    * bind a pdb file to a sequence in the current view
3904    * 
3905    * @param sequenceId
3906    *          - sequenceId within the dataset.
3907    * @param pdbEntryString
3908    *          - the short name for the PDB file
3909    * @param pdbFile
3910    *          - pdb file - either a URL or a valid PDB file.
3911    * @return true if binding was as success TODO: consider making an exception
3912    *         structure for indicating when PDB parsing or sequenceId location
3913    *         fails.
3914    */
3915   public boolean addPdbFile(String sequenceId, String pdbEntryString,
3916           String pdbFile)
3917   {
3918     SequenceI toaddpdb = viewport.getAlignment().findName(sequenceId);
3919     boolean needtoadd = false;
3920     if (toaddpdb != null)
3921     {
3922       Vector pdbe = toaddpdb.getPDBId();
3923       PDBEntry pdbentry = null;
3924       if (pdbe != null && pdbe.size() > 0)
3925       {
3926         for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
3927         {
3928           pdbentry = (PDBEntry) pdbe.elementAt(pe);
3929           if (!pdbentry.getId().equals(pdbEntryString)
3930                   && !pdbentry.getFile().equals(pdbFile))
3931           {
3932             pdbentry = null;
3933           }
3934           else
3935           {
3936             continue;
3937           }
3938         }
3939       }
3940       if (pdbentry == null)
3941       {
3942         pdbentry = new PDBEntry();
3943         pdbentry.setId(pdbEntryString);
3944         pdbentry.setFile(pdbFile);
3945         needtoadd = true; // add this new entry to sequence.
3946       }
3947       // resolve data source
3948       // TODO: this code should be a refactored to an io package
3949       String protocol = AppletFormatAdapter.resolveProtocol(pdbFile, "PDB");
3950       if (protocol == null)
3951       {
3952         return false;
3953       }
3954       if (needtoadd)
3955       {
3956         // make a note of the access mode and add
3957         if (pdbentry.getProperty() == null)
3958         {
3959           pdbentry.setProperty(new Hashtable());
3960         }
3961         pdbentry.getProperty().put("protocol", protocol);
3962         toaddpdb.addPDBId(pdbentry);
3963         alignPanel.getStructureSelectionManager()
3964                 .registerPDBEntry(pdbentry);
3965       }
3966     }
3967     return true;
3968   }
3969
3970   private Object[] cleanSeqChainArrays(SequenceI[] seqs, String[] chains)
3971   {
3972     if (seqs != null)
3973     {
3974       Vector sequences = new Vector();
3975       for (int i = 0; i < seqs.length; i++)
3976       {
3977         if (seqs[i] != null)
3978         {
3979           sequences.addElement(new Object[]
3980           { seqs[i], (chains != null) ? chains[i] : null });
3981         }
3982       }
3983       seqs = new SequenceI[sequences.size()];
3984       chains = new String[sequences.size()];
3985       for (int i = 0, isize = sequences.size(); i < isize; i++)
3986       {
3987         Object[] oj = (Object[]) sequences.elementAt(i);
3988
3989         seqs[i] = (SequenceI) oj[0];
3990         chains[i] = (String) oj[1];
3991       }
3992     }
3993     return new Object[]
3994     { seqs, chains };
3995
3996   }
3997
3998   public void newStructureView(JalviewLite applet, PDBEntry pdb,
3999           SequenceI[] seqs, String[] chains, String protocol)
4000   {
4001     // Scrub any null sequences from the array
4002     Object[] sqch = cleanSeqChainArrays(seqs, chains);
4003     seqs = (SequenceI[]) sqch[0];
4004     chains = (String[]) sqch[1];
4005     if (seqs == null || seqs.length == 0)
4006     {
4007       System.err
4008               .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to.");
4009     }
4010     if (protocol == null || protocol.trim().length() == 0
4011             || protocol.equals("null"))
4012     {
4013       protocol = (String) pdb.getProperty().get("protocol");
4014       if (protocol == null)
4015       {
4016         System.err.println("Couldn't work out protocol to open structure: "
4017                 + pdb.getId());
4018         return;
4019       }
4020     }
4021     if (applet.useXtrnalSviewer)
4022     {
4023       // register the association(s) and quit, don't create any windows.
4024       if (StructureSelectionManager.getStructureSelectionManager(applet)
4025               .setMapping(seqs, chains, pdb.getFile(), protocol) == null)
4026       {
4027         System.err.println("Failed to map " + pdb.getFile() + " ("
4028                 + protocol + ") to any sequences");
4029       }
4030       return;
4031     }
4032     if (applet.isAlignPdbStructures() && applet.jmolAvailable)
4033     {
4034       // can only do alignments with Jmol
4035       // find the last jmol window assigned to this alignment
4036       jalview.appletgui.AppletJmol ajm = null, tajm;
4037       Vector jmols = applet
4038               .getAppletWindow(jalview.appletgui.AppletJmol.class);
4039       for (int i = 0, iSize = jmols.size(); i < iSize; i++)
4040       {
4041         tajm = (jalview.appletgui.AppletJmol) jmols.elementAt(i);
4042         if (tajm.ap.alignFrame == this)
4043         {
4044           ajm = tajm;
4045           break;
4046         }
4047       }
4048       if (ajm != null)
4049       {
4050         System.err
4051                 .println("Incremental adding and aligning structure to existing Jmol view not yet implemented.");
4052         // try and add the pdb structure
4053         // ajm.addS
4054         ajm = null;
4055       }
4056     }
4057     // otherwise, create a new window
4058     if (applet.jmolAvailable)
4059     {
4060       new jalview.appletgui.AppletJmol(pdb, seqs, chains, alignPanel,
4061               protocol);
4062       applet.lastFrameX += 40;
4063       applet.lastFrameY += 40;
4064     }
4065     else
4066     {
4067       new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol);
4068     }
4069
4070   }
4071
4072   public void alignedStructureView(JalviewLite applet, PDBEntry[] pdb,
4073           SequenceI[][] seqs, String[][] chains, String[] protocols)
4074   {
4075     // TODO Auto-generated method stub
4076     System.err.println("Aligned Structure View: Not yet implemented.");
4077   }
4078
4079   /**
4080    * modify the current selection, providing the user has not made a selection
4081    * already.
4082    * 
4083    * @param sel
4084    *          - sequences from this alignment
4085    * @param csel
4086    *          - columns to be selected on the alignment
4087    */
4088   public void select(SequenceGroup sel, ColumnSelection csel)
4089   {
4090     alignPanel.seqPanel.selection(sel, csel, null);
4091   }
4092
4093   public void scrollTo(int row, int column)
4094   {
4095     alignPanel.seqPanel.scrollTo(row, column);
4096   }
4097
4098   public void scrollToRow(int row)
4099   {
4100     alignPanel.seqPanel.scrollToRow(row);
4101   }
4102
4103   public void scrollToColumn(int column)
4104   {
4105     alignPanel.seqPanel.scrollToColumn(column);
4106   }
4107
4108   /**
4109    * @return the alignments unique ID.
4110    */
4111   public String getSequenceSetId()
4112   {
4113     return viewport.getSequenceSetId();
4114   }
4115
4116   /**
4117    * Load the (T-Coffee) score file from the specified url
4118    * 
4119    * @param source
4120    *          File/URL/T-COFFEE score file contents
4121    * @throws IOException
4122    * @return true if alignment was annotated with data from source
4123    */
4124   public boolean loadScoreFile(String source) throws IOException
4125   {
4126
4127     TCoffeeScoreFile file = new TCoffeeScoreFile(source,
4128             AppletFormatAdapter.checkProtocol(source));
4129     if (!file.isValid())
4130     {
4131       // TODO: raise dialog for gui
4132       System.err.println("Problems parsing T-Coffee scores: "
4133               + file.getWarningMessage());
4134       System.err.println("Origin was:\n" + source);
4135       return false;
4136     }
4137
4138     /*
4139      * check that the score matrix matches the alignment dimensions
4140      */
4141     AlignmentI aln;
4142     if ((aln = viewport.getAlignment()) != null
4143             && (aln.getHeight() != file.getHeight() || aln.getWidth() != file
4144                     .getWidth()))
4145     {
4146       // TODO: raise a dialog box here rather than bomb out.
4147       System.err
4148               .println("The scores matrix does not match the alignment dimensions");
4149
4150     }
4151
4152     // TODO add parameter to indicate if matching should be done
4153     if (file.annotateAlignment(alignPanel.getAlignment(), false))
4154     {
4155       alignPanel.fontChanged();
4156       tcoffeeColour.setEnabled(true);
4157       // switch to this color
4158       changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
4159       return true;
4160     }
4161     else
4162     {
4163       System.err.println("Problems resolving T-Coffee scores:");
4164       if (file.getWarningMessage() != null)
4165       {
4166         System.err.println(file.getWarningMessage());
4167       }
4168     }
4169     return false;
4170   }
4171
4172   public SplitFrame getSplitFrame()
4173   {
4174     return this.splitFrame;
4175   }
4176
4177   public void setSplitFrame(SplitFrame sf)
4178   {
4179     this.splitFrame = sf;
4180   }
4181
4182   @Override
4183   public void setShowSeqFeatures(boolean b)
4184   {
4185     // showSeqFeatures.setSelected(b);
4186     viewport.setShowSequenceFeatures(b);
4187
4188   }
4189
4190   @Override
4191   public void setMenusForViewport()
4192   {
4193     // setMenusFromViewport(viewport);
4194
4195   }
4196 }