Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.gui

File AlignFrame.java

 

Coverage histogram

../../img/srcFileCovDistChart3.png
47% of files have more coverage

Code metrics

598
1,656
232
2
5,753
4,070
652
0.39
7.14
116
2.81

Classes

Class Line # Actions
AlignFrame 158 1,647 647 1,797
0.2727640627.3%
PrintThread 5717 9 5 15
0.00%
 

Contributing tests

This file is covered by 163 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.gui;
22   
23    import jalview.analysis.AlignmentSorter;
24    import jalview.analysis.AlignmentUtils;
25    import jalview.analysis.CrossRef;
26    import jalview.analysis.Dna;
27    import jalview.analysis.ParseProperties;
28    import jalview.analysis.SequenceIdMatcher;
29    import jalview.api.AlignExportSettingsI;
30    import jalview.api.AlignViewControllerGuiI;
31    import jalview.api.AlignViewControllerI;
32    import jalview.api.AlignViewportI;
33    import jalview.api.AlignmentViewPanel;
34    import jalview.api.FeatureSettingsControllerI;
35    import jalview.api.SplitContainerI;
36    import jalview.api.ViewStyleI;
37    import jalview.api.analysis.SimilarityParamsI;
38    import jalview.bin.Cache;
39    import jalview.bin.Jalview;
40    import jalview.commands.CommandI;
41    import jalview.commands.EditCommand;
42    import jalview.commands.EditCommand.Action;
43    import jalview.commands.OrderCommand;
44    import jalview.commands.RemoveGapColCommand;
45    import jalview.commands.RemoveGapsCommand;
46    import jalview.commands.SlideSequencesCommand;
47    import jalview.commands.TrimRegionCommand;
48    import jalview.datamodel.AlignExportSettingsAdapter;
49    import jalview.datamodel.AlignedCodonFrame;
50    import jalview.datamodel.Alignment;
51    import jalview.datamodel.AlignmentAnnotation;
52    import jalview.datamodel.AlignmentExportData;
53    import jalview.datamodel.AlignmentI;
54    import jalview.datamodel.AlignmentOrder;
55    import jalview.datamodel.AlignmentView;
56    import jalview.datamodel.ColumnSelection;
57    import jalview.datamodel.HiddenColumns;
58    import jalview.datamodel.PDBEntry;
59    import jalview.datamodel.SeqCigar;
60    import jalview.datamodel.Sequence;
61    import jalview.datamodel.SequenceGroup;
62    import jalview.datamodel.SequenceI;
63    import jalview.gui.ColourMenuHelper.ColourChangeListener;
64    import jalview.gui.ViewSelectionMenu.ViewSetProvider;
65    import jalview.io.AlignmentProperties;
66    import jalview.io.AnnotationFile;
67    import jalview.io.BioJsHTMLOutput;
68    import jalview.io.DataSourceType;
69    import jalview.io.FileFormat;
70    import jalview.io.FileFormatI;
71    import jalview.io.FileFormats;
72    import jalview.io.FileLoader;
73    import jalview.io.FileParse;
74    import jalview.io.FormatAdapter;
75    import jalview.io.HtmlSvgOutput;
76    import jalview.io.IdentifyFile;
77    import jalview.io.JPredFile;
78    import jalview.io.JalviewFileChooser;
79    import jalview.io.JalviewFileView;
80    import jalview.io.JnetAnnotationMaker;
81    import jalview.io.NewickFile;
82    import jalview.io.ScoreMatrixFile;
83    import jalview.io.TCoffeeScoreFile;
84    import jalview.io.vcf.VCFLoader;
85    import jalview.jbgui.GAlignFrame;
86    import jalview.schemes.ColourSchemeI;
87    import jalview.schemes.ColourSchemes;
88    import jalview.schemes.ResidueColourScheme;
89    import jalview.schemes.TCoffeeColourScheme;
90    import jalview.util.ImageMaker.TYPE;
91    import jalview.util.MessageManager;
92    import jalview.util.dialogrunner.RunResponse;
93    import jalview.viewmodel.AlignmentViewport;
94    import jalview.viewmodel.ViewportRanges;
95    import jalview.ws.DBRefFetcher;
96    import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
97    import jalview.ws.jws1.Discoverer;
98    import jalview.ws.jws2.Jws2Discoverer;
99    import jalview.ws.jws2.jabaws2.Jws2Instance;
100    import jalview.ws.seqfetcher.DbSourceProxy;
101   
102    import java.awt.BorderLayout;
103    import java.awt.Color;
104    import java.awt.Component;
105    import java.awt.Rectangle;
106    import java.awt.Toolkit;
107    import java.awt.datatransfer.Clipboard;
108    import java.awt.datatransfer.DataFlavor;
109    import java.awt.datatransfer.StringSelection;
110    import java.awt.datatransfer.Transferable;
111    import java.awt.dnd.DnDConstants;
112    import java.awt.dnd.DropTargetDragEvent;
113    import java.awt.dnd.DropTargetDropEvent;
114    import java.awt.dnd.DropTargetEvent;
115    import java.awt.dnd.DropTargetListener;
116    import java.awt.event.ActionEvent;
117    import java.awt.event.ActionListener;
118    import java.awt.event.FocusAdapter;
119    import java.awt.event.FocusEvent;
120    import java.awt.event.ItemEvent;
121    import java.awt.event.ItemListener;
122    import java.awt.event.KeyAdapter;
123    import java.awt.event.KeyEvent;
124    import java.awt.event.MouseEvent;
125    import java.awt.print.PageFormat;
126    import java.awt.print.PrinterJob;
127    import java.beans.PropertyChangeEvent;
128    import java.io.File;
129    import java.io.FileWriter;
130    import java.io.PrintWriter;
131    import java.net.URL;
132    import java.util.ArrayList;
133    import java.util.Arrays;
134    import java.util.Deque;
135    import java.util.Enumeration;
136    import java.util.Hashtable;
137    import java.util.List;
138    import java.util.Vector;
139   
140    import javax.swing.JCheckBoxMenuItem;
141    import javax.swing.JComponent;
142    import javax.swing.JEditorPane;
143    import javax.swing.JInternalFrame;
144    import javax.swing.JLabel;
145    import javax.swing.JLayeredPane;
146    import javax.swing.JMenu;
147    import javax.swing.JMenuItem;
148    import javax.swing.JPanel;
149    import javax.swing.JScrollPane;
150    import javax.swing.SwingUtilities;
151   
152    /**
153    * DOCUMENT ME!
154    *
155    * @author $author$
156    * @version $Revision$
157    */
 
158    public class AlignFrame extends GAlignFrame implements DropTargetListener,
159    IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
160    {
161   
162    public static final int DEFAULT_WIDTH = 700;
163   
164    public static final int DEFAULT_HEIGHT = 500;
165   
166    /*
167    * The currently displayed panel (selected tabbed view if more than one)
168    */
169    public AlignmentPanel alignPanel;
170   
171    AlignViewport viewport;
172   
173    public AlignViewControllerI avc;
174   
175    List<AlignmentPanel> alignPanels = new ArrayList<>();
176   
177    /**
178    * Last format used to load or save alignments in this window
179    */
180    FileFormatI currentFileFormat = null;
181   
182    /**
183    * Current filename for this alignment
184    */
185    String fileName = null;
186   
187    File fileObject;
188   
189    /**
190    * Creates a new AlignFrame object with specific width and height.
191    *
192    * @param al
193    * @param width
194    * @param height
195    */
 
196  114 toggle public AlignFrame(AlignmentI al, int width, int height)
197    {
198  114 this(al, null, width, height);
199    }
200   
201    /**
202    * Creates a new AlignFrame object with specific width, height and
203    * sequenceSetId
204    *
205    * @param al
206    * @param width
207    * @param height
208    * @param sequenceSetId
209    */
 
210  0 toggle public AlignFrame(AlignmentI al, int width, int height,
211    String sequenceSetId)
212    {
213  0 this(al, null, width, height, sequenceSetId);
214    }
215   
216    /**
217    * Creates a new AlignFrame object with specific width, height and
218    * sequenceSetId
219    *
220    * @param al
221    * @param width
222    * @param height
223    * @param sequenceSetId
224    * @param viewId
225    */
 
226  72 toggle public AlignFrame(AlignmentI al, int width, int height,
227    String sequenceSetId, String viewId)
228    {
229  72 this(al, null, width, height, sequenceSetId, viewId);
230    }
231   
232    /**
233    * new alignment window with hidden columns
234    *
235    * @param al
236    * AlignmentI
237    * @param hiddenColumns
238    * ColumnSelection or null
239    * @param width
240    * Width of alignment frame
241    * @param height
242    * height of frame.
243    */
 
244  114 toggle public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
245    int height)
246    {
247  114 this(al, hiddenColumns, width, height, null);
248    }
249   
250    /**
251    * Create alignment frame for al with hiddenColumns, a specific width and
252    * height, and specific sequenceId
253    *
254    * @param al
255    * @param hiddenColumns
256    * @param width
257    * @param height
258    * @param sequenceSetId
259    * (may be null)
260    */
 
261  114 toggle public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
262    int height, String sequenceSetId)
263    {
264  114 this(al, hiddenColumns, width, height, sequenceSetId, null);
265    }
266   
267    /**
268    * Create alignment frame for al with hiddenColumns, a specific width and
269    * height, and specific sequenceId
270    *
271    * @param al
272    * @param hiddenColumns
273    * @param width
274    * @param height
275    * @param sequenceSetId
276    * (may be null)
277    * @param viewId
278    * (may be null)
279    */
 
280  186 toggle public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
281    int height, String sequenceSetId, String viewId)
282    {
283  186 setSize(width, height);
284   
285  186 if (al.getDataset() == null)
286    {
287  107 al.setDataset(null);
288    }
289   
290  186 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
291   
292  186 alignPanel = new AlignmentPanel(this, viewport);
293   
294  186 addAlignmentPanel(alignPanel, true);
295  186 init();
296    }
297   
 
298  2 toggle public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
299    HiddenColumns hiddenColumns, int width, int height)
300    {
301  2 setSize(width, height);
302   
303  2 if (al.getDataset() == null)
304    {
305  2 al.setDataset(null);
306    }
307   
308  2 viewport = new AlignViewport(al, hiddenColumns);
309   
310  2 if (hiddenSeqs != null && hiddenSeqs.length > 0)
311    {
312  2 viewport.hideSequence(hiddenSeqs);
313    }
314  2 alignPanel = new AlignmentPanel(this, viewport);
315  2 addAlignmentPanel(alignPanel, true);
316  2 init();
317    }
318   
319    /**
320    * Make a new AlignFrame from existing alignmentPanels
321    *
322    * @param ap
323    * AlignmentPanel
324    * @param av
325    * AlignViewport
326    */
 
327  5 toggle public AlignFrame(AlignmentPanel ap)
328    {
329  5 viewport = ap.av;
330  5 alignPanel = ap;
331  5 addAlignmentPanel(ap, false);
332  5 init();
333    }
334   
335    /**
336    * initalise the alignframe from the underlying viewport data and the
337    * configurations
338    */
 
339  193 toggle void init()
340    {
341  193 if (!Jalview.isHeadlessMode())
342    {
343  193 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
344    }
345   
346  193 avc = new jalview.controller.AlignViewController(this, viewport,
347    alignPanel);
348  193 if (viewport.getAlignmentConservationAnnotation() == null)
349    {
350    // BLOSUM62Colour.setEnabled(false);
351  10 conservationMenuItem.setEnabled(false);
352  10 modifyConservation.setEnabled(false);
353    // PIDColour.setEnabled(false);
354    // abovePIDThreshold.setEnabled(false);
355    // modifyPID.setEnabled(false);
356    }
357   
358  193 String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT",
359    "No sort");
360   
361  193 if (sortby.equals("Id"))
362    {
363  0 sortIDMenuItem_actionPerformed(null);
364    }
365  193 else if (sortby.equals("Pairwise Identity"))
366    {
367  0 sortPairwiseMenuItem_actionPerformed(null);
368    }
369   
370  193 this.alignPanel.av
371    .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
372   
373  193 setMenusFromViewport(viewport);
374  193 buildSortByAnnotationScoresMenu();
375  193 calculateTree.addActionListener(new ActionListener()
376    {
377   
 
378  0 toggle @Override
379    public void actionPerformed(ActionEvent e)
380    {
381  0 openTreePcaDialog();
382    }
383    });
384  193 buildColourMenu();
385   
386  193 if (Desktop.desktop != null)
387    {
388  190 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
389    /**
390    * BH 2018 ignore service listeners
391    *
392    * @j2sNative
393    *
394    */
395    {
396  190 addServiceListeners();
397    }
398  190 setGUINucleotide();
399    }
400   
401  193 if (viewport.getWrapAlignment())
402    {
403  1 wrapMenuItem_actionPerformed(null);
404    }
405   
406  193 if (jalview.bin.Cache.getDefault("SHOW_OVERVIEW", false))
407    {
408  0 this.overviewMenuItem_actionPerformed(null);
409    }
410   
411  193 addKeyListener();
412   
413  193 final List<AlignmentPanel> selviews = new ArrayList<>();
414  193 final List<AlignmentPanel> origview = new ArrayList<>();
415  193 final String menuLabel = MessageManager
416    .getString("label.copy_format_from");
417  193 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
418    new ViewSetProvider()
419    {
420   
 
421  0 toggle @Override
422    public AlignmentPanel[] getAllAlignmentPanels()
423    {
424  0 origview.clear();
425  0 origview.add(alignPanel);
426    // make an array of all alignment panels except for this one
427  0 List<AlignmentPanel> aps = new ArrayList<>(
428    Arrays.asList(Desktop.getAlignmentPanels(null)));
429  0 aps.remove(AlignFrame.this.alignPanel);
430  0 return aps.toArray(new AlignmentPanel[aps.size()]);
431    }
432    }, selviews, new ItemListener()
433    {
434   
 
435  0 toggle @Override
436    public void itemStateChanged(ItemEvent e)
437    {
438  0 if (origview.size() > 0)
439    {
440  0 final AlignmentPanel ap = origview.get(0);
441   
442    /*
443    * Copy the ViewStyle of the selected panel to 'this one'.
444    * Don't change value of 'scaleProteinAsCdna' unless copying
445    * from a SplitFrame.
446    */
447  0 ViewStyleI vs = selviews.get(0).getAlignViewport()
448    .getViewStyle();
449  0 boolean fromSplitFrame = selviews.get(0)
450    .getAlignViewport().getCodingComplement() != null;
451  0 if (!fromSplitFrame)
452    {
453  0 vs.setScaleProteinAsCdna(ap.getAlignViewport()
454    .getViewStyle().isScaleProteinAsCdna());
455    }
456  0 ap.getAlignViewport().setViewStyle(vs);
457   
458    /*
459    * Also rescale ViewStyle of SplitFrame complement if there is
460    * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
461    * the whole ViewStyle (allow cDNA protein to have different
462    * fonts)
463    */
464  0 AlignViewportI complement = ap.getAlignViewport()
465    .getCodingComplement();
466  0 if (complement != null && vs.isScaleProteinAsCdna())
467    {
468  0 AlignFrame af = Desktop.getAlignFrameFor(complement);
469  0 ((SplitFrame) af.getSplitViewContainer())
470    .adjustLayout();
471  0 af.setMenusForViewport();
472    }
473   
474  0 ap.updateLayout();
475  0 ap.setSelected(true);
476  0 ap.alignFrame.setMenusForViewport();
477   
478    }
479    }
480    });
481  193 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase()
482    .indexOf("devel") > -1
483    || Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase()
484    .indexOf("test") > -1)
485    {
486  193 formatMenu.add(vsel);
487    }
488  193 addFocusListener(new FocusAdapter()
489    {
 
490  139 toggle @Override
491    public void focusGained(FocusEvent e)
492    {
493  139 Jalview.setCurrentAlignFrame(AlignFrame.this);
494    }
495    });
496   
497    }
498   
499    /**
500    * Change the filename and format for the alignment, and enable the 'reload'
501    * button functionality.
502    *
503    * @param file
504    * valid filename
505    * @param format
506    * format of file
507    */
 
508  108 toggle public void setFileName(String file, FileFormatI format)
509    {
510  108 fileName = file;
511  108 setFileFormat(format);
512  108 reload.setEnabled(true);
513    }
514   
515    /**
516    * JavaScript will have this, maybe others. More dependable than a file name
517    * and maintains a reference to the actual bytes loaded.
518    *
519    * @param file
520    */
 
521  36 toggle public void setFileObject(File file)
522    {
523  36 this.fileObject = file;
524    }
525   
526    /**
527    * Add a KeyListener with handlers for various KeyPressed and KeyReleased
528    * events
529    */
 
530  193 toggle void addKeyListener()
531    {
532  193 addKeyListener(new KeyAdapter()
533    {
 
534  0 toggle @Override
535    public void keyPressed(KeyEvent evt)
536    {
537  0 if (viewport.cursorMode
538    && ((evt.getKeyCode() >= KeyEvent.VK_0
539    && evt.getKeyCode() <= KeyEvent.VK_9)
540    || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
541    && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
542    && Character.isDigit(evt.getKeyChar()))
543    {
544  0 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
545    }
546   
547  0 switch (evt.getKeyCode())
548    {
549   
550  0 case 27: // escape key
551  0 deselectAllSequenceMenuItem_actionPerformed(null);
552   
553  0 break;
554   
555  0 case KeyEvent.VK_DOWN:
556  0 if (evt.isAltDown() || !viewport.cursorMode)
557    {
558  0 moveSelectedSequences(false);
559    }
560  0 if (viewport.cursorMode)
561    {
562  0 alignPanel.getSeqPanel().moveCursor(0, 1);
563    }
564  0 break;
565   
566  0 case KeyEvent.VK_UP:
567  0 if (evt.isAltDown() || !viewport.cursorMode)
568    {
569  0 moveSelectedSequences(true);
570    }
571  0 if (viewport.cursorMode)
572    {
573  0 alignPanel.getSeqPanel().moveCursor(0, -1);
574    }
575   
576  0 break;
577   
578  0 case KeyEvent.VK_LEFT:
579  0 if (evt.isAltDown() || !viewport.cursorMode)
580    {
581  0 slideSequences(false,
582    alignPanel.getSeqPanel().getKeyboardNo1());
583    }
584    else
585    {
586  0 alignPanel.getSeqPanel().moveCursor(-1, 0);
587    }
588   
589  0 break;
590   
591  0 case KeyEvent.VK_RIGHT:
592  0 if (evt.isAltDown() || !viewport.cursorMode)
593    {
594  0 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
595    }
596    else
597    {
598  0 alignPanel.getSeqPanel().moveCursor(1, 0);
599    }
600  0 break;
601   
602  0 case KeyEvent.VK_SPACE:
603  0 if (viewport.cursorMode)
604    {
605  0 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
606    || evt.isShiftDown() || evt.isAltDown());
607    }
608  0 break;
609   
610    // case KeyEvent.VK_A:
611    // if (viewport.cursorMode)
612    // {
613    // alignPanel.seqPanel.insertNucAtCursor(false,"A");
614    // //System.out.println("A");
615    // }
616    // break;
617    /*
618    * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
619    * System.out.println("closing bracket"); } break;
620    */
621  0 case KeyEvent.VK_DELETE:
622  0 case KeyEvent.VK_BACK_SPACE:
623  0 if (!viewport.cursorMode)
624    {
625  0 cut_actionPerformed(null);
626    }
627    else
628    {
629  0 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
630    || evt.isShiftDown() || evt.isAltDown());
631    }
632   
633  0 break;
634   
635  0 case KeyEvent.VK_S:
636  0 if (viewport.cursorMode)
637    {
638  0 alignPanel.getSeqPanel().setCursorRow();
639    }
640  0 break;
641  0 case KeyEvent.VK_C:
642  0 if (viewport.cursorMode && !evt.isControlDown())
643    {
644  0 alignPanel.getSeqPanel().setCursorColumn();
645    }
646  0 break;
647  0 case KeyEvent.VK_P:
648  0 if (viewport.cursorMode)
649    {
650  0 alignPanel.getSeqPanel().setCursorPosition();
651    }
652  0 break;
653   
654  0 case KeyEvent.VK_ENTER:
655  0 case KeyEvent.VK_COMMA:
656  0 if (viewport.cursorMode)
657    {
658  0 alignPanel.getSeqPanel().setCursorRowAndColumn();
659    }
660  0 break;
661   
662  0 case KeyEvent.VK_Q:
663  0 if (viewport.cursorMode)
664    {
665  0 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
666    }
667  0 break;
668  0 case KeyEvent.VK_M:
669  0 if (viewport.cursorMode)
670    {
671  0 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
672    }
673  0 break;
674   
675  0 case KeyEvent.VK_F2:
676  0 viewport.cursorMode = !viewport.cursorMode;
677  0 setStatus(MessageManager
678    .formatMessage("label.keyboard_editing_mode", new String[]
679  0 { (viewport.cursorMode ? "on" : "off") }));
680  0 if (viewport.cursorMode)
681    {
682  0 ViewportRanges ranges = viewport.getRanges();
683  0 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
684    .getStartRes();
685  0 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
686    .getStartSeq();
687    }
688  0 alignPanel.getSeqPanel().seqCanvas.repaint();
689  0 break;
690   
691  0 case KeyEvent.VK_F1:
692  0 try
693    {
694  0 Help.showHelpWindow();
695    } catch (Exception ex)
696    {
697  0 ex.printStackTrace();
698    }
699  0 break;
700  0 case KeyEvent.VK_H:
701    {
702  0 boolean toggleSeqs = !evt.isControlDown();
703  0 boolean toggleCols = !evt.isShiftDown();
704  0 toggleHiddenRegions(toggleSeqs, toggleCols);
705  0 break;
706    }
707  0 case KeyEvent.VK_B:
708    {
709  0 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
710  0 boolean modifyExisting = true; // always modify, don't clear
711    // evt.isShiftDown();
712  0 boolean invertHighlighted = evt.isAltDown();
713  0 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
714    toggleSel);
715  0 break;
716    }
717  0 case KeyEvent.VK_PAGE_UP:
718  0 viewport.getRanges().pageUp();
719  0 break;
720  0 case KeyEvent.VK_PAGE_DOWN:
721  0 viewport.getRanges().pageDown();
722  0 break;
723    }
724    }
725   
 
726  0 toggle @Override
727    public void keyReleased(KeyEvent evt)
728    {
729  0 switch (evt.getKeyCode())
730    {
731  0 case KeyEvent.VK_LEFT:
732  0 if (evt.isAltDown() || !viewport.cursorMode)
733    {
734  0 viewport.firePropertyChange("alignment", null,
735    viewport.getAlignment().getSequences());
736    }
737  0 break;
738   
739  0 case KeyEvent.VK_RIGHT:
740  0 if (evt.isAltDown() || !viewport.cursorMode)
741    {
742  0 viewport.firePropertyChange("alignment", null,
743    viewport.getAlignment().getSequences());
744    }
745  0 break;
746    }
747    }
748    });
749    }
750   
 
