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