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