751  241 toggle public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
752    {
753  241 ap.alignFrame = this;
754  241 avc = new jalview.controller.AlignViewController(this, viewport,
755    alignPanel);
756   
757  241 alignPanels.add(ap);
758   
759  241 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
760   
761  241 int aSize = alignPanels.size();
762   
763  241 tabbedPane.setVisible(aSize > 1 || ap.av.viewName != null);
764   
765  241 if (aSize == 1 && ap.av.viewName == null)
766    {
767  188 this.getContentPane().add(ap, BorderLayout.CENTER);
768    }
769    else
770    {
771  53 if (aSize == 2)
772    {
773  15 setInitialTabVisible();
774    }
775   
776  53 expandViews.setEnabled(true);
777  53 gatherViews.setEnabled(true);
778  53 tabbedPane.addTab(ap.av.viewName, ap);
779   
780  53 ap.setVisible(false);
781    }
782   
783  241 if (newPanel)
784    {
785  191 if (ap.av.isPadGaps())
786    {
787  84 ap.av.getAlignment().padGaps();
788    }
789  191 ap.av.updateConservation(ap);
790  191 ap.av.updateConsensus(ap);
791  191 ap.av.updateStrucConsensus(ap);
792    }
793    }
794   
 
795  77 toggle public void setInitialTabVisible()
796    {
797  77 expandViews.setEnabled(true);
798  77 gatherViews.setEnabled(true);
799  77 tabbedPane.setVisible(true);
800  77 AlignmentPanel first = alignPanels.get(0);
801  77 tabbedPane.addTab(first.av.viewName, first);
802  77 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
803    }
804   
 
805  1882 toggle public AlignViewport getViewport()
806    {
807  1882 return viewport;
808    }
809   
810    /* Set up intrinsic listeners for dynamically generated GUI bits. */
 
811  190 toggle private void addServiceListeners()
812    {
813  190 final java.beans.PropertyChangeListener thisListener;
814  190 Desktop.instance.addJalviewPropertyChangeListener("services",
815    thisListener = new java.beans.PropertyChangeListener()
816    {
 
817  920 toggle @Override
818    public void propertyChange(PropertyChangeEvent evt)
819    {
820    // // System.out.println("Discoverer property change.");
821    // if (evt.getPropertyName().equals("services"))
822    {
823  920 SwingUtilities.invokeLater(new Runnable()
824    {
825   
 
826  920 toggle @Override
827    public void run()
828    {
829  920 System.err.println(
830    "Rebuild WS Menu for service change");
831  920 BuildWebServiceMenu();
832    }
833   
834    });
835    }
836    }
837    });
838  190 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
839    {
 
840  96 toggle @Override
841    public void internalFrameClosed(
842    javax.swing.event.InternalFrameEvent evt)
843    {
844    // System.out.println("deregistering discoverer listener");
845  96 Desktop.instance.removeJalviewPropertyChangeListener("services",
846    thisListener);
847  96 closeMenuItem_actionPerformed(true);
848    };
849    });
850    // Finally, build the menu once to get current service state
851  190 new Thread(new Runnable()
852    {
 
853  190 toggle @Override
854    public void run()
855    {
856  190 BuildWebServiceMenu();
857    }
858    }).start();
859    }
860   
861    /**
862    * Configure menu items that vary according to whether the alignment is
863    * nucleotide or protein
864    */
 
865  190 toggle public void setGUINucleotide()
866    {
867  190 AlignmentI al = getViewport().getAlignment();
868  190 boolean nucleotide = al.isNucleotide();
869   
870  190 loadVcf.setVisible(nucleotide);
871  190 showTranslation.setVisible(nucleotide);
872  190 showReverse.setVisible(nucleotide);
873  190 showReverseComplement.setVisible(nucleotide);
874  190 conservationMenuItem.setEnabled(!nucleotide);
875  190 modifyConservation
876    .setEnabled(!nucleotide && conservationMenuItem.isSelected());
877  190 showGroupConservation.setEnabled(!nucleotide);
878   
879  190 showComplementMenuItem
880  190 .setText(nucleotide ? MessageManager.getString("label.protein")
881    : MessageManager.getString("label.nucleotide"));
882    }
883   
884    /**
885    * set up menus for the current viewport. This may be called after any
886    * operation that affects the data in the current view (selection changed,
887    * etc) to update the menus to reflect the new state.
888    */
 
889  20 toggle @Override
890    public void setMenusForViewport()
891    {
892  20 setMenusFromViewport(viewport);
893    }
894   
895    /**
896    * Need to call this method when tabs are selected for multiple views, or when
897    * loading from Jalview2XML.java
898    *
899    * @param av
900    * AlignViewport
901    */
 
902  376 toggle void setMenusFromViewport(AlignViewport av)
903    {
904  376 padGapsMenuitem.setSelected(av.isPadGaps());
905  376 colourTextMenuItem.setSelected(av.isShowColourText());
906  376 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
907  376 modifyPID.setEnabled(abovePIDThreshold.isSelected());
908  376 conservationMenuItem.setSelected(av.getConservationSelected());
909  376 modifyConservation.setEnabled(conservationMenuItem.isSelected());
910  376 seqLimits.setSelected(av.getShowJVSuffix());
911  376 idRightAlign.setSelected(av.isRightAlignIds());
912  376 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
913  376 renderGapsMenuItem.setSelected(av.isRenderGaps());
914  376 wrapMenuItem.setSelected(av.getWrapAlignment());
915  376 scaleAbove.setVisible(av.getWrapAlignment());
916  376 scaleLeft.setVisible(av.getWrapAlignment());
917  376 scaleRight.setVisible(av.getWrapAlignment());
918  376 annotationPanelMenuItem.setState(av.isShowAnnotation());
919    /*
920    * Show/hide annotations only enabled if annotation panel is shown
921    */
922  376 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
923  376 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
924  376 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
925  376 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
926  376 viewBoxesMenuItem.setSelected(av.getShowBoxes());
927  376 viewTextMenuItem.setSelected(av.getShowText());
928  376 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
929  376 showGroupConsensus.setSelected(av.isShowGroupConsensus());
930  376 showGroupConservation.setSelected(av.isShowGroupConservation());
931  376 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
932  376 showSequenceLogo.setSelected(av.isShowSequenceLogo());
933  376 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
934   
935  376 ColourMenuHelper.setColourSelected(colourMenu,
936    av.getGlobalColourScheme());
937   
938  376 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
939  376 hiddenMarkers.setState(av.getShowHiddenMarkers());
940  376 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
941  376 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
942  376 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
943  376 autoCalculate.setSelected(av.autoCalculateConsensus);
944  376 sortByTree.setSelected(av.sortByTree);
945  376 listenToViewSelections.setSelected(av.followSelection);
946   
947  376 showProducts.setEnabled(canShowProducts());
948  376 setGroovyEnabled(Desktop.getGroovyConsole() != null);
949   
950  376 updateEditMenuBar();
951    }
952   
953    /**
954    * Set the enabled state of the 'Run Groovy' option in the Calculate menu
955    *
956    * @param b
957    */
 
958  376 toggle public void setGroovyEnabled(boolean b)
959    {
960  376 runGroovy.setEnabled(b);
961    }
962   
963    private IProgressIndicator progressBar;
964   
965    /*
966    * (non-Javadoc)
967    *
968    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
969    */
 
970  10 toggle @Override
971    public void setProgressBar(String message, long id)
972    {
973  10 progressBar.setProgressBar(message, id);
974    }
975   
 
976  0 toggle @Override
977    public void registerHandler(final long id,
978    final IProgressIndicatorHandler handler)
979    {
980  0 progressBar.registerHandler(id, handler);
981    }
982   
983    /**
984    *
985    * @return true if any progress bars are still active
986    */
 
987  0 toggle @Override
988    public boolean operationInProgress()
989    {
990  0 return progressBar.operationInProgress();
991    }
992   
 
993  87 toggle @Override
994    public void setStatus(String text)
995    {
996  87 statusBar.setText(text);
997    }
998   
999    /*
1000    * Added so Castor Mapping file can obtain Jalview Version
1001    */
 
1002  0 toggle public String getVersion()
1003    {
1004  0 return jalview.bin.Cache.getProperty("VERSION");
1005    }
1006   
 
1007  43 toggle public FeatureRenderer getFeatureRenderer()
1008    {
1009  43 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1010    }
1011   
 
1012  0 toggle @Override
1013    public void fetchSequence_actionPerformed(ActionEvent e)
1014    {
1015  0 new jalview.gui.SequenceFetcher(this);
1016    }
1017   
 
1018  0 toggle @Override
1019    public void addFromFile_actionPerformed(ActionEvent e)
1020    {
1021  0 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1022    }
1023   
 
1024  0 toggle @Override
1025    public void reload_actionPerformed(ActionEvent e)
1026    {
1027  0 if (fileName != null)
1028    {
1029    // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1030    // originating file's format
1031    // TODO: work out how to recover feature settings for correct view(s) when
1032    // file is reloaded.
1033  0 if (FileFormat.Jalview.equals(currentFileFormat))
1034    {
1035  0 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1036  0 for (int i = 0; i < frames.length; i++)
1037    {
1038  0 if (frames[i] instanceof AlignFrame && frames[i] != this
1039    && ((AlignFrame) frames[i]).fileName != null
1040    && ((AlignFrame) frames[i]).fileName.equals(fileName))
1041    {
1042  0 try
1043    {
1044  0 frames[i].setSelected(true);
1045  0 Desktop.instance.closeAssociatedWindows();
1046    } catch (java.beans.PropertyVetoException ex)
1047    {
1048    }
1049    }
1050   
1051    }
1052  0 Desktop.instance.closeAssociatedWindows();
1053   
1054  0 FileLoader loader = new FileLoader();
1055  0 DataSourceType protocol = fileName.startsWith("http:")
1056    ? DataSourceType.URL
1057    : DataSourceType.FILE;
1058  0 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1059    }
1060    else
1061    {
1062  0 Rectangle bounds = this.getBounds();
1063   
1064  0 FileLoader loader = new FileLoader();
1065   
1066  0 AlignFrame newframe = null;
1067   
1068  0 if (fileObject == null)
1069    {
1070   
1071  0 DataSourceType protocol = (fileName.startsWith("http:")
1072    ? DataSourceType.URL
1073    : DataSourceType.FILE);
1074  0 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1075    currentFileFormat);
1076    }
1077    else
1078    {
1079  0 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1080    DataSourceType.FILE, currentFileFormat);
1081    }
1082   
1083  0 newframe.setBounds(bounds);
1084  0 if (featureSettings != null && featureSettings.isShowing())
1085    {
1086  0 final Rectangle fspos = featureSettings.frame.getBounds();
1087    // TODO: need a 'show feature settings' function that takes bounds -
1088    // need to refactor Desktop.addFrame
1089  0 newframe.featureSettings_actionPerformed(null);
1090  0 final FeatureSettings nfs = newframe.featureSettings;
1091  0 SwingUtilities.invokeLater(new Runnable()
1092    {
 
1093  0 toggle @Override
1094    public void run()
1095    {
1096  0 nfs.frame.setBounds(fspos);
1097    }
1098    });
1099  0 this.featureSettings.close();
1100  0 this.featureSettings = null;
1101    }
1102  0 this.closeMenuItem_actionPerformed(true);
1103    }
1104    }
1105    }
1106   
 
1107  0 toggle @Override
1108    public void addFromText_actionPerformed(ActionEvent e)
1109    {
1110  0 Desktop.instance
1111    .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1112    }
1113   
 
1114  0 toggle @Override
1115    public void addFromURL_actionPerformed(ActionEvent e)
1116    {
1117  0 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1118    }
1119   
 
1120  0 toggle @Override
1121    public void save_actionPerformed(ActionEvent e)
1122    {
1123  0 if (fileName == null || (currentFileFormat == null)
1124    || fileName.startsWith("http"))
1125    {
1126  0 saveAs_actionPerformed();
1127    }
1128    else
1129    {
1130  0 saveAlignment(fileName, currentFileFormat);
1131    }
1132    }
1133   
1134    /**
1135    * Saves the alignment to a file with a name chosen by the user, if necessary
1136    * warning if a file would be overwritten
1137    */
 
1138  0 toggle @Override
1139    public void saveAs_actionPerformed()
1140    {
1141  0 String format = currentFileFormat == null ? null
1142    : currentFileFormat.getName();
1143  0 JalviewFileChooser chooser = JalviewFileChooser
1144    .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1145   
1146  0 chooser.setFileView(new JalviewFileView());
1147  0 chooser.setDialogTitle(
1148    MessageManager.getString("label.save_alignment_to_file"));
1149  0 chooser.setToolTipText(MessageManager.getString("action.save"));
1150   
1151  0 int value = chooser.showSaveDialog(this);
1152   
1153  0 if (value != JalviewFileChooser.APPROVE_OPTION)
1154    {
1155  0 return;
1156    }
1157  0 currentFileFormat = chooser.getSelectedFormat();
1158    // todo is this (2005) test now obsolete - value is never null?
1159  0 while (currentFileFormat == null)
1160    {
1161  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1162    MessageManager
1163    .getString("label.select_file_format_before_saving"),
1164    MessageManager.getString("label.file_format_not_specified"),
1165    JvOptionPane.WARNING_MESSAGE);
1166  0 currentFileFormat = chooser.getSelectedFormat();
1167  0 value = chooser.showSaveDialog(this);
1168  0 if (value != JalviewFileChooser.APPROVE_OPTION)
1169    {
1170  0 return;
1171    }
1172    }
1173   
1174  0 fileName = chooser.getSelectedFile().getPath();
1175   
1176  0 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1177  0 Cache.setProperty("LAST_DIRECTORY", fileName);
1178  0 saveAlignment(fileName, currentFileFormat);
1179    }
1180   
1181    boolean lastSaveSuccessful = false;
1182   
1183    FileFormatI lastFormatSaved;
1184   
1185    String lastFilenameSaved;
1186   
1187    /**
1188    * Raise a dialog or status message for the last call to saveAlignment.
1189    *
1190    * @return true if last call to saveAlignment(file, format) was successful.
1191    */
 
1192  5 toggle public boolean isSaveAlignmentSuccessful()
1193    {
1194   
1195  5 if (!lastSaveSuccessful)
1196    {
1197  0 JvOptionPane.showInternalMessageDialog(this, MessageManager
1198    .formatMessage("label.couldnt_save_file", new Object[]
1199    { lastFilenameSaved }),
1200    MessageManager.getString("label.error_saving_file"),
1201    JvOptionPane.WARNING_MESSAGE);
1202    }
1203    else
1204    {
1205   
1206  5 setStatus(MessageManager.formatMessage(
1207    "label.successfully_saved_to_file_in_format", new Object[]
1208    { lastFilenameSaved, lastFormatSaved }));
1209   
1210    }
1211  5 return lastSaveSuccessful;
1212    }
1213   
1214    /**
1215    * Saves the alignment to the specified file path, in the specified format,
1216    * which may be an alignment format, or Jalview project format. If the
1217    * alignment has hidden regions, or the format is one capable of including
1218    * non-sequence data (features, annotations, groups), then the user may be
1219    * prompted to specify what to include in the output.
1220    *
1221    * @param file
1222    * @param format
1223    */
 
1224  5 toggle public void saveAlignment(String file, FileFormatI format)
1225    {
1226  5 lastSaveSuccessful = false;
1227  5 lastFilenameSaved = file;
1228  5 lastFormatSaved = format;
1229   
1230  5 if (FileFormat.Jalview.equals(format))
1231    {
1232  5 String shortName = title;
1233  5 if (shortName.indexOf(File.separatorChar) > -1)
1234    {
1235  4 shortName = shortName.substring(
1236    shortName.lastIndexOf(File.separatorChar) + 1);
1237    }
1238  5 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1239    shortName);
1240  5 return;
1241    }
1242   
1243  0 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1244  0 RunResponse cancelAction = new RunResponse(JvOptionPane.CANCEL_OPTION)
1245    {
 
1246  0 toggle @Override
1247    public void run()
1248    {
1249  0 lastSaveSuccessful = false;
1250    }
1251    };
1252  0 RunResponse outputAction = new RunResponse(JvOptionPane.OK_OPTION)
1253    {
 
1254  0 toggle @Override
1255    public void run()
1256    {
1257    // todo defer this to inside formatSequences (or later)
1258  0 AlignmentExportData exportData = viewport
1259    .getAlignExportData(options);
1260  0 String output = new FormatAdapter(alignPanel, options)
1261    .formatSequences(format, exportData.getAlignment(),
1262    exportData.getOmitHidden(),
1263    exportData.getStartEndPostions(),
1264    viewport.getAlignment().getHiddenColumns());
1265  0 if (output == null)
1266    {
1267  0 lastSaveSuccessful = false;
1268    }
1269    else
1270    {
1271  0 try
1272    {
1273  0 PrintWriter out = new PrintWriter(new FileWriter(file));
1274  0 out.print(output);
1275  0 out.close();
1276  0 AlignFrame.this.setTitle(file);
1277  0 setStatus(MessageManager.formatMessage(
1278    "label.successfully_saved_to_file_in_format",
1279    new Object[]
1280    { fileName, format.getName() }));
1281    } catch (Exception ex)
1282    {
1283  0 lastSaveSuccessful = false;
1284  0 ex.printStackTrace();
1285    }
1286    }
1287    }
1288    };
1289   
1290    /*
1291    * show dialog with export options if applicable; else just do it
1292    */
1293  0 if (AlignExportOptions.isNeeded(viewport, format))
1294    {
1295  0 AlignExportOptions choices = new AlignExportOptions(
1296    alignPanel.getAlignViewport(), format, options);
1297  0 choices.setResponseAction(outputAction);
1298  0 choices.setResponseAction(cancelAction);
1299  0 choices.showDialog();
1300    }
1301    else
1302    {
1303  0 outputAction.run();
1304    }
1305    }
1306   
1307    /**
1308    * Outputs the alignment to textbox in the requested format, if necessary
1309    * first prompting the user for whether to include hidden regions or
1310    * non-sequence data
1311    *
1312    * @param fileFormatName
1313    */
 
1314  0 toggle @Override
1315    protected void outputText_actionPerformed(String fileFormatName)
1316    {
1317  0 FileFormatI fileFormat = FileFormats.getInstance()
1318    .forName(fileFormatName);
1319  0 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1320  0 RunResponse outputAction = new RunResponse(JvOptionPane.OK_OPTION)
1321    {
 
1322  0 toggle @Override
1323    public void run()
1324    {
1325    // todo defer this to inside formatSequences (or later)
1326  0 AlignmentExportData exportData = viewport
1327    .getAlignExportData(options);
1328  0 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1329  0 cap.setForInput(null);
1330  0 try
1331    {
1332  0 FileFormatI format = fileFormat;
1333  0 cap.setText(new FormatAdapter(alignPanel, options)
1334    .formatSequences(format, exportData.getAlignment(),
1335    exportData.getOmitHidden(),
1336    exportData.getStartEndPostions(),
1337    viewport.getAlignment().getHiddenColumns()));
1338  0 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1339    "label.alignment_output_command", new Object[]
1340    { fileFormat.getName() }), 600, 500);
1341    } catch (OutOfMemoryError oom)
1342    {
1343  0 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1344    oom);
1345  0 cap.dispose();
1346    }
1347    }
1348    };
1349   
1350    /*
1351    * show dialog with export options if applicable; else just do it
1352    */
1353  0 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1354    {
1355  0 AlignExportOptions choices = new AlignExportOptions(
1356    alignPanel.getAlignViewport(), fileFormat, options);
1357  0 choices.setResponseAction(outputAction);
1358  0 choices.showDialog();
1359    }
1360    else
1361    {
1362  0 outputAction.run();
1363    }
1364    }
1365   
1366    /**
1367    * DOCUMENT ME!
1368    *
1369    * @param e
1370    * DOCUMENT ME!
1371    */
 
1372  0 toggle @Override
1373    protected void htmlMenuItem_actionPerformed(ActionEvent e)
1374    {
1375  0 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1376  0 htmlSVG.exportHTML(null);
1377    }
1378   
 
1379  0 toggle @Override
1380    public void bioJSMenuItem_actionPerformed(ActionEvent e)
1381    {
1382  0 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1383  0 bjs.exportHTML(null);
1384    }
1385   
 
1386  0 toggle public void createImageMap(File file, String image)
1387    {
1388  0 alignPanel.makePNGImageMap(file, image);
1389    }
1390   
1391    /**
1392    * Creates a PNG image of the alignment and writes it to the given file. If
1393    * the file is null, the user is prompted to choose a file.
1394    *
1395    * @param f
1396    */
 
1397  0 toggle @Override
1398    public void createPNG(File f)
1399    {
1400  0 alignPanel.makeAlignmentImage(TYPE.PNG, f);
1401    }
1402   
1403    /**
1404    * Creates an EPS image of the alignment and writes it to the given file. If
1405    * the file is null, the user is prompted to choose a file.
1406    *
1407    * @param f
1408    */
 
1409  0 toggle @Override
1410    public void createEPS(File f)
1411    {
1412  0 alignPanel.makeAlignmentImage(TYPE.EPS, f);
1413    }
1414   
1415    /**
1416    * Creates an SVG image of the alignment and writes it to the given file. If
1417    * the file is null, the user is prompted to choose a file.
1418    *
1419    * @param f
1420    */
 
