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