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