1421  0 toggle @Override
1422    public void createSVG(File f)
1423    {
1424  0 alignPanel.makeAlignmentImage(TYPE.SVG, f);
1425    }
1426   
 
1427  0 toggle @Override
1428    public void pageSetup_actionPerformed(ActionEvent e)
1429    {
1430  0 PrinterJob printJob = PrinterJob.getPrinterJob();
1431  0 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1432    }
1433   
1434    /**
1435    * DOCUMENT ME!
1436    *
1437    * @param e
1438    * DOCUMENT ME!
1439    */
 
1440  0 toggle @Override
1441    public void printMenuItem_actionPerformed(ActionEvent e)
1442    {
1443    // Putting in a thread avoids Swing painting problems
1444  0 PrintThread thread = new PrintThread(alignPanel);
1445  0 thread.start();
1446    }
1447   
 
1448  0 toggle @Override
1449    public void exportFeatures_actionPerformed(ActionEvent e)
1450    {
1451  0 new AnnotationExporter(alignPanel).exportFeatures();
1452    }
1453   
 
1454  0 toggle @Override
1455    public void exportAnnotations_actionPerformed(ActionEvent e)
1456    {
1457  0 new AnnotationExporter(alignPanel).exportAnnotations();
1458    }
1459   
 
1460  0 toggle @Override
1461    public void associatedData_actionPerformed(ActionEvent e)
1462    {
1463  0 final JalviewFileChooser chooser = new JalviewFileChooser(
1464    jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1465  0 chooser.setFileView(new JalviewFileView());
1466  0 chooser.setDialogTitle(
1467    MessageManager.getString("label.load_jalview_annotations"));
1468  0 chooser.setToolTipText(
1469    MessageManager.getString("label.load_jalview_annotations"));
1470  0 chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION)
1471    {
1472   
 
1473  0 toggle @Override
1474    public void run()
1475    {
1476  0 String choice = chooser.getSelectedFile().getPath();
1477  0 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1478  0 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1479    }
1480   
1481    });
1482   
1483  0 chooser.openDialog(this);
1484    }
1485   
1486    /**
1487    * Close the current view or all views in the alignment frame. If the frame
1488    * only contains one view then the alignment will be removed from memory.
1489    *
1490    * @param closeAllTabs
1491    */
 
1492  154 toggle @Override
1493    public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1494    {
1495  154 if (alignPanels != null && alignPanels.size() < 2)
1496    {
1497  140 closeAllTabs = true;
1498    }
1499   
1500  154 try
1501    {
1502  154 if (alignPanels != null)
1503    {
1504  154 if (closeAllTabs)
1505    {
1506  153 if (this.isClosed())
1507    {
1508    // really close all the windows - otherwise wait till
1509    // setClosed(true) is called
1510  186 for (int i = 0; i < alignPanels.size(); i++)
1511    {
1512  90 AlignmentPanel ap = alignPanels.get(i);
1513  90 ap.closePanel();
1514    }
1515    }
1516    }
1517    else
1518    {
1519  1 closeView(alignPanel);
1520    }
1521    }
1522   
1523  154 if (closeAllTabs)
1524    {
1525    /*
1526    * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1527    * be called recursively, with the frame now in 'closed' state
1528    */
1529  153 this.setClosed(true);
1530    }
1531    } catch (Exception ex)
1532    {
1533  0 ex.printStackTrace();
1534    }
1535    }
1536   
1537    /**
1538    * Close the specified panel and close up tabs appropriately.
1539    *
1540    * @param panelToClose
1541    */
 
1542  1 toggle public void closeView(AlignmentPanel panelToClose)
1543    {
1544  1 int index = tabbedPane.getSelectedIndex();
1545  1 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1546  1 alignPanels.remove(panelToClose);
1547  1 panelToClose.closePanel();
1548  1 panelToClose = null;
1549   
1550  1 tabbedPane.removeTabAt(closedindex);
1551  1 tabbedPane.validate();
1552   
1553  1 if (index > closedindex || index == tabbedPane.getTabCount())
1554    {
1555    // modify currently selected tab index if necessary.
1556  1 index--;
1557    }
1558   
1559  1 this.tabSelectionChanged(index);
1560    }
1561   
1562    /**
1563    * DOCUMENT ME!
1564    */
 
1565  643 toggle void updateEditMenuBar()
1566    {
1567   
1568  643 if (viewport.getHistoryList().size() > 0)
1569    {
1570  0 undoMenuItem.setEnabled(true);
1571  0 CommandI command = viewport.getHistoryList().peek();
1572  0 undoMenuItem.setText(MessageManager
1573    .formatMessage("label.undo_command", new Object[]
1574    { command.getDescription() }));
1575    }
1576    else
1577    {
1578  643 undoMenuItem.setEnabled(false);
1579  643 undoMenuItem.setText(MessageManager.getString("action.undo"));
1580    }
1581   
1582  643 if (viewport.getRedoList().size() > 0)
1583    {
1584  0 redoMenuItem.setEnabled(true);
1585   
1586  0 CommandI command = viewport.getRedoList().peek();
1587  0 redoMenuItem.setText(MessageManager
1588    .formatMessage("label.redo_command", new Object[]
1589    { command.getDescription() }));
1590    }
1591    else
1592    {
1593  643 redoMenuItem.setEnabled(false);
1594  643 redoMenuItem.setText(MessageManager.getString("action.redo"));
1595    }
1596    }
1597   
 
1598  0 toggle @Override
1599    public void addHistoryItem(CommandI command)
1600    {
1601  0 if (command.getSize() > 0)
1602    {
1603  0 viewport.addToHistoryList(command);
1604  0 viewport.clearRedoList();
1605  0 updateEditMenuBar();
1606  0 viewport.updateHiddenColumns();
1607    // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1608    // && viewport.getColumnSelection().getHiddenColumns() != null &&
1609    // viewport.getColumnSelection()
1610    // .getHiddenColumns().size() > 0);
1611    }
1612    }
1613   
1614    /**
1615    *
1616    * @return alignment objects for all views
1617    */
 
1618  0 toggle AlignmentI[] getViewAlignments()
1619    {
1620  0 if (alignPanels != null)
1621    {
1622  0 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1623  0 int i = 0;
1624  0 for (AlignmentPanel ap : alignPanels)
1625    {
1626  0 als[i++] = ap.av.getAlignment();
1627    }
1628  0 return als;
1629    }
1630  0 if (viewport != null)
1631    {
1632  0 return new AlignmentI[] { viewport.getAlignment() };
1633    }
1634  0 return null;
1635    }
1636   
1637    /**
1638    * DOCUMENT ME!
1639    *
1640    * @param e
1641    * DOCUMENT ME!
1642    */
 
1643  0 toggle @Override
1644    protected void undoMenuItem_actionPerformed(ActionEvent e)
1645    {
1646  0 if (viewport.getHistoryList().isEmpty())
1647    {
1648  0 return;
1649    }
1650  0 CommandI command = viewport.getHistoryList().pop();
1651  0 viewport.addToRedoList(command);
1652  0 command.undoCommand(getViewAlignments());
1653   
1654  0 AlignmentViewport originalSource = getOriginatingSource(command);
1655  0 updateEditMenuBar();
1656   
1657  0 if (originalSource != null)
1658    {
1659  0 if (originalSource != viewport)
1660    {
1661  0 Cache.log.warn(
1662    "Implementation worry: mismatch of viewport origin for undo");
1663    }
1664  0 originalSource.updateHiddenColumns();
1665    // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1666    // null
1667    // && viewport.getColumnSelection().getHiddenColumns() != null &&
1668    // viewport.getColumnSelection()
1669    // .getHiddenColumns().size() > 0);
1670  0 originalSource.firePropertyChange("alignment", null,
1671    originalSource.getAlignment().getSequences());
1672    }
1673    }
1674   
1675    /**
1676    * DOCUMENT ME!
1677    *
1678    * @param e
1679    * DOCUMENT ME!
1680    */
 
1681  0 toggle @Override
1682    protected void redoMenuItem_actionPerformed(ActionEvent e)
1683    {
1684  0 if (viewport.getRedoList().size() < 1)
1685    {
1686  0 return;
1687    }
1688   
1689  0 CommandI command = viewport.getRedoList().pop();
1690  0 viewport.addToHistoryList(command);
1691  0 command.doCommand(getViewAlignments());
1692   
1693  0 AlignmentViewport originalSource = getOriginatingSource(command);
1694  0 updateEditMenuBar();
1695   
1696  0 if (originalSource != null)
1697    {
1698   
1699  0 if (originalSource != viewport)
1700    {
1701  0 Cache.log.warn(
1702    "Implementation worry: mismatch of viewport origin for redo");
1703    }
1704  0 originalSource.updateHiddenColumns();
1705    // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1706    // null
1707    // && viewport.getColumnSelection().getHiddenColumns() != null &&
1708    // viewport.getColumnSelection()
1709    // .getHiddenColumns().size() > 0);
1710  0 originalSource.firePropertyChange("alignment", null,
1711    originalSource.getAlignment().getSequences());
1712    }
1713    }
1714   
 
1715  0 toggle AlignmentViewport getOriginatingSource(CommandI command)
1716    {
1717  0 AlignmentViewport originalSource = null;
1718    // For sequence removal and addition, we need to fire
1719    // the property change event FROM the viewport where the
1720    // original alignment was altered
1721  0 AlignmentI al = null;
1722  0 if (command instanceof EditCommand)
1723    {
1724  0 EditCommand editCommand = (EditCommand) command;
1725  0 al = editCommand.getAlignment();
1726  0 List<Component> comps = PaintRefresher.components
1727    .get(viewport.getSequenceSetId());
1728   
1729  0 for (Component comp : comps)
1730    {
1731  0 if (comp instanceof AlignmentPanel)
1732    {
1733  0 if (al == ((AlignmentPanel) comp).av.getAlignment())
1734    {
1735  0 originalSource = ((AlignmentPanel) comp).av;
1736  0 break;
1737    }
1738    }
1739    }
1740    }
1741   
1742  0 if (originalSource == null)
1743    {
1744    // The original view is closed, we must validate
1745    // the current view against the closed view first
1746  0 if (al != null)
1747    {
1748  0 PaintRefresher.validateSequences(al, viewport.getAlignment());
1749    }
1750   
1751  0 originalSource = viewport;
1752    }
1753   
1754  0 return originalSource;
1755    }
1756   
1757    /**
1758    * DOCUMENT ME!
1759    *
1760    * @param up
1761    * DOCUMENT ME!
1762    */
 
1763  0 toggle public void moveSelectedSequences(boolean up)
1764    {
1765  0 SequenceGroup sg = viewport.getSelectionGroup();
1766   
1767  0 if (sg == null)
1768    {
1769  0 return;
1770    }
1771  0 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1772    viewport.getHiddenRepSequences(), up);
1773  0 alignPanel.paintAlignment(true, false);
1774    }
1775   
 
1776  0 toggle synchronized void slideSequences(boolean right, int size)
1777    {
1778  0 List<SequenceI> sg = new ArrayList<>();
1779  0 if (viewport.cursorMode)
1780    {
1781  0 sg.add(viewport.getAlignment()
1782    .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1783    }
1784  0 else if (viewport.getSelectionGroup() != null
1785    && viewport.getSelectionGroup().getSize() != viewport
1786    .getAlignment().getHeight())
1787    {
1788  0 sg = viewport.getSelectionGroup()
1789    .getSequences(viewport.getHiddenRepSequences());
1790    }
1791   
1792  0 if (sg.size() < 1)
1793    {
1794  0 return;
1795    }
1796   
1797  0 List<SequenceI> invertGroup = new ArrayList<>();
1798   
1799  0 for (SequenceI seq : viewport.getAlignment().getSequences())
1800    {
1801  0 if (!sg.contains(seq))
1802    {
1803  0 invertGroup.add(seq);
1804    }
1805    }
1806   
1807  0 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1808   
1809  0 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1810  0 for (int i = 0; i < invertGroup.size(); i++)
1811    {
1812  0 seqs2[i] = invertGroup.get(i);
1813    }
1814   
1815  0 SlideSequencesCommand ssc;
1816  0 if (right)
1817    {
1818  0 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1819    viewport.getGapCharacter());
1820    }
1821    else
1822    {
1823  0 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1824    viewport.getGapCharacter());
1825    }
1826   
1827  0 int groupAdjustment = 0;
1828  0 if (ssc.getGapsInsertedBegin() && right)
1829    {
1830  0 if (viewport.cursorMode)
1831    {
1832  0 alignPanel.getSeqPanel().moveCursor(size, 0);
1833    }
1834    else
1835    {
1836  0 groupAdjustment = size;
1837    }
1838    }
1839  0 else if (!ssc.getGapsInsertedBegin() && !right)
1840    {
1841  0 if (viewport.cursorMode)
1842    {
1843  0 alignPanel.getSeqPanel().moveCursor(-size, 0);
1844    }
1845    else
1846    {
1847  0 groupAdjustment = -size;
1848    }
1849    }
1850   
1851  0 if (groupAdjustment != 0)
1852    {
1853  0 viewport.getSelectionGroup().setStartRes(
1854    viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1855  0 viewport.getSelectionGroup().setEndRes(
1856    viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1857    }
1858   
1859    /*
1860    * just extend the last slide command if compatible; but not if in
1861    * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
1862    */
1863  0 boolean appendHistoryItem = false;
1864  0 Deque<CommandI> historyList = viewport.getHistoryList();
1865  0 boolean inSplitFrame = getSplitViewContainer() != null;
1866  0 if (!inSplitFrame && historyList != null && historyList.size() > 0
1867    && historyList.peek() instanceof SlideSequencesCommand)
1868    {
1869  0 appendHistoryItem = ssc.appendSlideCommand(
1870    (SlideSequencesCommand) historyList.peek());
1871    }
1872   
1873  0 if (!appendHistoryItem)
1874    {
1875  0 addHistoryItem(ssc);
1876    }
1877   
1878  0 repaint();
1879    }
1880   
1881    /**
1882    * DOCUMENT ME!
1883    *
1884    * @param e
1885    * DOCUMENT ME!
1886    */
 
1887  0 toggle @Override
1888    protected void copy_actionPerformed(ActionEvent e)
1889    {
1890  0 if (viewport.getSelectionGroup() == null)
1891    {
1892  0 return;
1893    }
1894    // TODO: preserve the ordering of displayed alignment annotation in any
1895    // internal paste (particularly sequence associated annotation)
1896  0 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
1897  0 String[] omitHidden = null;
1898   
1899  0 if (viewport.hasHiddenColumns())
1900    {
1901  0 omitHidden = viewport.getViewAsString(true);
1902    }
1903   
1904  0 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
1905    seqs, omitHidden, null);
1906   
1907  0 StringSelection ss = new StringSelection(output);
1908   
1909  0 try
1910    {
1911  0 jalview.gui.Desktop.internalCopy = true;
1912    // Its really worth setting the clipboard contents
1913    // to empty before setting the large StringSelection!!
1914  0 Toolkit.getDefaultToolkit().getSystemClipboard()
1915    .setContents(new StringSelection(""), null);
1916   
1917  0 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
1918    Desktop.instance);
1919    } catch (OutOfMemoryError er)
1920    {
1921  0 new OOMWarning("copying region", er);
1922  0 return;
1923    }
1924   
1925  0 HiddenColumns hiddenColumns = null;
1926  0 if (viewport.hasHiddenColumns())
1927    {
1928  0 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
1929  0 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
1930   
1931    // create new HiddenColumns object with copy of hidden regions
1932    // between startRes and endRes, offset by startRes
1933  0 hiddenColumns = new HiddenColumns(
1934    viewport.getAlignment().getHiddenColumns(), hiddenOffset,
1935    hiddenCutoff, hiddenOffset);
1936    }
1937   
1938  0 Desktop.jalviewClipboard = new Object[] { seqs,
1939    viewport.getAlignment().getDataset(), hiddenColumns };
1940  0 setStatus(MessageManager.formatMessage(
1941    "label.copied_sequences_to_clipboard", new Object[]
1942    { Integer.valueOf(seqs.length).toString() }));
1943    }
1944   
1945    /**
1946    * DOCUMENT ME!
1947    *
1948    * @param e
1949    * DOCUMENT ME!
1950    */
 
1951  0 toggle @Override
1952    protected void pasteNew_actionPerformed(ActionEvent e)
1953    {
1954  0 paste(true);
1955    }
1956   
1957    /**
1958    * DOCUMENT ME!
1959    *
1960    * @param e
1961    * DOCUMENT ME!
1962    */
 
1963  0 toggle @Override
1964    protected void pasteThis_actionPerformed(ActionEvent e)
1965    {
1966  0 paste(false);
1967    }
1968   
1969    /**
1970    * Paste contents of Jalview clipboard
1971    *
1972    * @param newAlignment
1973    * true to paste to a new alignment, otherwise add to this.
1974    */
 
1975  0 toggle void paste(boolean newAlignment)
1976    {
1977  0 boolean externalPaste = true;
1978  0 try
1979    {
1980  0 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
1981  0 Transferable contents = c.getContents(this);
1982   
1983  0 if (contents == null)
1984    {
1985  0 return;
1986    }
1987   
1988  0 String str;
1989  0 FileFormatI format;
1990  0 try
1991    {
1992  0 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
1993  0 if (str.length() < 1)
1994    {
1995  0 return;
1996    }
1997   
1998  0 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
1999   
2000    } catch (OutOfMemoryError er)
2001    {
2002  0 new OOMWarning("Out of memory pasting sequences!!", er);
2003  0 return;
2004    }
2005   
2006  0 SequenceI[] sequences;
2007  0 boolean annotationAdded = false;
2008  0 AlignmentI alignment = null;
2009   
2010  0 if (Desktop.jalviewClipboard != null)
2011    {
2012    // The clipboard was filled from within Jalview, we must use the
2013    // sequences
2014    // And dataset from the copied alignment
2015  0 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2016    // be doubly sure that we create *new* sequence objects.
2017  0 sequences = new SequenceI[newseq.length];
2018  0 for (int i = 0; i < newseq.length; i++)
2019    {
2020  0 sequences[i] = new Sequence(newseq[i]);
2021    }
2022  0 alignment = new Alignment(sequences);
2023  0 externalPaste = false;
2024    }
2025    else
2026    {
2027    // parse the clipboard as an alignment.
2028  0 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2029    format);
2030  0 sequences = alignment.getSequencesArray();
2031    }
2032   
2033  0 int alwidth = 0;
2034  0 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2035  0 int fgroup = -1;
2036   
2037  0 if (newAlignment)
2038    {
2039   
2040  0 if (Desktop.jalviewClipboard != null)
2041    {
2042    // dataset is inherited
2043  0 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2044    }
2045    else
2046    {
2047    // new dataset is constructed
2048  0 alignment.setDataset(null);
2049    }
2050  0 alwidth = alignment.getWidth() + 1;
2051    }
2052    else
2053    {
2054  0 AlignmentI pastedal = alignment; // preserve pasted alignment object
2055    // Add pasted sequences and dataset into existing alignment.
2056  0 alignment = viewport.getAlignment();
2057  0 alwidth = alignment.getWidth() + 1;
2058    // decide if we need to import sequences from an existing dataset
2059  0 boolean importDs = Desktop.jalviewClipboard != null
2060    && Desktop.jalviewClipboard[1] != alignment.getDataset();
2061    // importDs==true instructs us to copy over new dataset sequences from
2062    // an existing alignment
2063  0 Vector newDs = (importDs) ? new Vector() : null; // used to create
2064    // minimum dataset set
2065   
2066  0 for (int i = 0; i < sequences.length; i++)
2067    {
2068  0 if (importDs)
2069    {
2070  0 newDs.addElement(null);
2071    }
2072  0 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2073    // paste
2074  0 if (importDs && ds != null)
2075    {
2076  0 if (!newDs.contains(ds))
2077    {
2078  0 newDs.setElementAt(ds, i);
2079  0 ds = new Sequence(ds);
2080    // update with new dataset sequence
2081  0 sequences[i].setDatasetSequence(ds);
2082    }
2083    else
2084    {
2085  0 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2086    }
2087    }
2088    else
2089    {
2090    // copy and derive new dataset sequence
2091  0 sequences[i] = sequences[i].deriveSequence();
2092  0 alignment.getDataset()
2093    .addSequence(sequences[i].getDatasetSequence());
2094    // TODO: avoid creation of duplicate dataset sequences with a
2095    // 'contains' method using SequenceI.equals()/SequenceI.contains()
2096    }
2097  0 alignment.addSequence(sequences[i]); // merges dataset
2098    }
2099  0 if (newDs != null)
2100    {
2101  0 newDs.clear(); // tidy up
2102    }
2103  0 if (alignment.getAlignmentAnnotation() != null)
2104    {
2105  0 for (AlignmentAnnotation alan : alignment
2106    .getAlignmentAnnotation())
2107    {
2108  0 if (alan.graphGroup > fgroup)
2109    {
2110  0 fgroup = alan.graphGroup;
2111    }
2112    }
2113    }
2114  0 if (pastedal.getAlignmentAnnotation() != null)
2115    {
2116    // Add any annotation attached to alignment.
2117  0 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2118  0 for (int i = 0; i < alann.length; i++)
2119    {
2120  0 annotationAdded = true;
2121  0 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2122    {
2123  0 AlignmentAnnotation newann = new AlignmentAnnotation(
2124    alann[i]);
2125  0 if (newann.graphGroup > -1)
2126    {
2127  0 if (newGraphGroups.size() <= newann.graphGroup
2128    || newGraphGroups.get(newann.graphGroup) == null)
2129    {
2130  0 for (int q = newGraphGroups
2131  0 .size(); q <= newann.graphGroup; q++)
2132    {
2133  0 newGraphGroups.add(q, null);
2134    }
2135  0 newGraphGroups.set(newann.graphGroup,
2136    new Integer(++fgroup));
2137    }
2138  0 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2139    .intValue();
2140    }
2141   
2142  0 newann.padAnnotation(alwidth);
2143  0 alignment.addAnnotation(newann);
2144    }
2145    }
2146    }
2147    }
2148  0 if (!newAlignment)
2149    {
2150    // /////
2151    // ADD HISTORY ITEM
2152    //
2153  0 addHistoryItem(new EditCommand(
2154    MessageManager.getString("label.add_sequences"),
2155    Action.PASTE, sequences, 0, alignment.getWidth(),
2156    alignment));
2157    }
2158    // Add any annotations attached to sequences
2159  0 for (int i = 0; i < sequences.length; i++)
2160    {
2161  0 if (sequences[i].getAnnotation() != null)
2162    {
2163  0 AlignmentAnnotation newann;
2164  0 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2165    {
2166  0 annotationAdded = true;
2167  0 newann = sequences[i].getAnnotation()[a];
2168  0 newann.adjustForAlignment();
2169  0 newann.padAnnotation(alwidth);
2170  0 if (newann.graphGroup > -1)
2171    {
2172  0 if (newann.graphGroup > -1)
2173    {
2174  0 if (newGraphGroups.size() <= newann.graphGroup
2175    || newGraphGroups.get(newann.graphGroup) == null)
2176    {
2177  0 for (int q = newGraphGroups
2178  0 .size(); q <= newann.graphGroup; q++)
2179    {
2180  0 newGraphGroups.add(q, null);
2181    }
2182  0 newGraphGroups.set(newann.graphGroup,
2183    new Integer(++fgroup));
2184    }
2185  0 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2186    .intValue();
2187    }
2188    }
2189  0 alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation
2190    // was
2191    // duplicated
2192    // earlier
2193  0 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2194    a);
2195    }
2196    }
2197    }
2198  0 if (!newAlignment)
2199    {
2200   
2201    // propagate alignment changed.
2202  0 viewport.getRanges().setEndSeq(alignment.getHeight());
2203  0 if (annotationAdded)
2204    {
2205    // Duplicate sequence annotation in all views.
2206  0 AlignmentI[] alview = this.getViewAlignments();
2207  0 for (int i = 0; i < sequences.length; i++)
2208    {
2209  0 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2210  0 if (sann == null)
2211    {
2212  0 continue;
2213    }
2214  0 for (int avnum = 0; avnum < alview.length; avnum++)
2215    {
2216  0 if (alview[avnum] != alignment)
2217    {
2218    // duplicate in a view other than the one with input focus
2219  0 int avwidth = alview[avnum].getWidth() + 1;
2220    // this relies on sann being preserved after we
2221    // modify the sequence's annotation array for each duplication
2222  0 for (int a = 0; a < sann.length; a++)
2223    {
2224  0 AlignmentAnnotation newann = new AlignmentAnnotation(
2225    sann[a]);
2226  0 sequences[i].addAlignmentAnnotation(newann);
2227  0 newann.padAnnotation(avwidth);
2228  0 alview[avnum].addAnnotation(newann); // annotation was
2229    // duplicated earlier
2230    // TODO JAL-1145 graphGroups are not updated for sequence
2231    // annotation added to several views. This may cause
2232    // strangeness
2233  0 alview[avnum].setAnnotationIndex(newann, a);
2234    }
2235    }
2236    }
2237    }
2238  0 buildSortByAnnotationScoresMenu();
2239    }
2240  0 viewport.firePropertyChange("alignment", null,
2241    alignment.getSequences());
2242  0 if (alignPanels != null)
2243    {
2244  0 for (AlignmentPanel ap : alignPanels)
2245    {
2246  0 ap.validateAnnotationDimensions(false);
2247    }
2248    }
2249    else
2250    {
2251  0 alignPanel.validateAnnotationDimensions(false);
2252    }
2253   
2254    }
2255    else
2256    {
2257  0 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2258    DEFAULT_HEIGHT);
2259  0 String newtitle = new String("Copied sequences");
2260   
2261  0 if (Desktop.jalviewClipboard != null
2262    && Desktop.jalviewClipboard[2] != null)
2263    {
2264  0 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2265  0 af.viewport.setHiddenColumns(hc);
2266    }
2267   
2268    // >>>This is a fix for the moment, until a better solution is
2269    // found!!<<<
2270  0 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2271    .transferSettings(alignPanel.getSeqPanel().seqCanvas
2272    .getFeatureRenderer());
2273   
2274    // TODO: maintain provenance of an alignment, rather than just make the
2275    // title a concatenation of operations.
2276  0 if (!externalPaste)
2277    {
2278  0 if (title.startsWith("Copied sequences"))
2279    {
2280  0 newtitle = title;
2281    }
2282    else
2283    {
2284  0 newtitle = newtitle.concat("- from " + title);
2285    }
2286    }
2287    else
2288    {
2289  0 newtitle = new String("Pasted sequences");
2290    }
2291   
2292  0 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2293    DEFAULT_HEIGHT);
2294   
2295    }
2296   
2297    } catch (Exception ex)
2298    {
2299  0 ex.printStackTrace();
2300  0 System.out.println("Exception whilst pasting: " + ex);
2301    // could be anything being pasted in here
2302    }
2303   
2304    }
2305   
 
