Jnet files sent to servlet as annotations
[jalview.git] / src / jalview / appletgui / AlignFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 \r
20 package jalview.appletgui;\r
21 \r
22 import jalview.schemes.*;\r
23 import jalview.datamodel.*;\r
24 import jalview.analysis.*;\r
25 import jalview.io.*;\r
26 import java.awt.*;\r
27 import java.awt.event.*;\r
28 import java.util.*;\r
29 import java.io.InputStreamReader;\r
30 import java.io.BufferedReader;\r
31 import java.net.URL;\r
32 \r
33 \r
34 public class AlignFrame extends Frame implements ActionListener,\r
35     ItemListener, KeyListener, MouseListener\r
36 {\r
37   public AlignmentPanel alignPanel;\r
38   public AlignViewport viewport;\r
39   int NEW_WINDOW_WIDTH = 700;\r
40   int NEW_WINDOW_HEIGHT = 500;\r
41 \r
42   String jalviewServletURL;\r
43 \r
44 \r
45    public AlignFrame(AlignmentI al,\r
46                      jalview.bin.JalviewLite applet,\r
47                      String title,\r
48                      boolean embedded)\r
49   {\r
50 \r
51     jalviewServletURL = applet.getParameter("APPLICATION_URL");\r
52 \r
53     try{\r
54       jbInit();\r
55     }catch(Exception ex)\r
56     {\r
57       ex.printStackTrace();\r
58     }\r
59 \r
60     viewport = new AlignViewport(al, applet);\r
61     alignPanel = new AlignmentPanel(this, viewport);\r
62 \r
63     annotationPanelMenuItem.setState(viewport.showAnnotation);\r
64 \r
65     seqLimits.setState(viewport.showJVSuffix);\r
66 \r
67     if(applet!=null)\r
68     {\r
69       String param = applet.getParameter("sortBy");\r
70       if (param != null)\r
71       {\r
72         if (param.equalsIgnoreCase("Id"))\r
73           sortIDMenuItem_actionPerformed();\r
74         else if (param.equalsIgnoreCase("Pairwise Identity"))\r
75           sortPairwiseMenuItem_actionPerformed();\r
76       }\r
77 \r
78       param = applet.getParameter("wrap");\r
79       if (param != null)\r
80       {\r
81         if (param.equalsIgnoreCase("true"))\r
82         {\r
83           wrapMenuItem.setState(true);\r
84           wrapMenuItem_actionPerformed();\r
85         }\r
86       }\r
87 \r
88       try\r
89       {\r
90         param = applet.getParameter("windowWidth");\r
91         if (param != null)\r
92         {\r
93           int width = Integer.parseInt(param);\r
94           NEW_WINDOW_WIDTH = width;\r
95         }\r
96         param = applet.getParameter("windowHeight");\r
97         if (param != null)\r
98         {\r
99           int height = Integer.parseInt(param);\r
100           NEW_WINDOW_HEIGHT = height;\r
101         }\r
102       }\r
103       catch (Exception ex)\r
104       {}\r
105 \r
106     }\r
107 \r
108    //Some JVMS send keyevents to Top frame or lowest panel,\r
109    //Havent worked out why yet. So add to both this frame and seqCanvas for now\r
110    this.addKeyListener(this);\r
111    alignPanel.seqPanel.seqCanvas.addKeyListener(this);\r
112    alignPanel.idPanel.idCanvas.addKeyListener(this);\r
113    alignPanel.scalePanel.addKeyListener(this);\r
114    alignPanel.annotationPanel.addKeyListener(this);\r
115 \r
116     viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener()\r
117     {\r
118      public void propertyChange(java.beans.PropertyChangeEvent evt)\r
119      {\r
120        if (evt.getPropertyName().equals("alignment"))\r
121        {\r
122          alignmentChanged();\r
123        }\r
124      }\r
125    });\r
126 \r
127 \r
128    if(embedded)\r
129    {\r
130      setEmbedded();\r
131    }\r
132    else\r
133    {\r
134      add(alignPanel, BorderLayout.CENTER);\r
135      jalview.bin.JalviewLite.addFrame(this, title, NEW_WINDOW_WIDTH,\r
136                                       NEW_WINDOW_HEIGHT);\r
137    }\r
138    alignPanel.validate();\r
139    alignPanel.repaint();\r
140   }\r
141   public AlignViewport getAlignViewport()\r
142   {\r
143     return viewport;\r
144   }\r
145 \r
146   public SeqCanvas getSeqcanvas()\r
147   {\r
148     return alignPanel.seqPanel.seqCanvas;\r
149   }\r
150 \r
151 \r
152   /**\r
153    * DOCUMENT ME!\r
154    *\r
155    * @param String DOCUMENT ME!\r
156    */\r
157 \r
158   public void parseFeaturesFile(String file, String type)\r
159   {\r
160     Hashtable featureLinks = new Hashtable();\r
161     boolean featuresFile = false;\r
162     try{\r
163       featuresFile = new jalview.io.FeaturesFile(file, type).parse(viewport.alignment,\r
164                                          alignPanel.seqPanel.seqCanvas.\r
165                                          getFeatureRenderer().featureColours,\r
166                                          featureLinks,\r
167                                          true);\r
168     }\r
169     catch(Exception ex)\r
170     {\r
171       ex.printStackTrace();\r
172     }\r
173 \r
174     if(featuresFile)\r
175     {\r
176       if(featureLinks.size()>0)\r
177         alignPanel.seqPanel.seqCanvas\r
178             .getFeatureRenderer().featureLinks = featureLinks;\r
179       viewport.showSequenceFeatures = true;\r
180       sequenceFeatures.setState(true);\r
181       alignPanel.repaint();\r
182     }\r
183 \r
184   }\r
185 \r
186 \r
187   public void keyPressed(KeyEvent evt)\r
188   {\r
189     if (viewport.cursorMode\r
190         && evt.getKeyCode() >= KeyEvent.VK_0\r
191         && evt.getKeyCode() <= KeyEvent.VK_9)\r
192     {\r
193       alignPanel.seqPanel.numberPressed(evt.getKeyChar());\r
194     }\r
195 \r
196     switch (evt.getKeyCode())\r
197     {\r
198       case 27: // escape key\r
199         deselectAllSequenceMenuItem_actionPerformed();\r
200         break;\r
201       case KeyEvent.VK_X:\r
202         if (evt.isControlDown() || evt.isMetaDown())\r
203         {\r
204           cut_actionPerformed();\r
205         }\r
206         break;\r
207       case KeyEvent.VK_C:\r
208         if (viewport.cursorMode && !evt.isControlDown())\r
209         {\r
210           alignPanel.seqPanel.setCursorColumn();\r
211         }\r
212         if (evt.isControlDown() || evt.isMetaDown())\r
213         {\r
214           copy_actionPerformed();\r
215         }\r
216         break;\r
217       case KeyEvent.VK_V:\r
218         if (evt.isControlDown() || evt.isMetaDown())\r
219         {\r
220           paste(true);\r
221         }\r
222         break;\r
223       case KeyEvent.VK_A:\r
224         if (evt.isControlDown() || evt.isMetaDown())\r
225         {\r
226           selectAllSequenceMenuItem_actionPerformed();\r
227         }\r
228         break;\r
229       case KeyEvent.VK_DOWN:\r
230         if(viewport.cursorMode)\r
231         {\r
232           alignPanel.seqPanel.moveCursor(0,1);\r
233         }\r
234         else\r
235           moveSelectedSequences(false);\r
236         break;\r
237 \r
238       case KeyEvent.VK_UP:\r
239         if (viewport.cursorMode)\r
240         {\r
241           alignPanel.seqPanel.moveCursor(0,-1);\r
242         }\r
243         else\r
244           moveSelectedSequences(true);\r
245         break;\r
246 \r
247       case KeyEvent.VK_LEFT:\r
248         if(viewport.cursorMode)\r
249         {\r
250           alignPanel.seqPanel.moveCursor(-1,0);\r
251         }\r
252         break;\r
253 \r
254       case KeyEvent.VK_RIGHT:\r
255         if (viewport.cursorMode)\r
256         {\r
257           alignPanel.seqPanel.moveCursor(1,0);\r
258         }\r
259         break;\r
260       case KeyEvent.VK_SPACE:\r
261         if(viewport.cursorMode)\r
262         {\r
263           alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown());\r
264         }\r
265         break;\r
266 \r
267       case KeyEvent.VK_DELETE:\r
268       case KeyEvent.VK_BACK_SPACE:\r
269         if(viewport.cursorMode)\r
270         {\r
271           alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown());\r
272         }\r
273        else\r
274         {\r
275           cut_actionPerformed();\r
276           alignPanel.seqPanel.seqCanvas.repaint();\r
277         }\r
278         break;\r
279 \r
280       case KeyEvent.VK_S:\r
281         if(viewport.cursorMode)\r
282         {\r
283           alignPanel.seqPanel.setCursorRow();\r
284         }\r
285         break;\r
286       case KeyEvent.VK_P:\r
287         if(viewport.cursorMode)\r
288         {\r
289           alignPanel.seqPanel.setCursorPosition();\r
290         }\r
291         break;\r
292 \r
293       case KeyEvent.VK_ENTER:\r
294       case KeyEvent.VK_COMMA:\r
295         if(viewport.cursorMode)\r
296         {\r
297           alignPanel.seqPanel.setCursorRowAndColumn();\r
298         }\r
299         break;\r
300 \r
301       case KeyEvent.VK_Q:\r
302         if(viewport.cursorMode)\r
303         {\r
304           alignPanel.seqPanel.setSelectionAreaAtCursor(true);\r
305         }\r
306         break;\r
307       case KeyEvent.VK_M:\r
308         if(viewport.cursorMode)\r
309         {\r
310           alignPanel.seqPanel.setSelectionAreaAtCursor(false);\r
311         }\r
312         break;\r
313 \r
314      case KeyEvent.VK_F2:\r
315        viewport.cursorMode = ! viewport.cursorMode;\r
316        statusBar.setText("Keyboard editing mode is "+\r
317            (viewport.cursorMode ? "on" : "off"));\r
318        if(viewport.cursorMode)\r
319        {\r
320          alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;\r
321          alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;\r
322        }\r
323        alignPanel.seqPanel.seqCanvas.repaint();\r
324        break;\r
325 \r
326       case KeyEvent.VK_F:\r
327         if (evt.isControlDown())\r
328         {\r
329           findMenuItem_actionPerformed();\r
330         }\r
331         break;\r
332       case KeyEvent.VK_H:\r
333       {\r
334         boolean toggleSeqs = !evt.isControlDown();\r
335         boolean toggleCols = !evt.isShiftDown();\r
336         boolean hide = false;\r
337         SequenceGroup sg = viewport.getSelectionGroup();\r
338 \r
339         if(toggleSeqs)\r
340         {\r
341           if (sg != null && sg.getSize(false) != viewport.alignment.getHeight())\r
342           {\r
343             hide = true;\r
344             viewport.hideAllSelectedSeqs();\r
345           }\r
346           else if (!(toggleCols && viewport.colSel.getSelected().size() > 0))\r
347             viewport.showAllHiddenSeqs();\r
348         }\r
349 \r
350         if(toggleCols)\r
351         {\r
352           if (viewport.colSel.getSelected().size() > 0)\r
353           {\r
354             viewport.hideSelectedColumns();\r
355             if(!toggleSeqs)\r
356                    viewport.selectionGroup = sg;\r
357           }\r
358           else if (!hide)\r
359             viewport.showAllHiddenColumns();\r
360         }\r
361 \r
362         alignPanel.repaint();\r
363         break;\r
364       }\r
365 \r
366     }\r
367   }\r
368   public void keyReleased(KeyEvent evt)\r
369   {}\r
370   public void keyTyped(KeyEvent evt)\r
371   {}\r
372 \r
373 public void itemStateChanged(ItemEvent evt)\r
374   {\r
375     if(evt.getSource()==colourTextMenuItem)\r
376             colourTextMenuItem_actionPerformed();\r
377     else if(evt.getSource()==wrapMenuItem)\r
378             wrapMenuItem_actionPerformed();\r
379     else if(evt.getSource()==scaleAbove)\r
380             scaleAbove_actionPerformed();\r
381     else if(evt.getSource()==scaleLeft)\r
382             scaleLeft_actionPerformed();\r
383     else if(evt.getSource()==scaleRight)\r
384             scaleRight_actionPerformed();\r
385      else if(evt.getSource()==seqLimits)\r
386       seqLimits_itemStateChanged();\r
387     else if(evt.getSource()==viewBoxesMenuItem)\r
388             viewBoxesMenuItem_actionPerformed();\r
389     else if(evt.getSource()==viewTextMenuItem)\r
390             viewTextMenuItem_actionPerformed();\r
391     else if(evt.getSource()==renderGapsMenuItem)\r
392             renderGapsMenuItem_actionPerformed();\r
393     else if(evt.getSource()==annotationPanelMenuItem)\r
394             annotationPanelMenuItem_actionPerformed();\r
395       else if(evt.getSource()==sequenceFeatures)\r
396       {\r
397            viewport.showSequenceFeatures(sequenceFeatures.getState());\r
398             alignPanel.seqPanel.seqCanvas.repaint();\r
399       }\r
400       else if(evt.getSource()==conservationMenuItem)\r
401             conservationMenuItem_actionPerformed();\r
402       else if(evt.getSource()==abovePIDThreshold)\r
403             abovePIDThreshold_actionPerformed();\r
404           else if(evt.getSource()==applyToAllGroups)\r
405             applyToAllGroups_actionPerformed();\r
406       else if(evt.getSource()==autoCalculate)\r
407           viewport.autocalculateConsensus = autoCalculate.getState();\r
408   }\r
409  public void actionPerformed(ActionEvent evt)\r
410  {\r
411     Object source = evt.getSource();\r
412 \r
413     if(source==inputText)\r
414       inputText_actionPerformed();\r
415     else if(source==loadTree)\r
416       loadTree_actionPerformed();\r
417     else if(source==loadApplication)\r
418       launchFullApplication();\r
419     else if(source==closeMenuItem)\r
420       closeMenuItem_actionPerformed();\r
421     else if(source==copy)\r
422       copy_actionPerformed();\r
423     else if(source==undoMenuItem)\r
424       undoMenuItem_actionPerformed();\r
425     else if(source==redoMenuItem)\r
426       redoMenuItem_actionPerformed();\r
427     else if(source==inputText)\r
428             inputText_actionPerformed();\r
429     else if(source==closeMenuItem)\r
430             closeMenuItem_actionPerformed();\r
431     else if(source==undoMenuItem)\r
432             undoMenuItem_actionPerformed();\r
433     else if(source==redoMenuItem)\r
434             redoMenuItem_actionPerformed();\r
435     else if(source==copy)\r
436             copy_actionPerformed();\r
437     else if(source==pasteNew)\r
438             pasteNew_actionPerformed();\r
439     else if(source==pasteThis)\r
440             pasteThis_actionPerformed();\r
441     else if(source==cut)\r
442             cut_actionPerformed();\r
443     else if(source==delete)\r
444             delete_actionPerformed();\r
445     else if(source==deleteGroups)\r
446             deleteGroups_actionPerformed();\r
447     else if(source==selectAllSequenceMenuItem)\r
448             selectAllSequenceMenuItem_actionPerformed();\r
449     else if(source==deselectAllSequenceMenuItem)\r
450             deselectAllSequenceMenuItem_actionPerformed();\r
451     else if(source==invertSequenceMenuItem)\r
452             invertSequenceMenuItem_actionPerformed();\r
453     else if(source==invertColSel)\r
454     { viewport.invertColumnSelection(); alignPanel.repaint(); }\r
455     else if(source==remove2LeftMenuItem)\r
456             remove2LeftMenuItem_actionPerformed();\r
457     else if(source==remove2RightMenuItem)\r
458             remove2RightMenuItem_actionPerformed();\r
459     else if(source==removeGappedColumnMenuItem)\r
460             removeGappedColumnMenuItem_actionPerformed();\r
461     else if(source==removeAllGapsMenuItem)\r
462             removeAllGapsMenuItem_actionPerformed();\r
463     else if(source==findMenuItem)\r
464             findMenuItem_actionPerformed();\r
465     else if(source==font)\r
466             font_actionPerformed();\r
467     else if(source==showColumns)\r
468     {\r
469       viewport.showAllHiddenColumns(); alignPanel.repaint();\r
470     }\r
471     else if(source==showSeqs)\r
472     {\r
473       viewport.showAllHiddenSeqs();\r
474     }\r
475     else if(source == hideColumns)\r
476     {\r
477       viewport.hideSelectedColumns(); alignPanel.repaint();\r
478     }\r
479     else if(source == hideSequences && viewport.getSelectionGroup()!=null)\r
480     {\r
481       viewport.hideAllSelectedSeqs();\r
482     }\r
483     else if(source==featureSettings)\r
484             featureSettings_actionPerformed();\r
485     else if(source==overviewMenuItem)\r
486             overviewMenuItem_actionPerformed();\r
487     else if(source==noColourmenuItem)\r
488             noColourmenuItem_actionPerformed();\r
489     else if(source==clustalColour)\r
490             clustalColour_actionPerformed();\r
491     else if(source==zappoColour)\r
492             zappoColour_actionPerformed();\r
493     else if(source==taylorColour)\r
494             taylorColour_actionPerformed();\r
495     else if(source==hydrophobicityColour)\r
496             hydrophobicityColour_actionPerformed();\r
497     else if(source==helixColour)\r
498             helixColour_actionPerformed();\r
499     else if(source==strandColour)\r
500             strandColour_actionPerformed();\r
501     else if(source==turnColour)\r
502             turnColour_actionPerformed();\r
503     else if(source==buriedColour)\r
504             buriedColour_actionPerformed();\r
505     else if(source==nucleotideColour)\r
506             nucleotideColour_actionPerformed();\r
507     else if(source==modifyPID)\r
508             modifyPID_actionPerformed();\r
509     else if(source==modifyConservation)\r
510             modifyConservation_actionPerformed();\r
511     else if(source==userDefinedColour)\r
512             userDefinedColour_actionPerformed();\r
513     else if(source==PIDColour)\r
514             PIDColour_actionPerformed();\r
515     else if(source==BLOSUM62Colour)\r
516             BLOSUM62Colour_actionPerformed();\r
517     else if(source==annotationColour)\r
518            new AnnotationColourChooser(viewport, alignPanel);\r
519     else if(source==sortPairwiseMenuItem)\r
520             sortPairwiseMenuItem_actionPerformed();\r
521     else if(source==sortIDMenuItem)\r
522             sortIDMenuItem_actionPerformed();\r
523     else if(source==sortGroupMenuItem)\r
524             sortGroupMenuItem_actionPerformed();\r
525     else if(source==removeRedundancyMenuItem)\r
526             removeRedundancyMenuItem_actionPerformed();\r
527     else if(source==pairwiseAlignmentMenuItem)\r
528             pairwiseAlignmentMenuItem_actionPerformed();\r
529     else if(source==PCAMenuItem)\r
530             PCAMenuItem_actionPerformed();\r
531     else if(source==averageDistanceTreeMenuItem)\r
532             averageDistanceTreeMenuItem_actionPerformed();\r
533     else if(source==neighbourTreeMenuItem)\r
534             neighbourTreeMenuItem_actionPerformed();\r
535     else if(source==njTreeBlosumMenuItem)\r
536             njTreeBlosumMenuItem_actionPerformed();\r
537     else if(source==avDistanceTreeBlosumMenuItem)\r
538             avTreeBlosumMenuItem_actionPerformed();\r
539     else if(source==documentation)\r
540             documentation_actionPerformed();\r
541     else if(source==about)\r
542             about_actionPerformed();\r
543 \r
544  }\r
545 \r
546   public void inputText_actionPerformed()\r
547   {\r
548     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
549     Frame frame = new Frame();\r
550     frame.add(cap);\r
551     jalview.bin.JalviewLite.addFrame(frame, "Cut & Paste Input", 500, 500);\r
552   }\r
553 \r
554   protected void outputText_actionPerformed(ActionEvent e)\r
555   {\r
556     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this);\r
557     Frame frame = new Frame();\r
558     frame.add(cap);\r
559     jalview.bin.JalviewLite.addFrame(frame,\r
560                                      "Alignment output - " + e.getActionCommand(),\r
561                                      600, 500);\r
562     cap.setText(new AppletFormatAdapter().formatSequences(e.getActionCommand(),\r
563                                               viewport.getAlignment().getSequences(),\r
564                                                       viewport.showJVSuffix));\r
565   }\r
566 \r
567   void launchFullApplication()\r
568   {\r
569     StringBuffer url = new StringBuffer(jalviewServletURL);\r
570 \r
571     url.append("?open="+\r
572                appendProtocol( viewport.applet.getParameter("file") ) );\r
573 \r
574     if(viewport.applet.getParameter("features")!=null)\r
575     {\r
576       url.append( "&features=" );\r
577       url.append( appendProtocol( viewport.applet.getParameter("features") ) );\r
578     }\r
579 \r
580     if(viewport.applet.getParameter("annotations")!=null)\r
581     {\r
582       url.append( "&annotations=" );\r
583       url.append( appendProtocol( viewport.applet.getParameter("annotations") ) );\r
584     }\r
585 \r
586     if(viewport.applet.getParameter("jnetfile")!=null)\r
587     {\r
588       url.append( "&annotations=" );\r
589       url.append( appendProtocol( viewport.applet.getParameter("jnetfile") ) );\r
590     }\r
591 \r
592     if(viewport.applet.getParameter("defaultColour")!=null)\r
593     {\r
594       url.append("&colour=" +\r
595                  removeWhiteSpace(viewport.applet.getParameter("defaultColour"))\r
596           );\r
597     }\r
598 \r
599     if(viewport.applet.getParameter("userDefinedColour")!=null)\r
600     {\r
601       url.append( "&colour=" +\r
602                  removeWhiteSpace( viewport.applet.getParameter("userDefinedColour") )\r
603          );\r
604     }\r
605 \r
606     showURL(url.toString(), "FULL_APP");\r
607   }\r
608 \r
609 \r
610   String removeWhiteSpace(String colour)\r
611   {\r
612     StringBuffer sb = new StringBuffer();\r
613     for (int i = 0; i < colour.length(); i++)\r
614     {\r
615       if (Character.isWhitespace(colour.charAt(i)))\r
616         sb.append("%20");\r
617       else\r
618         sb.append(colour.charAt(i));\r
619     }\r
620 \r
621     return sb.toString();\r
622   }\r
623 \r
624 \r
625   String appendProtocol(String url)\r
626   {\r
627     try{\r
628        new URL(url);\r
629     }catch(java.net.MalformedURLException ex)\r
630     {\r
631       url = viewport.applet.getCodeBase()+url;\r
632     }\r
633     return url;\r
634   }\r
635 \r
636   public void closeMenuItem_actionPerformed()\r
637   {\r
638     PaintRefresher.components.remove(viewport.alignment);\r
639     if(PaintRefresher.components.size()==0 && viewport.applet==null)\r
640       System.exit(0);\r
641 \r
642     this.dispose();\r
643   }\r
644 \r
645   Stack historyList = new Stack();\r
646   Stack redoList = new Stack();\r
647 \r
648   void updateEditMenuBar()\r
649   {\r
650     if (historyList.size() > 0)\r
651     {\r
652       undoMenuItem.setEnabled(true);\r
653       HistoryItem hi = (HistoryItem) historyList.peek();\r
654       undoMenuItem.setLabel("Undo " + hi.getDescription());\r
655     }\r
656     else\r
657     {\r
658       undoMenuItem.setEnabled(false);\r
659       undoMenuItem.setLabel("Undo");\r
660     }\r
661 \r
662     if (redoList.size() > 0)\r
663     {\r
664       redoMenuItem.setEnabled(true);\r
665       HistoryItem hi = (HistoryItem) redoList.peek();\r
666       redoMenuItem.setLabel("Redo " + hi.getDescription());\r
667     }\r
668     else\r
669     {\r
670       redoMenuItem.setEnabled(false);\r
671       redoMenuItem.setLabel("Redo");\r
672     }\r
673   }\r
674 \r
675   public void addHistoryItem(HistoryItem hi)\r
676   {\r
677     historyList.push(hi);\r
678     redoList.removeAllElements();\r
679     updateEditMenuBar();\r
680   }\r
681 \r
682   protected void undoMenuItem_actionPerformed()\r
683   {\r
684     HistoryItem nh,hi = (HistoryItem) historyList.pop();\r
685     redoList.push(nh=new HistoryItem(hi.getDescription(), viewport.alignment,\r
686                                   HistoryItem.HIDE));\r
687     if (hi.alColumnChanges!=null)\r
688       nh.alColumnChanges=hi.alColumnChanges.getInverse();\r
689     restoreHistoryItem(hi);\r
690     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
691   }\r
692 \r
693   protected void redoMenuItem_actionPerformed()\r
694   {\r
695     HistoryItem nh,hi = (HistoryItem) redoList.pop();\r
696     historyList.push(nh=new HistoryItem(hi.getDescription(), viewport.alignment,\r
697                                   HistoryItem.HIDE));\r
698     if (hi.alColumnChanges!=null)\r
699       nh.alColumnChanges=hi.alColumnChanges.getInverse();\r
700     restoreHistoryItem(hi);\r
701     updateEditMenuBar();\r
702     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
703   }\r
704 \r
705   // used by undo and redo\r
706   void restoreHistoryItem(HistoryItem hi)\r
707   {\r
708     hi.restore(viewport.getColumnSelection());\r
709     updateEditMenuBar();\r
710 \r
711     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
712   }\r
713 \r
714   public void moveSelectedSequences(boolean up)\r
715   {\r
716     SequenceGroup sg = viewport.getSelectionGroup();\r
717     if (sg == null)\r
718     {\r
719       return;\r
720     }\r
721 \r
722     if (up)\r
723     {\r
724       for (int i = 1; i < viewport.alignment.getHeight(); i++)\r
725       {\r
726         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
727         if (!sg.getSequences(false).contains(seq))\r
728         {\r
729           continue;\r
730         }\r
731 \r
732         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);\r
733         if (sg.getSequences(false).contains(temp))\r
734         {\r
735           continue;\r
736         }\r
737 \r
738         viewport.alignment.getSequences().setElementAt(temp, i);\r
739         viewport.alignment.getSequences().setElementAt(seq, i - 1);\r
740       }\r
741     }\r
742     else\r
743     {\r
744       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)\r
745       {\r
746         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
747         if (!sg.getSequences(true).contains(seq))\r
748         {\r
749           continue;\r
750         }\r
751 \r
752         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);\r
753         if (sg.getSequences(true).contains(temp))\r
754         {\r
755           continue;\r
756         }\r
757 \r
758         viewport.alignment.getSequences().setElementAt(temp, i);\r
759         viewport.alignment.getSequences().setElementAt(seq, i + 1);\r
760       }\r
761     }\r
762 \r
763     alignPanel.repaint();\r
764   }\r
765 \r
766   static StringBuffer copiedSequences;\r
767   static Vector copiedHiddenColumns;\r
768   protected void copy_actionPerformed()\r
769   {\r
770     if (viewport.getSelectionGroup() == null)\r
771     {\r
772       return;\r
773     }\r
774 \r
775     SequenceGroup sg = viewport.getSelectionGroup();\r
776     copiedSequences = new StringBuffer();\r
777     Hashtable orderedSeqs = new Hashtable();\r
778     for (int i = 0; i < sg.getSize(false); i++)\r
779     {\r
780       SequenceI seq = sg.getSequenceAt(i);\r
781       int index = viewport.alignment.findIndex(seq);\r
782       orderedSeqs.put(index + "", seq);\r
783     }\r
784 \r
785     int index = 0, startRes, endRes;\r
786     char ch;\r
787 \r
788     if (viewport.hasHiddenColumns && viewport.getSelectionGroup() != null)\r
789     {\r
790       copiedHiddenColumns = new Vector();\r
791       int hiddenOffset = viewport.getSelectionGroup().getStartRes();\r
792       for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns().size();\r
793            i++)\r
794       {\r
795         int[] region = (int[])\r
796             viewport.getColumnSelection().getHiddenColumns().elementAt(i);\r
797 \r
798         copiedHiddenColumns.addElement(new int[]\r
799                                  {region[0] - hiddenOffset,\r
800                                  region[1] - hiddenOffset});\r
801       }\r
802     }\r
803     else\r
804       copiedHiddenColumns = null;\r
805 \r
806 \r
807     for (int i = 0; i < sg.getSize(false); i++)\r
808     {\r
809         SequenceI seq = null;\r
810 \r
811         while (seq == null)\r
812         {\r
813             if (orderedSeqs.containsKey(index + ""))\r
814             {\r
815                 seq = (SequenceI) orderedSeqs.get(index + "");\r
816                 index++;\r
817 \r
818                 break;\r
819             }\r
820             else\r
821             {\r
822                 index++;\r
823             }\r
824         }\r
825 \r
826         //FIND START RES\r
827         //Returns residue following index if gap\r
828         startRes = seq.findPosition(sg.getStartRes());\r
829 \r
830         //FIND END RES\r
831         //Need to find the residue preceeding index if gap\r
832         endRes = 0;\r
833 \r
834         for (int j = 0; j < sg.getEndRes()+1 && j < seq.getLength(); j++)\r
835         {\r
836           ch = seq.getCharAt(j);\r
837           if (!jalview.util.Comparison.isGap( (ch)))\r
838           {\r
839             endRes++;\r
840           }\r
841         }\r
842 \r
843         if(endRes>0)\r
844         {\r
845           endRes += seq.getStart() -1;\r
846         }\r
847 \r
848         copiedSequences.append(seq.getName() + "\t" +\r
849             startRes + "\t" +\r
850             endRes + "\t" +\r
851             seq.getSequence(sg.getStartRes(),\r
852                 sg.getEndRes() + 1) + "\n");\r
853     }\r
854 \r
855   }\r
856 \r
857   protected void pasteNew_actionPerformed()\r
858   {\r
859     paste(true);\r
860   }\r
861 \r
862   protected void pasteThis_actionPerformed()\r
863   {\r
864     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment,\r
865                                    HistoryItem.PASTE));\r
866     paste(false);\r
867   }\r
868 \r
869   void paste(boolean newAlignment)\r
870   {\r
871     try\r
872     {\r
873       if (copiedSequences == null)\r
874       {\r
875         return;\r
876       }\r
877 \r
878       StringTokenizer st = new StringTokenizer(copiedSequences.toString());\r
879       Vector seqs = new Vector();\r
880       while (st.hasMoreElements())\r
881       {\r
882         String name = st.nextToken();\r
883         int start = Integer.parseInt(st.nextToken());\r
884         int end = Integer.parseInt(st.nextToken());\r
885         Sequence sequence = new Sequence(name, st.nextToken(), start, end);\r
886 \r
887         if (!newAlignment)\r
888         {\r
889           viewport.alignment.addSequence(sequence);\r
890         }\r
891         else\r
892         {\r
893           seqs.addElement(sequence);\r
894         }\r
895       }\r
896 \r
897       if (newAlignment)\r
898       {\r
899         SequenceI[] newSeqs = new SequenceI[seqs.size()];\r
900         for (int i = 0; i < seqs.size(); i++)\r
901         {\r
902           newSeqs[i] = (SequenceI) seqs.elementAt(i);\r
903         }\r
904 \r
905         String newtitle = new String("Copied sequences");\r
906         if (getTitle().startsWith("Copied sequences"))\r
907         {\r
908           newtitle = getTitle();\r
909         }\r
910         else\r
911         {\r
912           newtitle = newtitle.concat("- from " + getTitle());\r
913         }\r
914         AlignFrame af = new AlignFrame(new Alignment(newSeqs),\r
915                                        viewport.applet,\r
916                                        newtitle,\r
917                                        false);\r
918         if (copiedHiddenColumns != null)\r
919         {\r
920           for (int i = 0; i < copiedHiddenColumns.size(); i++)\r
921           {\r
922             int[] region = (int[]) copiedHiddenColumns.elementAt(i);\r
923             af.viewport.hideColumns(region[0], region[1]);\r
924           }\r
925         }\r
926 \r
927 \r
928         jalview.bin.JalviewLite.addFrame(af, newtitle, NEW_WINDOW_WIDTH,\r
929                                          NEW_WINDOW_HEIGHT);\r
930       }\r
931       else\r
932       {\r
933         viewport.setEndSeq(viewport.alignment.getHeight());\r
934         viewport.alignment.getWidth();\r
935         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
936       }\r
937 \r
938     }\r
939     catch (Exception ex)\r
940     {} // could be anything being pasted in here\r
941 \r
942   }\r
943 \r
944   protected void cut_actionPerformed()\r
945   {\r
946     copy_actionPerformed();\r
947     delete_actionPerformed();\r
948   }\r
949 \r
950   protected void delete_actionPerformed()\r
951   {\r
952     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment,\r
953                                    HistoryItem.HIDE));\r
954     if (viewport.getSelectionGroup() == null)\r
955     {\r
956       return;\r
957     }\r
958 \r
959 \r
960     SequenceGroup sg = viewport.getSelectionGroup();\r
961     boolean allSequences = false;\r
962     if(sg.getSize(false)==viewport.alignment.getHeight())\r
963           allSequences = true;\r
964 \r
965     for (int i = 0; i < sg.getSize(false); i++)\r
966     {\r
967       SequenceI seq = sg.getSequenceAt(i);\r
968       int index = viewport.getAlignment().findIndex(seq);\r
969       seq.deleteChars(sg.getStartRes(), sg.getEndRes() + 1);\r
970 \r
971       // If the cut affects all sequences, remove highlighted columns\r
972       if (allSequences)\r
973       {\r
974         viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
975                                                      sg.getEndRes() + 1);\r
976       }\r
977 \r
978 \r
979       if (seq.getSequence().length() < 1)\r
980       {\r
981         viewport.getAlignment().deleteSequence(seq);\r
982       }\r
983       else\r
984       {\r
985         viewport.getAlignment().getSequences().setElementAt(seq, index);\r
986       }\r
987     }\r
988 \r
989     viewport.setSelectionGroup(null);\r
990     viewport.alignment.deleteGroup(sg);\r
991     viewport.resetSeqLimits(alignPanel.seqPanel.seqCanvas.getSize().height);\r
992     if (viewport.getAlignment().getHeight() < 1)\r
993     {\r
994       try\r
995       {\r
996         this.setVisible(false);\r
997       }\r
998       catch (Exception ex)\r
999       {}\r
1000     }\r
1001     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1002 \r
1003   }\r
1004 \r
1005   protected void deleteGroups_actionPerformed()\r
1006   {\r
1007     viewport.alignment.deleteAllGroups();\r
1008     viewport.setSelectionGroup(null);\r
1009 \r
1010     alignPanel.repaint();\r
1011   }\r
1012 \r
1013   public void selectAllSequenceMenuItem_actionPerformed()\r
1014   {\r
1015     SequenceGroup sg = new SequenceGroup();\r
1016     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
1017     {\r
1018       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
1019     }\r
1020     sg.setEndRes(viewport.alignment.getWidth()-1);\r
1021     viewport.setSelectionGroup(sg);\r
1022     alignPanel.repaint();\r
1023     PaintRefresher.Refresh(null, viewport.alignment);\r
1024   }\r
1025 \r
1026   public void deselectAllSequenceMenuItem_actionPerformed()\r
1027   {\r
1028     if(viewport.cursorMode)\r
1029     {\r
1030       alignPanel.seqPanel.keyboardNo1=null;\r
1031       alignPanel.seqPanel.keyboardNo2=null;\r
1032     }\r
1033     viewport.setSelectionGroup(null);\r
1034     viewport.getColumnSelection().clear();\r
1035     viewport.setSelectionGroup(null);\r
1036     alignPanel.idPanel.idCanvas.searchResults = null;\r
1037     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);\r
1038     alignPanel.repaint();\r
1039     PaintRefresher.Refresh(null, viewport.alignment);\r
1040   }\r
1041 \r
1042   public void invertSequenceMenuItem_actionPerformed()\r
1043   {\r
1044     SequenceGroup sg = viewport.getSelectionGroup();\r
1045     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
1046     {\r
1047       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
1048     }\r
1049 \r
1050     PaintRefresher.Refresh(null, viewport.alignment);\r
1051   }\r
1052 \r
1053   public void remove2LeftMenuItem_actionPerformed()\r
1054   {\r
1055     ColumnSelection colSel = viewport.getColumnSelection();\r
1056     if (colSel.size() > 0)\r
1057     {\r
1058       HistoryItem edit;\r
1059       addHistoryItem(edit=new HistoryItem("Remove Left", viewport.alignment,\r
1060                                      HistoryItem.HIDE));\r
1061       int min = colSel.getMin();\r
1062       viewport.getAlignment().trimLeft(min);\r
1063       colSel.compensateForEdit(0, min);\r
1064       edit.addShift(0, min);\r
1065       if (viewport.getSelectionGroup() != null)\r
1066       {\r
1067         viewport.getSelectionGroup().adjustForRemoveLeft(min);\r
1068       }\r
1069 \r
1070       Vector groups = viewport.alignment.getGroups();\r
1071       for (int i = 0; i < groups.size(); i++)\r
1072       {\r
1073         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
1074         if (!sg.adjustForRemoveLeft(min))\r
1075         {\r
1076           viewport.alignment.deleteGroup(sg);\r
1077         }\r
1078       }\r
1079       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1080     }\r
1081   }\r
1082 \r
1083   public void remove2RightMenuItem_actionPerformed()\r
1084   {\r
1085     ColumnSelection colSel = viewport.getColumnSelection();\r
1086     if (colSel.size() > 0)\r
1087     {\r
1088       addHistoryItem(new HistoryItem("Remove Right", viewport.alignment,\r
1089                                      HistoryItem.HIDE));\r
1090       int max = colSel.getMax();\r
1091       viewport.getAlignment().trimRight(max);\r
1092 \r
1093       if (viewport.getSelectionGroup() != null)\r
1094       {\r
1095         viewport.getSelectionGroup().adjustForRemoveRight(max);\r
1096       }\r
1097 \r
1098       Vector groups = viewport.alignment.getGroups();\r
1099       for (int i = 0; i < groups.size(); i++)\r
1100       {\r
1101         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
1102         if (!sg.adjustForRemoveRight(max))\r
1103         {\r
1104           viewport.alignment.deleteGroup(sg);\r
1105         }\r
1106       }\r
1107       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1108     }\r
1109 \r
1110   }\r
1111 \r
1112   public void removeGappedColumnMenuItem_actionPerformed()\r
1113   {\r
1114     HistoryItem edit;\r
1115     addHistoryItem(edit=new HistoryItem("Remove Gapped Columns",\r
1116                                    viewport.alignment,\r
1117                                    HistoryItem.HIDE));\r
1118 \r
1119     //This is to maintain viewport position on first residue\r
1120     //of first sequence\r
1121     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
1122     int startRes = seq.findPosition(viewport.startRes);\r
1123 \r
1124     viewport.getAlignment().removeGaps();\r
1125 \r
1126     viewport.setStartRes(seq.findIndex(startRes)-1);\r
1127 \r
1128     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1129   }\r
1130 \r
1131   public void removeAllGapsMenuItem_actionPerformed()\r
1132   {\r
1133     // TODO: hidden regions should not be touched by removeAllGaps - a minimal number of gaps will remain in alignment segments containing uneven length subsequences\r
1134     // TODO: columnSelection.compensateforedits should be called (and passed to history item)\r
1135     HistoryItem editgaps;\r
1136     addHistoryItem(editgaps=new HistoryItem("Remove Gaps", viewport.alignment,\r
1137                                    HistoryItem.HIDE));\r
1138 \r
1139     //This is to maintain viewport position on first residue\r
1140     //of first sequence\r
1141     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
1142     int startRes = seq.findPosition(viewport.startRes);\r
1143 \r
1144     SequenceI current;\r
1145     Vector seqs=null;\r
1146 \r
1147     int start=0, end = viewport.alignment.getWidth();\r
1148 \r
1149     if (viewport.getSelectionGroup() != null\r
1150         && viewport.getSelectionGroup().getSequences(false) != null\r
1151         && viewport.getSelectionGroup().getSize(false)>0)\r
1152     {\r
1153       seqs = viewport.getSelectionGroup().getSequences(true);\r
1154       start = viewport.getSelectionGroup().getStartRes();\r
1155       end = viewport.getSelectionGroup().getEndRes()+1;\r
1156     }\r
1157     else\r
1158       seqs = viewport.alignment.getSequences();\r
1159 \r
1160     /* Commented out regions below are partial implementation of todo above.\r
1161      * divide start,end into visible chunks, and for each:\r
1162      int diff=end-start+1;\r
1163      int diffmax=0;\r
1164      int dr[] = new int[seqs.size()];\r
1165      */\r
1166     for (int i = 0; i < seqs.size(); i++)\r
1167     {\r
1168       current = (SequenceI) seqs.elementAt(i);\r
1169       //dr[i]=\r
1170       current.removeGaps(start, end);\r
1171       /*if (d<diff) // can only shift\r
1172         diff=d;\r
1173       if (diffmax<d)\r
1174         diffmax=d;\r
1175         */\r
1176     }\r
1177     /* // after the end of each chunk -\r
1178      * if (diff>0) {\r
1179      // record shift for history.\r
1180       editgaps.addShift(start, diff);\r
1181       if (viewport.hasHiddenColumns && diffmax>diff) {\r
1182       // pad sequence\r
1183        StringBuffer gaps=new StringBuffer(diffmax);\r
1184        for (int i=0,j=diffmax-diff; i<j; i++)\r
1185        gaps.append(viewport.getGapCharacter());\r
1186        for (int i=0, j=seqs.size(); i<j; i++) {\r
1187        current = (SequenceI) seqs.elementAt(i);\r
1188        if (dr[i]-diff>0) {\r
1189        String sq = current.getSequence();\r
1190        current.setSequence(sq.substring(0, hcend-dr[i])+gaps.substring(0, dr[i]-diff)+sq.substring());\r
1191        }\r
1192        }\r
1193       }\r
1194       }*/\r
1195 \r
1196     viewport.setStartRes(seq.findIndex(startRes)-1);\r
1197     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1198   }\r
1199 \r
1200   public void alignmentChanged()\r
1201   {\r
1202     viewport.alignment.padGaps();\r
1203     if(viewport.autocalculateConsensus)\r
1204     {\r
1205       viewport.updateConsensus();\r
1206       viewport.updateConservation();\r
1207     }\r
1208 \r
1209     resetAllColourSchemes();\r
1210     if(alignPanel.overviewPanel!=null)\r
1211       alignPanel.overviewPanel.updateOverviewImage();\r
1212 \r
1213     viewport.alignment.adjustSequenceAnnotations();\r
1214     alignPanel.repaint();\r
1215   }\r
1216 \r
1217   void resetAllColourSchemes()\r
1218   {\r
1219     ColourSchemeI cs = viewport.globalColourScheme;\r
1220     if(cs!=null)\r
1221     {\r
1222       if (cs instanceof ClustalxColourScheme)\r
1223       {\r
1224         ( (ClustalxColourScheme) viewport.getGlobalColourScheme()).\r
1225             resetClustalX(viewport.alignment.getSequences(),\r
1226                           viewport.alignment.getWidth());\r
1227       }\r
1228 \r
1229       cs.setConsensus(viewport.vconsensus);\r
1230       if (cs.conservationApplied())\r
1231       {\r
1232         Alignment al = (Alignment) viewport.alignment;\r
1233         Conservation c = new Conservation("All",\r
1234                                           ResidueProperties.propHash, 3,\r
1235                                           al.getSequences(), 0,\r
1236                                           al.getWidth() - 1);\r
1237         c.calculate();\r
1238         c.verdict(false, viewport.ConsPercGaps);\r
1239 \r
1240         cs.setConservation(c);\r
1241       }\r
1242     }\r
1243 \r
1244     int s, sSize = viewport.alignment.getGroups().size();\r
1245     for(s=0; s<sSize; s++)\r
1246     {\r
1247       SequenceGroup sg = (SequenceGroup)viewport.alignment.getGroups().elementAt(s);\r
1248       if(sg.cs!=null && sg.cs instanceof ClustalxColourScheme)\r
1249       {\r
1250         ((ClustalxColourScheme)sg.cs).resetClustalX(\r
1251             sg.getSequences(true), sg.getWidth());\r
1252       }\r
1253       sg.recalcConservation();\r
1254     }\r
1255   }\r
1256 \r
1257 \r
1258 \r
1259   public void findMenuItem_actionPerformed()\r
1260   {\r
1261     new Finder(alignPanel);\r
1262   }\r
1263 \r
1264   public void font_actionPerformed()\r
1265   {\r
1266     new FontChooser(alignPanel);\r
1267   }\r
1268 \r
1269 \r
1270   public void seqLimits_itemStateChanged()\r
1271   {\r
1272     viewport.setShowJVSuffix(seqLimits.getState());\r
1273     alignPanel.fontChanged();\r
1274     alignPanel.repaint();\r
1275   }\r
1276 \r
1277 \r
1278   protected void colourTextMenuItem_actionPerformed()\r
1279   {\r
1280     viewport.setColourText(colourTextMenuItem.getState());\r
1281     alignPanel.repaint();\r
1282   }\r
1283 \r
1284   protected void wrapMenuItem_actionPerformed()\r
1285   {\r
1286     viewport.setWrapAlignment(wrapMenuItem.getState());\r
1287     alignPanel.setWrapAlignment(wrapMenuItem.getState());\r
1288     scaleAbove.setEnabled(wrapMenuItem.getState());\r
1289     scaleLeft.setEnabled(wrapMenuItem.getState());\r
1290     scaleRight.setEnabled(wrapMenuItem.getState());\r
1291     alignPanel.repaint();\r
1292   }\r
1293 \r
1294 \r
1295   protected void scaleAbove_actionPerformed()\r
1296   {\r
1297     viewport.setScaleAboveWrapped(scaleAbove.getState());\r
1298     alignPanel.repaint();\r
1299   }\r
1300 \r
1301   protected void scaleLeft_actionPerformed()\r
1302   {\r
1303     viewport.setScaleLeftWrapped(scaleLeft.getState());\r
1304     alignPanel.repaint();\r
1305   }\r
1306 \r
1307   protected void scaleRight_actionPerformed()\r
1308   {\r
1309     viewport.setScaleRightWrapped(scaleRight.getState());\r
1310     alignPanel.repaint();\r
1311   }\r
1312 \r
1313   public void viewBoxesMenuItem_actionPerformed()\r
1314   {\r
1315     viewport.setShowBoxes(viewBoxesMenuItem.getState());\r
1316     alignPanel.repaint();\r
1317   }\r
1318 \r
1319   public void viewTextMenuItem_actionPerformed()\r
1320   {\r
1321     viewport.setShowText(viewTextMenuItem.getState());\r
1322     alignPanel.repaint();\r
1323   }\r
1324 \r
1325   protected void renderGapsMenuItem_actionPerformed()\r
1326   {\r
1327     viewport.setRenderGaps(renderGapsMenuItem.getState());\r
1328     alignPanel.repaint();\r
1329   }\r
1330 \r
1331   public void annotationPanelMenuItem_actionPerformed()\r
1332   {\r
1333     viewport.setShowAnnotation(annotationPanelMenuItem.getState());\r
1334     alignPanel.setAnnotationVisible(annotationPanelMenuItem.getState());\r
1335   }\r
1336 \r
1337   public void featureSettings_actionPerformed()\r
1338   {\r
1339     new FeatureSettings(viewport, alignPanel);\r
1340   }\r
1341 \r
1342   public void overviewMenuItem_actionPerformed()\r
1343   {\r
1344     if (alignPanel.overviewPanel != null)\r
1345     {\r
1346       return;\r
1347     }\r
1348 \r
1349     Frame frame = new Frame();\r
1350     OverviewPanel overview = new OverviewPanel(alignPanel);\r
1351     frame.add(overview);\r
1352     // +50 must allow for applet frame window\r
1353     jalview.bin.JalviewLite.addFrame(frame, "Overview " + this.getTitle(),\r
1354                                      overview.preferredSize().width,\r
1355                                      overview.preferredSize().height + 50);\r
1356 \r
1357     frame.pack();\r
1358     frame.addWindowListener(new WindowAdapter()\r
1359     {\r
1360       public void windowClosing(WindowEvent e)\r
1361       {\r
1362         alignPanel.setOverviewPanel(null);\r
1363       };\r
1364     });\r
1365 \r
1366     alignPanel.setOverviewPanel(overview);\r
1367 \r
1368   }\r
1369 \r
1370   protected void noColourmenuItem_actionPerformed()\r
1371   {\r
1372     changeColour(null);\r
1373   }\r
1374 \r
1375   public void clustalColour_actionPerformed()\r
1376   {\r
1377     abovePIDThreshold.setState(false);\r
1378     changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(),\r
1379                                           viewport.alignment.getWidth()));\r
1380   }\r
1381 \r
1382   public void zappoColour_actionPerformed()\r
1383   {\r
1384     changeColour(new ZappoColourScheme());\r
1385   }\r
1386 \r
1387   public void taylorColour_actionPerformed()\r
1388   {\r
1389     changeColour(new TaylorColourScheme());\r
1390   }\r
1391 \r
1392   public void hydrophobicityColour_actionPerformed()\r
1393   {\r
1394     changeColour(new HydrophobicColourScheme());\r
1395   }\r
1396 \r
1397   public void helixColour_actionPerformed()\r
1398   {\r
1399     changeColour(new HelixColourScheme());\r
1400   }\r
1401 \r
1402   public void strandColour_actionPerformed()\r
1403   {\r
1404     changeColour(new StrandColourScheme());\r
1405   }\r
1406 \r
1407   public void turnColour_actionPerformed()\r
1408   {\r
1409     changeColour(new TurnColourScheme());\r
1410   }\r
1411 \r
1412   public void buriedColour_actionPerformed()\r
1413   {\r
1414     changeColour(new BuriedColourScheme());\r
1415   }\r
1416 \r
1417   public void nucleotideColour_actionPerformed()\r
1418   {\r
1419     changeColour(new NucleotideColourScheme());\r
1420   }\r
1421 \r
1422   protected void applyToAllGroups_actionPerformed()\r
1423   {\r
1424     viewport.setColourAppliesToAllGroups(applyToAllGroups.getState());\r
1425   }\r
1426 \r
1427   void changeColour(ColourSchemeI cs)\r
1428   {\r
1429     int threshold = 0;\r
1430 \r
1431     if(cs!=null)\r
1432     {\r
1433       if (viewport.getAbovePIDThreshold())\r
1434       {\r
1435         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");\r
1436 \r
1437         cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
1438 \r
1439         viewport.setGlobalColourScheme(cs);\r
1440       }\r
1441       else\r
1442       {\r
1443         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1444       }\r
1445 \r
1446       if (viewport.getConservationSelected())\r
1447       {\r
1448 \r
1449         Alignment al = (Alignment) viewport.alignment;\r
1450         Conservation c = new Conservation("All",\r
1451                                           ResidueProperties.propHash, 3,\r
1452                                           al.getSequences(), 0,\r
1453                                           al.getWidth() - 1);\r
1454 \r
1455         c.calculate();\r
1456         c.verdict(false, viewport.ConsPercGaps);\r
1457 \r
1458         cs.setConservation(c);\r
1459 \r
1460         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,\r
1461             "Background"));\r
1462 \r
1463       }\r
1464       else\r
1465       {\r
1466         cs.setConservation(null);\r
1467       }\r
1468 \r
1469       cs.setConsensus(viewport.vconsensus);\r
1470 \r
1471     }\r
1472     viewport.setGlobalColourScheme(cs);\r
1473 \r
1474     if (viewport.getColourAppliesToAllGroups())\r
1475     {\r
1476       Vector groups = viewport.alignment.getGroups();\r
1477       for (int i = 0; i < groups.size(); i++)\r
1478       {\r
1479         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
1480 \r
1481         if(cs==null)\r
1482         {\r
1483           sg.cs = null;\r
1484           continue;\r
1485         }\r
1486         if (cs instanceof ClustalxColourScheme)\r
1487         {\r
1488           sg.cs = new ClustalxColourScheme(sg.getSequences(true), sg.getWidth());\r
1489         }\r
1490         else\r
1491         {\r
1492           try\r
1493           {\r
1494             sg.cs = (ColourSchemeI) cs.getClass().newInstance();\r
1495           }\r
1496           catch (Exception ex)\r
1497           {\r
1498             ex.printStackTrace();\r
1499             sg.cs = cs;\r
1500           }\r
1501         }\r
1502 \r
1503         if (viewport.getAbovePIDThreshold()\r
1504             || cs instanceof PIDColourScheme\r
1505             || cs instanceof Blosum62ColourScheme)\r
1506         {\r
1507           sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
1508           sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(true), 0, sg.getWidth()));\r
1509         }\r
1510         else\r
1511           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1512 \r
1513         if (viewport.getConservationSelected())\r
1514         {\r
1515           Conservation c = new Conservation("Group",\r
1516                                             ResidueProperties.propHash, 3,\r
1517                                             sg.getSequences(true), 0,\r
1518                                             viewport.alignment.getWidth() - 1);\r
1519           c.calculate();\r
1520           c.verdict(false, viewport.ConsPercGaps);\r
1521           sg.cs.setConservation(c);\r
1522         }\r
1523         else\r
1524         {\r
1525           sg.cs.setConservation(null);\r
1526           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1527         }\r
1528 \r
1529       }\r
1530     }\r
1531 \r
1532 \r
1533     if (alignPanel.getOverviewPanel() != null)\r
1534     {\r
1535       alignPanel.getOverviewPanel().updateOverviewImage();\r
1536     }\r
1537 \r
1538     alignPanel.repaint();\r
1539   }\r
1540 \r
1541 \r
1542 \r
1543   protected void modifyPID_actionPerformed()\r
1544   {\r
1545     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)\r
1546     {\r
1547       SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),\r
1548                                      "Background");\r
1549       SliderPanel.showPIDSlider();\r
1550     }\r
1551   }\r
1552 \r
1553   protected void modifyConservation_actionPerformed()\r
1554   {\r
1555     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)\r
1556     {\r
1557       SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,\r
1558                                         "Background");\r
1559       SliderPanel.showConservationSlider();\r
1560     }\r
1561   }\r
1562 \r
1563   protected void conservationMenuItem_actionPerformed()\r
1564   {\r
1565     viewport.setConservationSelected(conservationMenuItem.getState());\r
1566 \r
1567     viewport.setAbovePIDThreshold(false);\r
1568     abovePIDThreshold.setState(false);\r
1569 \r
1570     changeColour(viewport.getGlobalColourScheme());\r
1571 \r
1572     modifyConservation_actionPerformed();\r
1573   }\r
1574 \r
1575   public void abovePIDThreshold_actionPerformed()\r
1576   {\r
1577     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());\r
1578 \r
1579     conservationMenuItem.setState(false);\r
1580     viewport.setConservationSelected(false);\r
1581 \r
1582     changeColour(viewport.getGlobalColourScheme());\r
1583 \r
1584     modifyPID_actionPerformed();\r
1585   }\r
1586 \r
1587   public void userDefinedColour_actionPerformed()\r
1588   {\r
1589     new UserDefinedColours(alignPanel, null);\r
1590   }\r
1591 \r
1592   public void PIDColour_actionPerformed()\r
1593   {\r
1594     changeColour(new PIDColourScheme());\r
1595   }\r
1596 \r
1597   public void BLOSUM62Colour_actionPerformed()\r
1598   {\r
1599     changeColour(new Blosum62ColourScheme());\r
1600   }\r
1601 \r
1602   public void sortPairwiseMenuItem_actionPerformed()\r
1603   {\r
1604     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment,\r
1605                                    HistoryItem.SORT));\r
1606     AlignmentSorter.sortByPID(viewport.getAlignment(),\r
1607                               viewport.getAlignment().getSequenceAt(0));\r
1608     alignPanel.repaint();\r
1609   }\r
1610 \r
1611   public void sortIDMenuItem_actionPerformed()\r
1612   {\r
1613     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment,\r
1614                                    HistoryItem.SORT));\r
1615     AlignmentSorter.sortByID(viewport.getAlignment());\r
1616     alignPanel.repaint();\r
1617   }\r
1618 \r
1619   public void sortGroupMenuItem_actionPerformed()\r
1620   {\r
1621     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment,\r
1622                                    HistoryItem.SORT));\r
1623     AlignmentSorter.sortByGroup(viewport.getAlignment());\r
1624     alignPanel.repaint();\r
1625 \r
1626   }\r
1627 \r
1628   public void removeRedundancyMenuItem_actionPerformed()\r
1629   {\r
1630      new RedundancyPanel(alignPanel);\r
1631   }\r
1632 \r
1633   public void pairwiseAlignmentMenuItem_actionPerformed()\r
1634   {\r
1635     if (viewport.getSelectionGroup()!=null\r
1636         && viewport.getSelectionGroup().getSize(false) > 1)\r
1637     {\r
1638       Frame frame = new Frame();\r
1639       frame.add(new PairwiseAlignPanel(alignPanel));\r
1640       jalview.bin.JalviewLite.addFrame(frame, "Pairwise Alignment", 600, 500);\r
1641     }\r
1642   }\r
1643 \r
1644   public void PCAMenuItem_actionPerformed()\r
1645   {\r
1646     //are the sequences aligned?\r
1647     if (!viewport.alignment.isAligned())\r
1648     {\r
1649       SequenceI current;\r
1650       int Width = viewport.getAlignment().getWidth();\r
1651 \r
1652       for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1653            i++)\r
1654       {\r
1655         current = viewport.getAlignment().getSequenceAt(i);\r
1656 \r
1657         if (current.getLength() < Width)\r
1658         {\r
1659           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1660         }\r
1661       }\r
1662       alignPanel.repaint();\r
1663     }\r
1664 \r
1665     if ( (viewport.getSelectionGroup() != null &&\r
1666           viewport.getSelectionGroup().getSize(false) < 4 &&\r
1667           viewport.getSelectionGroup().getSize(false) > 0)\r
1668         || viewport.getAlignment().getHeight() < 4)\r
1669     {\r
1670       return;\r
1671     }\r
1672 \r
1673     try\r
1674     {\r
1675       new PCAPanel(viewport);\r
1676     }\r
1677     catch (java.lang.OutOfMemoryError ex)\r
1678     {\r
1679     }\r
1680 \r
1681   }\r
1682 \r
1683   public void averageDistanceTreeMenuItem_actionPerformed()\r
1684   {\r
1685     NewTreePanel("AV", "PID", "Average distance tree using PID");\r
1686   }\r
1687 \r
1688   public void neighbourTreeMenuItem_actionPerformed()\r
1689   {\r
1690     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
1691   }\r
1692 \r
1693   protected void njTreeBlosumMenuItem_actionPerformed()\r
1694   {\r
1695     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
1696   }\r
1697 \r
1698   protected void avTreeBlosumMenuItem_actionPerformed()\r
1699   {\r
1700     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62PID");\r
1701   }\r
1702 \r
1703   void NewTreePanel(String type, String pwType, String title)\r
1704   {\r
1705     //are the sequences aligned?\r
1706     if (!viewport.alignment.isAligned())\r
1707     {\r
1708       SequenceI current;\r
1709       int Width = viewport.getAlignment().getWidth();\r
1710 \r
1711       for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1712            i++)\r
1713       {\r
1714         current = viewport.getAlignment().getSequenceAt(i);\r
1715 \r
1716         if (current.getLength() < Width)\r
1717         {\r
1718           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1719         }\r
1720       }\r
1721       alignPanel.repaint();\r
1722 \r
1723     }\r
1724 \r
1725     if ( (viewport.getSelectionGroup() != null &&\r
1726           viewport.getSelectionGroup().getSize(false) > 1)\r
1727       || (viewport.getSelectionGroup() == null\r
1728           && viewport.alignment.getHeight() > 1))\r
1729     {\r
1730       final TreePanel tp = new TreePanel(viewport,\r
1731                                          type,\r
1732                                          pwType);\r
1733 \r
1734       addTreeMenuItem(tp, title);\r
1735 \r
1736       jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);\r
1737     }\r
1738   }\r
1739 \r
1740   void loadTree_actionPerformed()\r
1741   {\r
1742       CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);\r
1743       cap.setText("Paste your Newick tree file here.");\r
1744       cap.treeImport = true;\r
1745       Frame frame = new Frame();\r
1746       frame.add(cap);\r
1747       jalview.bin.JalviewLite.addFrame(frame, "Paste Newick file ", 400, 300);\r
1748   }\r
1749 \r
1750   public void loadTree(jalview.io.NewickFile tree, String treeFile)\r
1751   {\r
1752     TreePanel tp = new TreePanel(viewport,\r
1753                                  treeFile,\r
1754                                  "From File - ",\r
1755                                  tree);\r
1756     jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);\r
1757     addTreeMenuItem(tp, treeFile);\r
1758   }\r
1759 \r
1760   void addTreeMenuItem(final TreePanel treePanel, String title)\r
1761   {\r
1762     final MenuItem item = new MenuItem(title);\r
1763     sortByTreeMenu.add(item);\r
1764     item.addActionListener(new java.awt.event.ActionListener()\r
1765     {\r
1766       public void actionPerformed(ActionEvent evt)\r
1767       {\r
1768         addHistoryItem(new HistoryItem("Sort", viewport.alignment,\r
1769                                        HistoryItem.SORT));\r
1770         AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());\r
1771         alignPanel.repaint();\r
1772       }\r
1773     });\r
1774 \r
1775     treePanel.addWindowListener(new WindowAdapter()\r
1776     {\r
1777       public void windowClosing(WindowEvent e)\r
1778       {\r
1779         sortByTreeMenu.remove(item);\r
1780       };\r
1781     });\r
1782   }\r
1783 \r
1784   protected void documentation_actionPerformed()\r
1785   {\r
1786     showURL("http://www.jalview.org/help.html", "HELP");\r
1787   }\r
1788 \r
1789   protected void about_actionPerformed()\r
1790   {\r
1791 \r
1792     class AboutPanel extends Canvas\r
1793     {\r
1794       String version;\r
1795       public AboutPanel(String version)\r
1796       { this.version = version; }\r
1797 \r
1798       public void paint(Graphics g)\r
1799       {\r
1800         g.setColor(Color.white);\r
1801         g.fillRect(0, 0, getSize().width, getSize().height);\r
1802         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
1803         FontMetrics fm = g.getFontMetrics();\r
1804         int fh = fm.getHeight();\r
1805         int y = 5, x = 7;\r
1806         g.setColor(Color.black);\r
1807         g.setFont(new Font("Helvetica", Font.BOLD, 14));\r
1808         g.drawString("Jalview - Release "+version, 200, y += fh);\r
1809         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
1810         g.drawString("Authors:  Michele Clamp, James Cuff, Steve Searle, Andrew Waterhouse, Jim Procter & Geoff Barton.",\r
1811                      x, y += fh * 2);\r
1812         g.drawString("Current development managed by Andrew Waterhouse; Barton Group, University of Dundee.",\r
1813                      x, y += fh);\r
1814         g.drawString(\r
1815             "For any issues relating to Jalview, email help@jalview.org", x,\r
1816             y += fh);\r
1817         g.drawString("If  you use JalView, please cite:", x, y += fh + 8);\r
1818         g.drawString("\"Clamp, M., Cuff, J., Searle, S. M. and Barton, G. J. (2004), The Jalview Java Alignment Editor\"",\r
1819                      x, y += fh);\r
1820         g.drawString("Bioinformatics,  2004 20;426-7.", x, y += fh);\r
1821       }\r
1822     }\r
1823 \r
1824     String version = "test";\r
1825     java.net.URL url = getClass().getResource("/.build_properties");\r
1826     if (url != null)\r
1827     {\r
1828       try\r
1829       {\r
1830         BufferedReader reader = new BufferedReader(new InputStreamReader(\r
1831             url.openStream()));\r
1832         String line;\r
1833         while ( (line = reader.readLine()) != null)\r
1834         {\r
1835           if (line.indexOf("VERSION") > -1)\r
1836           {\r
1837             version = line.substring(line.indexOf("=") + 1);\r
1838           }\r
1839         }\r
1840       }\r
1841       catch (Exception ex)\r
1842       {\r
1843         ex.printStackTrace();\r
1844       }\r
1845     }\r
1846 \r
1847 \r
1848     Frame frame = new Frame();\r
1849     frame.add(new AboutPanel(version));\r
1850     jalview.bin.JalviewLite.addFrame(frame, "Jalview", 580, 200);\r
1851 \r
1852   }\r
1853 \r
1854   public void showURL(String url, String target)\r
1855   {\r
1856     if (viewport.applet == null)\r
1857     {\r
1858       System.out.println("Not running as applet - no browser available.");\r
1859     }\r
1860     else\r
1861     {\r
1862       try\r
1863       {\r
1864         System.out.println("Show url: "+url);\r
1865         viewport.applet.getAppletContext().showDocument(new java.net.URL(url),\r
1866                                                target);\r
1867       }\r
1868       catch (Exception ex)\r
1869       {\r
1870         ex.printStackTrace();\r
1871       }\r
1872     }\r
1873   }\r
1874 \r
1875 \r
1876   //////////////////////////////////////////////////////////////////////////////////\r
1877   //JBuilder Graphics here\r
1878 \r
1879     protected MenuBar alignFrameMenuBar = new MenuBar();\r
1880     protected Menu fileMenu = new Menu("File");\r
1881     protected MenuItem loadApplication = new MenuItem("View in Full Application");\r
1882     protected MenuItem loadTree = new MenuItem("Load Associated Tree");\r
1883     protected MenuItem closeMenuItem = new MenuItem("Close");\r
1884     protected Menu editMenu = new Menu("Edit");\r
1885     protected Menu viewMenu = new Menu("View");\r
1886     protected Menu colourMenu = new Menu("Colour");\r
1887     protected Menu calculateMenu = new Menu("Calculate");\r
1888     protected MenuItem selectAllSequenceMenuItem = new MenuItem("Select all");\r
1889     protected MenuItem deselectAllSequenceMenuItem = new MenuItem("Deselect All");\r
1890     protected MenuItem invertSequenceMenuItem = new MenuItem("Invert Selection");\r
1891     protected MenuItem remove2LeftMenuItem = new MenuItem();\r
1892     protected MenuItem remove2RightMenuItem = new MenuItem();\r
1893     protected MenuItem removeGappedColumnMenuItem = new MenuItem();\r
1894     protected MenuItem removeAllGapsMenuItem = new MenuItem();\r
1895     protected CheckboxMenuItem viewBoxesMenuItem = new CheckboxMenuItem();\r
1896     protected CheckboxMenuItem viewTextMenuItem = new CheckboxMenuItem();\r
1897     protected MenuItem sortPairwiseMenuItem = new MenuItem();\r
1898     protected MenuItem sortIDMenuItem = new MenuItem();\r
1899     protected MenuItem sortGroupMenuItem = new MenuItem();\r
1900     protected MenuItem removeRedundancyMenuItem = new MenuItem();\r
1901     protected MenuItem pairwiseAlignmentMenuItem = new MenuItem();\r
1902     protected MenuItem PCAMenuItem = new MenuItem();\r
1903     protected MenuItem averageDistanceTreeMenuItem = new MenuItem();\r
1904     protected MenuItem neighbourTreeMenuItem = new MenuItem();\r
1905     BorderLayout borderLayout1 = new BorderLayout();\r
1906     public Label statusBar = new Label();\r
1907     protected Menu outputTextboxMenu = new Menu();\r
1908     protected MenuItem clustalColour = new MenuItem();\r
1909     protected MenuItem zappoColour = new MenuItem();\r
1910     protected MenuItem taylorColour = new MenuItem();\r
1911     protected MenuItem hydrophobicityColour = new MenuItem();\r
1912     protected MenuItem helixColour = new MenuItem();\r
1913     protected MenuItem strandColour = new MenuItem();\r
1914     protected MenuItem turnColour = new MenuItem();\r
1915     protected MenuItem buriedColour = new MenuItem();\r
1916     protected MenuItem userDefinedColour = new MenuItem();\r
1917     protected MenuItem PIDColour = new MenuItem();\r
1918     protected MenuItem BLOSUM62Colour = new MenuItem();\r
1919     MenuItem njTreeBlosumMenuItem = new MenuItem();\r
1920     MenuItem avDistanceTreeBlosumMenuItem = new MenuItem();\r
1921     protected CheckboxMenuItem annotationPanelMenuItem = new CheckboxMenuItem();\r
1922     protected CheckboxMenuItem colourTextMenuItem = new CheckboxMenuItem();\r
1923     MenuItem overviewMenuItem = new MenuItem();\r
1924     protected MenuItem undoMenuItem = new MenuItem();\r
1925     protected MenuItem redoMenuItem = new MenuItem();\r
1926     protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();\r
1927     MenuItem noColourmenuItem = new MenuItem();\r
1928     protected CheckboxMenuItem wrapMenuItem = new CheckboxMenuItem();\r
1929     protected CheckboxMenuItem renderGapsMenuItem = new CheckboxMenuItem();\r
1930     MenuItem findMenuItem = new MenuItem();\r
1931     Menu searchMenu = new Menu();\r
1932     protected CheckboxMenuItem abovePIDThreshold = new CheckboxMenuItem();\r
1933     protected MenuItem nucleotideColour = new MenuItem();\r
1934     MenuItem deleteGroups = new MenuItem();\r
1935     MenuItem delete = new MenuItem();\r
1936     MenuItem copy = new MenuItem();\r
1937     MenuItem cut = new MenuItem();\r
1938     Menu pasteMenu = new Menu();\r
1939     MenuItem pasteNew = new MenuItem();\r
1940     MenuItem pasteThis = new MenuItem();\r
1941     protected CheckboxMenuItem applyToAllGroups = new CheckboxMenuItem();\r
1942     protected MenuItem font = new MenuItem();\r
1943     protected CheckboxMenuItem scaleAbove = new CheckboxMenuItem();\r
1944     protected CheckboxMenuItem scaleLeft = new CheckboxMenuItem();\r
1945     protected CheckboxMenuItem scaleRight = new CheckboxMenuItem();\r
1946     MenuItem modifyPID = new MenuItem();\r
1947     MenuItem modifyConservation = new MenuItem();\r
1948     protected CheckboxMenuItem autoCalculate\r
1949         = new CheckboxMenuItem("Autocalculate Consensus", true);\r
1950     protected Menu sortByTreeMenu = new Menu();\r
1951     Menu sort = new Menu();\r
1952     Menu calculate = new Menu();\r
1953     MenuItem inputText = new MenuItem();\r
1954     Menu helpMenu = new Menu();\r
1955     MenuItem documentation = new MenuItem();\r
1956     MenuItem about = new MenuItem();\r
1957     protected CheckboxMenuItem seqLimits = new CheckboxMenuItem();\r
1958   Panel embeddedMenu;\r
1959   Label embeddedEdit;\r
1960   Label embeddedSearch;\r
1961   Label embeddedView;\r
1962   Label embeddedColour;\r
1963   Label embeddedFile;\r
1964   Label embeddedHelp;\r
1965   Label embeddedCalculate;\r
1966   FlowLayout flowLayout1;\r
1967 \r
1968   private void jbInit() throws Exception {\r
1969 \r
1970       setMenuBar(alignFrameMenuBar);\r
1971 \r
1972       MenuItem item;\r
1973 \r
1974       // dynamically fill save as menu with available formats\r
1975       for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++)\r
1976       {\r
1977 \r
1978         item = new MenuItem( jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]);\r
1979 \r
1980         item.addActionListener(new java.awt.event.ActionListener()\r
1981         {\r
1982           public void actionPerformed(ActionEvent e)\r
1983           {\r
1984             outputText_actionPerformed(e);\r
1985           }\r
1986         });\r
1987 \r
1988         outputTextboxMenu.add(item);\r
1989       }\r
1990         closeMenuItem.addActionListener(this);\r
1991         loadApplication.addActionListener(this);\r
1992 \r
1993         loadTree.addActionListener(this);\r
1994         selectAllSequenceMenuItem.addActionListener(this);\r
1995         deselectAllSequenceMenuItem.addActionListener(this);\r
1996         invertSequenceMenuItem.addActionListener(this);\r
1997         remove2LeftMenuItem.setLabel("Remove Left");\r
1998         remove2LeftMenuItem.addActionListener(this);\r
1999         remove2RightMenuItem.setLabel("Remove Right");\r
2000         remove2RightMenuItem.addActionListener(this);\r
2001         removeGappedColumnMenuItem.setLabel("Remove Empty Columns");\r
2002         removeGappedColumnMenuItem.addActionListener(this);\r
2003         removeAllGapsMenuItem.setLabel("Remove All Gaps");\r
2004         removeAllGapsMenuItem.addActionListener(this);\r
2005         viewBoxesMenuItem.setLabel("Boxes");\r
2006         viewBoxesMenuItem.setState(true);\r
2007         viewBoxesMenuItem.addItemListener(this);\r
2008         viewTextMenuItem.setLabel("Text");\r
2009         viewTextMenuItem.setState(true);\r
2010         viewTextMenuItem.addItemListener(this);\r
2011         sortPairwiseMenuItem.setLabel("by Pairwise Identity");\r
2012         sortPairwiseMenuItem.addActionListener(this);\r
2013         sortIDMenuItem.setLabel("by ID");\r
2014         sortIDMenuItem.addActionListener(this);\r
2015         sortGroupMenuItem.setLabel("by Group");\r
2016         sortGroupMenuItem.addActionListener(this);\r
2017         removeRedundancyMenuItem.setLabel("Remove Redundancy...");\r
2018         removeRedundancyMenuItem.addActionListener(this);\r
2019         pairwiseAlignmentMenuItem.setLabel("Pairwise Alignments...");\r
2020         pairwiseAlignmentMenuItem.addActionListener(this);\r
2021         PCAMenuItem.setLabel("Principal Component Analysis");\r
2022         PCAMenuItem.addActionListener(this);\r
2023         averageDistanceTreeMenuItem.setLabel(\r
2024             "Average Distance Using % Identity");\r
2025         averageDistanceTreeMenuItem.addActionListener(this);\r
2026         neighbourTreeMenuItem.setLabel("Neighbour Joining Using % Identity");\r
2027         neighbourTreeMenuItem.addActionListener(this);\r
2028         alignFrameMenuBar.setFont(new java.awt.Font("Verdana", 0, 11));\r
2029         statusBar.setBackground(Color.white);\r
2030         statusBar.setFont(new java.awt.Font("Verdana", 0, 11));\r
2031         statusBar.setText("Status bar");\r
2032         outputTextboxMenu.setLabel("Output to Textbox");\r
2033         clustalColour.setLabel("Clustalx");\r
2034 \r
2035         clustalColour.addActionListener(this);\r
2036         zappoColour.setLabel("Zappo");\r
2037         zappoColour.addActionListener(this);\r
2038         taylorColour.setLabel("Taylor");\r
2039         taylorColour.addActionListener(this);\r
2040         hydrophobicityColour.setLabel("Hydrophobicity");\r
2041         hydrophobicityColour.addActionListener(this);\r
2042         helixColour.setLabel("Helix Propensity");\r
2043         helixColour.addActionListener(this);\r
2044         strandColour.setLabel("Strand Propensity");\r
2045         strandColour.addActionListener(this);\r
2046         turnColour.setLabel("Turn Propensity");\r
2047         turnColour.addActionListener(this);\r
2048         buriedColour.setLabel("Buried Index");\r
2049         buriedColour.addActionListener(this);\r
2050         userDefinedColour.setLabel("User Defined...");\r
2051         userDefinedColour.addActionListener(this);\r
2052         PIDColour.setLabel("Percentage Identity");\r
2053         PIDColour.addActionListener(this);\r
2054         BLOSUM62Colour.setLabel("BLOSUM62 Score");\r
2055         BLOSUM62Colour.addActionListener(this);\r
2056         avDistanceTreeBlosumMenuItem.setLabel(\r
2057             "Average Distance Using BLOSUM62");\r
2058         avDistanceTreeBlosumMenuItem.addActionListener(this);\r
2059         njTreeBlosumMenuItem.setLabel("Neighbour Joining Using BLOSUM62");\r
2060         njTreeBlosumMenuItem.addActionListener(this);\r
2061         annotationPanelMenuItem.setLabel("Show Annotations");\r
2062         annotationPanelMenuItem.addItemListener(this);\r
2063         colourTextMenuItem.setLabel("Colour Text");\r
2064         colourTextMenuItem.addItemListener(this);\r
2065         overviewMenuItem.setLabel("Overview Window");\r
2066         overviewMenuItem.addActionListener(this);\r
2067         undoMenuItem.setEnabled(false);\r
2068         undoMenuItem.setLabel("Undo");\r
2069         undoMenuItem.addActionListener(this);\r
2070         redoMenuItem.setEnabled(false);\r
2071         redoMenuItem.setLabel("Redo");\r
2072         redoMenuItem.addActionListener(this);\r
2073         conservationMenuItem.setLabel("by Conservation");\r
2074         conservationMenuItem.addItemListener(this);\r
2075         noColourmenuItem.setLabel("None");\r
2076         noColourmenuItem.addActionListener(this);\r
2077         wrapMenuItem.setLabel("Wrap");\r
2078         wrapMenuItem.addItemListener(this);\r
2079         renderGapsMenuItem.setLabel("Show Gaps");\r
2080         renderGapsMenuItem.setState(true);\r
2081         renderGapsMenuItem.addItemListener(this);\r
2082         findMenuItem.setLabel("Find...");\r
2083         findMenuItem.addActionListener(this);\r
2084         searchMenu.setLabel("Search");\r
2085 \r
2086         abovePIDThreshold.setLabel("Above Identity Threshold");\r
2087         abovePIDThreshold.addItemListener(this);\r
2088         nucleotideColour.setLabel("Nucleotide");\r
2089         nucleotideColour.addActionListener(this);\r
2090         deleteGroups.setLabel("Undefine Groups");\r
2091         deleteGroups.addActionListener(this);\r
2092         copy.setLabel("Copy");\r
2093         copy.addActionListener(this);\r
2094         cut.setLabel("Cut");\r
2095         cut.addActionListener(this);\r
2096         delete.setLabel("Delete");\r
2097         delete.addActionListener(this);\r
2098         pasteMenu.setLabel("Paste");\r
2099         pasteNew.setLabel("To New Alignment");\r
2100         pasteNew.addActionListener(this);\r
2101         pasteThis.setLabel("Add To This Alignment");\r
2102         pasteThis.addActionListener(this);\r
2103         applyToAllGroups.setLabel("Apply Colour To All Groups");\r
2104         applyToAllGroups.setState(true);\r
2105         applyToAllGroups.addItemListener(this);\r
2106         font.setLabel("Font...");\r
2107         font.addActionListener(this);\r
2108         scaleAbove.setLabel("Scale Above");\r
2109         scaleAbove.setState(true);\r
2110         scaleAbove.setEnabled(false);\r
2111         scaleAbove.addItemListener(this);\r
2112         scaleLeft.setEnabled(false);\r
2113         scaleLeft.setState(true);\r
2114         scaleLeft.setLabel("Scale Left");\r
2115         scaleLeft.addItemListener(this);\r
2116         scaleRight.setEnabled(false);\r
2117         scaleRight.setState(true);\r
2118         scaleRight.setLabel("Scale Right");\r
2119         scaleRight.addItemListener(this);\r
2120         modifyPID.setLabel("Modify Identity Threshold...");\r
2121         modifyPID.addActionListener(this);\r
2122         modifyConservation.setLabel("Modify Conservation Threshold...");\r
2123         modifyConservation.addActionListener(this);\r
2124         sortByTreeMenu.setLabel("By Tree Order");\r
2125         sort.setLabel("Sort");\r
2126         calculate.setLabel("Calculate Tree");\r
2127         autoCalculate.addItemListener(this);\r
2128         inputText.setLabel("Input from textbox");\r
2129         inputText.addActionListener(this);\r
2130 \r
2131         helpMenu.setLabel("Help");\r
2132         documentation.setLabel("Documentation");\r
2133         documentation.addActionListener(this);\r
2134 \r
2135         about.setLabel("About...");\r
2136         about.addActionListener(this);\r
2137           seqLimits.setState(true);\r
2138     seqLimits.setLabel("Show Sequence Limits");\r
2139     seqLimits.addItemListener(this);\r
2140     featureSettings.setLabel("Feature Settings...");\r
2141     featureSettings.addActionListener(this);\r
2142     sequenceFeatures.setLabel("Sequence Features");\r
2143     sequenceFeatures.addItemListener(this);\r
2144     sequenceFeatures.setState(false);\r
2145     annotationColour.setLabel("by Annotation...");\r
2146     annotationColour.addActionListener(this);\r
2147     invertSequenceMenuItem.setLabel("Invert Sequence Selection");\r
2148     invertColSel.setLabel("Invert Column Selection");\r
2149     menu1.setLabel("Show");\r
2150     showColumns.setLabel("All Columns ");\r
2151     showSeqs.setLabel("All Sequences");\r
2152     menu2.setLabel("Hide");\r
2153     hideColumns.setLabel("Selected Columns");\r
2154     hideSequences.setLabel("Selected Sequences");\r
2155     invertColSel.addActionListener(this);\r
2156     showColumns.addActionListener(this);\r
2157     showSeqs.addActionListener(this);\r
2158     hideColumns.addActionListener(this);\r
2159     hideSequences.addActionListener(this);\r
2160 \r
2161 \r
2162     alignFrameMenuBar.add(fileMenu);\r
2163         alignFrameMenuBar.add(editMenu);\r
2164         alignFrameMenuBar.add(searchMenu);\r
2165         alignFrameMenuBar.add(viewMenu);\r
2166         alignFrameMenuBar.add(colourMenu);\r
2167         alignFrameMenuBar.add(calculateMenu);\r
2168         alignFrameMenuBar.add(helpMenu);\r
2169         fileMenu.add(inputText);\r
2170         fileMenu.add(outputTextboxMenu);\r
2171         if(jalviewServletURL!=null)\r
2172           fileMenu.add(loadApplication);\r
2173         fileMenu.addSeparator();\r
2174         fileMenu.add(loadTree);\r
2175         fileMenu.add(closeMenuItem);\r
2176         editMenu.add(undoMenuItem);\r
2177         editMenu.add(redoMenuItem);\r
2178         editMenu.add(cut);\r
2179         editMenu.add(copy);\r
2180         editMenu.add(pasteMenu);\r
2181         editMenu.add(delete);\r
2182         editMenu.addSeparator();\r
2183         editMenu.add(selectAllSequenceMenuItem);\r
2184         editMenu.add(deselectAllSequenceMenuItem);\r
2185         editMenu.add(invertSequenceMenuItem);\r
2186     editMenu.add(invertColSel);\r
2187     editMenu.add(deleteGroups);\r
2188         editMenu.addSeparator();\r
2189         editMenu.add(remove2LeftMenuItem);\r
2190         editMenu.add(remove2RightMenuItem);\r
2191         editMenu.add(removeGappedColumnMenuItem);\r
2192         editMenu.add(removeAllGapsMenuItem);\r
2193         editMenu.add(removeRedundancyMenuItem);\r
2194         searchMenu.add(findMenuItem);\r
2195         viewMenu.add(font);\r
2196         viewMenu.addSeparator();\r
2197     viewMenu.add(menu1);\r
2198     viewMenu.add(menu2);\r
2199     viewMenu.addSeparator();\r
2200     viewMenu.add(wrapMenuItem);\r
2201         viewMenu.add(scaleAbove);\r
2202         viewMenu.add(scaleLeft);\r
2203         viewMenu.add(scaleRight);\r
2204         viewMenu.addSeparator();\r
2205     viewMenu.add(seqLimits);\r
2206     viewMenu.add(viewBoxesMenuItem);\r
2207         viewMenu.add(viewTextMenuItem);\r
2208         viewMenu.add(colourTextMenuItem);\r
2209         viewMenu.add(renderGapsMenuItem);\r
2210         viewMenu.add(annotationPanelMenuItem);\r
2211     viewMenu.addSeparator();\r
2212         viewMenu.add(sequenceFeatures);\r
2213         viewMenu.add(featureSettings);\r
2214     viewMenu.addSeparator();\r
2215         viewMenu.add(overviewMenuItem);\r
2216         colourMenu.add(applyToAllGroups);\r
2217         colourMenu.addSeparator();\r
2218         colourMenu.add(noColourmenuItem);\r
2219         colourMenu.add(clustalColour);\r
2220         colourMenu.add(BLOSUM62Colour);\r
2221         colourMenu.add(PIDColour);\r
2222         colourMenu.add(zappoColour);\r
2223         colourMenu.add(taylorColour);\r
2224         colourMenu.add(hydrophobicityColour);\r
2225         colourMenu.add(helixColour);\r
2226         colourMenu.add(strandColour);\r
2227         colourMenu.add(turnColour);\r
2228         colourMenu.add(buriedColour);\r
2229         colourMenu.add(nucleotideColour);\r
2230         colourMenu.add(userDefinedColour);\r
2231         colourMenu.addSeparator();\r
2232         colourMenu.add(conservationMenuItem);\r
2233         colourMenu.add(modifyConservation);\r
2234         colourMenu.add(abovePIDThreshold);\r
2235         colourMenu.add(modifyPID);\r
2236     colourMenu.add(annotationColour);\r
2237     calculateMenu.add(sort);\r
2238         calculateMenu.add(calculate);\r
2239         calculateMenu.addSeparator();\r
2240         calculateMenu.add(pairwiseAlignmentMenuItem);\r
2241         calculateMenu.add(PCAMenuItem);\r
2242         calculateMenu.add(autoCalculate);\r
2243         this.add(statusBar, BorderLayout.SOUTH);\r
2244         pasteMenu.add(pasteNew);\r
2245         pasteMenu.add(pasteThis);\r
2246         sort.add(sortIDMenuItem);\r
2247         sort.add(sortByTreeMenu);\r
2248         sort.add(sortGroupMenuItem);\r
2249         sort.add(sortPairwiseMenuItem);\r
2250         calculate.add(averageDistanceTreeMenuItem);\r
2251         calculate.add(neighbourTreeMenuItem);\r
2252         calculate.add(avDistanceTreeBlosumMenuItem);\r
2253         calculate.add(njTreeBlosumMenuItem);\r
2254         helpMenu.add(documentation);\r
2255         helpMenu.add(about);\r
2256     menu1.add(showColumns);\r
2257     menu1.add(showSeqs);\r
2258     menu2.add(hideColumns);\r
2259     menu2.add(hideSequences);\r
2260   }\r
2261 \r
2262   public void setEmbedded()\r
2263   {\r
2264 \r
2265     embeddedMenu = new Panel();\r
2266     embeddedEdit = new Label();\r
2267     embeddedSearch = new Label();\r
2268     embeddedView = new Label();\r
2269     embeddedColour = new Label();\r
2270     embeddedFile = new Label();\r
2271     embeddedHelp = new Label();\r
2272     embeddedCalculate = new Label();\r
2273     flowLayout1 = new FlowLayout();\r
2274     embeddedMenu.setBackground(Color.lightGray);\r
2275     embeddedMenu.setLayout(flowLayout1);\r
2276     embeddedEdit.setText("Edit");\r
2277     embeddedEdit.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2278     embeddedSearch.setText("Search");\r
2279     embeddedSearch.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2280     embeddedView.setText("View");\r
2281     embeddedView.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2282     embeddedColour.setText("Colour");\r
2283     embeddedColour.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2284     embeddedFile.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2285     embeddedFile.setText("File");\r
2286     embeddedHelp.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2287     embeddedHelp.setText("Help");\r
2288     embeddedCalculate.setFont(new java.awt.Font("Arial", Font.PLAIN, 10));\r
2289     embeddedCalculate.setText("Calculate");\r
2290     embeddedMenu.add(embeddedFile);\r
2291     embeddedMenu.add(embeddedEdit);\r
2292     embeddedMenu.add(embeddedSearch);\r
2293     embeddedMenu.add(embeddedView);\r
2294     embeddedMenu.add(embeddedColour);\r
2295     embeddedMenu.add(embeddedCalculate);\r
2296     embeddedMenu.add(embeddedHelp);\r
2297     flowLayout1.setAlignment(FlowLayout.LEFT);\r
2298     flowLayout1.setHgap(2);\r
2299     flowLayout1.setVgap(0);\r
2300     embeddedFile.addMouseListener(this);\r
2301     embeddedEdit.addMouseListener(this);\r
2302     embeddedSearch.addMouseListener(this);\r
2303     embeddedView.addMouseListener(this);\r
2304     embeddedColour.addMouseListener(this);\r
2305     embeddedCalculate.addMouseListener(this);\r
2306     embeddedHelp.addMouseListener(this);\r
2307 \r
2308    // setVisible(false);\r
2309     fileMenu.remove(closeMenuItem);\r
2310     fileMenu.remove(3); // Seperator\r
2311 \r
2312     viewport.applet.setLayout(new BorderLayout());\r
2313     viewport.applet.add(embeddedMenu, BorderLayout.NORTH);\r
2314     viewport.applet.add(statusBar, BorderLayout.SOUTH);\r
2315    // viewport.applet.validate();\r
2316 \r
2317     alignPanel.setSize(viewport.applet.size().width, viewport.applet.size().height\r
2318                        - embeddedMenu.HEIGHT - statusBar.HEIGHT);\r
2319 \r
2320      viewport.applet.add(alignPanel, BorderLayout.CENTER);\r
2321      viewport.applet.validate();\r
2322 \r
2323   }\r
2324 \r
2325 \r
2326 \r
2327   PopupMenu filePopup, editPopup, searchPopup,\r
2328       viewPopup, colourPopup, calculatePopup, helpPopup;\r
2329   MenuItem featureSettings = new MenuItem();\r
2330   CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem();\r
2331   MenuItem annotationColour = new MenuItem();\r
2332   MenuItem invertColSel = new MenuItem();\r
2333   Menu menu1 = new Menu();\r
2334   MenuItem showColumns = new MenuItem();\r
2335   MenuItem showSeqs = new MenuItem();\r
2336   Menu menu2 = new Menu();\r
2337   MenuItem hideColumns = new MenuItem();\r
2338   MenuItem hideSequences = new MenuItem();\r
2339 \r
2340   public void mousePressed(MouseEvent evt)\r
2341   {\r
2342     PopupMenu popup = null;\r
2343     Label source = (Label)evt.getSource();\r
2344     if(source==embeddedFile)\r
2345     {\r
2346       popup = filePopup = genPopupMenu(filePopup, fileMenu);\r
2347     }\r
2348     else if(source==embeddedEdit)\r
2349     {\r
2350       popup = editPopup = genPopupMenu(editPopup, editMenu);\r
2351     }\r
2352     else if(source==embeddedSearch)\r
2353     {\r
2354       popup = searchPopup = genPopupMenu(searchPopup, searchMenu);\r
2355     }\r
2356     else if(source==embeddedView)\r
2357     {\r
2358       popup = viewPopup = genPopupMenu(viewPopup, viewMenu);\r
2359     }\r
2360     else if(source==embeddedColour)\r
2361     {\r
2362       popup = colourPopup = genPopupMenu(colourPopup, colourMenu);\r
2363     }\r
2364     else if(source==embeddedCalculate)\r
2365     {\r
2366       popup = calculatePopup = genPopupMenu(calculatePopup, calculateMenu);\r
2367     }\r
2368     else if(source==embeddedHelp)\r
2369     {\r
2370       popup = helpPopup = genPopupMenu(helpPopup, helpMenu);\r
2371     }\r
2372 \r
2373     embeddedMenu.add(popup);\r
2374     popup.show(embeddedMenu,\r
2375                source.getBounds().x,\r
2376                source.getBounds().y + source.getBounds().getSize().height);\r
2377   }\r
2378 \r
2379   PopupMenu genPopupMenu(PopupMenu popup, Menu original)\r
2380   {\r
2381     if(popup!=null)\r
2382     {\r
2383       return popup;\r
2384     }\r
2385     popup = new PopupMenu();\r
2386     int m, mSize = original.getItemCount();\r
2387     for(m=0; m<mSize; m++)\r
2388     {\r
2389       popup.add(original.getItem(m));\r
2390       mSize--;\r
2391       m--;\r
2392     }\r
2393 \r
2394     return popup;\r
2395   }\r
2396   public void mouseClicked(MouseEvent evt)\r
2397   {}\r
2398   public void mouseReleased(MouseEvent evt)\r
2399   {}\r
2400   public void mouseEntered(MouseEvent evt)\r
2401   {}\r
2402   public void mouseExited(MouseEvent evt)\r
2403   {}\r
2404 \r
2405 }\r
2406 \r