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