JAL-2629 add sort by evalue and bit score
[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);
1461     }
1462     else
1463     {
1464       features = formatter.printGffFormat(viewport.getAlignment()
1465               .getSequencesArray(), alignPanel.getFeatureRenderer(), true);
1466     }
1467
1468     if (displayTextbox)
1469     {
1470       boolean frimport = false;
1471       if (features == null || features.equals("No Features Visible"))
1472       {
1473         features = "# No features visible - paste some and import them here.";
1474         frimport = true;
1475       }
1476
1477       CutAndPasteTransfer cap = new CutAndPasteTransfer(frimport, this);
1478       if (frimport)
1479       {
1480         cap.setAnnotationImport();
1481       }
1482       Frame frame = new Frame();
1483       frame.add(cap);
1484       jalview.bin.JalviewLite.addFrame(frame,
1485               MessageManager.getString("label.features"), 600, 500);
1486       cap.setText(features);
1487     }
1488     else
1489     {
1490       if (features == null)
1491       {
1492         features = "";
1493       }
1494     }
1495
1496     return features;
1497   }
1498
1499   void launchFullApplication()
1500   {
1501     StringBuffer url = new StringBuffer(jalviewServletURL);
1502
1503     // allow servlet parameters to be passed in applet parameter
1504     String firstSep = url.lastIndexOf("?") > url.lastIndexOf("/") ? "&"
1505             : "?";
1506     url.append(firstSep);
1507
1508     url.append(
1509             "open=" + appendProtocol(viewport.applet.getParameter("file")));
1510
1511     if (viewport.applet.getParameter("features") != null)
1512     {
1513       url.append("&features=");
1514       url.append(appendProtocol(viewport.applet.getParameter("features")));
1515     }
1516
1517     if (viewport.applet.getParameter("annotations") != null)
1518     {
1519       url.append("&annotations=");
1520       url.append(
1521               appendProtocol(viewport.applet.getParameter("annotations")));
1522     }
1523
1524     if (viewport.applet.getParameter("jnetfile") != null
1525             || viewport.applet.getParameter("jpredfile") != null)
1526     {
1527       url.append("&annotations=");
1528       url.append(appendProtocol(
1529               viewport.applet.getParameter("jnetfile") != null
1530                       ? viewport.applet.getParameter("jnetfile")
1531                       : viewport.applet.getParameter("jpredfile")));
1532     }
1533
1534     if (viewport.applet.getParameter("defaultColour") != null)
1535     {
1536       url.append("&colour=" + removeWhiteSpace(
1537               viewport.applet.getParameter("defaultColour")));
1538     }
1539
1540     if (viewport.applet.getParameter("userDefinedColour") != null)
1541     {
1542       url.append("&colour=" + removeWhiteSpace(
1543               viewport.applet.getParameter("userDefinedColour")));
1544     }
1545     if (viewport.applet.getParameter("tree") != null)
1546     {
1547       url.append("&tree="
1548               + appendProtocol(viewport.applet.getParameter("tree")));
1549     }
1550     if (viewport.applet.getParameter("treeFile") != null)
1551     {
1552       url.append("&tree="
1553               + appendProtocol(viewport.applet.getParameter("treeFile")));
1554     }
1555
1556     showURL(url.toString(), "FULL_APP");
1557   }
1558
1559   String removeWhiteSpace(String colour)
1560   {
1561     StringBuffer sb = new StringBuffer();
1562     for (int i = 0; i < colour.length(); i++)
1563     {
1564       if (Character.isWhitespace(colour.charAt(i)))
1565       {
1566         sb.append("%20");
1567       }
1568       else
1569       {
1570         sb.append(colour.charAt(i));
1571       }
1572     }
1573
1574     return sb.toString();
1575   }
1576
1577   String appendProtocol(String url)
1578   {
1579     try
1580     {
1581       new URL(url);
1582       url = URLEncoder.encode(url, "UTF-8");
1583     }
1584     /*
1585      * When we finally deprecate 1.1 compatibility, we can start to use
1586      * URLEncoder.encode(url,"UTF-8") and then we'll need this catch: catch
1587      * (UnsupportedEncodingException ex) { System.err.println("WARNING -
1588      * IMPLEMENTATION ERROR - UNSUPPORTED ENCODING EXCEPTION FOR "+url);
1589      * ex.printStackTrace(); }
1590      */
1591     catch (java.net.MalformedURLException ex)
1592     {
1593       url = viewport.applet.getCodeBase() + url;
1594     }
1595     catch (UnsupportedEncodingException ex)
1596     {
1597       System.err.println(
1598               "WARNING = IMPLEMENTATION ERROR - UNSUPPORTED ENCODING EXCEPTION FOR "
1599                       + url);
1600       ex.printStackTrace();
1601     }
1602     return url;
1603   }
1604
1605   public void closeMenuItem_actionPerformed()
1606   {
1607     PaintRefresher.RemoveComponent(alignPanel);
1608     if (alignPanel.seqPanel != null
1609             && alignPanel.seqPanel.seqCanvas != null)
1610     {
1611       PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
1612     }
1613     if (alignPanel.idPanel != null && alignPanel.idPanel.idCanvas != null)
1614     {
1615       PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
1616     }
1617
1618     if (PaintRefresher.components.size() == 0 && viewport.applet == null)
1619     {
1620       System.exit(0);
1621     }
1622
1623     viewport = null;
1624     if (alignPanel != null && alignPanel.overviewPanel != null)
1625     {
1626       alignPanel.overviewPanel.dispose();
1627     }
1628     alignPanel = null;
1629     this.dispose();
1630   }
1631
1632   /**
1633    * TODO: JAL-1104
1634    */
1635   void updateEditMenuBar()
1636   {
1637
1638     if (viewport.getHistoryList().size() > 0)
1639     {
1640       undoMenuItem.setEnabled(true);
1641       CommandI command = viewport.getHistoryList().peek();
1642       undoMenuItem.setLabel(MessageManager
1643               .formatMessage("label.undo_command", new Object[]
1644               { command.getDescription() }));
1645     }
1646     else
1647     {
1648       undoMenuItem.setEnabled(false);
1649       undoMenuItem.setLabel(MessageManager.getString("action.undo"));
1650     }
1651
1652     if (viewport.getRedoList().size() > 0)
1653     {
1654       redoMenuItem.setEnabled(true);
1655
1656       CommandI command = viewport.getRedoList().peek();
1657       redoMenuItem.setLabel(MessageManager
1658               .formatMessage("label.redo_command", new Object[]
1659               { command.getDescription() }));
1660     }
1661     else
1662     {
1663       redoMenuItem.setEnabled(false);
1664       redoMenuItem.setLabel(MessageManager.getString("action.redo"));
1665     }
1666   }
1667
1668   /**
1669    * TODO: JAL-1104
1670    */
1671   @Override
1672   public void addHistoryItem(CommandI command)
1673   {
1674     if (command.getSize() > 0)
1675     {
1676       viewport.addToHistoryList(command);
1677       viewport.clearRedoList();
1678       updateEditMenuBar();
1679       viewport.updateHiddenColumns();
1680     }
1681   }
1682
1683   /**
1684    * TODO: JAL-1104 DOCUMENT ME!
1685    * 
1686    * @param e
1687    *          DOCUMENT ME!
1688    */
1689   protected void undoMenuItem_actionPerformed()
1690   {
1691     if (viewport.getHistoryList().isEmpty())
1692     {
1693       return;
1694     }
1695
1696     CommandI command = viewport.getHistoryList().pop();
1697     viewport.addToRedoList(command);
1698     command.undoCommand(null);
1699
1700     AlignmentViewport originalSource = getOriginatingSource(command);
1701     // JBPNote Test
1702     if (originalSource != viewport)
1703     {
1704       System.err
1705               .println("Warning: Viewport object mismatch whilst undoing");
1706     }
1707     originalSource.updateHiddenColumns(); // originalSource.hasHiddenColumns =
1708                                           // viewport.getColumnSelection().getHiddenColumns()
1709                                           // != null;
1710     updateEditMenuBar();
1711     originalSource.firePropertyChange("alignment", null,
1712             originalSource.getAlignment().getSequences());
1713   }
1714
1715   /**
1716    * TODO: JAL-1104 DOCUMENT ME!
1717    * 
1718    * @param e
1719    *          DOCUMENT ME!
1720    */
1721   protected void redoMenuItem_actionPerformed()
1722   {
1723     if (viewport.getRedoList().isEmpty())
1724     {
1725       return;
1726     }
1727
1728     CommandI command = viewport.getRedoList().pop();
1729     viewport.addToHistoryList(command);
1730     command.doCommand(null);
1731
1732     AlignmentViewport originalSource = getOriginatingSource(command);
1733     // JBPNote Test
1734     if (originalSource != viewport)
1735     {
1736       System.err
1737               .println("Warning: Viewport object mismatch whilst re-doing");
1738     }
1739     originalSource.updateHiddenColumns(); // sethasHiddenColumns(); =
1740                                           // viewport.getColumnSelection().getHiddenColumns()
1741                                           // != null;
1742
1743     updateEditMenuBar();
1744     originalSource.firePropertyChange("alignment", null,
1745             originalSource.getAlignment().getSequences());
1746   }
1747
1748   AlignmentViewport getOriginatingSource(CommandI command)
1749   {
1750     AlignmentViewport originalSource = null;
1751     // For sequence removal and addition, we need to fire
1752     // the property change event FROM the viewport where the
1753     // original alignment was altered
1754     AlignmentI al = null;
1755     if (command instanceof EditCommand)
1756     {
1757       EditCommand editCommand = (EditCommand) command;
1758       al = editCommand.getAlignment();
1759       Vector comps = PaintRefresher.components
1760               .get(viewport.getSequenceSetId());
1761       for (int i = 0; i < comps.size(); i++)
1762       {
1763         if (comps.elementAt(i) instanceof AlignmentPanel)
1764         {
1765           if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())
1766           {
1767             originalSource = ((AlignmentPanel) comps.elementAt(i)).av;
1768             break;
1769           }
1770         }
1771       }
1772     }
1773
1774     if (originalSource == null)
1775     {
1776       // The original view is closed, we must validate
1777       // the current view against the closed view first
1778       if (al != null)
1779       {
1780         PaintRefresher.validateSequences(al, viewport.getAlignment());
1781       }
1782
1783       originalSource = viewport;
1784     }
1785
1786     return originalSource;
1787   }
1788
1789   /**
1790    * Move the currently selected sequences up or down one position in the
1791    * alignment
1792    * 
1793    * @param up
1794    */
1795   public void moveSelectedSequences(boolean up)
1796   {
1797     SequenceGroup sg = viewport.getSelectionGroup();
1798     if (sg == null)
1799     {
1800       return;
1801     }
1802     viewport.getAlignment().moveSelectedSequencesByOne(sg,
1803             up ? null : viewport.getHiddenRepSequences(), up);
1804     alignPanel.paintAlignment(true, false);
1805
1806     /*
1807      * Also move cDNA/protein complement sequences
1808      */
1809     AlignViewportI complement = viewport.getCodingComplement();
1810     if (complement != null)
1811     {
1812       SequenceGroup mappedSelection = MappingUtils.mapSequenceGroup(sg,
1813               viewport, complement);
1814       complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
1815               up ? null : complement.getHiddenRepSequences(), up);
1816       getSplitFrame().getComplement(this).alignPanel.paintAlignment(true,
1817               false);
1818     }
1819   }
1820
1821   synchronized void slideSequences(boolean right, int size)
1822   {
1823     List<SequenceI> sg = new Vector<>();
1824     if (viewport.cursorMode)
1825     {
1826       sg.add(viewport.getAlignment()
1827               .getSequenceAt(alignPanel.seqPanel.seqCanvas.cursorY));
1828     }
1829     else if (viewport.getSelectionGroup() != null
1830             && viewport.getSelectionGroup().getSize() != viewport
1831                     .getAlignment().getHeight())
1832     {
1833       sg = viewport.getSelectionGroup()
1834               .getSequences(viewport.getHiddenRepSequences());
1835     }
1836
1837     if (sg.size() < 1)
1838     {
1839       return;
1840     }
1841
1842     Vector<SequenceI> invertGroup = new Vector();
1843
1844     for (int i = 0; i < viewport.getAlignment().getHeight(); i++)
1845     {
1846       if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))
1847       {
1848         invertGroup.addElement(viewport.getAlignment().getSequenceAt(i));
1849       }
1850     }
1851
1852     SequenceI[] seqs1 = sg.toArray(new SequenceI[sg.size()]);
1853
1854     SequenceI[] seqs2 = invertGroup
1855             .toArray(new SequenceI[invertGroup.size()]);
1856     for (int i = 0; i < invertGroup.size(); i++)
1857     {
1858       seqs2[i] = invertGroup.elementAt(i);
1859     }
1860
1861     SlideSequencesCommand ssc;
1862     if (right)
1863     {
1864       ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1865               viewport.getGapCharacter());
1866     }
1867     else
1868     {
1869       ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1870               viewport.getGapCharacter());
1871     }
1872
1873     int groupAdjustment = 0;
1874     if (ssc.getGapsInsertedBegin() && right)
1875     {
1876       if (viewport.cursorMode)
1877       {
1878         alignPanel.seqPanel.moveCursor(size, 0);
1879       }
1880       else
1881       {
1882         groupAdjustment = size;
1883       }
1884     }
1885     else if (!ssc.getGapsInsertedBegin() && !right)
1886     {
1887       if (viewport.cursorMode)
1888       {
1889         alignPanel.seqPanel.moveCursor(-size, 0);
1890       }
1891       else
1892       {
1893         groupAdjustment = -size;
1894       }
1895     }
1896
1897     if (groupAdjustment != 0)
1898     {
1899       viewport.getSelectionGroup().setStartRes(
1900               viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1901       viewport.getSelectionGroup().setEndRes(
1902               viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1903     }
1904
1905     boolean appendHistoryItem = false;
1906     Deque<CommandI> historyList = viewport.getHistoryList();
1907     if (historyList != null && historyList.size() > 0
1908             && historyList.peek() instanceof SlideSequencesCommand)
1909     {
1910       appendHistoryItem = ssc.appendSlideCommand(
1911               (SlideSequencesCommand) historyList.peek());
1912     }
1913
1914     if (!appendHistoryItem)
1915     {
1916       addHistoryItem(ssc);
1917     }
1918
1919     repaint();
1920   }
1921
1922   static StringBuffer copiedSequences;
1923
1924   static HiddenColumns copiedHiddenColumns;
1925
1926   protected void copy_actionPerformed()
1927   {
1928     if (viewport.getSelectionGroup() == null)
1929     {
1930       return;
1931     }
1932
1933     SequenceGroup sg = viewport.getSelectionGroup();
1934     copiedSequences = new StringBuffer();
1935     Map<Integer, SequenceI> orderedSeqs = new HashMap<>();
1936     for (int i = 0; i < sg.getSize(); i++)
1937     {
1938       SequenceI seq = sg.getSequenceAt(i);
1939       int index = viewport.getAlignment().findIndex(seq);
1940       orderedSeqs.put(index, seq);
1941     }
1942
1943     int index = 0, startRes, endRes;
1944     char ch;
1945
1946     if (viewport.hasHiddenColumns() && viewport.getSelectionGroup() != null)
1947     {
1948       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
1949       int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
1950
1951       // create new HiddenColumns object with copy of hidden regions
1952       // between startRes and endRes, offset by startRes
1953       copiedHiddenColumns = new HiddenColumns(
1954               viewport.getAlignment().getHiddenColumns(), hiddenOffset,
1955               hiddenCutoff, hiddenOffset);
1956     }
1957     else
1958     {
1959       copiedHiddenColumns = null;
1960     }
1961
1962     for (int i = 0; i < sg.getSize(); i++)
1963     {
1964       SequenceI seq = null;
1965
1966       while (seq == null)
1967       {
1968         if (orderedSeqs.containsKey(index))
1969         {
1970           seq = orderedSeqs.get(index);
1971           index++;
1972           break;
1973         }
1974         else
1975         {
1976           index++;
1977         }
1978       }
1979
1980       // FIND START RES
1981       // Returns residue following index if gap
1982       startRes = seq.findPosition(sg.getStartRes());
1983
1984       // FIND END RES
1985       // Need to find the residue preceeding index if gap
1986       endRes = 0;
1987
1988       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)
1989       {
1990         ch = seq.getCharAt(j);
1991         if (!jalview.util.Comparison.isGap((ch)))
1992         {
1993           endRes++;
1994         }
1995       }
1996
1997       if (endRes > 0)
1998       {
1999         endRes += seq.getStart() - 1;
2000       }
2001
2002       copiedSequences.append(seq.getName() + "\t" + startRes + "\t" + endRes
2003               + "\t" + seq.getSequenceAsString(sg.getStartRes(),
2004                       sg.getEndRes() + 1)
2005               + "\n");
2006     }
2007
2008   }
2009
2010   protected void pasteNew_actionPerformed()
2011   {
2012     paste(true);
2013   }
2014
2015   protected void pasteThis_actionPerformed()
2016   {
2017     paste(false);
2018   }
2019
2020   void paste(boolean newAlignment)
2021   {
2022     try
2023     {
2024       if (copiedSequences == null)
2025       {
2026         return;
2027       }
2028
2029       StringTokenizer st = new StringTokenizer(copiedSequences.toString(),
2030               "\t");
2031       Vector seqs = new Vector();
2032       while (st.hasMoreElements())
2033       {
2034         String name = st.nextToken();
2035         int start = Integer.parseInt(st.nextToken());
2036         int end = Integer.parseInt(st.nextToken());
2037         seqs.addElement(new Sequence(name, st.nextToken(), start, end));
2038       }
2039       SequenceI[] newSeqs = new SequenceI[seqs.size()];
2040       for (int i = 0; i < seqs.size(); i++)
2041       {
2042         newSeqs[i] = (SequenceI) seqs.elementAt(i);
2043       }
2044
2045       if (newAlignment)
2046       {
2047         String newtitle = MessageManager
2048                 .getString("label.copied_sequences");
2049         if (getTitle().startsWith(
2050                 MessageManager.getString("label.copied_sequences")))
2051         {
2052           newtitle = getTitle();
2053         }
2054         else
2055         {
2056           newtitle = newtitle.concat(MessageManager
2057                   .formatMessage("label.from_msname", new String[]
2058                   { getTitle() }));
2059         }
2060         AlignFrame af = new AlignFrame(new Alignment(newSeqs),
2061                 viewport.applet, newtitle, false);
2062         af.viewport.setHiddenColumns(copiedHiddenColumns);
2063
2064         jalview.bin.JalviewLite.addFrame(af, newtitle, frameWidth,
2065                 frameHeight);
2066       }
2067       else
2068       {
2069         addSequences(newSeqs);
2070       }
2071
2072     } catch (Exception ex)
2073     {
2074     } // could be anything being pasted in here
2075
2076   }
2077
2078   void addSequences(SequenceI[] seqs)
2079   {
2080     for (int i = 0; i < seqs.length; i++)
2081     {
2082       viewport.getAlignment().addSequence(seqs[i]);
2083     }
2084
2085     // !newAlignment
2086     addHistoryItem(new EditCommand(
2087             MessageManager.getString("label.add_sequences"), Action.PASTE,
2088             seqs, 0, viewport.getAlignment().getWidth(),
2089             viewport.getAlignment()));
2090
2091     viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight());
2092     viewport.getAlignment().getWidth();
2093     viewport.firePropertyChange("alignment", null,
2094             viewport.getAlignment().getSequences());
2095
2096   }
2097
2098   protected void cut_actionPerformed()
2099   {
2100     copy_actionPerformed();
2101     delete_actionPerformed();
2102   }
2103
2104   protected void delete_actionPerformed()
2105   {
2106
2107     SequenceGroup sg = viewport.getSelectionGroup();
2108     if (sg == null)
2109     {
2110       return;
2111     }
2112
2113     Vector seqs = new Vector();
2114     SequenceI seq;
2115     for (int i = 0; i < sg.getSize(); i++)
2116     {
2117       seq = sg.getSequenceAt(i);
2118       seqs.addElement(seq);
2119     }
2120
2121     /*
2122      * If the cut affects all sequences, warn, remove highlighted columns
2123      */
2124     if (sg.getSize() == viewport.getAlignment().getHeight())
2125     {
2126       boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes())
2127               + 1) == viewport.getAlignment().getWidth()) ? true : false;
2128       if (isEntireAlignWidth)
2129       {
2130         String title = MessageManager.getString("label.delete_all");
2131         Panel infoPanel = new Panel();
2132         infoPanel.setLayout(new FlowLayout());
2133         infoPanel.add(
2134                 new Label(MessageManager.getString("warn.delete_all")));
2135
2136         final JVDialog dialog = new JVDialog(this, title, true, 400, 200);
2137         dialog.setMainPanel(infoPanel);
2138         dialog.ok.setLabel(MessageManager.getString("action.ok"));
2139         dialog.cancel.setLabel(MessageManager.getString("action.cancel"));
2140         dialog.setVisible(true);
2141
2142         if (!dialog.accept)
2143         {
2144           return;
2145         }
2146       }
2147       viewport.getColumnSelection().removeElements(sg.getStartRes(),
2148               sg.getEndRes() + 1);
2149     }
2150
2151     SequenceI[] cut = new SequenceI[seqs.size()];
2152     for (int i = 0; i < seqs.size(); i++)
2153     {
2154       cut[i] = (SequenceI) seqs.elementAt(i);
2155     }
2156
2157     /*
2158      * //ADD HISTORY ITEM
2159      */
2160     addHistoryItem(new EditCommand(
2161             MessageManager.getString("label.cut_sequences"), Action.CUT,
2162             cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2163             viewport.getAlignment()));
2164
2165     viewport.setSelectionGroup(null);
2166     viewport.getAlignment().deleteGroup(sg);
2167
2168     viewport.firePropertyChange("alignment", null,
2169             viewport.getAlignment().getSequences());
2170
2171     if (viewport.getAlignment().getHeight() < 1)
2172     {
2173       this.setVisible(false);
2174     }
2175     viewport.sendSelection();
2176   }
2177
2178   /**
2179    * group consensus toggled
2180    * 
2181    */
2182   protected void showGroupConsensus_actionPerformed()
2183   {
2184     viewport.setShowGroupConsensus(showGroupConsensus.getState());
2185     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2186
2187   }
2188
2189   /**
2190    * group conservation toggled.
2191    */
2192   protected void showGroupConservation_actionPerformed()
2193   {
2194     viewport.setShowGroupConservation(showGroupConservation.getState());
2195     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2196   }
2197
2198   /*
2199    * (non-Javadoc)
2200    * 
2201    * @see
2202    * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
2203    * .event.ActionEvent)
2204    */
2205   protected void showConsensusHistogram_actionPerformed()
2206   {
2207     viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
2208     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2209   }
2210
2211   /*
2212    * (non-Javadoc)
2213    * 
2214    * @see
2215    * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
2216    * .event.ActionEvent)
2217    */
2218   protected void showSequenceLogo_actionPerformed()
2219   {
2220     viewport.setShowSequenceLogo(showSequenceLogo.getState());
2221     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2222   }
2223
2224   protected void normSequenceLogo_actionPerformed()
2225   {
2226     showSequenceLogo.setState(true);
2227     viewport.setShowSequenceLogo(true);
2228     viewport.setNormaliseSequenceLogo(normSequenceLogo.getState());
2229     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2230   }
2231
2232   protected void applyAutoAnnotationSettings_actionPerformed()
2233   {
2234     alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
2235   }
2236
2237   protected void makeGrpsFromSelection_actionPerformed()
2238   {
2239     if (avc.makeGroupsFromSelection())
2240     {
2241       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2242       alignPanel.updateAnnotation();
2243       alignPanel.paintAlignment(true, true);
2244     }
2245   }
2246
2247   protected void createGroup_actionPerformed()
2248   {
2249     avc.createGroup();
2250   }
2251
2252   protected void unGroup_actionPerformed()
2253   {
2254     if (avc.unGroup())
2255     {
2256       alignPanel.alignmentChanged();
2257     }
2258   }
2259
2260   protected void deleteGroups_actionPerformed()
2261   {
2262     if (avc.deleteGroups())
2263     {
2264       alignPanel.alignmentChanged();
2265     }
2266   }
2267
2268   public void selectAllSequenceMenuItem_actionPerformed()
2269   {
2270     SequenceGroup sg = new SequenceGroup();
2271     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2272     {
2273       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
2274     }
2275     sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2276     viewport.setSelectionGroup(sg);
2277     // JAL-2034 - should delegate to
2278     // alignPanel to decide if overview needs
2279     // updating.
2280     alignPanel.paintAlignment(false, false);
2281     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2282     viewport.sendSelection();
2283   }
2284
2285   public void deselectAllSequenceMenuItem_actionPerformed()
2286   {
2287     if (viewport.cursorMode)
2288     {
2289       alignPanel.seqPanel.keyboardNo1 = null;
2290       alignPanel.seqPanel.keyboardNo2 = null;
2291     }
2292     viewport.setSelectionGroup(null);
2293     viewport.getColumnSelection().clear();
2294     viewport.setSelectionGroup(null);
2295     alignPanel.idPanel.idCanvas.searchResults = null;
2296     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
2297     // JAL-2034 - should delegate to
2298     // alignPanel to decide if overview needs
2299     // updating.
2300     alignPanel.paintAlignment(false, false);
2301     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2302     viewport.sendSelection();
2303   }
2304
2305   public void invertSequenceMenuItem_actionPerformed()
2306   {
2307     SequenceGroup sg = viewport.getSelectionGroup();
2308     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2309     {
2310       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2311     }
2312
2313     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2314     viewport.sendSelection();
2315   }
2316
2317   public void invertColSel_actionPerformed()
2318   {
2319     viewport.invertColumnSelection();
2320     alignPanel.paintAlignment(true, false);
2321     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2322     viewport.sendSelection();
2323   }
2324
2325   void trimAlignment(boolean trimLeft)
2326   {
2327     AlignmentI al = viewport.getAlignment();
2328     ViewportRanges ranges = viewport.getRanges();
2329     ColumnSelection colSel = viewport.getColumnSelection();
2330     int column;
2331
2332     if (!colSel.isEmpty())
2333     {
2334       if (trimLeft)
2335       {
2336         column = colSel.getMin();
2337       }
2338       else
2339       {
2340         column = colSel.getMax();
2341       }
2342
2343       SequenceI[] seqs;
2344       if (viewport.getSelectionGroup() != null)
2345       {
2346         seqs = viewport.getSelectionGroup()
2347                 .getSequencesAsArray(viewport.getHiddenRepSequences());
2348       }
2349       else
2350       {
2351         seqs = al.getSequencesArray();
2352       }
2353
2354       TrimRegionCommand trimRegion;
2355       if (trimLeft)
2356       {
2357         trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2358                 column, al);
2359         ranges.setStartRes(0);
2360       }
2361       else
2362       {
2363         trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2364                 column, al);
2365       }
2366
2367       statusBar.setText(MessageManager
2368               .formatMessage("label.removed_columns", new String[]
2369               { Integer.valueOf(trimRegion.getSize()).toString() }));
2370       addHistoryItem(trimRegion);
2371
2372       for (SequenceGroup sg : al.getGroups())
2373       {
2374         if ((trimLeft && !sg.adjustForRemoveLeft(column))
2375                 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2376         {
2377           al.deleteGroup(sg);
2378         }
2379       }
2380
2381       viewport.firePropertyChange("alignment", null, al.getSequences());
2382     }
2383   }
2384
2385   public void removeGappedColumnMenuItem_actionPerformed()
2386   {
2387     AlignmentI al = viewport.getAlignment();
2388     ViewportRanges ranges = viewport.getRanges();
2389     int start = 0;
2390     int end = ranges.getAbsoluteAlignmentWidth() - 1;
2391
2392     SequenceI[] seqs;
2393     if (viewport.getSelectionGroup() != null)
2394     {
2395       seqs = viewport.getSelectionGroup()
2396               .getSequencesAsArray(viewport.getHiddenRepSequences());
2397       start = viewport.getSelectionGroup().getStartRes();
2398       end = viewport.getSelectionGroup().getEndRes();
2399     }
2400     else
2401     {
2402       seqs = viewport.getAlignment().getSequencesArray();
2403     }
2404
2405     RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2406             "Remove Gapped Columns", seqs, start, end,
2407             viewport.getAlignment());
2408
2409     addHistoryItem(removeGapCols);
2410
2411     statusBar.setText(MessageManager
2412             .formatMessage("label.removed_empty_columns", new String[]
2413             { Integer.valueOf(removeGapCols.getSize()).toString() }));
2414
2415     // This is to maintain viewport position on first residue
2416     // of first sequence
2417     SequenceI seq = al.getSequenceAt(0);
2418     int startRes = seq.findPosition(ranges.getStartRes());
2419     // ShiftList shifts;
2420     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2421     // edit.alColumnChanges=shifts.getInverse();
2422     // if (viewport.hasHiddenColumns)
2423     // viewport.getColumnSelection().compensateForEdits(shifts);
2424     ranges.setStartRes(seq.findIndex(startRes) - 1);
2425     viewport.firePropertyChange("alignment", null, al.getSequences());
2426
2427   }
2428
2429   public void removeAllGapsMenuItem_actionPerformed()
2430   {
2431     AlignmentI al = viewport.getAlignment();
2432     ViewportRanges ranges = viewport.getRanges();
2433     int start = 0;
2434     int end = ranges.getAbsoluteAlignmentWidth() - 1;
2435
2436     SequenceI[] seqs;
2437     if (viewport.getSelectionGroup() != null)
2438     {
2439       seqs = viewport.getSelectionGroup()
2440               .getSequencesAsArray(viewport.getHiddenRepSequences());
2441       start = viewport.getSelectionGroup().getStartRes();
2442       end = viewport.getSelectionGroup().getEndRes();
2443     }
2444     else
2445     {
2446       seqs = viewport.getAlignment().getSequencesArray();
2447     }
2448
2449     // This is to maintain viewport position on first residue
2450     // of first sequence
2451     SequenceI seq = al.getSequenceAt(0);
2452     int startRes = seq.findPosition(ranges.getStartRes());
2453
2454     addHistoryItem(
2455             new RemoveGapsCommand("Remove Gaps", seqs, start, end, al));
2456
2457     ranges.setStartRes(seq.findIndex(startRes) - 1);
2458
2459     viewport.firePropertyChange("alignment", null, al.getSequences());
2460
2461   }
2462
2463   public void findMenuItem_actionPerformed()
2464   {
2465     new Finder(alignPanel);
2466   }
2467
2468   /**
2469    * create a new view derived from the current view
2470    * 
2471    * @param viewtitle
2472    * @return frame for the new view
2473    */
2474   public AlignFrame newView(String viewtitle)
2475   {
2476     AlignmentI newal;
2477     if (viewport.hasHiddenRows())
2478     {
2479       newal = new Alignment(viewport.getAlignment().getHiddenSequences()
2480               .getFullAlignment().getSequencesArray());
2481     }
2482     else
2483     {
2484       newal = new Alignment(viewport.getAlignment().getSequencesArray());
2485     }
2486
2487     if (viewport.getAlignment().getAlignmentAnnotation() != null)
2488     {
2489       for (int i = 0; i < viewport.getAlignment()
2490               .getAlignmentAnnotation().length; i++)
2491       {
2492         if (!viewport.getAlignment()
2493                 .getAlignmentAnnotation()[i].autoCalculated)
2494         {
2495           newal.addAnnotation(
2496                   viewport.getAlignment().getAlignmentAnnotation()[i]);
2497         }
2498       }
2499     }
2500
2501     AlignFrame newaf = new AlignFrame(newal, viewport.applet, "", false);
2502
2503     newaf.viewport.setSequenceSetId(alignPanel.av.getSequenceSetId());
2504     PaintRefresher.Register(alignPanel, alignPanel.av.getSequenceSetId());
2505     PaintRefresher.Register(newaf.alignPanel,
2506             newaf.alignPanel.av.getSequenceSetId());
2507
2508     PaintRefresher.Register(newaf.alignPanel.idPanel.idCanvas,
2509             newaf.alignPanel.av.getSequenceSetId());
2510     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,
2511             newaf.alignPanel.av.getSequenceSetId());
2512
2513     Vector comps = PaintRefresher.components
2514             .get(viewport.getSequenceSetId());
2515     int viewSize = -1;
2516     for (int i = 0; i < comps.size(); i++)
2517     {
2518       if (comps.elementAt(i) instanceof AlignmentPanel)
2519       {
2520         viewSize++;
2521       }
2522     }
2523
2524     String title = new String(this.getTitle());
2525     if (viewtitle != null)
2526     {
2527       title = viewtitle + " ( " + title + ")";
2528     }
2529     else
2530     {
2531       if (title.indexOf("(View") > -1)
2532       {
2533         title = title.substring(0, title.indexOf("(View"));
2534       }
2535       title += "(View " + viewSize + ")";
2536     }
2537
2538     newaf.setTitle(title.toString());
2539
2540     newaf.viewport.setHistoryList(viewport.getHistoryList());
2541     newaf.viewport.setRedoList(viewport.getRedoList());
2542     return newaf;
2543   }
2544
2545   /**
2546    * 
2547    * @return list of feature groups on the view
2548    */
2549   public String[] getFeatureGroups()
2550   {
2551     FeatureRenderer fr = null;
2552     if (alignPanel != null
2553             && (fr = alignPanel.getFeatureRenderer()) != null)
2554     {
2555       List<String> gps = fr.getFeatureGroups();
2556       String[] _gps = gps.toArray(new String[gps.size()]);
2557       return _gps;
2558     }
2559     return null;
2560   }
2561
2562   /**
2563    * get sequence feature groups that are hidden or shown
2564    * 
2565    * @param visible
2566    *          true is visible
2567    * @return list
2568    */
2569   public String[] getFeatureGroupsOfState(boolean visible)
2570   {
2571     FeatureRenderer fr = null;
2572     if (alignPanel != null
2573             && (fr = alignPanel.getFeatureRenderer()) != null)
2574     {
2575       List<String> gps = fr.getGroups(visible);
2576       String[] _gps = gps.toArray(new String[gps.size()]);
2577       return _gps;
2578     }
2579     return null;
2580   }
2581
2582   /**
2583    * Change the display state for the given feature groups
2584    * 
2585    * @param groups
2586    *          list of group strings
2587    * @param state
2588    *          visible or invisible
2589    */
2590   public void setFeatureGroupState(String[] groups, boolean state)
2591   {
2592     FeatureRenderer fr = null;
2593     this.sequenceFeatures.setState(true);
2594     viewport.setShowSequenceFeatures(true);
2595     if (alignPanel != null
2596             && (fr = alignPanel.getFeatureRenderer()) != null)
2597     {
2598
2599       fr.setGroupVisibility(Arrays.asList(groups), state);
2600       alignPanel.seqPanel.seqCanvas.repaint();
2601       if (alignPanel.overviewPanel != null)
2602       {
2603         alignPanel.overviewPanel.updateOverviewImage();
2604       }
2605     }
2606   }
2607
2608   public void seqLimits_itemStateChanged()
2609   {
2610     viewport.setShowJVSuffix(seqLimits.getState());
2611     alignPanel.fontChanged();
2612     alignPanel.paintAlignment(true, false);
2613   }
2614
2615   protected void colourTextMenuItem_actionPerformed()
2616   {
2617     viewport.setColourText(colourTextMenuItem.getState());
2618     alignPanel.paintAlignment(false, false);
2619   }
2620
2621   protected void displayNonconservedMenuItem_actionPerformed()
2622   {
2623     viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
2624     alignPanel.paintAlignment(false, false);
2625   }
2626
2627   protected void wrapMenuItem_actionPerformed()
2628   {
2629     viewport.setWrapAlignment(wrapMenuItem.getState());
2630     alignPanel.setWrapAlignment(wrapMenuItem.getState());
2631     scaleAbove.setEnabled(wrapMenuItem.getState());
2632     scaleLeft.setEnabled(wrapMenuItem.getState());
2633     scaleRight.setEnabled(wrapMenuItem.getState());
2634     alignPanel.paintAlignment(true, false);
2635   }
2636
2637   public void overviewMenuItem_actionPerformed()
2638   {
2639     if (alignPanel.overviewPanel != null)
2640     {
2641       return;
2642     }
2643
2644     Frame frame = new Frame();
2645     final OverviewPanel overview = new OverviewPanel(alignPanel);
2646     frame.add(overview);
2647     // +50 must allow for applet frame window
2648     jalview.bin.JalviewLite.addFrame(frame, MessageManager
2649             .formatMessage("label.overview_params", new String[]
2650             { this.getTitle() }), overview.getPreferredSize().width,
2651             overview.getPreferredSize().height + 50);
2652
2653     frame.pack();
2654     final AlignmentPanel ap = alignPanel;
2655     frame.addWindowListener(new WindowAdapter()
2656     {
2657       @Override
2658       public void windowClosing(WindowEvent e)
2659       {
2660         overview.dispose();
2661         if (ap != null)
2662         {
2663           ap.setOverviewPanel(null);
2664         }
2665       };
2666     });
2667
2668     alignPanel.setOverviewPanel(overview);
2669
2670   }
2671
2672   @Override
2673   public void changeColour(ColourSchemeI cs)
2674   {
2675     viewport.setGlobalColourScheme(cs);
2676
2677     alignPanel.paintAlignment(true, true);
2678   }
2679
2680   protected void modifyPID_actionPerformed()
2681   {
2682     if (viewport.getAbovePIDThreshold()
2683             && viewport.getGlobalColourScheme() != null)
2684     {
2685       SliderPanel.setPIDSliderSource(alignPanel,
2686               viewport.getResidueShading(), alignPanel.getViewName());
2687       SliderPanel.showPIDSlider();
2688     }
2689   }
2690
2691   protected void modifyConservation_actionPerformed()
2692   {
2693     if (viewport.getConservationSelected()
2694             && viewport.getGlobalColourScheme() != null)
2695     {
2696       SliderPanel.setConservationSlider(alignPanel,
2697               viewport.getResidueShading(), alignPanel.getViewName());
2698       SliderPanel.showConservationSlider();
2699     }
2700   }
2701
2702   protected void conservationMenuItem_actionPerformed()
2703   {
2704     boolean selected = conservationMenuItem.getState();
2705     modifyConservation.setEnabled(selected);
2706     viewport.setConservationSelected(selected);
2707     viewport.getResidueShading().setConservationApplied(selected);
2708
2709     changeColour(viewport.getGlobalColourScheme());
2710
2711     if (selected)
2712     {
2713       modifyConservation_actionPerformed();
2714     }
2715     else
2716     {
2717       SliderPanel.hideConservationSlider();
2718     }
2719   }
2720
2721   public void abovePIDThreshold_actionPerformed()
2722   {
2723     boolean selected = abovePIDThreshold.getState();
2724     modifyPID.setEnabled(selected);
2725     viewport.setAbovePIDThreshold(selected);
2726     if (!selected)
2727     {
2728       viewport.getResidueShading().setThreshold(0,
2729               viewport.isIgnoreGapsConsensus());
2730     }
2731
2732     changeColour(viewport.getGlobalColourScheme());
2733
2734     if (selected)
2735     {
2736       modifyPID_actionPerformed();
2737     }
2738     else
2739     {
2740       SliderPanel.hidePIDSlider();
2741     }
2742   }
2743
2744   public void sortPairwiseMenuItem_actionPerformed()
2745   {
2746     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2747     AlignmentSorter.sortByPID(viewport.getAlignment(),
2748             viewport.getAlignment().getSequenceAt(0));
2749
2750     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2751             viewport.getAlignment()));
2752     alignPanel.paintAlignment(true, false);
2753   }
2754
2755   public void sortIDMenuItem_actionPerformed()
2756   {
2757     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2758     AlignmentSorter.sortByID(viewport.getAlignment());
2759     addHistoryItem(
2760             new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
2761     alignPanel.paintAlignment(true, false);
2762   }
2763
2764   public void sortLengthMenuItem_actionPerformed()
2765   {
2766     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2767     AlignmentSorter.sortByLength(viewport.getAlignment());
2768     addHistoryItem(new OrderCommand("Length Sort", oldOrder,
2769             viewport.getAlignment()));
2770     alignPanel.paintAlignment(true, false);
2771   }
2772
2773   public void sortGroupMenuItem_actionPerformed()
2774   {
2775     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2776     AlignmentSorter.sortByGroup(viewport.getAlignment());
2777     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
2778             viewport.getAlignment()));
2779     alignPanel.paintAlignment(true, false);
2780
2781   }
2782
2783   public void sortEValueMenuItem_actionPerformed()
2784   {
2785     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2786     AlignmentSorter.sortByEValue(viewport.getAlignment());
2787     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
2788             viewport.getAlignment()));
2789     alignPanel.paintAlignment(true, false);
2790
2791   }
2792
2793   public void sortBitScoreMenuItem_actionPerformed()
2794   {
2795     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2796     AlignmentSorter.sortByBitScore(viewport.getAlignment());
2797     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
2798             viewport.getAlignment()));
2799     alignPanel.paintAlignment(true, false);
2800
2801   }
2802
2803   public void removeRedundancyMenuItem_actionPerformed()
2804   {
2805     new RedundancyPanel(alignPanel);
2806   }
2807
2808   public void pairwiseAlignmentMenuItem_actionPerformed()
2809   {
2810     if (viewport.getSelectionGroup() != null
2811             && viewport.getSelectionGroup().getSize() > 1)
2812     {
2813       Frame frame = new Frame();
2814       frame.add(new PairwiseAlignPanel(alignPanel));
2815       jalview.bin.JalviewLite.addFrame(frame,
2816               MessageManager.getString("action.pairwise_alignment"), 600,
2817               500);
2818     }
2819   }
2820
2821   public void PCAMenuItem_actionPerformed()
2822   {
2823     // are the sequences aligned?
2824     if (!viewport.getAlignment().isAligned(false))
2825     {
2826       SequenceI current;
2827       int Width = viewport.getAlignment().getWidth();
2828
2829       for (int i = 0; i < viewport.getAlignment().getSequences()
2830               .size(); i++)
2831       {
2832         current = viewport.getAlignment().getSequenceAt(i);
2833
2834         if (current.getLength() < Width)
2835         {
2836           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2837         }
2838       }
2839       alignPanel.paintAlignment(false, false);
2840     }
2841
2842     if ((viewport.getSelectionGroup() != null
2843             && viewport.getSelectionGroup().getSize() < 4
2844             && viewport.getSelectionGroup().getSize() > 0)
2845             || viewport.getAlignment().getHeight() < 4)
2846     {
2847       return;
2848     }
2849
2850     try
2851     {
2852       new PCAPanel(viewport);
2853     } catch (java.lang.OutOfMemoryError ex)
2854     {
2855     }
2856
2857   }
2858
2859   public void averageDistanceTreeMenuItem_actionPerformed()
2860   {
2861     newTreePanel(TreeBuilder.AVERAGE_DISTANCE, new PIDModel().getName(),
2862             "Average distance tree using PID");
2863   }
2864
2865   public void neighbourTreeMenuItem_actionPerformed()
2866   {
2867     newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, new PIDModel().getName(),
2868             "Neighbour joining tree using PID");
2869   }
2870
2871   protected void njTreeBlosumMenuItem_actionPerformed()
2872   {
2873     newTreePanel(TreeBuilder.NEIGHBOUR_JOINING,
2874             ScoreModels.getInstance().getBlosum62().getName(),
2875             "Neighbour joining tree using BLOSUM62");
2876   }
2877
2878   protected void avTreeBlosumMenuItem_actionPerformed()
2879   {
2880     newTreePanel(TreeBuilder.AVERAGE_DISTANCE,
2881             ScoreModels.getInstance().getBlosum62().getName(),
2882             "Average distance tree using BLOSUM62");
2883   }
2884
2885   void newTreePanel(String type, String pwType, String title)
2886   {
2887     // are the sequences aligned?
2888     if (!viewport.getAlignment().isAligned(false))
2889     {
2890       SequenceI current;
2891       int Width = viewport.getAlignment().getWidth();
2892
2893       for (int i = 0; i < viewport.getAlignment().getSequences()
2894               .size(); i++)
2895       {
2896         current = viewport.getAlignment().getSequenceAt(i);
2897
2898         if (current.getLength() < Width)
2899         {
2900           current.insertCharAt(Width - 1, viewport.getGapCharacter());
2901         }
2902       }
2903       alignPanel.paintAlignment(false, false);
2904
2905     }
2906
2907     if ((viewport.getSelectionGroup() != null
2908             && viewport.getSelectionGroup().getSize() > 1)
2909             || (viewport.getAlignment().getHeight() > 1))
2910     {
2911       final TreePanel tp = new TreePanel(alignPanel, type, pwType);
2912
2913       addTreeMenuItem(tp, title);
2914
2915       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);
2916     }
2917   }
2918
2919   void loadTree_actionPerformed()
2920   {
2921     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
2922     cap.setText(MessageManager.getString("label.paste_newick_tree_file"));
2923     cap.setTreeImport();
2924     Frame frame = new Frame();
2925     frame.add(cap);
2926     jalview.bin.JalviewLite.addFrame(frame,
2927             MessageManager.getString("label.paste_newick_file"), 400, 300);
2928   }
2929
2930   public void loadTree(jalview.io.NewickFile tree, String treeFile)
2931   {
2932     TreePanel tp = new TreePanel(alignPanel, treeFile,
2933             MessageManager.getString("label.load_tree_from_file"), tree);
2934     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);
2935     addTreeMenuItem(tp, treeFile);
2936   }
2937
2938   /**
2939    * sort the alignment using the given treePanel
2940    * 
2941    * @param treePanel
2942    *          tree used to sort view
2943    * @param title
2944    *          string used for undo event name
2945    */
2946   public void sortByTree(TreePanel treePanel, String title)
2947   {
2948     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2949     AlignmentSorter.sortByTree(viewport.getAlignment(),
2950             treePanel.getTree());
2951     // addHistoryItem(new HistoryItem("Sort", viewport.alignment,
2952     // HistoryItem.SORT));
2953     addHistoryItem(new OrderCommand(MessageManager
2954             .formatMessage("label.order_by_params", new String[]
2955             { title }), oldOrder, viewport.getAlignment()));
2956     alignPanel.paintAlignment(true, false);
2957   }
2958
2959   /**
2960    * Do any automatic reordering of the alignment and add the necessary bits to
2961    * the menu structure for the new tree
2962    * 
2963    * @param treePanel
2964    * @param title
2965    */
2966   protected void addTreeMenuItem(final TreePanel treePanel,
2967           final String title)
2968   {
2969     final MenuItem item = new MenuItem(title);
2970     sortByTreeMenu.add(item);
2971     item.addActionListener(new java.awt.event.ActionListener()
2972     {
2973       @Override
2974       public void actionPerformed(ActionEvent evt)
2975       {
2976         sortByTree(treePanel, title); // treePanel.getTitle());
2977       }
2978     });
2979
2980     treePanel.addWindowListener(new WindowAdapter()
2981     {
2982       @Override
2983       public void windowOpened(WindowEvent e)
2984       {
2985         if (viewport.sortByTree)
2986         {
2987           sortByTree(treePanel, title);
2988         }
2989         super.windowOpened(e);
2990       }
2991
2992       @Override
2993       public void windowClosing(WindowEvent e)
2994       {
2995         sortByTreeMenu.remove(item);
2996       };
2997     });
2998   }
2999
3000   public boolean sortBy(AlignmentOrder alorder, String undoname)
3001   {
3002     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3003     if (viewport.applet.debug)
3004     {
3005       System.err.println("Sorting " + alorder.getOrder().size()
3006               + " in alignment '" + getTitle() + "'");
3007     }
3008     AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
3009     if (undoname != null)
3010     {
3011       addHistoryItem(new OrderCommand(undoname, oldOrder,
3012               viewport.getAlignment()));
3013     }
3014     alignPanel.paintAlignment(true, false);
3015     return true;
3016   }
3017
3018   protected void documentation_actionPerformed()
3019   {
3020     alignPanel.av.applet.openJalviewHelpUrl();
3021   }
3022
3023   protected void about_actionPerformed()
3024   {
3025
3026     class AboutPanel extends Canvas
3027     {
3028       String version;
3029
3030       String builddate;
3031
3032       public AboutPanel(String version, String builddate)
3033       {
3034         this.version = version;
3035         this.builddate = builddate;
3036       }
3037
3038       @Override
3039       public void paint(Graphics g)
3040       {
3041         g.setColor(Color.white);
3042         g.fillRect(0, 0, getSize().width, getSize().height);
3043         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
3044         FontMetrics fm = g.getFontMetrics();
3045         int fh = fm.getHeight();
3046         int y = 5, x = 7;
3047         g.setColor(Color.black);
3048         // TODO: update this text for each release or centrally store it for
3049         // lite and application
3050         g.setFont(new Font("Helvetica", Font.BOLD, 14));
3051         g.drawString(MessageManager
3052                 .formatMessage("label.jalviewLite_release", new String[]
3053                 { version }), x, y += fh);
3054         g.setFont(new Font("Helvetica", Font.BOLD, 12));
3055         g.drawString(MessageManager.formatMessage("label.jaview_build_date",
3056                 new String[]
3057                 { builddate }), x, y += fh);
3058         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
3059         g.drawString(MessageManager.getString("label.jalview_authors_1"), x,
3060                 y += fh * 1.5);
3061         g.drawString(MessageManager.getString("label.jalview_authors_2"),
3062                 x + 50, y += fh + 8);
3063         g.drawString(MessageManager.getString("label.jalview_dev_managers"),
3064                 x, y += fh);
3065         g.drawString(MessageManager
3066                 .getString("label.jalview_distribution_lists"), x, y += fh);
3067         g.drawString(MessageManager.getString("label.jalview_please_cite"),
3068                 x, y += fh + 8);
3069         g.drawString(
3070                 MessageManager.getString("label.jalview_cite_1_authors"), x,
3071                 y += fh);
3072         g.drawString(MessageManager.getString("label.jalview_cite_1_title"),
3073                 x, y += fh);
3074         g.drawString(MessageManager.getString("label.jalview_cite_1_ref"),
3075                 x, y += fh);
3076       }
3077     }
3078
3079     Frame frame = new Frame();
3080     frame.add(new AboutPanel(JalviewLite.getVersion(),
3081             JalviewLite.getBuildDate()));
3082     jalview.bin.JalviewLite.addFrame(frame,
3083             MessageManager.getString("label.jalview"), 580, 220);
3084
3085   }
3086
3087   public void showURL(String url, String target)
3088   {
3089     if (viewport.applet == null)
3090     {
3091       System.out.println("Not running as applet - no browser available.");
3092     }
3093     else
3094     {
3095       viewport.applet.showURL(url, target);
3096     }
3097   }
3098
3099   // ////////////////////////////////////////////////////////////////////////////////
3100   // JBuilder Graphics here
3101
3102   MenuBar alignFrameMenuBar = new MenuBar();
3103
3104   Menu fileMenu = new Menu(MessageManager.getString("action.file"));
3105
3106   MenuItem loadApplication = new MenuItem(
3107           MessageManager.getString("label.view_full_application"));
3108
3109   MenuItem loadTree = new MenuItem(
3110           MessageManager.getString("label.load_associated_tree"));
3111
3112   MenuItem loadAnnotations = new MenuItem(
3113           MessageManager.getString("label.load_features_annotations"));
3114
3115   MenuItem outputFeatures = new MenuItem(
3116           MessageManager.getString("label.export_features"));
3117
3118   MenuItem outputAnnotations = new MenuItem(
3119           MessageManager.getString("label.export_annotations"));
3120
3121   MenuItem closeMenuItem = new MenuItem(
3122           MessageManager.getString("action.close"));
3123
3124   MenuItem selectAllSequenceMenuItem = new MenuItem(
3125           MessageManager.getString("action.select_all"));
3126
3127   MenuItem deselectAllSequenceMenuItem = new MenuItem(
3128           MessageManager.getString("action.deselect_all"));
3129
3130   MenuItem invertSequenceMenuItem = new MenuItem(
3131           MessageManager.getString("action.invert_selection"));
3132
3133   MenuItem remove2LeftMenuItem = new MenuItem();
3134
3135   MenuItem remove2RightMenuItem = new MenuItem();
3136
3137   MenuItem removeGappedColumnMenuItem = new MenuItem();
3138
3139   MenuItem removeAllGapsMenuItem = new MenuItem();
3140
3141   CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();
3142
3143   CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();
3144
3145   MenuItem sortPairwiseMenuItem = new MenuItem();
3146
3147   MenuItem sortIDMenuItem = new MenuItem();
3148
3149   MenuItem sortLengthMenuItem = new MenuItem();
3150
3151   MenuItem sortGroupMenuItem = new MenuItem();
3152
3153   MenuItem sortEValueMenuItem = new MenuItem();
3154
3155   MenuItem sortBitScoreMenuItem = new MenuItem();
3156
3157   MenuItem removeRedundancyMenuItem = new MenuItem();
3158
3159   MenuItem pairwiseAlignmentMenuItem = new MenuItem();
3160
3161   MenuItem PCAMenuItem = new MenuItem();
3162
3163   MenuItem averageDistanceTreeMenuItem = new MenuItem();
3164
3165   MenuItem neighbourTreeMenuItem = new MenuItem();
3166
3167   BorderLayout borderLayout1 = new BorderLayout();
3168
3169   public Label statusBar = new Label();
3170
3171   MenuItem clustalColour = new MenuItem();
3172
3173   MenuItem zappoColour = new MenuItem();
3174
3175   MenuItem taylorColour = new MenuItem();
3176
3177   MenuItem hydrophobicityColour = new MenuItem();
3178
3179   MenuItem helixColour = new MenuItem();
3180
3181   MenuItem strandColour = new MenuItem();
3182
3183   MenuItem turnColour = new MenuItem();
3184
3185   MenuItem buriedColour = new MenuItem();
3186
3187   MenuItem purinePyrimidineColour = new MenuItem();
3188
3189   // MenuItem RNAInteractionColour = new MenuItem();
3190
3191   MenuItem RNAHelixColour = new MenuItem();
3192
3193   MenuItem userDefinedColour = new MenuItem();
3194
3195   MenuItem PIDColour = new MenuItem();
3196
3197   MenuItem BLOSUM62Colour = new MenuItem();
3198
3199   MenuItem tcoffeeColour = new MenuItem();
3200
3201   MenuItem njTreeBlosumMenuItem = new MenuItem();
3202
3203   MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();
3204
3205   CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();
3206
3207   CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();
3208
3209   CheckboxMenuItem displayNonconservedMenuItem = new CheckboxMenuItem();
3210
3211   MenuItem alProperties = new MenuItem(
3212           MessageManager.getString("label.alignment_props"));
3213
3214   MenuItem overviewMenuItem = new MenuItem();
3215
3216   MenuItem undoMenuItem = new MenuItem();
3217
3218   MenuItem redoMenuItem = new MenuItem();
3219
3220   CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
3221
3222   MenuItem noColourmenuItem = new MenuItem();
3223
3224   CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();
3225
3226   CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();
3227
3228   MenuItem findMenuItem = new MenuItem();
3229
3230   CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();
3231
3232   MenuItem nucleotideColour = new MenuItem();
3233
3234   MenuItem deleteGroups = new MenuItem();
3235
3236   MenuItem grpsFromSelection = new MenuItem();
3237
3238   MenuItem createGroup = new MenuItem();
3239
3240   MenuItem unGroup = new MenuItem();
3241
3242   MenuItem delete = new MenuItem();
3243
3244   MenuItem copy = new MenuItem();
3245
3246   MenuItem cut = new MenuItem();
3247
3248   Menu pasteMenu = new Menu();
3249
3250   MenuItem pasteNew = new MenuItem();
3251
3252   MenuItem pasteThis = new MenuItem();
3253
3254   CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();
3255
3256   MenuItem font = new MenuItem();
3257
3258   CheckboxMenuItem scaleAbove = new CheckboxMenuItem();
3259
3260   CheckboxMenuItem scaleLeft = new CheckboxMenuItem();
3261
3262   CheckboxMenuItem scaleRight = new CheckboxMenuItem();
3263
3264   MenuItem modifyPID = new MenuItem();
3265
3266   MenuItem modifyConservation = new MenuItem();
3267
3268   CheckboxMenuItem autoCalculate = null;
3269
3270   CheckboxMenuItem sortByTree = new CheckboxMenuItem(
3271           "Sort Alignment With New Tree", true);
3272
3273   Menu sortByTreeMenu = new Menu();
3274
3275   MenuItem inputText = new MenuItem();
3276
3277   MenuItem documentation = new MenuItem();
3278
3279   MenuItem about = new MenuItem();
3280
3281   CheckboxMenuItem seqLimits = new CheckboxMenuItem();
3282
3283   CheckboxMenuItem centreColumnLabelFlag = new CheckboxMenuItem();
3284
3285   CheckboxMenuItem followMouseOverFlag = new CheckboxMenuItem();
3286
3287   CheckboxMenuItem showSequenceLogo = new CheckboxMenuItem();
3288
3289   CheckboxMenuItem applyAutoAnnotationSettings = new CheckboxMenuItem();
3290
3291   CheckboxMenuItem showConsensusHistogram = new CheckboxMenuItem();
3292
3293   CheckboxMenuItem showGroupConsensus = new CheckboxMenuItem();
3294
3295   CheckboxMenuItem showGroupConservation = new CheckboxMenuItem();
3296
3297   CheckboxMenuItem normSequenceLogo = new CheckboxMenuItem();
3298
3299   /**
3300    * Initialise menus and other items
3301    * 
3302    * @throws Exception
3303    */
3304   private void jbInit() throws Exception
3305   {
3306     setMenuBar(alignFrameMenuBar);
3307
3308     /*
3309      * Configure File menu items and actions
3310      */
3311     inputText
3312             .setLabel(MessageManager.getString("label.input_from_textbox"));
3313     inputText.addActionListener(this);
3314     Menu outputTextboxMenu = new Menu(
3315             MessageManager.getString("label.out_to_textbox"));
3316     for (String ff : FileFormats.getInstance().getWritableFormats(true))
3317     {
3318       MenuItem item = new MenuItem(ff);
3319
3320       item.addActionListener(new java.awt.event.ActionListener()
3321       {
3322         @Override
3323         public void actionPerformed(ActionEvent e)
3324         {
3325           outputText_actionPerformed(e);
3326         }
3327       });
3328
3329       outputTextboxMenu.add(item);
3330     }
3331     closeMenuItem.addActionListener(this);
3332     loadApplication.addActionListener(this);
3333     loadTree.addActionListener(this);
3334     loadAnnotations.addActionListener(this);
3335     outputFeatures.addActionListener(this);
3336     outputAnnotations.addActionListener(this);
3337
3338     /*
3339      * Configure Edit menu items and actions
3340      */
3341     undoMenuItem.setEnabled(false);
3342     undoMenuItem.setLabel(MessageManager.getString("action.undo"));
3343     undoMenuItem.addActionListener(this);
3344     redoMenuItem.setEnabled(false);
3345     redoMenuItem.setLabel(MessageManager.getString("action.redo"));
3346     redoMenuItem.addActionListener(this);
3347     copy.setLabel(MessageManager.getString("action.copy"));
3348     copy.addActionListener(this);
3349     cut.setLabel(MessageManager.getString("action.cut"));
3350     cut.addActionListener(this);
3351     delete.setLabel(MessageManager.getString("action.delete"));
3352     delete.addActionListener(this);
3353     pasteMenu.setLabel(MessageManager.getString("action.paste"));
3354     pasteNew.setLabel(MessageManager.getString("label.to_new_alignment"));
3355     pasteNew.addActionListener(this);
3356     pasteThis.setLabel(MessageManager.getString("label.to_this_alignment"));
3357     pasteThis.addActionListener(this);
3358     remove2LeftMenuItem
3359             .setLabel(MessageManager.getString("action.remove_left"));
3360     remove2LeftMenuItem.addActionListener(this);
3361     remove2RightMenuItem
3362             .setLabel(MessageManager.getString("action.remove_right"));
3363     remove2RightMenuItem.addActionListener(this);
3364     removeGappedColumnMenuItem.setLabel(
3365             MessageManager.getString("action.remove_empty_columns"));
3366     removeGappedColumnMenuItem.addActionListener(this);
3367     removeAllGapsMenuItem
3368             .setLabel(MessageManager.getString("action.remove_all_gaps"));
3369     removeAllGapsMenuItem.addActionListener(this);
3370     removeRedundancyMenuItem
3371             .setLabel(MessageManager.getString("action.remove_redundancy"));
3372     removeRedundancyMenuItem.addActionListener(this);
3373
3374     /*
3375      * Configure Select menu items and actions
3376      */
3377     findMenuItem.setLabel(MessageManager.getString("action.find"));
3378     findMenuItem.addActionListener(this);
3379     selectAllSequenceMenuItem.addActionListener(this);
3380     deselectAllSequenceMenuItem.addActionListener(this);
3381     invertSequenceMenuItem.setLabel(
3382             MessageManager.getString("action.invert_sequence_selection"));
3383     invertSequenceMenuItem.addActionListener(this);
3384     invertColSel.setLabel(
3385             MessageManager.getString("action.invert_column_selection"));
3386     invertColSel.addActionListener(this);
3387     deleteGroups
3388             .setLabel(MessageManager.getString("action.undefine_groups"));
3389     deleteGroups.addActionListener(this);
3390     grpsFromSelection.setLabel(
3391             MessageManager.getString("action.make_groups_selection"));
3392     grpsFromSelection.addActionListener(this);
3393     createGroup.setLabel(MessageManager.getString("action.create_group"));
3394     createGroup.addActionListener(this);
3395     unGroup.setLabel(MessageManager.getString("action.remove_group"));
3396     unGroup.addActionListener(this);
3397
3398     annotationColumnSelection.setLabel(
3399             MessageManager.getString("action.select_by_annotation"));
3400     annotationColumnSelection.addActionListener(this);
3401
3402     /*
3403      * Configure View menu items and actions
3404      */
3405     newView.setLabel(MessageManager.getString("action.new_view"));
3406     newView.addActionListener(this);
3407     Menu showMenu = new Menu(MessageManager.getString("action.show"));
3408     showColumns.setLabel(MessageManager.getString("label.all_columns"));
3409     showSeqs.setLabel(MessageManager.getString("label.all_sequences"));
3410     Menu hideMenu = new Menu(MessageManager.getString("action.hide"));
3411     hideColumns
3412             .setLabel(MessageManager.getString("label.selected_columns"));
3413     hideSequences
3414             .setLabel(MessageManager.getString("label.selected_sequences"));
3415     hideAllButSelection.setLabel(
3416             MessageManager.getString("label.all_but_selected_region"));
3417     hideAllSelection
3418             .setLabel(MessageManager.getString("label.selected_region"));
3419     showAllHidden.setLabel(
3420             MessageManager.getString("label.all_sequences_columns"));
3421     showColumns.addActionListener(this);
3422     showSeqs.addActionListener(this);
3423     hideColumns.addActionListener(this);
3424     hideSequences.addActionListener(this);
3425     hideAllButSelection.addActionListener(this);
3426     hideAllSelection.addActionListener(this);
3427     showAllHidden.addActionListener(this);
3428     featureSettings
3429             .setLabel(MessageManager.getString("action.feature_settings"));
3430     featureSettings.addActionListener(this);
3431     sequenceFeatures.setLabel(
3432             MessageManager.getString("label.show_sequence_features"));
3433     sequenceFeatures.addItemListener(this);
3434     sequenceFeatures.setState(false);
3435     followMouseOverFlag.setLabel(
3436             MessageManager.getString("label.automatic_scrolling"));
3437     followMouseOverFlag.addItemListener(this);
3438     alProperties.addActionListener(this);
3439     overviewMenuItem
3440             .setLabel(MessageManager.getString("label.overview_window"));
3441     overviewMenuItem.addActionListener(this);
3442
3443     /*
3444      * Configure Annotations menu items and actions
3445      */
3446     annotationPanelMenuItem
3447             .setLabel(MessageManager.getString("label.show_annotations"));
3448     annotationPanelMenuItem.addItemListener(this);
3449     showGroupConsensus
3450             .setLabel(MessageManager.getString("label.group_consensus"));
3451     showGroupConservation
3452             .setLabel(MessageManager.getString("label.group_conservation"));
3453     showConsensusHistogram.setLabel(
3454             MessageManager.getString("label.show_consensus_histogram"));
3455     showSequenceLogo.setLabel(
3456             MessageManager.getString("label.show_consensus_logo"));
3457     normSequenceLogo.setLabel(
3458             MessageManager.getString("label.norm_consensus_logo"));
3459     applyAutoAnnotationSettings
3460             .setLabel(MessageManager.getString("label.apply_all_groups"));
3461     applyAutoAnnotationSettings.setState(true);
3462     Menu autoAnnMenu = new Menu(
3463             MessageManager.getString("label.autocalculated_annotation"));
3464     showGroupConsensus.addItemListener(this);
3465     showGroupConservation.addItemListener(this);
3466     showConsensusHistogram.addItemListener(this);
3467     showSequenceLogo.addItemListener(this);
3468     normSequenceLogo.addItemListener(this);
3469     applyAutoAnnotationSettings.addItemListener(this);
3470     showAlignmentAnnotations = new CheckboxMenuItem(
3471             MessageManager.getString("label.show_all_al_annotations"));
3472     showSequenceAnnotations = new CheckboxMenuItem(
3473             MessageManager.getString("label.show_all_seq_annotations"));
3474     sortAnnBySequence = new CheckboxMenuItem(
3475             MessageManager.getString("label.sort_annotations_by_sequence"));
3476     sortAnnByLabel = new CheckboxMenuItem(
3477             MessageManager.getString("label.sort_annotations_by_label"));
3478     showAutoFirst = new CheckboxMenuItem(
3479             MessageManager.getString("label.show_first"));
3480     showAutoFirst.setState(false); // pending applet parameter
3481     setShowAutoCalculatedAbove(showAutoFirst.getState());
3482     showAutoLast = new CheckboxMenuItem(
3483             MessageManager.getString("label.show_last"));
3484     showAutoLast.setState(!showAutoFirst.getState());
3485     showAlignmentAnnotations.addItemListener(this);
3486     showSequenceAnnotations.addItemListener(this);
3487     sortAnnBySequence.addItemListener(this);
3488     sortAnnByLabel.addItemListener(this);
3489     showAutoFirst.addItemListener(this);
3490     showAutoLast.addItemListener(this);
3491
3492     /*
3493      * Configure Format menu items and actions
3494      */
3495     font.setLabel(MessageManager.getString("action.font"));
3496     font.addActionListener(this);
3497     scaleAbove.setLabel(MessageManager.getString("action.scale_above"));
3498     scaleAbove.setState(true);
3499     scaleAbove.setEnabled(false);
3500     scaleAbove.addItemListener(this);
3501     scaleLeft.setEnabled(false);
3502     scaleLeft.setState(true);
3503     scaleLeft.setLabel(MessageManager.getString("action.scale_left"));
3504     scaleLeft.addItemListener(this);
3505     scaleRight.setEnabled(false);
3506     scaleRight.setState(true);
3507     scaleRight.setLabel(MessageManager.getString("action.scale_right"));
3508     scaleRight.addItemListener(this);
3509     viewBoxesMenuItem.setLabel(MessageManager.getString("action.boxes"));
3510     viewBoxesMenuItem.setState(true);
3511     viewBoxesMenuItem.addItemListener(this);
3512     viewTextMenuItem.setLabel(MessageManager.getString("action.text"));
3513     viewTextMenuItem.setState(true);
3514     viewTextMenuItem.addItemListener(this);
3515     colourTextMenuItem
3516             .setLabel(MessageManager.getString("label.colour_text"));
3517     colourTextMenuItem.addItemListener(this);
3518     displayNonconservedMenuItem
3519             .setLabel(MessageManager.getString("label.show_non_conserved"));
3520     displayNonconservedMenuItem.addItemListener(this);
3521     wrapMenuItem.setLabel(MessageManager.getString("action.wrap"));
3522     wrapMenuItem.addItemListener(this);
3523     renderGapsMenuItem
3524             .setLabel(MessageManager.getString("action.show_gaps"));
3525     renderGapsMenuItem.setState(true);
3526     renderGapsMenuItem.addItemListener(this);
3527     centreColumnLabelFlag.setLabel(
3528             MessageManager.getString("label.centre_column_labels"));
3529     centreColumnLabelFlag.addItemListener(this);
3530     seqLimits.setState(true);
3531     seqLimits.setLabel(
3532             MessageManager.getString("label.show_sequence_limits"));
3533     seqLimits.addItemListener(this);
3534
3535     /*
3536      * Configure Colour menu items and actions
3537      */
3538     applyToAllGroups.setLabel(
3539             MessageManager.getString("label.apply_colour_to_all_groups"));
3540     applyToAllGroups.setState(true);
3541     applyToAllGroups.addItemListener(this);
3542     clustalColour.setLabel(
3543             MessageManager.getString("label.colourScheme_clustal"));
3544     clustalColour.addActionListener(this);
3545     zappoColour
3546             .setLabel(MessageManager.getString("label.colourScheme_zappo"));
3547     zappoColour.addActionListener(this);
3548     taylorColour.setLabel(
3549             MessageManager.getString("label.colourScheme_taylor"));
3550     taylorColour.addActionListener(this);
3551     hydrophobicityColour.setLabel(
3552             MessageManager.getString("label.colourScheme_hydrophobic"));
3553     hydrophobicityColour.addActionListener(this);
3554     helixColour.setLabel(MessageManager
3555             .getString("label.colourScheme_helix_propensity"));
3556     helixColour.addActionListener(this);
3557     strandColour.setLabel(MessageManager
3558             .getString("label.colourScheme_strand_propensity"));
3559     strandColour.addActionListener(this);
3560     turnColour.setLabel(
3561             MessageManager.getString("label.colourScheme_turn_propensity"));
3562     turnColour.addActionListener(this);
3563     buriedColour.setLabel(
3564             MessageManager.getString("label.colourScheme_buried_index"));
3565     buriedColour.addActionListener(this);
3566     purinePyrimidineColour.setLabel(MessageManager
3567             .getString("label.colourScheme_purine/pyrimidine"));
3568     purinePyrimidineColour.addActionListener(this);
3569     // RNAInteractionColour.setLabel(MessageManager
3570     // .getString("label.rna_interaction"));
3571     // RNAInteractionColour.addActionListener(this);
3572     RNAHelixColour.setLabel(
3573             MessageManager.getString("label.colourScheme_rna_helices"));
3574     RNAHelixColour.addActionListener(this);
3575     userDefinedColour
3576             .setLabel(MessageManager.getString("action.user_defined"));
3577     userDefinedColour.addActionListener(this);
3578     PIDColour.setLabel(
3579             MessageManager.getString("label.colourScheme_%_identity"));
3580     PIDColour.addActionListener(this);
3581     BLOSUM62Colour.setLabel(
3582             MessageManager.getString("label.colourScheme_blosum62"));
3583     BLOSUM62Colour.addActionListener(this);
3584     tcoffeeColour.setLabel(
3585             MessageManager.getString("label.colourScheme_t-coffee_scores"));
3586     // it will be enabled only if a score file is provided
3587     tcoffeeColour.setEnabled(false);
3588     tcoffeeColour.addActionListener(this);
3589     conservationMenuItem
3590             .setLabel(MessageManager.getString("action.by_conservation"));
3591     conservationMenuItem.addItemListener(this);
3592     noColourmenuItem.setLabel(MessageManager.getString("label.none"));
3593     noColourmenuItem.addActionListener(this);
3594     abovePIDThreshold.setLabel(
3595             MessageManager.getString("label.above_identity_threshold"));
3596     abovePIDThreshold.addItemListener(this);
3597     nucleotideColour.setLabel(
3598             MessageManager.getString("label.colourScheme_nucleotide"));
3599     nucleotideColour.addActionListener(this);
3600     modifyPID.setLabel(
3601             MessageManager.getString("label.modify_identity_threshold"));
3602     modifyPID.setEnabled(abovePIDThreshold.getState());
3603     modifyPID.addActionListener(this);
3604     modifyConservation.setLabel(MessageManager
3605             .getString("label.modify_conservation_threshold"));
3606     modifyConservation.setEnabled(conservationMenuItem.getState());
3607     modifyConservation.addActionListener(this);
3608     annotationColour
3609             .setLabel(MessageManager.getString("action.by_annotation"));
3610     annotationColour.addActionListener(this);
3611
3612     /*
3613      * Configure Calculate menu items and actions
3614      */
3615     sortPairwiseMenuItem
3616             .setLabel(MessageManager.getString("action.by_pairwise_id"));
3617     sortPairwiseMenuItem.addActionListener(this);
3618     sortIDMenuItem.setLabel(MessageManager.getString("action.by_id"));
3619     sortIDMenuItem.addActionListener(this);
3620     sortLengthMenuItem
3621             .setLabel(MessageManager.getString("action.by_length"));
3622     sortLengthMenuItem.addActionListener(this);
3623     sortGroupMenuItem.setLabel(MessageManager.getString("action.by_group"));
3624     sortGroupMenuItem.addActionListener(this);
3625     pairwiseAlignmentMenuItem.setLabel(
3626             MessageManager.getString("action.pairwise_alignment"));
3627     pairwiseAlignmentMenuItem.addActionListener(this);
3628     PCAMenuItem.setLabel(
3629             MessageManager.getString("label.principal_component_analysis"));
3630     PCAMenuItem.addActionListener(this);
3631     autoCalculate = new CheckboxMenuItem(
3632             MessageManager.getString("label.autocalculate_consensus"),
3633             true);
3634     averageDistanceTreeMenuItem.setLabel(
3635             MessageManager.getString("label.average_distance_identity"));
3636     averageDistanceTreeMenuItem.addActionListener(this);
3637     neighbourTreeMenuItem.setLabel(
3638             MessageManager.getString("label.neighbour_joining_identity"));
3639     neighbourTreeMenuItem.addActionListener(this);
3640     avDistanceTreeBlosumMenuItem.setLabel(
3641             MessageManager.getString("label.average_distance_blosum62"));
3642     avDistanceTreeBlosumMenuItem.addActionListener(this);
3643     njTreeBlosumMenuItem
3644             .setLabel(MessageManager.getString("label.neighbour_blosum62"));
3645     njTreeBlosumMenuItem.addActionListener(this);
3646     sortByTreeMenu
3647             .setLabel(MessageManager.getString("action.by_tree_order"));
3648     Menu sortMenu = new Menu(MessageManager.getString("action.sort"));
3649     Menu calculateTreeMenu = new Menu(
3650             MessageManager.getString("action.calculate_tree"));
3651     autoCalculate.addItemListener(this);
3652     sortByTree.addItemListener(this);
3653
3654     /*
3655      * Configure Help menu items and actions
3656      */
3657     Menu helpMenu = new Menu(MessageManager.getString("action.help"));
3658     documentation.setLabel(MessageManager.getString("label.documentation"));
3659     documentation.addActionListener(this);
3660     about.setLabel(MessageManager.getString("label.about"));
3661     about.addActionListener(this);
3662
3663     /*
3664      * Add top level menus to frame
3665      */
3666     alignFrameMenuBar.add(fileMenu);
3667     Menu editMenu = new Menu(MessageManager.getString("action.edit"));
3668     alignFrameMenuBar.add(editMenu);
3669     Menu selectMenu = new Menu(MessageManager.getString("action.select"));
3670     alignFrameMenuBar.add(selectMenu);
3671     Menu viewMenu = new Menu(MessageManager.getString("action.view"));
3672     alignFrameMenuBar.add(viewMenu);
3673     Menu annotationsMenu = new Menu(
3674             MessageManager.getString("action.annotations"));
3675     alignFrameMenuBar.add(annotationsMenu);
3676     Menu formatMenu = new Menu(MessageManager.getString("action.format"));
3677     alignFrameMenuBar.add(formatMenu);
3678     Menu colourMenu = new Menu(MessageManager.getString("action.colour"));
3679     alignFrameMenuBar.add(colourMenu);
3680     Menu calculateMenu = new Menu(
3681             MessageManager.getString("action.calculate"));
3682     alignFrameMenuBar.add(calculateMenu);
3683     alignFrameMenuBar.add(helpMenu);
3684
3685     /*
3686      * File menu
3687      */
3688     fileMenu.add(inputText);
3689     fileMenu.add(loadTree);
3690     fileMenu.add(loadAnnotations);
3691     fileMenu.addSeparator();
3692     fileMenu.add(outputTextboxMenu);
3693     fileMenu.add(outputFeatures);
3694     fileMenu.add(outputAnnotations);
3695     if (jalviewServletURL != null)
3696     {
3697       fileMenu.add(loadApplication);
3698     }
3699     fileMenu.addSeparator();
3700     fileMenu.add(closeMenuItem);
3701
3702     /*
3703      * Edit menu
3704      */
3705     editMenu.add(undoMenuItem);
3706     editMenu.add(redoMenuItem);
3707     editMenu.add(cut);
3708     editMenu.add(copy);
3709     pasteMenu.add(pasteNew);
3710     pasteMenu.add(pasteThis);
3711     editMenu.add(pasteMenu);
3712     editMenu.add(delete);
3713     editMenu.addSeparator();
3714     editMenu.add(remove2LeftMenuItem);
3715     editMenu.add(remove2RightMenuItem);
3716     editMenu.add(removeGappedColumnMenuItem);
3717     editMenu.add(removeAllGapsMenuItem);
3718     editMenu.add(removeRedundancyMenuItem);
3719
3720     /*
3721      * Select menu
3722      */
3723     selectMenu.add(findMenuItem);
3724     selectMenu.addSeparator();
3725     selectMenu.add(selectAllSequenceMenuItem);
3726     selectMenu.add(deselectAllSequenceMenuItem);
3727     selectMenu.add(invertSequenceMenuItem);
3728     selectMenu.add(invertColSel);
3729     selectMenu.add(createGroup);
3730     selectMenu.add(unGroup);
3731     selectMenu.add(grpsFromSelection);
3732     selectMenu.add(deleteGroups);
3733     selectMenu.add(annotationColumnSelection);
3734
3735     /*
3736      * View menu
3737      */
3738     viewMenu.add(newView);
3739     viewMenu.addSeparator();
3740     showMenu.add(showColumns);
3741     showMenu.add(showSeqs);
3742     showMenu.add(showAllHidden);
3743     viewMenu.add(showMenu);
3744     hideMenu.add(hideColumns);
3745     hideMenu.add(hideSequences);
3746     hideMenu.add(hideAllSelection);
3747     hideMenu.add(hideAllButSelection);
3748     viewMenu.add(hideMenu);
3749     viewMenu.addSeparator();
3750     viewMenu.add(followMouseOverFlag);
3751     viewMenu.addSeparator();
3752     viewMenu.add(sequenceFeatures);
3753     viewMenu.add(featureSettings);
3754     viewMenu.addSeparator();
3755     viewMenu.add(alProperties);
3756     viewMenu.addSeparator();
3757     viewMenu.add(overviewMenuItem);
3758
3759     /*
3760      * Annotations menu
3761      */
3762     annotationsMenu.add(annotationPanelMenuItem);
3763     annotationsMenu.addSeparator();
3764     annotationsMenu.add(showAlignmentAnnotations);
3765     annotationsMenu.add(showSequenceAnnotations);
3766     annotationsMenu.add(sortAnnBySequence);
3767     annotationsMenu.add(sortAnnByLabel);
3768     annotationsMenu.addSeparator();
3769     autoAnnMenu.add(showAutoFirst);
3770     autoAnnMenu.add(showAutoLast);
3771     autoAnnMenu.addSeparator();
3772     autoAnnMenu.add(applyAutoAnnotationSettings);
3773     autoAnnMenu.add(showConsensusHistogram);
3774     autoAnnMenu.add(showSequenceLogo);
3775     autoAnnMenu.add(normSequenceLogo);
3776     autoAnnMenu.addSeparator();
3777     autoAnnMenu.add(showGroupConservation);
3778     autoAnnMenu.add(showGroupConsensus);
3779     annotationsMenu.add(autoAnnMenu);
3780
3781     /*
3782      * Format menu
3783      */
3784     formatMenu.add(font);
3785     formatMenu.add(seqLimits);
3786     formatMenu.add(wrapMenuItem);
3787     formatMenu.add(scaleAbove);
3788     formatMenu.add(scaleLeft);
3789     formatMenu.add(scaleRight);
3790     formatMenu.add(viewBoxesMenuItem);
3791     formatMenu.add(viewTextMenuItem);
3792     formatMenu.add(colourTextMenuItem);
3793     formatMenu.add(displayNonconservedMenuItem);
3794     formatMenu.add(renderGapsMenuItem);
3795     formatMenu.add(centreColumnLabelFlag);
3796
3797     /*
3798      * Colour menu
3799      */
3800     colourMenu.add(applyToAllGroups);
3801     colourMenu.addSeparator();
3802     colourMenu.add(noColourmenuItem);
3803     colourMenu.add(clustalColour);
3804     colourMenu.add(BLOSUM62Colour);
3805     colourMenu.add(PIDColour);
3806     colourMenu.add(zappoColour);
3807     colourMenu.add(taylorColour);
3808     colourMenu.add(hydrophobicityColour);
3809     colourMenu.add(helixColour);
3810     colourMenu.add(strandColour);
3811     colourMenu.add(turnColour);
3812     colourMenu.add(buriedColour);
3813     colourMenu.add(nucleotideColour);
3814     colourMenu.add(purinePyrimidineColour);
3815     // colourMenu.add(RNAInteractionColour);
3816     colourMenu.add(tcoffeeColour);
3817     colourMenu.add(userDefinedColour);
3818     colourMenu.addSeparator();
3819     colourMenu.add(conservationMenuItem);
3820     colourMenu.add(modifyConservation);
3821     colourMenu.add(abovePIDThreshold);
3822     colourMenu.add(modifyPID);
3823     colourMenu.add(annotationColour);
3824     colourMenu.add(RNAHelixColour);
3825
3826     /*
3827      * Calculate menu
3828      */
3829     sortMenu.add(sortIDMenuItem);
3830     sortMenu.add(sortLengthMenuItem);
3831     sortMenu.add(sortByTreeMenu);
3832     sortMenu.add(sortGroupMenuItem);
3833     sortMenu.add(sortPairwiseMenuItem);
3834     calculateMenu.add(sortMenu);
3835     calculateTreeMenu.add(averageDistanceTreeMenuItem);
3836     calculateTreeMenu.add(neighbourTreeMenuItem);
3837     calculateTreeMenu.add(avDistanceTreeBlosumMenuItem);
3838     calculateTreeMenu.add(njTreeBlosumMenuItem);
3839     calculateMenu.add(calculateTreeMenu);
3840     calculateMenu.addSeparator();
3841     calculateMenu.add(pairwiseAlignmentMenuItem);
3842     calculateMenu.add(PCAMenuItem);
3843     calculateMenu.add(autoCalculate);
3844     calculateMenu.add(sortByTree);
3845
3846     /*
3847      * Help menu
3848      */
3849     helpMenu.add(documentation);
3850     helpMenu.add(about);
3851
3852     /*
3853      * Status bar
3854      */
3855     statusBar.setBackground(Color.white);
3856     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
3857     statusBar.setText(MessageManager.getString("label.status_bar"));
3858     this.add(statusBar, BorderLayout.SOUTH);
3859   }
3860
3861   @Override
3862   public void setStatus(String string)
3863   {
3864     statusBar.setText(string);
3865   };
3866
3867   MenuItem featureSettings = new MenuItem();
3868
3869   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();
3870
3871   MenuItem annotationColour = new MenuItem();
3872
3873   MenuItem annotationColumnSelection = new MenuItem();
3874
3875   MenuItem invertColSel = new MenuItem();
3876
3877   MenuItem showColumns = new MenuItem();
3878
3879   MenuItem showSeqs = new MenuItem();
3880
3881   MenuItem hideColumns = new MenuItem();
3882
3883   MenuItem hideSequences = new MenuItem();
3884
3885   MenuItem hideAllButSelection = new MenuItem();
3886
3887   MenuItem hideAllSelection = new MenuItem();
3888
3889   MenuItem showAllHidden = new MenuItem();
3890
3891   MenuItem newView = new MenuItem();
3892
3893   private CheckboxMenuItem showAlignmentAnnotations;
3894
3895   private CheckboxMenuItem showSequenceAnnotations;
3896
3897   private CheckboxMenuItem sortAnnBySequence;
3898
3899   private CheckboxMenuItem sortAnnByLabel;
3900
3901   private CheckboxMenuItem showAutoFirst;
3902
3903   private CheckboxMenuItem showAutoLast;
3904
3905   private SplitFrame splitFrame;
3906
3907   /**
3908    * Attach the alignFrame panels after embedding menus, if necessary. This used
3909    * to be called setEmbedded, but is now creates the dropdown menus in a
3910    * platform independent manner to avoid OSX/Mac menu appendage daftness.
3911    * 
3912    * @param reallyEmbedded
3913    *          true to attach the view to the applet area on the page rather than
3914    *          in a new window
3915    */
3916   public void createAlignFrameWindow(boolean reallyEmbedded)
3917   {
3918     if (reallyEmbedded)
3919     {
3920       embedAlignFrameInApplet(viewport.applet);
3921     }
3922     else
3923     {
3924       // //////
3925       // test and embed menu bar if necessary.
3926       //
3927       if (embedMenuIfNeeded(alignPanel))
3928       {
3929         /*
3930          * adjust for status bar height too. ? pointless as overridden by layout
3931          * manager
3932          */
3933         alignPanel.setSize(getSize().width,
3934                 getSize().height - statusBar.getHeight());
3935       }
3936       add(statusBar, BorderLayout.SOUTH);
3937       add(alignPanel, BorderLayout.CENTER);
3938       // and register with the applet so it can pass external API calls to us
3939       jalview.bin.JalviewLite.addFrame(this, this.getTitle(), frameWidth,
3940               frameHeight);
3941     }
3942   }
3943
3944   /**
3945    * Add the components of this AlignFrame to the applet container.
3946    * 
3947    * @param theApplet
3948    */
3949   public void embedAlignFrameInApplet(final JalviewLite theApplet)
3950   {
3951     // ////
3952     // Explicitly build the embedded menu panel for the on-page applet
3953     //
3954     // view cannot be closed if its actually on the page
3955     fileMenu.remove(closeMenuItem);
3956     fileMenu.remove(3); // Remove Separator
3957     // construct embedded menu, using default font
3958     embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, false, false);
3959     // and actually add the components to the applet area
3960     theApplet.setLayout(new BorderLayout());
3961     theApplet.add(embeddedMenu, BorderLayout.NORTH);
3962     theApplet.add(statusBar, BorderLayout.SOUTH);
3963     // TODO should size be left to the layout manager?
3964     alignPanel.setSize(theApplet.getSize().width, theApplet.getSize().height
3965             - embeddedMenu.getHeight() - statusBar.getHeight());
3966     theApplet.add(alignPanel, BorderLayout.CENTER);
3967     final AlignFrame me = this;
3968     theApplet.addFocusListener(new FocusListener()
3969     {
3970
3971       @Override
3972       public void focusLost(FocusEvent e)
3973       {
3974         if (theApplet.currentAlignFrame == me)
3975         {
3976           theApplet.currentAlignFrame = null;
3977         }
3978       }
3979
3980       @Override
3981       public void focusGained(FocusEvent e)
3982       {
3983         theApplet.currentAlignFrame = me;
3984       }
3985     });
3986     theApplet.validate();
3987   }
3988
3989   /**
3990    * create a new binding between structures in an existing jmol viewer instance
3991    * and an alignpanel with sequences that have existing PDBFile entries. Note,
3992    * this does not open a new Jmol window, or modify the display of the
3993    * structures in the original jmol window. Note This method doesn't work
3994    * without an additional javascript library to exchange messages between the
3995    * distinct applets. See http://issues.jalview.org/browse/JAL-621
3996    * 
3997    * @param viewer
3998    *          JmolViewer instance
3999    * @param sequenceIds
4000    *          - sequence Ids to search for associations
4001    */
4002   public SequenceStructureBinding addStructureViewInstance(
4003           Object jmolviewer, String[] sequenceIds)
4004   {
4005     Viewer viewer = null;
4006     try
4007     {
4008       viewer = (Viewer) jmolviewer;
4009     } catch (ClassCastException ex)
4010     {
4011       System.err.println(
4012               "Unsupported viewer object :" + jmolviewer.getClass());
4013     }
4014     if (viewer == null)
4015     {
4016       System.err.println("Can't use this object as a structure viewer:"
4017               + jmolviewer.getClass());
4018       return null;
4019     }
4020     SequenceI[] seqs = null;
4021     if (sequenceIds == null || sequenceIds.length == 0)
4022     {
4023       seqs = viewport.getAlignment().getSequencesArray();
4024     }
4025     else
4026     {
4027       Vector sqi = new Vector();
4028       AlignmentI al = viewport.getAlignment();
4029       for (int sid = 0; sid < sequenceIds.length; sid++)
4030       {
4031         SequenceI sq = al.findName(sequenceIds[sid]);
4032         if (sq != null)
4033         {
4034           sqi.addElement(sq);
4035         }
4036       }
4037       if (sqi.size() > 0)
4038       {
4039         seqs = new SequenceI[sqi.size()];
4040         for (int sid = 0, sSize = sqi.size(); sid < sSize; sid++)
4041         {
4042           seqs[sid] = (SequenceI) sqi.elementAt(sid);
4043         }
4044       }
4045       else
4046       {
4047         return null;
4048       }
4049     }
4050     AAStructureBindingModel jmv = null;
4051     // TODO: search for a jmv that involves viewer
4052     if (jmv == null)
4053     { // create a new viewer/jalview binding.
4054       jmv = new ExtJmol(viewer, alignPanel, new SequenceI[][] { seqs });
4055     }
4056     return jmv;
4057
4058   }
4059
4060   /**
4061    * bind a pdb file to a sequence in the current view
4062    * 
4063    * @param sequenceId
4064    *          - sequenceId within the dataset.
4065    * @param pdbEntryString
4066    *          - the short name for the PDB file
4067    * @param pdbFile
4068    *          - pdb file - either a URL or a valid PDB file.
4069    * @return true if binding was as success TODO: consider making an exception
4070    *         structure for indicating when PDB parsing or sequenceId location
4071    *         fails.
4072    */
4073   public boolean addPdbFile(String sequenceId, String pdbEntryString,
4074           String pdbFile)
4075   {
4076     SequenceI toaddpdb = viewport.getAlignment().findName(sequenceId);
4077     boolean needtoadd = false;
4078     if (toaddpdb != null)
4079     {
4080       Vector pdbe = toaddpdb.getAllPDBEntries();
4081       PDBEntry pdbentry = null;
4082       if (pdbe != null && pdbe.size() > 0)
4083       {
4084         for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
4085         {
4086           pdbentry = (PDBEntry) pdbe.elementAt(pe);
4087           if (!pdbentry.getId().equals(pdbEntryString)
4088                   && !pdbentry.getFile().equals(pdbFile))
4089           {
4090             pdbentry = null;
4091           }
4092           else
4093           {
4094             continue;
4095           }
4096         }
4097       }
4098       if (pdbentry == null)
4099       {
4100         pdbentry = new PDBEntry();
4101         pdbentry.setId(pdbEntryString);
4102         pdbentry.setFile(pdbFile);
4103         needtoadd = true; // add this new entry to sequence.
4104       }
4105       // resolve data source
4106       // TODO: this code should be a refactored to an io package
4107       DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
4108               FileFormat.PDB);
4109       if (protocol == null)
4110       {
4111         return false;
4112       }
4113       if (needtoadd)
4114       {
4115         pdbentry.setProperty("protocol", protocol);
4116         toaddpdb.addPDBId(pdbentry);
4117         alignPanel.getStructureSelectionManager()
4118                 .registerPDBEntry(pdbentry);
4119       }
4120     }
4121     return true;
4122   }
4123
4124   private Object[] cleanSeqChainArrays(SequenceI[] seqs, String[] chains)
4125   {
4126     if (seqs != null)
4127     {
4128       Vector sequences = new Vector();
4129       for (int i = 0; i < seqs.length; i++)
4130       {
4131         if (seqs[i] != null)
4132         {
4133           sequences
4134                   .addElement(new Object[]
4135                   { seqs[i], (chains != null) ? chains[i] : null });
4136         }
4137       }
4138       seqs = new SequenceI[sequences.size()];
4139       chains = new String[sequences.size()];
4140       for (int i = 0, isize = sequences.size(); i < isize; i++)
4141       {
4142         Object[] oj = (Object[]) sequences.elementAt(i);
4143
4144         seqs[i] = (SequenceI) oj[0];
4145         chains[i] = (String) oj[1];
4146       }
4147     }
4148     return new Object[] { seqs, chains };
4149
4150   }
4151
4152   public void newStructureView(JalviewLite applet, PDBEntry pdb,
4153           SequenceI[] seqs, String[] chains, DataSourceType protocol)
4154   {
4155     // Scrub any null sequences from the array
4156     Object[] sqch = cleanSeqChainArrays(seqs, chains);
4157     seqs = (SequenceI[]) sqch[0];
4158     chains = (String[]) sqch[1];
4159     if (seqs == null || seqs.length == 0)
4160     {
4161       System.err.println(
4162               "JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to.");
4163     }
4164     if (protocol == null)
4165     {
4166       String sourceType = (String) pdb.getProperty("protocol");
4167       try
4168       {
4169         protocol = DataSourceType.valueOf(sourceType);
4170       } catch (IllegalArgumentException e)
4171       {
4172         // ignore
4173       }
4174       if (protocol == null)
4175       {
4176         System.err.println("Couldn't work out protocol to open structure: "
4177                 + pdb.getId());
4178         return;
4179       }
4180     }
4181     if (applet.useXtrnalSviewer)
4182     {
4183       // register the association(s) and quit, don't create any windows.
4184       if (StructureSelectionManager.getStructureSelectionManager(applet)
4185               .setMapping(seqs, chains, pdb.getFile(), protocol, null) == null)
4186       {
4187         System.err.println("Failed to map " + pdb.getFile() + " ("
4188                 + protocol + ") to any sequences");
4189       }
4190       return;
4191     }
4192     if (applet.isAlignPdbStructures() && applet.jmolAvailable)
4193     {
4194       // can only do alignments with Jmol
4195       // find the last jmol window assigned to this alignment
4196       AppletJmol ajm = null, tajm;
4197       Vector jmols = applet.getAppletWindow(AppletJmol.class);
4198       for (int i = 0, iSize = jmols.size(); i < iSize; i++)
4199       {
4200         tajm = (AppletJmol) jmols.elementAt(i);
4201         if (tajm.ap.alignFrame == this)
4202         {
4203           ajm = tajm;
4204           break;
4205         }
4206       }
4207       if (ajm != null)
4208       {
4209         System.err.println(
4210                 "Incremental adding and aligning structure to existing Jmol view not yet implemented.");
4211         // try and add the pdb structure
4212         // ajm.addS
4213         ajm = null;
4214       }
4215     }
4216     // otherwise, create a new window
4217     if (applet.jmolAvailable)
4218     {
4219       new AppletJmol(pdb, seqs, chains, alignPanel, protocol);
4220       applet.lastFrameX += 40;
4221       applet.lastFrameY += 40;
4222     }
4223     else
4224     {
4225       new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol);
4226     }
4227
4228   }
4229
4230   public void alignedStructureView(JalviewLite applet, PDBEntry[] pdb,
4231           SequenceI[][] seqs, String[][] chains, String[] protocols)
4232   {
4233     // TODO Auto-generated method stub
4234     System.err.println("Aligned Structure View: Not yet implemented.");
4235   }
4236
4237   /**
4238    * modify the current selection, providing the user has not made a selection
4239    * already.
4240    * 
4241    * @param sel
4242    *          - sequences from this alignment
4243    * @param csel
4244    *          - columns to be selected on the alignment
4245    */
4246   public void select(SequenceGroup sel, ColumnSelection csel,
4247           HiddenColumns hidden)
4248   {
4249     alignPanel.seqPanel.selection(sel, csel, hidden, null);
4250   }
4251
4252   public void scrollTo(int row, int column)
4253   {
4254     alignPanel.seqPanel.scrollTo(row, column);
4255   }
4256
4257   public void scrollToRow(int row)
4258   {
4259     alignPanel.seqPanel.scrollToRow(row);
4260   }
4261
4262   public void scrollToColumn(int column)
4263   {
4264     alignPanel.seqPanel.scrollToColumn(column);
4265   }
4266
4267   /**
4268    * @return the alignments unique ID.
4269    */
4270   public String getSequenceSetId()
4271   {
4272     return viewport.getSequenceSetId();
4273   }
4274
4275   /**
4276    * Load the (T-Coffee) score file from the specified url
4277    * 
4278    * @param source
4279    *          File/URL/T-COFFEE score file contents
4280    * @throws IOException
4281    * @return true if alignment was annotated with data from source
4282    */
4283   public boolean loadScoreFile(String source) throws IOException
4284   {
4285
4286     TCoffeeScoreFile file = new TCoffeeScoreFile(source,
4287             AppletFormatAdapter.checkProtocol(source));
4288     if (!file.isValid())
4289     {
4290       // TODO: raise dialog for gui
4291       System.err.println("Problems parsing T-Coffee scores: "
4292               + file.getWarningMessage());
4293       System.err.println("Origin was:\n" + source);
4294       return false;
4295     }
4296
4297     /*
4298      * check that the score matrix matches the alignment dimensions
4299      */
4300     AlignmentI aln;
4301     if ((aln = viewport.getAlignment()) != null
4302             && (aln.getHeight() != file.getHeight()
4303                     || aln.getWidth() != file.getWidth()))
4304     {
4305       // TODO: raise a dialog box here rather than bomb out.
4306       System.err.println(
4307               "The scores matrix does not match the alignment dimensions");
4308
4309     }
4310
4311     // TODO add parameter to indicate if matching should be done
4312     if (file.annotateAlignment(alignPanel.getAlignment(), false))
4313     {
4314       alignPanel.fontChanged();
4315       tcoffeeColour.setEnabled(true);
4316       // switch to this color
4317       changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
4318       return true;
4319     }
4320     else
4321     {
4322       System.err.println("Problems resolving T-Coffee scores:");
4323       if (file.getWarningMessage() != null)
4324       {
4325         System.err.println(file.getWarningMessage());
4326       }
4327     }
4328     return false;
4329   }
4330
4331   public SplitFrame getSplitFrame()
4332   {
4333     return this.splitFrame;
4334   }
4335
4336   public void setSplitFrame(SplitFrame sf)
4337   {
4338     this.splitFrame = sf;
4339   }
4340
4341   // may not need this
4342   @Override
4343   public void setShowSeqFeatures(boolean b)
4344   {
4345     // showSeqFeatures.setSelected(b);
4346     viewport.setShowSequenceFeatures(b);
4347
4348   }
4349
4350   @Override
4351   public void setMenusForViewport()
4352   {
4353     // setMenusFromViewport(viewport);
4354
4355   }
4356
4357   @Override
4358   public void refreshFeatureUI(boolean enableIfNecessary)
4359   {
4360     if (enableIfNecessary)
4361     {
4362       sequenceFeatures.setState(true);
4363       alignPanel.av.setShowSequenceFeatures(true);
4364     }
4365   }
4366
4367   @Override
4368   public FeatureSettingsControllerI getFeatureSettingsUI()
4369   {
4370     return alignPanel.av.featureSettings;
4371   }
4372
4373 }