2306  0 toggle @Override
2307    protected void expand_newalign(ActionEvent e)
2308    {
2309  0 try
2310    {
2311  0 AlignmentI alignment = AlignmentUtils
2312    .expandContext(getViewport().getAlignment(), -1);
2313  0 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2314    DEFAULT_HEIGHT);
2315  0 String newtitle = new String("Flanking alignment");
2316   
2317  0 if (Desktop.jalviewClipboard != null
2318    && Desktop.jalviewClipboard[2] != null)
2319    {
2320  0 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2321  0 af.viewport.setHiddenColumns(hc);
2322    }
2323   
2324    // >>>This is a fix for the moment, until a better solution is
2325    // found!!<<<
2326  0 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2327    .transferSettings(alignPanel.getSeqPanel().seqCanvas
2328    .getFeatureRenderer());
2329   
2330    // TODO: maintain provenance of an alignment, rather than just make the
2331    // title a concatenation of operations.
2332    {
2333  0 if (title.startsWith("Copied sequences"))
2334    {
2335  0 newtitle = title;
2336    }
2337    else
2338    {
2339  0 newtitle = newtitle.concat("- from " + title);
2340    }
2341    }
2342   
2343  0 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2344   
2345    } catch (Exception ex)
2346    {
2347  0 ex.printStackTrace();
2348  0 System.out.println("Exception whilst pasting: " + ex);
2349    // could be anything being pasted in here
2350    } catch (OutOfMemoryError oom)
2351    {
2352  0 new OOMWarning("Viewing flanking region of alignment", oom);
2353    }
2354    }
2355   
2356    /**
2357    * DOCUMENT ME!
2358    *
2359    * @param e
2360    * DOCUMENT ME!
2361    */
 
2362  0 toggle @Override
2363    protected void cut_actionPerformed(ActionEvent e)
2364    {
2365  0 copy_actionPerformed(null);
2366  0 delete_actionPerformed(null);
2367    }
2368   
2369    /**
2370    * DOCUMENT ME!
2371    *
2372    * @param e
2373    * DOCUMENT ME!
2374    */
 
2375  0 toggle @Override
2376    protected void delete_actionPerformed(ActionEvent evt)
2377    {
2378   
2379  0 SequenceGroup sg = viewport.getSelectionGroup();
2380  0 if (sg == null)
2381    {
2382  0 return;
2383    }
2384   
2385    /*
2386    * If the cut affects all sequences, warn, remove highlighted columns
2387    */
2388  0 if (sg.getSize() == viewport.getAlignment().getHeight())
2389    {
2390  0 boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes())
2391    + 1) == viewport.getAlignment().getWidth()) ? true : false;
2392  0 if (isEntireAlignWidth)
2393    {
2394  0 int confirm = JvOptionPane.showConfirmDialog(this,
2395    MessageManager.getString("warn.delete_all"), // $NON-NLS-1$
2396    MessageManager.getString("label.delete_all"), // $NON-NLS-1$
2397    JvOptionPane.OK_CANCEL_OPTION);
2398   
2399  0 if (confirm == JvOptionPane.CANCEL_OPTION
2400    || confirm == JvOptionPane.CLOSED_OPTION)
2401    {
2402  0 return;
2403    }
2404    }
2405  0 viewport.getColumnSelection().removeElements(sg.getStartRes(),
2406    sg.getEndRes() + 1);
2407    }
2408  0 SequenceI[] cut = sg.getSequences()
2409    .toArray(new SequenceI[sg.getSize()]);
2410   
2411  0 addHistoryItem(new EditCommand(
2412    MessageManager.getString("label.cut_sequences"), Action.CUT,
2413    cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2414    viewport.getAlignment()));
2415   
2416  0 viewport.setSelectionGroup(null);
2417  0 viewport.sendSelection();
2418  0 viewport.getAlignment().deleteGroup(sg);
2419   
2420  0 viewport.firePropertyChange("alignment", null,
2421    viewport.getAlignment().getSequences());
2422  0 if (viewport.getAlignment().getHeight() < 1)
2423    {
2424  0 try
2425    {
2426  0 this.setClosed(true);
2427    } catch (Exception ex)
2428    {
2429    }
2430    }
2431    }
2432   
2433    /**
2434    * DOCUMENT ME!
2435    *
2436    * @param e
2437    * DOCUMENT ME!
2438    */
 
2439  0 toggle @Override
2440    protected void deleteGroups_actionPerformed(ActionEvent e)
2441    {
2442  0 if (avc.deleteGroups())
2443    {
2444  0 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2445  0 alignPanel.updateAnnotation();
2446  0 alignPanel.paintAlignment(true, true);
2447    }
2448    }
2449   
2450    /**
2451    * DOCUMENT ME!
2452    *
2453    * @param e
2454    * DOCUMENT ME!
2455    */
 
2456  4 toggle @Override
2457    public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2458    {
2459  4 SequenceGroup sg = new SequenceGroup();
2460   
2461  18 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2462    {
2463  14 sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
2464    }
2465   
2466  4 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2467  4 viewport.setSelectionGroup(sg);
2468  4 viewport.sendSelection();
2469    // JAL-2034 - should delegate to
2470    // alignPanel to decide if overview needs
2471    // updating.
2472  4 alignPanel.paintAlignment(false, false);
2473  4 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2474    }
2475   
2476    /**
2477    * DOCUMENT ME!
2478    *
2479    * @param e
2480    * DOCUMENT ME!
2481    */
 
2482  0 toggle @Override
2483    public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2484    {
2485  0 if (viewport.cursorMode)
2486    {
2487  0 alignPanel.getSeqPanel().keyboardNo1 = null;
2488  0 alignPanel.getSeqPanel().keyboardNo2 = null;
2489    }
2490  0 viewport.setSelectionGroup(null);
2491  0 viewport.getColumnSelection().clear();
2492  0 viewport.setSelectionGroup(null);
2493  0 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2494    // JAL-2034 - should delegate to
2495    // alignPanel to decide if overview needs
2496    // updating.
2497  0 alignPanel.paintAlignment(false, false);
2498  0 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2499  0 viewport.sendSelection();
2500    }
2501   
2502    /**
2503    * DOCUMENT ME!
2504    *
2505    * @param e
2506    * DOCUMENT ME!
2507    */
 
2508  0 toggle @Override
2509    public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2510    {
2511  0 SequenceGroup sg = viewport.getSelectionGroup();
2512   
2513  0 if (sg == null)
2514    {
2515  0 selectAllSequenceMenuItem_actionPerformed(null);
2516   
2517  0 return;
2518    }
2519   
2520  0 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2521    {
2522  0 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2523    }
2524    // JAL-2034 - should delegate to
2525    // alignPanel to decide if overview needs
2526    // updating.
2527   
2528  0 alignPanel.paintAlignment(true, false);
2529  0 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2530  0 viewport.sendSelection();
2531    }
2532   
 
2533  0 toggle @Override
2534    public void invertColSel_actionPerformed(ActionEvent e)
2535    {
2536  0 viewport.invertColumnSelection();
2537  0 alignPanel.paintAlignment(true, false);
2538  0 viewport.sendSelection();
2539    }
2540   
2541    /**
2542    * DOCUMENT ME!
2543    *
2544    * @param e
2545    * DOCUMENT ME!
2546    */
 
2547  0 toggle @Override
2548    public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2549    {
2550  0 trimAlignment(true);
2551    }
2552   
2553    /**
2554    * DOCUMENT ME!
2555    *
2556    * @param e
2557    * DOCUMENT ME!
2558    */
 
2559  0 toggle @Override
2560    public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2561    {
2562  0 trimAlignment(false);
2563    }
2564   
 
2565  0 toggle void trimAlignment(boolean trimLeft)
2566    {
2567  0 ColumnSelection colSel = viewport.getColumnSelection();
2568  0 int column;
2569   
2570  0 if (!colSel.isEmpty())
2571    {
2572  0 if (trimLeft)
2573    {
2574  0 column = colSel.getMin();
2575    }
2576    else
2577    {
2578  0 column = colSel.getMax();
2579    }
2580   
2581  0 SequenceI[] seqs;
2582  0 if (viewport.getSelectionGroup() != null)
2583    {
2584  0 seqs = viewport.getSelectionGroup()
2585    .getSequencesAsArray(viewport.getHiddenRepSequences());
2586    }
2587    else
2588    {
2589  0 seqs = viewport.getAlignment().getSequencesArray();
2590    }
2591   
2592  0 TrimRegionCommand trimRegion;
2593  0 if (trimLeft)
2594    {
2595  0 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2596    column, viewport.getAlignment());
2597  0 viewport.getRanges().setStartRes(0);
2598    }
2599    else
2600    {
2601  0 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2602    column, viewport.getAlignment());
2603    }
2604   
2605  0 setStatus(MessageManager
2606    .formatMessage("label.removed_columns", new String[]
2607    { Integer.valueOf(trimRegion.getSize()).toString() }));
2608   
2609  0 addHistoryItem(trimRegion);
2610   
2611  0 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2612    {
2613  0 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2614    || (!trimLeft && !sg.adjustForRemoveRight(column)))
2615    {
2616  0 viewport.getAlignment().deleteGroup(sg);
2617    }
2618    }
2619   
2620  0 viewport.firePropertyChange("alignment", null,
2621    viewport.getAlignment().getSequences());
2622    }
2623    }
2624   
2625    /**
2626    * DOCUMENT ME!
2627    *
2628    * @param e
2629    * DOCUMENT ME!
2630    */
 
2631  0 toggle @Override
2632    public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2633    {
2634  0 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2635   
2636  0 SequenceI[] seqs;
2637  0 if (viewport.getSelectionGroup() != null)
2638    {
2639  0 seqs = viewport.getSelectionGroup()
2640    .getSequencesAsArray(viewport.getHiddenRepSequences());
2641  0 start = viewport.getSelectionGroup().getStartRes();
2642  0 end = viewport.getSelectionGroup().getEndRes();
2643    }
2644    else
2645    {
2646  0 seqs = viewport.getAlignment().getSequencesArray();
2647    }
2648   
2649  0 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2650    "Remove Gapped Columns", seqs, start, end,
2651    viewport.getAlignment());
2652   
2653  0 addHistoryItem(removeGapCols);
2654   
2655  0 setStatus(MessageManager
2656    .formatMessage("label.removed_empty_columns", new Object[]
2657    { Integer.valueOf(removeGapCols.getSize()).toString() }));
2658   
2659    // This is to maintain viewport position on first residue
2660    // of first sequence
2661  0 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2662  0 ViewportRanges ranges = viewport.getRanges();
2663  0 int startRes = seq.findPosition(ranges.getStartRes());
2664    // ShiftList shifts;
2665    // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2666    // edit.alColumnChanges=shifts.getInverse();
2667    // if (viewport.hasHiddenColumns)
2668    // viewport.getColumnSelection().compensateForEdits(shifts);
2669  0 ranges.setStartRes(seq.findIndex(startRes) - 1);
2670  0 viewport.firePropertyChange("alignment", null,
2671    viewport.getAlignment().getSequences());
2672   
2673    }
2674   
2675    /**
2676    * DOCUMENT ME!
2677    *
2678    * @param e
2679    * DOCUMENT ME!
2680    */
 
2681  0 toggle @Override
2682    public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2683    {
2684  0 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2685   
2686  0 SequenceI[] seqs;
2687  0 if (viewport.getSelectionGroup() != null)
2688    {
2689  0 seqs = viewport.getSelectionGroup()
2690    .getSequencesAsArray(viewport.getHiddenRepSequences());
2691  0 start = viewport.getSelectionGroup().getStartRes();
2692  0 end = viewport.getSelectionGroup().getEndRes();
2693    }
2694    else
2695    {
2696  0 seqs = viewport.getAlignment().getSequencesArray();
2697    }
2698   
2699    // This is to maintain viewport position on first residue
2700    // of first sequence
2701  0 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2702  0 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2703   
2704  0 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2705    viewport.getAlignment()));
2706   
2707  0 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2708   
2709  0 viewport.firePropertyChange("alignment", null,
2710    viewport.getAlignment().getSequences());
2711   
2712    }
2713   
2714    /**
2715    * DOCUMENT ME!
2716    *
2717    * @param e
2718    * DOCUMENT ME!
2719    */
 
2720  0 toggle @Override
2721    public void padGapsMenuitem_actionPerformed(ActionEvent e)
2722    {
2723  0 viewport.setPadGaps(padGapsMenuitem.isSelected());
2724  0 viewport.firePropertyChange("alignment", null,
2725    viewport.getAlignment().getSequences());
2726    }
2727   
2728    /**
2729    * DOCUMENT ME!
2730    *
2731    * @param e
2732    * DOCUMENT ME!
2733    */
 
2734  0 toggle @Override
2735    public void findMenuItem_actionPerformed(ActionEvent e)
2736    {
2737  0 new Finder();
2738    }
2739   
2740    /**
2741    * Create a new view of the current alignment.
2742    */
 
2743  3 toggle @Override
2744    public void newView_actionPerformed(ActionEvent e)
2745    {
2746  3 newView(null, true);
2747    }
2748   
2749    /**
2750    * Creates and shows a new view of the current alignment.
2751    *
2752    * @param viewTitle
2753    * title of newly created view; if null, one will be generated
2754    * @param copyAnnotation
2755    * if true then duplicate all annnotation, groups and settings
2756    * @return new alignment panel, already displayed.
2757    */
 
2758  3 toggle public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2759    {
2760    /*
2761    * Create a new AlignmentPanel (with its own, new Viewport)
2762    */
2763  3 AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
2764  3 if (!copyAnnotation)
2765    {
2766    /*
2767    * remove all groups and annotation except for the automatic stuff
2768    */
2769  0 newap.av.getAlignment().deleteAllGroups();
2770  0 newap.av.getAlignment().deleteAllAnnotations(false);
2771    }
2772   
2773  3 newap.av.setGatherViewsHere(false);
2774   
2775  3 if (viewport.viewName == null)
2776    {
2777  3 viewport.viewName = MessageManager
2778    .getString("label.view_name_original");
2779    }
2780   
2781    /*
2782    * Views share the same edits undo and redo stacks
2783    */
2784  3 newap.av.setHistoryList(viewport.getHistoryList());
2785  3 newap.av.setRedoList(viewport.getRedoList());
2786   
2787    /*
2788    * Views share the same mappings; need to deregister any new mappings
2789    * created by copyAlignPanel, and register the new reference to the shared
2790    * mappings
2791    */
2792  3 newap.av.replaceMappings(viewport.getAlignment());
2793   
2794    /*
2795    * start up cDNA consensus (if applicable) now mappings are in place
2796    */
2797  3 if (newap.av.initComplementConsensus())
2798    {
2799  0 newap.refresh(true); // adjust layout of annotations
2800    }
2801   
2802  3 newap.av.viewName = getNewViewName(viewTitle);
2803   
2804  3 addAlignmentPanel(newap, true);
2805  3 newap.alignmentChanged();
2806   
2807  3 if (alignPanels.size() == 2)
2808    {
2809  3 viewport.setGatherViewsHere(true);
2810    }
2811  3 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2812  3 return newap;
2813    }
2814   
2815    /**
2816    * Make a new name for the view, ensuring it is unique within the current
2817    * sequenceSetId. (This used to be essential for Jalview Project archives, but
2818    * these now use viewId. Unique view names are still desirable for usability.)
2819    *
2820    * @param viewTitle
2821    * @return
2822    */
 
2823  3 toggle protected String getNewViewName(String viewTitle)
2824    {
2825  3 int index = Desktop.getViewCount(viewport.getSequenceSetId());
2826  3 boolean addFirstIndex = false;
2827  3 if (viewTitle == null || viewTitle.trim().length() == 0)
2828    {
2829  3 viewTitle = MessageManager.getString("action.view");
2830  3 addFirstIndex = true;
2831    }
2832    else
2833    {
2834  0 index = 1;// we count from 1 if given a specific name
2835    }
2836  3 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
2837   
2838  3 List<Component> comps = PaintRefresher.components
2839    .get(viewport.getSequenceSetId());
2840   
2841  3 List<String> existingNames = getExistingViewNames(comps);
2842   
2843  3 while (existingNames.contains(newViewName))
2844    {
2845  0 newViewName = viewTitle + " " + (++index);
2846    }
2847  3 return newViewName;
2848    }
2849   
2850    /**
2851    * Returns a list of distinct view names found in the given list of
2852    * components. View names are held on the viewport of an AlignmentPanel.
2853    *
2854    * @param comps
2855    * @return
2856    */
 
2857  3 toggle protected List<String> getExistingViewNames(List<Component> comps)
2858    {
2859  3 List<String> existingNames = new ArrayList<>();
2860  3 for (Component comp : comps)
2861    {
2862  18 if (comp instanceof AlignmentPanel)
2863    {
2864  6 AlignmentPanel ap = (AlignmentPanel) comp;
2865  6 if (!existingNames.contains(ap.av.viewName))
2866    {
2867  6 existingNames.add(ap.av.viewName);
2868    }
2869    }
2870    }
2871  3 return existingNames;
2872    }
2873   
2874    /**
2875    * Explode tabbed views into separate windows.
2876    */
 
2877  0 toggle @Override
2878    public void expandViews_actionPerformed(ActionEvent e)
2879    {
2880  0 Desktop.explodeViews(this);
2881    }
2882   
2883    /**
2884    * Gather views in separate windows back into a tabbed presentation.
2885    */
 
