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