2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.PrintWriter;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.Deque;
57 import java.util.Enumeration;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.Locale;
61 import java.util.Vector;
63 import javax.swing.ButtonGroup;
64 import javax.swing.JCheckBoxMenuItem;
65 import javax.swing.JComponent;
66 import javax.swing.JEditorPane;
67 import javax.swing.JInternalFrame;
68 import javax.swing.JLabel;
69 import javax.swing.JLayeredPane;
70 import javax.swing.JMenu;
71 import javax.swing.JMenuItem;
72 import javax.swing.JPanel;
73 import javax.swing.JScrollPane;
74 import javax.swing.SwingUtilities;
76 import ext.vamsas.ServiceHandle;
77 import jalview.analysis.AlignmentSorter;
78 import jalview.analysis.AlignmentUtils;
79 import jalview.analysis.CrossRef;
80 import jalview.analysis.Dna;
81 import jalview.analysis.GeneticCodeI;
82 import jalview.analysis.ParseProperties;
83 import jalview.analysis.SequenceIdMatcher;
84 import jalview.api.AlignExportSettingsI;
85 import jalview.api.AlignViewControllerGuiI;
86 import jalview.api.AlignViewControllerI;
87 import jalview.api.AlignViewportI;
88 import jalview.api.AlignmentViewPanel;
89 import jalview.api.FeatureSettingsControllerI;
90 import jalview.api.FeatureSettingsModelI;
91 import jalview.api.SplitContainerI;
92 import jalview.api.ViewStyleI;
93 import jalview.api.analysis.SimilarityParamsI;
94 import jalview.bin.Cache;
95 import jalview.bin.Console;
96 import jalview.bin.Jalview;
97 import jalview.commands.CommandI;
98 import jalview.commands.EditCommand;
99 import jalview.commands.EditCommand.Action;
100 import jalview.commands.OrderCommand;
101 import jalview.commands.RemoveGapColCommand;
102 import jalview.commands.RemoveGapsCommand;
103 import jalview.commands.SlideSequencesCommand;
104 import jalview.commands.TrimRegionCommand;
105 import jalview.datamodel.AlignExportSettingsAdapter;
106 import jalview.datamodel.AlignedCodonFrame;
107 import jalview.datamodel.Alignment;
108 import jalview.datamodel.AlignmentAnnotation;
109 import jalview.datamodel.AlignmentExportData;
110 import jalview.datamodel.AlignmentI;
111 import jalview.datamodel.AlignmentOrder;
112 import jalview.datamodel.AlignmentView;
113 import jalview.datamodel.ColumnSelection;
114 import jalview.datamodel.HiddenColumns;
115 import jalview.datamodel.PDBEntry;
116 import jalview.datamodel.SeqCigar;
117 import jalview.datamodel.Sequence;
118 import jalview.datamodel.SequenceGroup;
119 import jalview.datamodel.SequenceI;
120 import jalview.gui.ColourMenuHelper.ColourChangeListener;
121 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
122 import jalview.io.AlignmentProperties;
123 import jalview.io.AnnotationFile;
124 import jalview.io.BackupFiles;
125 import jalview.io.BioJsHTMLOutput;
126 import jalview.io.DataSourceType;
127 import jalview.io.FileFormat;
128 import jalview.io.FileFormatI;
129 import jalview.io.FileFormats;
130 import jalview.io.FileLoader;
131 import jalview.io.FileParse;
132 import jalview.io.FormatAdapter;
133 import jalview.io.HtmlSvgOutput;
134 import jalview.io.IdentifyFile;
135 import jalview.io.JPredFile;
136 import jalview.io.JalviewFileChooser;
137 import jalview.io.JalviewFileView;
138 import jalview.io.JnetAnnotationMaker;
139 import jalview.io.NewickFile;
140 import jalview.io.ScoreMatrixFile;
141 import jalview.io.TCoffeeScoreFile;
142 import jalview.io.vcf.VCFLoader;
143 import jalview.jbgui.GAlignFrame;
144 import jalview.project.Jalview2XML;
145 import jalview.schemes.ColourSchemeI;
146 import jalview.schemes.ColourSchemes;
147 import jalview.schemes.ResidueColourScheme;
148 import jalview.schemes.TCoffeeColourScheme;
149 import jalview.util.HttpUtils;
150 import jalview.util.ImageMaker.TYPE;
151 import jalview.util.MessageManager;
152 import jalview.util.Platform;
153 import jalview.util.imagemaker.BitmapImageSizing;
154 import jalview.viewmodel.AlignmentViewport;
155 import jalview.viewmodel.ViewportRanges;
156 import jalview.ws.DBRefFetcher;
157 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
158 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
159 import jalview.ws.jws1.Discoverer;
160 import jalview.ws.jws2.Jws2Discoverer;
161 import jalview.ws.jws2.jabaws2.Jws2Instance;
162 import jalview.ws.seqfetcher.DbSourceProxy;
168 * @version $Revision$
170 @SuppressWarnings("serial")
171 public class AlignFrame extends GAlignFrame implements DropTargetListener,
172 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
175 public static final int DEFAULT_WIDTH = 700;
177 public static final int DEFAULT_HEIGHT = 500;
180 * The currently displayed panel (selected tabbed view if more than one)
182 public AlignmentPanel alignPanel;
184 AlignViewport viewport;
186 public AlignViewControllerI avc;
188 List<AlignmentPanel> alignPanels = new ArrayList<>();
191 * Last format used to load or save alignments in this window
193 FileFormatI currentFileFormat = null;
196 * Current filename for this alignment
198 String fileName = null;
203 * Creates a new AlignFrame object with specific width and height.
209 public AlignFrame(AlignmentI al, int width, int height)
211 this(al, null, width, height);
215 * Creates a new AlignFrame object with specific width, height and
221 * @param sequenceSetId
223 public AlignFrame(AlignmentI al, int width, int height,
224 String sequenceSetId)
226 this(al, null, width, height, sequenceSetId);
230 * Creates a new AlignFrame object with specific width, height and
236 * @param sequenceSetId
239 public AlignFrame(AlignmentI al, int width, int height,
240 String sequenceSetId, String viewId)
242 this(al, null, width, height, sequenceSetId, viewId);
246 * new alignment window with hidden columns
250 * @param hiddenColumns
251 * ColumnSelection or null
253 * Width of alignment frame
257 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
260 this(al, hiddenColumns, width, height, null);
264 * Create alignment frame for al with hiddenColumns, a specific width and
265 * height, and specific sequenceId
268 * @param hiddenColumns
271 * @param sequenceSetId
274 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
275 int height, String sequenceSetId)
277 this(al, hiddenColumns, width, height, sequenceSetId, null);
281 * Create alignment frame for al with hiddenColumns, a specific width and
282 * height, and specific sequenceId
285 * @param hiddenColumns
288 * @param sequenceSetId
293 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
294 int height, String sequenceSetId, String viewId)
296 setSize(width, height);
298 if (al.getDataset() == null)
303 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
305 alignPanel = new AlignmentPanel(this, viewport);
307 addAlignmentPanel(alignPanel, true);
311 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
312 HiddenColumns hiddenColumns, int width, int height)
314 setSize(width, height);
316 if (al.getDataset() == null)
321 viewport = new AlignViewport(al, hiddenColumns);
323 if (hiddenSeqs != null && hiddenSeqs.length > 0)
325 viewport.hideSequence(hiddenSeqs);
327 alignPanel = new AlignmentPanel(this, viewport);
328 addAlignmentPanel(alignPanel, true);
333 * Make a new AlignFrame from existing alignmentPanels
340 public AlignFrame(AlignmentPanel ap)
344 addAlignmentPanel(ap, false);
349 * initalise the alignframe from the underlying viewport data and the
356 // setBackground(Color.white); // BH 2019
358 if (!Jalview.isHeadlessMode())
360 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
363 avc = new jalview.controller.AlignViewController(this, viewport,
365 if (viewport.getAlignmentConservationAnnotation() == null)
367 // BLOSUM62Colour.setEnabled(false);
368 conservationMenuItem.setEnabled(false);
369 modifyConservation.setEnabled(false);
370 // PIDColour.setEnabled(false);
371 // abovePIDThreshold.setEnabled(false);
372 // modifyPID.setEnabled(false);
375 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
377 if (sortby.equals("Id"))
379 sortIDMenuItem_actionPerformed(null);
381 else if (sortby.equals("Pairwise Identity"))
383 sortPairwiseMenuItem_actionPerformed(null);
387 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
389 setMenusFromViewport(viewport);
390 buildSortByAnnotationScoresMenu();
391 calculateTree.addActionListener(new ActionListener()
395 public void actionPerformed(ActionEvent e)
402 if (Desktop.desktop != null)
404 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
405 if (!Platform.isJS())
407 addServiceListeners();
412 if (viewport.getWrapAlignment())
414 wrapMenuItem_actionPerformed(null);
417 if (Cache.getDefault("SHOW_OVERVIEW", false))
419 this.overviewMenuItem_actionPerformed(null);
424 final List<AlignmentViewPanel> selviews = new ArrayList<>();
425 final List<AlignmentPanel> origview = new ArrayList<>();
426 final String menuLabel = MessageManager
427 .getString("label.copy_format_from");
428 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
429 new ViewSetProvider()
433 public AlignmentPanel[] getAllAlignmentPanels()
436 origview.add(alignPanel);
437 // make an array of all alignment panels except for this one
438 List<AlignmentPanel> aps = new ArrayList<>(
439 Arrays.asList(Desktop.getAlignmentPanels(null)));
440 aps.remove(AlignFrame.this.alignPanel);
441 return aps.toArray(new AlignmentPanel[aps.size()]);
443 }, selviews, new ItemListener()
447 public void itemStateChanged(ItemEvent e)
449 if (origview.size() > 0)
451 final AlignmentPanel ap = origview.get(0);
454 * Copy the ViewStyle of the selected panel to 'this one'.
455 * Don't change value of 'scaleProteinAsCdna' unless copying
458 ViewStyleI vs = selviews.get(0).getAlignViewport()
460 boolean fromSplitFrame = selviews.get(0)
461 .getAlignViewport().getCodingComplement() != null;
464 vs.setScaleProteinAsCdna(ap.getAlignViewport()
465 .getViewStyle().isScaleProteinAsCdna());
467 ap.getAlignViewport().setViewStyle(vs);
470 * Also rescale ViewStyle of SplitFrame complement if there is
471 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
472 * the whole ViewStyle (allow cDNA protein to have different
475 AlignViewportI complement = ap.getAlignViewport()
476 .getCodingComplement();
477 if (complement != null && vs.isScaleProteinAsCdna())
479 AlignFrame af = Desktop.getAlignFrameFor(complement);
480 ((SplitFrame) af.getSplitViewContainer())
482 af.setMenusForViewport();
486 ap.setSelected(true);
487 ap.alignFrame.setMenusForViewport();
492 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
493 .indexOf("devel") > -1
494 || Cache.getDefault("VERSION", "DEVELOPMENT")
495 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
497 formatMenu.add(vsel);
499 addFocusListener(new FocusAdapter()
502 public void focusGained(FocusEvent e)
504 Jalview.setCurrentAlignFrame(AlignFrame.this);
511 * Change the filename and format for the alignment, and enable the 'reload'
512 * button functionality.
519 public void setFileName(String file, FileFormatI format)
522 setFileFormat(format);
523 reload.setEnabled(true);
527 * JavaScript will have this, maybe others. More dependable than a file name
528 * and maintains a reference to the actual bytes loaded.
532 public void setFileObject(File file)
534 this.fileObject = file;
538 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
541 void addKeyListener()
543 addKeyListener(new KeyAdapter()
546 public void keyPressed(KeyEvent evt)
548 if (viewport.cursorMode
549 && ((evt.getKeyCode() >= KeyEvent.VK_0
550 && evt.getKeyCode() <= KeyEvent.VK_9)
551 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
552 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
553 && Character.isDigit(evt.getKeyChar()))
555 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
558 switch (evt.getKeyCode())
561 case 27: // escape key
562 deselectAllSequenceMenuItem_actionPerformed(null);
566 case KeyEvent.VK_DOWN:
567 if (evt.isAltDown() || !viewport.cursorMode)
569 moveSelectedSequences(false);
571 if (viewport.cursorMode)
573 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
578 if (evt.isAltDown() || !viewport.cursorMode)
580 moveSelectedSequences(true);
582 if (viewport.cursorMode)
584 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
589 case KeyEvent.VK_LEFT:
590 if (evt.isAltDown() || !viewport.cursorMode)
592 slideSequences(false,
593 alignPanel.getSeqPanel().getKeyboardNo1());
597 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
602 case KeyEvent.VK_RIGHT:
603 if (evt.isAltDown() || !viewport.cursorMode)
605 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
609 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
613 case KeyEvent.VK_SPACE:
614 if (viewport.cursorMode)
616 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
617 || evt.isShiftDown() || evt.isAltDown());
621 // case KeyEvent.VK_A:
622 // if (viewport.cursorMode)
624 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
625 // //System.out.println("A");
629 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
630 * System.out.println("closing bracket"); } break;
632 case KeyEvent.VK_DELETE:
633 case KeyEvent.VK_BACK_SPACE:
634 if (!viewport.cursorMode)
636 cut_actionPerformed();
640 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
641 || evt.isShiftDown() || evt.isAltDown());
647 if (viewport.cursorMode)
649 alignPanel.getSeqPanel().setCursorRow();
653 if (viewport.cursorMode && !evt.isControlDown())
655 alignPanel.getSeqPanel().setCursorColumn();
659 if (viewport.cursorMode)
661 alignPanel.getSeqPanel().setCursorPosition();
665 case KeyEvent.VK_ENTER:
666 case KeyEvent.VK_COMMA:
667 if (viewport.cursorMode)
669 alignPanel.getSeqPanel().setCursorRowAndColumn();
674 if (viewport.cursorMode)
676 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
680 if (viewport.cursorMode)
682 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
687 viewport.cursorMode = !viewport.cursorMode;
688 setStatus(MessageManager
689 .formatMessage("label.keyboard_editing_mode", new String[]
690 { (viewport.cursorMode ? "on" : "off") }));
691 if (viewport.cursorMode)
693 ViewportRanges ranges = viewport.getRanges();
694 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
696 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
699 alignPanel.getSeqPanel().seqCanvas.repaint();
705 Help.showHelpWindow();
706 } catch (Exception ex)
708 ex.printStackTrace();
713 boolean toggleSeqs = !evt.isControlDown();
714 boolean toggleCols = !evt.isShiftDown();
715 toggleHiddenRegions(toggleSeqs, toggleCols);
720 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
721 boolean modifyExisting = true; // always modify, don't clear
722 // evt.isShiftDown();
723 boolean invertHighlighted = evt.isAltDown();
724 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
728 case KeyEvent.VK_PAGE_UP:
729 viewport.getRanges().pageUp();
731 case KeyEvent.VK_PAGE_DOWN:
732 viewport.getRanges().pageDown();
738 public void keyReleased(KeyEvent evt)
740 switch (evt.getKeyCode())
742 case KeyEvent.VK_LEFT:
743 if (evt.isAltDown() || !viewport.cursorMode)
745 viewport.firePropertyChange("alignment", null,
746 viewport.getAlignment().getSequences());
750 case KeyEvent.VK_RIGHT:
751 if (evt.isAltDown() || !viewport.cursorMode)
753 viewport.firePropertyChange("alignment", null,
754 viewport.getAlignment().getSequences());
762 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
764 ap.alignFrame = this;
765 avc = new jalview.controller.AlignViewController(this, viewport,
770 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
772 int aSize = alignPanels.size();
774 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
776 if (aSize == 1 && ap.av.getViewName() == null)
778 this.getContentPane().add(ap, BorderLayout.CENTER);
784 setInitialTabVisible();
787 expandViews.setEnabled(true);
788 gatherViews.setEnabled(true);
789 tabbedPane.addTab(ap.av.getViewName(), ap);
791 ap.setVisible(false);
796 if (ap.av.isPadGaps())
798 ap.av.getAlignment().padGaps();
800 ap.av.updateConservation(ap);
801 ap.av.updateConsensus(ap);
802 ap.av.updateStrucConsensus(ap);
806 public void setInitialTabVisible()
808 expandViews.setEnabled(true);
809 gatherViews.setEnabled(true);
810 tabbedPane.setVisible(true);
811 AlignmentPanel first = alignPanels.get(0);
812 tabbedPane.addTab(first.av.getViewName(), first);
813 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
816 public AlignViewport getViewport()
821 /* Set up intrinsic listeners for dynamically generated GUI bits. */
822 private void addServiceListeners()
824 final java.beans.PropertyChangeListener thisListener;
825 Desktop.instance.addJalviewPropertyChangeListener("services",
826 thisListener = new java.beans.PropertyChangeListener()
829 public void propertyChange(PropertyChangeEvent evt)
831 // // System.out.println("Discoverer property change.");
832 // if (evt.getPropertyName().equals("services"))
834 SwingUtilities.invokeLater(new Runnable()
841 "Rebuild WS Menu for service change");
842 BuildWebServiceMenu();
849 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
852 public void internalFrameClosed(
853 javax.swing.event.InternalFrameEvent evt)
855 // System.out.println("deregistering discoverer listener");
856 Desktop.instance.removeJalviewPropertyChangeListener("services",
858 closeMenuItem_actionPerformed(true);
861 // Finally, build the menu once to get current service state
862 new Thread(new Runnable()
867 BuildWebServiceMenu();
873 * Configure menu items that vary according to whether the alignment is
874 * nucleotide or protein
876 public void setGUINucleotide()
878 AlignmentI al = getViewport().getAlignment();
879 boolean nucleotide = al.isNucleotide();
881 loadVcf.setVisible(nucleotide);
882 showTranslation.setVisible(nucleotide);
883 showReverse.setVisible(nucleotide);
884 showReverseComplement.setVisible(nucleotide);
885 conservationMenuItem.setEnabled(!nucleotide);
887 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
888 showGroupConservation.setEnabled(!nucleotide);
890 showComplementMenuItem
891 .setText(nucleotide ? MessageManager.getString("label.protein")
892 : MessageManager.getString("label.nucleotide"));
896 * set up menus for the current viewport. This may be called after any
897 * operation that affects the data in the current view (selection changed,
898 * etc) to update the menus to reflect the new state.
901 public void setMenusForViewport()
903 setMenusFromViewport(viewport);
907 * Need to call this method when tabs are selected for multiple views, or when
908 * loading from Jalview2XML.java
913 public void setMenusFromViewport(AlignViewport av)
915 padGapsMenuitem.setSelected(av.isPadGaps());
916 colourTextMenuItem.setSelected(av.isShowColourText());
917 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
918 modifyPID.setEnabled(abovePIDThreshold.isSelected());
919 conservationMenuItem.setSelected(av.getConservationSelected());
920 modifyConservation.setEnabled(conservationMenuItem.isSelected());
921 seqLimits.setSelected(av.getShowJVSuffix());
922 idRightAlign.setSelected(av.isRightAlignIds());
923 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
924 renderGapsMenuItem.setSelected(av.isRenderGaps());
925 wrapMenuItem.setSelected(av.getWrapAlignment());
926 scaleAbove.setVisible(av.getWrapAlignment());
927 scaleLeft.setVisible(av.getWrapAlignment());
928 scaleRight.setVisible(av.getWrapAlignment());
929 annotationPanelMenuItem.setState(av.isShowAnnotation());
931 * Show/hide annotations only enabled if annotation panel is shown
933 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
934 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
935 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
936 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
937 viewBoxesMenuItem.setSelected(av.getShowBoxes());
938 viewTextMenuItem.setSelected(av.getShowText());
939 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
940 showGroupConsensus.setSelected(av.isShowGroupConsensus());
941 showGroupConservation.setSelected(av.isShowGroupConservation());
942 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
943 showSequenceLogo.setSelected(av.isShowSequenceLogo());
944 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
946 ColourMenuHelper.setColourSelected(colourMenu,
947 av.getGlobalColourScheme());
949 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
950 hiddenMarkers.setState(av.getShowHiddenMarkers());
951 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
952 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
953 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
954 autoCalculate.setSelected(av.autoCalculateConsensus);
955 sortByTree.setSelected(av.sortByTree);
956 listenToViewSelections.setSelected(av.followSelection);
958 showProducts.setEnabled(canShowProducts());
959 setGroovyEnabled(Desktop.getGroovyConsole() != null);
965 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
969 public void setGroovyEnabled(boolean b)
971 runGroovy.setEnabled(b);
974 private IProgressIndicator progressBar;
979 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
982 public void setProgressBar(String message, long id)
984 if (!Platform.isHeadless() && progressBar != null)
985 progressBar.setProgressBar(message, id);
989 public void registerHandler(final long id,
990 final IProgressIndicatorHandler handler)
992 if (progressBar != null)
993 progressBar.registerHandler(id, handler);
998 * @return true if any progress bars are still active
1001 public boolean operationInProgress()
1003 return progressBar == null ? false : progressBar.operationInProgress();
1007 * Sets the text of the status bar. Note that setting a null or empty value
1008 * will cause the status bar to be hidden, with possibly undesirable flicker
1009 * of the screen layout.
1012 public void setStatus(String text)
1014 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1018 * Added so Castor Mapping file can obtain Jalview Version
1020 public String getVersion()
1022 return Cache.getProperty("VERSION");
1025 public FeatureRenderer getFeatureRenderer()
1027 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1031 public void fetchSequence_actionPerformed()
1033 new SequenceFetcher(this);
1037 public void addFromFile_actionPerformed(ActionEvent e)
1039 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1043 public void reload_actionPerformed(ActionEvent e)
1045 if (fileName != null)
1047 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1048 // originating file's format
1049 // TODO: work out how to recover feature settings for correct view(s) when
1050 // file is reloaded.
1051 if (FileFormat.Jalview.equals(currentFileFormat))
1053 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1054 for (int i = 0; i < frames.length; i++)
1056 if (frames[i] instanceof AlignFrame && frames[i] != this
1057 && ((AlignFrame) frames[i]).fileName != null
1058 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1062 frames[i].setSelected(true);
1063 Desktop.instance.closeAssociatedWindows();
1064 } catch (java.beans.PropertyVetoException ex)
1070 Desktop.instance.closeAssociatedWindows();
1072 FileLoader loader = new FileLoader();
1073 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1074 ? DataSourceType.URL
1075 : DataSourceType.FILE;
1076 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1080 Rectangle bounds = this.getBounds();
1082 FileLoader loader = new FileLoader();
1084 AlignFrame newframe = null;
1086 if (fileObject == null)
1089 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1090 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1091 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1096 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1097 DataSourceType.FILE, currentFileFormat);
1100 newframe.setBounds(bounds);
1101 if (featureSettings != null && featureSettings.isShowing())
1103 final Rectangle fspos = featureSettings.frame.getBounds();
1104 // TODO: need a 'show feature settings' function that takes bounds -
1105 // need to refactor Desktop.addFrame
1106 newframe.featureSettings_actionPerformed(null);
1107 final FeatureSettings nfs = newframe.featureSettings;
1108 SwingUtilities.invokeLater(new Runnable()
1113 nfs.frame.setBounds(fspos);
1116 this.featureSettings.close();
1117 this.featureSettings = null;
1119 this.closeMenuItem_actionPerformed(true);
1125 public void addFromText_actionPerformed(ActionEvent e)
1128 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1132 public void addFromURL_actionPerformed(ActionEvent e)
1134 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1138 public void save_actionPerformed(ActionEvent e)
1140 if (fileName == null || (currentFileFormat == null)
1141 || HttpUtils.startsWithHttpOrHttps(fileName))
1143 saveAs_actionPerformed();
1147 saveAlignment(fileName, currentFileFormat);
1152 * Saves the alignment to a file with a name chosen by the user, if necessary
1153 * warning if a file would be overwritten
1156 public void saveAs_actionPerformed()
1158 String format = currentFileFormat == null ? null
1159 : currentFileFormat.getName();
1160 JalviewFileChooser chooser = JalviewFileChooser
1161 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1163 chooser.setFileView(new JalviewFileView());
1164 chooser.setDialogTitle(
1165 MessageManager.getString("label.save_alignment_to_file"));
1166 chooser.setToolTipText(MessageManager.getString("action.save"));
1168 int value = chooser.showSaveDialog(this);
1170 if (value != JalviewFileChooser.APPROVE_OPTION)
1174 currentFileFormat = chooser.getSelectedFormat();
1175 // todo is this (2005) test now obsolete - value is never null?
1176 while (currentFileFormat == null)
1178 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1180 .getString("label.select_file_format_before_saving"),
1181 MessageManager.getString("label.file_format_not_specified"),
1182 JvOptionPane.WARNING_MESSAGE);
1183 currentFileFormat = chooser.getSelectedFormat();
1184 value = chooser.showSaveDialog(this);
1185 if (value != JalviewFileChooser.APPROVE_OPTION)
1191 fileName = chooser.getSelectedFile().getPath();
1193 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1194 Cache.setProperty("LAST_DIRECTORY", fileName);
1195 saveAlignment(fileName, currentFileFormat);
1198 boolean lastSaveSuccessful = false;
1200 FileFormatI lastFormatSaved;
1202 String lastFilenameSaved;
1205 * Raise a dialog or status message for the last call to saveAlignment.
1207 * @return true if last call to saveAlignment(file, format) was successful.
1209 public boolean isSaveAlignmentSuccessful()
1212 if (!lastSaveSuccessful)
1214 if (!Platform.isHeadless())
1216 JvOptionPane.showInternalMessageDialog(this, MessageManager
1217 .formatMessage("label.couldnt_save_file", new Object[]
1218 { lastFilenameSaved }),
1219 MessageManager.getString("label.error_saving_file"),
1220 JvOptionPane.WARNING_MESSAGE);
1224 Console.error(MessageManager
1225 .formatMessage("label.couldnt_save_file", new Object[]
1226 { lastFilenameSaved }));
1232 setStatus(MessageManager.formatMessage(
1233 "label.successfully_saved_to_file_in_format", new Object[]
1234 { lastFilenameSaved, lastFormatSaved }));
1237 return lastSaveSuccessful;
1241 * Saves the alignment to the specified file path, in the specified format,
1242 * which may be an alignment format, or Jalview project format. If the
1243 * alignment has hidden regions, or the format is one capable of including
1244 * non-sequence data (features, annotations, groups), then the user may be
1245 * prompted to specify what to include in the output.
1250 public void saveAlignment(String file, FileFormatI format)
1252 lastSaveSuccessful = true;
1253 lastFilenameSaved = file;
1254 lastFormatSaved = format;
1256 if (FileFormat.Jalview.equals(format))
1258 String shortName = title;
1259 if (shortName.indexOf(File.separatorChar) > -1)
1261 shortName = shortName
1262 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1264 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1267 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1268 if (lastSaveSuccessful)
1270 this.getViewport().setSavedUpToDate(true);
1273 statusBar.setText(MessageManager.formatMessage(
1274 "label.successfully_saved_to_file_in_format", new Object[]
1280 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1281 Runnable cancelAction = () -> {
1282 lastSaveSuccessful = false;
1284 Runnable outputAction = () -> {
1285 // todo defer this to inside formatSequences (or later)
1286 AlignmentExportData exportData = viewport.getAlignExportData(options);
1287 String output = new FormatAdapter(alignPanel, options)
1288 .formatSequences(format, exportData.getAlignment(),
1289 exportData.getOmitHidden(),
1290 exportData.getStartEndPostions(),
1291 viewport.getAlignment().getHiddenColumns());
1294 lastSaveSuccessful = false;
1298 // create backupfiles object and get new temp filename destination
1299 boolean doBackup = BackupFiles.getEnabled();
1300 BackupFiles backupfiles = null;
1303 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1304 backupfiles = new BackupFiles(file);
1308 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1310 Console.trace("ALIGNFRAME setting PrintWriter");
1311 PrintWriter out = new PrintWriter(new FileWriter(tempFilePath));
1313 if (backupfiles != null)
1315 Console.trace("ALIGNFRAME about to write to temp file "
1316 + backupfiles.getTempFilePath());
1320 Console.trace("ALIGNFRAME about to close file");
1322 Console.trace("ALIGNFRAME closed file");
1323 AlignFrame.this.setTitle(file);
1324 statusBar.setText(MessageManager.formatMessage(
1325 "label.successfully_saved_to_file_in_format", new Object[]
1326 { fileName, format.getName() }));
1327 lastSaveSuccessful = true;
1328 } catch (IOException e)
1330 lastSaveSuccessful = false;
1332 "ALIGNFRAME Something happened writing the temp file");
1333 Console.error(e.getMessage());
1334 Console.debug(Cache.getStackTraceString(e));
1335 } catch (Exception ex)
1337 lastSaveSuccessful = false;
1339 "ALIGNFRAME Something unexpected happened writing the temp file");
1340 Console.error(ex.getMessage());
1341 Console.debug(Cache.getStackTraceString(ex));
1346 backupfiles.setWriteSuccess(lastSaveSuccessful);
1347 Console.debug("ALIGNFRAME writing temp file was "
1348 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1349 // do the backup file roll and rename the temp file to actual file
1350 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1351 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1352 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1353 + (lastSaveSuccessful ? "" : "un") + "successfully");
1356 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1357 if (lastSaveSuccessful)
1359 AlignFrame.this.getViewport().setSavedUpToDate(true);
1365 * show dialog with export options if applicable; else just do it
1367 if (AlignExportOptions.isNeeded(viewport, format))
1369 AlignExportOptions choices = new AlignExportOptions(
1370 alignPanel.getAlignViewport(), format, options);
1371 choices.setResponseAction(0, outputAction);
1372 choices.setResponseAction(1, cancelAction);
1373 choices.showDialog();
1380 } catch (Exception e)
1382 // TODO Auto-generated catch block
1383 e.printStackTrace();
1389 * Outputs the alignment to textbox in the requested format, if necessary
1390 * first prompting the user for whether to include hidden regions or
1393 * @param fileFormatName
1396 protected void outputText_actionPerformed(String fileFormatName)
1398 FileFormatI fileFormat = FileFormats.getInstance()
1399 .forName(fileFormatName);
1400 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1401 Runnable outputAction = () -> {
1402 // todo defer this to inside formatSequences (or later)
1403 AlignmentExportData exportData = viewport.getAlignExportData(options);
1404 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1405 cap.setForInput(null);
1408 FileFormatI format = fileFormat;
1409 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1410 format, exportData.getAlignment(),
1411 exportData.getOmitHidden(),
1412 exportData.getStartEndPostions(),
1413 viewport.getAlignment().getHiddenColumns()));
1414 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1415 "label.alignment_output_command", new Object[]
1416 { fileFormat.getName() }), 600, 500);
1417 } catch (OutOfMemoryError oom)
1419 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1426 * show dialog with export options if applicable; else just do it
1428 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1430 AlignExportOptions choices = new AlignExportOptions(
1431 alignPanel.getAlignViewport(), fileFormat, options);
1432 choices.setResponseAction(0, outputAction);
1433 choices.showDialog();
1440 } catch (Exception e)
1442 e.printStackTrace();
1454 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1456 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1457 htmlSVG.exportHTML(null);
1461 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1463 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1464 bjs.exportHTML(null);
1467 public void createImageMap(File file, String image)
1469 alignPanel.makePNGImageMap(file, image);
1473 * Creates a PNG image of the alignment and writes it to the given file. If
1474 * the file is null, the user is prompted to choose a file.
1479 public void createPNG(File f)
1481 createPNG(f, null, BitmapImageSizing.nullBitmapImageSizing());
1484 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1486 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1490 * Creates an EPS image of the alignment and writes it to the given file. If
1491 * the file is null, the user is prompted to choose a file.
1496 public void createEPS(File f)
1501 public void createEPS(File f, String renderer)
1503 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1507 * Creates an SVG image of the alignment and writes it to the given file. If
1508 * the file is null, the user is prompted to choose a file.
1513 public void createSVG(File f)
1518 public void createSVG(File f, String renderer)
1520 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1524 public void pageSetup_actionPerformed(ActionEvent e)
1526 PrinterJob printJob = PrinterJob.getPrinterJob();
1527 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1537 public void printMenuItem_actionPerformed(ActionEvent e)
1539 // Putting in a thread avoids Swing painting problems
1540 PrintThread thread = new PrintThread(alignPanel);
1545 public void exportFeatures_actionPerformed(ActionEvent e)
1547 new AnnotationExporter(alignPanel).exportFeatures();
1551 public void exportAnnotations_actionPerformed(ActionEvent e)
1553 new AnnotationExporter(alignPanel).exportAnnotations();
1557 public void associatedData_actionPerformed(ActionEvent e)
1559 final JalviewFileChooser chooser = new JalviewFileChooser(
1560 Cache.getProperty("LAST_DIRECTORY"));
1561 chooser.setFileView(new JalviewFileView());
1562 String tooltip = MessageManager
1563 .getString("label.load_jalview_annotations");
1564 chooser.setDialogTitle(tooltip);
1565 chooser.setToolTipText(tooltip);
1566 chooser.setResponseHandler(0, () -> {
1567 String choice = chooser.getSelectedFile().getPath();
1568 Cache.setProperty("LAST_DIRECTORY", choice);
1569 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1572 chooser.showOpenDialog(this);
1576 * Close the current view or all views in the alignment frame. If the frame
1577 * only contains one view then the alignment will be removed from memory.
1579 * @param closeAllTabs
1582 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1584 if (alignPanels != null && alignPanels.size() < 2)
1586 closeAllTabs = true;
1591 if (alignPanels != null)
1595 if (this.isClosed())
1597 // really close all the windows - otherwise wait till
1598 // setClosed(true) is called
1599 for (int i = 0; i < alignPanels.size(); i++)
1601 AlignmentPanel ap = alignPanels.get(i);
1608 closeView(alignPanel);
1613 if (featureSettings != null && featureSettings.isOpen())
1615 featureSettings.close();
1616 featureSettings = null;
1619 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1620 * be called recursively, with the frame now in 'closed' state
1622 this.setClosed(true);
1624 } catch (Exception ex)
1626 ex.printStackTrace();
1631 * Close the specified panel and close up tabs appropriately.
1633 * @param panelToClose
1635 public void closeView(AlignmentPanel panelToClose)
1637 int index = tabbedPane.getSelectedIndex();
1638 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1639 alignPanels.remove(panelToClose);
1640 panelToClose.closePanel();
1641 panelToClose = null;
1643 tabbedPane.removeTabAt(closedindex);
1644 tabbedPane.validate();
1646 if (index > closedindex || index == tabbedPane.getTabCount())
1648 // modify currently selected tab index if necessary.
1652 this.tabSelectionChanged(index);
1658 void updateEditMenuBar()
1661 if (viewport.getHistoryList().size() > 0)
1663 undoMenuItem.setEnabled(true);
1664 CommandI command = viewport.getHistoryList().peek();
1665 undoMenuItem.setText(MessageManager
1666 .formatMessage("label.undo_command", new Object[]
1667 { command.getDescription() }));
1671 undoMenuItem.setEnabled(false);
1672 undoMenuItem.setText(MessageManager.getString("action.undo"));
1675 if (viewport.getRedoList().size() > 0)
1677 redoMenuItem.setEnabled(true);
1679 CommandI command = viewport.getRedoList().peek();
1680 redoMenuItem.setText(MessageManager
1681 .formatMessage("label.redo_command", new Object[]
1682 { command.getDescription() }));
1686 redoMenuItem.setEnabled(false);
1687 redoMenuItem.setText(MessageManager.getString("action.redo"));
1692 public void addHistoryItem(CommandI command)
1694 if (command.getSize() > 0)
1696 viewport.addToHistoryList(command);
1697 viewport.clearRedoList();
1698 updateEditMenuBar();
1699 viewport.updateHiddenColumns();
1700 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1701 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1702 // viewport.getColumnSelection()
1703 // .getHiddenColumns().size() > 0);
1709 * @return alignment objects for all views
1711 AlignmentI[] getViewAlignments()
1713 if (alignPanels != null)
1715 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1717 for (AlignmentPanel ap : alignPanels)
1719 als[i++] = ap.av.getAlignment();
1723 if (viewport != null)
1725 return new AlignmentI[] { viewport.getAlignment() };
1737 protected void undoMenuItem_actionPerformed(ActionEvent e)
1739 if (viewport.getHistoryList().isEmpty())
1743 CommandI command = viewport.getHistoryList().pop();
1744 viewport.addToRedoList(command);
1745 command.undoCommand(getViewAlignments());
1747 AlignmentViewport originalSource = getOriginatingSource(command);
1748 updateEditMenuBar();
1750 if (originalSource != null)
1752 if (originalSource != viewport)
1755 "Implementation worry: mismatch of viewport origin for undo");
1757 originalSource.updateHiddenColumns();
1758 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1760 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1761 // viewport.getColumnSelection()
1762 // .getHiddenColumns().size() > 0);
1763 originalSource.firePropertyChange("alignment", null,
1764 originalSource.getAlignment().getSequences());
1775 protected void redoMenuItem_actionPerformed(ActionEvent e)
1777 if (viewport.getRedoList().size() < 1)
1782 CommandI command = viewport.getRedoList().pop();
1783 viewport.addToHistoryList(command);
1784 command.doCommand(getViewAlignments());
1786 AlignmentViewport originalSource = getOriginatingSource(command);
1787 updateEditMenuBar();
1789 if (originalSource != null)
1792 if (originalSource != viewport)
1795 "Implementation worry: mismatch of viewport origin for redo");
1797 originalSource.updateHiddenColumns();
1798 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1800 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1801 // viewport.getColumnSelection()
1802 // .getHiddenColumns().size() > 0);
1803 originalSource.firePropertyChange("alignment", null,
1804 originalSource.getAlignment().getSequences());
1808 AlignmentViewport getOriginatingSource(CommandI command)
1810 AlignmentViewport originalSource = null;
1811 // For sequence removal and addition, we need to fire
1812 // the property change event FROM the viewport where the
1813 // original alignment was altered
1814 AlignmentI al = null;
1815 if (command instanceof EditCommand)
1817 EditCommand editCommand = (EditCommand) command;
1818 al = editCommand.getAlignment();
1819 List<Component> comps = PaintRefresher.components
1820 .get(viewport.getSequenceSetId());
1822 for (Component comp : comps)
1824 if (comp instanceof AlignmentPanel)
1826 if (al == ((AlignmentPanel) comp).av.getAlignment())
1828 originalSource = ((AlignmentPanel) comp).av;
1835 if (originalSource == null)
1837 // The original view is closed, we must validate
1838 // the current view against the closed view first
1841 PaintRefresher.validateSequences(al, viewport.getAlignment());
1844 originalSource = viewport;
1847 return originalSource;
1851 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1852 * or the sequence under cursor in keyboard mode
1857 public void moveSelectedSequences(boolean up)
1859 SequenceGroup sg = viewport.getSelectionGroup();
1863 if (viewport.cursorMode)
1865 sg = new SequenceGroup();
1866 sg.addSequence(viewport.getAlignment().getSequenceAt(
1867 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1875 if (sg.getSize() < 1)
1880 // TODO: JAL-3733 - add an event to the undo buffer for this !
1882 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1883 viewport.getHiddenRepSequences(), up);
1884 alignPanel.paintAlignment(true, false);
1887 synchronized void slideSequences(boolean right, int size)
1889 List<SequenceI> sg = new ArrayList<>();
1890 if (viewport.cursorMode)
1892 sg.add(viewport.getAlignment()
1893 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1895 else if (viewport.getSelectionGroup() != null
1896 && viewport.getSelectionGroup().getSize() != viewport
1897 .getAlignment().getHeight())
1899 sg = viewport.getSelectionGroup()
1900 .getSequences(viewport.getHiddenRepSequences());
1908 List<SequenceI> invertGroup = new ArrayList<>();
1910 for (SequenceI seq : viewport.getAlignment().getSequences())
1912 if (!sg.contains(seq))
1914 invertGroup.add(seq);
1918 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1920 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1921 for (int i = 0; i < invertGroup.size(); i++)
1923 seqs2[i] = invertGroup.get(i);
1926 SlideSequencesCommand ssc;
1929 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1930 viewport.getGapCharacter());
1934 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1935 viewport.getGapCharacter());
1938 int groupAdjustment = 0;
1939 if (ssc.getGapsInsertedBegin() && right)
1941 if (viewport.cursorMode)
1943 alignPanel.getSeqPanel().moveCursor(size, 0);
1947 groupAdjustment = size;
1950 else if (!ssc.getGapsInsertedBegin() && !right)
1952 if (viewport.cursorMode)
1954 alignPanel.getSeqPanel().moveCursor(-size, 0);
1958 groupAdjustment = -size;
1962 if (groupAdjustment != 0)
1964 viewport.getSelectionGroup().setStartRes(
1965 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1966 viewport.getSelectionGroup().setEndRes(
1967 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1971 * just extend the last slide command if compatible; but not if in
1972 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
1974 boolean appendHistoryItem = false;
1975 Deque<CommandI> historyList = viewport.getHistoryList();
1976 boolean inSplitFrame = getSplitViewContainer() != null;
1977 if (!inSplitFrame && historyList != null && historyList.size() > 0
1978 && historyList.peek() instanceof SlideSequencesCommand)
1980 appendHistoryItem = ssc.appendSlideCommand(
1981 (SlideSequencesCommand) historyList.peek());
1984 if (!appendHistoryItem)
1986 addHistoryItem(ssc);
1999 protected void copy_actionPerformed()
2001 if (viewport.getSelectionGroup() == null)
2005 // TODO: preserve the ordering of displayed alignment annotation in any
2006 // internal paste (particularly sequence associated annotation)
2007 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2008 String[] omitHidden = null;
2010 if (viewport.hasHiddenColumns())
2012 omitHidden = viewport.getViewAsString(true);
2015 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2016 seqs, omitHidden, null);
2018 StringSelection ss = new StringSelection(output);
2022 jalview.gui.Desktop.internalCopy = true;
2023 // Its really worth setting the clipboard contents
2024 // to empty before setting the large StringSelection!!
2025 Toolkit.getDefaultToolkit().getSystemClipboard()
2026 .setContents(new StringSelection(""), null);
2028 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2030 } catch (OutOfMemoryError er)
2032 new OOMWarning("copying region", er);
2036 HiddenColumns hiddenColumns = null;
2037 if (viewport.hasHiddenColumns())
2039 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2040 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2042 // create new HiddenColumns object with copy of hidden regions
2043 // between startRes and endRes, offset by startRes
2044 hiddenColumns = new HiddenColumns(
2045 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2046 hiddenCutoff, hiddenOffset);
2049 Desktop.jalviewClipboard = new Object[] { seqs,
2050 viewport.getAlignment().getDataset(), hiddenColumns };
2051 setStatus(MessageManager.formatMessage(
2052 "label.copied_sequences_to_clipboard", new Object[]
2053 { Integer.valueOf(seqs.length).toString() }));
2063 protected void pasteNew_actionPerformed(ActionEvent e)
2075 protected void pasteThis_actionPerformed(ActionEvent e)
2081 * Paste contents of Jalview clipboard
2083 * @param newAlignment
2084 * true to paste to a new alignment, otherwise add to this.
2086 void paste(boolean newAlignment)
2088 boolean externalPaste = true;
2091 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2092 Transferable contents = c.getContents(this);
2094 if (contents == null)
2103 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2104 if (str.length() < 1)
2109 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2111 } catch (OutOfMemoryError er)
2113 new OOMWarning("Out of memory pasting sequences!!", er);
2117 SequenceI[] sequences;
2118 boolean annotationAdded = false;
2119 AlignmentI alignment = null;
2121 if (Desktop.jalviewClipboard != null)
2123 // The clipboard was filled from within Jalview, we must use the
2125 // And dataset from the copied alignment
2126 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2127 // be doubly sure that we create *new* sequence objects.
2128 sequences = new SequenceI[newseq.length];
2129 for (int i = 0; i < newseq.length; i++)
2131 sequences[i] = new Sequence(newseq[i]);
2133 alignment = new Alignment(sequences);
2134 externalPaste = false;
2138 // parse the clipboard as an alignment.
2139 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2141 sequences = alignment.getSequencesArray();
2145 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2151 if (Desktop.jalviewClipboard != null)
2153 // dataset is inherited
2154 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2158 // new dataset is constructed
2159 alignment.setDataset(null);
2161 alwidth = alignment.getWidth() + 1;
2165 AlignmentI pastedal = alignment; // preserve pasted alignment object
2166 // Add pasted sequences and dataset into existing alignment.
2167 alignment = viewport.getAlignment();
2168 alwidth = alignment.getWidth() + 1;
2169 // decide if we need to import sequences from an existing dataset
2170 boolean importDs = Desktop.jalviewClipboard != null
2171 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2172 // importDs==true instructs us to copy over new dataset sequences from
2173 // an existing alignment
2174 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2176 // minimum dataset set
2178 for (int i = 0; i < sequences.length; i++)
2182 newDs.addElement(null);
2184 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2186 if (importDs && ds != null)
2188 if (!newDs.contains(ds))
2190 newDs.setElementAt(ds, i);
2191 ds = new Sequence(ds);
2192 // update with new dataset sequence
2193 sequences[i].setDatasetSequence(ds);
2197 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2202 // copy and derive new dataset sequence
2203 sequences[i] = sequences[i].deriveSequence();
2204 alignment.getDataset()
2205 .addSequence(sequences[i].getDatasetSequence());
2206 // TODO: avoid creation of duplicate dataset sequences with a
2207 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2209 alignment.addSequence(sequences[i]); // merges dataset
2213 newDs.clear(); // tidy up
2215 if (alignment.getAlignmentAnnotation() != null)
2217 for (AlignmentAnnotation alan : alignment
2218 .getAlignmentAnnotation())
2220 if (alan.graphGroup > fgroup)
2222 fgroup = alan.graphGroup;
2226 if (pastedal.getAlignmentAnnotation() != null)
2228 // Add any annotation attached to alignment.
2229 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2230 for (int i = 0; i < alann.length; i++)
2232 annotationAdded = true;
2233 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2235 AlignmentAnnotation newann = new AlignmentAnnotation(
2237 if (newann.graphGroup > -1)
2239 if (newGraphGroups.size() <= newann.graphGroup
2240 || newGraphGroups.get(newann.graphGroup) == null)
2242 for (int q = newGraphGroups
2243 .size(); q <= newann.graphGroup; q++)
2245 newGraphGroups.add(q, null);
2247 newGraphGroups.set(newann.graphGroup,
2248 Integer.valueOf(++fgroup));
2250 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2254 newann.padAnnotation(alwidth);
2255 alignment.addAnnotation(newann);
2265 addHistoryItem(new EditCommand(
2266 MessageManager.getString("label.add_sequences"),
2267 Action.PASTE, sequences, 0, alignment.getWidth(),
2270 // Add any annotations attached to sequences
2271 for (int i = 0; i < sequences.length; i++)
2273 if (sequences[i].getAnnotation() != null)
2275 AlignmentAnnotation newann;
2276 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2278 annotationAdded = true;
2279 newann = sequences[i].getAnnotation()[a];
2280 newann.adjustForAlignment();
2281 newann.padAnnotation(alwidth);
2282 if (newann.graphGroup > -1)
2284 if (newann.graphGroup > -1)
2286 if (newGraphGroups.size() <= newann.graphGroup
2287 || newGraphGroups.get(newann.graphGroup) == null)
2289 for (int q = newGraphGroups
2290 .size(); q <= newann.graphGroup; q++)
2292 newGraphGroups.add(q, null);
2294 newGraphGroups.set(newann.graphGroup,
2295 Integer.valueOf(++fgroup));
2297 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2301 alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation
2305 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2313 // propagate alignment changed.
2314 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2315 if (annotationAdded)
2317 // Duplicate sequence annotation in all views.
2318 AlignmentI[] alview = this.getViewAlignments();
2319 for (int i = 0; i < sequences.length; i++)
2321 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2326 for (int avnum = 0; avnum < alview.length; avnum++)
2328 if (alview[avnum] != alignment)
2330 // duplicate in a view other than the one with input focus
2331 int avwidth = alview[avnum].getWidth() + 1;
2332 // this relies on sann being preserved after we
2333 // modify the sequence's annotation array for each duplication
2334 for (int a = 0; a < sann.length; a++)
2336 AlignmentAnnotation newann = new AlignmentAnnotation(
2338 sequences[i].addAlignmentAnnotation(newann);
2339 newann.padAnnotation(avwidth);
2340 alview[avnum].addAnnotation(newann); // annotation was
2341 // duplicated earlier
2342 // TODO JAL-1145 graphGroups are not updated for sequence
2343 // annotation added to several views. This may cause
2345 alview[avnum].setAnnotationIndex(newann, a);
2350 buildSortByAnnotationScoresMenu();
2352 viewport.firePropertyChange("alignment", null,
2353 alignment.getSequences());
2354 if (alignPanels != null)
2356 for (AlignmentPanel ap : alignPanels)
2358 ap.validateAnnotationDimensions(false);
2363 alignPanel.validateAnnotationDimensions(false);
2369 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2371 String newtitle = new String("Copied sequences");
2373 if (Desktop.jalviewClipboard != null
2374 && Desktop.jalviewClipboard[2] != null)
2376 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2377 af.viewport.setHiddenColumns(hc);
2380 // >>>This is a fix for the moment, until a better solution is
2382 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2383 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2384 .getFeatureRenderer());
2386 // TODO: maintain provenance of an alignment, rather than just make the
2387 // title a concatenation of operations.
2390 if (title.startsWith("Copied sequences"))
2396 newtitle = newtitle.concat("- from " + title);
2401 newtitle = new String("Pasted sequences");
2404 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2409 } catch (Exception ex)
2411 ex.printStackTrace();
2412 System.out.println("Exception whilst pasting: " + ex);
2413 // could be anything being pasted in here
2419 protected void expand_newalign(ActionEvent e)
2423 AlignmentI alignment = AlignmentUtils
2424 .expandContext(getViewport().getAlignment(), -1);
2425 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2427 String newtitle = new String("Flanking alignment");
2429 if (Desktop.jalviewClipboard != null
2430 && Desktop.jalviewClipboard[2] != null)
2432 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2433 af.viewport.setHiddenColumns(hc);
2436 // >>>This is a fix for the moment, until a better solution is
2438 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2439 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2440 .getFeatureRenderer());
2442 // TODO: maintain provenance of an alignment, rather than just make the
2443 // title a concatenation of operations.
2445 if (title.startsWith("Copied sequences"))
2451 newtitle = newtitle.concat("- from " + title);
2455 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2457 } catch (Exception ex)
2459 ex.printStackTrace();
2460 System.out.println("Exception whilst pasting: " + ex);
2461 // could be anything being pasted in here
2462 } catch (OutOfMemoryError oom)
2464 new OOMWarning("Viewing flanking region of alignment", oom);
2469 * Action Cut (delete and copy) the selected region
2472 protected void cut_actionPerformed()
2474 copy_actionPerformed();
2475 delete_actionPerformed();
2479 * Performs menu option to Delete the currently selected region
2482 protected void delete_actionPerformed()
2485 SequenceGroup sg = viewport.getSelectionGroup();
2491 Runnable okAction = () -> {
2492 SequenceI[] cut = sg.getSequences()
2493 .toArray(new SequenceI[sg.getSize()]);
2495 addHistoryItem(new EditCommand(
2496 MessageManager.getString("label.cut_sequences"), Action.CUT,
2497 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2498 viewport.getAlignment()));
2500 viewport.setSelectionGroup(null);
2501 viewport.sendSelection();
2502 viewport.getAlignment().deleteGroup(sg);
2504 viewport.firePropertyChange("alignment", null,
2505 viewport.getAlignment().getSequences());
2506 if (viewport.getAlignment().getHeight() < 1)
2510 AlignFrame.this.setClosed(true);
2511 } catch (Exception ex)
2518 * If the cut affects all sequences, prompt for confirmation
2520 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2522 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2523 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2524 if (wholeHeight && wholeWidth)
2526 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2527 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2528 Object[] options = new Object[] {
2529 MessageManager.getString("action.ok"),
2530 MessageManager.getString("action.cancel") };
2531 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2532 MessageManager.getString("label.delete_all"),
2533 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2534 options, options[0]);
2541 } catch (Exception e)
2543 e.printStackTrace();
2555 protected void deleteGroups_actionPerformed(ActionEvent e)
2557 if (avc.deleteGroups())
2559 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2560 alignPanel.updateAnnotation();
2561 alignPanel.paintAlignment(true, true);
2572 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2574 SequenceGroup sg = new SequenceGroup(
2575 viewport.getAlignment().getSequences());
2577 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2578 viewport.setSelectionGroup(sg);
2579 viewport.isSelectionGroupChanged(true);
2580 viewport.sendSelection();
2581 // JAL-2034 - should delegate to
2582 // alignPanel to decide if overview needs
2584 alignPanel.paintAlignment(false, false);
2585 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2595 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2597 if (viewport.cursorMode)
2599 alignPanel.getSeqPanel().keyboardNo1 = null;
2600 alignPanel.getSeqPanel().keyboardNo2 = null;
2602 viewport.setSelectionGroup(null);
2603 viewport.getColumnSelection().clear();
2604 viewport.setSearchResults(null);
2605 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2606 // JAL-2034 - should delegate to
2607 // alignPanel to decide if overview needs
2609 alignPanel.paintAlignment(false, false);
2610 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2611 viewport.sendSelection();
2621 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2623 SequenceGroup sg = viewport.getSelectionGroup();
2627 selectAllSequenceMenuItem_actionPerformed(null);
2632 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2634 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2636 // JAL-2034 - should delegate to
2637 // alignPanel to decide if overview needs
2640 alignPanel.paintAlignment(true, false);
2641 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2642 viewport.sendSelection();
2646 public void invertColSel_actionPerformed(ActionEvent e)
2648 viewport.invertColumnSelection();
2649 alignPanel.paintAlignment(true, false);
2650 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2651 viewport.sendSelection();
2661 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2663 trimAlignment(true);
2673 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2675 trimAlignment(false);
2678 void trimAlignment(boolean trimLeft)
2680 ColumnSelection colSel = viewport.getColumnSelection();
2683 if (!colSel.isEmpty())
2687 column = colSel.getMin();
2691 column = colSel.getMax();
2695 if (viewport.getSelectionGroup() != null)
2697 seqs = viewport.getSelectionGroup()
2698 .getSequencesAsArray(viewport.getHiddenRepSequences());
2702 seqs = viewport.getAlignment().getSequencesArray();
2705 TrimRegionCommand trimRegion;
2708 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2709 column, viewport.getAlignment());
2710 viewport.getRanges().setStartRes(0);
2714 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2715 column, viewport.getAlignment());
2718 setStatus(MessageManager.formatMessage("label.removed_columns",
2720 { Integer.valueOf(trimRegion.getSize()).toString() }));
2722 addHistoryItem(trimRegion);
2724 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2726 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2727 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2729 viewport.getAlignment().deleteGroup(sg);
2733 viewport.firePropertyChange("alignment", null,
2734 viewport.getAlignment().getSequences());
2745 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2747 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2750 if (viewport.getSelectionGroup() != null)
2752 seqs = viewport.getSelectionGroup()
2753 .getSequencesAsArray(viewport.getHiddenRepSequences());
2754 start = viewport.getSelectionGroup().getStartRes();
2755 end = viewport.getSelectionGroup().getEndRes();
2759 seqs = viewport.getAlignment().getSequencesArray();
2762 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2763 "Remove Gapped Columns", seqs, start, end,
2764 viewport.getAlignment());
2766 addHistoryItem(removeGapCols);
2768 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2770 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2772 // This is to maintain viewport position on first residue
2773 // of first sequence
2774 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2775 ViewportRanges ranges = viewport.getRanges();
2776 int startRes = seq.findPosition(ranges.getStartRes());
2777 // ShiftList shifts;
2778 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2779 // edit.alColumnChanges=shifts.getInverse();
2780 // if (viewport.hasHiddenColumns)
2781 // viewport.getColumnSelection().compensateForEdits(shifts);
2782 ranges.setStartRes(seq.findIndex(startRes) - 1);
2783 viewport.firePropertyChange("alignment", null,
2784 viewport.getAlignment().getSequences());
2795 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2797 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2800 if (viewport.getSelectionGroup() != null)
2802 seqs = viewport.getSelectionGroup()
2803 .getSequencesAsArray(viewport.getHiddenRepSequences());
2804 start = viewport.getSelectionGroup().getStartRes();
2805 end = viewport.getSelectionGroup().getEndRes();
2809 seqs = viewport.getAlignment().getSequencesArray();
2812 // This is to maintain viewport position on first residue
2813 // of first sequence
2814 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2815 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2817 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2818 viewport.getAlignment()));
2820 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2822 viewport.firePropertyChange("alignment", null,
2823 viewport.getAlignment().getSequences());
2834 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2836 viewport.setPadGaps(padGapsMenuitem.isSelected());
2837 viewport.firePropertyChange("alignment", null,
2838 viewport.getAlignment().getSequences());
2842 * Opens a Finder dialog
2847 public void findMenuItem_actionPerformed(ActionEvent e)
2849 new Finder(alignPanel, false, null);
2853 * Create a new view of the current alignment.
2856 public void newView_actionPerformed(ActionEvent e)
2858 newView(null, true);
2862 * Creates and shows a new view of the current alignment.
2865 * title of newly created view; if null, one will be generated
2866 * @param copyAnnotation
2867 * if true then duplicate all annnotation, groups and settings
2868 * @return new alignment panel, already displayed.
2870 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2873 * Create a new AlignmentPanel (with its own, new Viewport)
2875 AlignmentPanel newap = new jalview.project.Jalview2XML()
2876 .copyAlignPanel(alignPanel);
2877 if (!copyAnnotation)
2880 * remove all groups and annotation except for the automatic stuff
2882 newap.av.getAlignment().deleteAllGroups();
2883 newap.av.getAlignment().deleteAllAnnotations(false);
2886 newap.av.setGatherViewsHere(false);
2888 if (viewport.getViewName() == null)
2890 viewport.setViewName(
2891 MessageManager.getString("label.view_name_original"));
2895 * Views share the same edits undo and redo stacks
2897 newap.av.setHistoryList(viewport.getHistoryList());
2898 newap.av.setRedoList(viewport.getRedoList());
2901 * copy any visualisation settings that are not saved in the project
2903 newap.av.setColourAppliesToAllGroups(
2904 viewport.getColourAppliesToAllGroups());
2907 * Views share the same mappings; need to deregister any new mappings
2908 * created by copyAlignPanel, and register the new reference to the shared
2911 newap.av.replaceMappings(viewport.getAlignment());
2914 * start up cDNA consensus (if applicable) now mappings are in place
2916 if (newap.av.initComplementConsensus())
2918 newap.refresh(true); // adjust layout of annotations
2921 newap.av.setViewName(getNewViewName(viewTitle));
2923 addAlignmentPanel(newap, true);
2924 newap.alignmentChanged();
2926 if (alignPanels.size() == 2)
2928 viewport.setGatherViewsHere(true);
2930 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2936 * Make a new name for the view, ensuring it is unique within the current
2937 * sequenceSetId. (This used to be essential for Jalview Project archives, but
2938 * these now use viewId. Unique view names are still desirable for usability.)
2943 protected String getNewViewName(String viewTitle)
2945 int index = Desktop.getViewCount(viewport.getSequenceSetId());
2946 boolean addFirstIndex = false;
2947 if (viewTitle == null || viewTitle.trim().length() == 0)
2949 viewTitle = MessageManager.getString("action.view");
2950 addFirstIndex = true;
2954 index = 1;// we count from 1 if given a specific name
2956 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
2958 List<Component> comps = PaintRefresher.components
2959 .get(viewport.getSequenceSetId());
2961 List<String> existingNames = getExistingViewNames(comps);
2963 while (existingNames.contains(newViewName))
2965 newViewName = viewTitle + " " + (++index);
2971 * Returns a list of distinct view names found in the given list of
2972 * components. View names are held on the viewport of an AlignmentPanel.
2977 protected List<String> getExistingViewNames(List<Component> comps)
2979 List<String> existingNames = new ArrayList<>();
2980 for (Component comp : comps)
2982 if (comp instanceof AlignmentPanel)
2984 AlignmentPanel ap = (AlignmentPanel) comp;
2985 if (!existingNames.contains(ap.av.getViewName()))
2987 existingNames.add(ap.av.getViewName());
2991 return existingNames;
2995 * Explode tabbed views into separate windows.
2998 public void expandViews_actionPerformed(ActionEvent e)
3000 Desktop.explodeViews(this);
3004 * Gather views in separate windows back into a tabbed presentation.
3007 public void gatherViews_actionPerformed(ActionEvent e)
3009 Desktop.instance.gatherViews(this);
3019 public void font_actionPerformed(ActionEvent e)
3021 new FontChooser(alignPanel);
3031 protected void seqLimit_actionPerformed(ActionEvent e)
3033 viewport.setShowJVSuffix(seqLimits.isSelected());
3035 alignPanel.getIdPanel().getIdCanvas()
3036 .setPreferredSize(alignPanel.calculateIdWidth());
3037 alignPanel.paintAlignment(true, false);
3041 public void idRightAlign_actionPerformed(ActionEvent e)
3043 viewport.setRightAlignIds(idRightAlign.isSelected());
3044 alignPanel.paintAlignment(false, false);
3048 public void centreColumnLabels_actionPerformed(ActionEvent e)
3050 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3051 alignPanel.paintAlignment(false, false);
3057 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3060 protected void followHighlight_actionPerformed()
3063 * Set the 'follow' flag on the Viewport (and scroll to position if now
3066 final boolean state = this.followHighlightMenuItem.getState();
3067 viewport.setFollowHighlight(state);
3070 alignPanel.scrollToPosition(viewport.getSearchResults());
3081 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3083 viewport.setColourText(colourTextMenuItem.isSelected());
3084 alignPanel.paintAlignment(false, false);
3094 public void wrapMenuItem_actionPerformed(ActionEvent e)
3096 scaleAbove.setVisible(wrapMenuItem.isSelected());
3097 scaleLeft.setVisible(wrapMenuItem.isSelected());
3098 scaleRight.setVisible(wrapMenuItem.isSelected());
3099 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3100 alignPanel.updateLayout();
3104 public void showAllSeqs_actionPerformed(ActionEvent e)
3106 viewport.showAllHiddenSeqs();
3110 public void showAllColumns_actionPerformed(ActionEvent e)
3112 viewport.showAllHiddenColumns();
3113 alignPanel.paintAlignment(true, true);
3114 viewport.sendSelection();
3118 public void hideSelSequences_actionPerformed(ActionEvent e)
3120 viewport.hideAllSelectedSeqs();
3124 * called by key handler and the hide all/show all menu items
3129 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3132 boolean hide = false;
3133 SequenceGroup sg = viewport.getSelectionGroup();
3134 if (!toggleSeqs && !toggleCols)
3136 // Hide everything by the current selection - this is a hack - we do the
3137 // invert and then hide
3138 // first check that there will be visible columns after the invert.
3139 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3140 && sg.getStartRes() <= sg.getEndRes()))
3142 // now invert the sequence set, if required - empty selection implies
3143 // that no hiding is required.
3146 invertSequenceMenuItem_actionPerformed(null);
3147 sg = viewport.getSelectionGroup();
3151 viewport.expandColSelection(sg, true);
3152 // finally invert the column selection and get the new sequence
3154 invertColSel_actionPerformed(null);
3161 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3163 hideSelSequences_actionPerformed(null);
3166 else if (!(toggleCols && viewport.hasSelectedColumns()))
3168 showAllSeqs_actionPerformed(null);
3174 if (viewport.hasSelectedColumns())
3176 hideSelColumns_actionPerformed(null);
3179 viewport.setSelectionGroup(sg);
3184 showAllColumns_actionPerformed(null);
3193 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3194 * event.ActionEvent)
3197 public void hideAllButSelection_actionPerformed(ActionEvent e)
3199 toggleHiddenRegions(false, false);
3200 viewport.sendSelection();
3207 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3211 public void hideAllSelection_actionPerformed(ActionEvent e)
3213 SequenceGroup sg = viewport.getSelectionGroup();
3214 viewport.expandColSelection(sg, false);
3215 viewport.hideAllSelectedSeqs();
3216 viewport.hideSelectedColumns();
3217 alignPanel.updateLayout();
3218 alignPanel.paintAlignment(true, true);
3219 viewport.sendSelection();
3226 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3230 public void showAllhidden_actionPerformed(ActionEvent e)
3232 viewport.showAllHiddenColumns();
3233 viewport.showAllHiddenSeqs();
3234 alignPanel.paintAlignment(true, true);
3235 viewport.sendSelection();
3239 public void hideSelColumns_actionPerformed(ActionEvent e)
3241 viewport.hideSelectedColumns();
3242 alignPanel.updateLayout();
3243 alignPanel.paintAlignment(true, true);
3244 viewport.sendSelection();
3248 public void hiddenMarkers_actionPerformed(ActionEvent e)
3250 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3261 protected void scaleAbove_actionPerformed(ActionEvent e)
3263 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3264 alignPanel.updateLayout();
3265 alignPanel.paintAlignment(true, false);
3275 protected void scaleLeft_actionPerformed(ActionEvent e)
3277 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3278 alignPanel.updateLayout();
3279 alignPanel.paintAlignment(true, false);
3289 protected void scaleRight_actionPerformed(ActionEvent e)
3291 viewport.setScaleRightWrapped(scaleRight.isSelected());
3292 alignPanel.updateLayout();
3293 alignPanel.paintAlignment(true, false);
3303 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3305 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3306 alignPanel.paintAlignment(false, false);
3316 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3318 viewport.setShowText(viewTextMenuItem.isSelected());
3319 alignPanel.paintAlignment(false, false);
3329 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3331 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3332 alignPanel.paintAlignment(false, false);
3335 public FeatureSettings featureSettings;
3338 public FeatureSettingsControllerI getFeatureSettingsUI()
3340 return featureSettings;
3344 public void featureSettings_actionPerformed(ActionEvent e)
3346 showFeatureSettingsUI();
3350 public FeatureSettingsControllerI showFeatureSettingsUI()
3352 if (featureSettings != null)
3354 featureSettings.closeOldSettings();
3355 featureSettings = null;
3357 if (!showSeqFeatures.isSelected())
3359 // make sure features are actually displayed
3360 showSeqFeatures.setSelected(true);
3361 showSeqFeatures_actionPerformed(null);
3363 featureSettings = new FeatureSettings(this);
3364 return featureSettings;
3368 * Set or clear 'Show Sequence Features'
3374 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3376 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3377 alignPanel.paintAlignment(true, true);
3381 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3382 * the annotations panel as a whole.
3384 * The options to show/hide all annotations should be enabled when the panel
3385 * is shown, and disabled when the panel is hidden.
3390 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3392 final boolean setVisible = annotationPanelMenuItem.isSelected();
3393 viewport.setShowAnnotation(setVisible);
3394 this.showAllSeqAnnotations.setEnabled(setVisible);
3395 this.hideAllSeqAnnotations.setEnabled(setVisible);
3396 this.showAllAlAnnotations.setEnabled(setVisible);
3397 this.hideAllAlAnnotations.setEnabled(setVisible);
3398 alignPanel.updateLayout();
3402 public void alignmentProperties()
3405 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3408 String content = MessageManager.formatMessage("label.html_content",
3410 { contents.toString() });
3413 if (Platform.isJS())
3415 JLabel textLabel = new JLabel();
3416 textLabel.setText(content);
3417 textLabel.setBackground(Color.WHITE);
3419 pane = new JPanel(new BorderLayout());
3420 ((JPanel) pane).setOpaque(true);
3421 pane.setBackground(Color.WHITE);
3422 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3431 JEditorPane editPane = new JEditorPane("text/html", "");
3432 editPane.setEditable(false);
3433 editPane.setText(content);
3437 JInternalFrame frame = new JInternalFrame();
3439 frame.getContentPane().add(new JScrollPane(pane));
3441 Desktop.addInternalFrame(frame, MessageManager
3442 .formatMessage("label.alignment_properties", new Object[]
3443 { getTitle() }), 500, 400);
3447 * Opens an Overview panel for the alignment, unless one is open already
3452 public void overviewMenuItem_actionPerformed(ActionEvent e)
3454 boolean showHiddenRegions = Cache
3455 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3456 openOverviewPanel(showHiddenRegions);
3459 public OverviewPanel openOverviewPanel(boolean showHidden)
3461 if (alignPanel.overviewPanel != null)
3463 return alignPanel.overviewPanel;
3465 JInternalFrame frame = new JInternalFrame();
3466 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3468 frame.setContentPane(overview);
3469 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3470 frame.getHeight(), true, true);
3471 frame.setFrameIcon(null);
3473 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3474 final AlignmentPanel thePanel = this.alignPanel;
3475 frame.addInternalFrameListener(
3476 new javax.swing.event.InternalFrameAdapter()
3479 public void internalFrameClosed(
3480 javax.swing.event.InternalFrameEvent evt)
3483 thePanel.setOverviewPanel(null);
3486 if (getKeyListeners().length > 0)
3488 frame.addKeyListener(getKeyListeners()[0]);
3491 alignPanel.setOverviewPanel(overview);
3492 alignPanel.setOverviewTitle(this);
3498 public void textColour_actionPerformed()
3500 new TextColourChooser().chooseColour(alignPanel, null);
3504 * public void covariationColour_actionPerformed() {
3506 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3510 public void annotationColour_actionPerformed()
3512 new AnnotationColourChooser(viewport, alignPanel);
3516 public void annotationColumn_actionPerformed(ActionEvent e)
3518 new AnnotationColumnChooser(viewport, alignPanel);
3522 * Action on the user checking or unchecking the option to apply the selected
3523 * colour scheme to all groups. If unchecked, groups may have their own
3524 * independent colour schemes.
3529 public void applyToAllGroups_actionPerformed(boolean selected)
3531 viewport.setColourAppliesToAllGroups(selected);
3535 * Action on user selecting a colour from the colour menu
3538 * the name (not the menu item label!) of the colour scheme
3541 public void changeColour_actionPerformed(String name)
3544 * 'User Defined' opens a panel to configure or load a
3545 * user-defined colour scheme
3547 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3549 new UserDefinedColours(alignPanel);
3554 * otherwise set the chosen colour scheme (or null for 'None')
3556 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3557 viewport, viewport.getAlignment(),
3558 viewport.getHiddenRepSequences());
3563 * Actions on setting or changing the alignment colour scheme
3568 public void changeColour(ColourSchemeI cs)
3570 // TODO: pull up to controller method
3571 ColourMenuHelper.setColourSelected(colourMenu, cs);
3573 viewport.setGlobalColourScheme(cs);
3575 alignPanel.paintAlignment(true, true);
3579 * Show the PID threshold slider panel
3582 protected void modifyPID_actionPerformed()
3584 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3585 alignPanel.getViewName());
3586 SliderPanel.showPIDSlider();
3590 * Show the Conservation slider panel
3593 protected void modifyConservation_actionPerformed()
3595 SliderPanel.setConservationSlider(alignPanel,
3596 viewport.getResidueShading(), alignPanel.getViewName());
3597 SliderPanel.showConservationSlider();
3601 * Action on selecting or deselecting (Colour) By Conservation
3604 public void conservationMenuItem_actionPerformed(boolean selected)
3606 modifyConservation.setEnabled(selected);
3607 viewport.setConservationSelected(selected);
3608 viewport.getResidueShading().setConservationApplied(selected);
3610 changeColour(viewport.getGlobalColourScheme());
3613 modifyConservation_actionPerformed();
3617 SliderPanel.hideConservationSlider();
3622 * Action on selecting or deselecting (Colour) Above PID Threshold
3625 public void abovePIDThreshold_actionPerformed(boolean selected)
3627 modifyPID.setEnabled(selected);
3628 viewport.setAbovePIDThreshold(selected);
3631 viewport.getResidueShading().setThreshold(0,
3632 viewport.isIgnoreGapsConsensus());
3635 changeColour(viewport.getGlobalColourScheme());
3638 modifyPID_actionPerformed();
3642 SliderPanel.hidePIDSlider();
3653 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3655 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3656 AlignmentSorter.sortByPID(viewport.getAlignment(),
3657 viewport.getAlignment().getSequenceAt(0));
3658 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3659 viewport.getAlignment()));
3660 alignPanel.paintAlignment(true, false);
3670 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3672 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3673 AlignmentSorter.sortByID(viewport.getAlignment());
3675 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3676 alignPanel.paintAlignment(true, false);
3686 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3688 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3689 AlignmentSorter.sortByLength(viewport.getAlignment());
3690 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3691 viewport.getAlignment()));
3692 alignPanel.paintAlignment(true, false);
3702 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3704 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3705 AlignmentSorter.sortByGroup(viewport.getAlignment());
3706 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3707 viewport.getAlignment()));
3709 alignPanel.paintAlignment(true, false);
3719 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3721 new RedundancyPanel(alignPanel, this);
3731 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3733 if ((viewport.getSelectionGroup() == null)
3734 || (viewport.getSelectionGroup().getSize() < 2))
3736 JvOptionPane.showInternalMessageDialog(this,
3737 MessageManager.getString(
3738 "label.you_must_select_least_two_sequences"),
3739 MessageManager.getString("label.invalid_selection"),
3740 JvOptionPane.WARNING_MESSAGE);
3744 JInternalFrame frame = new JInternalFrame();
3745 frame.setContentPane(new PairwiseAlignPanel(viewport));
3746 Desktop.addInternalFrame(frame,
3747 MessageManager.getString("action.pairwise_alignment"), 600,
3753 public void autoCalculate_actionPerformed(ActionEvent e)
3755 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3756 if (viewport.autoCalculateConsensus)
3758 viewport.firePropertyChange("alignment", null,
3759 viewport.getAlignment().getSequences());
3764 public void sortByTreeOption_actionPerformed(ActionEvent e)
3766 viewport.sortByTree = sortByTree.isSelected();
3770 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3772 viewport.followSelection = listenToViewSelections.isSelected();
3776 * Constructs a tree panel and adds it to the desktop
3779 * tree type (NJ or AV)
3781 * name of score model used to compute the tree
3783 * parameters for the distance or similarity calculation
3785 void newTreePanel(String type, String modelName,
3786 SimilarityParamsI options)
3788 String frameTitle = "";
3791 boolean onSelection = false;
3792 if (viewport.getSelectionGroup() != null
3793 && viewport.getSelectionGroup().getSize() > 0)
3795 SequenceGroup sg = viewport.getSelectionGroup();
3797 /* Decide if the selection is a column region */
3798 for (SequenceI _s : sg.getSequences())
3800 if (_s.getLength() < sg.getEndRes())
3802 JvOptionPane.showMessageDialog(Desktop.desktop,
3803 MessageManager.getString(
3804 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3805 MessageManager.getString(
3806 "label.sequences_selection_not_aligned"),
3807 JvOptionPane.WARNING_MESSAGE);
3816 if (viewport.getAlignment().getHeight() < 2)
3822 tp = new TreePanel(alignPanel, type, modelName, options);
3823 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3825 frameTitle += " from ";
3827 if (viewport.getViewName() != null)
3829 frameTitle += viewport.getViewName() + " of ";
3832 frameTitle += this.title;
3834 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3845 public void addSortByOrderMenuItem(String title,
3846 final AlignmentOrder order)
3848 final JMenuItem item = new JMenuItem(MessageManager
3849 .formatMessage("action.by_title_param", new Object[]
3852 item.addActionListener(new java.awt.event.ActionListener()
3855 public void actionPerformed(ActionEvent e)
3857 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3859 // TODO: JBPNote - have to map order entries to curent SequenceI
3861 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3863 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3864 viewport.getAlignment()));
3866 alignPanel.paintAlignment(true, false);
3872 * Add a new sort by annotation score menu item
3875 * the menu to add the option to
3877 * the label used to retrieve scores for each sequence on the
3880 public void addSortByAnnotScoreMenuItem(JMenu sort,
3881 final String scoreLabel)
3883 final JMenuItem item = new JMenuItem(scoreLabel);
3885 item.addActionListener(new java.awt.event.ActionListener()
3888 public void actionPerformed(ActionEvent e)
3890 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3891 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3892 viewport.getAlignment());// ,viewport.getSelectionGroup());
3893 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3894 viewport.getAlignment()));
3895 alignPanel.paintAlignment(true, false);
3901 * last hash for alignment's annotation array - used to minimise cost of
3904 protected int _annotationScoreVectorHash;
3907 * search the alignment and rebuild the sort by annotation score submenu the
3908 * last alignment annotation vector hash is stored to minimize cost of
3909 * rebuilding in subsequence calls.
3913 public void buildSortByAnnotationScoresMenu()
3915 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3920 if (viewport.getAlignment().getAlignmentAnnotation()
3921 .hashCode() != _annotationScoreVectorHash)
3923 sortByAnnotScore.removeAll();
3924 // almost certainly a quicker way to do this - but we keep it simple
3925 Hashtable<String, String> scoreSorts = new Hashtable<>();
3926 AlignmentAnnotation aann[];
3927 for (SequenceI sqa : viewport.getAlignment().getSequences())
3929 aann = sqa.getAnnotation();
3930 for (int i = 0; aann != null && i < aann.length; i++)
3932 if (aann[i].hasScore() && aann[i].sequenceRef != null)
3934 scoreSorts.put(aann[i].label, aann[i].label);
3938 Enumeration<String> labels = scoreSorts.keys();
3939 while (labels.hasMoreElements())
3941 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
3943 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
3946 _annotationScoreVectorHash = viewport.getAlignment()
3947 .getAlignmentAnnotation().hashCode();
3952 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
3953 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
3954 * call. Listeners are added to remove the menu item when the treePanel is
3955 * closed, and adjust the tree leaf to sequence mapping when the alignment is
3959 public void buildTreeSortMenu()
3961 sortByTreeMenu.removeAll();
3963 List<Component> comps = PaintRefresher.components
3964 .get(viewport.getSequenceSetId());
3965 List<TreePanel> treePanels = new ArrayList<>();
3966 for (Component comp : comps)
3968 if (comp instanceof TreePanel)
3970 treePanels.add((TreePanel) comp);
3974 if (treePanels.size() < 1)
3976 sortByTreeMenu.setVisible(false);
3980 sortByTreeMenu.setVisible(true);
3982 for (final TreePanel tp : treePanels)
3984 final JMenuItem item = new JMenuItem(tp.getTitle());
3985 item.addActionListener(new java.awt.event.ActionListener()
3988 public void actionPerformed(ActionEvent e)
3990 tp.sortByTree_actionPerformed();
3991 addHistoryItem(tp.sortAlignmentIn(alignPanel));
3996 sortByTreeMenu.add(item);
4000 public boolean sortBy(AlignmentOrder alorder, String undoname)
4002 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4003 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4004 if (undoname != null)
4006 addHistoryItem(new OrderCommand(undoname, oldOrder,
4007 viewport.getAlignment()));
4009 alignPanel.paintAlignment(true, false);
4014 * Work out whether the whole set of sequences or just the selected set will
4015 * be submitted for multiple alignment.
4018 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4020 // Now, check we have enough sequences
4021 AlignmentView msa = null;
4023 if ((viewport.getSelectionGroup() != null)
4024 && (viewport.getSelectionGroup().getSize() > 1))
4026 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4027 // some common interface!
4029 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4030 * SequenceI[sz = seqs.getSize(false)];
4032 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4033 * seqs.getSequenceAt(i); }
4035 msa = viewport.getAlignmentView(true);
4037 else if (viewport.getSelectionGroup() != null
4038 && viewport.getSelectionGroup().getSize() == 1)
4040 int option = JvOptionPane.showConfirmDialog(this,
4041 MessageManager.getString("warn.oneseq_msainput_selection"),
4042 MessageManager.getString("label.invalid_selection"),
4043 JvOptionPane.OK_CANCEL_OPTION);
4044 if (option == JvOptionPane.OK_OPTION)
4046 msa = viewport.getAlignmentView(false);
4051 msa = viewport.getAlignmentView(false);
4057 * Decides what is submitted to a secondary structure prediction service: the
4058 * first sequence in the alignment, or in the current selection, or, if the
4059 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4060 * region or the whole alignment. (where the first sequence in the set is the
4061 * one that the prediction will be for).
4063 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4065 AlignmentView seqs = null;
4067 if ((viewport.getSelectionGroup() != null)
4068 && (viewport.getSelectionGroup().getSize() > 0))
4070 seqs = viewport.getAlignmentView(true);
4074 seqs = viewport.getAlignmentView(false);
4076 // limit sequences - JBPNote in future - could spawn multiple prediction
4078 // TODO: viewport.getAlignment().isAligned is a global state - the local
4079 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4080 if (!viewport.getAlignment().isAligned(false))
4082 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4083 // TODO: if seqs.getSequences().length>1 then should really have warned
4097 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4099 // Pick the tree file
4100 JalviewFileChooser chooser = new JalviewFileChooser(
4101 Cache.getProperty("LAST_DIRECTORY"));
4102 chooser.setFileView(new JalviewFileView());
4103 chooser.setDialogTitle(
4104 MessageManager.getString("label.select_newick_like_tree_file"));
4105 chooser.setToolTipText(
4106 MessageManager.getString("label.load_tree_file"));
4108 chooser.setResponseHandler(0, () -> {
4109 String filePath = chooser.getSelectedFile().getPath();
4110 Cache.setProperty("LAST_DIRECTORY", filePath);
4111 NewickFile fin = null;
4114 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4115 DataSourceType.FILE));
4116 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4117 } catch (Exception ex)
4119 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4120 MessageManager.getString("label.problem_reading_tree_file"),
4121 JvOptionPane.WARNING_MESSAGE);
4122 ex.printStackTrace();
4124 if (fin != null && fin.hasWarningMessage())
4126 JvOptionPane.showMessageDialog(Desktop.desktop,
4127 fin.getWarningMessage(),
4129 .getString("label.possible_problem_with_tree_file"),
4130 JvOptionPane.WARNING_MESSAGE);
4133 chooser.showOpenDialog(this);
4136 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4138 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4141 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4142 int h, int x, int y)
4144 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4148 * Add a treeviewer for the tree extracted from a Newick file object to the
4149 * current alignment view
4156 * Associated alignment input data (or null)
4165 * @return TreePanel handle
4167 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4168 AlignmentView input, int w, int h, int x, int y)
4170 TreePanel tp = null;
4176 if (nf.getTree() != null)
4178 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4184 tp.setLocation(x, y);
4187 Desktop.addInternalFrame(tp, treeTitle, w, h);
4189 } catch (Exception ex)
4191 ex.printStackTrace();
4197 public void showContactMapTree(AlignmentAnnotation aa,
4198 PAEContactMatrix cm)
4201 int w = 400, h = 500;
4205 NewickFile fin = new NewickFile(
4206 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4207 String title = "PAE Matrix Tree for "
4208 + cm.getReferenceSeq().getDisplayId(false);
4210 showColumnWiseTree(fin, aa, title, w, h, x, y);
4211 } catch (Throwable xx)
4213 Console.error("Unexpected exception showing tree for contact matrix",
4218 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4219 String treeTitle, int w, int h, int x, int y)
4224 if (nf.getTree() == null)
4228 TreePanel tp = new TreePanel(alignPanel, nf, aa, title);
4234 tp.setLocation(x, y);
4237 Desktop.addInternalFrame(tp, title, w, h);
4239 } catch (Throwable xx)
4241 Console.error("Unexpected exception showing tree for contact matrix",
4247 private boolean buildingMenu = false;
4250 * Generates menu items and listener event actions for web service clients
4253 public void BuildWebServiceMenu()
4255 while (buildingMenu)
4259 System.err.println("Waiting for building menu to finish.");
4261 } catch (Exception e)
4265 final AlignFrame me = this;
4266 buildingMenu = true;
4267 new Thread(new Runnable()
4272 final List<JMenuItem> legacyItems = new ArrayList<>();
4275 // System.err.println("Building ws menu again "
4276 // + Thread.currentThread());
4277 // TODO: add support for context dependent disabling of services based
4279 // alignment and current selection
4280 // TODO: add additional serviceHandle parameter to specify abstract
4282 // class independently of AbstractName
4283 // TODO: add in rediscovery GUI function to restart discoverer
4284 // TODO: group services by location as well as function and/or
4286 // object broker mechanism.
4287 final Vector<JMenu> wsmenu = new Vector<>();
4288 final IProgressIndicator af = me;
4291 * do not i18n these strings - they are hard-coded in class
4292 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4293 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4295 final JMenu msawsmenu = new JMenu("Alignment");
4296 final JMenu secstrmenu = new JMenu(
4297 "Secondary Structure Prediction");
4298 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4299 final JMenu analymenu = new JMenu("Analysis");
4300 final JMenu dismenu = new JMenu("Protein Disorder");
4301 // JAL-940 - only show secondary structure prediction services from
4302 // the legacy server
4303 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4305 Discoverer.services != null && (Discoverer.services.size() > 0))
4307 // TODO: refactor to allow list of AbstractName/Handler bindings to
4309 // stored or retrieved from elsewhere
4310 // No MSAWS used any more:
4311 // Vector msaws = null; // (Vector)
4312 // Discoverer.services.get("MsaWS");
4313 Vector<ServiceHandle> secstrpr = Discoverer.services
4315 if (secstrpr != null)
4317 // Add any secondary structure prediction services
4318 for (int i = 0, j = secstrpr.size(); i < j; i++)
4320 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4321 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4322 .getServiceClient(sh);
4323 int p = secstrmenu.getItemCount();
4324 impl.attachWSMenuEntry(secstrmenu, me);
4325 int q = secstrmenu.getItemCount();
4326 for (int litm = p; litm < q; litm++)
4328 legacyItems.add(secstrmenu.getItem(litm));
4334 // Add all submenus in the order they should appear on the web
4336 wsmenu.add(msawsmenu);
4337 wsmenu.add(secstrmenu);
4338 wsmenu.add(dismenu);
4339 wsmenu.add(analymenu);
4340 // No search services yet
4341 // wsmenu.add(seqsrchmenu);
4343 javax.swing.SwingUtilities.invokeLater(new Runnable()
4350 webService.removeAll();
4351 // first, add discovered services onto the webservices menu
4352 if (wsmenu.size() > 0)
4354 for (int i = 0, j = wsmenu.size(); i < j; i++)
4356 webService.add(wsmenu.get(i));
4361 webService.add(me.webServiceNoServices);
4363 // TODO: move into separate menu builder class.
4365 // logic for 2.11.1.4 is
4366 // always look to see if there is a discover. if there isn't
4367 // we can't show any Jws2 services
4368 // if there are services available, show them - regardless of
4369 // the 'show JWS2 preference'
4370 // if the discoverer is running then say so
4371 // otherwise offer to trigger discovery if 'show JWS2' is not
4373 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4374 if (jws2servs != null)
4376 if (jws2servs.hasServices())
4378 jws2servs.attachWSMenuEntry(webService, me);
4379 for (Jws2Instance sv : jws2servs.getServices())
4381 if (sv.description.toLowerCase(Locale.ROOT)
4384 for (JMenuItem jmi : legacyItems)
4386 jmi.setVisible(false);
4392 if (jws2servs.isRunning())
4394 JMenuItem tm = new JMenuItem(
4395 "Still discovering JABA Services");
4396 tm.setEnabled(false);
4399 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4401 JMenuItem enableJws2 = new JMenuItem(
4402 "Discover Web Services");
4403 enableJws2.setToolTipText(
4404 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4405 enableJws2.setEnabled(true);
4406 enableJws2.addActionListener(new ActionListener()
4410 public void actionPerformed(ActionEvent e)
4412 // start service discoverer, but ignore preference
4413 Desktop.instance.startServiceDiscovery(false,
4417 webService.add(enableJws2);
4421 build_urlServiceMenu(me.webService);
4422 build_fetchdbmenu(webService);
4423 for (JMenu item : wsmenu)
4425 if (item.getItemCount() == 0)
4427 item.setEnabled(false);
4431 item.setEnabled(true);
4434 } catch (Exception e)
4437 "Exception during web service menu building process.",
4442 } catch (Exception e)
4445 buildingMenu = false;
4452 * construct any groupURL type service menu entries.
4456 protected void build_urlServiceMenu(JMenu webService)
4458 // TODO: remove this code when 2.7 is released
4459 // DEBUG - alignmentView
4461 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4462 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4464 * @Override public void actionPerformed(ActionEvent e) {
4465 * jalview.datamodel.AlignmentView
4466 * .testSelectionViews(af.viewport.getAlignment(),
4467 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4469 * }); webService.add(testAlView);
4471 // TODO: refactor to RestClient discoverer and merge menu entries for
4472 // rest-style services with other types of analysis/calculation service
4473 // SHmmr test client - still being implemented.
4474 // DEBUG - alignmentView
4476 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4479 client.attachWSMenuEntry(
4480 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4486 * Searches the alignment sequences for xRefs and builds the Show
4487 * Cross-References menu (formerly called Show Products), with database
4488 * sources for which cross-references are found (protein sources for a
4489 * nucleotide alignment and vice versa)
4491 * @return true if Show Cross-references menu should be enabled
4493 public boolean canShowProducts()
4495 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4496 AlignmentI dataset = viewport.getAlignment().getDataset();
4498 showProducts.removeAll();
4499 final boolean dna = viewport.getAlignment().isNucleotide();
4501 if (seqs == null || seqs.length == 0)
4503 // nothing to see here.
4507 boolean showp = false;
4510 List<String> ptypes = new CrossRef(seqs, dataset)
4511 .findXrefSourcesForSequences(dna);
4513 for (final String source : ptypes)
4516 final AlignFrame af = this;
4517 JMenuItem xtype = new JMenuItem(source);
4518 xtype.addActionListener(new ActionListener()
4521 public void actionPerformed(ActionEvent e)
4523 showProductsFor(af.viewport.getSequenceSelection(), dna,
4527 showProducts.add(xtype);
4529 showProducts.setVisible(showp);
4530 showProducts.setEnabled(showp);
4531 } catch (Exception e)
4534 "canShowProducts threw an exception - please report to help@jalview.org",
4542 * Finds and displays cross-references for the selected sequences (protein
4543 * products for nucleotide sequences, dna coding sequences for peptides).
4546 * the sequences to show cross-references for
4548 * true if from a nucleotide alignment (so showing proteins)
4550 * the database to show cross-references for
4552 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4553 final String source)
4555 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4560 * Construct and display a new frame containing the translation of this
4561 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4564 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4566 AlignmentI al = null;
4569 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4571 al = dna.translateCdna(codeTable);
4572 } catch (Exception ex)
4574 Console.error("Exception during translation. Please report this !",
4576 final String msg = MessageManager.getString(
4577 "label.error_when_translating_sequences_submit_bug_report");
4578 final String errorTitle = MessageManager
4579 .getString("label.implementation_error")
4580 + MessageManager.getString("label.translation_failed");
4581 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4582 JvOptionPane.ERROR_MESSAGE);
4585 if (al == null || al.getHeight() == 0)
4587 final String msg = MessageManager.getString(
4588 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4589 final String errorTitle = MessageManager
4590 .getString("label.translation_failed");
4591 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4592 JvOptionPane.WARNING_MESSAGE);
4596 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4597 af.setFileFormat(this.currentFileFormat);
4598 final String newTitle = MessageManager
4599 .formatMessage("label.translation_of_params", new Object[]
4600 { this.getTitle(), codeTable.getId() });
4601 af.setTitle(newTitle);
4602 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4604 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4605 viewport.openSplitFrame(af, new Alignment(seqs));
4609 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4616 * Set the file format
4620 public void setFileFormat(FileFormatI format)
4622 this.currentFileFormat = format;
4626 * Try to load a features file onto the alignment.
4629 * contents or path to retrieve file or a File object
4631 * access mode of file (see jalview.io.AlignFile)
4632 * @return true if features file was parsed correctly.
4634 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4637 return avc.parseFeaturesFile(file, sourceType,
4638 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4643 public void refreshFeatureUI(boolean enableIfNecessary)
4645 // note - currently this is only still here rather than in the controller
4646 // because of the featureSettings hard reference that is yet to be
4648 if (enableIfNecessary)
4650 viewport.setShowSequenceFeatures(true);
4651 showSeqFeatures.setSelected(true);
4657 public void dragEnter(DropTargetDragEvent evt)
4662 public void dragExit(DropTargetEvent evt)
4667 public void dragOver(DropTargetDragEvent evt)
4672 public void dropActionChanged(DropTargetDragEvent evt)
4677 public void drop(DropTargetDropEvent evt)
4679 // JAL-1552 - acceptDrop required before getTransferable call for
4680 // Java's Transferable for native dnd
4681 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4682 Transferable t = evt.getTransferable();
4684 final AlignFrame thisaf = this;
4685 final List<Object> files = new ArrayList<>();
4686 List<DataSourceType> protocols = new ArrayList<>();
4690 Desktop.transferFromDropTarget(files, protocols, evt, t);
4691 } catch (Exception e)
4693 e.printStackTrace();
4697 new Thread(new Runnable()
4704 // check to see if any of these files have names matching sequences
4707 SequenceIdMatcher idm = new SequenceIdMatcher(
4708 viewport.getAlignment().getSequencesArray());
4710 * Object[] { String,SequenceI}
4712 ArrayList<Object[]> filesmatched = new ArrayList<>();
4713 ArrayList<Object> filesnotmatched = new ArrayList<>();
4714 for (int i = 0; i < files.size(); i++)
4717 Object file = files.get(i);
4718 String fileName = file.toString();
4720 DataSourceType protocol = (file instanceof File
4721 ? DataSourceType.FILE
4722 : FormatAdapter.checkProtocol(fileName));
4723 if (protocol == DataSourceType.FILE)
4726 if (file instanceof File)
4729 Platform.cacheFileData(fl);
4733 fl = new File(fileName);
4735 pdbfn = fl.getName();
4737 else if (protocol == DataSourceType.URL)
4739 URL url = new URL(fileName);
4740 pdbfn = url.getFile();
4742 if (pdbfn.length() > 0)
4744 // attempt to find a match in the alignment
4745 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4746 int l = 0, c = pdbfn.indexOf(".");
4747 while (mtch == null && c != -1)
4752 } while ((c = pdbfn.indexOf(".", l)) > l);
4755 pdbfn = pdbfn.substring(0, l);
4757 mtch = idm.findAllIdMatches(pdbfn);
4764 type = new IdentifyFile().identify(file, protocol);
4765 } catch (Exception ex)
4769 if (type != null && type.isStructureFile())
4771 filesmatched.add(new Object[] { file, protocol, mtch });
4775 // File wasn't named like one of the sequences or wasn't a PDB
4777 filesnotmatched.add(file);
4781 if (filesmatched.size() > 0)
4783 boolean autoAssociate = Cache
4784 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4787 String msg = MessageManager.formatMessage(
4788 "label.automatically_associate_structure_files_with_sequences_same_name",
4790 { Integer.valueOf(filesmatched.size())
4792 String ttl = MessageManager.getString(
4793 "label.automatically_associate_structure_files_by_name");
4794 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4795 ttl, JvOptionPane.YES_NO_OPTION);
4796 autoAssociate = choice == JvOptionPane.YES_OPTION;
4800 for (Object[] fm : filesmatched)
4802 // try and associate
4803 // TODO: may want to set a standard ID naming formalism for
4804 // associating PDB files which have no IDs.
4805 for (SequenceI toassoc : (SequenceI[]) fm[2])
4807 PDBEntry pe = new AssociatePdbFileWithSeq()
4808 .associatePdbWithSeq(fm[0].toString(),
4809 (DataSourceType) fm[1], toassoc, false,
4813 System.err.println("Associated file : "
4814 + (fm[0].toString()) + " with "
4815 + toassoc.getDisplayId(true));
4819 // TODO: do we need to update overview ? only if features are
4821 alignPanel.paintAlignment(true, false);
4827 * add declined structures as sequences
4829 for (Object[] o : filesmatched)
4831 filesnotmatched.add(o[0]);
4835 if (filesnotmatched.size() > 0)
4837 if (assocfiles > 0 && (Cache.getDefault(
4838 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4839 || JvOptionPane.showConfirmDialog(thisaf,
4840 "<html>" + MessageManager.formatMessage(
4841 "label.ignore_unmatched_dropped_files_info",
4844 filesnotmatched.size())
4847 MessageManager.getString(
4848 "label.ignore_unmatched_dropped_files"),
4849 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4853 for (Object fn : filesnotmatched)
4855 loadJalviewDataFile(fn, null, null, null);
4859 } catch (Exception ex)
4861 ex.printStackTrace();
4869 * Attempt to load a "dropped" file or URL string, by testing in turn for
4871 * <li>an Annotation file</li>
4872 * <li>a JNet file</li>
4873 * <li>a features file</li>
4874 * <li>else try to interpret as an alignment file</li>
4878 * either a filename or a URL string.
4880 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4881 FileFormatI format, SequenceI assocSeq)
4883 // BH 2018 was String file
4886 if (sourceType == null)
4888 sourceType = FormatAdapter.checkProtocol(file);
4890 // if the file isn't identified, or not positively identified as some
4891 // other filetype (PFAM is default unidentified alignment file type) then
4892 // try to parse as annotation.
4893 boolean isAnnotation = (format == null
4894 || FileFormat.Pfam.equals(format))
4895 ? new AnnotationFile().annotateAlignmentView(viewport,
4901 // first see if its a T-COFFEE score file
4902 TCoffeeScoreFile tcf = null;
4905 tcf = new TCoffeeScoreFile(file, sourceType);
4908 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4912 new TCoffeeColourScheme(viewport.getAlignment()));
4913 isAnnotation = true;
4914 setStatus(MessageManager.getString(
4915 "label.successfully_pasted_tcoffee_scores_to_alignment"));
4919 // some problem - if no warning its probable that the ID matching
4920 // process didn't work
4921 JvOptionPane.showMessageDialog(Desktop.desktop,
4922 tcf.getWarningMessage() == null
4923 ? MessageManager.getString(
4924 "label.check_file_matches_sequence_ids_alignment")
4925 : tcf.getWarningMessage(),
4926 MessageManager.getString(
4927 "label.problem_reading_tcoffee_score_file"),
4928 JvOptionPane.WARNING_MESSAGE);
4935 } catch (Exception x)
4938 "Exception when processing data source as T-COFFEE score file",
4944 // try to see if its a JNet 'concise' style annotation file *before*
4946 // try to parse it as a features file
4949 format = new IdentifyFile().identify(file, sourceType);
4951 if (FileFormat.ScoreMatrix == format)
4953 ScoreMatrixFile sm = new ScoreMatrixFile(
4954 new FileParse(file, sourceType));
4956 // todo: i18n this message
4957 setStatus(MessageManager.formatMessage(
4958 "label.successfully_loaded_matrix",
4959 sm.getMatrixName()));
4961 else if (FileFormat.Jnet.equals(format))
4963 JPredFile predictions = new JPredFile(file, sourceType);
4964 new JnetAnnotationMaker();
4965 JnetAnnotationMaker.add_annotation(predictions,
4966 viewport.getAlignment(), 0, false);
4967 viewport.getAlignment().setupJPredAlignment();
4968 isAnnotation = true;
4970 // else if (IdentifyFile.FeaturesFile.equals(format))
4971 else if (FileFormat.Features.equals(format))
4973 if (parseFeaturesFile(file, sourceType))
4975 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
4976 if (splitFrame != null)
4978 splitFrame.repaint();
4982 alignPanel.paintAlignment(true, true);
4988 new FileLoader().LoadFile(viewport, file, sourceType, format);
4995 alignPanel.adjustAnnotationHeight();
4996 viewport.updateSequenceIdColours();
4997 buildSortByAnnotationScoresMenu();
4998 alignPanel.paintAlignment(true, true);
5000 } catch (Exception ex)
5002 ex.printStackTrace();
5003 } catch (OutOfMemoryError oom)
5008 } catch (Exception x)
5013 + (sourceType != null
5014 ? (sourceType == DataSourceType.PASTE
5016 : "using " + sourceType + " from "
5020 ? "(parsing as '" + format + "' file)"
5022 oom, Desktop.desktop);
5027 * Method invoked by the ChangeListener on the tabbed pane, in other words
5028 * when a different tabbed pane is selected by the user or programmatically.
5031 public void tabSelectionChanged(int index)
5036 * update current Overview window title (if there is one)
5037 * to add view name "Original" if necessary
5039 alignPanel.setOverviewTitle(this);
5042 * switch panels and set Overview title (if there is one
5043 * because it was opened automatically)
5045 alignPanel = alignPanels.get(index);
5046 alignPanel.setOverviewTitle(this);
5048 viewport = alignPanel.av;
5049 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5050 setMenusFromViewport(viewport);
5051 if (featureSettings != null && featureSettings.isOpen()
5052 && featureSettings.fr.getViewport() != viewport)
5054 if (viewport.isShowSequenceFeatures())
5056 // refresh the featureSettings to reflect UI change
5057 showFeatureSettingsUI();
5061 // close feature settings for this view.
5062 featureSettings.close();
5069 * 'focus' any colour slider that is open to the selected viewport
5071 if (viewport.getConservationSelected())
5073 SliderPanel.setConservationSlider(alignPanel,
5074 viewport.getResidueShading(), alignPanel.getViewName());
5078 SliderPanel.hideConservationSlider();
5080 if (viewport.getAbovePIDThreshold())
5082 SliderPanel.setPIDSliderSource(alignPanel,
5083 viewport.getResidueShading(), alignPanel.getViewName());
5087 SliderPanel.hidePIDSlider();
5091 * If there is a frame linked to this one in a SplitPane, switch it to the
5092 * same view tab index. No infinite recursion of calls should happen, since
5093 * tabSelectionChanged() should not get invoked on setting the selected
5094 * index to an unchanged value. Guard against setting an invalid index
5095 * before the new view peer tab has been created.
5097 final AlignViewportI peer = viewport.getCodingComplement();
5100 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5101 .getAlignPanel().alignFrame;
5102 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5104 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5110 * On right mouse click on view tab, prompt for and set new view name.
5113 public void tabbedPane_mousePressed(MouseEvent e)
5115 if (e.isPopupTrigger())
5117 String msg = MessageManager.getString("label.enter_view_name");
5118 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5119 String reply = JvOptionPane.showInputDialog(msg, ttl);
5123 viewport.setViewName(reply);
5124 // TODO warn if reply is in getExistingViewNames()?
5125 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5130 public AlignViewport getCurrentView()
5136 * Open the dialog for regex description parsing.
5139 protected void extractScores_actionPerformed(ActionEvent e)
5141 ParseProperties pp = new jalview.analysis.ParseProperties(
5142 viewport.getAlignment());
5143 // TODO: verify regex and introduce GUI dialog for version 2.5
5144 // if (pp.getScoresFromDescription("col", "score column ",
5145 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5147 if (pp.getScoresFromDescription("description column",
5148 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5150 buildSortByAnnotationScoresMenu();
5158 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5162 protected void showDbRefs_actionPerformed(ActionEvent e)
5164 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5170 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5174 protected void showNpFeats_actionPerformed(ActionEvent e)
5176 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5180 * find the viewport amongst the tabs in this alignment frame and close that
5185 public boolean closeView(AlignViewportI av)
5189 this.closeMenuItem_actionPerformed(false);
5192 Component[] comp = tabbedPane.getComponents();
5193 for (int i = 0; comp != null && i < comp.length; i++)
5195 if (comp[i] instanceof AlignmentPanel)
5197 if (((AlignmentPanel) comp[i]).av == av)
5200 closeView((AlignmentPanel) comp[i]);
5208 protected void build_fetchdbmenu(JMenu webService)
5210 // Temporary hack - DBRef Fetcher always top level ws entry.
5211 // TODO We probably want to store a sequence database checklist in
5212 // preferences and have checkboxes.. rather than individual sources selected
5214 final JMenu rfetch = new JMenu(
5215 MessageManager.getString("action.fetch_db_references"));
5216 rfetch.setToolTipText(MessageManager.getString(
5217 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5218 webService.add(rfetch);
5220 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5221 MessageManager.getString("option.trim_retrieved_seqs"));
5222 trimrs.setToolTipText(
5223 MessageManager.getString("label.trim_retrieved_sequences"));
5225 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5226 trimrs.addActionListener(new ActionListener()
5229 public void actionPerformed(ActionEvent e)
5231 trimrs.setSelected(trimrs.isSelected());
5232 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5233 Boolean.valueOf(trimrs.isSelected()).toString());
5237 JMenuItem fetchr = new JMenuItem(
5238 MessageManager.getString("label.standard_databases"));
5239 fetchr.setToolTipText(
5240 MessageManager.getString("label.fetch_embl_uniprot"));
5241 fetchr.addActionListener(new ActionListener()
5245 public void actionPerformed(ActionEvent e)
5247 new Thread(new Runnable()
5252 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5253 .getAlignment().isNucleotide();
5254 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5255 alignPanel.av.getSequenceSelection(),
5256 alignPanel.alignFrame, null,
5257 alignPanel.alignFrame.featureSettings, isNucleotide);
5258 dbRefFetcher.addListener(new FetchFinishedListenerI()
5261 public void finished()
5264 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5265 .getFeatureSettingsModels())
5268 alignPanel.av.mergeFeaturesStyle(srcSettings);
5270 AlignFrame.this.setMenusForViewport();
5273 dbRefFetcher.fetchDBRefs(false);
5281 new Thread(new Runnable()
5286 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5287 .getSequenceFetcherSingleton();
5288 javax.swing.SwingUtilities.invokeLater(new Runnable()
5293 String[] dbclasses = sf.getNonAlignmentSources();
5294 List<DbSourceProxy> otherdb;
5295 JMenu dfetch = new JMenu();
5296 JMenu ifetch = new JMenu();
5297 JMenuItem fetchr = null;
5298 int comp = 0, icomp = 0, mcomp = 15;
5299 String mname = null;
5301 for (String dbclass : dbclasses)
5303 otherdb = sf.getSourceProxy(dbclass);
5304 // add a single entry for this class, or submenu allowing 'fetch
5306 if (otherdb == null || otherdb.size() < 1)
5312 mname = "From " + dbclass;
5314 if (otherdb.size() == 1)
5316 final DbSourceProxy[] dassource = otherdb
5317 .toArray(new DbSourceProxy[0]);
5318 DbSourceProxy src = otherdb.get(0);
5319 fetchr = new JMenuItem(src.getDbSource());
5320 fetchr.addActionListener(new ActionListener()
5324 public void actionPerformed(ActionEvent e)
5326 new Thread(new Runnable()
5332 boolean isNucleotide = alignPanel.alignFrame
5333 .getViewport().getAlignment()
5335 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5336 alignPanel.av.getSequenceSelection(),
5337 alignPanel.alignFrame, dassource,
5338 alignPanel.alignFrame.featureSettings,
5341 .addListener(new FetchFinishedListenerI()
5344 public void finished()
5346 FeatureSettingsModelI srcSettings = dassource[0]
5347 .getFeatureColourScheme();
5348 alignPanel.av.mergeFeaturesStyle(
5350 AlignFrame.this.setMenusForViewport();
5353 dbRefFetcher.fetchDBRefs(false);
5359 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5360 MessageManager.formatMessage(
5361 "label.fetch_retrieve_from", new Object[]
5362 { src.getDbName() })));
5368 final DbSourceProxy[] dassource = otherdb
5369 .toArray(new DbSourceProxy[0]);
5371 DbSourceProxy src = otherdb.get(0);
5372 fetchr = new JMenuItem(MessageManager
5373 .formatMessage("label.fetch_all_param", new Object[]
5374 { src.getDbSource() }));
5375 fetchr.addActionListener(new ActionListener()
5378 public void actionPerformed(ActionEvent e)
5380 new Thread(new Runnable()
5386 boolean isNucleotide = alignPanel.alignFrame
5387 .getViewport().getAlignment()
5389 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5390 alignPanel.av.getSequenceSelection(),
5391 alignPanel.alignFrame, dassource,
5392 alignPanel.alignFrame.featureSettings,
5395 .addListener(new FetchFinishedListenerI()
5398 public void finished()
5400 AlignFrame.this.setMenusForViewport();
5403 dbRefFetcher.fetchDBRefs(false);
5409 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5410 MessageManager.formatMessage(
5411 "label.fetch_retrieve_from_all_sources",
5413 { Integer.valueOf(otherdb.size())
5415 src.getDbSource(), src.getDbName() })));
5418 // and then build the rest of the individual menus
5419 ifetch = new JMenu(MessageManager.formatMessage(
5420 "label.source_from_db_source", new Object[]
5421 { src.getDbSource() }));
5423 String imname = null;
5425 for (DbSourceProxy sproxy : otherdb)
5427 String dbname = sproxy.getDbName();
5428 String sname = dbname.length() > 5
5429 ? dbname.substring(0, 5) + "..."
5431 String msname = dbname.length() > 10
5432 ? dbname.substring(0, 10) + "..."
5436 imname = MessageManager
5437 .formatMessage("label.from_msname", new Object[]
5440 fetchr = new JMenuItem(msname);
5441 final DbSourceProxy[] dassrc = { sproxy };
5442 fetchr.addActionListener(new ActionListener()
5446 public void actionPerformed(ActionEvent e)
5448 new Thread(new Runnable()
5454 boolean isNucleotide = alignPanel.alignFrame
5455 .getViewport().getAlignment()
5457 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5458 alignPanel.av.getSequenceSelection(),
5459 alignPanel.alignFrame, dassrc,
5460 alignPanel.alignFrame.featureSettings,
5463 .addListener(new FetchFinishedListenerI()
5466 public void finished()
5468 AlignFrame.this.setMenusForViewport();
5471 dbRefFetcher.fetchDBRefs(false);
5477 fetchr.setToolTipText(
5478 "<html>" + MessageManager.formatMessage(
5479 "label.fetch_retrieve_from", new Object[]
5483 if (++icomp >= mcomp || i == (otherdb.size()))
5485 ifetch.setText(MessageManager.formatMessage(
5486 "label.source_to_target", imname, sname));
5488 ifetch = new JMenu();
5496 if (comp >= mcomp || dbi >= (dbclasses.length))
5498 dfetch.setText(MessageManager.formatMessage(
5499 "label.source_to_target", mname, dbclass));
5501 dfetch = new JMenu();
5514 * Left justify the whole alignment.
5517 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5519 AlignmentI al = viewport.getAlignment();
5521 viewport.firePropertyChange("alignment", null, al);
5525 * Right justify the whole alignment.
5528 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5530 AlignmentI al = viewport.getAlignment();
5532 viewport.firePropertyChange("alignment", null, al);
5536 public void setShowSeqFeatures(boolean b)
5538 showSeqFeatures.setSelected(b);
5539 viewport.setShowSequenceFeatures(b);
5546 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5547 * awt.event.ActionEvent)
5550 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5552 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5553 alignPanel.paintAlignment(false, false);
5560 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5564 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5566 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5567 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5575 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5576 * .event.ActionEvent)
5579 protected void showGroupConservation_actionPerformed(ActionEvent e)
5581 viewport.setShowGroupConservation(showGroupConservation.getState());
5582 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5589 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5590 * .event.ActionEvent)
5593 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5595 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5596 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5603 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5604 * .event.ActionEvent)
5607 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5609 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5610 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5614 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5616 showSequenceLogo.setState(true);
5617 viewport.setShowSequenceLogo(true);
5618 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5619 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5623 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5625 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5632 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5633 * .event.ActionEvent)
5636 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5638 if (avc.makeGroupsFromSelection())
5640 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5641 alignPanel.updateAnnotation();
5642 alignPanel.paintAlignment(true,
5643 viewport.needToUpdateStructureViews());
5647 public void clearAlignmentSeqRep()
5649 // TODO refactor alignmentseqrep to controller
5650 if (viewport.getAlignment().hasSeqrep())
5652 viewport.getAlignment().setSeqrep(null);
5653 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5654 alignPanel.updateAnnotation();
5655 alignPanel.paintAlignment(true, true);
5660 protected void createGroup_actionPerformed(ActionEvent e)
5662 if (avc.createGroup())
5664 if (applyAutoAnnotationSettings.isSelected())
5666 alignPanel.updateAnnotation(true, false);
5668 alignPanel.alignmentChanged();
5673 protected void unGroup_actionPerformed(ActionEvent e)
5677 alignPanel.alignmentChanged();
5682 * make the given alignmentPanel the currently selected tab
5684 * @param alignmentPanel
5686 public void setDisplayedView(AlignmentPanel alignmentPanel)
5688 if (!viewport.getSequenceSetId()
5689 .equals(alignmentPanel.av.getSequenceSetId()))
5691 throw new Error(MessageManager.getString(
5692 "error.implementation_error_cannot_show_view_alignment_frame"));
5694 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5695 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5697 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5702 * Action on selection of menu options to Show or Hide annotations.
5705 * @param forSequences
5706 * update sequence-related annotations
5707 * @param forAlignment
5708 * update non-sequence-related annotations
5711 public void setAnnotationsVisibility(boolean visible,
5712 boolean forSequences, boolean forAlignment)
5714 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5715 .getAlignmentAnnotation();
5720 for (AlignmentAnnotation aa : anns)
5723 * don't display non-positional annotations on an alignment
5725 if (aa.annotations == null)
5729 boolean apply = (aa.sequenceRef == null && forAlignment)
5730 || (aa.sequenceRef != null && forSequences);
5733 aa.visible = visible;
5736 alignPanel.validateAnnotationDimensions(true);
5737 alignPanel.alignmentChanged();
5741 * Store selected annotation sort order for the view and repaint.
5744 protected void sortAnnotations_actionPerformed()
5746 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5748 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5749 alignPanel.paintAlignment(false, false);
5754 * @return alignment panels in this alignment frame
5756 public List<? extends AlignmentViewPanel> getAlignPanels()
5758 // alignPanels is never null
5759 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5764 * Open a new alignment window, with the cDNA associated with this (protein)
5765 * alignment, aligned as is the protein.
5767 protected void viewAsCdna_actionPerformed()
5769 // TODO no longer a menu action - refactor as required
5770 final AlignmentI alignment = getViewport().getAlignment();
5771 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5772 if (mappings == null)
5776 List<SequenceI> cdnaSeqs = new ArrayList<>();
5777 for (SequenceI aaSeq : alignment.getSequences())
5779 for (AlignedCodonFrame acf : mappings)
5781 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5785 * There is a cDNA mapping for this protein sequence - add to new
5786 * alignment. It will share the same dataset sequence as other mapped
5787 * cDNA (no new mappings need to be created).
5789 final Sequence newSeq = new Sequence(dnaSeq);
5790 newSeq.setDatasetSequence(dnaSeq);
5791 cdnaSeqs.add(newSeq);
5795 if (cdnaSeqs.size() == 0)
5797 // show a warning dialog no mapped cDNA
5800 AlignmentI cdna = new Alignment(
5801 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5802 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5803 AlignFrame.DEFAULT_HEIGHT);
5804 cdna.alignAs(alignment);
5805 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5807 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5808 AlignFrame.DEFAULT_HEIGHT);
5812 * Set visibility of dna/protein complement view (available when shown in a
5818 protected void showComplement_actionPerformed(boolean show)
5820 SplitContainerI sf = getSplitViewContainer();
5823 sf.setComplementVisible(this, show);
5828 * Generate the reverse (optionally complemented) of the selected sequences,
5829 * and add them to the alignment
5832 protected void showReverse_actionPerformed(boolean complement)
5834 AlignmentI al = null;
5837 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5838 al = dna.reverseCdna(complement);
5839 viewport.addAlignment(al, "");
5840 addHistoryItem(new EditCommand(
5841 MessageManager.getString("label.add_sequences"), Action.PASTE,
5842 al.getSequencesArray(), 0, al.getWidth(),
5843 viewport.getAlignment()));
5844 } catch (Exception ex)
5846 System.err.println(ex.getMessage());
5852 * Try to run a script in the Groovy console, having first ensured that this
5853 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5854 * be targeted at this alignment.
5857 protected void runGroovy_actionPerformed()
5859 Jalview.setCurrentAlignFrame(this);
5860 groovy.ui.Console console = Desktop.getGroovyConsole();
5861 if (console != null)
5865 console.runScript();
5866 } catch (Exception ex)
5868 System.err.println((ex.toString()));
5869 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5870 MessageManager.getString("label.couldnt_run_groovy_script"),
5871 MessageManager.getString("label.groovy_support_failed"),
5872 JvOptionPane.ERROR_MESSAGE);
5877 System.err.println("Can't run Groovy script as console not found");
5882 * Hides columns containing (or not containing) a specified feature, provided
5883 * that would not leave all columns hidden
5885 * @param featureType
5886 * @param columnsContaining
5889 public boolean hideFeatureColumns(String featureType,
5890 boolean columnsContaining)
5892 boolean notForHiding = avc.markColumnsContainingFeatures(
5893 columnsContaining, false, false, featureType);
5896 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5897 false, featureType))
5899 getViewport().hideSelectedColumns();
5907 protected void selectHighlightedColumns_actionPerformed(
5908 ActionEvent actionEvent)
5910 // include key modifier check in case user selects from menu
5911 avc.markHighlightedColumns(
5912 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5913 (actionEvent.getModifiers() & (ActionEvent.META_MASK
5914 | ActionEvent.CTRL_MASK)) != 0);
5918 protected void copyHighlightedColumns_actionPerformed(
5919 ActionEvent actionEvent)
5921 avc.copyHighlightedRegionsToClipboard();
5925 * Rebuilds the Colour menu, including any user-defined colours which have
5926 * been loaded either on startup or during the session
5928 public void buildColourMenu()
5930 colourMenu.removeAll();
5932 colourMenu.add(applyToAllGroups);
5933 colourMenu.add(textColour);
5934 colourMenu.addSeparator();
5936 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
5937 viewport.getAlignment(), false);
5939 colourMenu.add(annotationColour);
5940 bg.add(annotationColour);
5941 colourMenu.addSeparator();
5942 colourMenu.add(conservationMenuItem);
5943 colourMenu.add(modifyConservation);
5944 colourMenu.add(abovePIDThreshold);
5945 colourMenu.add(modifyPID);
5947 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
5948 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
5952 * Open a dialog (if not already open) that allows the user to select and
5953 * calculate PCA or Tree analysis
5955 protected void openTreePcaDialog()
5957 if (alignPanel.getCalculationDialog() == null)
5959 new CalculationChooser(AlignFrame.this);
5964 protected void loadVcf_actionPerformed()
5966 JalviewFileChooser chooser = new JalviewFileChooser(
5967 Cache.getProperty("LAST_DIRECTORY"));
5968 chooser.setFileView(new JalviewFileView());
5969 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
5970 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
5971 final AlignFrame us = this;
5972 chooser.setResponseHandler(0, () -> {
5973 String choice = chooser.getSelectedFile().getPath();
5974 Cache.setProperty("LAST_DIRECTORY", choice);
5975 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
5976 new VCFLoader(choice).loadVCF(seqs, us);
5978 chooser.showOpenDialog(null);
5982 private Rectangle lastFeatureSettingsBounds = null;
5985 public void setFeatureSettingsGeometry(Rectangle bounds)
5987 lastFeatureSettingsBounds = bounds;
5991 public Rectangle getFeatureSettingsGeometry()
5993 return lastFeatureSettingsBounds;
5998 class PrintThread extends Thread
6002 public PrintThread(AlignmentPanel ap)
6007 static PageFormat pf;
6012 PrinterJob printJob = PrinterJob.getPrinterJob();
6016 printJob.setPrintable(ap, pf);
6020 printJob.setPrintable(ap);
6023 if (printJob.printDialog())
6028 } catch (Exception PrintException)
6030 PrintException.printStackTrace();