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;
62 import java.util.concurrent.Callable;
64 import javax.swing.ButtonGroup;
65 import javax.swing.JCheckBoxMenuItem;
66 import javax.swing.JComponent;
67 import javax.swing.JEditorPane;
68 import javax.swing.JInternalFrame;
69 import javax.swing.JLabel;
70 import javax.swing.JLayeredPane;
71 import javax.swing.JMenu;
72 import javax.swing.JMenuItem;
73 import javax.swing.JPanel;
74 import javax.swing.JScrollPane;
75 import javax.swing.SwingUtilities;
77 import ext.vamsas.ServiceHandle;
78 import jalview.analysis.AlignmentSorter;
79 import jalview.analysis.AlignmentUtils;
80 import jalview.analysis.CrossRef;
81 import jalview.analysis.Dna;
82 import jalview.analysis.GeneticCodeI;
83 import jalview.analysis.ParseProperties;
84 import jalview.analysis.SequenceIdMatcher;
85 import jalview.api.AlignExportSettingsI;
86 import jalview.api.AlignViewControllerGuiI;
87 import jalview.api.AlignViewControllerI;
88 import jalview.api.AlignViewportI;
89 import jalview.api.AlignmentViewPanel;
90 import jalview.api.FeatureSettingsControllerI;
91 import jalview.api.FeatureSettingsModelI;
92 import jalview.api.SplitContainerI;
93 import jalview.api.ViewStyleI;
94 import jalview.api.analysis.SimilarityParamsI;
95 import jalview.bin.Cache;
96 import jalview.bin.Console;
97 import jalview.bin.Jalview;
98 import jalview.commands.CommandI;
99 import jalview.commands.EditCommand;
100 import jalview.commands.EditCommand.Action;
101 import jalview.commands.OrderCommand;
102 import jalview.commands.RemoveGapColCommand;
103 import jalview.commands.RemoveGapsCommand;
104 import jalview.commands.SlideSequencesCommand;
105 import jalview.commands.TrimRegionCommand;
106 import jalview.datamodel.AlignExportSettingsAdapter;
107 import jalview.datamodel.AlignedCodonFrame;
108 import jalview.datamodel.Alignment;
109 import jalview.datamodel.AlignmentAnnotation;
110 import jalview.datamodel.AlignmentExportData;
111 import jalview.datamodel.AlignmentI;
112 import jalview.datamodel.AlignmentOrder;
113 import jalview.datamodel.AlignmentView;
114 import jalview.datamodel.ColumnSelection;
115 import jalview.datamodel.HiddenColumns;
116 import jalview.datamodel.PDBEntry;
117 import jalview.datamodel.SeqCigar;
118 import jalview.datamodel.Sequence;
119 import jalview.datamodel.SequenceGroup;
120 import jalview.datamodel.SequenceI;
121 import jalview.gui.ColourMenuHelper.ColourChangeListener;
122 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
123 import jalview.io.AlignmentProperties;
124 import jalview.io.AnnotationFile;
125 import jalview.io.BackupFiles;
126 import jalview.io.BioJsHTMLOutput;
127 import jalview.io.DataSourceType;
128 import jalview.io.FileFormat;
129 import jalview.io.FileFormatI;
130 import jalview.io.FileFormats;
131 import jalview.io.FileLoader;
132 import jalview.io.FileParse;
133 import jalview.io.FormatAdapter;
134 import jalview.io.HtmlSvgOutput;
135 import jalview.io.IdentifyFile;
136 import jalview.io.JPredFile;
137 import jalview.io.JalviewFileChooser;
138 import jalview.io.JalviewFileView;
139 import jalview.io.JnetAnnotationMaker;
140 import jalview.io.NewickFile;
141 import jalview.io.ScoreMatrixFile;
142 import jalview.io.TCoffeeScoreFile;
143 import jalview.io.vcf.VCFLoader;
144 import jalview.jbgui.GAlignFrame;
145 import jalview.project.Jalview2XML;
146 import jalview.schemes.ColourSchemeI;
147 import jalview.schemes.ColourSchemes;
148 import jalview.schemes.ResidueColourScheme;
149 import jalview.schemes.TCoffeeColourScheme;
150 import jalview.util.HttpUtils;
151 import jalview.util.ImageMaker.TYPE;
152 import jalview.util.MessageManager;
153 import jalview.util.Platform;
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())
985 progressBar.setProgressBar(message, id);
989 public void registerHandler(final long id,
990 final IProgressIndicatorHandler handler)
992 progressBar.registerHandler(id, handler);
997 * @return true if any progress bars are still active
1000 public boolean operationInProgress()
1002 return progressBar.operationInProgress();
1006 * Sets the text of the status bar. Note that setting a null or empty value
1007 * will cause the status bar to be hidden, with possibly undesirable flicker
1008 * of the screen layout.
1011 public void setStatus(String text)
1013 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1017 * Added so Castor Mapping file can obtain Jalview Version
1019 public String getVersion()
1021 return Cache.getProperty("VERSION");
1024 public FeatureRenderer getFeatureRenderer()
1026 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1030 public void fetchSequence_actionPerformed()
1032 new SequenceFetcher(this);
1036 public void addFromFile_actionPerformed(ActionEvent e)
1038 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1042 public void reload_actionPerformed(ActionEvent e)
1044 if (fileName != null)
1046 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1047 // originating file's format
1048 // TODO: work out how to recover feature settings for correct view(s) when
1049 // file is reloaded.
1050 if (FileFormat.Jalview.equals(currentFileFormat))
1052 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1053 for (int i = 0; i < frames.length; i++)
1055 if (frames[i] instanceof AlignFrame && frames[i] != this
1056 && ((AlignFrame) frames[i]).fileName != null
1057 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1061 frames[i].setSelected(true);
1062 Desktop.instance.closeAssociatedWindows();
1063 } catch (java.beans.PropertyVetoException ex)
1069 Desktop.instance.closeAssociatedWindows();
1071 FileLoader loader = new FileLoader();
1072 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1073 ? DataSourceType.URL
1074 : DataSourceType.FILE;
1075 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1079 Rectangle bounds = this.getBounds();
1081 FileLoader loader = new FileLoader();
1083 AlignFrame newframe = null;
1085 if (fileObject == null)
1088 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1089 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1090 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1095 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1096 DataSourceType.FILE, currentFileFormat);
1099 newframe.setBounds(bounds);
1100 if (featureSettings != null && featureSettings.isShowing())
1102 final Rectangle fspos = featureSettings.frame.getBounds();
1103 // TODO: need a 'show feature settings' function that takes bounds -
1104 // need to refactor Desktop.addFrame
1105 newframe.featureSettings_actionPerformed(null);
1106 final FeatureSettings nfs = newframe.featureSettings;
1107 SwingUtilities.invokeLater(new Runnable()
1112 nfs.frame.setBounds(fspos);
1115 this.featureSettings.close();
1116 this.featureSettings = null;
1118 this.closeMenuItem_actionPerformed(true);
1124 public void addFromText_actionPerformed(ActionEvent e)
1127 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1131 public void addFromURL_actionPerformed(ActionEvent e)
1133 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1137 public void save_actionPerformed(ActionEvent e)
1139 if (fileName == null || (currentFileFormat == null)
1140 || HttpUtils.startsWithHttpOrHttps(fileName))
1142 saveAs_actionPerformed();
1146 saveAlignment(fileName, currentFileFormat);
1151 * Saves the alignment to a file with a name chosen by the user, if necessary
1152 * warning if a file would be overwritten
1155 public void saveAs_actionPerformed()
1157 String format = currentFileFormat == null ? null
1158 : currentFileFormat.getName();
1159 JalviewFileChooser chooser = JalviewFileChooser
1160 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1162 chooser.setFileView(new JalviewFileView());
1163 chooser.setDialogTitle(
1164 MessageManager.getString("label.save_alignment_to_file"));
1165 chooser.setToolTipText(MessageManager.getString("action.save"));
1167 int value = chooser.showSaveDialog(this);
1169 if (value != JalviewFileChooser.APPROVE_OPTION)
1173 currentFileFormat = chooser.getSelectedFormat();
1174 // todo is this (2005) test now obsolete - value is never null?
1175 while (currentFileFormat == null)
1177 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1179 .getString("label.select_file_format_before_saving"),
1180 MessageManager.getString("label.file_format_not_specified"),
1181 JvOptionPane.WARNING_MESSAGE);
1182 currentFileFormat = chooser.getSelectedFormat();
1183 value = chooser.showSaveDialog(this);
1184 if (value != JalviewFileChooser.APPROVE_OPTION)
1190 fileName = chooser.getSelectedFile().getPath();
1192 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1193 Cache.setProperty("LAST_DIRECTORY", fileName);
1194 saveAlignment(fileName, currentFileFormat);
1197 boolean lastSaveSuccessful = false;
1199 FileFormatI lastFormatSaved;
1201 String lastFilenameSaved;
1204 * Raise a dialog or status message for the last call to saveAlignment.
1206 * @return true if last call to saveAlignment(file, format) was successful.
1208 public boolean isSaveAlignmentSuccessful()
1211 if (!lastSaveSuccessful)
1213 if (!Platform.isHeadless())
1215 JvOptionPane.showInternalMessageDialog(this, MessageManager
1216 .formatMessage("label.couldnt_save_file", new Object[]
1217 { lastFilenameSaved }),
1218 MessageManager.getString("label.error_saving_file"),
1219 JvOptionPane.WARNING_MESSAGE);
1223 Console.error(MessageManager
1224 .formatMessage("label.couldnt_save_file", new Object[]
1225 { lastFilenameSaved }));
1231 setStatus(MessageManager.formatMessage(
1232 "label.successfully_saved_to_file_in_format", new Object[]
1233 { lastFilenameSaved, lastFormatSaved }));
1236 return lastSaveSuccessful;
1240 * Saves the alignment to the specified file path, in the specified format,
1241 * which may be an alignment format, or Jalview project format. If the
1242 * alignment has hidden regions, or the format is one capable of including
1243 * non-sequence data (features, annotations, groups), then the user may be
1244 * prompted to specify what to include in the output.
1249 public void saveAlignment(String file, FileFormatI format)
1251 lastSaveSuccessful = true;
1252 lastFilenameSaved = file;
1253 lastFormatSaved = format;
1255 if (FileFormat.Jalview.equals(format))
1257 String shortName = title;
1258 if (shortName.indexOf(File.separatorChar) > -1)
1260 shortName = shortName
1261 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1263 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1266 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1267 if (lastSaveSuccessful)
1269 this.getViewport().setSavedUpToDate(true);
1272 statusBar.setText(MessageManager.formatMessage(
1273 "label.successfully_saved_to_file_in_format", new Object[]
1279 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1280 Callable<Void> cancelAction = () -> {
1281 lastSaveSuccessful = false;
1284 Callable<Void> 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);
1366 * show dialog with export options if applicable; else just do it
1368 if (AlignExportOptions.isNeeded(viewport, format))
1370 AlignExportOptions choices = new AlignExportOptions(
1371 alignPanel.getAlignViewport(), format, options);
1372 choices.setResponseAction(0, outputAction);
1373 choices.setResponseAction(1, cancelAction);
1374 choices.showDialog();
1380 outputAction.call();
1381 } catch (Exception e)
1383 // TODO Auto-generated catch block
1384 e.printStackTrace();
1390 * Outputs the alignment to textbox in the requested format, if necessary
1391 * first prompting the user for whether to include hidden regions or
1394 * @param fileFormatName
1397 protected void outputText_actionPerformed(String fileFormatName)
1399 FileFormatI fileFormat = FileFormats.getInstance()
1400 .forName(fileFormatName);
1401 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1402 Callable<Void> outputAction = () -> {
1403 // todo defer this to inside formatSequences (or later)
1404 AlignmentExportData exportData = viewport.getAlignExportData(options);
1405 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1406 cap.setForInput(null);
1409 FileFormatI format = fileFormat;
1410 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1411 format, exportData.getAlignment(),
1412 exportData.getOmitHidden(),
1413 exportData.getStartEndPostions(),
1414 viewport.getAlignment().getHiddenColumns()));
1415 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1416 "label.alignment_output_command", new Object[]
1417 { fileFormat.getName() }), 600, 500);
1418 } catch (OutOfMemoryError oom)
1420 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1428 * show dialog with export options if applicable; else just do it
1430 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1432 AlignExportOptions choices = new AlignExportOptions(
1433 alignPanel.getAlignViewport(), fileFormat, options);
1434 choices.setResponseAction(0, outputAction);
1435 choices.showDialog();
1441 outputAction.call();
1442 } catch (Exception e)
1444 e.printStackTrace();
1456 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1458 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1459 htmlSVG.exportHTML(null);
1463 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1465 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1466 bjs.exportHTML(null);
1469 public void createImageMap(File file, String image)
1471 alignPanel.makePNGImageMap(file, image);
1475 * Creates a PNG image of the alignment and writes it to the given file. If
1476 * the file is null, the user is prompted to choose a file.
1481 public void createPNG(File f)
1483 alignPanel.makeAlignmentImage(TYPE.PNG, f);
1487 * Creates an EPS image of the alignment and writes it to the given file. If
1488 * the file is null, the user is prompted to choose a file.
1493 public void createEPS(File f)
1495 alignPanel.makeAlignmentImage(TYPE.EPS, f);
1499 * Creates an SVG image of the alignment and writes it to the given file. If
1500 * the file is null, the user is prompted to choose a file.
1505 public void createSVG(File f)
1507 alignPanel.makeAlignmentImage(TYPE.SVG, f);
1511 public void pageSetup_actionPerformed(ActionEvent e)
1513 PrinterJob printJob = PrinterJob.getPrinterJob();
1514 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1524 public void printMenuItem_actionPerformed(ActionEvent e)
1526 // Putting in a thread avoids Swing painting problems
1527 PrintThread thread = new PrintThread(alignPanel);
1532 public void exportFeatures_actionPerformed(ActionEvent e)
1534 new AnnotationExporter(alignPanel).exportFeatures();
1538 public void exportAnnotations_actionPerformed(ActionEvent e)
1540 new AnnotationExporter(alignPanel).exportAnnotations();
1544 public void associatedData_actionPerformed(ActionEvent e)
1546 final JalviewFileChooser chooser = new JalviewFileChooser(
1547 Cache.getProperty("LAST_DIRECTORY"));
1548 chooser.setFileView(new JalviewFileView());
1549 String tooltip = MessageManager
1550 .getString("label.load_jalview_annotations");
1551 chooser.setDialogTitle(tooltip);
1552 chooser.setToolTipText(tooltip);
1553 chooser.setResponseHandler(0, () -> {
1554 String choice = chooser.getSelectedFile().getPath();
1555 Cache.setProperty("LAST_DIRECTORY", choice);
1556 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1560 chooser.showOpenDialog(this);
1564 * Close the current view or all views in the alignment frame. If the frame
1565 * only contains one view then the alignment will be removed from memory.
1567 * @param closeAllTabs
1570 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1572 if (alignPanels != null && alignPanels.size() < 2)
1574 closeAllTabs = true;
1579 if (alignPanels != null)
1583 if (this.isClosed())
1585 // really close all the windows - otherwise wait till
1586 // setClosed(true) is called
1587 for (int i = 0; i < alignPanels.size(); i++)
1589 AlignmentPanel ap = alignPanels.get(i);
1596 closeView(alignPanel);
1601 if (featureSettings != null && featureSettings.isOpen())
1603 featureSettings.close();
1604 featureSettings = null;
1607 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1608 * be called recursively, with the frame now in 'closed' state
1610 this.setClosed(true);
1612 } catch (Exception ex)
1614 ex.printStackTrace();
1619 * Close the specified panel and close up tabs appropriately.
1621 * @param panelToClose
1623 public void closeView(AlignmentPanel panelToClose)
1625 int index = tabbedPane.getSelectedIndex();
1626 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1627 alignPanels.remove(panelToClose);
1628 panelToClose.closePanel();
1629 panelToClose = null;
1631 tabbedPane.removeTabAt(closedindex);
1632 tabbedPane.validate();
1634 if (index > closedindex || index == tabbedPane.getTabCount())
1636 // modify currently selected tab index if necessary.
1640 this.tabSelectionChanged(index);
1646 void updateEditMenuBar()
1649 if (viewport.getHistoryList().size() > 0)
1651 undoMenuItem.setEnabled(true);
1652 CommandI command = viewport.getHistoryList().peek();
1653 undoMenuItem.setText(MessageManager
1654 .formatMessage("label.undo_command", new Object[]
1655 { command.getDescription() }));
1659 undoMenuItem.setEnabled(false);
1660 undoMenuItem.setText(MessageManager.getString("action.undo"));
1663 if (viewport.getRedoList().size() > 0)
1665 redoMenuItem.setEnabled(true);
1667 CommandI command = viewport.getRedoList().peek();
1668 redoMenuItem.setText(MessageManager
1669 .formatMessage("label.redo_command", new Object[]
1670 { command.getDescription() }));
1674 redoMenuItem.setEnabled(false);
1675 redoMenuItem.setText(MessageManager.getString("action.redo"));
1680 public void addHistoryItem(CommandI command)
1682 if (command.getSize() > 0)
1684 viewport.addToHistoryList(command);
1685 viewport.clearRedoList();
1686 updateEditMenuBar();
1687 viewport.updateHiddenColumns();
1688 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1689 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1690 // viewport.getColumnSelection()
1691 // .getHiddenColumns().size() > 0);
1697 * @return alignment objects for all views
1699 AlignmentI[] getViewAlignments()
1701 if (alignPanels != null)
1703 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1705 for (AlignmentPanel ap : alignPanels)
1707 als[i++] = ap.av.getAlignment();
1711 if (viewport != null)
1713 return new AlignmentI[] { viewport.getAlignment() };
1725 protected void undoMenuItem_actionPerformed(ActionEvent e)
1727 if (viewport.getHistoryList().isEmpty())
1731 CommandI command = viewport.getHistoryList().pop();
1732 viewport.addToRedoList(command);
1733 command.undoCommand(getViewAlignments());
1735 AlignmentViewport originalSource = getOriginatingSource(command);
1736 updateEditMenuBar();
1738 if (originalSource != null)
1740 if (originalSource != viewport)
1743 "Implementation worry: mismatch of viewport origin for undo");
1745 originalSource.updateHiddenColumns();
1746 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1748 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1749 // viewport.getColumnSelection()
1750 // .getHiddenColumns().size() > 0);
1751 originalSource.firePropertyChange("alignment", null,
1752 originalSource.getAlignment().getSequences());
1763 protected void redoMenuItem_actionPerformed(ActionEvent e)
1765 if (viewport.getRedoList().size() < 1)
1770 CommandI command = viewport.getRedoList().pop();
1771 viewport.addToHistoryList(command);
1772 command.doCommand(getViewAlignments());
1774 AlignmentViewport originalSource = getOriginatingSource(command);
1775 updateEditMenuBar();
1777 if (originalSource != null)
1780 if (originalSource != viewport)
1783 "Implementation worry: mismatch of viewport origin for redo");
1785 originalSource.updateHiddenColumns();
1786 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1788 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1789 // viewport.getColumnSelection()
1790 // .getHiddenColumns().size() > 0);
1791 originalSource.firePropertyChange("alignment", null,
1792 originalSource.getAlignment().getSequences());
1796 AlignmentViewport getOriginatingSource(CommandI command)
1798 AlignmentViewport originalSource = null;
1799 // For sequence removal and addition, we need to fire
1800 // the property change event FROM the viewport where the
1801 // original alignment was altered
1802 AlignmentI al = null;
1803 if (command instanceof EditCommand)
1805 EditCommand editCommand = (EditCommand) command;
1806 al = editCommand.getAlignment();
1807 List<Component> comps = PaintRefresher.components
1808 .get(viewport.getSequenceSetId());
1810 for (Component comp : comps)
1812 if (comp instanceof AlignmentPanel)
1814 if (al == ((AlignmentPanel) comp).av.getAlignment())
1816 originalSource = ((AlignmentPanel) comp).av;
1823 if (originalSource == null)
1825 // The original view is closed, we must validate
1826 // the current view against the closed view first
1829 PaintRefresher.validateSequences(al, viewport.getAlignment());
1832 originalSource = viewport;
1835 return originalSource;
1839 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1840 * or the sequence under cursor in keyboard mode
1845 public void moveSelectedSequences(boolean up)
1847 SequenceGroup sg = viewport.getSelectionGroup();
1851 if (viewport.cursorMode)
1853 sg = new SequenceGroup();
1854 sg.addSequence(viewport.getAlignment().getSequenceAt(
1855 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1863 if (sg.getSize() < 1)
1868 // TODO: JAL-3733 - add an event to the undo buffer for this !
1870 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1871 viewport.getHiddenRepSequences(), up);
1872 alignPanel.paintAlignment(true, false);
1875 synchronized void slideSequences(boolean right, int size)
1877 List<SequenceI> sg = new ArrayList<>();
1878 if (viewport.cursorMode)
1880 sg.add(viewport.getAlignment()
1881 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1883 else if (viewport.getSelectionGroup() != null
1884 && viewport.getSelectionGroup().getSize() != viewport
1885 .getAlignment().getHeight())
1887 sg = viewport.getSelectionGroup()
1888 .getSequences(viewport.getHiddenRepSequences());
1896 List<SequenceI> invertGroup = new ArrayList<>();
1898 for (SequenceI seq : viewport.getAlignment().getSequences())
1900 if (!sg.contains(seq))
1902 invertGroup.add(seq);
1906 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1908 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1909 for (int i = 0; i < invertGroup.size(); i++)
1911 seqs2[i] = invertGroup.get(i);
1914 SlideSequencesCommand ssc;
1917 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1918 viewport.getGapCharacter());
1922 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1923 viewport.getGapCharacter());
1926 int groupAdjustment = 0;
1927 if (ssc.getGapsInsertedBegin() && right)
1929 if (viewport.cursorMode)
1931 alignPanel.getSeqPanel().moveCursor(size, 0);
1935 groupAdjustment = size;
1938 else if (!ssc.getGapsInsertedBegin() && !right)
1940 if (viewport.cursorMode)
1942 alignPanel.getSeqPanel().moveCursor(-size, 0);
1946 groupAdjustment = -size;
1950 if (groupAdjustment != 0)
1952 viewport.getSelectionGroup().setStartRes(
1953 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1954 viewport.getSelectionGroup().setEndRes(
1955 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1959 * just extend the last slide command if compatible; but not if in
1960 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
1962 boolean appendHistoryItem = false;
1963 Deque<CommandI> historyList = viewport.getHistoryList();
1964 boolean inSplitFrame = getSplitViewContainer() != null;
1965 if (!inSplitFrame && historyList != null && historyList.size() > 0
1966 && historyList.peek() instanceof SlideSequencesCommand)
1968 appendHistoryItem = ssc.appendSlideCommand(
1969 (SlideSequencesCommand) historyList.peek());
1972 if (!appendHistoryItem)
1974 addHistoryItem(ssc);
1987 protected void copy_actionPerformed()
1989 if (viewport.getSelectionGroup() == null)
1993 // TODO: preserve the ordering of displayed alignment annotation in any
1994 // internal paste (particularly sequence associated annotation)
1995 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
1996 String[] omitHidden = null;
1998 if (viewport.hasHiddenColumns())
2000 omitHidden = viewport.getViewAsString(true);
2003 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2004 seqs, omitHidden, null);
2006 StringSelection ss = new StringSelection(output);
2010 jalview.gui.Desktop.internalCopy = true;
2011 // Its really worth setting the clipboard contents
2012 // to empty before setting the large StringSelection!!
2013 Toolkit.getDefaultToolkit().getSystemClipboard()
2014 .setContents(new StringSelection(""), null);
2016 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2018 } catch (OutOfMemoryError er)
2020 new OOMWarning("copying region", er);
2024 HiddenColumns hiddenColumns = null;
2025 if (viewport.hasHiddenColumns())
2027 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2028 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2030 // create new HiddenColumns object with copy of hidden regions
2031 // between startRes and endRes, offset by startRes
2032 hiddenColumns = new HiddenColumns(
2033 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2034 hiddenCutoff, hiddenOffset);
2037 Desktop.jalviewClipboard = new Object[] { seqs,
2038 viewport.getAlignment().getDataset(), hiddenColumns };
2039 setStatus(MessageManager.formatMessage(
2040 "label.copied_sequences_to_clipboard", new Object[]
2041 { Integer.valueOf(seqs.length).toString() }));
2051 protected void pasteNew_actionPerformed(ActionEvent e)
2063 protected void pasteThis_actionPerformed(ActionEvent e)
2069 * Paste contents of Jalview clipboard
2071 * @param newAlignment
2072 * true to paste to a new alignment, otherwise add to this.
2074 void paste(boolean newAlignment)
2076 boolean externalPaste = true;
2079 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2080 Transferable contents = c.getContents(this);
2082 if (contents == null)
2091 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2092 if (str.length() < 1)
2097 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2099 } catch (OutOfMemoryError er)
2101 new OOMWarning("Out of memory pasting sequences!!", er);
2105 SequenceI[] sequences;
2106 boolean annotationAdded = false;
2107 AlignmentI alignment = null;
2109 if (Desktop.jalviewClipboard != null)
2111 // The clipboard was filled from within Jalview, we must use the
2113 // And dataset from the copied alignment
2114 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2115 // be doubly sure that we create *new* sequence objects.
2116 sequences = new SequenceI[newseq.length];
2117 for (int i = 0; i < newseq.length; i++)
2119 sequences[i] = new Sequence(newseq[i]);
2121 alignment = new Alignment(sequences);
2122 externalPaste = false;
2126 // parse the clipboard as an alignment.
2127 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2129 sequences = alignment.getSequencesArray();
2133 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2139 if (Desktop.jalviewClipboard != null)
2141 // dataset is inherited
2142 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2146 // new dataset is constructed
2147 alignment.setDataset(null);
2149 alwidth = alignment.getWidth() + 1;
2153 AlignmentI pastedal = alignment; // preserve pasted alignment object
2154 // Add pasted sequences and dataset into existing alignment.
2155 alignment = viewport.getAlignment();
2156 alwidth = alignment.getWidth() + 1;
2157 // decide if we need to import sequences from an existing dataset
2158 boolean importDs = Desktop.jalviewClipboard != null
2159 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2160 // importDs==true instructs us to copy over new dataset sequences from
2161 // an existing alignment
2162 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2164 // minimum dataset set
2166 for (int i = 0; i < sequences.length; i++)
2170 newDs.addElement(null);
2172 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2174 if (importDs && ds != null)
2176 if (!newDs.contains(ds))
2178 newDs.setElementAt(ds, i);
2179 ds = new Sequence(ds);
2180 // update with new dataset sequence
2181 sequences[i].setDatasetSequence(ds);
2185 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2190 // copy and derive new dataset sequence
2191 sequences[i] = sequences[i].deriveSequence();
2192 alignment.getDataset()
2193 .addSequence(sequences[i].getDatasetSequence());
2194 // TODO: avoid creation of duplicate dataset sequences with a
2195 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2197 alignment.addSequence(sequences[i]); // merges dataset
2201 newDs.clear(); // tidy up
2203 if (alignment.getAlignmentAnnotation() != null)
2205 for (AlignmentAnnotation alan : alignment
2206 .getAlignmentAnnotation())
2208 if (alan.graphGroup > fgroup)
2210 fgroup = alan.graphGroup;
2214 if (pastedal.getAlignmentAnnotation() != null)
2216 // Add any annotation attached to alignment.
2217 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2218 for (int i = 0; i < alann.length; i++)
2220 annotationAdded = true;
2221 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2223 AlignmentAnnotation newann = new AlignmentAnnotation(
2225 if (newann.graphGroup > -1)
2227 if (newGraphGroups.size() <= newann.graphGroup
2228 || newGraphGroups.get(newann.graphGroup) == null)
2230 for (int q = newGraphGroups
2231 .size(); q <= newann.graphGroup; q++)
2233 newGraphGroups.add(q, null);
2235 newGraphGroups.set(newann.graphGroup,
2236 Integer.valueOf(++fgroup));
2238 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2242 newann.padAnnotation(alwidth);
2243 alignment.addAnnotation(newann);
2253 addHistoryItem(new EditCommand(
2254 MessageManager.getString("label.add_sequences"),
2255 Action.PASTE, sequences, 0, alignment.getWidth(),
2258 // Add any annotations attached to sequences
2259 for (int i = 0; i < sequences.length; i++)
2261 if (sequences[i].getAnnotation() != null)
2263 AlignmentAnnotation newann;
2264 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2266 annotationAdded = true;
2267 newann = sequences[i].getAnnotation()[a];
2268 newann.adjustForAlignment();
2269 newann.padAnnotation(alwidth);
2270 if (newann.graphGroup > -1)
2272 if (newann.graphGroup > -1)
2274 if (newGraphGroups.size() <= newann.graphGroup
2275 || newGraphGroups.get(newann.graphGroup) == null)
2277 for (int q = newGraphGroups
2278 .size(); q <= newann.graphGroup; q++)
2280 newGraphGroups.add(q, null);
2282 newGraphGroups.set(newann.graphGroup,
2283 Integer.valueOf(++fgroup));
2285 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2289 alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation
2293 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2301 // propagate alignment changed.
2302 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2303 if (annotationAdded)
2305 // Duplicate sequence annotation in all views.
2306 AlignmentI[] alview = this.getViewAlignments();
2307 for (int i = 0; i < sequences.length; i++)
2309 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2314 for (int avnum = 0; avnum < alview.length; avnum++)
2316 if (alview[avnum] != alignment)
2318 // duplicate in a view other than the one with input focus
2319 int avwidth = alview[avnum].getWidth() + 1;
2320 // this relies on sann being preserved after we
2321 // modify the sequence's annotation array for each duplication
2322 for (int a = 0; a < sann.length; a++)
2324 AlignmentAnnotation newann = new AlignmentAnnotation(
2326 sequences[i].addAlignmentAnnotation(newann);
2327 newann.padAnnotation(avwidth);
2328 alview[avnum].addAnnotation(newann); // annotation was
2329 // duplicated earlier
2330 // TODO JAL-1145 graphGroups are not updated for sequence
2331 // annotation added to several views. This may cause
2333 alview[avnum].setAnnotationIndex(newann, a);
2338 buildSortByAnnotationScoresMenu();
2340 viewport.firePropertyChange("alignment", null,
2341 alignment.getSequences());
2342 if (alignPanels != null)
2344 for (AlignmentPanel ap : alignPanels)
2346 ap.validateAnnotationDimensions(false);
2351 alignPanel.validateAnnotationDimensions(false);
2357 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2359 String newtitle = new String("Copied sequences");
2361 if (Desktop.jalviewClipboard != null
2362 && Desktop.jalviewClipboard[2] != null)
2364 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2365 af.viewport.setHiddenColumns(hc);
2368 // >>>This is a fix for the moment, until a better solution is
2370 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2371 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2372 .getFeatureRenderer());
2374 // TODO: maintain provenance of an alignment, rather than just make the
2375 // title a concatenation of operations.
2378 if (title.startsWith("Copied sequences"))
2384 newtitle = newtitle.concat("- from " + title);
2389 newtitle = new String("Pasted sequences");
2392 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2397 } catch (Exception ex)
2399 ex.printStackTrace();
2400 System.out.println("Exception whilst pasting: " + ex);
2401 // could be anything being pasted in here
2407 protected void expand_newalign(ActionEvent e)
2411 AlignmentI alignment = AlignmentUtils
2412 .expandContext(getViewport().getAlignment(), -1);
2413 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2415 String newtitle = new String("Flanking alignment");
2417 if (Desktop.jalviewClipboard != null
2418 && Desktop.jalviewClipboard[2] != null)
2420 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2421 af.viewport.setHiddenColumns(hc);
2424 // >>>This is a fix for the moment, until a better solution is
2426 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2427 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2428 .getFeatureRenderer());
2430 // TODO: maintain provenance of an alignment, rather than just make the
2431 // title a concatenation of operations.
2433 if (title.startsWith("Copied sequences"))
2439 newtitle = newtitle.concat("- from " + title);
2443 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2445 } catch (Exception ex)
2447 ex.printStackTrace();
2448 System.out.println("Exception whilst pasting: " + ex);
2449 // could be anything being pasted in here
2450 } catch (OutOfMemoryError oom)
2452 new OOMWarning("Viewing flanking region of alignment", oom);
2457 * Action Cut (delete and copy) the selected region
2460 protected void cut_actionPerformed()
2462 copy_actionPerformed();
2463 delete_actionPerformed();
2467 * Performs menu option to Delete the currently selected region
2470 protected void delete_actionPerformed()
2473 SequenceGroup sg = viewport.getSelectionGroup();
2479 Callable okAction = () -> {
2480 SequenceI[] cut = sg.getSequences()
2481 .toArray(new SequenceI[sg.getSize()]);
2483 addHistoryItem(new EditCommand(
2484 MessageManager.getString("label.cut_sequences"), Action.CUT,
2485 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2486 viewport.getAlignment()));
2488 viewport.setSelectionGroup(null);
2489 viewport.sendSelection();
2490 viewport.getAlignment().deleteGroup(sg);
2492 viewport.firePropertyChange("alignment", null,
2493 viewport.getAlignment().getSequences());
2494 if (viewport.getAlignment().getHeight() < 1)
2498 AlignFrame.this.setClosed(true);
2499 } catch (Exception ex)
2507 * If the cut affects all sequences, prompt for confirmation
2509 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2511 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2512 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2513 if (wholeHeight && wholeWidth)
2515 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2516 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2517 Object[] options = new Object[] {
2518 MessageManager.getString("action.ok"),
2519 MessageManager.getString("action.cancel") };
2520 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2521 MessageManager.getString("label.delete_all"),
2522 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2523 options, options[0]);
2530 } catch (Exception e)
2532 e.printStackTrace();
2544 protected void deleteGroups_actionPerformed(ActionEvent e)
2546 if (avc.deleteGroups())
2548 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2549 alignPanel.updateAnnotation();
2550 alignPanel.paintAlignment(true, true);
2561 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2563 SequenceGroup sg = new SequenceGroup(
2564 viewport.getAlignment().getSequences());
2566 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2567 viewport.setSelectionGroup(sg);
2568 viewport.isSelectionGroupChanged(true);
2569 viewport.sendSelection();
2570 // JAL-2034 - should delegate to
2571 // alignPanel to decide if overview needs
2573 alignPanel.paintAlignment(false, false);
2574 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2584 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2586 if (viewport.cursorMode)
2588 alignPanel.getSeqPanel().keyboardNo1 = null;
2589 alignPanel.getSeqPanel().keyboardNo2 = null;
2591 viewport.setSelectionGroup(null);
2592 viewport.getColumnSelection().clear();
2593 viewport.setSearchResults(null);
2594 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2595 // JAL-2034 - should delegate to
2596 // alignPanel to decide if overview needs
2598 alignPanel.paintAlignment(false, false);
2599 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2600 viewport.sendSelection();
2610 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2612 SequenceGroup sg = viewport.getSelectionGroup();
2616 selectAllSequenceMenuItem_actionPerformed(null);
2621 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2623 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2625 // JAL-2034 - should delegate to
2626 // alignPanel to decide if overview needs
2629 alignPanel.paintAlignment(true, false);
2630 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2631 viewport.sendSelection();
2635 public void invertColSel_actionPerformed(ActionEvent e)
2637 viewport.invertColumnSelection();
2638 alignPanel.paintAlignment(true, false);
2639 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2640 viewport.sendSelection();
2650 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2652 trimAlignment(true);
2662 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2664 trimAlignment(false);
2667 void trimAlignment(boolean trimLeft)
2669 ColumnSelection colSel = viewport.getColumnSelection();
2672 if (!colSel.isEmpty())
2676 column = colSel.getMin();
2680 column = colSel.getMax();
2684 if (viewport.getSelectionGroup() != null)
2686 seqs = viewport.getSelectionGroup()
2687 .getSequencesAsArray(viewport.getHiddenRepSequences());
2691 seqs = viewport.getAlignment().getSequencesArray();
2694 TrimRegionCommand trimRegion;
2697 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2698 column, viewport.getAlignment());
2699 viewport.getRanges().setStartRes(0);
2703 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2704 column, viewport.getAlignment());
2707 setStatus(MessageManager.formatMessage("label.removed_columns",
2709 { Integer.valueOf(trimRegion.getSize()).toString() }));
2711 addHistoryItem(trimRegion);
2713 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2715 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2716 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2718 viewport.getAlignment().deleteGroup(sg);
2722 viewport.firePropertyChange("alignment", null,
2723 viewport.getAlignment().getSequences());
2734 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2736 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2739 if (viewport.getSelectionGroup() != null)
2741 seqs = viewport.getSelectionGroup()
2742 .getSequencesAsArray(viewport.getHiddenRepSequences());
2743 start = viewport.getSelectionGroup().getStartRes();
2744 end = viewport.getSelectionGroup().getEndRes();
2748 seqs = viewport.getAlignment().getSequencesArray();
2751 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2752 "Remove Gapped Columns", seqs, start, end,
2753 viewport.getAlignment());
2755 addHistoryItem(removeGapCols);
2757 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2759 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2761 // This is to maintain viewport position on first residue
2762 // of first sequence
2763 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2764 ViewportRanges ranges = viewport.getRanges();
2765 int startRes = seq.findPosition(ranges.getStartRes());
2766 // ShiftList shifts;
2767 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2768 // edit.alColumnChanges=shifts.getInverse();
2769 // if (viewport.hasHiddenColumns)
2770 // viewport.getColumnSelection().compensateForEdits(shifts);
2771 ranges.setStartRes(seq.findIndex(startRes) - 1);
2772 viewport.firePropertyChange("alignment", null,
2773 viewport.getAlignment().getSequences());
2784 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2786 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2789 if (viewport.getSelectionGroup() != null)
2791 seqs = viewport.getSelectionGroup()
2792 .getSequencesAsArray(viewport.getHiddenRepSequences());
2793 start = viewport.getSelectionGroup().getStartRes();
2794 end = viewport.getSelectionGroup().getEndRes();
2798 seqs = viewport.getAlignment().getSequencesArray();
2801 // This is to maintain viewport position on first residue
2802 // of first sequence
2803 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2804 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2806 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2807 viewport.getAlignment()));
2809 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2811 viewport.firePropertyChange("alignment", null,
2812 viewport.getAlignment().getSequences());
2823 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2825 viewport.setPadGaps(padGapsMenuitem.isSelected());
2826 viewport.firePropertyChange("alignment", null,
2827 viewport.getAlignment().getSequences());
2831 * Opens a Finder dialog
2836 public void findMenuItem_actionPerformed(ActionEvent e)
2838 new Finder(alignPanel, false, null);
2842 * Create a new view of the current alignment.
2845 public void newView_actionPerformed(ActionEvent e)
2847 newView(null, true);
2851 * Creates and shows a new view of the current alignment.
2854 * title of newly created view; if null, one will be generated
2855 * @param copyAnnotation
2856 * if true then duplicate all annnotation, groups and settings
2857 * @return new alignment panel, already displayed.
2859 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2862 * Create a new AlignmentPanel (with its own, new Viewport)
2864 AlignmentPanel newap = new jalview.project.Jalview2XML()
2865 .copyAlignPanel(alignPanel);
2866 if (!copyAnnotation)
2869 * remove all groups and annotation except for the automatic stuff
2871 newap.av.getAlignment().deleteAllGroups();
2872 newap.av.getAlignment().deleteAllAnnotations(false);
2875 newap.av.setGatherViewsHere(false);
2877 if (viewport.getViewName() == null)
2879 viewport.setViewName(
2880 MessageManager.getString("label.view_name_original"));
2884 * Views share the same edits undo and redo stacks
2886 newap.av.setHistoryList(viewport.getHistoryList());
2887 newap.av.setRedoList(viewport.getRedoList());
2890 * copy any visualisation settings that are not saved in the project
2892 newap.av.setColourAppliesToAllGroups(
2893 viewport.getColourAppliesToAllGroups());
2896 * Views share the same mappings; need to deregister any new mappings
2897 * created by copyAlignPanel, and register the new reference to the shared
2900 newap.av.replaceMappings(viewport.getAlignment());
2903 * start up cDNA consensus (if applicable) now mappings are in place
2905 if (newap.av.initComplementConsensus())
2907 newap.refresh(true); // adjust layout of annotations
2910 newap.av.setViewName(getNewViewName(viewTitle));
2912 addAlignmentPanel(newap, true);
2913 newap.alignmentChanged();
2915 if (alignPanels.size() == 2)
2917 viewport.setGatherViewsHere(true);
2919 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2925 * Make a new name for the view, ensuring it is unique within the current
2926 * sequenceSetId. (This used to be essential for Jalview Project archives, but
2927 * these now use viewId. Unique view names are still desirable for usability.)
2932 protected String getNewViewName(String viewTitle)
2934 int index = Desktop.getViewCount(viewport.getSequenceSetId());
2935 boolean addFirstIndex = false;
2936 if (viewTitle == null || viewTitle.trim().length() == 0)
2938 viewTitle = MessageManager.getString("action.view");
2939 addFirstIndex = true;
2943 index = 1;// we count from 1 if given a specific name
2945 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
2947 List<Component> comps = PaintRefresher.components
2948 .get(viewport.getSequenceSetId());
2950 List<String> existingNames = getExistingViewNames(comps);
2952 while (existingNames.contains(newViewName))
2954 newViewName = viewTitle + " " + (++index);
2960 * Returns a list of distinct view names found in the given list of
2961 * components. View names are held on the viewport of an AlignmentPanel.
2966 protected List<String> getExistingViewNames(List<Component> comps)
2968 List<String> existingNames = new ArrayList<>();
2969 for (Component comp : comps)
2971 if (comp instanceof AlignmentPanel)
2973 AlignmentPanel ap = (AlignmentPanel) comp;
2974 if (!existingNames.contains(ap.av.getViewName()))
2976 existingNames.add(ap.av.getViewName());
2980 return existingNames;
2984 * Explode tabbed views into separate windows.
2987 public void expandViews_actionPerformed(ActionEvent e)
2989 Desktop.explodeViews(this);
2993 * Gather views in separate windows back into a tabbed presentation.
2996 public void gatherViews_actionPerformed(ActionEvent e)
2998 Desktop.instance.gatherViews(this);
3008 public void font_actionPerformed(ActionEvent e)
3010 new FontChooser(alignPanel);
3020 protected void seqLimit_actionPerformed(ActionEvent e)
3022 viewport.setShowJVSuffix(seqLimits.isSelected());
3024 alignPanel.getIdPanel().getIdCanvas()
3025 .setPreferredSize(alignPanel.calculateIdWidth());
3026 alignPanel.paintAlignment(true, false);
3030 public void idRightAlign_actionPerformed(ActionEvent e)
3032 viewport.setRightAlignIds(idRightAlign.isSelected());
3033 alignPanel.paintAlignment(false, false);
3037 public void centreColumnLabels_actionPerformed(ActionEvent e)
3039 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3040 alignPanel.paintAlignment(false, false);
3046 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3049 protected void followHighlight_actionPerformed()
3052 * Set the 'follow' flag on the Viewport (and scroll to position if now
3055 final boolean state = this.followHighlightMenuItem.getState();
3056 viewport.setFollowHighlight(state);
3059 alignPanel.scrollToPosition(viewport.getSearchResults());
3070 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3072 viewport.setColourText(colourTextMenuItem.isSelected());
3073 alignPanel.paintAlignment(false, false);
3083 public void wrapMenuItem_actionPerformed(ActionEvent e)
3085 scaleAbove.setVisible(wrapMenuItem.isSelected());
3086 scaleLeft.setVisible(wrapMenuItem.isSelected());
3087 scaleRight.setVisible(wrapMenuItem.isSelected());
3088 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3089 alignPanel.updateLayout();
3093 public void showAllSeqs_actionPerformed(ActionEvent e)
3095 viewport.showAllHiddenSeqs();
3099 public void showAllColumns_actionPerformed(ActionEvent e)
3101 viewport.showAllHiddenColumns();
3102 alignPanel.paintAlignment(true, true);
3103 viewport.sendSelection();
3107 public void hideSelSequences_actionPerformed(ActionEvent e)
3109 viewport.hideAllSelectedSeqs();
3113 * called by key handler and the hide all/show all menu items
3118 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3121 boolean hide = false;
3122 SequenceGroup sg = viewport.getSelectionGroup();
3123 if (!toggleSeqs && !toggleCols)
3125 // Hide everything by the current selection - this is a hack - we do the
3126 // invert and then hide
3127 // first check that there will be visible columns after the invert.
3128 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3129 && sg.getStartRes() <= sg.getEndRes()))
3131 // now invert the sequence set, if required - empty selection implies
3132 // that no hiding is required.
3135 invertSequenceMenuItem_actionPerformed(null);
3136 sg = viewport.getSelectionGroup();
3140 viewport.expandColSelection(sg, true);
3141 // finally invert the column selection and get the new sequence
3143 invertColSel_actionPerformed(null);
3150 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3152 hideSelSequences_actionPerformed(null);
3155 else if (!(toggleCols && viewport.hasSelectedColumns()))
3157 showAllSeqs_actionPerformed(null);
3163 if (viewport.hasSelectedColumns())
3165 hideSelColumns_actionPerformed(null);
3168 viewport.setSelectionGroup(sg);
3173 showAllColumns_actionPerformed(null);
3182 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3183 * event.ActionEvent)
3186 public void hideAllButSelection_actionPerformed(ActionEvent e)
3188 toggleHiddenRegions(false, false);
3189 viewport.sendSelection();
3196 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3200 public void hideAllSelection_actionPerformed(ActionEvent e)
3202 SequenceGroup sg = viewport.getSelectionGroup();
3203 viewport.expandColSelection(sg, false);
3204 viewport.hideAllSelectedSeqs();
3205 viewport.hideSelectedColumns();
3206 alignPanel.updateLayout();
3207 alignPanel.paintAlignment(true, true);
3208 viewport.sendSelection();
3215 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3219 public void showAllhidden_actionPerformed(ActionEvent e)
3221 viewport.showAllHiddenColumns();
3222 viewport.showAllHiddenSeqs();
3223 alignPanel.paintAlignment(true, true);
3224 viewport.sendSelection();
3228 public void hideSelColumns_actionPerformed(ActionEvent e)
3230 viewport.hideSelectedColumns();
3231 alignPanel.updateLayout();
3232 alignPanel.paintAlignment(true, true);
3233 viewport.sendSelection();
3237 public void hiddenMarkers_actionPerformed(ActionEvent e)
3239 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3250 protected void scaleAbove_actionPerformed(ActionEvent e)
3252 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3253 alignPanel.updateLayout();
3254 alignPanel.paintAlignment(true, false);
3264 protected void scaleLeft_actionPerformed(ActionEvent e)
3266 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3267 alignPanel.updateLayout();
3268 alignPanel.paintAlignment(true, false);
3278 protected void scaleRight_actionPerformed(ActionEvent e)
3280 viewport.setScaleRightWrapped(scaleRight.isSelected());
3281 alignPanel.updateLayout();
3282 alignPanel.paintAlignment(true, false);
3292 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3294 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3295 alignPanel.paintAlignment(false, false);
3305 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3307 viewport.setShowText(viewTextMenuItem.isSelected());
3308 alignPanel.paintAlignment(false, false);
3318 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3320 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3321 alignPanel.paintAlignment(false, false);
3324 public FeatureSettings featureSettings;
3327 public FeatureSettingsControllerI getFeatureSettingsUI()
3329 return featureSettings;
3333 public void featureSettings_actionPerformed(ActionEvent e)
3335 showFeatureSettingsUI();
3339 public FeatureSettingsControllerI showFeatureSettingsUI()
3341 if (featureSettings != null)
3343 featureSettings.closeOldSettings();
3344 featureSettings = null;
3346 if (!showSeqFeatures.isSelected())
3348 // make sure features are actually displayed
3349 showSeqFeatures.setSelected(true);
3350 showSeqFeatures_actionPerformed(null);
3352 featureSettings = new FeatureSettings(this);
3353 return featureSettings;
3357 * Set or clear 'Show Sequence Features'
3363 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3365 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3366 alignPanel.paintAlignment(true, true);
3370 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3371 * the annotations panel as a whole.
3373 * The options to show/hide all annotations should be enabled when the panel
3374 * is shown, and disabled when the panel is hidden.
3379 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3381 final boolean setVisible = annotationPanelMenuItem.isSelected();
3382 viewport.setShowAnnotation(setVisible);
3383 this.showAllSeqAnnotations.setEnabled(setVisible);
3384 this.hideAllSeqAnnotations.setEnabled(setVisible);
3385 this.showAllAlAnnotations.setEnabled(setVisible);
3386 this.hideAllAlAnnotations.setEnabled(setVisible);
3387 alignPanel.updateLayout();
3391 public void alignmentProperties()
3394 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3397 String content = MessageManager.formatMessage("label.html_content",
3399 { contents.toString() });
3402 if (Platform.isJS())
3404 JLabel textLabel = new JLabel();
3405 textLabel.setText(content);
3406 textLabel.setBackground(Color.WHITE);
3408 pane = new JPanel(new BorderLayout());
3409 ((JPanel) pane).setOpaque(true);
3410 pane.setBackground(Color.WHITE);
3411 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3420 JEditorPane editPane = new JEditorPane("text/html", "");
3421 editPane.setEditable(false);
3422 editPane.setText(content);
3426 JInternalFrame frame = new JInternalFrame();
3428 frame.getContentPane().add(new JScrollPane(pane));
3430 Desktop.addInternalFrame(frame, MessageManager
3431 .formatMessage("label.alignment_properties", new Object[]
3432 { getTitle() }), 500, 400);
3436 * Opens an Overview panel for the alignment, unless one is open already
3441 public void overviewMenuItem_actionPerformed(ActionEvent e)
3443 boolean showHiddenRegions = Cache.getDefault(Preferences.SHOW_OV_HIDDEN_AT_START,
3445 openOverviewPanel(showHiddenRegions);
3448 public OverviewPanel openOverviewPanel(boolean showHidden)
3450 if (alignPanel.overviewPanel != null)
3452 return alignPanel.overviewPanel;
3454 JInternalFrame frame = new JInternalFrame();
3455 final OverviewPanel overview = new OverviewPanel(alignPanel, frame, showHidden);
3456 frame.setContentPane(overview);
3457 Desktop.addInternalFrame(frame, "", true, frame.getWidth(), frame.getHeight(),
3459 frame.setFrameIcon(null);
3461 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3462 final AlignmentPanel thePanel = this.alignPanel;
3463 frame.addInternalFrameListener(
3464 new javax.swing.event.InternalFrameAdapter()
3467 public void internalFrameClosed(
3468 javax.swing.event.InternalFrameEvent evt)
3471 thePanel.setOverviewPanel(null);
3474 if (getKeyListeners().length > 0)
3476 frame.addKeyListener(getKeyListeners()[0]);
3479 alignPanel.setOverviewPanel(overview);
3480 alignPanel.setOverviewTitle(this);
3486 public void textColour_actionPerformed()
3488 new TextColourChooser().chooseColour(alignPanel, null);
3492 * public void covariationColour_actionPerformed() {
3494 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3498 public void annotationColour_actionPerformed()
3500 new AnnotationColourChooser(viewport, alignPanel);
3504 public void annotationColumn_actionPerformed(ActionEvent e)
3506 new AnnotationColumnChooser(viewport, alignPanel);
3510 * Action on the user checking or unchecking the option to apply the selected
3511 * colour scheme to all groups. If unchecked, groups may have their own
3512 * independent colour schemes.
3517 public void applyToAllGroups_actionPerformed(boolean selected)
3519 viewport.setColourAppliesToAllGroups(selected);
3523 * Action on user selecting a colour from the colour menu
3526 * the name (not the menu item label!) of the colour scheme
3529 public void changeColour_actionPerformed(String name)
3532 * 'User Defined' opens a panel to configure or load a
3533 * user-defined colour scheme
3535 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3537 new UserDefinedColours(alignPanel);
3542 * otherwise set the chosen colour scheme (or null for 'None')
3544 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3545 viewport, viewport.getAlignment(),
3546 viewport.getHiddenRepSequences());
3551 * Actions on setting or changing the alignment colour scheme
3556 public void changeColour(ColourSchemeI cs)
3558 // TODO: pull up to controller method
3559 ColourMenuHelper.setColourSelected(colourMenu, cs);
3561 viewport.setGlobalColourScheme(cs);
3563 alignPanel.paintAlignment(true, true);
3567 * Show the PID threshold slider panel
3570 protected void modifyPID_actionPerformed()
3572 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3573 alignPanel.getViewName());
3574 SliderPanel.showPIDSlider();
3578 * Show the Conservation slider panel
3581 protected void modifyConservation_actionPerformed()
3583 SliderPanel.setConservationSlider(alignPanel,
3584 viewport.getResidueShading(), alignPanel.getViewName());
3585 SliderPanel.showConservationSlider();
3589 * Action on selecting or deselecting (Colour) By Conservation
3592 public void conservationMenuItem_actionPerformed(boolean selected)
3594 modifyConservation.setEnabled(selected);
3595 viewport.setConservationSelected(selected);
3596 viewport.getResidueShading().setConservationApplied(selected);
3598 changeColour(viewport.getGlobalColourScheme());
3601 modifyConservation_actionPerformed();
3605 SliderPanel.hideConservationSlider();
3610 * Action on selecting or deselecting (Colour) Above PID Threshold
3613 public void abovePIDThreshold_actionPerformed(boolean selected)
3615 modifyPID.setEnabled(selected);
3616 viewport.setAbovePIDThreshold(selected);
3619 viewport.getResidueShading().setThreshold(0,
3620 viewport.isIgnoreGapsConsensus());
3623 changeColour(viewport.getGlobalColourScheme());
3626 modifyPID_actionPerformed();
3630 SliderPanel.hidePIDSlider();
3641 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3643 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3644 AlignmentSorter.sortByPID(viewport.getAlignment(),
3645 viewport.getAlignment().getSequenceAt(0));
3646 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3647 viewport.getAlignment()));
3648 alignPanel.paintAlignment(true, false);
3658 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3660 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3661 AlignmentSorter.sortByID(viewport.getAlignment());
3663 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3664 alignPanel.paintAlignment(true, false);
3674 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3676 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3677 AlignmentSorter.sortByLength(viewport.getAlignment());
3678 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3679 viewport.getAlignment()));
3680 alignPanel.paintAlignment(true, false);
3690 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3692 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3693 AlignmentSorter.sortByGroup(viewport.getAlignment());
3694 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3695 viewport.getAlignment()));
3697 alignPanel.paintAlignment(true, false);
3707 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3709 new RedundancyPanel(alignPanel, this);
3719 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3721 if ((viewport.getSelectionGroup() == null)
3722 || (viewport.getSelectionGroup().getSize() < 2))
3724 JvOptionPane.showInternalMessageDialog(this,
3725 MessageManager.getString(
3726 "label.you_must_select_least_two_sequences"),
3727 MessageManager.getString("label.invalid_selection"),
3728 JvOptionPane.WARNING_MESSAGE);
3732 JInternalFrame frame = new JInternalFrame();
3733 frame.setContentPane(new PairwiseAlignPanel(viewport));
3734 Desktop.addInternalFrame(frame,
3735 MessageManager.getString("action.pairwise_alignment"), 600,
3741 public void autoCalculate_actionPerformed(ActionEvent e)
3743 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3744 if (viewport.autoCalculateConsensus)
3746 viewport.firePropertyChange("alignment", null,
3747 viewport.getAlignment().getSequences());
3752 public void sortByTreeOption_actionPerformed(ActionEvent e)
3754 viewport.sortByTree = sortByTree.isSelected();
3758 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3760 viewport.followSelection = listenToViewSelections.isSelected();
3764 * Constructs a tree panel and adds it to the desktop
3767 * tree type (NJ or AV)
3769 * name of score model used to compute the tree
3771 * parameters for the distance or similarity calculation
3773 void newTreePanel(String type, String modelName,
3774 SimilarityParamsI options)
3776 String frameTitle = "";
3779 boolean onSelection = false;
3780 if (viewport.getSelectionGroup() != null
3781 && viewport.getSelectionGroup().getSize() > 0)
3783 SequenceGroup sg = viewport.getSelectionGroup();
3785 /* Decide if the selection is a column region */
3786 for (SequenceI _s : sg.getSequences())
3788 if (_s.getLength() < sg.getEndRes())
3790 JvOptionPane.showMessageDialog(Desktop.desktop,
3791 MessageManager.getString(
3792 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3793 MessageManager.getString(
3794 "label.sequences_selection_not_aligned"),
3795 JvOptionPane.WARNING_MESSAGE);
3804 if (viewport.getAlignment().getHeight() < 2)
3810 tp = new TreePanel(alignPanel, type, modelName, options);
3811 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3813 frameTitle += " from ";
3815 if (viewport.getViewName() != null)
3817 frameTitle += viewport.getViewName() + " of ";
3820 frameTitle += this.title;
3822 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3833 public void addSortByOrderMenuItem(String title,
3834 final AlignmentOrder order)
3836 final JMenuItem item = new JMenuItem(MessageManager
3837 .formatMessage("action.by_title_param", new Object[]
3840 item.addActionListener(new java.awt.event.ActionListener()
3843 public void actionPerformed(ActionEvent e)
3845 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3847 // TODO: JBPNote - have to map order entries to curent SequenceI
3849 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3851 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3852 viewport.getAlignment()));
3854 alignPanel.paintAlignment(true, false);
3860 * Add a new sort by annotation score menu item
3863 * the menu to add the option to
3865 * the label used to retrieve scores for each sequence on the
3868 public void addSortByAnnotScoreMenuItem(JMenu sort,
3869 final String scoreLabel)
3871 final JMenuItem item = new JMenuItem(scoreLabel);
3873 item.addActionListener(new java.awt.event.ActionListener()
3876 public void actionPerformed(ActionEvent e)
3878 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3879 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3880 viewport.getAlignment());// ,viewport.getSelectionGroup());
3881 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3882 viewport.getAlignment()));
3883 alignPanel.paintAlignment(true, false);
3889 * last hash for alignment's annotation array - used to minimise cost of
3892 protected int _annotationScoreVectorHash;
3895 * search the alignment and rebuild the sort by annotation score submenu the
3896 * last alignment annotation vector hash is stored to minimize cost of
3897 * rebuilding in subsequence calls.
3901 public void buildSortByAnnotationScoresMenu()
3903 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3908 if (viewport.getAlignment().getAlignmentAnnotation()
3909 .hashCode() != _annotationScoreVectorHash)
3911 sortByAnnotScore.removeAll();
3912 // almost certainly a quicker way to do this - but we keep it simple
3913 Hashtable<String, String> scoreSorts = new Hashtable<>();
3914 AlignmentAnnotation aann[];
3915 for (SequenceI sqa : viewport.getAlignment().getSequences())
3917 aann = sqa.getAnnotation();
3918 for (int i = 0; aann != null && i < aann.length; i++)
3920 if (aann[i].hasScore() && aann[i].sequenceRef != null)
3922 scoreSorts.put(aann[i].label, aann[i].label);
3926 Enumeration<String> labels = scoreSorts.keys();
3927 while (labels.hasMoreElements())
3929 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
3931 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
3934 _annotationScoreVectorHash = viewport.getAlignment()
3935 .getAlignmentAnnotation().hashCode();
3940 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
3941 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
3942 * call. Listeners are added to remove the menu item when the treePanel is
3943 * closed, and adjust the tree leaf to sequence mapping when the alignment is
3947 public void buildTreeSortMenu()
3949 sortByTreeMenu.removeAll();
3951 List<Component> comps = PaintRefresher.components
3952 .get(viewport.getSequenceSetId());
3953 List<TreePanel> treePanels = new ArrayList<>();
3954 for (Component comp : comps)
3956 if (comp instanceof TreePanel)
3958 treePanels.add((TreePanel) comp);
3962 if (treePanels.size() < 1)
3964 sortByTreeMenu.setVisible(false);
3968 sortByTreeMenu.setVisible(true);
3970 for (final TreePanel tp : treePanels)
3972 final JMenuItem item = new JMenuItem(tp.getTitle());
3973 item.addActionListener(new java.awt.event.ActionListener()
3976 public void actionPerformed(ActionEvent e)
3978 tp.sortByTree_actionPerformed();
3979 addHistoryItem(tp.sortAlignmentIn(alignPanel));
3984 sortByTreeMenu.add(item);
3988 public boolean sortBy(AlignmentOrder alorder, String undoname)
3990 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3991 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
3992 if (undoname != null)
3994 addHistoryItem(new OrderCommand(undoname, oldOrder,
3995 viewport.getAlignment()));
3997 alignPanel.paintAlignment(true, false);
4002 * Work out whether the whole set of sequences or just the selected set will
4003 * be submitted for multiple alignment.
4006 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4008 // Now, check we have enough sequences
4009 AlignmentView msa = null;
4011 if ((viewport.getSelectionGroup() != null)
4012 && (viewport.getSelectionGroup().getSize() > 1))
4014 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4015 // some common interface!
4017 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4018 * SequenceI[sz = seqs.getSize(false)];
4020 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4021 * seqs.getSequenceAt(i); }
4023 msa = viewport.getAlignmentView(true);
4025 else if (viewport.getSelectionGroup() != null
4026 && viewport.getSelectionGroup().getSize() == 1)
4028 int option = JvOptionPane.showConfirmDialog(this,
4029 MessageManager.getString("warn.oneseq_msainput_selection"),
4030 MessageManager.getString("label.invalid_selection"),
4031 JvOptionPane.OK_CANCEL_OPTION);
4032 if (option == JvOptionPane.OK_OPTION)
4034 msa = viewport.getAlignmentView(false);
4039 msa = viewport.getAlignmentView(false);
4045 * Decides what is submitted to a secondary structure prediction service: the
4046 * first sequence in the alignment, or in the current selection, or, if the
4047 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4048 * region or the whole alignment. (where the first sequence in the set is the
4049 * one that the prediction will be for).
4051 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4053 AlignmentView seqs = null;
4055 if ((viewport.getSelectionGroup() != null)
4056 && (viewport.getSelectionGroup().getSize() > 0))
4058 seqs = viewport.getAlignmentView(true);
4062 seqs = viewport.getAlignmentView(false);
4064 // limit sequences - JBPNote in future - could spawn multiple prediction
4066 // TODO: viewport.getAlignment().isAligned is a global state - the local
4067 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4068 if (!viewport.getAlignment().isAligned(false))
4070 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4071 // TODO: if seqs.getSequences().length>1 then should really have warned
4085 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4087 // Pick the tree file
4088 JalviewFileChooser chooser = new JalviewFileChooser(
4089 Cache.getProperty("LAST_DIRECTORY"));
4090 chooser.setFileView(new JalviewFileView());
4091 chooser.setDialogTitle(
4092 MessageManager.getString("label.select_newick_like_tree_file"));
4093 chooser.setToolTipText(
4094 MessageManager.getString("label.load_tree_file"));
4096 chooser.setResponseHandler(0, () -> {
4097 String filePath = chooser.getSelectedFile().getPath();
4098 Cache.setProperty("LAST_DIRECTORY", filePath);
4099 NewickFile fin = null;
4102 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4103 DataSourceType.FILE));
4104 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4105 } catch (Exception ex)
4107 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4108 MessageManager.getString("label.problem_reading_tree_file"),
4109 JvOptionPane.WARNING_MESSAGE);
4110 ex.printStackTrace();
4112 if (fin != null && fin.hasWarningMessage())
4114 JvOptionPane.showMessageDialog(Desktop.desktop,
4115 fin.getWarningMessage(),
4117 .getString("label.possible_problem_with_tree_file"),
4118 JvOptionPane.WARNING_MESSAGE);
4122 chooser.showOpenDialog(this);
4125 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4127 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4130 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4131 int h, int x, int y)
4133 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4138 * Add a treeviewer for the tree extracted from a Newick file object to the
4139 * current alignment view
4146 * Associated alignment input data (or null)
4155 * @return TreePanel handle
4157 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4158 AlignmentView input, int w, int h, int x, int y)
4160 TreePanel tp = null;
4166 if (nf.getTree() != null)
4168 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4174 tp.setLocation(x, y);
4177 Desktop.addInternalFrame(tp, treeTitle, w, h);
4179 } catch (Exception ex)
4181 ex.printStackTrace();
4188 public void showContactMapTree(AlignmentAnnotation aa,
4189 PAEContactMatrix cm)
4192 int w = 400, h = 500;
4196 NewickFile fin = new NewickFile(
4197 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4198 String title = "PAE Matrix Tree for "
4199 + cm.getReferenceSeq().getDisplayId(false);
4201 showColumnWiseTree(fin, aa, title, w,h, x,y);
4202 } catch (Throwable xx)
4204 Console.error("Unexpected exception showing tree for contact matrix",
4208 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa, String treeTitle,
4209 int w, int h, int x, int y)
4214 if (nf.getTree() == null)
4218 TreePanel tp = new TreePanel(alignPanel, nf, aa, title);
4224 tp.setLocation(x, y);
4227 Desktop.addInternalFrame(tp, title, w, h);
4229 } catch (Throwable xx)
4231 Console.error("Unexpected exception showing tree for contact matrix",
4237 private boolean buildingMenu = false;
4240 * Generates menu items and listener event actions for web service clients
4243 public void BuildWebServiceMenu()
4245 while (buildingMenu)
4249 System.err.println("Waiting for building menu to finish.");
4251 } catch (Exception e)
4255 final AlignFrame me = this;
4256 buildingMenu = true;
4257 new Thread(new Runnable()
4262 final List<JMenuItem> legacyItems = new ArrayList<>();
4265 // System.err.println("Building ws menu again "
4266 // + Thread.currentThread());
4267 // TODO: add support for context dependent disabling of services based
4269 // alignment and current selection
4270 // TODO: add additional serviceHandle parameter to specify abstract
4272 // class independently of AbstractName
4273 // TODO: add in rediscovery GUI function to restart discoverer
4274 // TODO: group services by location as well as function and/or
4276 // object broker mechanism.
4277 final Vector<JMenu> wsmenu = new Vector<>();
4278 final IProgressIndicator af = me;
4281 * do not i18n these strings - they are hard-coded in class
4282 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4283 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4285 final JMenu msawsmenu = new JMenu("Alignment");
4286 final JMenu secstrmenu = new JMenu(
4287 "Secondary Structure Prediction");
4288 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4289 final JMenu analymenu = new JMenu("Analysis");
4290 final JMenu dismenu = new JMenu("Protein Disorder");
4291 // JAL-940 - only show secondary structure prediction services from
4292 // the legacy server
4293 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4295 Discoverer.services != null && (Discoverer.services.size() > 0))
4297 // TODO: refactor to allow list of AbstractName/Handler bindings to
4299 // stored or retrieved from elsewhere
4300 // No MSAWS used any more:
4301 // Vector msaws = null; // (Vector)
4302 // Discoverer.services.get("MsaWS");
4303 Vector<ServiceHandle> secstrpr = Discoverer.services
4305 if (secstrpr != null)
4307 // Add any secondary structure prediction services
4308 for (int i = 0, j = secstrpr.size(); i < j; i++)
4310 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4311 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4312 .getServiceClient(sh);
4313 int p = secstrmenu.getItemCount();
4314 impl.attachWSMenuEntry(secstrmenu, me);
4315 int q = secstrmenu.getItemCount();
4316 for (int litm = p; litm < q; litm++)
4318 legacyItems.add(secstrmenu.getItem(litm));
4324 // Add all submenus in the order they should appear on the web
4326 wsmenu.add(msawsmenu);
4327 wsmenu.add(secstrmenu);
4328 wsmenu.add(dismenu);
4329 wsmenu.add(analymenu);
4330 // No search services yet
4331 // wsmenu.add(seqsrchmenu);
4333 javax.swing.SwingUtilities.invokeLater(new Runnable()
4340 webService.removeAll();
4341 // first, add discovered services onto the webservices menu
4342 if (wsmenu.size() > 0)
4344 for (int i = 0, j = wsmenu.size(); i < j; i++)
4346 webService.add(wsmenu.get(i));
4351 webService.add(me.webServiceNoServices);
4353 // TODO: move into separate menu builder class.
4355 // logic for 2.11.1.4 is
4356 // always look to see if there is a discover. if there isn't
4357 // we can't show any Jws2 services
4358 // if there are services available, show them - regardless of
4359 // the 'show JWS2 preference'
4360 // if the discoverer is running then say so
4361 // otherwise offer to trigger discovery if 'show JWS2' is not
4363 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4364 if (jws2servs != null)
4366 if (jws2servs.hasServices())
4368 jws2servs.attachWSMenuEntry(webService, me);
4369 for (Jws2Instance sv : jws2servs.getServices())
4371 if (sv.description.toLowerCase(Locale.ROOT)
4374 for (JMenuItem jmi : legacyItems)
4376 jmi.setVisible(false);
4382 if (jws2servs.isRunning())
4384 JMenuItem tm = new JMenuItem(
4385 "Still discovering JABA Services");
4386 tm.setEnabled(false);
4389 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4391 JMenuItem enableJws2 = new JMenuItem(
4392 "Discover Web Services");
4393 enableJws2.setToolTipText(
4394 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4395 enableJws2.setEnabled(true);
4396 enableJws2.addActionListener(new ActionListener()
4400 public void actionPerformed(ActionEvent e)
4402 // start service discoverer, but ignore preference
4403 Desktop.instance.startServiceDiscovery(false,
4407 webService.add(enableJws2);
4411 build_urlServiceMenu(me.webService);
4412 build_fetchdbmenu(webService);
4413 for (JMenu item : wsmenu)
4415 if (item.getItemCount() == 0)
4417 item.setEnabled(false);
4421 item.setEnabled(true);
4424 } catch (Exception e)
4427 "Exception during web service menu building process.",
4432 } catch (Exception e)
4435 buildingMenu = false;
4442 * construct any groupURL type service menu entries.
4446 protected void build_urlServiceMenu(JMenu webService)
4448 // TODO: remove this code when 2.7 is released
4449 // DEBUG - alignmentView
4451 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4452 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4454 * @Override public void actionPerformed(ActionEvent e) {
4455 * jalview.datamodel.AlignmentView
4456 * .testSelectionViews(af.viewport.getAlignment(),
4457 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4459 * }); webService.add(testAlView);
4461 // TODO: refactor to RestClient discoverer and merge menu entries for
4462 // rest-style services with other types of analysis/calculation service
4463 // SHmmr test client - still being implemented.
4464 // DEBUG - alignmentView
4466 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4469 client.attachWSMenuEntry(
4470 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4476 * Searches the alignment sequences for xRefs and builds the Show
4477 * Cross-References menu (formerly called Show Products), with database
4478 * sources for which cross-references are found (protein sources for a
4479 * nucleotide alignment and vice versa)
4481 * @return true if Show Cross-references menu should be enabled
4483 public boolean canShowProducts()
4485 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4486 AlignmentI dataset = viewport.getAlignment().getDataset();
4488 showProducts.removeAll();
4489 final boolean dna = viewport.getAlignment().isNucleotide();
4491 if (seqs == null || seqs.length == 0)
4493 // nothing to see here.
4497 boolean showp = false;
4500 List<String> ptypes = new CrossRef(seqs, dataset)
4501 .findXrefSourcesForSequences(dna);
4503 for (final String source : ptypes)
4506 final AlignFrame af = this;
4507 JMenuItem xtype = new JMenuItem(source);
4508 xtype.addActionListener(new ActionListener()
4511 public void actionPerformed(ActionEvent e)
4513 showProductsFor(af.viewport.getSequenceSelection(), dna,
4517 showProducts.add(xtype);
4519 showProducts.setVisible(showp);
4520 showProducts.setEnabled(showp);
4521 } catch (Exception e)
4524 "canShowProducts threw an exception - please report to help@jalview.org",
4532 * Finds and displays cross-references for the selected sequences (protein
4533 * products for nucleotide sequences, dna coding sequences for peptides).
4536 * the sequences to show cross-references for
4538 * true if from a nucleotide alignment (so showing proteins)
4540 * the database to show cross-references for
4542 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4543 final String source)
4545 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4550 * Construct and display a new frame containing the translation of this
4551 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4554 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4556 AlignmentI al = null;
4559 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4561 al = dna.translateCdna(codeTable);
4562 } catch (Exception ex)
4564 Console.error("Exception during translation. Please report this !",
4566 final String msg = MessageManager.getString(
4567 "label.error_when_translating_sequences_submit_bug_report");
4568 final String errorTitle = MessageManager
4569 .getString("label.implementation_error")
4570 + MessageManager.getString("label.translation_failed");
4571 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4572 JvOptionPane.ERROR_MESSAGE);
4575 if (al == null || al.getHeight() == 0)
4577 final String msg = MessageManager.getString(
4578 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4579 final String errorTitle = MessageManager
4580 .getString("label.translation_failed");
4581 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4582 JvOptionPane.WARNING_MESSAGE);
4586 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4587 af.setFileFormat(this.currentFileFormat);
4588 final String newTitle = MessageManager
4589 .formatMessage("label.translation_of_params", new Object[]
4590 { this.getTitle(), codeTable.getId() });
4591 af.setTitle(newTitle);
4592 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4594 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4595 viewport.openSplitFrame(af, new Alignment(seqs));
4599 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4606 * Set the file format
4610 public void setFileFormat(FileFormatI format)
4612 this.currentFileFormat = format;
4616 * Try to load a features file onto the alignment.
4619 * contents or path to retrieve file or a File object
4621 * access mode of file (see jalview.io.AlignFile)
4622 * @return true if features file was parsed correctly.
4624 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4627 return avc.parseFeaturesFile(file, sourceType,
4628 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4633 public void refreshFeatureUI(boolean enableIfNecessary)
4635 // note - currently this is only still here rather than in the controller
4636 // because of the featureSettings hard reference that is yet to be
4638 if (enableIfNecessary)
4640 viewport.setShowSequenceFeatures(true);
4641 showSeqFeatures.setSelected(true);
4647 public void dragEnter(DropTargetDragEvent evt)
4652 public void dragExit(DropTargetEvent evt)
4657 public void dragOver(DropTargetDragEvent evt)
4662 public void dropActionChanged(DropTargetDragEvent evt)
4667 public void drop(DropTargetDropEvent evt)
4669 // JAL-1552 - acceptDrop required before getTransferable call for
4670 // Java's Transferable for native dnd
4671 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4672 Transferable t = evt.getTransferable();
4674 final AlignFrame thisaf = this;
4675 final List<Object> files = new ArrayList<>();
4676 List<DataSourceType> protocols = new ArrayList<>();
4680 Desktop.transferFromDropTarget(files, protocols, evt, t);
4681 } catch (Exception e)
4683 e.printStackTrace();
4687 new Thread(new Runnable()
4694 // check to see if any of these files have names matching sequences
4697 SequenceIdMatcher idm = new SequenceIdMatcher(
4698 viewport.getAlignment().getSequencesArray());
4700 * Object[] { String,SequenceI}
4702 ArrayList<Object[]> filesmatched = new ArrayList<>();
4703 ArrayList<Object> filesnotmatched = new ArrayList<>();
4704 for (int i = 0; i < files.size(); i++)
4707 Object file = files.get(i);
4708 String fileName = file.toString();
4710 DataSourceType protocol = (file instanceof File
4711 ? DataSourceType.FILE
4712 : FormatAdapter.checkProtocol(fileName));
4713 if (protocol == DataSourceType.FILE)
4716 if (file instanceof File)
4719 Platform.cacheFileData(fl);
4723 fl = new File(fileName);
4725 pdbfn = fl.getName();
4727 else if (protocol == DataSourceType.URL)
4729 URL url = new URL(fileName);
4730 pdbfn = url.getFile();
4732 if (pdbfn.length() > 0)
4734 // attempt to find a match in the alignment
4735 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4736 int l = 0, c = pdbfn.indexOf(".");
4737 while (mtch == null && c != -1)
4742 } while ((c = pdbfn.indexOf(".", l)) > l);
4745 pdbfn = pdbfn.substring(0, l);
4747 mtch = idm.findAllIdMatches(pdbfn);
4754 type = new IdentifyFile().identify(file, protocol);
4755 } catch (Exception ex)
4759 if (type != null && type.isStructureFile())
4761 filesmatched.add(new Object[] { file, protocol, mtch });
4765 // File wasn't named like one of the sequences or wasn't a PDB
4767 filesnotmatched.add(file);
4771 if (filesmatched.size() > 0)
4773 boolean autoAssociate = Cache
4774 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4777 String msg = MessageManager.formatMessage(
4778 "label.automatically_associate_structure_files_with_sequences_same_name",
4780 { Integer.valueOf(filesmatched.size())
4782 String ttl = MessageManager.getString(
4783 "label.automatically_associate_structure_files_by_name");
4784 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4785 ttl, JvOptionPane.YES_NO_OPTION);
4786 autoAssociate = choice == JvOptionPane.YES_OPTION;
4790 for (Object[] fm : filesmatched)
4792 // try and associate
4793 // TODO: may want to set a standard ID naming formalism for
4794 // associating PDB files which have no IDs.
4795 for (SequenceI toassoc : (SequenceI[]) fm[2])
4797 PDBEntry pe = new AssociatePdbFileWithSeq()
4798 .associatePdbWithSeq(fm[0].toString(),
4799 (DataSourceType) fm[1], toassoc, false,
4803 System.err.println("Associated file : "
4804 + (fm[0].toString()) + " with "
4805 + toassoc.getDisplayId(true));
4809 // TODO: do we need to update overview ? only if features are
4811 alignPanel.paintAlignment(true, false);
4817 * add declined structures as sequences
4819 for (Object[] o : filesmatched)
4821 filesnotmatched.add(o[0]);
4825 if (filesnotmatched.size() > 0)
4827 if (assocfiles > 0 && (Cache.getDefault(
4828 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4829 || JvOptionPane.showConfirmDialog(thisaf,
4830 "<html>" + MessageManager.formatMessage(
4831 "label.ignore_unmatched_dropped_files_info",
4834 filesnotmatched.size())
4837 MessageManager.getString(
4838 "label.ignore_unmatched_dropped_files"),
4839 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4843 for (Object fn : filesnotmatched)
4845 loadJalviewDataFile(fn, null, null, null);
4849 } catch (Exception ex)
4851 ex.printStackTrace();
4859 * Attempt to load a "dropped" file or URL string, by testing in turn for
4861 * <li>an Annotation file</li>
4862 * <li>a JNet file</li>
4863 * <li>a features file</li>
4864 * <li>else try to interpret as an alignment file</li>
4868 * either a filename or a URL string.
4870 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4871 FileFormatI format, SequenceI assocSeq)
4873 // BH 2018 was String file
4876 if (sourceType == null)
4878 sourceType = FormatAdapter.checkProtocol(file);
4880 // if the file isn't identified, or not positively identified as some
4881 // other filetype (PFAM is default unidentified alignment file type) then
4882 // try to parse as annotation.
4883 boolean isAnnotation = (format == null
4884 || FileFormat.Pfam.equals(format))
4885 ? new AnnotationFile().annotateAlignmentView(viewport,
4891 // first see if its a T-COFFEE score file
4892 TCoffeeScoreFile tcf = null;
4895 tcf = new TCoffeeScoreFile(file, sourceType);
4898 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4902 new TCoffeeColourScheme(viewport.getAlignment()));
4903 isAnnotation = true;
4904 setStatus(MessageManager.getString(
4905 "label.successfully_pasted_tcoffee_scores_to_alignment"));
4909 // some problem - if no warning its probable that the ID matching
4910 // process didn't work
4911 JvOptionPane.showMessageDialog(Desktop.desktop,
4912 tcf.getWarningMessage() == null
4913 ? MessageManager.getString(
4914 "label.check_file_matches_sequence_ids_alignment")
4915 : tcf.getWarningMessage(),
4916 MessageManager.getString(
4917 "label.problem_reading_tcoffee_score_file"),
4918 JvOptionPane.WARNING_MESSAGE);
4925 } catch (Exception x)
4928 "Exception when processing data source as T-COFFEE score file",
4934 // try to see if its a JNet 'concise' style annotation file *before*
4936 // try to parse it as a features file
4939 format = new IdentifyFile().identify(file, sourceType);
4941 if (FileFormat.ScoreMatrix == format)
4943 ScoreMatrixFile sm = new ScoreMatrixFile(
4944 new FileParse(file, sourceType));
4946 // todo: i18n this message
4947 setStatus(MessageManager.formatMessage(
4948 "label.successfully_loaded_matrix",
4949 sm.getMatrixName()));
4951 else if (FileFormat.Jnet.equals(format))
4953 JPredFile predictions = new JPredFile(file, sourceType);
4954 new JnetAnnotationMaker();
4955 JnetAnnotationMaker.add_annotation(predictions,
4956 viewport.getAlignment(), 0, false);
4957 viewport.getAlignment().setupJPredAlignment();
4958 isAnnotation = true;
4960 // else if (IdentifyFile.FeaturesFile.equals(format))
4961 else if (FileFormat.Features.equals(format))
4963 if (parseFeaturesFile(file, sourceType))
4965 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
4966 if (splitFrame != null)
4968 splitFrame.repaint();
4972 alignPanel.paintAlignment(true, true);
4978 new FileLoader().LoadFile(viewport, file, sourceType, format);
4985 alignPanel.adjustAnnotationHeight();
4986 viewport.updateSequenceIdColours();
4987 buildSortByAnnotationScoresMenu();
4988 alignPanel.paintAlignment(true, true);
4990 } catch (Exception ex)
4992 ex.printStackTrace();
4993 } catch (OutOfMemoryError oom)
4998 } catch (Exception x)
5003 + (sourceType != null
5004 ? (sourceType == DataSourceType.PASTE
5006 : "using " + sourceType + " from "
5010 ? "(parsing as '" + format + "' file)"
5012 oom, Desktop.desktop);
5017 * Method invoked by the ChangeListener on the tabbed pane, in other words
5018 * when a different tabbed pane is selected by the user or programmatically.
5021 public void tabSelectionChanged(int index)
5026 * update current Overview window title (if there is one)
5027 * to add view name "Original" if necessary
5029 alignPanel.setOverviewTitle(this);
5032 * switch panels and set Overview title (if there is one
5033 * because it was opened automatically)
5035 alignPanel = alignPanels.get(index);
5036 alignPanel.setOverviewTitle(this);
5038 viewport = alignPanel.av;
5039 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5040 setMenusFromViewport(viewport);
5041 if (featureSettings != null && featureSettings.isOpen()
5042 && featureSettings.fr.getViewport() != viewport)
5044 if (viewport.isShowSequenceFeatures())
5046 // refresh the featureSettings to reflect UI change
5047 showFeatureSettingsUI();
5051 // close feature settings for this view.
5052 featureSettings.close();
5059 * 'focus' any colour slider that is open to the selected viewport
5061 if (viewport.getConservationSelected())
5063 SliderPanel.setConservationSlider(alignPanel,
5064 viewport.getResidueShading(), alignPanel.getViewName());
5068 SliderPanel.hideConservationSlider();
5070 if (viewport.getAbovePIDThreshold())
5072 SliderPanel.setPIDSliderSource(alignPanel,
5073 viewport.getResidueShading(), alignPanel.getViewName());
5077 SliderPanel.hidePIDSlider();
5081 * If there is a frame linked to this one in a SplitPane, switch it to the
5082 * same view tab index. No infinite recursion of calls should happen, since
5083 * tabSelectionChanged() should not get invoked on setting the selected
5084 * index to an unchanged value. Guard against setting an invalid index
5085 * before the new view peer tab has been created.
5087 final AlignViewportI peer = viewport.getCodingComplement();
5090 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5091 .getAlignPanel().alignFrame;
5092 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5094 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5100 * On right mouse click on view tab, prompt for and set new view name.
5103 public void tabbedPane_mousePressed(MouseEvent e)
5105 if (e.isPopupTrigger())
5107 String msg = MessageManager.getString("label.enter_view_name");
5108 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5109 String reply = JvOptionPane.showInputDialog(msg, ttl);
5113 viewport.setViewName(reply);
5114 // TODO warn if reply is in getExistingViewNames()?
5115 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5120 public AlignViewport getCurrentView()
5126 * Open the dialog for regex description parsing.
5129 protected void extractScores_actionPerformed(ActionEvent e)
5131 ParseProperties pp = new jalview.analysis.ParseProperties(
5132 viewport.getAlignment());
5133 // TODO: verify regex and introduce GUI dialog for version 2.5
5134 // if (pp.getScoresFromDescription("col", "score column ",
5135 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5137 if (pp.getScoresFromDescription("description column",
5138 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5140 buildSortByAnnotationScoresMenu();
5148 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5152 protected void showDbRefs_actionPerformed(ActionEvent e)
5154 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5160 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5164 protected void showNpFeats_actionPerformed(ActionEvent e)
5166 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5170 * find the viewport amongst the tabs in this alignment frame and close that
5175 public boolean closeView(AlignViewportI av)
5179 this.closeMenuItem_actionPerformed(false);
5182 Component[] comp = tabbedPane.getComponents();
5183 for (int i = 0; comp != null && i < comp.length; i++)
5185 if (comp[i] instanceof AlignmentPanel)
5187 if (((AlignmentPanel) comp[i]).av == av)
5190 closeView((AlignmentPanel) comp[i]);
5198 protected void build_fetchdbmenu(JMenu webService)
5200 // Temporary hack - DBRef Fetcher always top level ws entry.
5201 // TODO We probably want to store a sequence database checklist in
5202 // preferences and have checkboxes.. rather than individual sources selected
5204 final JMenu rfetch = new JMenu(
5205 MessageManager.getString("action.fetch_db_references"));
5206 rfetch.setToolTipText(MessageManager.getString(
5207 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5208 webService.add(rfetch);
5210 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5211 MessageManager.getString("option.trim_retrieved_seqs"));
5212 trimrs.setToolTipText(
5213 MessageManager.getString("label.trim_retrieved_sequences"));
5215 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5216 trimrs.addActionListener(new ActionListener()
5219 public void actionPerformed(ActionEvent e)
5221 trimrs.setSelected(trimrs.isSelected());
5222 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5223 Boolean.valueOf(trimrs.isSelected()).toString());
5227 JMenuItem fetchr = new JMenuItem(
5228 MessageManager.getString("label.standard_databases"));
5229 fetchr.setToolTipText(
5230 MessageManager.getString("label.fetch_embl_uniprot"));
5231 fetchr.addActionListener(new ActionListener()
5235 public void actionPerformed(ActionEvent e)
5237 new Thread(new Runnable()
5242 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5243 .getAlignment().isNucleotide();
5244 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5245 alignPanel.av.getSequenceSelection(),
5246 alignPanel.alignFrame, null,
5247 alignPanel.alignFrame.featureSettings, isNucleotide);
5248 dbRefFetcher.addListener(new FetchFinishedListenerI()
5251 public void finished()
5254 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5255 .getFeatureSettingsModels())
5258 alignPanel.av.mergeFeaturesStyle(srcSettings);
5260 AlignFrame.this.setMenusForViewport();
5263 dbRefFetcher.fetchDBRefs(false);
5271 new Thread(new Runnable()
5276 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5277 .getSequenceFetcherSingleton();
5278 javax.swing.SwingUtilities.invokeLater(new Runnable()
5283 String[] dbclasses = sf.getNonAlignmentSources();
5284 List<DbSourceProxy> otherdb;
5285 JMenu dfetch = new JMenu();
5286 JMenu ifetch = new JMenu();
5287 JMenuItem fetchr = null;
5288 int comp = 0, icomp = 0, mcomp = 15;
5289 String mname = null;
5291 for (String dbclass : dbclasses)
5293 otherdb = sf.getSourceProxy(dbclass);
5294 // add a single entry for this class, or submenu allowing 'fetch
5296 if (otherdb == null || otherdb.size() < 1)
5302 mname = "From " + dbclass;
5304 if (otherdb.size() == 1)
5306 final DbSourceProxy[] dassource = otherdb
5307 .toArray(new DbSourceProxy[0]);
5308 DbSourceProxy src = otherdb.get(0);
5309 fetchr = new JMenuItem(src.getDbSource());
5310 fetchr.addActionListener(new ActionListener()
5314 public void actionPerformed(ActionEvent e)
5316 new Thread(new Runnable()
5322 boolean isNucleotide = alignPanel.alignFrame
5323 .getViewport().getAlignment()
5325 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5326 alignPanel.av.getSequenceSelection(),
5327 alignPanel.alignFrame, dassource,
5328 alignPanel.alignFrame.featureSettings,
5331 .addListener(new FetchFinishedListenerI()
5334 public void finished()
5336 FeatureSettingsModelI srcSettings = dassource[0]
5337 .getFeatureColourScheme();
5338 alignPanel.av.mergeFeaturesStyle(
5340 AlignFrame.this.setMenusForViewport();
5343 dbRefFetcher.fetchDBRefs(false);
5349 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5350 MessageManager.formatMessage(
5351 "label.fetch_retrieve_from", new Object[]
5352 { src.getDbName() })));
5358 final DbSourceProxy[] dassource = otherdb
5359 .toArray(new DbSourceProxy[0]);
5361 DbSourceProxy src = otherdb.get(0);
5362 fetchr = new JMenuItem(MessageManager
5363 .formatMessage("label.fetch_all_param", new Object[]
5364 { src.getDbSource() }));
5365 fetchr.addActionListener(new ActionListener()
5368 public void actionPerformed(ActionEvent e)
5370 new Thread(new Runnable()
5376 boolean isNucleotide = alignPanel.alignFrame
5377 .getViewport().getAlignment()
5379 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5380 alignPanel.av.getSequenceSelection(),
5381 alignPanel.alignFrame, dassource,
5382 alignPanel.alignFrame.featureSettings,
5385 .addListener(new FetchFinishedListenerI()
5388 public void finished()
5390 AlignFrame.this.setMenusForViewport();
5393 dbRefFetcher.fetchDBRefs(false);
5399 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5400 MessageManager.formatMessage(
5401 "label.fetch_retrieve_from_all_sources",
5403 { Integer.valueOf(otherdb.size())
5405 src.getDbSource(), src.getDbName() })));
5408 // and then build the rest of the individual menus
5409 ifetch = new JMenu(MessageManager.formatMessage(
5410 "label.source_from_db_source", new Object[]
5411 { src.getDbSource() }));
5413 String imname = null;
5415 for (DbSourceProxy sproxy : otherdb)
5417 String dbname = sproxy.getDbName();
5418 String sname = dbname.length() > 5
5419 ? dbname.substring(0, 5) + "..."
5421 String msname = dbname.length() > 10
5422 ? dbname.substring(0, 10) + "..."
5426 imname = MessageManager
5427 .formatMessage("label.from_msname", new Object[]
5430 fetchr = new JMenuItem(msname);
5431 final DbSourceProxy[] dassrc = { sproxy };
5432 fetchr.addActionListener(new ActionListener()
5436 public void actionPerformed(ActionEvent e)
5438 new Thread(new Runnable()
5444 boolean isNucleotide = alignPanel.alignFrame
5445 .getViewport().getAlignment()
5447 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5448 alignPanel.av.getSequenceSelection(),
5449 alignPanel.alignFrame, dassrc,
5450 alignPanel.alignFrame.featureSettings,
5453 .addListener(new FetchFinishedListenerI()
5456 public void finished()
5458 AlignFrame.this.setMenusForViewport();
5461 dbRefFetcher.fetchDBRefs(false);
5467 fetchr.setToolTipText(
5468 "<html>" + MessageManager.formatMessage(
5469 "label.fetch_retrieve_from", new Object[]
5473 if (++icomp >= mcomp || i == (otherdb.size()))
5475 ifetch.setText(MessageManager.formatMessage(
5476 "label.source_to_target", imname, sname));
5478 ifetch = new JMenu();
5486 if (comp >= mcomp || dbi >= (dbclasses.length))
5488 dfetch.setText(MessageManager.formatMessage(
5489 "label.source_to_target", mname, dbclass));
5491 dfetch = new JMenu();
5504 * Left justify the whole alignment.
5507 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5509 AlignmentI al = viewport.getAlignment();
5511 viewport.firePropertyChange("alignment", null, al);
5515 * Right justify the whole alignment.
5518 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5520 AlignmentI al = viewport.getAlignment();
5522 viewport.firePropertyChange("alignment", null, al);
5526 public void setShowSeqFeatures(boolean b)
5528 showSeqFeatures.setSelected(b);
5529 viewport.setShowSequenceFeatures(b);
5536 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5537 * awt.event.ActionEvent)
5540 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5542 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5543 alignPanel.paintAlignment(false, false);
5550 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5554 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5556 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5557 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5565 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5566 * .event.ActionEvent)
5569 protected void showGroupConservation_actionPerformed(ActionEvent e)
5571 viewport.setShowGroupConservation(showGroupConservation.getState());
5572 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5579 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5580 * .event.ActionEvent)
5583 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5585 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5586 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5593 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5594 * .event.ActionEvent)
5597 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5599 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5600 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5604 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5606 showSequenceLogo.setState(true);
5607 viewport.setShowSequenceLogo(true);
5608 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5609 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5613 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5615 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5622 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5623 * .event.ActionEvent)
5626 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5628 if (avc.makeGroupsFromSelection())
5630 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5631 alignPanel.updateAnnotation();
5632 alignPanel.paintAlignment(true,
5633 viewport.needToUpdateStructureViews());
5637 public void clearAlignmentSeqRep()
5639 // TODO refactor alignmentseqrep to controller
5640 if (viewport.getAlignment().hasSeqrep())
5642 viewport.getAlignment().setSeqrep(null);
5643 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5644 alignPanel.updateAnnotation();
5645 alignPanel.paintAlignment(true, true);
5650 protected void createGroup_actionPerformed(ActionEvent e)
5652 if (avc.createGroup())
5654 if (applyAutoAnnotationSettings.isSelected())
5656 alignPanel.updateAnnotation(true, false);
5658 alignPanel.alignmentChanged();
5663 protected void unGroup_actionPerformed(ActionEvent e)
5667 alignPanel.alignmentChanged();
5672 * make the given alignmentPanel the currently selected tab
5674 * @param alignmentPanel
5676 public void setDisplayedView(AlignmentPanel alignmentPanel)
5678 if (!viewport.getSequenceSetId()
5679 .equals(alignmentPanel.av.getSequenceSetId()))
5681 throw new Error(MessageManager.getString(
5682 "error.implementation_error_cannot_show_view_alignment_frame"));
5684 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5685 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5687 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5692 * Action on selection of menu options to Show or Hide annotations.
5695 * @param forSequences
5696 * update sequence-related annotations
5697 * @param forAlignment
5698 * update non-sequence-related annotations
5701 protected void setAnnotationsVisibility(boolean visible,
5702 boolean forSequences, boolean forAlignment)
5704 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5705 .getAlignmentAnnotation();
5710 for (AlignmentAnnotation aa : anns)
5713 * don't display non-positional annotations on an alignment
5715 if (aa.annotations == null)
5719 boolean apply = (aa.sequenceRef == null && forAlignment)
5720 || (aa.sequenceRef != null && forSequences);
5723 aa.visible = visible;
5726 alignPanel.validateAnnotationDimensions(true);
5727 alignPanel.alignmentChanged();
5731 * Store selected annotation sort order for the view and repaint.
5734 protected void sortAnnotations_actionPerformed()
5736 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5738 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5739 alignPanel.paintAlignment(false, false);
5744 * @return alignment panels in this alignment frame
5746 public List<? extends AlignmentViewPanel> getAlignPanels()
5748 // alignPanels is never null
5749 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5754 * Open a new alignment window, with the cDNA associated with this (protein)
5755 * alignment, aligned as is the protein.
5757 protected void viewAsCdna_actionPerformed()
5759 // TODO no longer a menu action - refactor as required
5760 final AlignmentI alignment = getViewport().getAlignment();
5761 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5762 if (mappings == null)
5766 List<SequenceI> cdnaSeqs = new ArrayList<>();
5767 for (SequenceI aaSeq : alignment.getSequences())
5769 for (AlignedCodonFrame acf : mappings)
5771 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5775 * There is a cDNA mapping for this protein sequence - add to new
5776 * alignment. It will share the same dataset sequence as other mapped
5777 * cDNA (no new mappings need to be created).
5779 final Sequence newSeq = new Sequence(dnaSeq);
5780 newSeq.setDatasetSequence(dnaSeq);
5781 cdnaSeqs.add(newSeq);
5785 if (cdnaSeqs.size() == 0)
5787 // show a warning dialog no mapped cDNA
5790 AlignmentI cdna = new Alignment(
5791 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5792 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5793 AlignFrame.DEFAULT_HEIGHT);
5794 cdna.alignAs(alignment);
5795 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5797 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5798 AlignFrame.DEFAULT_HEIGHT);
5802 * Set visibility of dna/protein complement view (available when shown in a
5808 protected void showComplement_actionPerformed(boolean show)
5810 SplitContainerI sf = getSplitViewContainer();
5813 sf.setComplementVisible(this, show);
5818 * Generate the reverse (optionally complemented) of the selected sequences,
5819 * and add them to the alignment
5822 protected void showReverse_actionPerformed(boolean complement)
5824 AlignmentI al = null;
5827 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5828 al = dna.reverseCdna(complement);
5829 viewport.addAlignment(al, "");
5830 addHistoryItem(new EditCommand(
5831 MessageManager.getString("label.add_sequences"), Action.PASTE,
5832 al.getSequencesArray(), 0, al.getWidth(),
5833 viewport.getAlignment()));
5834 } catch (Exception ex)
5836 System.err.println(ex.getMessage());
5842 * Try to run a script in the Groovy console, having first ensured that this
5843 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5844 * be targeted at this alignment.
5847 protected void runGroovy_actionPerformed()
5849 Jalview.setCurrentAlignFrame(this);
5850 groovy.ui.Console console = Desktop.getGroovyConsole();
5851 if (console != null)
5855 console.runScript();
5856 } catch (Exception ex)
5858 System.err.println((ex.toString()));
5859 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5860 MessageManager.getString("label.couldnt_run_groovy_script"),
5861 MessageManager.getString("label.groovy_support_failed"),
5862 JvOptionPane.ERROR_MESSAGE);
5867 System.err.println("Can't run Groovy script as console not found");
5872 * Hides columns containing (or not containing) a specified feature, provided
5873 * that would not leave all columns hidden
5875 * @param featureType
5876 * @param columnsContaining
5879 public boolean hideFeatureColumns(String featureType,
5880 boolean columnsContaining)
5882 boolean notForHiding = avc.markColumnsContainingFeatures(
5883 columnsContaining, false, false, featureType);
5886 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5887 false, featureType))
5889 getViewport().hideSelectedColumns();
5897 protected void selectHighlightedColumns_actionPerformed(
5898 ActionEvent actionEvent)
5900 // include key modifier check in case user selects from menu
5901 avc.markHighlightedColumns(
5902 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5903 (actionEvent.getModifiers() & (ActionEvent.META_MASK
5904 | ActionEvent.CTRL_MASK)) != 0);
5908 protected void copyHighlightedColumns_actionPerformed(
5909 ActionEvent actionEvent)
5911 avc.copyHighlightedRegionsToClipboard();
5915 * Rebuilds the Colour menu, including any user-defined colours which have
5916 * been loaded either on startup or during the session
5918 public void buildColourMenu()
5920 colourMenu.removeAll();
5922 colourMenu.add(applyToAllGroups);
5923 colourMenu.add(textColour);
5924 colourMenu.addSeparator();
5926 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
5927 viewport.getAlignment(), false);
5929 colourMenu.add(annotationColour);
5930 bg.add(annotationColour);
5931 colourMenu.addSeparator();
5932 colourMenu.add(conservationMenuItem);
5933 colourMenu.add(modifyConservation);
5934 colourMenu.add(abovePIDThreshold);
5935 colourMenu.add(modifyPID);
5937 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
5938 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
5942 * Open a dialog (if not already open) that allows the user to select and
5943 * calculate PCA or Tree analysis
5945 protected void openTreePcaDialog()
5947 if (alignPanel.getCalculationDialog() == null)
5949 new CalculationChooser(AlignFrame.this);
5954 protected void loadVcf_actionPerformed()
5956 JalviewFileChooser chooser = new JalviewFileChooser(
5957 Cache.getProperty("LAST_DIRECTORY"));
5958 chooser.setFileView(new JalviewFileView());
5959 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
5960 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
5961 final AlignFrame us = this;
5962 chooser.setResponseHandler(0, () -> {
5963 String choice = chooser.getSelectedFile().getPath();
5964 Cache.setProperty("LAST_DIRECTORY", choice);
5965 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
5966 new VCFLoader(choice).loadVCF(seqs, us);
5969 chooser.showOpenDialog(null);
5973 private Rectangle lastFeatureSettingsBounds = null;
5976 public void setFeatureSettingsGeometry(Rectangle bounds)
5978 lastFeatureSettingsBounds = bounds;
5982 public Rectangle getFeatureSettingsGeometry()
5984 return lastFeatureSettingsBounds;
5989 class PrintThread extends Thread
5993 public PrintThread(AlignmentPanel ap)
5998 static PageFormat pf;
6003 PrinterJob printJob = PrinterJob.getPrinterJob();
6007 printJob.setPrintable(ap, pf);
6011 printJob.setPrintable(ap);
6014 if (printJob.printDialog())
6019 } catch (Exception PrintException)
6021 PrintException.printStackTrace();