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