2886  0 toggle @Override
2887    public void gatherViews_actionPerformed(ActionEvent e)
2888    {
2889  0 Desktop.instance.gatherViews(this);
2890    }
2891   
2892    /**
2893    * DOCUMENT ME!
2894    *
2895    * @param e
2896    * DOCUMENT ME!
2897    */
 
2898  0 toggle @Override
2899    public void font_actionPerformed(ActionEvent e)
2900    {
2901  0 new FontChooser(alignPanel);
2902    }
2903   
2904    /**
2905    * DOCUMENT ME!
2906    *
2907    * @param e
2908    * DOCUMENT ME!
2909    */
 
2910  0 toggle @Override
2911    protected void seqLimit_actionPerformed(ActionEvent e)
2912    {
2913  0 viewport.setShowJVSuffix(seqLimits.isSelected());
2914   
2915  0 alignPanel.getIdPanel().getIdCanvas()
2916    .setPreferredSize(alignPanel.calculateIdWidth());
2917  0 alignPanel.paintAlignment(true, false);
2918    }
2919   
 
2920  0 toggle @Override
2921    public void idRightAlign_actionPerformed(ActionEvent e)
2922    {
2923  0 viewport.setRightAlignIds(idRightAlign.isSelected());
2924  0 alignPanel.paintAlignment(false, false);
2925    }
2926   
 
2927  0 toggle @Override
2928    public void centreColumnLabels_actionPerformed(ActionEvent e)
2929    {
2930  0 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
2931  0 alignPanel.paintAlignment(false, false);
2932    }
2933   
2934    /*
2935    * (non-Javadoc)
2936    *
2937    * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
2938    */
 
2939  0 toggle @Override
2940    protected void followHighlight_actionPerformed()
2941    {
2942    /*
2943    * Set the 'follow' flag on the Viewport (and scroll to position if now
2944    * true).
2945    */
2946  0 final boolean state = this.followHighlightMenuItem.getState();
2947  0 viewport.setFollowHighlight(state);
2948  0 if (state)
2949    {
2950  0 alignPanel.scrollToPosition(viewport.getSearchResults(), false);
2951    }
2952    }
2953   
2954    /**
2955    * DOCUMENT ME!
2956    *
2957    * @param e
2958    * DOCUMENT ME!
2959    */
 
2960  0 toggle @Override
2961    protected void colourTextMenuItem_actionPerformed(ActionEvent e)
2962    {
2963  0 viewport.setColourText(colourTextMenuItem.isSelected());
2964  0 alignPanel.paintAlignment(false, false);
2965    }
2966   
2967    /**
2968    * DOCUMENT ME!
2969    *
2970    * @param e
2971    * DOCUMENT ME!
2972    */
 
2973  1 toggle @Override
2974    public void wrapMenuItem_actionPerformed(ActionEvent e)
2975    {
2976  1 scaleAbove.setVisible(wrapMenuItem.isSelected());
2977  1 scaleLeft.setVisible(wrapMenuItem.isSelected());
2978  1 scaleRight.setVisible(wrapMenuItem.isSelected());
2979  1 viewport.setWrapAlignment(wrapMenuItem.isSelected());
2980  1 alignPanel.updateLayout();
2981    }
2982   
 
2983  0 toggle @Override
2984    public void showAllSeqs_actionPerformed(ActionEvent e)
2985    {
2986  0 viewport.showAllHiddenSeqs();
2987    }
2988   
 
2989  0 toggle @Override
2990    public void showAllColumns_actionPerformed(ActionEvent e)
2991    {
2992  0 viewport.showAllHiddenColumns();
2993  0 alignPanel.paintAlignment(true, true);
2994  0 viewport.sendSelection();
2995    }
2996   
 
2997  0 toggle @Override
2998    public void hideSelSequences_actionPerformed(ActionEvent e)
2999    {
3000  0 viewport.hideAllSelectedSeqs();
3001    }
3002   
3003    /**
3004    * called by key handler and the hide all/show all menu items
3005    *
3006    * @param toggleSeqs
3007    * @param toggleCols
3008    */
 
3009  0 toggle private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3010    {
3011   
3012  0 boolean hide = false;
3013  0 SequenceGroup sg = viewport.getSelectionGroup();
3014  0 if (!toggleSeqs && !toggleCols)
3015    {
3016    // Hide everything by the current selection - this is a hack - we do the
3017    // invert and then hide
3018    // first check that there will be visible columns after the invert.
3019  0 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3020    && sg.getStartRes() <= sg.getEndRes()))
3021    {
3022    // now invert the sequence set, if required - empty selection implies
3023    // that no hiding is required.
3024  0 if (sg != null)
3025    {
3026  0 invertSequenceMenuItem_actionPerformed(null);
3027  0 sg = viewport.getSelectionGroup();
3028  0 toggleSeqs = true;
3029   
3030    }
3031  0 viewport.expandColSelection(sg, true);
3032    // finally invert the column selection and get the new sequence
3033    // selection.
3034  0 invertColSel_actionPerformed(null);
3035  0 toggleCols = true;
3036    }
3037    }
3038   
3039  0 if (toggleSeqs)
3040    {
3041  0 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3042    {
3043  0 hideSelSequences_actionPerformed(null);
3044  0 hide = true;
3045    }
3046  0 else if (!(toggleCols && viewport.hasSelectedColumns()))
3047    {
3048  0 showAllSeqs_actionPerformed(null);
3049    }
3050    }
3051   
3052  0 if (toggleCols)
3053    {
3054  0 if (viewport.hasSelectedColumns())
3055    {
3056  0 hideSelColumns_actionPerformed(null);
3057  0 if (!toggleSeqs)
3058    {
3059  0 viewport.setSelectionGroup(sg);
3060    }
3061    }
3062  0 else if (!hide)
3063    {
3064  0 showAllColumns_actionPerformed(null);
3065    }
3066    }
3067    }
3068   
3069    /*
3070    * (non-Javadoc)
3071    *
3072    * @see
3073    * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3074    * event.ActionEvent)
3075    */
 
3076  0 toggle @Override
3077    public void hideAllButSelection_actionPerformed(ActionEvent e)
3078    {
3079  0 toggleHiddenRegions(false, false);
3080  0 viewport.sendSelection();
3081    }
3082   
3083    /*
3084    * (non-Javadoc)
3085    *
3086    * @see
3087    * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3088    * .ActionEvent)
3089    */
 
3090  0 toggle @Override
3091    public void hideAllSelection_actionPerformed(ActionEvent e)
3092    {
3093  0 SequenceGroup sg = viewport.getSelectionGroup();
3094  0 viewport.expandColSelection(sg, false);
3095  0 viewport.hideAllSelectedSeqs();
3096  0 viewport.hideSelectedColumns();
3097  0 alignPanel.paintAlignment(true, true);
3098  0 viewport.sendSelection();
3099    }
3100   
3101    /*
3102    * (non-Javadoc)
3103    *
3104    * @see
3105    * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3106    * ActionEvent)
3107    */
 
3108  0 toggle @Override
3109    public void showAllhidden_actionPerformed(ActionEvent e)
3110    {
3111  0 viewport.showAllHiddenColumns();
3112  0 viewport.showAllHiddenSeqs();
3113  0 alignPanel.paintAlignment(true, true);
3114  0 viewport.sendSelection();
3115    }
3116   
 
3117  2 toggle @Override
3118    public void hideSelColumns_actionPerformed(ActionEvent e)
3119    {
3120  2 viewport.hideSelectedColumns();
3121  2 alignPanel.paintAlignment(true, true);
3122  2 viewport.sendSelection();
3123    }
3124   
 
3125  0 toggle @Override
3126    public void hiddenMarkers_actionPerformed(ActionEvent e)
3127    {
3128  0 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3129  0 repaint();
3130    }
3131   
3132    /**
3133    * DOCUMENT ME!
3134    *
3135    * @param e
3136    * DOCUMENT ME!
3137    */
 
3138  0 toggle @Override
3139    protected void scaleAbove_actionPerformed(ActionEvent e)
3140    {
3141  0 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3142    // TODO: do we actually need to update overview for scale above change ?
3143  0 alignPanel.paintAlignment(true, false);
3144    }
3145   
3146    /**
3147    * DOCUMENT ME!
3148    *
3149    * @param e
3150    * DOCUMENT ME!
3151    */
 
3152  0 toggle @Override
3153    protected void scaleLeft_actionPerformed(ActionEvent e)
3154    {
3155  0 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3156  0 alignPanel.paintAlignment(true, false);
3157    }
3158   
3159    /**
3160    * DOCUMENT ME!
3161    *
3162    * @param e
3163    * DOCUMENT ME!
3164    */
 
3165  0 toggle @Override
3166    protected void scaleRight_actionPerformed(ActionEvent e)
3167    {
3168  0 viewport.setScaleRightWrapped(scaleRight.isSelected());
3169  0 alignPanel.paintAlignment(true, false);
3170    }
3171   
3172    /**
3173    * DOCUMENT ME!
3174    *
3175    * @param e
3176    * DOCUMENT ME!
3177    */
 
3178  0 toggle @Override
3179    public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3180    {
3181  0 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3182  0 alignPanel.paintAlignment(false, false);
3183    }
3184   
3185    /**
3186    * DOCUMENT ME!
3187    *
3188    * @param e
3189    * DOCUMENT ME!
3190    */
 
3191  0 toggle @Override
3192    public void viewTextMenuItem_actionPerformed(ActionEvent e)
3193    {
3194  0 viewport.setShowText(viewTextMenuItem.isSelected());
3195  0 alignPanel.paintAlignment(false, false);
3196    }
3197   
3198    /**
3199    * DOCUMENT ME!
3200    *
3201    * @param e
3202    * DOCUMENT ME!
3203    */
 
3204  0 toggle @Override
3205    protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3206    {
3207  0 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3208  0 alignPanel.paintAlignment(false, false);
3209    }
3210   
3211    public FeatureSettings featureSettings;
3212   
 
3213  2 toggle @Override
3214    public FeatureSettingsControllerI getFeatureSettingsUI()
3215    {
3216  2 return featureSettings;
3217    }
3218   
 
3219  0 toggle @Override
3220    public void featureSettings_actionPerformed(ActionEvent e)
3221    {
3222  0 if (featureSettings != null)
3223    {
3224  0 featureSettings.close();
3225  0 featureSettings = null;
3226    }
3227  0 if (!showSeqFeatures.isSelected())
3228    {
3229    // make sure features are actually displayed
3230  0 showSeqFeatures.setSelected(true);
3231  0 showSeqFeatures_actionPerformed(null);
3232    }
3233  0 featureSettings = new FeatureSettings(this);
3234    }
3235   
3236    /**
3237    * Set or clear 'Show Sequence Features'
3238    *
3239    * @param evt
3240    * DOCUMENT ME!
3241    */
 
3242  0 toggle @Override
3243    public void showSeqFeatures_actionPerformed(ActionEvent evt)
3244    {
3245  0 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3246  0 alignPanel.paintAlignment(true, true);
3247    }
3248   
3249    /**
3250    * Action on toggle of the 'Show annotations' menu item. This shows or hides
3251    * the annotations panel as a whole.
3252    *
3253    * The options to show/hide all annotations should be enabled when the panel
3254    * is shown, and disabled when the panel is hidden.
3255    *
3256    * @param e
3257    */
 
3258  0 toggle @Override
3259    public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3260    {
3261  0 final boolean setVisible = annotationPanelMenuItem.isSelected();
3262  0 viewport.setShowAnnotation(setVisible);
3263  0 this.showAllSeqAnnotations.setEnabled(setVisible);
3264  0 this.hideAllSeqAnnotations.setEnabled(setVisible);
3265  0 this.showAllAlAnnotations.setEnabled(setVisible);
3266  0 this.hideAllAlAnnotations.setEnabled(setVisible);
3267  0 alignPanel.updateLayout();
3268    }
3269   
 
3270  0 toggle @Override
3271    public void alignmentProperties()
3272    {
3273  0 JComponent pane;
3274  0 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3275   
3276    .formatAsHtml();
3277  0 String content = MessageManager.formatMessage("label.html_content",
3278    new Object[]
3279    { contents.toString() });
3280  0 contents = null;
3281   
3282  0 if (Jalview.isJS())
3283    {
3284  0 JLabel textLabel = new JLabel();
3285  0 textLabel.setText(content);
3286  0 textLabel.setBackground(Color.WHITE);
3287   
3288  0 pane = new JPanel(new BorderLayout());
3289  0 ((JPanel) pane).setOpaque(true);
3290  0 pane.setBackground(Color.WHITE);
3291  0 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3292    }
3293    else
3294    {
3295  0 JEditorPane editPane = new JEditorPane("text/html", "");
3296  0 editPane.setEditable(false);
3297  0 editPane.setText(content);
3298  0 pane = editPane;
3299    }
3300   
3301  0 JInternalFrame frame = new JInternalFrame();
3302   
3303  0 frame.getContentPane().add(new JScrollPane(pane));
3304   
3305  0 Desktop.addInternalFrame(frame, MessageManager
3306    .formatMessage("label.alignment_properties", new Object[]
3307    { getTitle() }), 500, 400);
3308    }
3309   
3310    /**
3311    * DOCUMENT ME!
3312    *
3313    * @param e
3314    * DOCUMENT ME!
3315    */
 
3316  0 toggle @Override
3317    public void overviewMenuItem_actionPerformed(ActionEvent e)
3318    {
3319  0 if (alignPanel.overviewPanel != null)
3320    {
3321  0 return;
3322    }
3323   
3324  0 JInternalFrame frame = new JInternalFrame();
3325  0 final OverviewPanel overview = new OverviewPanel(alignPanel);
3326  0 frame.setContentPane(overview);
3327  0 Desktop.addInternalFrame(frame, MessageManager
3328    .formatMessage("label.overview_params", new Object[]
3329    { this.getTitle() }), true, frame.getWidth(), frame.getHeight(),
3330    true, true);
3331  0 frame.pack();
3332  0 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3333  0 frame.addInternalFrameListener(
3334    new javax.swing.event.InternalFrameAdapter()
3335    {
 
3336  0 toggle @Override
3337    public void internalFrameClosed(
3338    javax.swing.event.InternalFrameEvent evt)
3339    {
3340  0 overview.dispose();
3341  0 alignPanel.setOverviewPanel(null);
3342    };
3343    });
3344  0 if (getKeyListeners().length > 0)
3345    {
3346  0 frame.addKeyListener(getKeyListeners()[0]);
3347    }
3348   
3349  0 alignPanel.setOverviewPanel(overview);
3350    }
3351   
 
3352  0 toggle @Override
3353    public void textColour_actionPerformed()
3354    {
3355  0 new TextColourChooser().chooseColour(alignPanel, null);
3356    }
3357   
3358    /*
3359    * public void covariationColour_actionPerformed() {
3360    * changeColour(new
3361    * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3362    * ()[0])); }
3363    */
 
3364  0 toggle @Override
3365    public void annotationColour_actionPerformed()
3366    {
3367  0 new AnnotationColourChooser(viewport, alignPanel);
3368    }
3369   
 
3370  0 toggle @Override
3371    public void annotationColumn_actionPerformed(ActionEvent e)
3372    {
3373  0 new AnnotationColumnChooser(viewport, alignPanel);
3374    }
3375   
3376    /**
3377    * Action on the user checking or unchecking the option to apply the selected
3378    * colour scheme to all groups. If unchecked, groups may have their own
3379    * independent colour schemes.
3380    *
3381    * @param selected
3382    */
 
3383  3 toggle @Override
3384    public void applyToAllGroups_actionPerformed(boolean selected)
3385    {
3386  3 viewport.setColourAppliesToAllGroups(selected);
3387    }
3388   
3389    /**
3390    * Action on user selecting a colour from the colour menu
3391    *
3392    * @param name
3393    * the name (not the menu item label!) of the colour scheme
3394    */
 
3395  15 toggle @Override
3396    public void changeColour_actionPerformed(String name)
3397    {
3398    /*
3399    * 'User Defined' opens a panel to configure or load a
3400    * user-defined colour scheme
3401    */
3402  15 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3403    {
3404  0 new UserDefinedColours(alignPanel);
3405  0 return;
3406    }
3407   
3408    /*
3409    * otherwise set the chosen colour scheme (or null for 'None')
3410    */
3411  15 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3412    viewport.getAlignment(), viewport.getHiddenRepSequences());
3413  15 changeColour(cs);
3414    }
3415   
3416    /**
3417    * Actions on setting or changing the alignment colour scheme
3418    *
3419    * @param cs
3420    */
 
3421  108 toggle @Override
3422    public void changeColour(ColourSchemeI cs)
3423    {
3424    // TODO: pull up to controller method
3425  108 ColourMenuHelper.setColourSelected(colourMenu, cs);
3426   
3427  108 viewport.setGlobalColourScheme(cs);
3428   
3429  108 alignPanel.paintAlignment(true, true);
3430    }
3431   
3432    /**
3433    * Show the PID threshold slider panel
3434    */
 
3435  6 toggle @Override
3436    protected void modifyPID_actionPerformed()
3437    {
3438  6 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3439    alignPanel.getViewName());
3440  6 SliderPanel.showPIDSlider();
3441    }
3442   
3443    /**
3444    * Show the Conservation slider panel
3445    */
 
3446  6 toggle @Override
3447    protected void modifyConservation_actionPerformed()
3448    {
3449  6 SliderPanel.setConservationSlider(alignPanel,
3450    viewport.getResidueShading(), alignPanel.getViewName());
3451  6 SliderPanel.showConservationSlider();
3452    }
3453   
3454    /**
3455    * Action on selecting or deselecting (Colour) By Conservation
3456    */
 
3457  8 toggle @Override
3458    public void conservationMenuItem_actionPerformed(boolean selected)
3459    {
3460  8 modifyConservation.setEnabled(selected);
3461  8 viewport.setConservationSelected(selected);
3462  8 viewport.getResidueShading().setConservationApplied(selected);
3463   
3464  8 changeColour(viewport.getGlobalColourScheme());
3465  8 if (selected)
3466    {
3467  6 modifyConservation_actionPerformed();
3468    }
3469    else
3470    {
3471  2 SliderPanel.hideConservationSlider();
3472    }
3473    }
3474   
3475    /**
3476    * Action on selecting or deselecting (Colour) Above PID Threshold
3477    */
 
3478  9 toggle @Override
3479    public void abovePIDThreshold_actionPerformed(boolean selected)
3480    {
3481  9 modifyPID.setEnabled(selected);
3482  9 viewport.setAbovePIDThreshold(selected);
3483  9 if (!selected)
3484    {
3485  3 viewport.getResidueShading().setThreshold(0,
3486    viewport.isIgnoreGapsConsensus());
3487    }
3488   
3489  9 changeColour(viewport.getGlobalColourScheme());
3490  9 if (selected)
3491    {
3492  6 modifyPID_actionPerformed();
3493    }
3494    else
3495    {
3496  3 SliderPanel.hidePIDSlider();
3497    }
3498    }
3499   
3500    /**
3501    * DOCUMENT ME!
3502    *
3503    * @param e
3504    * DOCUMENT ME!
3505    */
 
3506  0 toggle @Override
3507    public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3508    {
3509  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3510  0 AlignmentSorter.sortByPID(viewport.getAlignment(),
3511    viewport.getAlignment().getSequenceAt(0));
3512  0 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3513    viewport.getAlignment()));
3514  0 alignPanel.paintAlignment(true, false);
3515    }
3516   
3517    /**
3518    * DOCUMENT ME!
3519    *
3520    * @param e
3521    * DOCUMENT ME!
3522    */
 
3523  0 toggle @Override
3524    public void sortIDMenuItem_actionPerformed(ActionEvent e)
3525    {
3526  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3527  0 AlignmentSorter.sortByID(viewport.getAlignment());
3528  0 addHistoryItem(
3529    new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3530  0 alignPanel.paintAlignment(true, false);
3531    }
3532   
3533    /**
3534    * DOCUMENT ME!
3535    *
3536    * @param e
3537    * DOCUMENT ME!
3538    */
 
3539  0 toggle @Override
3540    public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3541    {
3542  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3543  0 AlignmentSorter.sortByLength(viewport.getAlignment());
3544  0 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3545    viewport.getAlignment()));
3546  0 alignPanel.paintAlignment(true, false);
3547    }
3548   
3549    /**
3550    * DOCUMENT ME!
3551    *
3552    * @param e
3553    * DOCUMENT ME!
3554    */
 
3555  0 toggle @Override
3556    public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3557    {
3558  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3559  0 AlignmentSorter.sortByGroup(viewport.getAlignment());
3560  0 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3561    viewport.getAlignment()));
3562   
3563  0 alignPanel.paintAlignment(true, false);
3564    }
3565   
3566    /**
3567    * DOCUMENT ME!
3568    *
3569    * @param e
3570    * DOCUMENT ME!
3571    */
 
3572  0 toggle @Override
3573    public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3574    {
3575  0 new RedundancyPanel(alignPanel, this);
3576    }
3577   
3578    /**
3579    * DOCUMENT ME!
3580    *
3581    * @param e
3582    * DOCUMENT ME!
3583    */
 
3584  0 toggle @Override
3585    public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3586    {
3587  0 if ((viewport.getSelectionGroup() == null)
3588    || (viewport.getSelectionGroup().getSize() < 2))
3589    {
3590  0 JvOptionPane.showInternalMessageDialog(this,
3591    MessageManager.getString(
3592    "label.you_must_select_least_two_sequences"),
3593    MessageManager.getString("label.invalid_selection"),
3594    JvOptionPane.WARNING_MESSAGE);
3595    }
3596    else
3597    {
3598  0 JInternalFrame frame = new JInternalFrame();
3599  0 frame.setContentPane(new PairwiseAlignPanel(viewport));
3600  0 Desktop.addInternalFrame(frame,
3601    MessageManager.getString("action.pairwise_alignment"), 600,
3602    500);
3603    }
3604    }
3605   
 
