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