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.OutputStreamWriter;
53 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Deque;
58 import java.util.Enumeration;
59 import java.util.Hashtable;
60 import java.util.List;
61 import java.util.Locale;
62 import java.util.Vector;
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.ContactMatrixI;
116 import jalview.datamodel.HiddenColumns;
117 import jalview.datamodel.PDBEntry;
118 import jalview.datamodel.SeqCigar;
119 import jalview.datamodel.Sequence;
120 import jalview.datamodel.SequenceGroup;
121 import jalview.datamodel.SequenceI;
122 import jalview.gui.ColourMenuHelper.ColourChangeListener;
123 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
124 import jalview.io.AlignmentProperties;
125 import jalview.io.AnnotationFile;
126 import jalview.io.BackupFiles;
127 import jalview.io.BioJsHTMLOutput;
128 import jalview.io.DataSourceType;
129 import jalview.io.FileFormat;
130 import jalview.io.FileFormatI;
131 import jalview.io.FileFormats;
132 import jalview.io.FileLoader;
133 import jalview.io.FileParse;
134 import jalview.io.FormatAdapter;
135 import jalview.io.HtmlSvgOutput;
136 import jalview.io.IdentifyFile;
137 import jalview.io.JPredFile;
138 import jalview.io.JalviewFileChooser;
139 import jalview.io.JalviewFileView;
140 import jalview.io.JnetAnnotationMaker;
141 import jalview.io.NewickFile;
142 import jalview.io.ScoreMatrixFile;
143 import jalview.io.TCoffeeScoreFile;
144 import jalview.io.exceptions.ImageOutputException;
145 import jalview.io.vcf.VCFLoader;
146 import jalview.jbgui.GAlignFrame;
147 import jalview.project.Jalview2XML;
148 import jalview.schemes.ColourSchemeI;
149 import jalview.schemes.ColourSchemes;
150 import jalview.schemes.ResidueColourScheme;
151 import jalview.schemes.TCoffeeColourScheme;
152 import jalview.util.HttpUtils;
153 import jalview.util.ImageMaker.TYPE;
154 import jalview.util.MessageManager;
155 import jalview.util.Platform;
156 import jalview.util.imagemaker.BitmapImageSizing;
157 import jalview.viewmodel.AlignmentViewport;
158 import jalview.viewmodel.ViewportRanges;
159 import jalview.ws.DBRefFetcher;
160 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
161 import jalview.ws.jws1.Discoverer;
162 import jalview.ws.jws2.Jws2Discoverer;
163 import jalview.ws.jws2.jabaws2.Jws2Instance;
164 import jalview.ws.seqfetcher.DbSourceProxy;
170 * @version $Revision$
172 @SuppressWarnings("serial")
173 public class AlignFrame extends GAlignFrame implements DropTargetListener,
174 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
177 public static final int DEFAULT_WIDTH = 700;
179 public static final int DEFAULT_HEIGHT = 500;
182 * The currently displayed panel (selected tabbed view if more than one)
184 public AlignmentPanel alignPanel;
186 AlignViewport viewport;
188 public AlignViewControllerI avc;
190 List<AlignmentPanel> alignPanels = new ArrayList<>();
193 * Last format used to load or save alignments in this window
195 FileFormatI currentFileFormat = null;
198 * Current filename for this alignment
200 String fileName = null;
205 * Creates a new AlignFrame object with specific width and height.
211 public AlignFrame(AlignmentI al, int width, int height)
213 this(al, null, width, height);
217 * Creates a new AlignFrame object with specific width, height and
223 * @param sequenceSetId
225 public AlignFrame(AlignmentI al, int width, int height,
226 String sequenceSetId)
228 this(al, null, width, height, sequenceSetId);
232 * Creates a new AlignFrame object with specific width, height and
238 * @param sequenceSetId
241 public AlignFrame(AlignmentI al, int width, int height,
242 String sequenceSetId, String viewId)
244 this(al, null, width, height, sequenceSetId, viewId);
248 * new alignment window with hidden columns
252 * @param hiddenColumns
253 * ColumnSelection or null
255 * Width of alignment frame
259 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
262 this(al, hiddenColumns, width, height, null);
266 * Create alignment frame for al with hiddenColumns, a specific width and
267 * height, and specific sequenceId
270 * @param hiddenColumns
273 * @param sequenceSetId
276 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
277 int height, String sequenceSetId)
279 this(al, hiddenColumns, width, height, sequenceSetId, null);
283 * Create alignment frame for al with hiddenColumns, a specific width and
284 * height, and specific sequenceId
287 * @param hiddenColumns
290 * @param sequenceSetId
295 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
296 int height, String sequenceSetId, String viewId)
298 setSize(width, height);
300 if (al.getDataset() == null)
305 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
307 alignPanel = new AlignmentPanel(this, viewport);
309 addAlignmentPanel(alignPanel, true);
313 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
314 HiddenColumns hiddenColumns, int width, int height)
316 setSize(width, height);
318 if (al.getDataset() == null)
323 viewport = new AlignViewport(al, hiddenColumns);
325 if (hiddenSeqs != null && hiddenSeqs.length > 0)
327 viewport.hideSequence(hiddenSeqs);
329 alignPanel = new AlignmentPanel(this, viewport);
330 addAlignmentPanel(alignPanel, true);
335 * Make a new AlignFrame from existing alignmentPanels
342 public AlignFrame(AlignmentPanel ap)
346 addAlignmentPanel(ap, false);
351 * initalise the alignframe from the underlying viewport data and the
358 // setBackground(Color.white); // BH 2019
360 if (!Jalview.isHeadlessMode())
362 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
365 avc = new jalview.controller.AlignViewController(this, viewport,
367 if (viewport.getAlignmentConservationAnnotation() == null)
369 // BLOSUM62Colour.setEnabled(false);
370 conservationMenuItem.setEnabled(false);
371 modifyConservation.setEnabled(false);
372 // PIDColour.setEnabled(false);
373 // abovePIDThreshold.setEnabled(false);
374 // modifyPID.setEnabled(false);
377 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
379 if (sortby.equals("Id"))
381 sortIDMenuItem_actionPerformed(null);
383 else if (sortby.equals("Pairwise Identity"))
385 sortPairwiseMenuItem_actionPerformed(null);
389 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
391 setMenusFromViewport(viewport);
392 buildSortByAnnotationScoresMenu();
393 calculateTree.addActionListener(new ActionListener()
397 public void actionPerformed(ActionEvent e)
404 if (Desktop.desktop != null)
406 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
407 if (!Platform.isJS())
409 addServiceListeners();
414 if (viewport.getWrapAlignment())
416 wrapMenuItem_actionPerformed(null);
419 if (Cache.getDefault("SHOW_OVERVIEW", false))
421 this.overviewMenuItem_actionPerformed(null);
426 final List<AlignmentViewPanel> selviews = new ArrayList<>();
427 final List<AlignmentPanel> origview = new ArrayList<>();
428 final String menuLabel = MessageManager
429 .getString("label.copy_format_from");
430 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
431 new ViewSetProvider()
435 public AlignmentPanel[] getAllAlignmentPanels()
438 origview.add(alignPanel);
439 // make an array of all alignment panels except for this one
440 List<AlignmentPanel> aps = new ArrayList<>(
441 Arrays.asList(Desktop.getAlignmentPanels(null)));
442 aps.remove(AlignFrame.this.alignPanel);
443 return aps.toArray(new AlignmentPanel[aps.size()]);
445 }, selviews, new ItemListener()
449 public void itemStateChanged(ItemEvent e)
451 if (origview.size() > 0)
453 final AlignmentPanel ap = origview.get(0);
456 * Copy the ViewStyle of the selected panel to 'this one'.
457 * Don't change value of 'scaleProteinAsCdna' unless copying
460 ViewStyleI vs = selviews.get(0).getAlignViewport()
462 boolean fromSplitFrame = selviews.get(0)
463 .getAlignViewport().getCodingComplement() != null;
466 vs.setScaleProteinAsCdna(ap.getAlignViewport()
467 .getViewStyle().isScaleProteinAsCdna());
469 ap.getAlignViewport().setViewStyle(vs);
472 * Also rescale ViewStyle of SplitFrame complement if there is
473 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
474 * the whole ViewStyle (allow cDNA protein to have different
477 AlignViewportI complement = ap.getAlignViewport()
478 .getCodingComplement();
479 if (complement != null && vs.isScaleProteinAsCdna())
481 AlignFrame af = Desktop.getAlignFrameFor(complement);
482 ((SplitFrame) af.getSplitViewContainer())
484 af.setMenusForViewport();
488 ap.setSelected(true);
489 ap.alignFrame.setMenusForViewport();
494 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
495 .indexOf("devel") > -1
496 || Cache.getDefault("VERSION", "DEVELOPMENT")
497 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
499 formatMenu.add(vsel);
501 addFocusListener(new FocusAdapter()
504 public void focusGained(FocusEvent e)
506 Jalview.setCurrentAlignFrame(AlignFrame.this);
513 * Change the filename and format for the alignment, and enable the 'reload'
514 * button functionality.
521 public void setFileName(String file, FileFormatI format)
524 setFileFormat(format);
525 reload.setEnabled(true);
529 * JavaScript will have this, maybe others. More dependable than a file name
530 * and maintains a reference to the actual bytes loaded.
534 public void setFileObject(File file)
536 this.fileObject = file;
540 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
543 void addKeyListener()
545 addKeyListener(new KeyAdapter()
548 public void keyPressed(KeyEvent evt)
550 if (viewport.cursorMode
551 && ((evt.getKeyCode() >= KeyEvent.VK_0
552 && evt.getKeyCode() <= KeyEvent.VK_9)
553 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
554 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
555 && Character.isDigit(evt.getKeyChar()))
557 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
560 switch (evt.getKeyCode())
563 case 27: // escape key
564 deselectAllSequenceMenuItem_actionPerformed(null);
568 case KeyEvent.VK_DOWN:
569 if (evt.isAltDown() || !viewport.cursorMode)
571 moveSelectedSequences(false);
573 if (viewport.cursorMode)
575 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
580 if (evt.isAltDown() || !viewport.cursorMode)
582 moveSelectedSequences(true);
584 if (viewport.cursorMode)
586 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
591 case KeyEvent.VK_LEFT:
592 if (evt.isAltDown() || !viewport.cursorMode)
594 slideSequences(false,
595 alignPanel.getSeqPanel().getKeyboardNo1());
599 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
604 case KeyEvent.VK_RIGHT:
605 if (evt.isAltDown() || !viewport.cursorMode)
607 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
611 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
615 case KeyEvent.VK_SPACE:
616 if (viewport.cursorMode)
618 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
619 || evt.isShiftDown() || evt.isAltDown());
623 // case KeyEvent.VK_A:
624 // if (viewport.cursorMode)
626 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
627 // //jalview.bin.Console.outPrintln("A");
631 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
632 * jalview.bin.Console.outPrintln("closing bracket"); } break;
634 case KeyEvent.VK_DELETE:
635 case KeyEvent.VK_BACK_SPACE:
636 if (!viewport.cursorMode)
638 cut_actionPerformed();
642 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
643 || evt.isShiftDown() || evt.isAltDown());
649 if (viewport.cursorMode)
651 alignPanel.getSeqPanel().setCursorRow();
655 if (viewport.cursorMode && !evt.isControlDown())
657 alignPanel.getSeqPanel().setCursorColumn();
661 if (viewport.cursorMode)
663 alignPanel.getSeqPanel().setCursorPosition();
667 case KeyEvent.VK_ENTER:
668 case KeyEvent.VK_COMMA:
669 if (viewport.cursorMode)
671 alignPanel.getSeqPanel().setCursorRowAndColumn();
676 if (viewport.cursorMode)
678 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
682 if (viewport.cursorMode)
684 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
689 viewport.cursorMode = !viewport.cursorMode;
690 setStatus(MessageManager
691 .formatMessage("label.keyboard_editing_mode", new String[]
692 { (viewport.cursorMode ? "on" : "off") }));
693 if (viewport.cursorMode)
695 ViewportRanges ranges = viewport.getRanges();
696 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
698 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
701 alignPanel.getSeqPanel().seqCanvas.repaint();
707 Help.showHelpWindow();
708 } catch (Exception ex)
710 ex.printStackTrace();
715 boolean toggleSeqs = !evt.isControlDown();
716 boolean toggleCols = !evt.isShiftDown();
717 toggleHiddenRegions(toggleSeqs, toggleCols);
722 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
723 boolean modifyExisting = true; // always modify, don't clear
724 // evt.isShiftDown();
725 boolean invertHighlighted = evt.isAltDown();
726 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
730 case KeyEvent.VK_PAGE_UP:
731 viewport.getRanges().pageUp();
733 case KeyEvent.VK_PAGE_DOWN:
734 viewport.getRanges().pageDown();
740 public void keyReleased(KeyEvent evt)
742 switch (evt.getKeyCode())
744 case KeyEvent.VK_LEFT:
745 if (evt.isAltDown() || !viewport.cursorMode)
747 viewport.firePropertyChange("alignment", null,
748 viewport.getAlignment().getSequences());
752 case KeyEvent.VK_RIGHT:
753 if (evt.isAltDown() || !viewport.cursorMode)
755 viewport.firePropertyChange("alignment", null,
756 viewport.getAlignment().getSequences());
764 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
766 ap.alignFrame = this;
767 avc = new jalview.controller.AlignViewController(this, viewport,
772 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
774 int aSize = alignPanels.size();
776 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
778 if (aSize == 1 && ap.av.getViewName() == null)
780 this.getContentPane().add(ap, BorderLayout.CENTER);
786 setInitialTabVisible();
789 expandViews.setEnabled(true);
790 gatherViews.setEnabled(true);
791 tabbedPane.addTab(ap.av.getViewName(), ap);
793 ap.setVisible(false);
798 if (ap.av.isPadGaps())
800 ap.av.getAlignment().padGaps();
802 ap.av.updateConservation(ap);
803 ap.av.updateConsensus(ap);
804 ap.av.updateStrucConsensus(ap);
808 public void setInitialTabVisible()
810 expandViews.setEnabled(true);
811 gatherViews.setEnabled(true);
812 tabbedPane.setVisible(true);
813 AlignmentPanel first = alignPanels.get(0);
814 tabbedPane.addTab(first.av.getViewName(), first);
815 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
818 public AlignViewport getViewport()
823 /* Set up intrinsic listeners for dynamically generated GUI bits. */
824 private void addServiceListeners()
826 final java.beans.PropertyChangeListener thisListener;
827 Desktop.instance.addJalviewPropertyChangeListener("services",
828 thisListener = new java.beans.PropertyChangeListener()
831 public void propertyChange(PropertyChangeEvent evt)
833 // // jalview.bin.Console.outPrintln("Discoverer property change.");
834 // if (evt.getPropertyName().equals("services"))
836 SwingUtilities.invokeLater(new Runnable()
842 jalview.bin.Console.errPrintln(
843 "Rebuild WS Menu for service change");
844 BuildWebServiceMenu();
851 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
854 public void internalFrameClosed(
855 javax.swing.event.InternalFrameEvent evt)
857 // jalview.bin.Console.outPrintln("deregistering discoverer listener");
858 Desktop.instance.removeJalviewPropertyChangeListener("services",
860 closeMenuItem_actionPerformed(true);
863 // Finally, build the menu once to get current service state
864 new Thread(new Runnable()
869 BuildWebServiceMenu();
875 * Configure menu items that vary according to whether the alignment is
876 * nucleotide or protein
878 public void setGUINucleotide()
880 AlignmentI al = getViewport().getAlignment();
881 boolean nucleotide = al.isNucleotide();
883 loadVcf.setVisible(nucleotide);
884 showTranslation.setVisible(nucleotide);
885 showReverse.setVisible(nucleotide);
886 showReverseComplement.setVisible(nucleotide);
887 conservationMenuItem.setEnabled(!nucleotide);
889 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
890 showGroupConservation.setEnabled(!nucleotide);
892 showComplementMenuItem
893 .setText(nucleotide ? MessageManager.getString("label.protein")
894 : MessageManager.getString("label.nucleotide"));
898 * set up menus for the current viewport. This may be called after any
899 * operation that affects the data in the current view (selection changed,
900 * etc) to update the menus to reflect the new state.
903 public void setMenusForViewport()
905 setMenusFromViewport(viewport);
909 * Need to call this method when tabs are selected for multiple views, or when
910 * loading from Jalview2XML.java
915 public void setMenusFromViewport(AlignViewport av)
917 padGapsMenuitem.setSelected(av.isPadGaps());
918 colourTextMenuItem.setSelected(av.isShowColourText());
919 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
920 modifyPID.setEnabled(abovePIDThreshold.isSelected());
921 conservationMenuItem.setSelected(av.getConservationSelected());
922 modifyConservation.setEnabled(conservationMenuItem.isSelected());
923 seqLimits.setSelected(av.getShowJVSuffix());
924 idRightAlign.setSelected(av.isRightAlignIds());
925 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
926 renderGapsMenuItem.setSelected(av.isRenderGaps());
927 wrapMenuItem.setSelected(av.getWrapAlignment());
928 scaleAbove.setVisible(av.getWrapAlignment());
929 scaleLeft.setVisible(av.getWrapAlignment());
930 scaleRight.setVisible(av.getWrapAlignment());
931 annotationPanelMenuItem.setState(av.isShowAnnotation());
933 * Show/hide annotations only enabled if annotation panel is shown
935 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
936 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
937 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
938 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
939 viewBoxesMenuItem.setSelected(av.getShowBoxes());
940 viewTextMenuItem.setSelected(av.getShowText());
941 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
942 showGroupConsensus.setSelected(av.isShowGroupConsensus());
943 showGroupConservation.setSelected(av.isShowGroupConservation());
944 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
945 showSequenceLogo.setSelected(av.isShowSequenceLogo());
946 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
948 ColourMenuHelper.setColourSelected(colourMenu,
949 av.getGlobalColourScheme());
951 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
952 hiddenMarkers.setState(av.getShowHiddenMarkers());
953 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
954 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
955 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
956 autoCalculate.setSelected(av.autoCalculateConsensus);
957 sortByTree.setSelected(av.sortByTree);
958 listenToViewSelections.setSelected(av.followSelection);
960 showProducts.setEnabled(canShowProducts());
961 setGroovyEnabled(Desktop.getGroovyConsole() != null);
967 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
971 public void setGroovyEnabled(boolean b)
973 runGroovy.setEnabled(b);
976 private IProgressIndicator progressBar;
981 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
984 public void setProgressBar(String message, long id)
986 if (!Platform.isHeadless() && progressBar != null)
987 progressBar.setProgressBar(message, id);
991 public void registerHandler(final long id,
992 final IProgressIndicatorHandler handler)
994 if (progressBar != null)
995 progressBar.registerHandler(id, handler);
1000 * @return true if any progress bars are still active
1003 public boolean operationInProgress()
1005 return progressBar == null ? false : progressBar.operationInProgress();
1009 * Sets the text of the status bar. Note that setting a null or empty value
1010 * will cause the status bar to be hidden, with possibly undesirable flicker
1011 * of the screen layout.
1014 public void setStatus(String text)
1016 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1020 * Added so Castor Mapping file can obtain Jalview Version
1022 public String getVersion()
1024 return Cache.getProperty("VERSION");
1027 public FeatureRenderer getFeatureRenderer()
1029 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1033 public void fetchSequence_actionPerformed()
1035 new SequenceFetcher(this);
1039 public void addFromFile_actionPerformed(ActionEvent e)
1041 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1045 public void reload_actionPerformed(ActionEvent e)
1047 if (fileName != null)
1049 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1050 // originating file's format
1051 // TODO: work out how to recover feature settings for correct view(s) when
1052 // file is reloaded.
1053 if (FileFormat.Jalview.equals(currentFileFormat))
1055 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1056 for (int i = 0; i < frames.length; i++)
1058 if (frames[i] instanceof AlignFrame && frames[i] != this
1059 && ((AlignFrame) frames[i]).fileName != null
1060 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1064 frames[i].setSelected(true);
1065 Desktop.instance.closeAssociatedWindows();
1066 } catch (java.beans.PropertyVetoException ex)
1072 Desktop.instance.closeAssociatedWindows();
1074 FileLoader loader = new FileLoader();
1075 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1076 ? DataSourceType.URL
1077 : DataSourceType.FILE;
1078 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1082 Rectangle bounds = this.getBounds();
1084 FileLoader loader = new FileLoader();
1086 AlignFrame newframe = null;
1088 if (fileObject == null)
1091 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1092 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1093 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1098 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1099 DataSourceType.FILE, currentFileFormat);
1102 newframe.setBounds(bounds);
1103 if (featureSettings != null && featureSettings.isShowing())
1105 final Rectangle fspos = featureSettings.frame.getBounds();
1106 // TODO: need a 'show feature settings' function that takes bounds -
1107 // need to refactor Desktop.addFrame
1108 newframe.featureSettings_actionPerformed(null);
1109 final FeatureSettings nfs = newframe.featureSettings;
1110 SwingUtilities.invokeLater(new Runnable()
1115 nfs.frame.setBounds(fspos);
1118 this.featureSettings.close();
1119 this.featureSettings = null;
1121 this.closeMenuItem_actionPerformed(true);
1127 public void addFromText_actionPerformed(ActionEvent e)
1130 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1134 public void addFromURL_actionPerformed(ActionEvent e)
1136 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1140 public void save_actionPerformed(ActionEvent e)
1142 if (fileName == null || (currentFileFormat == null)
1143 || HttpUtils.startsWithHttpOrHttps(fileName))
1145 saveAs_actionPerformed();
1149 saveAlignment(fileName, currentFileFormat);
1154 * Saves the alignment to a file with a name chosen by the user, if necessary
1155 * warning if a file would be overwritten
1158 public void saveAs_actionPerformed()
1160 String format = currentFileFormat == null ? null
1161 : currentFileFormat.getName();
1162 JalviewFileChooser chooser = JalviewFileChooser
1163 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1165 chooser.setFileView(new JalviewFileView());
1166 chooser.setDialogTitle(
1167 MessageManager.getString("label.save_alignment_to_file"));
1168 chooser.setToolTipText(MessageManager.getString("action.save"));
1170 int value = chooser.showSaveDialog(this);
1172 if (value != JalviewFileChooser.APPROVE_OPTION)
1176 currentFileFormat = chooser.getSelectedFormat();
1177 // todo is this (2005) test now obsolete - value is never null?
1178 while (currentFileFormat == null)
1180 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1182 .getString("label.select_file_format_before_saving"),
1183 MessageManager.getString("label.file_format_not_specified"),
1184 JvOptionPane.WARNING_MESSAGE);
1185 currentFileFormat = chooser.getSelectedFormat();
1186 value = chooser.showSaveDialog(this);
1187 if (value != JalviewFileChooser.APPROVE_OPTION)
1193 fileName = chooser.getSelectedFile().getPath();
1195 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1196 Cache.setProperty("LAST_DIRECTORY", fileName);
1197 saveAlignment(fileName, currentFileFormat);
1200 boolean lastSaveSuccessful = false;
1202 FileFormatI lastFormatSaved;
1204 String lastFilenameSaved;
1207 * Raise a dialog or status message for the last call to saveAlignment.
1209 * @return true if last call to saveAlignment(file, format) was successful.
1211 public boolean isSaveAlignmentSuccessful()
1214 if (!lastSaveSuccessful)
1216 if (!Platform.isHeadless())
1218 JvOptionPane.showInternalMessageDialog(this, MessageManager
1219 .formatMessage("label.couldnt_save_file", new Object[]
1220 { lastFilenameSaved }),
1221 MessageManager.getString("label.error_saving_file"),
1222 JvOptionPane.WARNING_MESSAGE);
1226 Console.error(MessageManager
1227 .formatMessage("label.couldnt_save_file", new Object[]
1228 { lastFilenameSaved }));
1234 setStatus(MessageManager.formatMessage(
1235 "label.successfully_saved_to_file_in_format", new Object[]
1236 { lastFilenameSaved, lastFormatSaved }));
1239 return lastSaveSuccessful;
1243 * Saves the alignment to the specified file path, in the specified format,
1244 * which may be an alignment format, or Jalview project format. If the
1245 * alignment has hidden regions, or the format is one capable of including
1246 * non-sequence data (features, annotations, groups), then the user may be
1247 * prompted to specify what to include in the output.
1252 public void saveAlignment(String file, FileFormatI format)
1254 saveAlignment(file, format, false);
1257 public void saveAlignment(String file, FileFormatI format, boolean stdout)
1259 lastSaveSuccessful = true;
1262 lastFilenameSaved = file;
1264 lastFormatSaved = format;
1266 if (FileFormat.Jalview.equals(format))
1268 String shortName = title;
1269 if (shortName.indexOf(File.separatorChar) > -1)
1271 shortName = shortName
1272 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1274 // TODO deal with stdout=true
1275 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1278 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1279 if (lastSaveSuccessful)
1281 this.getViewport().setSavedUpToDate(true);
1284 statusBar.setText(MessageManager.formatMessage(
1285 "label.successfully_saved_to_file_in_format", new Object[]
1291 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1292 Runnable cancelAction = () -> {
1293 lastSaveSuccessful = false;
1295 Runnable outputAction = () -> {
1296 // todo defer this to inside formatSequences (or later)
1297 AlignmentExportData exportData = viewport.getAlignExportData(options);
1298 String output = new FormatAdapter(alignPanel, options)
1299 .formatSequences(format, exportData.getAlignment(),
1300 exportData.getOmitHidden(),
1301 exportData.getStartEndPostions(),
1302 viewport.getAlignment().getHiddenColumns());
1305 lastSaveSuccessful = false;
1309 // create backupfiles object and get new temp filename destination
1310 boolean doBackup = BackupFiles.getEnabled() && !stdout;
1311 BackupFiles backupfiles = null;
1314 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1315 backupfiles = new BackupFiles(file);
1319 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1321 Console.trace("ALIGNFRAME setting PrintWriter");
1322 PrintWriter out = stdout
1323 ? new PrintWriter(new OutputStreamWriter(System.out))
1324 : new PrintWriter(new FileWriter(tempFilePath));
1326 if (backupfiles != null)
1328 Console.trace("ALIGNFRAME about to write to temp file "
1329 + backupfiles.getTempFilePath());
1334 Console.trace("ALIGNFRAME about to close file");
1336 Console.trace("ALIGNFRAME closed file");
1337 AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1340 statusBar.setText(MessageManager.formatMessage(
1341 "label.successfully_printed_to_stdout_in_format",
1343 { format.getName() }));
1347 statusBar.setText(MessageManager.formatMessage(
1348 "label.successfully_saved_to_file_in_format",
1350 { fileName, format.getName() }));
1352 lastSaveSuccessful = true;
1353 } catch (IOException e)
1355 lastSaveSuccessful = false;
1357 "ALIGNFRAME Something happened writing the temp file");
1358 Console.error(e.getMessage());
1359 Console.debug(Cache.getStackTraceString(e));
1360 } catch (Exception ex)
1362 lastSaveSuccessful = false;
1364 "ALIGNFRAME Something unexpected happened writing the temp file");
1365 Console.error(ex.getMessage());
1366 Console.debug(Cache.getStackTraceString(ex));
1371 backupfiles.setWriteSuccess(lastSaveSuccessful);
1372 Console.debug("ALIGNFRAME writing temp file was "
1373 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1374 // do the backup file roll and rename the temp file to actual file
1375 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1376 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1377 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1378 + (lastSaveSuccessful ? "" : "un") + "successfully");
1381 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1382 if (lastSaveSuccessful)
1384 AlignFrame.this.getViewport().setSavedUpToDate(true);
1390 * show dialog with export options if applicable; else just do it
1392 if (AlignExportOptions.isNeeded(viewport, format))
1394 AlignExportOptions choices = new AlignExportOptions(
1395 alignPanel.getAlignViewport(), format, options);
1396 choices.setResponseAction(0, outputAction);
1397 choices.setResponseAction(1, cancelAction);
1398 choices.showDialog();
1405 } catch (Exception e)
1407 // TODO Auto-generated catch block
1408 e.printStackTrace();
1414 * Outputs the alignment to textbox in the requested format, if necessary
1415 * first prompting the user for whether to include hidden regions or
1418 * @param fileFormatName
1421 protected void outputText_actionPerformed(String fileFormatName)
1423 FileFormatI fileFormat = FileFormats.getInstance()
1424 .forName(fileFormatName);
1425 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1426 Runnable outputAction = () -> {
1427 // todo defer this to inside formatSequences (or later)
1428 AlignmentExportData exportData = viewport.getAlignExportData(options);
1429 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1430 cap.setForInput(null);
1433 FileFormatI format = fileFormat;
1434 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1435 format, exportData.getAlignment(),
1436 exportData.getOmitHidden(),
1437 exportData.getStartEndPostions(),
1438 viewport.getAlignment().getHiddenColumns()));
1439 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1440 "label.alignment_output_command", new Object[]
1441 { fileFormat.getName() }), 600, 500);
1442 } catch (OutOfMemoryError oom)
1444 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1451 * show dialog with export options if applicable; else just do it
1453 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1455 AlignExportOptions choices = new AlignExportOptions(
1456 alignPanel.getAlignViewport(), fileFormat, options);
1457 choices.setResponseAction(0, outputAction);
1458 choices.showDialog();
1465 } catch (Exception e)
1467 e.printStackTrace();
1479 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1481 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1484 htmlSVG.exportHTML(null);
1485 } catch (ImageOutputException x)
1487 // report problem to console and raise dialog
1492 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1494 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1497 bjs.exportHTML(null);
1498 } catch (ImageOutputException x)
1500 // report problem to console and raise dialog
1504 public void createImageMap(File file, String image)
1508 alignPanel.makePNGImageMap(file, image);
1509 } catch (ImageOutputException x)
1511 // report problem to console and raise dialog
1516 public void createPNG_actionPerformed(ActionEvent e)
1521 } catch (ImageOutputException ioex)
1523 // raise dialog, and report via console
1528 public void createEPS_actionPerformed(ActionEvent e)
1533 } catch (ImageOutputException ioex)
1535 // raise dialog, and report via console
1541 public void createSVG_actionPerformed(ActionEvent e)
1546 } catch (ImageOutputException ioex)
1548 // raise dialog, and report via console
1554 * Creates a PNG image of the alignment and writes it to the given file. If
1555 * the file is null, the user is prompted to choose a file.
1559 public void createPNG(File f) throws ImageOutputException
1561 createPNG(f, null, BitmapImageSizing.nullBitmapImageSizing());
1564 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1565 throws ImageOutputException
1567 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1571 * Creates an EPS image of the alignment and writes it to the given file. If
1572 * the file is null, the user is prompted to choose a file.
1576 public void createEPS(File f) throws ImageOutputException
1581 public void createEPS(File f, String renderer) throws ImageOutputException
1583 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1587 * Creates an SVG image of the alignment and writes it to the given file. If
1588 * the file is null, the user is prompted to choose a file.
1592 public void createSVG(File f) throws ImageOutputException
1597 public void createSVG(File f, String renderer) throws ImageOutputException
1599 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1603 public void pageSetup_actionPerformed(ActionEvent e)
1605 PrinterJob printJob = PrinterJob.getPrinterJob();
1606 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1616 public void printMenuItem_actionPerformed(ActionEvent e)
1618 // Putting in a thread avoids Swing painting problems
1619 PrintThread thread = new PrintThread(alignPanel);
1624 public void exportFeatures_actionPerformed(ActionEvent e)
1626 new AnnotationExporter(alignPanel).exportFeatures();
1630 public void exportAnnotations_actionPerformed(ActionEvent e)
1632 new AnnotationExporter(alignPanel).exportAnnotations();
1636 public void associatedData_actionPerformed(ActionEvent e)
1638 final JalviewFileChooser chooser = new JalviewFileChooser(
1639 Cache.getProperty("LAST_DIRECTORY"));
1640 chooser.setFileView(new JalviewFileView());
1641 String tooltip = MessageManager
1642 .getString("label.load_jalview_annotations");
1643 chooser.setDialogTitle(tooltip);
1644 chooser.setToolTipText(tooltip);
1645 chooser.setResponseHandler(0, () -> {
1646 String choice = chooser.getSelectedFile().getPath();
1647 Cache.setProperty("LAST_DIRECTORY", choice);
1648 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1651 chooser.showOpenDialog(this);
1655 * Close the current view or all views in the alignment frame. If the frame
1656 * only contains one view then the alignment will be removed from memory.
1658 * @param closeAllTabs
1661 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1663 if (alignPanels != null && alignPanels.size() < 2)
1665 closeAllTabs = true;
1670 if (alignPanels != null)
1674 if (this.isClosed())
1676 // really close all the windows - otherwise wait till
1677 // setClosed(true) is called
1678 for (int i = 0; i < alignPanels.size(); i++)
1680 AlignmentPanel ap = alignPanels.get(i);
1687 closeView(alignPanel);
1692 if (featureSettings != null && featureSettings.isOpen())
1694 featureSettings.close();
1695 featureSettings = null;
1698 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1699 * be called recursively, with the frame now in 'closed' state
1701 this.setClosed(true);
1703 } catch (Exception ex)
1705 ex.printStackTrace();
1710 * Close the specified panel and close up tabs appropriately.
1712 * @param panelToClose
1714 public void closeView(AlignmentPanel panelToClose)
1716 int index = tabbedPane.getSelectedIndex();
1717 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1718 alignPanels.remove(panelToClose);
1719 panelToClose.closePanel();
1720 panelToClose = null;
1722 tabbedPane.removeTabAt(closedindex);
1723 tabbedPane.validate();
1725 if (index > closedindex || index == tabbedPane.getTabCount())
1727 // modify currently selected tab index if necessary.
1731 this.tabSelectionChanged(index);
1737 void updateEditMenuBar()
1740 if (viewport.getHistoryList().size() > 0)
1742 undoMenuItem.setEnabled(true);
1743 CommandI command = viewport.getHistoryList().peek();
1744 undoMenuItem.setText(MessageManager
1745 .formatMessage("label.undo_command", new Object[]
1746 { command.getDescription() }));
1750 undoMenuItem.setEnabled(false);
1751 undoMenuItem.setText(MessageManager.getString("action.undo"));
1754 if (viewport.getRedoList().size() > 0)
1756 redoMenuItem.setEnabled(true);
1758 CommandI command = viewport.getRedoList().peek();
1759 redoMenuItem.setText(MessageManager
1760 .formatMessage("label.redo_command", new Object[]
1761 { command.getDescription() }));
1765 redoMenuItem.setEnabled(false);
1766 redoMenuItem.setText(MessageManager.getString("action.redo"));
1771 public void addHistoryItem(CommandI command)
1773 if (command.getSize() > 0)
1775 viewport.addToHistoryList(command);
1776 viewport.clearRedoList();
1777 updateEditMenuBar();
1778 viewport.updateHiddenColumns();
1779 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1780 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1781 // viewport.getColumnSelection()
1782 // .getHiddenColumns().size() > 0);
1788 * @return alignment objects for all views
1790 AlignmentI[] getViewAlignments()
1792 if (alignPanels != null)
1794 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1796 for (AlignmentPanel ap : alignPanels)
1798 als[i++] = ap.av.getAlignment();
1802 if (viewport != null)
1804 return new AlignmentI[] { viewport.getAlignment() };
1816 protected void undoMenuItem_actionPerformed(ActionEvent e)
1818 if (viewport.getHistoryList().isEmpty())
1822 CommandI command = viewport.getHistoryList().pop();
1823 viewport.addToRedoList(command);
1824 command.undoCommand(getViewAlignments());
1826 AlignmentViewport originalSource = getOriginatingSource(command);
1827 updateEditMenuBar();
1829 if (originalSource != null)
1831 if (originalSource != viewport)
1834 "Implementation worry: mismatch of viewport origin for undo");
1836 originalSource.updateHiddenColumns();
1837 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1839 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1840 // viewport.getColumnSelection()
1841 // .getHiddenColumns().size() > 0);
1842 originalSource.firePropertyChange("alignment", null,
1843 originalSource.getAlignment().getSequences());
1854 protected void redoMenuItem_actionPerformed(ActionEvent e)
1856 if (viewport.getRedoList().size() < 1)
1861 CommandI command = viewport.getRedoList().pop();
1862 viewport.addToHistoryList(command);
1863 command.doCommand(getViewAlignments());
1865 AlignmentViewport originalSource = getOriginatingSource(command);
1866 updateEditMenuBar();
1868 if (originalSource != null)
1871 if (originalSource != viewport)
1874 "Implementation worry: mismatch of viewport origin for redo");
1876 originalSource.updateHiddenColumns();
1877 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1879 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1880 // viewport.getColumnSelection()
1881 // .getHiddenColumns().size() > 0);
1882 originalSource.firePropertyChange("alignment", null,
1883 originalSource.getAlignment().getSequences());
1887 AlignmentViewport getOriginatingSource(CommandI command)
1889 AlignmentViewport originalSource = null;
1890 // For sequence removal and addition, we need to fire
1891 // the property change event FROM the viewport where the
1892 // original alignment was altered
1893 AlignmentI al = null;
1894 if (command instanceof EditCommand)
1896 EditCommand editCommand = (EditCommand) command;
1897 al = editCommand.getAlignment();
1898 List<Component> comps = PaintRefresher.components
1899 .get(viewport.getSequenceSetId());
1901 for (Component comp : comps)
1903 if (comp instanceof AlignmentPanel)
1905 if (al == ((AlignmentPanel) comp).av.getAlignment())
1907 originalSource = ((AlignmentPanel) comp).av;
1914 if (originalSource == null)
1916 // The original view is closed, we must validate
1917 // the current view against the closed view first
1920 PaintRefresher.validateSequences(al, viewport.getAlignment());
1923 originalSource = viewport;
1926 return originalSource;
1930 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1931 * or the sequence under cursor in keyboard mode
1936 public void moveSelectedSequences(boolean up)
1938 SequenceGroup sg = viewport.getSelectionGroup();
1942 if (viewport.cursorMode)
1944 sg = new SequenceGroup();
1945 sg.addSequence(viewport.getAlignment().getSequenceAt(
1946 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1954 if (sg.getSize() < 1)
1959 // TODO: JAL-3733 - add an event to the undo buffer for this !
1961 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1962 viewport.getHiddenRepSequences(), up);
1963 alignPanel.paintAlignment(true, false);
1966 synchronized void slideSequences(boolean right, int size)
1968 List<SequenceI> sg = new ArrayList<>();
1969 if (viewport.cursorMode)
1971 sg.add(viewport.getAlignment()
1972 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1974 else if (viewport.getSelectionGroup() != null
1975 && viewport.getSelectionGroup().getSize() != viewport
1976 .getAlignment().getHeight())
1978 sg = viewport.getSelectionGroup()
1979 .getSequences(viewport.getHiddenRepSequences());
1987 List<SequenceI> invertGroup = new ArrayList<>();
1989 for (SequenceI seq : viewport.getAlignment().getSequences())
1991 if (!sg.contains(seq))
1993 invertGroup.add(seq);
1997 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1999 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2000 for (int i = 0; i < invertGroup.size(); i++)
2002 seqs2[i] = invertGroup.get(i);
2005 SlideSequencesCommand ssc;
2008 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2009 viewport.getGapCharacter());
2013 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2014 viewport.getGapCharacter());
2017 int groupAdjustment = 0;
2018 if (ssc.getGapsInsertedBegin() && right)
2020 if (viewport.cursorMode)
2022 alignPanel.getSeqPanel().moveCursor(size, 0);
2026 groupAdjustment = size;
2029 else if (!ssc.getGapsInsertedBegin() && !right)
2031 if (viewport.cursorMode)
2033 alignPanel.getSeqPanel().moveCursor(-size, 0);
2037 groupAdjustment = -size;
2041 if (groupAdjustment != 0)
2043 viewport.getSelectionGroup().setStartRes(
2044 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2045 viewport.getSelectionGroup().setEndRes(
2046 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2050 * just extend the last slide command if compatible; but not if in
2051 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2053 boolean appendHistoryItem = false;
2054 Deque<CommandI> historyList = viewport.getHistoryList();
2055 boolean inSplitFrame = getSplitViewContainer() != null;
2056 if (!inSplitFrame && historyList != null && historyList.size() > 0
2057 && historyList.peek() instanceof SlideSequencesCommand)
2059 appendHistoryItem = ssc.appendSlideCommand(
2060 (SlideSequencesCommand) historyList.peek());
2063 if (!appendHistoryItem)
2065 addHistoryItem(ssc);
2078 protected void copy_actionPerformed()
2080 if (viewport.getSelectionGroup() == null)
2084 // TODO: preserve the ordering of displayed alignment annotation in any
2085 // internal paste (particularly sequence associated annotation)
2086 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2087 String[] omitHidden = null;
2089 if (viewport.hasHiddenColumns())
2091 omitHidden = viewport.getViewAsString(true);
2094 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2095 seqs, omitHidden, null);
2097 StringSelection ss = new StringSelection(output);
2101 jalview.gui.Desktop.internalCopy = true;
2102 // Its really worth setting the clipboard contents
2103 // to empty before setting the large StringSelection!!
2104 Toolkit.getDefaultToolkit().getSystemClipboard()
2105 .setContents(new StringSelection(""), null);
2107 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2109 } catch (OutOfMemoryError er)
2111 new OOMWarning("copying region", er);
2115 HiddenColumns hiddenColumns = null;
2116 if (viewport.hasHiddenColumns())
2118 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2119 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2121 // create new HiddenColumns object with copy of hidden regions
2122 // between startRes and endRes, offset by startRes
2123 hiddenColumns = new HiddenColumns(
2124 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2125 hiddenCutoff, hiddenOffset);
2128 Desktop.jalviewClipboard = new Object[] { seqs,
2129 viewport.getAlignment().getDataset(), hiddenColumns };
2130 setStatus(MessageManager.formatMessage(
2131 "label.copied_sequences_to_clipboard", new Object[]
2132 { Integer.valueOf(seqs.length).toString() }));
2142 protected void pasteNew_actionPerformed(ActionEvent e)
2154 protected void pasteThis_actionPerformed(ActionEvent e)
2160 * Paste contents of Jalview clipboard
2162 * @param newAlignment
2163 * true to paste to a new alignment, otherwise add to this.
2165 void paste(boolean newAlignment)
2167 boolean externalPaste = true;
2170 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2171 Transferable contents = c.getContents(this);
2173 if (contents == null)
2182 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2183 if (str.length() < 1)
2188 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2190 } catch (OutOfMemoryError er)
2192 new OOMWarning("Out of memory pasting sequences!!", er);
2196 SequenceI[] sequences;
2197 boolean annotationAdded = false;
2198 AlignmentI alignment = null;
2200 if (Desktop.jalviewClipboard != null)
2202 // The clipboard was filled from within Jalview, we must use the
2204 // And dataset from the copied alignment
2205 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2206 // be doubly sure that we create *new* sequence objects.
2207 sequences = new SequenceI[newseq.length];
2208 for (int i = 0; i < newseq.length; i++)
2210 sequences[i] = new Sequence(newseq[i]);
2212 alignment = new Alignment(sequences);
2213 externalPaste = false;
2217 // parse the clipboard as an alignment.
2218 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2220 sequences = alignment.getSequencesArray();
2224 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2230 if (Desktop.jalviewClipboard != null)
2232 // dataset is inherited
2233 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2237 // new dataset is constructed
2238 alignment.setDataset(null);
2240 alwidth = alignment.getWidth() + 1;
2244 AlignmentI pastedal = alignment; // preserve pasted alignment object
2245 // Add pasted sequences and dataset into existing alignment.
2246 alignment = viewport.getAlignment();
2247 alwidth = alignment.getWidth() + 1;
2248 // decide if we need to import sequences from an existing dataset
2249 boolean importDs = Desktop.jalviewClipboard != null
2250 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2251 // importDs==true instructs us to copy over new dataset sequences from
2252 // an existing alignment
2253 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2255 // minimum dataset set
2257 for (int i = 0; i < sequences.length; i++)
2261 newDs.addElement(null);
2263 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2265 if (importDs && ds != null)
2267 if (!newDs.contains(ds))
2269 newDs.setElementAt(ds, i);
2270 ds = new Sequence(ds);
2271 // update with new dataset sequence
2272 sequences[i].setDatasetSequence(ds);
2276 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2281 // copy and derive new dataset sequence
2282 sequences[i] = sequences[i].deriveSequence();
2283 alignment.getDataset()
2284 .addSequence(sequences[i].getDatasetSequence());
2285 // TODO: avoid creation of duplicate dataset sequences with a
2286 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2288 alignment.addSequence(sequences[i]); // merges dataset
2292 newDs.clear(); // tidy up
2294 if (alignment.getAlignmentAnnotation() != null)
2296 for (AlignmentAnnotation alan : alignment
2297 .getAlignmentAnnotation())
2299 if (alan.graphGroup > fgroup)
2301 fgroup = alan.graphGroup;
2305 if (pastedal.getAlignmentAnnotation() != null)
2307 // Add any annotation attached to alignment.
2308 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2309 for (int i = 0; i < alann.length; i++)
2311 annotationAdded = true;
2312 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2314 AlignmentAnnotation newann = new AlignmentAnnotation(
2316 if (newann.graphGroup > -1)
2318 if (newGraphGroups.size() <= newann.graphGroup
2319 || newGraphGroups.get(newann.graphGroup) == null)
2321 for (int q = newGraphGroups
2322 .size(); q <= newann.graphGroup; q++)
2324 newGraphGroups.add(q, null);
2326 newGraphGroups.set(newann.graphGroup,
2327 Integer.valueOf(++fgroup));
2329 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2333 newann.padAnnotation(alwidth);
2334 alignment.addAnnotation(newann);
2344 addHistoryItem(new EditCommand(
2345 MessageManager.getString("label.add_sequences"),
2346 Action.PASTE, sequences, 0, alignment.getWidth(),
2349 // Add any annotations attached to sequences
2350 for (int i = 0; i < sequences.length; i++)
2352 if (sequences[i].getAnnotation() != null)
2354 AlignmentAnnotation newann;
2355 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2357 annotationAdded = true;
2358 newann = sequences[i].getAnnotation()[a];
2359 newann.adjustForAlignment();
2360 newann.padAnnotation(alwidth);
2361 if (newann.graphGroup > -1)
2363 if (newann.graphGroup > -1)
2365 if (newGraphGroups.size() <= newann.graphGroup
2366 || newGraphGroups.get(newann.graphGroup) == null)
2368 for (int q = newGraphGroups
2369 .size(); q <= newann.graphGroup; q++)
2371 newGraphGroups.add(q, null);
2373 newGraphGroups.set(newann.graphGroup,
2374 Integer.valueOf(++fgroup));
2376 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2380 // annotation was duplicated earlier
2381 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2382 // take care of contact matrix too
2383 ContactMatrixI cm = sequences[i]
2384 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2387 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2391 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2399 // propagate alignment changed.
2400 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2401 if (annotationAdded)
2403 // Duplicate sequence annotation in all views.
2404 AlignmentI[] alview = this.getViewAlignments();
2405 for (int i = 0; i < sequences.length; i++)
2407 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2412 for (int avnum = 0; avnum < alview.length; avnum++)
2414 if (alview[avnum] != alignment)
2416 // duplicate in a view other than the one with input focus
2417 int avwidth = alview[avnum].getWidth() + 1;
2418 // this relies on sann being preserved after we
2419 // modify the sequence's annotation array for each duplication
2420 for (int a = 0; a < sann.length; a++)
2422 AlignmentAnnotation newann = new AlignmentAnnotation(
2424 sequences[i].addAlignmentAnnotation(newann);
2425 newann.padAnnotation(avwidth);
2426 alview[avnum].addAnnotation(newann); // annotation was
2427 // duplicated earlier
2428 // TODO JAL-1145 graphGroups are not updated for sequence
2429 // annotation added to several views. This may cause
2431 alview[avnum].setAnnotationIndex(newann, a);
2436 buildSortByAnnotationScoresMenu();
2438 viewport.firePropertyChange("alignment", null,
2439 alignment.getSequences());
2440 if (alignPanels != null)
2442 for (AlignmentPanel ap : alignPanels)
2444 ap.validateAnnotationDimensions(false);
2449 alignPanel.validateAnnotationDimensions(false);
2455 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2457 String newtitle = new String("Copied sequences");
2459 if (Desktop.jalviewClipboard != null
2460 && Desktop.jalviewClipboard[2] != null)
2462 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2463 af.viewport.setHiddenColumns(hc);
2466 // >>>This is a fix for the moment, until a better solution is
2468 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2469 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2470 .getFeatureRenderer());
2472 // TODO: maintain provenance of an alignment, rather than just make the
2473 // title a concatenation of operations.
2476 if (title.startsWith("Copied sequences"))
2482 newtitle = newtitle.concat("- from " + title);
2487 newtitle = new String("Pasted sequences");
2490 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2495 } catch (Exception ex)
2497 ex.printStackTrace();
2498 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2499 // could be anything being pasted in here
2505 protected void expand_newalign(ActionEvent e)
2509 AlignmentI alignment = AlignmentUtils
2510 .expandContext(getViewport().getAlignment(), -1);
2511 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2513 String newtitle = new String("Flanking alignment");
2515 if (Desktop.jalviewClipboard != null
2516 && Desktop.jalviewClipboard[2] != null)
2518 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2519 af.viewport.setHiddenColumns(hc);
2522 // >>>This is a fix for the moment, until a better solution is
2524 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2525 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2526 .getFeatureRenderer());
2528 // TODO: maintain provenance of an alignment, rather than just make the
2529 // title a concatenation of operations.
2531 if (title.startsWith("Copied sequences"))
2537 newtitle = newtitle.concat("- from " + title);
2541 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2543 } catch (Exception ex)
2545 ex.printStackTrace();
2546 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2547 // could be anything being pasted in here
2548 } catch (OutOfMemoryError oom)
2550 new OOMWarning("Viewing flanking region of alignment", oom);
2555 * Action Cut (delete and copy) the selected region
2558 protected void cut_actionPerformed()
2560 copy_actionPerformed();
2561 delete_actionPerformed();
2565 * Performs menu option to Delete the currently selected region
2568 protected void delete_actionPerformed()
2571 SequenceGroup sg = viewport.getSelectionGroup();
2577 Runnable okAction = () -> {
2578 SequenceI[] cut = sg.getSequences()
2579 .toArray(new SequenceI[sg.getSize()]);
2581 addHistoryItem(new EditCommand(
2582 MessageManager.getString("label.cut_sequences"), Action.CUT,
2583 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2584 viewport.getAlignment()));
2586 viewport.setSelectionGroup(null);
2587 viewport.sendSelection();
2588 viewport.getAlignment().deleteGroup(sg);
2590 viewport.firePropertyChange("alignment", null,
2591 viewport.getAlignment().getSequences());
2592 if (viewport.getAlignment().getHeight() < 1)
2596 AlignFrame.this.setClosed(true);
2597 } catch (Exception ex)
2604 * If the cut affects all sequences, prompt for confirmation
2606 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2608 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2609 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2610 if (wholeHeight && wholeWidth)
2612 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2613 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2614 Object[] options = new Object[] {
2615 MessageManager.getString("action.ok"),
2616 MessageManager.getString("action.cancel") };
2617 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2618 MessageManager.getString("label.delete_all"),
2619 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2620 options, options[0]);
2627 } catch (Exception e)
2629 e.printStackTrace();
2641 protected void deleteGroups_actionPerformed(ActionEvent e)
2643 if (avc.deleteGroups())
2645 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2646 alignPanel.updateAnnotation();
2647 alignPanel.paintAlignment(true, true);
2658 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2660 SequenceGroup sg = new SequenceGroup(
2661 viewport.getAlignment().getSequences());
2663 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2664 viewport.setSelectionGroup(sg);
2665 viewport.isSelectionGroupChanged(true);
2666 viewport.sendSelection();
2667 // JAL-2034 - should delegate to
2668 // alignPanel to decide if overview needs
2670 alignPanel.paintAlignment(false, false);
2671 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2681 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2683 if (viewport.cursorMode)
2685 alignPanel.getSeqPanel().keyboardNo1 = null;
2686 alignPanel.getSeqPanel().keyboardNo2 = null;
2688 viewport.setSelectionGroup(null);
2689 viewport.getColumnSelection().clear();
2690 viewport.setSearchResults(null);
2691 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2692 // JAL-2034 - should delegate to
2693 // alignPanel to decide if overview needs
2695 alignPanel.paintAlignment(false, false);
2696 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2697 viewport.sendSelection();
2707 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2709 SequenceGroup sg = viewport.getSelectionGroup();
2713 selectAllSequenceMenuItem_actionPerformed(null);
2718 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2720 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2722 // JAL-2034 - should delegate to
2723 // alignPanel to decide if overview needs
2726 alignPanel.paintAlignment(true, false);
2727 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2728 viewport.sendSelection();
2732 public void invertColSel_actionPerformed(ActionEvent e)
2734 viewport.invertColumnSelection();
2735 alignPanel.paintAlignment(true, false);
2736 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2737 viewport.sendSelection();
2747 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2749 trimAlignment(true);
2759 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2761 trimAlignment(false);
2764 void trimAlignment(boolean trimLeft)
2766 ColumnSelection colSel = viewport.getColumnSelection();
2769 if (!colSel.isEmpty())
2773 column = colSel.getMin();
2777 column = colSel.getMax();
2781 if (viewport.getSelectionGroup() != null)
2783 seqs = viewport.getSelectionGroup()
2784 .getSequencesAsArray(viewport.getHiddenRepSequences());
2788 seqs = viewport.getAlignment().getSequencesArray();
2791 TrimRegionCommand trimRegion;
2794 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2795 column, viewport.getAlignment());
2796 viewport.getRanges().setStartRes(0);
2800 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2801 column, viewport.getAlignment());
2804 setStatus(MessageManager.formatMessage("label.removed_columns",
2806 { Integer.valueOf(trimRegion.getSize()).toString() }));
2808 addHistoryItem(trimRegion);
2810 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2812 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2813 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2815 viewport.getAlignment().deleteGroup(sg);
2819 viewport.firePropertyChange("alignment", null,
2820 viewport.getAlignment().getSequences());
2831 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2833 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2836 if (viewport.getSelectionGroup() != null)
2838 seqs = viewport.getSelectionGroup()
2839 .getSequencesAsArray(viewport.getHiddenRepSequences());
2840 start = viewport.getSelectionGroup().getStartRes();
2841 end = viewport.getSelectionGroup().getEndRes();
2845 seqs = viewport.getAlignment().getSequencesArray();
2848 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2849 "Remove Gapped Columns", seqs, start, end,
2850 viewport.getAlignment());
2852 addHistoryItem(removeGapCols);
2854 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2856 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2858 // This is to maintain viewport position on first residue
2859 // of first sequence
2860 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2861 ViewportRanges ranges = viewport.getRanges();
2862 int startRes = seq.findPosition(ranges.getStartRes());
2863 // ShiftList shifts;
2864 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2865 // edit.alColumnChanges=shifts.getInverse();
2866 // if (viewport.hasHiddenColumns)
2867 // viewport.getColumnSelection().compensateForEdits(shifts);
2868 ranges.setStartRes(seq.findIndex(startRes) - 1);
2869 viewport.firePropertyChange("alignment", null,
2870 viewport.getAlignment().getSequences());
2881 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2883 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2886 if (viewport.getSelectionGroup() != null)
2888 seqs = viewport.getSelectionGroup()
2889 .getSequencesAsArray(viewport.getHiddenRepSequences());
2890 start = viewport.getSelectionGroup().getStartRes();
2891 end = viewport.getSelectionGroup().getEndRes();
2895 seqs = viewport.getAlignment().getSequencesArray();
2898 // This is to maintain viewport position on first residue
2899 // of first sequence
2900 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2901 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2903 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2904 viewport.getAlignment()));
2906 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2908 viewport.firePropertyChange("alignment", null,
2909 viewport.getAlignment().getSequences());
2920 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2922 viewport.setPadGaps(padGapsMenuitem.isSelected());
2923 viewport.firePropertyChange("alignment", null,
2924 viewport.getAlignment().getSequences());
2928 * Opens a Finder dialog
2933 public void findMenuItem_actionPerformed(ActionEvent e)
2935 new Finder(alignPanel, false, null);
2939 * Create a new view of the current alignment.
2942 public void newView_actionPerformed(ActionEvent e)
2944 newView(null, true);
2948 * Creates and shows a new view of the current alignment.
2951 * title of newly created view; if null, one will be generated
2952 * @param copyAnnotation
2953 * if true then duplicate all annnotation, groups and settings
2954 * @return new alignment panel, already displayed.
2956 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2959 * Create a new AlignmentPanel (with its own, new Viewport)
2961 AlignmentPanel newap = new jalview.project.Jalview2XML()
2962 .copyAlignPanel(alignPanel);
2963 if (!copyAnnotation)
2966 * remove all groups and annotation except for the automatic stuff
2968 newap.av.getAlignment().deleteAllGroups();
2969 newap.av.getAlignment().deleteAllAnnotations(false);
2972 newap.av.setGatherViewsHere(false);
2974 if (viewport.getViewName() == null)
2976 viewport.setViewName(
2977 MessageManager.getString("label.view_name_original"));
2981 * Views share the same edits undo and redo stacks
2983 newap.av.setHistoryList(viewport.getHistoryList());
2984 newap.av.setRedoList(viewport.getRedoList());
2987 * copy any visualisation settings that are not saved in the project
2989 newap.av.setColourAppliesToAllGroups(
2990 viewport.getColourAppliesToAllGroups());
2993 * Views share the same mappings; need to deregister any new mappings
2994 * created by copyAlignPanel, and register the new reference to the shared
2997 newap.av.replaceMappings(viewport.getAlignment());
3000 * start up cDNA consensus (if applicable) now mappings are in place
3002 if (newap.av.initComplementConsensus())
3004 newap.refresh(true); // adjust layout of annotations
3007 newap.av.setViewName(getNewViewName(viewTitle));
3009 addAlignmentPanel(newap, true);
3010 newap.alignmentChanged();
3012 if (alignPanels.size() == 2)
3014 viewport.setGatherViewsHere(true);
3016 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3022 * Make a new name for the view, ensuring it is unique within the current
3023 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3024 * these now use viewId. Unique view names are still desirable for usability.)
3029 protected String getNewViewName(String viewTitle)
3031 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3032 boolean addFirstIndex = false;
3033 if (viewTitle == null || viewTitle.trim().length() == 0)
3035 viewTitle = MessageManager.getString("action.view");
3036 addFirstIndex = true;
3040 index = 1;// we count from 1 if given a specific name
3042 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3044 List<Component> comps = PaintRefresher.components
3045 .get(viewport.getSequenceSetId());
3047 List<String> existingNames = getExistingViewNames(comps);
3049 while (existingNames.contains(newViewName))
3051 newViewName = viewTitle + " " + (++index);
3057 * Returns a list of distinct view names found in the given list of
3058 * components. View names are held on the viewport of an AlignmentPanel.
3063 protected List<String> getExistingViewNames(List<Component> comps)
3065 List<String> existingNames = new ArrayList<>();
3066 for (Component comp : comps)
3068 if (comp instanceof AlignmentPanel)
3070 AlignmentPanel ap = (AlignmentPanel) comp;
3071 if (!existingNames.contains(ap.av.getViewName()))
3073 existingNames.add(ap.av.getViewName());
3077 return existingNames;
3081 * Explode tabbed views into separate windows.
3084 public void expandViews_actionPerformed(ActionEvent e)
3086 Desktop.explodeViews(this);
3090 * Gather views in separate windows back into a tabbed presentation.
3093 public void gatherViews_actionPerformed(ActionEvent e)
3095 Desktop.instance.gatherViews(this);
3105 public void font_actionPerformed(ActionEvent e)
3107 new FontChooser(alignPanel);
3117 protected void seqLimit_actionPerformed(ActionEvent e)
3119 viewport.setShowJVSuffix(seqLimits.isSelected());
3121 alignPanel.getIdPanel().getIdCanvas()
3122 .setPreferredSize(alignPanel.calculateIdWidth());
3123 alignPanel.paintAlignment(true, false);
3127 public void idRightAlign_actionPerformed(ActionEvent e)
3129 viewport.setRightAlignIds(idRightAlign.isSelected());
3130 alignPanel.paintAlignment(false, false);
3134 public void centreColumnLabels_actionPerformed(ActionEvent e)
3136 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3137 alignPanel.paintAlignment(false, false);
3143 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3146 protected void followHighlight_actionPerformed()
3149 * Set the 'follow' flag on the Viewport (and scroll to position if now
3152 final boolean state = this.followHighlightMenuItem.getState();
3153 viewport.setFollowHighlight(state);
3156 alignPanel.scrollToPosition(viewport.getSearchResults());
3167 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3169 viewport.setColourText(colourTextMenuItem.isSelected());
3170 alignPanel.paintAlignment(false, false);
3180 public void wrapMenuItem_actionPerformed(ActionEvent e)
3182 scaleAbove.setVisible(wrapMenuItem.isSelected());
3183 scaleLeft.setVisible(wrapMenuItem.isSelected());
3184 scaleRight.setVisible(wrapMenuItem.isSelected());
3185 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3186 alignPanel.updateLayout();
3190 public void showAllSeqs_actionPerformed(ActionEvent e)
3192 viewport.showAllHiddenSeqs();
3196 public void showAllColumns_actionPerformed(ActionEvent e)
3198 viewport.showAllHiddenColumns();
3199 alignPanel.paintAlignment(true, true);
3200 viewport.sendSelection();
3204 public void hideSelSequences_actionPerformed(ActionEvent e)
3206 viewport.hideAllSelectedSeqs();
3210 * called by key handler and the hide all/show all menu items
3215 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3218 boolean hide = false;
3219 SequenceGroup sg = viewport.getSelectionGroup();
3220 if (!toggleSeqs && !toggleCols)
3222 // Hide everything by the current selection - this is a hack - we do the
3223 // invert and then hide
3224 // first check that there will be visible columns after the invert.
3225 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3226 && sg.getStartRes() <= sg.getEndRes()))
3228 // now invert the sequence set, if required - empty selection implies
3229 // that no hiding is required.
3232 invertSequenceMenuItem_actionPerformed(null);
3233 sg = viewport.getSelectionGroup();
3237 viewport.expandColSelection(sg, true);
3238 // finally invert the column selection and get the new sequence
3240 invertColSel_actionPerformed(null);
3247 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3249 hideSelSequences_actionPerformed(null);
3252 else if (!(toggleCols && viewport.hasSelectedColumns()))
3254 showAllSeqs_actionPerformed(null);
3260 if (viewport.hasSelectedColumns())
3262 hideSelColumns_actionPerformed(null);
3265 viewport.setSelectionGroup(sg);
3270 showAllColumns_actionPerformed(null);
3279 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3280 * event.ActionEvent)
3283 public void hideAllButSelection_actionPerformed(ActionEvent e)
3285 toggleHiddenRegions(false, false);
3286 viewport.sendSelection();
3293 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3297 public void hideAllSelection_actionPerformed(ActionEvent e)
3299 SequenceGroup sg = viewport.getSelectionGroup();
3300 viewport.expandColSelection(sg, false);
3301 viewport.hideAllSelectedSeqs();
3302 viewport.hideSelectedColumns();
3303 alignPanel.updateLayout();
3304 alignPanel.paintAlignment(true, true);
3305 viewport.sendSelection();
3312 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3316 public void showAllhidden_actionPerformed(ActionEvent e)
3318 viewport.showAllHiddenColumns();
3319 viewport.showAllHiddenSeqs();
3320 alignPanel.paintAlignment(true, true);
3321 viewport.sendSelection();
3325 public void hideSelColumns_actionPerformed(ActionEvent e)
3327 viewport.hideSelectedColumns();
3328 alignPanel.updateLayout();
3329 alignPanel.paintAlignment(true, true);
3330 viewport.sendSelection();
3334 public void hiddenMarkers_actionPerformed(ActionEvent e)
3336 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3347 protected void scaleAbove_actionPerformed(ActionEvent e)
3349 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3350 alignPanel.updateLayout();
3351 alignPanel.paintAlignment(true, false);
3361 protected void scaleLeft_actionPerformed(ActionEvent e)
3363 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3364 alignPanel.updateLayout();
3365 alignPanel.paintAlignment(true, false);
3375 protected void scaleRight_actionPerformed(ActionEvent e)
3377 viewport.setScaleRightWrapped(scaleRight.isSelected());
3378 alignPanel.updateLayout();
3379 alignPanel.paintAlignment(true, false);
3389 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3391 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3392 alignPanel.paintAlignment(false, false);
3402 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3404 viewport.setShowText(viewTextMenuItem.isSelected());
3405 alignPanel.paintAlignment(false, false);
3415 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3417 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3418 alignPanel.paintAlignment(false, false);
3421 public FeatureSettings featureSettings;
3424 public FeatureSettingsControllerI getFeatureSettingsUI()
3426 return featureSettings;
3430 public void featureSettings_actionPerformed(ActionEvent e)
3432 showFeatureSettingsUI();
3436 public FeatureSettingsControllerI showFeatureSettingsUI()
3438 if (featureSettings != null)
3440 featureSettings.closeOldSettings();
3441 featureSettings = null;
3443 if (!showSeqFeatures.isSelected())
3445 // make sure features are actually displayed
3446 showSeqFeatures.setSelected(true);
3447 showSeqFeatures_actionPerformed(null);
3449 featureSettings = new FeatureSettings(this);
3450 return featureSettings;
3454 * Set or clear 'Show Sequence Features'
3460 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3462 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3463 alignPanel.paintAlignment(true, true);
3467 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3468 * the annotations panel as a whole.
3470 * The options to show/hide all annotations should be enabled when the panel
3471 * is shown, and disabled when the panel is hidden.
3476 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3478 final boolean setVisible = annotationPanelMenuItem.isSelected();
3479 viewport.setShowAnnotation(setVisible);
3480 this.showAllSeqAnnotations.setEnabled(setVisible);
3481 this.hideAllSeqAnnotations.setEnabled(setVisible);
3482 this.showAllAlAnnotations.setEnabled(setVisible);
3483 this.hideAllAlAnnotations.setEnabled(setVisible);
3484 alignPanel.updateLayout();
3488 public void alignmentProperties()
3491 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3494 String content = MessageManager.formatMessage("label.html_content",
3496 { contents.toString() });
3499 if (Platform.isJS())
3501 JLabel textLabel = new JLabel();
3502 textLabel.setText(content);
3503 textLabel.setBackground(Color.WHITE);
3505 pane = new JPanel(new BorderLayout());
3506 ((JPanel) pane).setOpaque(true);
3507 pane.setBackground(Color.WHITE);
3508 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3517 JEditorPane editPane = new JEditorPane("text/html", "");
3518 editPane.setEditable(false);
3519 editPane.setText(content);
3523 JInternalFrame frame = new JInternalFrame();
3525 frame.getContentPane().add(new JScrollPane(pane));
3527 Desktop.addInternalFrame(frame, MessageManager
3528 .formatMessage("label.alignment_properties", new Object[]
3529 { getTitle() }), 500, 400);
3533 * Opens an Overview panel for the alignment, unless one is open already
3538 public void overviewMenuItem_actionPerformed(ActionEvent e)
3540 boolean showHiddenRegions = Cache
3541 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3542 openOverviewPanel(showHiddenRegions);
3545 public OverviewPanel openOverviewPanel(boolean showHidden)
3547 if (alignPanel.overviewPanel != null)
3549 return alignPanel.overviewPanel;
3551 JInternalFrame frame = new JInternalFrame();
3552 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3554 frame.setContentPane(overview);
3555 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3556 frame.getHeight(), true, true);
3557 frame.setFrameIcon(null);
3559 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3560 final AlignmentPanel thePanel = this.alignPanel;
3561 frame.addInternalFrameListener(
3562 new javax.swing.event.InternalFrameAdapter()
3565 public void internalFrameClosed(
3566 javax.swing.event.InternalFrameEvent evt)
3569 thePanel.setOverviewPanel(null);
3572 if (getKeyListeners().length > 0)
3574 frame.addKeyListener(getKeyListeners()[0]);
3577 alignPanel.setOverviewPanel(overview);
3578 alignPanel.setOverviewTitle(this);
3584 public void textColour_actionPerformed()
3586 new TextColourChooser().chooseColour(alignPanel, null);
3590 * public void covariationColour_actionPerformed() {
3592 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3596 public void annotationColour_actionPerformed()
3598 new AnnotationColourChooser(viewport, alignPanel);
3602 public void annotationColumn_actionPerformed(ActionEvent e)
3604 new AnnotationColumnChooser(viewport, alignPanel);
3608 * Action on the user checking or unchecking the option to apply the selected
3609 * colour scheme to all groups. If unchecked, groups may have their own
3610 * independent colour schemes.
3615 public void applyToAllGroups_actionPerformed(boolean selected)
3617 viewport.setColourAppliesToAllGroups(selected);
3621 * Action on user selecting a colour from the colour menu
3624 * the name (not the menu item label!) of the colour scheme
3627 public void changeColour_actionPerformed(String name)
3630 * 'User Defined' opens a panel to configure or load a
3631 * user-defined colour scheme
3633 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3635 new UserDefinedColours(alignPanel);
3640 * otherwise set the chosen colour scheme (or null for 'None')
3642 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3643 viewport, viewport.getAlignment(),
3644 viewport.getHiddenRepSequences());
3649 * Actions on setting or changing the alignment colour scheme
3654 public void changeColour(ColourSchemeI cs)
3656 // TODO: pull up to controller method
3657 ColourMenuHelper.setColourSelected(colourMenu, cs);
3659 viewport.setGlobalColourScheme(cs);
3661 alignPanel.paintAlignment(true, true);
3665 * Show the PID threshold slider panel
3668 protected void modifyPID_actionPerformed()
3670 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3671 alignPanel.getViewName());
3672 SliderPanel.showPIDSlider();
3676 * Show the Conservation slider panel
3679 protected void modifyConservation_actionPerformed()
3681 SliderPanel.setConservationSlider(alignPanel,
3682 viewport.getResidueShading(), alignPanel.getViewName());
3683 SliderPanel.showConservationSlider();
3687 * Action on selecting or deselecting (Colour) By Conservation
3690 public void conservationMenuItem_actionPerformed(boolean selected)
3692 modifyConservation.setEnabled(selected);
3693 viewport.setConservationSelected(selected);
3694 viewport.getResidueShading().setConservationApplied(selected);
3696 changeColour(viewport.getGlobalColourScheme());
3699 modifyConservation_actionPerformed();
3703 SliderPanel.hideConservationSlider();
3708 * Action on selecting or deselecting (Colour) Above PID Threshold
3711 public void abovePIDThreshold_actionPerformed(boolean selected)
3713 modifyPID.setEnabled(selected);
3714 viewport.setAbovePIDThreshold(selected);
3717 viewport.getResidueShading().setThreshold(0,
3718 viewport.isIgnoreGapsConsensus());
3721 changeColour(viewport.getGlobalColourScheme());
3724 modifyPID_actionPerformed();
3728 SliderPanel.hidePIDSlider();
3739 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3741 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3742 AlignmentSorter.sortByPID(viewport.getAlignment(),
3743 viewport.getAlignment().getSequenceAt(0));
3744 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3745 viewport.getAlignment()));
3746 alignPanel.paintAlignment(true, false);
3756 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3758 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3759 AlignmentSorter.sortByID(viewport.getAlignment());
3761 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3762 alignPanel.paintAlignment(true, false);
3772 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3774 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3775 AlignmentSorter.sortByLength(viewport.getAlignment());
3776 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3777 viewport.getAlignment()));
3778 alignPanel.paintAlignment(true, false);
3788 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3790 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3791 AlignmentSorter.sortByGroup(viewport.getAlignment());
3792 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3793 viewport.getAlignment()));
3795 alignPanel.paintAlignment(true, false);
3805 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3807 new RedundancyPanel(alignPanel, this);
3817 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3819 if ((viewport.getSelectionGroup() == null)
3820 || (viewport.getSelectionGroup().getSize() < 2))
3822 JvOptionPane.showInternalMessageDialog(this,
3823 MessageManager.getString(
3824 "label.you_must_select_least_two_sequences"),
3825 MessageManager.getString("label.invalid_selection"),
3826 JvOptionPane.WARNING_MESSAGE);
3830 JInternalFrame frame = new JInternalFrame();
3831 frame.setContentPane(new PairwiseAlignPanel(viewport));
3832 Desktop.addInternalFrame(frame,
3833 MessageManager.getString("action.pairwise_alignment"), 600,
3839 public void autoCalculate_actionPerformed(ActionEvent e)
3841 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3842 if (viewport.autoCalculateConsensus)
3844 viewport.firePropertyChange("alignment", null,
3845 viewport.getAlignment().getSequences());
3850 public void sortByTreeOption_actionPerformed(ActionEvent e)
3852 viewport.sortByTree = sortByTree.isSelected();
3856 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3858 viewport.followSelection = listenToViewSelections.isSelected();
3862 * Constructs a tree panel and adds it to the desktop
3865 * tree type (NJ or AV)
3867 * name of score model used to compute the tree
3869 * parameters for the distance or similarity calculation
3871 void newTreePanel(String type, String modelName,
3872 SimilarityParamsI options)
3874 String frameTitle = "";
3877 boolean onSelection = false;
3878 if (viewport.getSelectionGroup() != null
3879 && viewport.getSelectionGroup().getSize() > 0)
3881 SequenceGroup sg = viewport.getSelectionGroup();
3883 /* Decide if the selection is a column region */
3884 for (SequenceI _s : sg.getSequences())
3886 if (_s.getLength() < sg.getEndRes())
3888 JvOptionPane.showMessageDialog(Desktop.desktop,
3889 MessageManager.getString(
3890 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3891 MessageManager.getString(
3892 "label.sequences_selection_not_aligned"),
3893 JvOptionPane.WARNING_MESSAGE);
3902 if (viewport.getAlignment().getHeight() < 2)
3908 tp = new TreePanel(alignPanel, type, modelName, options);
3909 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3911 frameTitle += " from ";
3913 if (viewport.getViewName() != null)
3915 frameTitle += viewport.getViewName() + " of ";
3918 frameTitle += this.title;
3920 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3931 public void addSortByOrderMenuItem(String title,
3932 final AlignmentOrder order)
3934 final JMenuItem item = new JMenuItem(MessageManager
3935 .formatMessage("action.by_title_param", new Object[]
3938 item.addActionListener(new java.awt.event.ActionListener()
3941 public void actionPerformed(ActionEvent e)
3943 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3945 // TODO: JBPNote - have to map order entries to curent SequenceI
3947 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3949 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3950 viewport.getAlignment()));
3952 alignPanel.paintAlignment(true, false);
3958 * Add a new sort by annotation score menu item
3961 * the menu to add the option to
3963 * the label used to retrieve scores for each sequence on the
3966 public void addSortByAnnotScoreMenuItem(JMenu sort,
3967 final String scoreLabel)
3969 final JMenuItem item = new JMenuItem(scoreLabel);
3971 item.addActionListener(new java.awt.event.ActionListener()
3974 public void actionPerformed(ActionEvent e)
3976 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3977 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3978 viewport.getAlignment());// ,viewport.getSelectionGroup());
3979 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3980 viewport.getAlignment()));
3981 alignPanel.paintAlignment(true, false);
3987 * last hash for alignment's annotation array - used to minimise cost of
3990 protected int _annotationScoreVectorHash;
3993 * search the alignment and rebuild the sort by annotation score submenu the
3994 * last alignment annotation vector hash is stored to minimize cost of
3995 * rebuilding in subsequence calls.
3999 public void buildSortByAnnotationScoresMenu()
4001 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4006 if (viewport.getAlignment().getAlignmentAnnotation()
4007 .hashCode() != _annotationScoreVectorHash)
4009 sortByAnnotScore.removeAll();
4010 // almost certainly a quicker way to do this - but we keep it simple
4011 Hashtable<String, String> scoreSorts = new Hashtable<>();
4012 AlignmentAnnotation aann[];
4013 for (SequenceI sqa : viewport.getAlignment().getSequences())
4015 aann = sqa.getAnnotation();
4016 for (int i = 0; aann != null && i < aann.length; i++)
4018 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4020 scoreSorts.put(aann[i].label, aann[i].label);
4024 Enumeration<String> labels = scoreSorts.keys();
4025 while (labels.hasMoreElements())
4027 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4029 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4032 _annotationScoreVectorHash = viewport.getAlignment()
4033 .getAlignmentAnnotation().hashCode();
4038 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4039 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4040 * call. Listeners are added to remove the menu item when the treePanel is
4041 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4045 public void buildTreeSortMenu()
4047 sortByTreeMenu.removeAll();
4049 List<Component> comps = PaintRefresher.components
4050 .get(viewport.getSequenceSetId());
4051 List<TreePanel> treePanels = new ArrayList<>();
4052 for (Component comp : comps)
4054 if (comp instanceof TreePanel)
4056 treePanels.add((TreePanel) comp);
4060 if (treePanels.size() < 1)
4062 sortByTreeMenu.setVisible(false);
4066 sortByTreeMenu.setVisible(true);
4068 for (final TreePanel tp : treePanels)
4070 final JMenuItem item = new JMenuItem(tp.getTitle());
4071 item.addActionListener(new java.awt.event.ActionListener()
4074 public void actionPerformed(ActionEvent e)
4076 tp.sortByTree_actionPerformed();
4077 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4082 sortByTreeMenu.add(item);
4086 public boolean sortBy(AlignmentOrder alorder, String undoname)
4088 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4089 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4090 if (undoname != null)
4092 addHistoryItem(new OrderCommand(undoname, oldOrder,
4093 viewport.getAlignment()));
4095 alignPanel.paintAlignment(true, false);
4100 * Work out whether the whole set of sequences or just the selected set will
4101 * be submitted for multiple alignment.
4104 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4106 // Now, check we have enough sequences
4107 AlignmentView msa = null;
4109 if ((viewport.getSelectionGroup() != null)
4110 && (viewport.getSelectionGroup().getSize() > 1))
4112 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4113 // some common interface!
4115 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4116 * SequenceI[sz = seqs.getSize(false)];
4118 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4119 * seqs.getSequenceAt(i); }
4121 msa = viewport.getAlignmentView(true);
4123 else if (viewport.getSelectionGroup() != null
4124 && viewport.getSelectionGroup().getSize() == 1)
4126 int option = JvOptionPane.showConfirmDialog(this,
4127 MessageManager.getString("warn.oneseq_msainput_selection"),
4128 MessageManager.getString("label.invalid_selection"),
4129 JvOptionPane.OK_CANCEL_OPTION);
4130 if (option == JvOptionPane.OK_OPTION)
4132 msa = viewport.getAlignmentView(false);
4137 msa = viewport.getAlignmentView(false);
4143 * Decides what is submitted to a secondary structure prediction service: the
4144 * first sequence in the alignment, or in the current selection, or, if the
4145 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4146 * region or the whole alignment. (where the first sequence in the set is the
4147 * one that the prediction will be for).
4149 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4151 AlignmentView seqs = null;
4153 if ((viewport.getSelectionGroup() != null)
4154 && (viewport.getSelectionGroup().getSize() > 0))
4156 seqs = viewport.getAlignmentView(true);
4160 seqs = viewport.getAlignmentView(false);
4162 // limit sequences - JBPNote in future - could spawn multiple prediction
4164 // TODO: viewport.getAlignment().isAligned is a global state - the local
4165 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4166 if (!viewport.getAlignment().isAligned(false))
4168 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4169 // TODO: if seqs.getSequences().length>1 then should really have warned
4183 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4185 // Pick the tree file
4186 JalviewFileChooser chooser = new JalviewFileChooser(
4187 Cache.getProperty("LAST_DIRECTORY"));
4188 chooser.setFileView(new JalviewFileView());
4189 chooser.setDialogTitle(
4190 MessageManager.getString("label.select_newick_like_tree_file"));
4191 chooser.setToolTipText(
4192 MessageManager.getString("label.load_tree_file"));
4194 chooser.setResponseHandler(0, () -> {
4195 String filePath = chooser.getSelectedFile().getPath();
4196 Cache.setProperty("LAST_DIRECTORY", filePath);
4197 NewickFile fin = null;
4200 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4201 DataSourceType.FILE));
4202 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4203 } catch (Exception ex)
4205 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4206 MessageManager.getString("label.problem_reading_tree_file"),
4207 JvOptionPane.WARNING_MESSAGE);
4208 ex.printStackTrace();
4210 if (fin != null && fin.hasWarningMessage())
4212 JvOptionPane.showMessageDialog(Desktop.desktop,
4213 fin.getWarningMessage(),
4215 .getString("label.possible_problem_with_tree_file"),
4216 JvOptionPane.WARNING_MESSAGE);
4219 chooser.showOpenDialog(this);
4222 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4224 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4227 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4228 int h, int x, int y)
4230 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4234 * Add a treeviewer for the tree extracted from a Newick file object to the
4235 * current alignment view
4242 * Associated alignment input data (or null)
4251 * @return TreePanel handle
4253 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4254 AlignmentView input, int w, int h, int x, int y)
4256 TreePanel tp = null;
4262 if (nf.getTree() != null)
4264 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4270 tp.setLocation(x, y);
4273 Desktop.addInternalFrame(tp, treeTitle, w, h);
4275 } catch (Exception ex)
4277 ex.printStackTrace();
4283 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4286 int w = 400, h = 500;
4290 NewickFile fin = new NewickFile(
4291 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4292 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4293 + (aa.sequenceRef != null
4294 ? (" for " + aa.sequenceRef.getDisplayId(false))
4297 showColumnWiseTree(fin, aa, title, w, h, x, y);
4298 } catch (Throwable xx)
4300 Console.error("Unexpected exception showing tree for contact matrix",
4305 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4306 String treeTitle, int w, int h, int x, int y)
4311 if (nf.getTree() == null)
4315 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4321 tp.setLocation(x, y);
4324 Desktop.addInternalFrame(tp, treeTitle, w, h);
4326 } catch (Throwable xx)
4328 Console.error("Unexpected exception showing tree for contact matrix",
4334 private boolean buildingMenu = false;
4337 * Generates menu items and listener event actions for web service clients
4340 public void BuildWebServiceMenu()
4342 while (buildingMenu)
4346 jalview.bin.Console.errPrintln("Waiting for building menu to finish.");
4348 } catch (Exception e)
4352 final AlignFrame me = this;
4353 buildingMenu = true;
4354 new Thread(new Runnable()
4359 final List<JMenuItem> legacyItems = new ArrayList<>();
4362 // jalview.bin.Console.errPrintln("Building ws menu again "
4363 // + Thread.currentThread());
4364 // TODO: add support for context dependent disabling of services based
4366 // alignment and current selection
4367 // TODO: add additional serviceHandle parameter to specify abstract
4369 // class independently of AbstractName
4370 // TODO: add in rediscovery GUI function to restart discoverer
4371 // TODO: group services by location as well as function and/or
4373 // object broker mechanism.
4374 final Vector<JMenu> wsmenu = new Vector<>();
4375 final IProgressIndicator af = me;
4378 * do not i18n these strings - they are hard-coded in class
4379 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4380 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4382 final JMenu msawsmenu = new JMenu("Alignment");
4383 final JMenu secstrmenu = new JMenu(
4384 "Secondary Structure Prediction");
4385 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4386 final JMenu analymenu = new JMenu("Analysis");
4387 final JMenu dismenu = new JMenu("Protein Disorder");
4388 // JAL-940 - only show secondary structure prediction services from
4389 // the legacy server
4390 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4392 Discoverer.services != null && (Discoverer.services.size() > 0))
4394 // TODO: refactor to allow list of AbstractName/Handler bindings to
4396 // stored or retrieved from elsewhere
4397 // No MSAWS used any more:
4398 // Vector msaws = null; // (Vector)
4399 // Discoverer.services.get("MsaWS");
4400 Vector<ServiceHandle> secstrpr = Discoverer.services
4402 if (secstrpr != null)
4404 // Add any secondary structure prediction services
4405 for (int i = 0, j = secstrpr.size(); i < j; i++)
4407 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4408 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4409 .getServiceClient(sh);
4410 int p = secstrmenu.getItemCount();
4411 impl.attachWSMenuEntry(secstrmenu, me);
4412 int q = secstrmenu.getItemCount();
4413 for (int litm = p; litm < q; litm++)
4415 legacyItems.add(secstrmenu.getItem(litm));
4421 // Add all submenus in the order they should appear on the web
4423 wsmenu.add(msawsmenu);
4424 wsmenu.add(secstrmenu);
4425 wsmenu.add(dismenu);
4426 wsmenu.add(analymenu);
4427 // No search services yet
4428 // wsmenu.add(seqsrchmenu);
4430 javax.swing.SwingUtilities.invokeLater(new Runnable()
4437 webService.removeAll();
4438 // first, add discovered services onto the webservices menu
4439 if (wsmenu.size() > 0)
4441 for (int i = 0, j = wsmenu.size(); i < j; i++)
4443 webService.add(wsmenu.get(i));
4448 webService.add(me.webServiceNoServices);
4450 // TODO: move into separate menu builder class.
4452 // logic for 2.11.1.4 is
4453 // always look to see if there is a discover. if there isn't
4454 // we can't show any Jws2 services
4455 // if there are services available, show them - regardless of
4456 // the 'show JWS2 preference'
4457 // if the discoverer is running then say so
4458 // otherwise offer to trigger discovery if 'show JWS2' is not
4460 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4461 if (jws2servs != null)
4463 if (jws2servs.hasServices())
4465 jws2servs.attachWSMenuEntry(webService, me);
4466 for (Jws2Instance sv : jws2servs.getServices())
4468 if (sv.description.toLowerCase(Locale.ROOT)
4471 for (JMenuItem jmi : legacyItems)
4473 jmi.setVisible(false);
4479 if (jws2servs.isRunning())
4481 JMenuItem tm = new JMenuItem(
4482 "Still discovering JABA Services");
4483 tm.setEnabled(false);
4486 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4488 JMenuItem enableJws2 = new JMenuItem(
4489 "Discover Web Services");
4490 enableJws2.setToolTipText(
4491 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4492 enableJws2.setEnabled(true);
4493 enableJws2.addActionListener(new ActionListener()
4497 public void actionPerformed(ActionEvent e)
4499 // start service discoverer, but ignore preference
4500 Desktop.instance.startServiceDiscovery(false,
4504 webService.add(enableJws2);
4508 build_urlServiceMenu(me.webService);
4509 build_fetchdbmenu(webService);
4510 for (JMenu item : wsmenu)
4512 if (item.getItemCount() == 0)
4514 item.setEnabled(false);
4518 item.setEnabled(true);
4521 } catch (Exception e)
4524 "Exception during web service menu building process.",
4529 } catch (Exception e)
4532 buildingMenu = false;
4539 * construct any groupURL type service menu entries.
4543 protected void build_urlServiceMenu(JMenu webService)
4545 // TODO: remove this code when 2.7 is released
4546 // DEBUG - alignmentView
4548 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4549 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4551 * @Override public void actionPerformed(ActionEvent e) {
4552 * jalview.datamodel.AlignmentView
4553 * .testSelectionViews(af.viewport.getAlignment(),
4554 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4556 * }); webService.add(testAlView);
4558 // TODO: refactor to RestClient discoverer and merge menu entries for
4559 // rest-style services with other types of analysis/calculation service
4560 // SHmmr test client - still being implemented.
4561 // DEBUG - alignmentView
4563 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4566 client.attachWSMenuEntry(
4567 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4573 * Searches the alignment sequences for xRefs and builds the Show
4574 * Cross-References menu (formerly called Show Products), with database
4575 * sources for which cross-references are found (protein sources for a
4576 * nucleotide alignment and vice versa)
4578 * @return true if Show Cross-references menu should be enabled
4580 public boolean canShowProducts()
4582 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4583 AlignmentI dataset = viewport.getAlignment().getDataset();
4585 showProducts.removeAll();
4586 final boolean dna = viewport.getAlignment().isNucleotide();
4588 if (seqs == null || seqs.length == 0)
4590 // nothing to see here.
4594 boolean showp = false;
4597 List<String> ptypes = new CrossRef(seqs, dataset)
4598 .findXrefSourcesForSequences(dna);
4600 for (final String source : ptypes)
4603 final AlignFrame af = this;
4604 JMenuItem xtype = new JMenuItem(source);
4605 xtype.addActionListener(new ActionListener()
4608 public void actionPerformed(ActionEvent e)
4610 showProductsFor(af.viewport.getSequenceSelection(), dna,
4614 showProducts.add(xtype);
4616 showProducts.setVisible(showp);
4617 showProducts.setEnabled(showp);
4618 } catch (Exception e)
4621 "canShowProducts threw an exception - please report to help@jalview.org",
4629 * Finds and displays cross-references for the selected sequences (protein
4630 * products for nucleotide sequences, dna coding sequences for peptides).
4633 * the sequences to show cross-references for
4635 * true if from a nucleotide alignment (so showing proteins)
4637 * the database to show cross-references for
4639 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4640 final String source)
4642 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4647 * Construct and display a new frame containing the translation of this
4648 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4651 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4653 AlignmentI al = null;
4656 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4658 al = dna.translateCdna(codeTable);
4659 } catch (Exception ex)
4661 Console.error("Exception during translation. Please report this !",
4663 final String msg = MessageManager.getString(
4664 "label.error_when_translating_sequences_submit_bug_report");
4665 final String errorTitle = MessageManager
4666 .getString("label.implementation_error")
4667 + MessageManager.getString("label.translation_failed");
4668 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4669 JvOptionPane.ERROR_MESSAGE);
4672 if (al == null || al.getHeight() == 0)
4674 final String msg = MessageManager.getString(
4675 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4676 final String errorTitle = MessageManager
4677 .getString("label.translation_failed");
4678 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4679 JvOptionPane.WARNING_MESSAGE);
4683 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4684 af.setFileFormat(this.currentFileFormat);
4685 final String newTitle = MessageManager
4686 .formatMessage("label.translation_of_params", new Object[]
4687 { this.getTitle(), codeTable.getId() });
4688 af.setTitle(newTitle);
4689 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4691 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4692 viewport.openSplitFrame(af, new Alignment(seqs));
4696 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4703 * Set the file format
4707 public void setFileFormat(FileFormatI format)
4709 this.currentFileFormat = format;
4713 * Try to load a features file onto the alignment.
4716 * contents or path to retrieve file or a File object
4718 * access mode of file (see jalview.io.AlignFile)
4719 * @return true if features file was parsed correctly.
4721 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4724 return avc.parseFeaturesFile(file, sourceType,
4725 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4730 public void refreshFeatureUI(boolean enableIfNecessary)
4732 // note - currently this is only still here rather than in the controller
4733 // because of the featureSettings hard reference that is yet to be
4735 if (enableIfNecessary)
4737 viewport.setShowSequenceFeatures(true);
4738 showSeqFeatures.setSelected(true);
4744 public void dragEnter(DropTargetDragEvent evt)
4749 public void dragExit(DropTargetEvent evt)
4754 public void dragOver(DropTargetDragEvent evt)
4759 public void dropActionChanged(DropTargetDragEvent evt)
4764 public void drop(DropTargetDropEvent evt)
4766 // JAL-1552 - acceptDrop required before getTransferable call for
4767 // Java's Transferable for native dnd
4768 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4769 Transferable t = evt.getTransferable();
4771 final AlignFrame thisaf = this;
4772 final List<Object> files = new ArrayList<>();
4773 List<DataSourceType> protocols = new ArrayList<>();
4777 Desktop.transferFromDropTarget(files, protocols, evt, t);
4778 } catch (Exception e)
4780 e.printStackTrace();
4784 new Thread(new Runnable()
4791 // check to see if any of these files have names matching sequences
4794 SequenceIdMatcher idm = new SequenceIdMatcher(
4795 viewport.getAlignment().getSequencesArray());
4797 * Object[] { String,SequenceI}
4799 ArrayList<Object[]> filesmatched = new ArrayList<>();
4800 ArrayList<Object> filesnotmatched = new ArrayList<>();
4801 for (int i = 0; i < files.size(); i++)
4804 Object file = files.get(i);
4805 String fileName = file.toString();
4807 DataSourceType protocol = (file instanceof File
4808 ? DataSourceType.FILE
4809 : FormatAdapter.checkProtocol(fileName));
4810 if (protocol == DataSourceType.FILE)
4813 if (file instanceof File)
4816 Platform.cacheFileData(fl);
4820 fl = new File(fileName);
4822 pdbfn = fl.getName();
4824 else if (protocol == DataSourceType.URL)
4826 URL url = new URL(fileName);
4827 pdbfn = url.getFile();
4829 if (pdbfn.length() > 0)
4831 // attempt to find a match in the alignment
4832 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4833 int l = 0, c = pdbfn.indexOf(".");
4834 while (mtch == null && c != -1)
4839 } while ((c = pdbfn.indexOf(".", l)) > l);
4842 pdbfn = pdbfn.substring(0, l);
4844 mtch = idm.findAllIdMatches(pdbfn);
4851 type = new IdentifyFile().identify(file, protocol);
4852 } catch (Exception ex)
4856 if (type != null && type.isStructureFile())
4858 filesmatched.add(new Object[] { file, protocol, mtch });
4862 // File wasn't named like one of the sequences or wasn't a PDB
4864 filesnotmatched.add(file);
4868 if (filesmatched.size() > 0)
4870 boolean autoAssociate = Cache
4871 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4874 String msg = MessageManager.formatMessage(
4875 "label.automatically_associate_structure_files_with_sequences_same_name",
4877 { Integer.valueOf(filesmatched.size())
4879 String ttl = MessageManager.getString(
4880 "label.automatically_associate_structure_files_by_name");
4881 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4882 ttl, JvOptionPane.YES_NO_OPTION);
4883 autoAssociate = choice == JvOptionPane.YES_OPTION;
4887 for (Object[] fm : filesmatched)
4889 // try and associate
4890 // TODO: may want to set a standard ID naming formalism for
4891 // associating PDB files which have no IDs.
4892 for (SequenceI toassoc : (SequenceI[]) fm[2])
4894 PDBEntry pe = new AssociatePdbFileWithSeq()
4895 .associatePdbWithSeq(fm[0].toString(),
4896 (DataSourceType) fm[1], toassoc, false,
4900 jalview.bin.Console.errPrintln("Associated file : "
4901 + (fm[0].toString()) + " with "
4902 + toassoc.getDisplayId(true));
4906 // TODO: do we need to update overview ? only if features are
4908 alignPanel.paintAlignment(true, false);
4914 * add declined structures as sequences
4916 for (Object[] o : filesmatched)
4918 filesnotmatched.add(o[0]);
4922 if (filesnotmatched.size() > 0)
4924 if (assocfiles > 0 && (Cache.getDefault(
4925 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4926 || JvOptionPane.showConfirmDialog(thisaf,
4927 "<html>" + MessageManager.formatMessage(
4928 "label.ignore_unmatched_dropped_files_info",
4931 filesnotmatched.size())
4934 MessageManager.getString(
4935 "label.ignore_unmatched_dropped_files"),
4936 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4940 for (Object fn : filesnotmatched)
4942 loadJalviewDataFile(fn, null, null, null);
4946 } catch (Exception ex)
4948 ex.printStackTrace();
4956 * Attempt to load a "dropped" file or URL string, by testing in turn for
4958 * <li>an Annotation file</li>
4959 * <li>a JNet file</li>
4960 * <li>a features file</li>
4961 * <li>else try to interpret as an alignment file</li>
4965 * either a filename or a URL string.
4967 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4968 FileFormatI format, SequenceI assocSeq)
4970 // BH 2018 was String file
4973 if (sourceType == null)
4975 sourceType = FormatAdapter.checkProtocol(file);
4977 // if the file isn't identified, or not positively identified as some
4978 // other filetype (PFAM is default unidentified alignment file type) then
4979 // try to parse as annotation.
4980 boolean isAnnotation = (format == null
4981 || FileFormat.Pfam.equals(format))
4982 ? new AnnotationFile().annotateAlignmentView(viewport,
4988 // first see if its a T-COFFEE score file
4989 TCoffeeScoreFile tcf = null;
4992 tcf = new TCoffeeScoreFile(file, sourceType);
4995 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4999 new TCoffeeColourScheme(viewport.getAlignment()));
5000 isAnnotation = true;
5001 setStatus(MessageManager.getString(
5002 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5006 // some problem - if no warning its probable that the ID matching
5007 // process didn't work
5008 JvOptionPane.showMessageDialog(Desktop.desktop,
5009 tcf.getWarningMessage() == null
5010 ? MessageManager.getString(
5011 "label.check_file_matches_sequence_ids_alignment")
5012 : tcf.getWarningMessage(),
5013 MessageManager.getString(
5014 "label.problem_reading_tcoffee_score_file"),
5015 JvOptionPane.WARNING_MESSAGE);
5022 } catch (Exception x)
5025 "Exception when processing data source as T-COFFEE score file",
5031 // try to see if its a JNet 'concise' style annotation file *before*
5033 // try to parse it as a features file
5036 format = new IdentifyFile().identify(file, sourceType);
5038 if (FileFormat.ScoreMatrix == format)
5040 ScoreMatrixFile sm = new ScoreMatrixFile(
5041 new FileParse(file, sourceType));
5043 // todo: i18n this message
5044 setStatus(MessageManager.formatMessage(
5045 "label.successfully_loaded_matrix",
5046 sm.getMatrixName()));
5048 else if (FileFormat.Jnet.equals(format))
5050 JPredFile predictions = new JPredFile(file, sourceType);
5051 new JnetAnnotationMaker();
5052 JnetAnnotationMaker.add_annotation(predictions,
5053 viewport.getAlignment(), 0, false);
5054 viewport.getAlignment().setupJPredAlignment();
5055 isAnnotation = true;
5057 // else if (IdentifyFile.FeaturesFile.equals(format))
5058 else if (FileFormat.Features.equals(format))
5060 if (parseFeaturesFile(file, sourceType))
5062 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5063 if (splitFrame != null)
5065 splitFrame.repaint();
5069 alignPanel.paintAlignment(true, true);
5075 new FileLoader().LoadFile(viewport, file, sourceType, format);
5082 alignPanel.adjustAnnotationHeight();
5083 viewport.updateSequenceIdColours();
5084 buildSortByAnnotationScoresMenu();
5085 alignPanel.paintAlignment(true, true);
5087 } catch (Exception ex)
5089 ex.printStackTrace();
5090 } catch (OutOfMemoryError oom)
5095 } catch (Exception x)
5100 + (sourceType != null
5101 ? (sourceType == DataSourceType.PASTE
5103 : "using " + sourceType + " from "
5107 ? "(parsing as '" + format + "' file)"
5109 oom, Desktop.desktop);
5114 * Method invoked by the ChangeListener on the tabbed pane, in other words
5115 * when a different tabbed pane is selected by the user or programmatically.
5118 public void tabSelectionChanged(int index)
5123 * update current Overview window title (if there is one)
5124 * to add view name "Original" if necessary
5126 alignPanel.setOverviewTitle(this);
5129 * switch panels and set Overview title (if there is one
5130 * because it was opened automatically)
5132 alignPanel = alignPanels.get(index);
5133 alignPanel.setOverviewTitle(this);
5135 viewport = alignPanel.av;
5136 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5137 setMenusFromViewport(viewport);
5138 if (featureSettings != null && featureSettings.isOpen()
5139 && featureSettings.fr.getViewport() != viewport)
5141 if (viewport.isShowSequenceFeatures())
5143 // refresh the featureSettings to reflect UI change
5144 showFeatureSettingsUI();
5148 // close feature settings for this view.
5149 featureSettings.close();
5156 * 'focus' any colour slider that is open to the selected viewport
5158 if (viewport.getConservationSelected())
5160 SliderPanel.setConservationSlider(alignPanel,
5161 viewport.getResidueShading(), alignPanel.getViewName());
5165 SliderPanel.hideConservationSlider();
5167 if (viewport.getAbovePIDThreshold())
5169 SliderPanel.setPIDSliderSource(alignPanel,
5170 viewport.getResidueShading(), alignPanel.getViewName());
5174 SliderPanel.hidePIDSlider();
5178 * If there is a frame linked to this one in a SplitPane, switch it to the
5179 * same view tab index. No infinite recursion of calls should happen, since
5180 * tabSelectionChanged() should not get invoked on setting the selected
5181 * index to an unchanged value. Guard against setting an invalid index
5182 * before the new view peer tab has been created.
5184 final AlignViewportI peer = viewport.getCodingComplement();
5187 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5188 .getAlignPanel().alignFrame;
5189 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5191 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5197 * On right mouse click on view tab, prompt for and set new view name.
5200 public void tabbedPane_mousePressed(MouseEvent e)
5202 if (e.isPopupTrigger())
5204 String msg = MessageManager.getString("label.enter_view_name");
5205 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5206 String reply = JvOptionPane.showInputDialog(msg, ttl);
5210 viewport.setViewName(reply);
5211 // TODO warn if reply is in getExistingViewNames()?
5212 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5217 public AlignViewport getCurrentView()
5223 * Open the dialog for regex description parsing.
5226 protected void extractScores_actionPerformed(ActionEvent e)
5228 ParseProperties pp = new jalview.analysis.ParseProperties(
5229 viewport.getAlignment());
5230 // TODO: verify regex and introduce GUI dialog for version 2.5
5231 // if (pp.getScoresFromDescription("col", "score column ",
5232 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5234 if (pp.getScoresFromDescription("description column",
5235 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5237 buildSortByAnnotationScoresMenu();
5245 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5249 protected void showDbRefs_actionPerformed(ActionEvent e)
5251 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5257 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5261 protected void showNpFeats_actionPerformed(ActionEvent e)
5263 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5267 * find the viewport amongst the tabs in this alignment frame and close that
5272 public boolean closeView(AlignViewportI av)
5276 this.closeMenuItem_actionPerformed(false);
5279 Component[] comp = tabbedPane.getComponents();
5280 for (int i = 0; comp != null && i < comp.length; i++)
5282 if (comp[i] instanceof AlignmentPanel)
5284 if (((AlignmentPanel) comp[i]).av == av)
5287 closeView((AlignmentPanel) comp[i]);
5295 protected void build_fetchdbmenu(JMenu webService)
5297 // Temporary hack - DBRef Fetcher always top level ws entry.
5298 // TODO We probably want to store a sequence database checklist in
5299 // preferences and have checkboxes.. rather than individual sources selected
5301 final JMenu rfetch = new JMenu(
5302 MessageManager.getString("action.fetch_db_references"));
5303 rfetch.setToolTipText(MessageManager.getString(
5304 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5305 webService.add(rfetch);
5307 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5308 MessageManager.getString("option.trim_retrieved_seqs"));
5309 trimrs.setToolTipText(
5310 MessageManager.getString("label.trim_retrieved_sequences"));
5312 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5313 trimrs.addActionListener(new ActionListener()
5316 public void actionPerformed(ActionEvent e)
5318 trimrs.setSelected(trimrs.isSelected());
5319 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5320 Boolean.valueOf(trimrs.isSelected()).toString());
5324 JMenuItem fetchr = new JMenuItem(
5325 MessageManager.getString("label.standard_databases"));
5326 fetchr.setToolTipText(
5327 MessageManager.getString("label.fetch_embl_uniprot"));
5328 fetchr.addActionListener(new ActionListener()
5332 public void actionPerformed(ActionEvent e)
5334 new Thread(new Runnable()
5339 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5340 .getAlignment().isNucleotide();
5341 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5342 alignPanel.av.getSequenceSelection(),
5343 alignPanel.alignFrame, null,
5344 alignPanel.alignFrame.featureSettings, isNucleotide);
5345 dbRefFetcher.addListener(new FetchFinishedListenerI()
5348 public void finished()
5351 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5352 .getFeatureSettingsModels())
5355 alignPanel.av.mergeFeaturesStyle(srcSettings);
5357 AlignFrame.this.setMenusForViewport();
5360 dbRefFetcher.fetchDBRefs(false);
5368 new Thread(new Runnable()
5373 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5374 .getSequenceFetcherSingleton();
5375 javax.swing.SwingUtilities.invokeLater(new Runnable()
5380 String[] dbclasses = sf.getNonAlignmentSources();
5381 List<DbSourceProxy> otherdb;
5382 JMenu dfetch = new JMenu();
5383 JMenu ifetch = new JMenu();
5384 JMenuItem fetchr = null;
5385 int comp = 0, icomp = 0, mcomp = 15;
5386 String mname = null;
5388 for (String dbclass : dbclasses)
5390 otherdb = sf.getSourceProxy(dbclass);
5391 // add a single entry for this class, or submenu allowing 'fetch
5393 if (otherdb == null || otherdb.size() < 1)
5399 mname = "From " + dbclass;
5401 if (otherdb.size() == 1)
5403 final DbSourceProxy[] dassource = otherdb
5404 .toArray(new DbSourceProxy[0]);
5405 DbSourceProxy src = otherdb.get(0);
5406 fetchr = new JMenuItem(src.getDbSource());
5407 fetchr.addActionListener(new ActionListener()
5411 public void actionPerformed(ActionEvent e)
5413 new Thread(new Runnable()
5419 boolean isNucleotide = alignPanel.alignFrame
5420 .getViewport().getAlignment()
5422 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5423 alignPanel.av.getSequenceSelection(),
5424 alignPanel.alignFrame, dassource,
5425 alignPanel.alignFrame.featureSettings,
5428 .addListener(new FetchFinishedListenerI()
5431 public void finished()
5433 FeatureSettingsModelI srcSettings = dassource[0]
5434 .getFeatureColourScheme();
5435 alignPanel.av.mergeFeaturesStyle(
5437 AlignFrame.this.setMenusForViewport();
5440 dbRefFetcher.fetchDBRefs(false);
5446 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5447 MessageManager.formatMessage(
5448 "label.fetch_retrieve_from", new Object[]
5449 { src.getDbName() })));
5455 final DbSourceProxy[] dassource = otherdb
5456 .toArray(new DbSourceProxy[0]);
5458 DbSourceProxy src = otherdb.get(0);
5459 fetchr = new JMenuItem(MessageManager
5460 .formatMessage("label.fetch_all_param", new Object[]
5461 { src.getDbSource() }));
5462 fetchr.addActionListener(new ActionListener()
5465 public void actionPerformed(ActionEvent e)
5467 new Thread(new Runnable()
5473 boolean isNucleotide = alignPanel.alignFrame
5474 .getViewport().getAlignment()
5476 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5477 alignPanel.av.getSequenceSelection(),
5478 alignPanel.alignFrame, dassource,
5479 alignPanel.alignFrame.featureSettings,
5482 .addListener(new FetchFinishedListenerI()
5485 public void finished()
5487 AlignFrame.this.setMenusForViewport();
5490 dbRefFetcher.fetchDBRefs(false);
5496 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5497 MessageManager.formatMessage(
5498 "label.fetch_retrieve_from_all_sources",
5500 { Integer.valueOf(otherdb.size())
5502 src.getDbSource(), src.getDbName() })));
5505 // and then build the rest of the individual menus
5506 ifetch = new JMenu(MessageManager.formatMessage(
5507 "label.source_from_db_source", new Object[]
5508 { src.getDbSource() }));
5510 String imname = null;
5512 for (DbSourceProxy sproxy : otherdb)
5514 String dbname = sproxy.getDbName();
5515 String sname = dbname.length() > 5
5516 ? dbname.substring(0, 5) + "..."
5518 String msname = dbname.length() > 10
5519 ? dbname.substring(0, 10) + "..."
5523 imname = MessageManager
5524 .formatMessage("label.from_msname", new Object[]
5527 fetchr = new JMenuItem(msname);
5528 final DbSourceProxy[] dassrc = { sproxy };
5529 fetchr.addActionListener(new ActionListener()
5533 public void actionPerformed(ActionEvent e)
5535 new Thread(new Runnable()
5541 boolean isNucleotide = alignPanel.alignFrame
5542 .getViewport().getAlignment()
5544 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5545 alignPanel.av.getSequenceSelection(),
5546 alignPanel.alignFrame, dassrc,
5547 alignPanel.alignFrame.featureSettings,
5550 .addListener(new FetchFinishedListenerI()
5553 public void finished()
5555 AlignFrame.this.setMenusForViewport();
5558 dbRefFetcher.fetchDBRefs(false);
5564 fetchr.setToolTipText(
5565 "<html>" + MessageManager.formatMessage(
5566 "label.fetch_retrieve_from", new Object[]
5570 if (++icomp >= mcomp || i == (otherdb.size()))
5572 ifetch.setText(MessageManager.formatMessage(
5573 "label.source_to_target", imname, sname));
5575 ifetch = new JMenu();
5583 if (comp >= mcomp || dbi >= (dbclasses.length))
5585 dfetch.setText(MessageManager.formatMessage(
5586 "label.source_to_target", mname, dbclass));
5588 dfetch = new JMenu();
5601 * Left justify the whole alignment.
5604 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5606 AlignmentI al = viewport.getAlignment();
5608 viewport.firePropertyChange("alignment", null, al);
5612 * Right justify the whole alignment.
5615 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5617 AlignmentI al = viewport.getAlignment();
5619 viewport.firePropertyChange("alignment", null, al);
5623 public void setShowSeqFeatures(boolean b)
5625 showSeqFeatures.setSelected(b);
5626 viewport.setShowSequenceFeatures(b);
5633 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5634 * awt.event.ActionEvent)
5637 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5639 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5640 alignPanel.paintAlignment(false, false);
5647 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5651 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5653 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5654 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5662 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5663 * .event.ActionEvent)
5666 protected void showGroupConservation_actionPerformed(ActionEvent e)
5668 viewport.setShowGroupConservation(showGroupConservation.getState());
5669 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5676 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5677 * .event.ActionEvent)
5680 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5682 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5683 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5690 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5691 * .event.ActionEvent)
5694 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5696 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5697 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5701 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5703 showSequenceLogo.setState(true);
5704 viewport.setShowSequenceLogo(true);
5705 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5706 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5710 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5712 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5719 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5720 * .event.ActionEvent)
5723 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5725 if (avc.makeGroupsFromSelection())
5727 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5728 alignPanel.updateAnnotation();
5729 alignPanel.paintAlignment(true,
5730 viewport.needToUpdateStructureViews());
5734 public void clearAlignmentSeqRep()
5736 // TODO refactor alignmentseqrep to controller
5737 if (viewport.getAlignment().hasSeqrep())
5739 viewport.getAlignment().setSeqrep(null);
5740 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5741 alignPanel.updateAnnotation();
5742 alignPanel.paintAlignment(true, true);
5747 protected void createGroup_actionPerformed(ActionEvent e)
5749 if (avc.createGroup())
5751 if (applyAutoAnnotationSettings.isSelected())
5753 alignPanel.updateAnnotation(true, false);
5755 alignPanel.alignmentChanged();
5760 protected void unGroup_actionPerformed(ActionEvent e)
5764 alignPanel.alignmentChanged();
5769 * make the given alignmentPanel the currently selected tab
5771 * @param alignmentPanel
5773 public void setDisplayedView(AlignmentPanel alignmentPanel)
5775 if (!viewport.getSequenceSetId()
5776 .equals(alignmentPanel.av.getSequenceSetId()))
5778 throw new Error(MessageManager.getString(
5779 "error.implementation_error_cannot_show_view_alignment_frame"));
5781 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5782 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5784 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5789 * Action on selection of menu options to Show or Hide annotations.
5792 * @param forSequences
5793 * update sequence-related annotations
5794 * @param forAlignment
5795 * update non-sequence-related annotations
5798 public void setAnnotationsVisibility(boolean visible,
5799 boolean forSequences, boolean forAlignment)
5801 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5802 .getAlignmentAnnotation();
5807 for (AlignmentAnnotation aa : anns)
5810 * don't display non-positional annotations on an alignment
5812 if (aa.annotations == null)
5816 boolean apply = (aa.sequenceRef == null && forAlignment)
5817 || (aa.sequenceRef != null && forSequences);
5820 aa.visible = visible;
5823 alignPanel.validateAnnotationDimensions(true);
5824 alignPanel.alignmentChanged();
5828 * Store selected annotation sort order for the view and repaint.
5831 protected void sortAnnotations_actionPerformed()
5833 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5835 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5836 alignPanel.paintAlignment(false, false);
5841 * @return alignment panels in this alignment frame
5843 public List<? extends AlignmentViewPanel> getAlignPanels()
5845 // alignPanels is never null
5846 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5851 * Open a new alignment window, with the cDNA associated with this (protein)
5852 * alignment, aligned as is the protein.
5854 protected void viewAsCdna_actionPerformed()
5856 // TODO no longer a menu action - refactor as required
5857 final AlignmentI alignment = getViewport().getAlignment();
5858 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5859 if (mappings == null)
5863 List<SequenceI> cdnaSeqs = new ArrayList<>();
5864 for (SequenceI aaSeq : alignment.getSequences())
5866 for (AlignedCodonFrame acf : mappings)
5868 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5872 * There is a cDNA mapping for this protein sequence - add to new
5873 * alignment. It will share the same dataset sequence as other mapped
5874 * cDNA (no new mappings need to be created).
5876 final Sequence newSeq = new Sequence(dnaSeq);
5877 newSeq.setDatasetSequence(dnaSeq);
5878 cdnaSeqs.add(newSeq);
5882 if (cdnaSeqs.size() == 0)
5884 // show a warning dialog no mapped cDNA
5887 AlignmentI cdna = new Alignment(
5888 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5889 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5890 AlignFrame.DEFAULT_HEIGHT);
5891 cdna.alignAs(alignment);
5892 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5894 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5895 AlignFrame.DEFAULT_HEIGHT);
5899 * Set visibility of dna/protein complement view (available when shown in a
5905 protected void showComplement_actionPerformed(boolean show)
5907 SplitContainerI sf = getSplitViewContainer();
5910 sf.setComplementVisible(this, show);
5915 * Generate the reverse (optionally complemented) of the selected sequences,
5916 * and add them to the alignment
5919 protected void showReverse_actionPerformed(boolean complement)
5921 AlignmentI al = null;
5924 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5925 al = dna.reverseCdna(complement);
5926 viewport.addAlignment(al, "");
5927 addHistoryItem(new EditCommand(
5928 MessageManager.getString("label.add_sequences"), Action.PASTE,
5929 al.getSequencesArray(), 0, al.getWidth(),
5930 viewport.getAlignment()));
5931 } catch (Exception ex)
5933 jalview.bin.Console.errPrintln(ex.getMessage());
5939 * Try to run a script in the Groovy console, having first ensured that this
5940 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5941 * be targeted at this alignment.
5944 protected void runGroovy_actionPerformed()
5946 Jalview.setCurrentAlignFrame(this);
5947 groovy.ui.Console console = Desktop.getGroovyConsole();
5948 if (console != null)
5952 console.runScript();
5953 } catch (Exception ex)
5955 jalview.bin.Console.errPrintln((ex.toString()));
5956 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5957 MessageManager.getString("label.couldnt_run_groovy_script"),
5958 MessageManager.getString("label.groovy_support_failed"),
5959 JvOptionPane.ERROR_MESSAGE);
5964 jalview.bin.Console.errPrintln("Can't run Groovy script as console not found");
5969 * Hides columns containing (or not containing) a specified feature, provided
5970 * that would not leave all columns hidden
5972 * @param featureType
5973 * @param columnsContaining
5976 public boolean hideFeatureColumns(String featureType,
5977 boolean columnsContaining)
5979 boolean notForHiding = avc.markColumnsContainingFeatures(
5980 columnsContaining, false, false, featureType);
5983 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5984 false, featureType))
5986 getViewport().hideSelectedColumns();
5994 protected void selectHighlightedColumns_actionPerformed(
5995 ActionEvent actionEvent)
5997 // include key modifier check in case user selects from menu
5998 avc.markHighlightedColumns(
5999 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6000 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6001 | ActionEvent.CTRL_MASK)) != 0);
6005 protected void copyHighlightedColumns_actionPerformed(
6006 ActionEvent actionEvent)
6008 avc.copyHighlightedRegionsToClipboard();
6012 * Rebuilds the Colour menu, including any user-defined colours which have
6013 * been loaded either on startup or during the session
6015 public void buildColourMenu()
6017 colourMenu.removeAll();
6019 colourMenu.add(applyToAllGroups);
6020 colourMenu.add(textColour);
6021 colourMenu.addSeparator();
6023 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6024 viewport.getAlignment(), false);
6026 colourMenu.add(annotationColour);
6027 bg.add(annotationColour);
6028 colourMenu.addSeparator();
6029 colourMenu.add(conservationMenuItem);
6030 colourMenu.add(modifyConservation);
6031 colourMenu.add(abovePIDThreshold);
6032 colourMenu.add(modifyPID);
6034 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6035 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6039 * Open a dialog (if not already open) that allows the user to select and
6040 * calculate PCA or Tree analysis
6042 protected void openTreePcaDialog()
6044 if (alignPanel.getCalculationDialog() == null)
6046 new CalculationChooser(AlignFrame.this);
6051 protected void loadVcf_actionPerformed()
6053 JalviewFileChooser chooser = new JalviewFileChooser(
6054 Cache.getProperty("LAST_DIRECTORY"));
6055 chooser.setFileView(new JalviewFileView());
6056 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6057 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6058 final AlignFrame us = this;
6059 chooser.setResponseHandler(0, () -> {
6060 String choice = chooser.getSelectedFile().getPath();
6061 Cache.setProperty("LAST_DIRECTORY", choice);
6062 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6063 new VCFLoader(choice).loadVCF(seqs, us);
6065 chooser.showOpenDialog(null);
6069 private Rectangle lastFeatureSettingsBounds = null;
6072 public void setFeatureSettingsGeometry(Rectangle bounds)
6074 lastFeatureSettingsBounds = bounds;
6078 public Rectangle getFeatureSettingsGeometry()
6080 return lastFeatureSettingsBounds;
6085 class PrintThread extends Thread
6089 public PrintThread(AlignmentPanel ap)
6094 static PageFormat pf;
6099 PrinterJob printJob = PrinterJob.getPrinterJob();
6103 printJob.setPrintable(ap, pf);
6107 printJob.setPrintable(ap);
6110 if (printJob.printDialog())
6115 } catch (Exception PrintException)
6117 PrintException.printStackTrace();