3606  0 toggle @Override
3607    public void autoCalculate_actionPerformed(ActionEvent e)
3608    {
3609  0 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3610  0 if (viewport.autoCalculateConsensus)
3611    {
3612  0 viewport.firePropertyChange("alignment", null,
3613    viewport.getAlignment().getSequences());
3614    }
3615    }
3616   
 
3617  0 toggle @Override
3618    public void sortByTreeOption_actionPerformed(ActionEvent e)
3619    {
3620  0 viewport.sortByTree = sortByTree.isSelected();
3621    }
3622   
 
3623  0 toggle @Override
3624    protected void listenToViewSelections_actionPerformed(ActionEvent e)
3625    {
3626  0 viewport.followSelection = listenToViewSelections.isSelected();
3627    }
3628   
3629    /**
3630    * Constructs a tree panel and adds it to the desktop
3631    *
3632    * @param type
3633    * tree type (NJ or AV)
3634    * @param modelName
3635    * name of score model used to compute the tree
3636    * @param options
3637    * parameters for the distance or similarity calculation
3638    */
 
3639  0 toggle void newTreePanel(String type, String modelName,
3640    SimilarityParamsI options)
3641    {
3642  0 String frameTitle = "";
3643  0 TreePanel tp;
3644   
3645  0 boolean onSelection = false;
3646  0 if (viewport.getSelectionGroup() != null
3647    && viewport.getSelectionGroup().getSize() > 0)
3648    {
3649  0 SequenceGroup sg = viewport.getSelectionGroup();
3650   
3651    /* Decide if the selection is a column region */
3652  0 for (SequenceI _s : sg.getSequences())
3653    {
3654  0 if (_s.getLength() < sg.getEndRes())
3655    {
3656  0 JvOptionPane.showMessageDialog(Desktop.desktop,
3657    MessageManager.getString(
3658    "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3659    MessageManager.getString(
3660    "label.sequences_selection_not_aligned"),
3661    JvOptionPane.WARNING_MESSAGE);
3662   
3663  0 return;
3664    }
3665    }
3666  0 onSelection = true;
3667    }
3668    else
3669    {
3670  0 if (viewport.getAlignment().getHeight() < 2)
3671    {
3672  0 return;
3673    }
3674    }
3675   
3676  0 tp = new TreePanel(alignPanel, type, modelName, options);
3677  0 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3678   
3679  0 frameTitle += " from ";
3680   
3681  0 if (viewport.viewName != null)
3682    {
3683  0 frameTitle += viewport.viewName + " of ";
3684    }
3685   
3686  0 frameTitle += this.title;
3687   
3688  0 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3689    }
3690   
3691    /**
3692    * DOCUMENT ME!
3693    *
3694    * @param title
3695    * DOCUMENT ME!
3696    * @param order
3697    * DOCUMENT ME!
3698    */
 
3699  0 toggle public void addSortByOrderMenuItem(String title,
3700    final AlignmentOrder order)
3701    {
3702  0 final JMenuItem item = new JMenuItem(MessageManager
3703    .formatMessage("action.by_title_param", new Object[]
3704    { title }));
3705  0 sort.add(item);
3706  0 item.addActionListener(new java.awt.event.ActionListener()
3707    {
 
3708  0 toggle @Override
3709    public void actionPerformed(ActionEvent e)
3710    {
3711  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3712   
3713    // TODO: JBPNote - have to map order entries to curent SequenceI
3714    // pointers
3715  0 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3716   
3717  0 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3718    viewport.getAlignment()));
3719   
3720  0 alignPanel.paintAlignment(true, false);
3721    }
3722    });
3723    }
3724   
3725    /**
3726    * Add a new sort by annotation score menu item
3727    *
3728    * @param sort
3729    * the menu to add the option to
3730    * @param scoreLabel
3731    * the label used to retrieve scores for each sequence on the
3732    * alignment
3733    */
 
3734  4 toggle public void addSortByAnnotScoreMenuItem(JMenu sort,
3735    final String scoreLabel)
3736    {
3737  4 final JMenuItem item = new JMenuItem(scoreLabel);
3738  4 sort.add(item);
3739  4 item.addActionListener(new java.awt.event.ActionListener()
3740    {
 
3741  0 toggle @Override
3742    public void actionPerformed(ActionEvent e)
3743    {
3744  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3745  0 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3746    viewport.getAlignment());// ,viewport.getSelectionGroup());
3747  0 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3748    viewport.getAlignment()));
3749  0 alignPanel.paintAlignment(true, false);
3750    }
3751    });
3752    }
3753   
3754    /**
3755    * last hash for alignment's annotation array - used to minimise cost of
3756    * rebuild.
3757    */
3758    protected int _annotationScoreVectorHash;
3759   
3760    /**
3761    * search the alignment and rebuild the sort by annotation score submenu the
3762    * last alignment annotation vector hash is stored to minimize cost of
3763    * rebuilding in subsequence calls.
3764    *
3765    */
 
3766  196 toggle @Override
3767    public void buildSortByAnnotationScoresMenu()
3768    {
3769  196 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3770    {
3771  0 return;
3772    }
3773   
3774  196 if (viewport.getAlignment().getAlignmentAnnotation()
3775    .hashCode() != _annotationScoreVectorHash)
3776    {
3777  195 sortByAnnotScore.removeAll();
3778    // almost certainly a quicker way to do this - but we keep it simple
3779  195 Hashtable scoreSorts = new Hashtable();
3780  195 AlignmentAnnotation aann[];
3781  195 for (SequenceI sqa : viewport.getAlignment().getSequences())
3782    {
3783  2034 aann = sqa.getAnnotation();
3784  2312 for (int i = 0; aann != null && i < aann.length; i++)
3785    {
3786  278 if (aann[i].hasScore() && aann[i].sequenceRef != null)
3787    {
3788  152 scoreSorts.put(aann[i].label, aann[i].label);
3789    }
3790    }
3791    }
3792  195 Enumeration labels = scoreSorts.keys();
3793  199 while (labels.hasMoreElements())
3794    {
3795  4 addSortByAnnotScoreMenuItem(sortByAnnotScore,
3796    (String) labels.nextElement());
3797    }
3798  195 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
3799  195 scoreSorts.clear();
3800   
3801  195 _annotationScoreVectorHash = viewport.getAlignment()
3802    .getAlignmentAnnotation().hashCode();
3803    }
3804    }
3805   
3806    /**
3807    * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
3808    * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
3809    * call. Listeners are added to remove the menu item when the treePanel is
3810    * closed, and adjust the tree leaf to sequence mapping when the alignment is
3811    * modified.
3812    */
 
3813  0 toggle @Override
3814    public void buildTreeSortMenu()
3815    {
3816  0 sortByTreeMenu.removeAll();
3817   
3818  0 List<Component> comps = PaintRefresher.components
3819    .get(viewport.getSequenceSetId());
3820  0 List<TreePanel> treePanels = new ArrayList<>();
3821  0 for (Component comp : comps)
3822    {
3823  0 if (comp instanceof TreePanel)
3824    {
3825  0 treePanels.add((TreePanel) comp);
3826    }
3827    }
3828   
3829  0 if (treePanels.size() < 1)
3830    {
3831  0 sortByTreeMenu.setVisible(false);
3832  0 return;
3833    }
3834   
3835  0 sortByTreeMenu.setVisible(true);
3836   
3837  0 for (final TreePanel tp : treePanels)
3838    {
3839  0 final JMenuItem item = new JMenuItem(tp.getTitle());
3840  0 item.addActionListener(new java.awt.event.ActionListener()
3841    {
 
3842  0 toggle @Override
3843    public void actionPerformed(ActionEvent e)
3844    {
3845  0 tp.sortByTree_actionPerformed();
3846  0 addHistoryItem(tp.sortAlignmentIn(alignPanel));
3847   
3848    }
3849    });
3850   
3851  0 sortByTreeMenu.add(item);
3852    }
3853    }
3854   
 
3855  0 toggle public boolean sortBy(AlignmentOrder alorder, String undoname)
3856    {
3857  0 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3858  0 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
3859  0 if (undoname != null)
3860    {
3861  0 addHistoryItem(new OrderCommand(undoname, oldOrder,
3862    viewport.getAlignment()));
3863    }
3864  0 alignPanel.paintAlignment(true, false);
3865  0 return true;
3866    }
3867   
3868    /**
3869    * Work out whether the whole set of sequences or just the selected set will
3870    * be submitted for multiple alignment.
3871    *
3872    */
 
3873  0 toggle public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
3874    {
3875    // Now, check we have enough sequences
3876  0 AlignmentView msa = null;
3877   
3878  0 if ((viewport.getSelectionGroup() != null)
3879    && (viewport.getSelectionGroup().getSize() > 1))
3880    {
3881    // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
3882    // some common interface!
3883    /*
3884    * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
3885    * SequenceI[sz = seqs.getSize(false)];
3886    *
3887    * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
3888    * seqs.getSequenceAt(i); }
3889    */
3890  0 msa = viewport.getAlignmentView(true);
3891    }
3892  0 else if (viewport.getSelectionGroup() != null
3893    && viewport.getSelectionGroup().getSize() == 1)
3894    {
3895  0 int option = JvOptionPane.showConfirmDialog(this,
3896    MessageManager.getString("warn.oneseq_msainput_selection"),
3897    MessageManager.getString("label.invalid_selection"),
3898    JvOptionPane.OK_CANCEL_OPTION);
3899  0 if (option == JvOptionPane.OK_OPTION)
3900    {
3901  0 msa = viewport.getAlignmentView(false);
3902    }
3903    }
3904    else
3905    {
3906  0 msa = viewport.getAlignmentView(false);
3907    }
3908  0 return msa;
3909    }
3910   
3911    /**
3912    * Decides what is submitted to a secondary structure prediction service: the
3913    * first sequence in the alignment, or in the current selection, or, if the
3914    * alignment is 'aligned' (ie padded with gaps), then the currently selected
3915    * region or the whole alignment. (where the first sequence in the set is the
3916    * one that the prediction will be for).
3917    */
 
3918  0 toggle public AlignmentView gatherSeqOrMsaForSecStrPrediction()
3919    {
3920  0 AlignmentView seqs = null;
3921   
3922  0 if ((viewport.getSelectionGroup() != null)
3923    && (viewport.getSelectionGroup().getSize() > 0))
3924    {
3925  0 seqs = viewport.getAlignmentView(true);
3926    }
3927    else
3928    {
3929  0 seqs = viewport.getAlignmentView(false);
3930    }
3931    // limit sequences - JBPNote in future - could spawn multiple prediction
3932    // jobs
3933    // TODO: viewport.getAlignment().isAligned is a global state - the local
3934    // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
3935  0 if (!viewport.getAlignment().isAligned(false))
3936    {
3937  0 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
3938    // TODO: if seqs.getSequences().length>1 then should really have warned
3939    // user!
3940   
3941    }
3942  0 return seqs;
3943    }
3944   
3945    /**
3946    * DOCUMENT ME!
3947    *
3948    * @param e
3949    * DOCUMENT ME!
3950    */
 
3951  0 toggle @Override
3952    protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
3953    {
3954    // Pick the tree file
3955  0 JalviewFileChooser chooser = new JalviewFileChooser(
3956    jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
3957  0 chooser.setFileView(new JalviewFileView());
3958  0 chooser.setDialogTitle(
3959    MessageManager.getString("label.select_newick_like_tree_file"));
3960  0 chooser.setToolTipText(
3961    MessageManager.getString("label.load_tree_file"));
3962   
3963  0 chooser.response(new jalview.util.dialogrunner.RunResponse(
3964    JalviewFileChooser.APPROVE_OPTION)
3965    {
 
3966  0 toggle @Override
3967    public void run()
3968    {
3969  0 String filePath = chooser.getSelectedFile().getPath();
3970  0 Cache.setProperty("LAST_DIRECTORY", filePath);
3971  0 NewickFile fin = null;
3972  0 try
3973    {
3974  0 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
3975    DataSourceType.FILE));
3976  0 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
3977    } catch (Exception ex)
3978    {
3979  0 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
3980    MessageManager
3981    .getString("label.problem_reading_tree_file"),
3982    JvOptionPane.WARNING_MESSAGE);
3983  0 ex.printStackTrace();
3984    }
3985  0 if (fin != null && fin.hasWarningMessage())
3986    {
3987  0 JvOptionPane.showMessageDialog(Desktop.desktop,
3988    fin.getWarningMessage(),
3989    MessageManager.getString(
3990    "label.possible_problem_with_tree_file"),
3991    JvOptionPane.WARNING_MESSAGE);
3992    }
3993    }
3994    }).openDialog(this);
3995    }
3996   
 
3997  0 toggle public TreePanel showNewickTree(NewickFile nf, String treeTitle)
3998    {
3999  0 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4000    }
4001   
 
4002  12 toggle public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4003    int h, int x, int y)
4004    {
4005  12 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4006    }
4007   
4008    /**
4009    * Add a treeviewer for the tree extracted from a Newick file object to the
4010    * current alignment view
4011    *
4012    * @param nf
4013    * the tree
4014    * @param title
4015    * tree viewer title
4016    * @param input
4017    * Associated alignment input data (or null)
4018    * @param w
4019    * width
4020    * @param h
4021    * height
4022    * @param x
4023    * position
4024    * @param y
4025    * position
4026    * @return TreePanel handle
4027    */
 
4028  12 toggle public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4029    AlignmentView input, int w, int h, int x, int y)
4030    {
4031  12 TreePanel tp = null;
4032   
4033  12 try
4034    {
4035  12 nf.parse();
4036   
4037  12 if (nf.getTree() != null)
4038    {
4039  12 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4040   
4041  12 tp.setSize(w, h);
4042   
4043  12 if (x > 0 && y > 0)
4044    {
4045  12 tp.setLocation(x, y);
4046    }
4047   
4048  12 Desktop.addInternalFrame(tp, treeTitle, w, h);
4049    }
4050    } catch (Exception ex)
4051    {
4052  0 ex.printStackTrace();
4053    }
4054   
4055  12 return tp;
4056    }
4057   
4058    private boolean buildingMenu = false;
4059   
4060    /**
4061    * Generates menu items and listener event actions for web service clients
4062    *
4063    */
 
4064  1110 toggle public void BuildWebServiceMenu()
4065    {
4066  1110 while (buildingMenu)
4067    {
4068  0 try
4069    {
4070  0 System.err.println("Waiting for building menu to finish.");
4071  0 Thread.sleep(10);
4072    } catch (Exception e)
4073    {
4074    }
4075    }
4076  1110 final AlignFrame me = this;
4077  1110 buildingMenu = true;
4078  1110 new Thread(new Runnable()
4079    {
 
4080  1110 toggle @Override
4081    public void run()
4082    {
4083  1110 final List<JMenuItem> legacyItems = new ArrayList<>();
4084  1110 try
4085    {
4086    // System.err.println("Building ws menu again "
4087    // + Thread.currentThread());
4088    // TODO: add support for context dependent disabling of services based
4089    // on
4090    // alignment and current selection
4091    // TODO: add additional serviceHandle parameter to specify abstract
4092    // handler
4093    // class independently of AbstractName
4094    // TODO: add in rediscovery GUI function to restart discoverer
4095    // TODO: group services by location as well as function and/or
4096    // introduce
4097    // object broker mechanism.
4098  1110 final Vector<JMenu> wsmenu = new Vector<>();
4099  1110 final IProgressIndicator af = me;
4100   
4101    /*
4102    * do not i18n these strings - they are hard-coded in class
4103    * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4104    * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4105    */
4106  1110 final JMenu msawsmenu = new JMenu("Alignment");
4107  1110 final JMenu secstrmenu = new JMenu(
4108    "Secondary Structure Prediction");
4109  1110 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4110  1110 final JMenu analymenu = new JMenu("Analysis");
4111  1110 final JMenu dismenu = new JMenu("Protein Disorder");
4112    // JAL-940 - only show secondary structure prediction services from
4113    // the legacy server
4114  1110 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4115    // &&
4116  1110 Discoverer.services != null && (Discoverer.services.size() > 0))
4117    {
4118    // TODO: refactor to allow list of AbstractName/Handler bindings to
4119    // be
4120    // stored or retrieved from elsewhere
4121    // No MSAWS used any more:
4122    // Vector msaws = null; // (Vector)
4123    // Discoverer.services.get("MsaWS");
4124  1110 Vector secstrpr = (Vector) Discoverer.services
4125    .get("SecStrPred");
4126  1110 if (secstrpr != null)
4127    {
4128    // Add any secondary structure prediction services
4129  2220 for (int i = 0, j = secstrpr.size(); i < j; i++)
4130    {
4131  1110 final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) secstrpr
4132    .get(i);
4133  1110 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4134    .getServiceClient(sh);
4135  1110 int p = secstrmenu.getItemCount();
4136  1110 impl.attachWSMenuEntry(secstrmenu, me);
4137  1110 int q = secstrmenu.getItemCount();
4138  2220 for (int litm = p; litm < q; litm++)
4139    {
4140  1110 legacyItems.add(secstrmenu.getItem(litm));
4141    }
4142    }
4143    }
4144    }
4145   
4146    // Add all submenus in the order they should appear on the web
4147    // services menu
4148  1110 wsmenu.add(msawsmenu);
4149  1110 wsmenu.add(secstrmenu);
4150  1110 wsmenu.add(dismenu);
4151  1110 wsmenu.add(analymenu);
4152    // No search services yet
4153    // wsmenu.add(seqsrchmenu);
4154   
4155  1110 javax.swing.SwingUtilities.invokeLater(new Runnable()
4156    {
 
4157  1110 toggle @Override
4158    public void run()
4159    {
4160  1110 try
4161    {
4162  1110 webService.removeAll();
4163    // first, add discovered services onto the webservices menu
4164  1110 if (wsmenu.size() > 0)
4165    {
4166  5550 for (int i = 0, j = wsmenu.size(); i < j; i++)
4167    {
4168  4440 webService.add(wsmenu.get(i));
4169    }
4170    }
4171    else
4172    {
4173  0 webService.add(me.webServiceNoServices);
4174    }
4175    // TODO: move into separate menu builder class.
4176  1110 boolean new_sspred = false;
4177  1110 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
4178    {
4179  1110 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4180  1110 if (jws2servs != null)
4181    {
4182  1110 if (jws2servs.hasServices())
4183    {
4184  474 jws2servs.attachWSMenuEntry(webService, me);
4185  466 for (Jws2Instance sv : jws2servs.getServices())
4186    {
4187  6524 if (sv.description.toLowerCase().contains("jpred"))
4188    {
4189  0 for (JMenuItem jmi : legacyItems)
4190    {
4191  0 jmi.setVisible(false);
4192    }
4193    }
4194    }
4195   
4196    }
4197  1102 if (jws2servs.isRunning())
4198    {
4199  636 JMenuItem tm = new JMenuItem(
4200    "Still discovering JABA Services");
4201  636 tm.setEnabled(false);
4202  636 webService.add(tm);
4203    }
4204    }
4205    }
4206  1102 build_urlServiceMenu(me.webService);
4207  1102 build_fetchdbmenu(webService);
4208  1102 for (JMenu item : wsmenu)
4209    {
4210  4408 if (item.getItemCount() == 0)
4211    {
4212  1272 item.setEnabled(false);
4213    }
4214    else
4215    {
4216  3136 item.setEnabled(true);
4217    }
4218    }
4219    } catch (Exception e)
4220    {
4221  8 Cache.log.debug(
4222    "Exception during web service menu building process.",
4223    e);
4224    }
4225    }
4226    });
4227    } catch (Exception e)
4228    {
4229    }
4230  1110 buildingMenu = false;
4231    }
4232    }).start();
4233   
4234    }
4235   
4236    /**
4237    * construct any groupURL type service menu entries.
4238    *
4239    * @param webService
4240    */
 
4241  1102 toggle private void build_urlServiceMenu(JMenu webService)
4242    {
4243    // TODO: remove this code when 2.7 is released
4244    // DEBUG - alignmentView
4245    /*
4246    * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4247    * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4248    *
4249    * @Override public void actionPerformed(ActionEvent e) {
4250    * jalview.datamodel.AlignmentView
4251    * .testSelectionViews(af.viewport.getAlignment(),
4252    * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4253    *
4254    * }); webService.add(testAlView);
4255    */
4256    // TODO: refactor to RestClient discoverer and merge menu entries for
4257    // rest-style services with other types of analysis/calculation service
4258    // SHmmr test client - still being implemented.
4259    // DEBUG - alignmentView
4260   
4261  1102 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4262    .getRestClients())
4263    {
4264  1102 client.attachWSMenuEntry(
4265    JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4266    this);
4267    }
4268    }
4269   
4270    /**
4271    * Searches the alignment sequences for xRefs and builds the Show
4272    * Cross-References menu (formerly called Show Products), with database
4273    * sources for which cross-references are found (protein sources for a
4274    * nucleotide alignment and vice versa)
4275    *
4276    * @return true if Show Cross-references menu should be enabled
4277    */
 
4278  376 toggle public boolean canShowProducts()
4279    {
4280  376 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4281  376 AlignmentI dataset = viewport.getAlignment().getDataset();
4282   
4283  376 showProducts.removeAll();
4284  376 final boolean dna = viewport.getAlignment().isNucleotide();
4285   
4286  376 if (seqs == null || seqs.length == 0)
4287    {
4288    // nothing to see here.
4289  0 return false;
4290    }
4291   
4292  376 boolean showp = false;
4293  376 try
4294    {
4295  376 List<String> ptypes = new CrossRef(seqs, dataset)
4296    .findXrefSourcesForSequences(dna);
4297   
4298  376 for (final String source : ptypes)
4299    {
4300  0 showp = true;
4301  0 final AlignFrame af = this;
4302  0 JMenuItem xtype = new JMenuItem(source);
4303  0 xtype.addActionListener(new ActionListener()
4304    {
 
4305  0 toggle @Override
4306    public void actionPerformed(ActionEvent e)
4307    {
4308  0 showProductsFor(af.viewport.getSequenceSelection(), dna,
4309    source);
4310    }
4311    });
4312  0 showProducts.add(xtype);
4313    }
4314  376 showProducts.setVisible(showp);
4315  376 showProducts.setEnabled(showp);
4316    } catch (Exception e)
4317    {
4318  0 Cache.log.warn(
4319    "canShowProducts threw an exception - please report to help@jalview.org",
4320    e);
4321  0 return false;
4322    }
4323  376 return showp;
4324    }
4325   
4326    /**
4327    * Finds and displays cross-references for the selected sequences (protein
4328    * products for nucleotide sequences, dna coding sequences for peptides).
4329    *
4330    * @param sel
4331    * the sequences to show cross-references for
4332    * @param dna
4333    * true if from a nucleotide alignment (so showing proteins)
4334    * @param source
4335    * the database to show cross-references for
4336    */
 
4337  0 toggle protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4338    final String source)
4339    {
4340  0 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4341    .start();
4342    }
4343   
4344    /**
4345    * Construct and display a new frame containing the translation of this
4346    * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4347    */
 
4348  0 toggle @Override
4349    public void showTranslation_actionPerformed(ActionEvent e)
4350    {
4351  0 AlignmentI al = null;
4352  0 try
4353    {
4354  0 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4355   
4356  0 al = dna.translateCdna();
4357    } catch (Exception ex)
4358    {
4359  0 jalview.bin.Cache.log.error(
4360    "Exception during translation. Please report this !", ex);
4361  0 final String msg = MessageManager.getString(
4362    "label.error_when_translating_sequences_submit_bug_report");
4363  0 final String errorTitle = MessageManager
4364    .getString("label.implementation_error")
4365    + MessageManager.getString("label.translation_failed");
4366  0 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4367    JvOptionPane.ERROR_MESSAGE);
4368  0 return;
4369    }
4370  0 if (al == null || al.getHeight() == 0)
4371    {
4372  0 final String msg = MessageManager.getString(
4373    "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4374  0 final String errorTitle = MessageManager
4375    .getString("label.translation_failed");
4376  0 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4377    JvOptionPane.WARNING_MESSAGE);
4378    }
4379    else
4380    {
4381  0 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4382  0 af.setFileFormat(this.currentFileFormat);
4383  0 final String newTitle = MessageManager
4384    .formatMessage("label.translation_of_params", new Object[]
4385    { this.getTitle() });
4386  0 af.setTitle(newTitle);
4387  0 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4388    {
4389  0 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4390  0 viewport.openSplitFrame(af, new Alignment(seqs));
4391    }
4392    else
4393    {
4394  0 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4395    DEFAULT_HEIGHT);
4396    }
4397    }
4398    }
4399   
4400    /**
4401    * Set the file format
4402    *
4403    * @param format
4404    */
 
4405  108 toggle public void setFileFormat(FileFormatI format)
4406    {
4407  108 this.currentFileFormat = format;
4408    }
4409   
4410    /**
4411    * Try to load a features file onto the alignment.
4412    *
4413    * @param file
4414    * contents or path to retrieve file or a File object
4415    * @param sourceType
4416    * access mode of file (see jalview.io.AlignFile)
4417    * @return true if features file was parsed correctly.
4418    */
 
4419  2 toggle public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4420    {
4421    // BH 2018
4422  2 return avc.parseFeaturesFile(file, sourceType,
4423    Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4424   
4425    }
4426   
 
4427  3 toggle @Override
4428    public void refreshFeatureUI(boolean enableIfNecessary)
4429    {
4430    // note - currently this is only still here rather than in the controller
4431    // because of the featureSettings hard reference that is yet to be
4432    // abstracted
4433  3 if (enableIfNecessary)
4434    {
4435  3 viewport.setShowSequenceFeatures(true);
4436  3 showSeqFeatures.setSelected(true);
4437    }
4438   
4439    }
4440   
 
4441  0 toggle @Override
4442    public void dragEnter(DropTargetDragEvent evt)
4443    {
4444    }
4445   
 
4446  0 toggle @Override
4447    public void dragExit(DropTargetEvent evt)
4448    {
4449    }
4450   
 
4451  0 toggle @Override
4452    public void dragOver(DropTargetDragEvent evt)
4453    {
4454    }
4455   
 
4456  0 toggle @Override
4457    public void dropActionChanged(DropTargetDragEvent evt)
4458    {
4459    }
4460   
 
4461  0 toggle @Override
4462    public void drop(DropTargetDropEvent evt)
4463    {
4464    // JAL-1552 - acceptDrop required before getTransferable call for
4465    // Java's Transferable for native dnd
4466  0 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4467  0 Transferable t = evt.getTransferable();
4468   
4469  0 final AlignFrame thisaf = this;
4470  0 final List<Object> files = new ArrayList<>();
4471  0 List<DataSourceType> protocols = new ArrayList<>();
4472   
4473  0 try
4474    {
4475  0 Desktop.transferFromDropTarget(files, protocols, evt, t);
4476    } catch (Exception e)
4477    {
4478  0 e.printStackTrace();
4479    }
4480  0 if (files != null)
4481    {
4482  0 new Thread(new Runnable()
4483    {
 
4484  0 toggle @Override
4485    public void run()
4486    {
4487  0 try
4488    {
4489    // check to see if any of these files have names matching sequences
4490    // in
4491    // the alignment
4492  0 SequenceIdMatcher idm = new SequenceIdMatcher(
4493    viewport.getAlignment().getSequencesArray());
4494    /**
4495    * Object[] { String,SequenceI}
4496    */
4497  0 ArrayList<Object[]> filesmatched = new ArrayList<>();
4498  0 ArrayList<Object> filesnotmatched = new ArrayList<>();
4499  0 for (int i = 0; i < files.size(); i++)
4500    {
4501    // BH 2018
4502  0 Object file = files.get(i);
4503  0 String fileName = file.toString();
4504  0 String pdbfn = "";
4505  0 DataSourceType protocol = (file instanceof File
4506    ? DataSourceType.FILE
4507    : FormatAdapter.checkProtocol(fileName));
4508  0 if (protocol == DataSourceType.FILE)
4509    {
4510  0 File fl = (file instanceof File ? (File) file
4511    : new File(fileName));
4512  0 pdbfn = fl.getName();
4513    }
4514  0 else if (protocol == DataSourceType.URL)
4515    {
4516  0 URL url = new URL(fileName);
4517  0 pdbfn = url.getFile();
4518    }
4519  0 if (pdbfn.length() > 0)
4520    {
4521    // attempt to find a match in the alignment
4522  0 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4523  0 int l = 0, c = pdbfn.indexOf(".");
4524  0 while (mtch == null && c != -1)
4525    {
4526  0 do
4527    {
4528  0 l = c;
4529  ? } while ((c = pdbfn.indexOf(".", l)) > l);
4530  0 if (l > -1)
4531    {
4532  0 pdbfn = pdbfn.substring(0, l);
4533    }
4534  0 mtch = idm.findAllIdMatches(pdbfn);
4535    }
4536  0 if (mtch != null)
4537    {
4538  0 FileFormatI type;
4539  0 try
4540    {
4541  0 type = new IdentifyFile().identify(file, protocol);
4542    } catch (Exception ex)
4543    {
4544  0 type = null;
4545    }
4546  0 if (type != null && type.isStructureFile())
4547    {
4548  0 filesmatched.add(new Object[] { file, protocol, mtch });
4549  0 continue;
4550    }
4551    }
4552    // File wasn't named like one of the sequences or wasn't a PDB
4553    // file.
4554  0 filesnotmatched.add(file);
4555    }
4556    }
4557  0 int assocfiles = 0;
4558  0 if (filesmatched.size() > 0)
4559    {
4560  0 boolean autoAssociate = Cache
4561    .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4562  0 if (!autoAssociate)
4563    {
4564  0 String msg = MessageManager.formatMessage(
4565    "label.automatically_associate_structure_files_with_sequences_same_name",
4566    new Object[]
4567    { Integer.valueOf(filesmatched.size())
4568    .toString() });
4569  0 String ttl = MessageManager.getString(
4570    "label.automatically_associate_structure_files_by_name");
4571  0 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4572    ttl, JvOptionPane.YES_NO_OPTION);
4573  0 autoAssociate = choice == JvOptionPane.YES_OPTION;
4574    }
4575  0 if (autoAssociate)
4576    {
4577  0 for (Object[] fm : filesmatched)
4578    {
4579    // try and associate
4580    // TODO: may want to set a standard ID naming formalism for
4581    // associating PDB files which have no IDs.
4582  0 for (SequenceI toassoc : (SequenceI[]) fm[2])
4583    {
4584  0 PDBEntry pe = new AssociatePdbFileWithSeq()
4585    .associatePdbWithSeq(fm[0].toString(),
4586    (DataSourceType) fm[1], toassoc, false,
4587    Desktop.instance);
4588  0 if (pe != null)
4589    {
4590  0 System.err.println("Associated file : "
4591    + (fm[0].toString()) + " with "
4592    + toassoc.getDisplayId(true));
4593  0 assocfiles++;
4594    }
4595    }
4596    // TODO: do we need to update overview ? only if features are
4597    // shown I guess
4598  0 alignPanel.paintAlignment(true, false);
4599    }
4600    }
4601    else
4602    {
4603    /*
4604    * add declined structures as sequences
4605    */
4606  0 for (Object[] o : filesmatched)
4607    {
4608  0 filesnotmatched.add(o[0]);
4609    }
4610    }
4611    }
4612  0 if (filesnotmatched.size() > 0)
4613    {
4614  0 if (assocfiles > 0 && (Cache.getDefault(
4615    "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4616    || JvOptionPane.showConfirmDialog(thisaf,
4617    "<html>" + MessageManager.formatMessage(
4618    "label.ignore_unmatched_dropped_files_info",
4619    new Object[]
4620    { Integer.valueOf(
4621    filesnotmatched.size())
4622    .toString() })
4623    + "</html>",
4624    MessageManager.getString(
4625    "label.ignore_unmatched_dropped_files"),
4626    JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4627    {
4628  0 return;
4629    }
4630  0 for (Object fn : filesnotmatched)
4631    {
4632  0 loadJalviewDataFile(fn, null, null, null);
4633    }
4634   
4635    }
4636    } catch (Exception ex)
4637    {
4638  0 ex.printStackTrace();
4639    }
4640    }
4641    }).start();
4642    }
4643    }
4644   
4645    /**
4646    * Attempt to load a "dropped" file or URL string, by testing in turn for
4647    * <ul>
4648    * <li>an Annotation file</li>
4649    * <li>a JNet file</li>
4650    * <li>a features file</li>
4651    * <li>else try to interpret as an alignment file</li>
4652    * </ul>
4653    *
4654    * @param file
4655    * either a filename or a URL string.
4656    */
 
4657  5 toggle public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4658    FileFormatI format, SequenceI assocSeq)
4659    {
4660    // BH 2018 was String file
4661  5 try
4662    {
4663  5 if (sourceType == null)
4664    {
4665  0 sourceType = FormatAdapter.checkProtocol(file);
4666    }
4667    // if the file isn't identified, or not positively identified as some
4668    // other filetype (PFAM is default unidentified alignment file type) then
4669    // try to parse as annotation.
4670  5 boolean isAnnotation = (format == null
4671    || FileFormat.Pfam.equals(format))
4672    ? new AnnotationFile().annotateAlignmentView(viewport,
4673    file, sourceType)
4674    : false;
4675   
4676  5 if (!isAnnotation)
4677    {
4678    // first see if its a T-COFFEE score file
4679  3 TCoffeeScoreFile tcf = null;
4680  3 try
4681    {
4682  3 tcf = new TCoffeeScoreFile(file, sourceType);
4683  3 if (tcf.isValid())
4684    {
4685  1 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4686    {
4687  1 buildColourMenu();
4688  1 changeColour(
4689    new TCoffeeColourScheme(viewport.getAlignment()));
4690  1 isAnnotation = true;
4691  1 setStatus(MessageManager.getString(
4692    "label.successfully_pasted_tcoffee_scores_to_alignment"));
4693    }
4694    else
4695    {
4696    // some problem - if no warning its probable that the ID matching
4697    // process didn't work
4698  0 JvOptionPane.showMessageDialog(Desktop.desktop,
4699  0 tcf.getWarningMessage() == null
4700    ? MessageManager.getString(
4701    "label.check_file_matches_sequence_ids_alignment")
4702    : tcf.getWarningMessage(),
4703    MessageManager.getString(
4704    "label.problem_reading_tcoffee_score_file"),
4705    JvOptionPane.WARNING_MESSAGE);
4706    }
4707    }
4708    else
4709    {
4710  2 tcf = null;
4711    }
4712    } catch (Exception x)
4713    {
4714  0 Cache.log.debug(
4715    "Exception when processing data source as T-COFFEE score file",
4716    x);
4717  0 tcf = null;
4718    }
4719  3 if (tcf == null)
4720    {
4721    // try to see if its a JNet 'concise' style annotation file *before*
4722    // we
4723    // try to parse it as a features file
4724  2 if (format == null)
4725    {
4726  2 format = new IdentifyFile().identify(file, sourceType);
4727    }
4728  2 if (FileFormat.ScoreMatrix == format)
4729    {
4730  0 ScoreMatrixFile sm = new ScoreMatrixFile(
4731    new FileParse(file, sourceType));
4732  0 sm.parse();
4733    // todo: i18n this message
4734  0 setStatus(MessageManager.formatMessage(
4735    "label.successfully_loaded_matrix",
4736    sm.getMatrixName()));
4737    }
4738  2 else if (FileFormat.Jnet.equals(format))
4739    {
4740  0 JPredFile predictions = new JPredFile(file, sourceType);
4741  0 new JnetAnnotationMaker();
4742  0 JnetAnnotationMaker.add_annotation(predictions,
4743    viewport.getAlignment(), 0, false);
4744  0 viewport.getAlignment().setupJPredAlignment();
4745  0 isAnnotation = true;
4746    }
4747    // else if (IdentifyFile.FeaturesFile.equals(format))
4748  2 else if (FileFormat.Features.equals(format))
4749    {
4750  2 if (parseFeaturesFile(file, sourceType))
4751    {
4752  2 alignPanel.paintAlignment(true, true);
4753    }
4754    }
4755    else
4756    {
4757  0 new FileLoader().LoadFile(viewport, file, sourceType, format);
4758    }
4759    }
4760    }
4761  5 if (isAnnotation)
4762    {
4763   
4764  3 alignPanel.adjustAnnotationHeight();
4765  3 viewport.updateSequenceIdColours();
4766  3 buildSortByAnnotationScoresMenu();
4767  3 alignPanel.paintAlignment(true, true);
4768    }
4769    } catch (Exception ex)
4770    {
4771  0 ex.printStackTrace();
4772    } catch (OutOfMemoryError oom)
4773    {
4774  0 try
4775    {
4776  0 System.gc();
4777    } catch (Exception x)
4778    {
4779    }
4780  0 new OOMWarning(
4781    "loading data "
4782  0 + (sourceType != null
4783  0 ? (sourceType == DataSourceType.PASTE
4784    ? "from clipboard."
4785    : "using " + sourceType + " from "
4786    + file)
4787    : ".")
4788  0 + (format != null
4789    ? "(parsing as '" + format + "' file)"
4790    : ""),
4791    oom, Desktop.desktop);
4792    }
4793    }
4794   
4795    /**
4796    * Method invoked by the ChangeListener on the tabbed pane, in other words
4797    * when a different tabbed pane is selected by the user or programmatically.
4798    */
 
4799  149 toggle @Override
4800    public void tabSelectionChanged(int index)
4801    {
4802  149 if (index > -1)
4803    {
4804  91 alignPanel = alignPanels.get(index);
4805  91 viewport = alignPanel.av;
4806  91 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
4807  91 setMenusFromViewport(viewport);
4808    }
4809   
4810    /*
4811    * 'focus' any colour slider that is open to the selected viewport
4812    */
4813  149 if (viewport.getConservationSelected())
4814    {
4815  2 SliderPanel.setConservationSlider(alignPanel,
4816    viewport.getResidueShading(), alignPanel.getViewName());
4817    }
4818    else
4819    {
4820  147 SliderPanel.hideConservationSlider();
4821    }
4822  149 if (viewport.getAbovePIDThreshold())
4823    {
4824  2 SliderPanel.setPIDSliderSource(alignPanel,
4825    viewport.getResidueShading(), alignPanel.getViewName());
4826    }
4827    else
4828    {
4829  147 SliderPanel.hidePIDSlider();
4830    }
4831   
4832    /*
4833    * If there is a frame linked to this one in a SplitPane, switch it to the
4834    * same view tab index. No infinite recursion of calls should happen, since
4835    * tabSelectionChanged() should not get invoked on setting the selected
4836    * index to an unchanged value. Guard against setting an invalid index
4837    * before the new view peer tab has been created.
4838    */
4839  149 final AlignViewportI peer = viewport.getCodingComplement();
4840  149 if (peer != null)
4841    {
4842  0 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
4843    .getAlignPanel().alignFrame;
4844  0 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
4845    {
4846  0 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
4847    }
4848    }
4849    }
4850   
4851    /**
4852    * On right mouse click on view tab, prompt for and set new view name.
4853    */
 
4854  0 toggle @Override
4855    public void tabbedPane_mousePressed(MouseEvent e)
4856    {
4857  0 if (e.isPopupTrigger())
4858    {
4859  0 String msg = MessageManager.getString("label.enter_view_name");
4860  0 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
4861  0 String reply = JvOptionPane.showInputDialog(msg, ttl);
4862   
4863  0 if (reply != null)
4864    {
4865  0 viewport.viewName = reply;
4866    // TODO warn if reply is in getExistingViewNames()?
4867  0 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
4868    }
4869    }
4870    }
4871   
 
4872  14 toggle public AlignViewport getCurrentView()
4873    {
4874  14 return viewport;
4875    }
4876   
4877    /**
4878    * Open the dialog for regex description parsing.
4879    */
 
4880  0 toggle @Override
4881    protected void extractScores_actionPerformed(ActionEvent e)
4882    {
4883  0 ParseProperties pp = new jalview.analysis.ParseProperties(
4884    viewport.getAlignment());
4885    // TODO: verify regex and introduce GUI dialog for version 2.5
4886    // if (pp.getScoresFromDescription("col", "score column ",
4887    // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
4888    // true)>0)
4889  0 if (pp.getScoresFromDescription("description column",
4890    "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
4891    {
4892  0 buildSortByAnnotationScoresMenu();
4893    }
4894    }
4895   
4896    /*
4897    * (non-Javadoc)
4898    *
4899    * @see
4900    * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
4901    * )
4902    */
 
4903  0 toggle @Override
4904    protected void showDbRefs_actionPerformed(ActionEvent e)
4905    {
4906  0 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
4907    }
4908   
4909    /*
4910    * (non-Javadoc)
4911    *
4912    * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
4913    * ActionEvent)
4914    */
 
4915  0 toggle @Override
4916    protected void showNpFeats_actionPerformed(ActionEvent e)
4917    {
4918  0 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
4919    }
4920   
4921    /**
4922    * find the viewport amongst the tabs in this alignment frame and close that
4923    * tab
4924    *
4925    * @param av
4926    */
 
4927  0 toggle public boolean closeView(AlignViewportI av)
4928    {
4929  0 if (viewport == av)
4930    {
4931  0 this.closeMenuItem_actionPerformed(false);
4932  0 return true;
4933    }
4934  0 Component[] comp = tabbedPane.getComponents();
4935  0 for (int i = 0; comp != null && i < comp.length; i++)
4936    {
4937  0 if (comp[i] instanceof AlignmentPanel)
4938    {
4939  0 if (((AlignmentPanel) comp[i]).av == av)
4940    {
4941    // close the view.
4942  0 closeView((AlignmentPanel) comp[i]);
4943  0 return true;
4944    }
4945    }
4946    }
4947  0 return false;
4948    }
4949   
 
4950  1102 toggle protected void build_fetchdbmenu(JMenu webService)
4951    {
4952    // Temporary hack - DBRef Fetcher always top level ws entry.
4953    // TODO We probably want to store a sequence database checklist in
4954    // preferences and have checkboxes.. rather than individual sources selected
4955    // here
4956  1102 final JMenu rfetch = new JMenu(
4957    MessageManager.getString("action.fetch_db_references"));
4958  1102 rfetch.setToolTipText(MessageManager.getString(
4959    "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
4960  1102 webService.add(rfetch);
4961   
4962  1102 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
4963    MessageManager.getString("option.trim_retrieved_seqs"));
4964  1102 trimrs.setToolTipText(
4965    MessageManager.getString("label.trim_retrieved_sequences"));
4966  1102 trimrs.setSelected(
4967    Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
4968  1102 trimrs.addActionListener(new ActionListener()
4969    {
 
4970  0 toggle @Override
4971    public void actionPerformed(ActionEvent e)
4972    {
4973  0 trimrs.setSelected(trimrs.isSelected());
4974  0 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
4975    Boolean.valueOf(trimrs.isSelected()).toString());
4976    };
4977    });
4978  1102 rfetch.add(trimrs);
4979  1102 JMenuItem fetchr = new JMenuItem(
4980    MessageManager.getString("label.standard_databases"));
4981  1102 fetchr.setToolTipText(
4982    MessageManager.getString("label.fetch_embl_uniprot"));
4983  1102 fetchr.addActionListener(new ActionListener()
4984    {
4985   
 
4986  0 toggle @Override
4987    public void actionPerformed(ActionEvent e)
4988    {
4989  0 new Thread(new Runnable()
4990    {
 
4991  0 toggle @Override
4992    public void run()
4993    {
4994  0 boolean isNucleotide = alignPanel.alignFrame.getViewport()
4995    .getAlignment().isNucleotide();
4996  0 DBRefFetcher dbRefFetcher = new DBRefFetcher(
4997    alignPanel.av.getSequenceSelection(),
4998    alignPanel.alignFrame, null,
4999    alignPanel.alignFrame.featureSettings, isNucleotide);
5000  0 dbRefFetcher.addListener(new FetchFinishedListenerI()
5001    {
 
5002  0 toggle @Override
5003    public void finished()
5004    {
5005  0 AlignFrame.this.setMenusForViewport();
5006    }
5007    });
5008  0 dbRefFetcher.fetchDBRefs(false);
5009    }
5010    }).start();
5011   
5012    }
5013   
5014    });
5015  1102 rfetch.add(fetchr);
5016  1102 final AlignFrame me = this;
5017  1102 new Thread(new Runnable()
5018    {
 
5019  1102 toggle @Override
5020    public void run()
5021    {
5022  1102 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5023    .getSequenceFetcherSingleton(me);
5024  1102 javax.swing.SwingUtilities.invokeLater(new Runnable()
5025    {
 
5026  1102 toggle @Override
5027    public void run()
5028    {
5029  1102 String[] dbclasses = sf.getOrderedSupportedSources();
5030    // sf.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class);
5031    // jalview.util.QuickSort.sort(otherdb, otherdb);
5032  1102 List<DbSourceProxy> otherdb;
5033  1102 JMenu dfetch = new JMenu();
5034  1102 JMenu ifetch = new JMenu();
5035  1102 JMenuItem fetchr = null;
5036  1102 int comp = 0, icomp = 0, mcomp = 15;
5037  1102 String mname = null;
5038  1102 int dbi = 0;
5039  1102 for (String dbclass : dbclasses)
5040    {
5041  9918 otherdb = sf.getSourceProxy(dbclass);
5042    // add a single entry for this class, or submenu allowing 'fetch
5043    // all' or pick one
5044  9918 if (otherdb == null || otherdb.size() < 1)
5045    {
5046  0 continue;
5047    }
5048    // List<DbSourceProxy> dbs=otherdb;
5049    // otherdb=new ArrayList<DbSourceProxy>();
5050    // for (DbSourceProxy db:dbs)
5051    // {
5052    // if (!db.isA(DBRefSource.ALIGNMENTDB)
5053    // }
5054  9918 if (mname == null)
5055    {
5056  1102 mname = "From " + dbclass;
5057    }
5058  9918 if (otherdb.size() == 1)
5059    {
5060  9918 final DbSourceProxy[] dassource = otherdb
5061    .toArray(new DbSourceProxy[0]);
5062  9918 DbSourceProxy src = otherdb.get(0);
5063  9918 fetchr = new JMenuItem(src.getDbSource());
5064  9918 fetchr.addActionListener(new ActionListener()
5065    {
5066   
 
5067  0 toggle @Override
5068    public void actionPerformed(ActionEvent e)
5069    {
5070  0 new Thread(new Runnable()
5071    {
5072   
 
5073  0 toggle @Override
5074    public void run()
5075    {
5076  0 boolean isNucleotide = alignPanel.alignFrame
5077    .getViewport().getAlignment()
5078    .isNucleotide();
5079  0 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5080    alignPanel.av.getSequenceSelection(),
5081    alignPanel.alignFrame, dassource,
5082    alignPanel.alignFrame.featureSettings,
5083    isNucleotide);
5084  0 dbRefFetcher
5085    .addListener(new FetchFinishedListenerI()
5086    {
 
5087  0 toggle @Override
5088    public void finished()
5089    {
5090  0 AlignFrame.this.setMenusForViewport();
5091    }
5092    });
5093  0 dbRefFetcher.fetchDBRefs(false);
5094    }
5095    }).start();
5096    }
5097   
5098    });
5099  9918 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5100    MessageManager.formatMessage(
5101    "label.fetch_retrieve_from", new Object[]
5102    { src.getDbName() })));
5103  9918 dfetch.add(fetchr);
5104  9918 comp++;
5105    }
5106    else
5107    {
5108  0 final DbSourceProxy[] dassource = otherdb
5109    .toArray(new DbSourceProxy[0]);
5110    // fetch all entry
5111  0 DbSourceProxy src = otherdb.get(0);
5112  0 fetchr = new JMenuItem(MessageManager
5113    .formatMessage("label.fetch_all_param", new Object[]
5114    { src.getDbSource() }));
5115  0 fetchr.addActionListener(new ActionListener()
5116    {
 
5117  0 toggle @Override
5118    public void actionPerformed(ActionEvent e)
5119    {
5120  0 new Thread(new Runnable()
5121    {
5122   
 
5123  0 toggle @Override
5124    public void run()
5125    {
5126  0 boolean isNucleotide = alignPanel.alignFrame
5127    .getViewport().getAlignment()
5128    .isNucleotide();
5129  0 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5130    alignPanel.av.getSequenceSelection(),
5131    alignPanel.alignFrame, dassource,
5132    alignPanel.alignFrame.featureSettings,
5133    isNucleotide);
5134  0 dbRefFetcher
5135    .addListener(new FetchFinishedListenerI()
5136    {
 
5137  0 toggle @Override
5138    public void finished()
5139    {
5140  0 AlignFrame.this.setMenusForViewport();
5141    }
5142    });
5143  0 dbRefFetcher.fetchDBRefs(false);
5144    }
5145    }).start();
5146    }
5147    });
5148   
5149  0 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5150    MessageManager.formatMessage(
5151    "label.fetch_retrieve_from_all_sources",
5152    new Object[]
5153    { Integer.valueOf(otherdb.size())
5154    .toString(),
5155    src.getDbSource(), src.getDbName() })));
5156  0 dfetch.add(fetchr);
5157  0 comp++;
5158    // and then build the rest of the individual menus
5159  0 ifetch = new JMenu(MessageManager.formatMessage(
5160    "label.source_from_db_source", new Object[]
5161    { src.getDbSource() }));
5162  0 icomp = 0;
5163  0 String imname = null;
5164  0 int i = 0;
5165  0 for (DbSourceProxy sproxy : otherdb)
5166    {
5167  0 String dbname = sproxy.getDbName();
5168  0 String sname = dbname.length() > 5
5169    ? dbname.substring(0, 5) + "..."
5170    : dbname;
5171  0 String msname = dbname.length() > 10
5172    ? dbname.substring(0, 10) + "..."
5173    : dbname;
5174  0 if (imname == null)
5175    {
5176  0 imname = MessageManager
5177    .formatMessage("label.from_msname", new Object[]
5178    { sname });
5179    }
5180  0 fetchr = new JMenuItem(msname);
5181  0 final DbSourceProxy[] dassrc = { sproxy };
5182  0 fetchr.addActionListener(new ActionListener()
5183    {
5184   
 
5185  0 toggle @Override
5186    public void actionPerformed(ActionEvent e)
5187    {
5188  0 new Thread(new Runnable()
5189    {
5190   
 
5191  0 toggle @Override
5192    public void run()
5193    {
5194  0 boolean isNucleotide = alignPanel.alignFrame
5195    .getViewport().getAlignment()
5196    .isNucleotide();
5197  0 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5198    alignPanel.av.getSequenceSelection(),
5199    alignPanel.alignFrame, dassrc,
5200    alignPanel.alignFrame.featureSettings,
5201    isNucleotide);
5202  0 dbRefFetcher
5203    .addListener(new FetchFinishedListenerI()
5204    {
 
5205  0 toggle @Override
5206    public void finished()
5207    {
5208  0 AlignFrame.this.setMenusForViewport();
5209    }
5210    });
5211  0 dbRefFetcher.fetchDBRefs(false);
5212    }
5213    }).start();
5214    }
5215   
5216    });
5217  0 fetchr.setToolTipText(
5218    "<html>" + MessageManager.formatMessage(
5219    "label.fetch_retrieve_from", new Object[]
5220    { dbname }));
5221  0 ifetch.add(fetchr);
5222  0 ++i;
5223  0 if (++icomp >= mcomp || i == (otherdb.size()))
5224    {
5225  0 ifetch.setText(MessageManager.formatMessage(
5226    "label.source_to_target", imname, sname));
5227  0 dfetch.add(ifetch);
5228  0 ifetch = new JMenu();
5229  0 imname = null;
5230  0 icomp = 0;
5231  0 comp++;
5232    }
5233    }
5234    }
5235  9918 ++dbi;
5236  9918 if (comp >= mcomp || dbi >= (dbclasses.length))
5237    {
5238  1102 dfetch.setText(MessageManager.formatMessage(
5239    "label.source_to_target", mname, dbclass));
5240  1102 rfetch.add(dfetch);
5241  1102 dfetch = new JMenu();
5242  1102 mname = null;
5243  1102 comp = 0;
5244    }
5245    }
5246    }
5247    });
5248    }
5249    }).start();
5250   
5251    }
5252   
5253    /**
5254    * Left justify the whole alignment.
5255    */
 
5256  0 toggle @Override
5257    protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5258    {
5259  0 AlignmentI al = viewport.getAlignment();
5260  0 al.justify(false);
5261  0 viewport.firePropertyChange("alignment", null, al);
5262    }
5263   
5264    /**
5265    * Right justify the whole alignment.
5266    */
 
5267  0 toggle @Override
5268    protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5269    {
5270  0 AlignmentI al = viewport.getAlignment();
5271  0 al.justify(true);
5272  0 viewport.firePropertyChange("alignment", null, al);
5273    }
5274   
 
5275  5 toggle @Override
5276    public void setShowSeqFeatures(boolean b)
5277    {
5278  5 showSeqFeatures.setSelected(b);
5279  5 viewport.setShowSequenceFeatures(b);
5280    }
5281   
5282    /*
5283    * (non-Javadoc)
5284    *
5285    * @see
5286    * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5287    * awt.event.ActionEvent)
5288    */
 
5289  0 toggle @Override
5290    protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5291    {
5292  0 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5293  0 alignPanel.paintAlignment(false, false);
5294    }
5295   
5296    /*
5297    * (non-Javadoc)
5298    *
5299    * @see
5300    * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5301    * .ActionEvent)
5302    */
 
5303  0 toggle @Override
5304    protected void showGroupConsensus_actionPerformed(ActionEvent e)
5305    {
5306  0 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5307  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5308   
5309    }
5310   
5311    /*
5312    * (non-Javadoc)
5313    *
5314    * @see
5315    * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5316    * .event.ActionEvent)
5317    */
 
5318  0 toggle @Override
5319    protected void showGroupConservation_actionPerformed(ActionEvent e)
5320    {
5321  0 viewport.setShowGroupConservation(showGroupConservation.getState());
5322  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5323    }
5324   
5325    /*
5326    * (non-Javadoc)
5327    *
5328    * @see
5329    * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5330    * .event.ActionEvent)
5331    */
 
5332  0 toggle @Override
5333    protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5334    {
5335  0 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5336  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5337    }
5338   
5339    /*
5340    * (non-Javadoc)
5341    *
5342    * @see
5343    * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5344    * .event.ActionEvent)
5345    */
 
5346  0 toggle @Override
5347    protected void showSequenceLogo_actionPerformed(ActionEvent e)
5348    {
5349  0 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5350  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5351    }
5352   
 
5353  0 toggle @Override
5354    protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5355    {
5356  0 showSequenceLogo.setState(true);
5357  0 viewport.setShowSequenceLogo(true);
5358  0 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5359  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5360    }
5361   
 
5362  0 toggle @Override
5363    protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5364    {
5365  0 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5366    }
5367   
5368    /*
5369    * (non-Javadoc)
5370    *
5371    * @see
5372    * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5373    * .event.ActionEvent)
5374    */
 
5375  0 toggle @Override
5376    protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5377    {
5378  0 if (avc.makeGroupsFromSelection())
5379    {
5380  0 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5381  0 alignPanel.updateAnnotation();
5382  0 alignPanel.paintAlignment(true, true);
5383    }
5384    }
5385   
 
5386  0 toggle public void clearAlignmentSeqRep()
5387    {
5388    // TODO refactor alignmentseqrep to controller
5389  0 if (viewport.getAlignment().hasSeqrep())
5390    {
5391  0 viewport.getAlignment().setSeqrep(null);
5392  0 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5393  0 alignPanel.updateAnnotation();
5394  0 alignPanel.paintAlignment(true, true);
5395    }
5396    }
5397   
 
5398  0 toggle @Override
5399    protected void createGroup_actionPerformed(ActionEvent e)
5400    {
5401  0 if (avc.createGroup())
5402    {
5403  0 alignPanel.alignmentChanged();
5404    }
5405    }
5406   
 
5407  0 toggle @Override
5408    protected void unGroup_actionPerformed(ActionEvent e)
5409    {
5410  0 if (avc.unGroup())
5411    {
5412  0 alignPanel.alignmentChanged();
5413    }
5414    }
5415   
5416    /**
5417    * make the given alignmentPanel the currently selected tab
5418    *
5419    * @param alignmentPanel
5420    */
 
5421  0 toggle public void setDisplayedView(AlignmentPanel alignmentPanel)
5422    {
5423  0 if (!viewport.getSequenceSetId()
5424    .equals(alignmentPanel.av.getSequenceSetId()))
5425    {
5426  0 throw new Error(MessageManager.getString(
5427    "error.implementation_error_cannot_show_view_alignment_frame"));
5428    }
5429  0 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5430    .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5431    {
5432  0 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5433    }
5434    }
5435   
5436    /**
5437    * Action on selection of menu options to Show or Hide annotations.
5438    *
5439    * @param visible
5440    * @param forSequences
5441    * update sequence-related annotations
5442    * @param forAlignment
5443    * update non-sequence-related annotations
5444    */
 
5445  0 toggle @Override
5446    protected void setAnnotationsVisibility(boolean visible,
5447    boolean forSequences, boolean forAlignment)
5448    {
5449  0 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5450    .getAlignmentAnnotation();
5451  0 if (anns == null)
5452    {
5453  0 return;
5454    }
5455  0 for (AlignmentAnnotation aa : anns)
5456    {
5457    /*
5458    * don't display non-positional annotations on an alignment
5459    */
5460  0 if (aa.annotations == null)
5461    {
5462  0 continue;
5463    }
5464  0 boolean apply = (aa.sequenceRef == null && forAlignment)
5465    || (aa.sequenceRef != null && forSequences);
5466  0 if (apply)
5467    {
5468  0 aa.visible = visible;
5469    }
5470    }
5471  0 alignPanel.validateAnnotationDimensions(true);
5472  0 alignPanel.alignmentChanged();
5473    }
5474   
5475    /**
5476    * Store selected annotation sort order for the view and repaint.
5477    */
 
5478  0 toggle @Override
5479    protected void sortAnnotations_actionPerformed()
5480    {
5481  0 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5482  0 this.alignPanel.av
5483    .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5484  0 alignPanel.paintAlignment(false, false);
5485    }
5486   
5487    /**
5488    *
5489    * @return alignment panels in this alignment frame
5490    */
 
5491  14 toggle public List<? extends AlignmentViewPanel> getAlignPanels()
5492    {
5493  14 return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5494    }
5495   
5496    /**
5497    * Open a new alignment window, with the cDNA associated with this (protein)
5498    * alignment, aligned as is the protein.
5499    */
 
5500  0 toggle protected void viewAsCdna_actionPerformed()
5501    {
5502    // TODO no longer a menu action - refactor as required
5503  0 final AlignmentI alignment = getViewport().getAlignment();
5504  0 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5505  0 if (mappings == null)
5506    {
5507  0 return;
5508    }
5509  0 List<SequenceI> cdnaSeqs = new ArrayList<>();
5510  0 for (SequenceI aaSeq : alignment.getSequences())
5511    {
5512  0 for (AlignedCodonFrame acf : mappings)
5513    {
5514  0 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5515  0 if (dnaSeq != null)
5516    {
5517    /*
5518    * There is a cDNA mapping for this protein sequence - add to new
5519    * alignment. It will share the same dataset sequence as other mapped
5520    * cDNA (no new mappings need to be created).
5521    */
5522  0 final Sequence newSeq = new Sequence(dnaSeq);
5523  0 newSeq.setDatasetSequence(dnaSeq);
5524  0 cdnaSeqs.add(newSeq);
5525    }
5526    }
5527    }
5528  0 if (cdnaSeqs.size() == 0)
5529    {
5530    // show a warning dialog no mapped cDNA
5531  0 return;
5532    }
5533  0 AlignmentI cdna = new Alignment(
5534    cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5535  0 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5536    AlignFrame.DEFAULT_HEIGHT);
5537  0 cdna.alignAs(alignment);
5538  0 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5539    + this.title;
5540  0 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5541    AlignFrame.DEFAULT_HEIGHT);
5542    }
5543   
5544    /**
5545    * Set visibility of dna/protein complement view (available when shown in a
5546    * split frame).
5547    *
5548    * @param show
5549    */
 
5550  0 toggle @Override
5551    protected void showComplement_actionPerformed(boolean show)
5552    {
5553  0 SplitContainerI sf = getSplitViewContainer();
5554  0 if (sf != null)
5555    {
5556  0 sf.setComplementVisible(this, show);
5557    }
5558    }
5559   
5560    /**
5561    * Generate the reverse (optionally complemented) of the selected sequences,
5562    * and add them to the alignment
5563    */
 
5564  0 toggle @Override
5565    protected void showReverse_actionPerformed(boolean complement)
5566    {
5567  0 AlignmentI al = null;
5568  0 try
5569    {
5570  0 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5571  0 al = dna.reverseCdna(complement);
5572  0 viewport.addAlignment(al, "");
5573  0 addHistoryItem(new EditCommand(
5574    MessageManager.getString("label.add_sequences"), Action.PASTE,
5575    al.getSequencesArray(), 0, al.getWidth(),
5576    viewport.getAlignment()));
5577    } catch (Exception ex)
5578    {
5579  0 System.err.println(ex.getMessage());
5580  0 return;
5581    }
5582    }
5583   
5584    /**
5585    * Try to run a script in the Groovy console, having first ensured that this
5586    * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5587    * be targeted at this alignment.
5588    */
 
5589  0 toggle @Override
5590    protected void runGroovy_actionPerformed()
5591    {
5592  0 Jalview.setCurrentAlignFrame(this);
5593  0 groovy.ui.Console console = Desktop.getGroovyConsole();
5594  0 if (console != null)
5595    {
5596  0 try
5597    {
5598  0 console.runScript();
5599    } catch (Exception ex)
5600    {
5601  0 System.err.println((ex.toString()));
5602  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5603    MessageManager.getString("label.couldnt_run_groovy_script"),
5604    MessageManager.getString("label.groovy_support_failed"),
5605    JvOptionPane.ERROR_MESSAGE);
5606    }
5607    }
5608    else
5609    {
5610  0 System.err.println("Can't run Groovy script as console not found");
5611    }
5612    }
5613   
5614    /**
5615    * Hides columns containing (or not containing) a specified feature, provided
5616    * that would not leave all columns hidden
5617    *
5618    * @param featureType
5619    * @param columnsContaining
5620    * @return
5621    */
 
5622  5 toggle public boolean hideFeatureColumns(String featureType,
5623    boolean columnsContaining)
5624    {
5625  5 boolean notForHiding = avc.markColumnsContainingFeatures(
5626    columnsContaining, false, false, featureType);
5627  5 if (notForHiding)
5628    {
5629  3 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5630    false, featureType))
5631    {
5632  2 getViewport().hideSelectedColumns();
5633  2 return true;
5634    }
5635    }
5636  3 return false;
5637    }
5638   
 
5639  0 toggle @Override
5640    protected void selectHighlightedColumns_actionPerformed(
5641    ActionEvent actionEvent)
5642    {
5643    // include key modifier check in case user selects from menu
5644  0 avc.markHighlightedColumns(
5645    (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5646    (actionEvent.getModifiers() & (ActionEvent.META_MASK
5647    | ActionEvent.CTRL_MASK)) != 0);
5648    }
5649   
5650    /**
5651    * Rebuilds the Colour menu, including any user-defined colours which have
5652    * been loaded either on startup or during the session
5653    */
 
5654  194 toggle public void buildColourMenu()
5655    {
5656  194 colourMenu.removeAll();
5657   
5658  194 colourMenu.add(applyToAllGroups);
5659  194 colourMenu.add(textColour);
5660  194 colourMenu.addSeparator();
5661   
5662  194 ColourMenuHelper.addMenuItems(colourMenu, this, viewport.getAlignment(),
5663    false);
5664   
5665  194 colourMenu.addSeparator();
5666  194 colourMenu.add(conservationMenuItem);
5667  194 colourMenu.add(modifyConservation);
5668  194 colourMenu.add(abovePIDThreshold);
5669  194 colourMenu.add(modifyPID);
5670  194 colourMenu.add(annotationColour);
5671   
5672  194 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
5673  194 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
5674    }
5675   
5676    /**
5677    * Open a dialog (if not already open) that allows the user to select and
5678    * calculate PCA or Tree analysis
5679    */
 
5680  0 toggle protected void openTreePcaDialog()
5681    {
5682  0 if (alignPanel.getCalculationDialog() == null)
5683    {
5684  0 new CalculationChooser(AlignFrame.this);
5685    }
5686    }
5687   
 
5688  0 toggle @Override
5689    protected void loadVcf_actionPerformed()
5690    {
5691  0 JalviewFileChooser chooser = new JalviewFileChooser(
5692    Cache.getProperty("LAST_DIRECTORY"));
5693  0 chooser.setFileView(new JalviewFileView());
5694  0 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
5695  0 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
5696  0 final AlignFrame us = this;
5697  0 chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION)
5698    {
 
5699  0 toggle @Override
5700    public void run()
5701    {
5702   
5703    {
5704  0 String choice = chooser.getSelectedFile().getPath();
5705  0 Cache.setProperty("LAST_DIRECTORY", choice);
5706  0 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
5707  0 new VCFLoader(choice).loadVCF(seqs, us);
5708    }
5709   
5710    };
5711    }).openDialog(null);
5712   
5713    }
5714   
5715    }
5716   
 
5717    class PrintThread extends Thread
5718    {
5719    AlignmentPanel ap;
5720   
 
5721  0 toggle public PrintThread(AlignmentPanel ap)
5722    {
5723  0 this.ap = ap;
5724    }
5725   
5726    static PageFormat pf;
5727   
 
5728  0 toggle @Override
5729    public void run()
5730    {
5731  0 PrinterJob printJob = PrinterJob.getPrinterJob();
5732   
5733  0 if (pf != null)
5734    {
5735  0 printJob.setPrintable(ap, pf);
5736    }
5737    else
5738    {
5739  0 printJob.setPrintable(ap);
5740    }
5741   
5742  0 if (printJob.printDialog())
5743    {
5744  0 try
5745    {
5746  0 printJob.print();
5747    } catch (Exception PrintException)
5748    {
5749  0 PrintException.printStackTrace();
5750    }
5751    }
5752    }
5753    }