2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.PrintWriter;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.Deque;
57 import java.util.Enumeration;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.Locale;
61 import java.util.Vector;
62 import java.util.concurrent.Callable;
64 import javax.swing.ButtonGroup;
65 import javax.swing.JCheckBoxMenuItem;
66 import javax.swing.JComponent;
67 import javax.swing.JEditorPane;
68 import javax.swing.JInternalFrame;
69 import javax.swing.JLabel;
70 import javax.swing.JLayeredPane;
71 import javax.swing.JMenu;
72 import javax.swing.JMenuItem;
73 import javax.swing.JPanel;
74 import javax.swing.JScrollPane;
75 import javax.swing.SwingUtilities;
77 import ext.vamsas.ServiceHandle;
78 import jalview.analysis.AlignmentSorter;
79 import jalview.analysis.AlignmentUtils;
80 import jalview.analysis.CrossRef;
81 import jalview.analysis.Dna;
82 import jalview.analysis.GeneticCodeI;
83 import jalview.analysis.ParseProperties;
84 import jalview.analysis.SequenceIdMatcher;
85 import jalview.api.AlignExportSettingsI;
86 import jalview.api.AlignViewControllerGuiI;
87 import jalview.api.AlignViewControllerI;
88 import jalview.api.AlignViewportI;
89 import jalview.api.AlignmentViewPanel;
90 import jalview.api.FeatureSettingsControllerI;
91 import jalview.api.FeatureSettingsModelI;
92 import jalview.api.SplitContainerI;
93 import jalview.api.ViewStyleI;
94 import jalview.api.analysis.SimilarityParamsI;
95 import jalview.bin.Cache;
96 import jalview.bin.Console;
97 import jalview.bin.Jalview;
98 import jalview.commands.CommandI;
99 import jalview.commands.EditCommand;
100 import jalview.commands.EditCommand.Action;
101 import jalview.commands.OrderCommand;
102 import jalview.commands.RemoveGapColCommand;
103 import jalview.commands.RemoveGapsCommand;
104 import jalview.commands.SlideSequencesCommand;
105 import jalview.commands.TrimRegionCommand;
106 import jalview.datamodel.AlignExportSettingsAdapter;
107 import jalview.datamodel.AlignedCodonFrame;
108 import jalview.datamodel.Alignment;
109 import jalview.datamodel.AlignmentAnnotation;
110 import jalview.datamodel.AlignmentExportData;
111 import jalview.datamodel.AlignmentI;
112 import jalview.datamodel.AlignmentOrder;
113 import jalview.datamodel.AlignmentView;
114 import jalview.datamodel.ColumnSelection;
115 import jalview.datamodel.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.vcf.VCFLoader;
145 import jalview.jbgui.GAlignFrame;
146 import jalview.project.Jalview2XML;
147 import jalview.schemes.ColourSchemeI;
148 import jalview.schemes.ColourSchemes;
149 import jalview.schemes.ResidueColourScheme;
150 import jalview.schemes.TCoffeeColourScheme;
151 import jalview.util.HttpUtils;
152 import jalview.util.ImageMaker.TYPE;
153 import jalview.util.MessageManager;
154 import jalview.util.Platform;
155 import jalview.viewmodel.AlignmentViewport;
156 import jalview.viewmodel.ViewportRanges;
157 import jalview.ws.DBRefFetcher;
158 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
159 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
160 import jalview.ws.jws1.Discoverer;
161 import jalview.ws.jws2.Jws2Discoverer;
162 import jalview.ws.jws2.jabaws2.Jws2Instance;
163 import jalview.ws.seqfetcher.DbSourceProxy;
169 * @version $Revision$
171 @SuppressWarnings("serial")
172 public class AlignFrame extends GAlignFrame implements DropTargetListener,
173 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
176 public static final int DEFAULT_WIDTH = 700;
178 public static final int DEFAULT_HEIGHT = 500;
181 * The currently displayed panel (selected tabbed view if more than one)
183 public AlignmentPanel alignPanel;
185 AlignViewport viewport;
187 public AlignViewControllerI avc;
189 List<AlignmentPanel> alignPanels = new ArrayList<>();
192 * Last format used to load or save alignments in this window
194 FileFormatI currentFileFormat = null;
197 * Current filename for this alignment
199 String fileName = null;
204 * Creates a new AlignFrame object with specific width and height.
210 public AlignFrame(AlignmentI al, int width, int height)
212 this(al, null, width, height);
216 * Creates a new AlignFrame object with specific width, height and
222 * @param sequenceSetId
224 public AlignFrame(AlignmentI al, int width, int height,
225 String sequenceSetId)
227 this(al, null, width, height, sequenceSetId);
231 * Creates a new AlignFrame object with specific width, height and
237 * @param sequenceSetId
240 public AlignFrame(AlignmentI al, int width, int height,
241 String sequenceSetId, String viewId)
243 this(al, null, width, height, sequenceSetId, viewId);
247 * new alignment window with hidden columns
251 * @param hiddenColumns
252 * ColumnSelection or null
254 * Width of alignment frame
258 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
261 this(al, hiddenColumns, width, height, null);
265 * Create alignment frame for al with hiddenColumns, a specific width and
266 * height, and specific sequenceId
269 * @param hiddenColumns
272 * @param sequenceSetId
275 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
276 int height, String sequenceSetId)
278 this(al, hiddenColumns, width, height, sequenceSetId, null);
282 * Create alignment frame for al with hiddenColumns, a specific width and
283 * height, and specific sequenceId
286 * @param hiddenColumns
289 * @param sequenceSetId
294 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
295 int height, String sequenceSetId, String viewId)
297 setSize(width, height);
299 if (al.getDataset() == null)
304 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
306 alignPanel = new AlignmentPanel(this, viewport);
308 addAlignmentPanel(alignPanel, true);
312 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
313 HiddenColumns hiddenColumns, int width, int height)
315 setSize(width, height);
317 if (al.getDataset() == null)
322 viewport = new AlignViewport(al, hiddenColumns);
324 if (hiddenSeqs != null && hiddenSeqs.length > 0)
326 viewport.hideSequence(hiddenSeqs);
328 alignPanel = new AlignmentPanel(this, viewport);
329 addAlignmentPanel(alignPanel, true);
334 * Make a new AlignFrame from existing alignmentPanels
341 public AlignFrame(AlignmentPanel ap)
345 addAlignmentPanel(ap, false);
350 * initalise the alignframe from the underlying viewport data and the
357 // setBackground(Color.white); // BH 2019
359 if (!Jalview.isHeadlessMode())
361 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
364 avc = new jalview.controller.AlignViewController(this, viewport,
366 if (viewport.getAlignmentConservationAnnotation() == null)
368 // BLOSUM62Colour.setEnabled(false);
369 conservationMenuItem.setEnabled(false);
370 modifyConservation.setEnabled(false);
371 // PIDColour.setEnabled(false);
372 // abovePIDThreshold.setEnabled(false);
373 // modifyPID.setEnabled(false);
376 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
378 if (sortby.equals("Id"))
380 sortIDMenuItem_actionPerformed(null);
382 else if (sortby.equals("Pairwise Identity"))
384 sortPairwiseMenuItem_actionPerformed(null);
388 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
390 setMenusFromViewport(viewport);
391 buildSortByAnnotationScoresMenu();
392 calculateTree.addActionListener(new ActionListener()
396 public void actionPerformed(ActionEvent e)
403 if (Desktop.desktop != null)
405 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
406 if (!Platform.isJS())
408 addServiceListeners();
413 if (viewport.getWrapAlignment())
415 wrapMenuItem_actionPerformed(null);
418 if (Cache.getDefault("SHOW_OVERVIEW", false))
420 this.overviewMenuItem_actionPerformed(null);
425 final List<AlignmentViewPanel> selviews = new ArrayList<>();
426 final List<AlignmentPanel> origview = new ArrayList<>();
427 final String menuLabel = MessageManager
428 .getString("label.copy_format_from");
429 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
430 new ViewSetProvider()
434 public AlignmentPanel[] getAllAlignmentPanels()
437 origview.add(alignPanel);
438 // make an array of all alignment panels except for this one
439 List<AlignmentPanel> aps = new ArrayList<>(
440 Arrays.asList(Desktop.getAlignmentPanels(null)));
441 aps.remove(AlignFrame.this.alignPanel);
442 return aps.toArray(new AlignmentPanel[aps.size()]);
444 }, selviews, new ItemListener()
448 public void itemStateChanged(ItemEvent e)
450 if (origview.size() > 0)
452 final AlignmentPanel ap = origview.get(0);
455 * Copy the ViewStyle of the selected panel to 'this one'.
456 * Don't change value of 'scaleProteinAsCdna' unless copying
459 ViewStyleI vs = selviews.get(0).getAlignViewport()
461 boolean fromSplitFrame = selviews.get(0)
462 .getAlignViewport().getCodingComplement() != null;
465 vs.setScaleProteinAsCdna(ap.getAlignViewport()
466 .getViewStyle().isScaleProteinAsCdna());
468 ap.getAlignViewport().setViewStyle(vs);
471 * Also rescale ViewStyle of SplitFrame complement if there is
472 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
473 * the whole ViewStyle (allow cDNA protein to have different
476 AlignViewportI complement = ap.getAlignViewport()
477 .getCodingComplement();
478 if (complement != null && vs.isScaleProteinAsCdna())
480 AlignFrame af = Desktop.getAlignFrameFor(complement);
481 ((SplitFrame) af.getSplitViewContainer())
483 af.setMenusForViewport();
487 ap.setSelected(true);
488 ap.alignFrame.setMenusForViewport();
493 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
494 .indexOf("devel") > -1
495 || Cache.getDefault("VERSION", "DEVELOPMENT")
496 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
498 formatMenu.add(vsel);
500 addFocusListener(new FocusAdapter()
503 public void focusGained(FocusEvent e)
505 Jalview.setCurrentAlignFrame(AlignFrame.this);
512 * Change the filename and format for the alignment, and enable the 'reload'
513 * button functionality.
520 public void setFileName(String file, FileFormatI format)
523 setFileFormat(format);
524 reload.setEnabled(true);
528 * JavaScript will have this, maybe others. More dependable than a file name
529 * and maintains a reference to the actual bytes loaded.
533 public void setFileObject(File file)
535 this.fileObject = file;
539 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
542 void addKeyListener()
544 addKeyListener(new KeyAdapter()
547 public void keyPressed(KeyEvent evt)
549 if (viewport.cursorMode
550 && ((evt.getKeyCode() >= KeyEvent.VK_0
551 && evt.getKeyCode() <= KeyEvent.VK_9)
552 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
553 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
554 && Character.isDigit(evt.getKeyChar()))
556 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
559 switch (evt.getKeyCode())
562 case 27: // escape key
563 deselectAllSequenceMenuItem_actionPerformed(null);
567 case KeyEvent.VK_DOWN:
568 if (evt.isAltDown() || !viewport.cursorMode)
570 moveSelectedSequences(false);
572 if (viewport.cursorMode)
574 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
579 if (evt.isAltDown() || !viewport.cursorMode)
581 moveSelectedSequences(true);
583 if (viewport.cursorMode)
585 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
590 case KeyEvent.VK_LEFT:
591 if (evt.isAltDown() || !viewport.cursorMode)
593 slideSequences(false,
594 alignPanel.getSeqPanel().getKeyboardNo1());
598 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
603 case KeyEvent.VK_RIGHT:
604 if (evt.isAltDown() || !viewport.cursorMode)
606 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
610 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
614 case KeyEvent.VK_SPACE:
615 if (viewport.cursorMode)
617 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
618 || evt.isShiftDown() || evt.isAltDown());
622 // case KeyEvent.VK_A:
623 // if (viewport.cursorMode)
625 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
626 // //System.out.println("A");
630 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
631 * System.out.println("closing bracket"); } break;
633 case KeyEvent.VK_DELETE:
634 case KeyEvent.VK_BACK_SPACE:
635 if (!viewport.cursorMode)
637 cut_actionPerformed();
641 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
642 || evt.isShiftDown() || evt.isAltDown());
648 if (viewport.cursorMode)
650 alignPanel.getSeqPanel().setCursorRow();
654 if (viewport.cursorMode && !evt.isControlDown())
656 alignPanel.getSeqPanel().setCursorColumn();
660 if (viewport.cursorMode)
662 alignPanel.getSeqPanel().setCursorPosition();
666 case KeyEvent.VK_ENTER:
667 case KeyEvent.VK_COMMA:
668 if (viewport.cursorMode)
670 alignPanel.getSeqPanel().setCursorRowAndColumn();
675 if (viewport.cursorMode)
677 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
681 if (viewport.cursorMode)
683 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
688 viewport.cursorMode = !viewport.cursorMode;
689 setStatus(MessageManager
690 .formatMessage("label.keyboard_editing_mode", new String[]
691 { (viewport.cursorMode ? "on" : "off") }));
692 if (viewport.cursorMode)
694 ViewportRanges ranges = viewport.getRanges();
695 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
697 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
700 alignPanel.getSeqPanel().seqCanvas.repaint();
706 Help.showHelpWindow();
707 } catch (Exception ex)
709 ex.printStackTrace();
714 boolean toggleSeqs = !evt.isControlDown();
715 boolean toggleCols = !evt.isShiftDown();
716 toggleHiddenRegions(toggleSeqs, toggleCols);
721 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
722 boolean modifyExisting = true; // always modify, don't clear
723 // evt.isShiftDown();
724 boolean invertHighlighted = evt.isAltDown();
725 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
729 case KeyEvent.VK_PAGE_UP:
730 viewport.getRanges().pageUp();
732 case KeyEvent.VK_PAGE_DOWN:
733 viewport.getRanges().pageDown();
739 public void keyReleased(KeyEvent evt)
741 switch (evt.getKeyCode())
743 case KeyEvent.VK_LEFT:
744 if (evt.isAltDown() || !viewport.cursorMode)
746 viewport.firePropertyChange("alignment", null,
747 viewport.getAlignment().getSequences());
751 case KeyEvent.VK_RIGHT:
752 if (evt.isAltDown() || !viewport.cursorMode)
754 viewport.firePropertyChange("alignment", null,
755 viewport.getAlignment().getSequences());
763 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
765 ap.alignFrame = this;
766 avc = new jalview.controller.AlignViewController(this, viewport,
771 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
773 int aSize = alignPanels.size();
775 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
777 if (aSize == 1 && ap.av.getViewName() == null)
779 this.getContentPane().add(ap, BorderLayout.CENTER);
785 setInitialTabVisible();
788 expandViews.setEnabled(true);
789 gatherViews.setEnabled(true);
790 tabbedPane.addTab(ap.av.getViewName(), ap);
792 ap.setVisible(false);
797 if (ap.av.isPadGaps())
799 ap.av.getAlignment().padGaps();
801 ap.av.updateConservation(ap);
802 ap.av.updateConsensus(ap);
803 ap.av.updateStrucConsensus(ap);
807 public void setInitialTabVisible()
809 expandViews.setEnabled(true);
810 gatherViews.setEnabled(true);
811 tabbedPane.setVisible(true);
812 AlignmentPanel first = alignPanels.get(0);
813 tabbedPane.addTab(first.av.getViewName(), first);
814 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
817 public AlignViewport getViewport()
822 /* Set up intrinsic listeners for dynamically generated GUI bits. */
823 private void addServiceListeners()
825 final java.beans.PropertyChangeListener thisListener;
826 Desktop.instance.addJalviewPropertyChangeListener("services",
827 thisListener = new java.beans.PropertyChangeListener()
830 public void propertyChange(PropertyChangeEvent evt)
832 // // System.out.println("Discoverer property change.");
833 // if (evt.getPropertyName().equals("services"))
835 SwingUtilities.invokeLater(new Runnable()
842 "Rebuild WS Menu for service change");
843 BuildWebServiceMenu();
850 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
853 public void internalFrameClosed(
854 javax.swing.event.InternalFrameEvent evt)
856 // System.out.println("deregistering discoverer listener");
857 Desktop.instance.removeJalviewPropertyChangeListener("services",
859 closeMenuItem_actionPerformed(true);
862 // Finally, build the menu once to get current service state
863 new Thread(new Runnable()
868 BuildWebServiceMenu();
874 * Configure menu items that vary according to whether the alignment is
875 * nucleotide or protein
877 public void setGUINucleotide()
879 AlignmentI al = getViewport().getAlignment();
880 boolean nucleotide = al.isNucleotide();
882 loadVcf.setVisible(nucleotide);
883 showTranslation.setVisible(nucleotide);
884 showReverse.setVisible(nucleotide);
885 showReverseComplement.setVisible(nucleotide);
886 conservationMenuItem.setEnabled(!nucleotide);
888 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
889 showGroupConservation.setEnabled(!nucleotide);
891 showComplementMenuItem
892 .setText(nucleotide ? MessageManager.getString("label.protein")
893 : MessageManager.getString("label.nucleotide"));
897 * set up menus for the current viewport. This may be called after any
898 * operation that affects the data in the current view (selection changed,
899 * etc) to update the menus to reflect the new state.
902 public void setMenusForViewport()
904 setMenusFromViewport(viewport);
908 * Need to call this method when tabs are selected for multiple views, or when
909 * loading from Jalview2XML.java
914 public void setMenusFromViewport(AlignViewport av)
916 padGapsMenuitem.setSelected(av.isPadGaps());
917 colourTextMenuItem.setSelected(av.isShowColourText());
918 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
919 modifyPID.setEnabled(abovePIDThreshold.isSelected());
920 conservationMenuItem.setSelected(av.getConservationSelected());
921 modifyConservation.setEnabled(conservationMenuItem.isSelected());
922 seqLimits.setSelected(av.getShowJVSuffix());
923 idRightAlign.setSelected(av.isRightAlignIds());
924 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
925 renderGapsMenuItem.setSelected(av.isRenderGaps());
926 wrapMenuItem.setSelected(av.getWrapAlignment());
927 scaleAbove.setVisible(av.getWrapAlignment());
928 scaleLeft.setVisible(av.getWrapAlignment());
929 scaleRight.setVisible(av.getWrapAlignment());
930 annotationPanelMenuItem.setState(av.isShowAnnotation());
932 * Show/hide annotations only enabled if annotation panel is shown
934 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
935 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
936 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
937 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
938 viewBoxesMenuItem.setSelected(av.getShowBoxes());
939 viewTextMenuItem.setSelected(av.getShowText());
940 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
941 showGroupConsensus.setSelected(av.isShowGroupConsensus());
942 showGroupConservation.setSelected(av.isShowGroupConservation());
943 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
944 showSequenceLogo.setSelected(av.isShowSequenceLogo());
945 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
947 ColourMenuHelper.setColourSelected(colourMenu,
948 av.getGlobalColourScheme());
950 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
951 hiddenMarkers.setState(av.getShowHiddenMarkers());
952 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
953 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
954 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
955 autoCalculate.setSelected(av.autoCalculateConsensus);
956 sortByTree.setSelected(av.sortByTree);
957 listenToViewSelections.setSelected(av.followSelection);
959 showProducts.setEnabled(canShowProducts());
960 setGroovyEnabled(Desktop.getGroovyConsole() != null);
966 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
970 public void setGroovyEnabled(boolean b)
972 runGroovy.setEnabled(b);
975 private IProgressIndicator progressBar;
980 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
983 public void setProgressBar(String message, long id)
985 if (!Platform.isHeadless())
986 progressBar.setProgressBar(message, id);
990 public void registerHandler(final long id,
991 final IProgressIndicatorHandler handler)
993 progressBar.registerHandler(id, handler);
998 * @return true if any progress bars are still active
1001 public boolean operationInProgress()
1003 return progressBar.operationInProgress();
1007 * Sets the text of the status bar. Note that setting a null or empty value
1008 * will cause the status bar to be hidden, with possibly undesirable flicker
1009 * of the screen layout.
1012 public void setStatus(String text)
1014 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1018 * Added so Castor Mapping file can obtain Jalview Version
1020 public String getVersion()
1022 return Cache.getProperty("VERSION");
1025 public FeatureRenderer getFeatureRenderer()
1027 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1031 public void fetchSequence_actionPerformed()
1033 new SequenceFetcher(this);
1037 public void addFromFile_actionPerformed(ActionEvent e)
1039 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1043 public void reload_actionPerformed(ActionEvent e)
1045 if (fileName != null)
1047 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1048 // originating file's format
1049 // TODO: work out how to recover feature settings for correct view(s) when
1050 // file is reloaded.
1051 if (FileFormat.Jalview.equals(currentFileFormat))
1053 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1054 for (int i = 0; i < frames.length; i++)
1056 if (frames[i] instanceof AlignFrame && frames[i] != this
1057 && ((AlignFrame) frames[i]).fileName != null
1058 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1062 frames[i].setSelected(true);
1063 Desktop.instance.closeAssociatedWindows();
1064 } catch (java.beans.PropertyVetoException ex)
1070 Desktop.instance.closeAssociatedWindows();
1072 FileLoader loader = new FileLoader();
1073 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1074 ? DataSourceType.URL
1075 : DataSourceType.FILE;
1076 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1080 Rectangle bounds = this.getBounds();
1082 FileLoader loader = new FileLoader();
1084 AlignFrame newframe = null;
1086 if (fileObject == null)
1089 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1090 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1091 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1096 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1097 DataSourceType.FILE, currentFileFormat);
1100 newframe.setBounds(bounds);
1101 if (featureSettings != null && featureSettings.isShowing())
1103 final Rectangle fspos = featureSettings.frame.getBounds();
1104 // TODO: need a 'show feature settings' function that takes bounds -
1105 // need to refactor Desktop.addFrame
1106 newframe.featureSettings_actionPerformed(null);
1107 final FeatureSettings nfs = newframe.featureSettings;
1108 SwingUtilities.invokeLater(new Runnable()
1113 nfs.frame.setBounds(fspos);
1116 this.featureSettings.close();
1117 this.featureSettings = null;
1119 this.closeMenuItem_actionPerformed(true);
1125 public void addFromText_actionPerformed(ActionEvent e)
1128 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1132 public void addFromURL_actionPerformed(ActionEvent e)
1134 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1138 public void save_actionPerformed(ActionEvent e)
1140 if (fileName == null || (currentFileFormat == null)
1141 || HttpUtils.startsWithHttpOrHttps(fileName))
1143 saveAs_actionPerformed();
1147 saveAlignment(fileName, currentFileFormat);
1152 * Saves the alignment to a file with a name chosen by the user, if necessary
1153 * warning if a file would be overwritten
1156 public void saveAs_actionPerformed()
1158 String format = currentFileFormat == null ? null
1159 : currentFileFormat.getName();
1160 JalviewFileChooser chooser = JalviewFileChooser
1161 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1163 chooser.setFileView(new JalviewFileView());
1164 chooser.setDialogTitle(
1165 MessageManager.getString("label.save_alignment_to_file"));
1166 chooser.setToolTipText(MessageManager.getString("action.save"));
1168 int value = chooser.showSaveDialog(this);
1170 if (value != JalviewFileChooser.APPROVE_OPTION)
1174 currentFileFormat = chooser.getSelectedFormat();
1175 // todo is this (2005) test now obsolete - value is never null?
1176 while (currentFileFormat == null)
1178 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1180 .getString("label.select_file_format_before_saving"),
1181 MessageManager.getString("label.file_format_not_specified"),
1182 JvOptionPane.WARNING_MESSAGE);
1183 currentFileFormat = chooser.getSelectedFormat();
1184 value = chooser.showSaveDialog(this);
1185 if (value != JalviewFileChooser.APPROVE_OPTION)
1191 fileName = chooser.getSelectedFile().getPath();
1193 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1194 Cache.setProperty("LAST_DIRECTORY", fileName);
1195 saveAlignment(fileName, currentFileFormat);
1198 boolean lastSaveSuccessful = false;
1200 FileFormatI lastFormatSaved;
1202 String lastFilenameSaved;
1205 * Raise a dialog or status message for the last call to saveAlignment.
1207 * @return true if last call to saveAlignment(file, format) was successful.
1209 public boolean isSaveAlignmentSuccessful()
1212 if (!lastSaveSuccessful)
1214 if (!Platform.isHeadless())
1216 JvOptionPane.showInternalMessageDialog(this, MessageManager
1217 .formatMessage("label.couldnt_save_file", new Object[]
1218 { lastFilenameSaved }),
1219 MessageManager.getString("label.error_saving_file"),
1220 JvOptionPane.WARNING_MESSAGE);
1224 Console.error(MessageManager
1225 .formatMessage("label.couldnt_save_file", new Object[]
1226 { lastFilenameSaved }));
1232 setStatus(MessageManager.formatMessage(
1233 "label.successfully_saved_to_file_in_format", new Object[]
1234 { lastFilenameSaved, lastFormatSaved }));
1237 return lastSaveSuccessful;
1241 * Saves the alignment to the specified file path, in the specified format,
1242 * which may be an alignment format, or Jalview project format. If the
1243 * alignment has hidden regions, or the format is one capable of including
1244 * non-sequence data (features, annotations, groups), then the user may be
1245 * prompted to specify what to include in the output.
1250 public void saveAlignment(String file, FileFormatI format)
1252 lastSaveSuccessful = true;
1253 lastFilenameSaved = file;
1254 lastFormatSaved = format;
1256 if (FileFormat.Jalview.equals(format))
1258 String shortName = title;
1259 if (shortName.indexOf(File.separatorChar) > -1)
1261 shortName = shortName
1262 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1264 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1267 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1268 if (lastSaveSuccessful)
1270 this.getViewport().setSavedUpToDate(true);
1273 statusBar.setText(MessageManager.formatMessage(
1274 "label.successfully_saved_to_file_in_format", new Object[]
1280 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1281 Callable<Void> cancelAction = () -> {
1282 lastSaveSuccessful = false;
1285 Callable<Void> outputAction = () -> {
1286 // todo defer this to inside formatSequences (or later)
1287 AlignmentExportData exportData = viewport.getAlignExportData(options);
1288 String output = new FormatAdapter(alignPanel, options)
1289 .formatSequences(format, exportData.getAlignment(),
1290 exportData.getOmitHidden(),
1291 exportData.getStartEndPostions(),
1292 viewport.getAlignment().getHiddenColumns());
1295 lastSaveSuccessful = false;
1299 // create backupfiles object and get new temp filename destination
1300 boolean doBackup = BackupFiles.getEnabled();
1301 BackupFiles backupfiles = null;
1304 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1305 backupfiles = new BackupFiles(file);
1309 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1311 Console.trace("ALIGNFRAME setting PrintWriter");
1312 PrintWriter out = new PrintWriter(new FileWriter(tempFilePath));
1314 if (backupfiles != null)
1316 Console.trace("ALIGNFRAME about to write to temp file "
1317 + backupfiles.getTempFilePath());
1321 Console.trace("ALIGNFRAME about to close file");
1323 Console.trace("ALIGNFRAME closed file");
1324 AlignFrame.this.setTitle(file);
1325 statusBar.setText(MessageManager.formatMessage(
1326 "label.successfully_saved_to_file_in_format", new Object[]
1327 { fileName, format.getName() }));
1328 lastSaveSuccessful = true;
1329 } catch (IOException e)
1331 lastSaveSuccessful = false;
1333 "ALIGNFRAME Something happened writing the temp file");
1334 Console.error(e.getMessage());
1335 Console.debug(Cache.getStackTraceString(e));
1336 } catch (Exception ex)
1338 lastSaveSuccessful = false;
1340 "ALIGNFRAME Something unexpected happened writing the temp file");
1341 Console.error(ex.getMessage());
1342 Console.debug(Cache.getStackTraceString(ex));
1347 backupfiles.setWriteSuccess(lastSaveSuccessful);
1348 Console.debug("ALIGNFRAME writing temp file was "
1349 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1350 // do the backup file roll and rename the temp file to actual file
1351 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1352 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1353 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1354 + (lastSaveSuccessful ? "" : "un") + "successfully");
1357 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1358 if (lastSaveSuccessful)
1360 AlignFrame.this.getViewport().setSavedUpToDate(true);
1367 * show dialog with export options if applicable; else just do it
1369 if (AlignExportOptions.isNeeded(viewport, format))
1371 AlignExportOptions choices = new AlignExportOptions(
1372 alignPanel.getAlignViewport(), format, options);
1373 choices.setResponseAction(0, outputAction);
1374 choices.setResponseAction(1, cancelAction);
1375 choices.showDialog();
1381 outputAction.call();
1382 } catch (Exception e)
1384 // TODO Auto-generated catch block
1385 e.printStackTrace();
1391 * Outputs the alignment to textbox in the requested format, if necessary
1392 * first prompting the user for whether to include hidden regions or
1395 * @param fileFormatName
1398 protected void outputText_actionPerformed(String fileFormatName)
1400 FileFormatI fileFormat = FileFormats.getInstance()
1401 .forName(fileFormatName);
1402 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1403 Callable<Void> outputAction = () -> {
1404 // todo defer this to inside formatSequences (or later)
1405 AlignmentExportData exportData = viewport.getAlignExportData(options);
1406 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1407 cap.setForInput(null);
1410 FileFormatI format = fileFormat;
1411 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1412 format, exportData.getAlignment(),
1413 exportData.getOmitHidden(),
1414 exportData.getStartEndPostions(),
1415 viewport.getAlignment().getHiddenColumns()));
1416 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1417 "label.alignment_output_command", new Object[]
1418 { fileFormat.getName() }), 600, 500);
1419 } catch (OutOfMemoryError oom)
1421 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1429 * show dialog with export options if applicable; else just do it
1431 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1433 AlignExportOptions choices = new AlignExportOptions(
1434 alignPanel.getAlignViewport(), fileFormat, options);
1435 choices.setResponseAction(0, outputAction);
1436 choices.showDialog();
1442 outputAction.call();
1443 } catch (Exception e)
1445 e.printStackTrace();
1457 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1459 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1460 htmlSVG.exportHTML(null);
1464 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1466 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1467 bjs.exportHTML(null);
1470 public void createImageMap(File file, String image)
1472 alignPanel.makePNGImageMap(file, image);
1476 * Creates a PNG image of the alignment and writes it to the given file. If
1477 * the file is null, the user is prompted to choose a file.
1482 public void createPNG(File f)
1484 createPNG(f, null, 0.0f, 0, 0);
1487 public void createPNG(File f, String renderer, float bitmapscale,
1488 int bitmapwidth, int bitmapheight)
1490 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, bitmapscale,
1491 bitmapwidth, bitmapheight);
1495 * Creates an EPS image of the alignment and writes it to the given file. If
1496 * the file is null, the user is prompted to choose a file.
1501 public void createEPS(File f)
1506 public void createEPS(File f, String renderer)
1508 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1512 * Creates an SVG image of the alignment and writes it to the given file. If
1513 * the file is null, the user is prompted to choose a file.
1518 public void createSVG(File f)
1523 public void createSVG(File f, String renderer)
1525 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1529 public void pageSetup_actionPerformed(ActionEvent e)
1531 PrinterJob printJob = PrinterJob.getPrinterJob();
1532 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1542 public void printMenuItem_actionPerformed(ActionEvent e)
1544 // Putting in a thread avoids Swing painting problems
1545 PrintThread thread = new PrintThread(alignPanel);
1550 public void exportFeatures_actionPerformed(ActionEvent e)
1552 new AnnotationExporter(alignPanel).exportFeatures();
1556 public void exportAnnotations_actionPerformed(ActionEvent e)
1558 new AnnotationExporter(alignPanel).exportAnnotations();
1562 public void associatedData_actionPerformed(ActionEvent e)
1564 final JalviewFileChooser chooser = new JalviewFileChooser(
1565 Cache.getProperty("LAST_DIRECTORY"));
1566 chooser.setFileView(new JalviewFileView());
1567 String tooltip = MessageManager
1568 .getString("label.load_jalview_annotations");
1569 chooser.setDialogTitle(tooltip);
1570 chooser.setToolTipText(tooltip);
1571 chooser.setResponseHandler(0, () -> {
1572 String choice = chooser.getSelectedFile().getPath();
1573 Cache.setProperty("LAST_DIRECTORY", choice);
1574 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1578 chooser.showOpenDialog(this);
1582 * Close the current view or all views in the alignment frame. If the frame
1583 * only contains one view then the alignment will be removed from memory.
1585 * @param closeAllTabs
1588 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1590 if (alignPanels != null && alignPanels.size() < 2)
1592 closeAllTabs = true;
1597 if (alignPanels != null)
1601 if (this.isClosed())
1603 // really close all the windows - otherwise wait till
1604 // setClosed(true) is called
1605 for (int i = 0; i < alignPanels.size(); i++)
1607 AlignmentPanel ap = alignPanels.get(i);
1614 closeView(alignPanel);
1619 if (featureSettings != null && featureSettings.isOpen())
1621 featureSettings.close();
1622 featureSettings = null;
1625 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1626 * be called recursively, with the frame now in 'closed' state
1628 this.setClosed(true);
1630 } catch (Exception ex)
1632 ex.printStackTrace();
1637 * Close the specified panel and close up tabs appropriately.
1639 * @param panelToClose
1641 public void closeView(AlignmentPanel panelToClose)
1643 int index = tabbedPane.getSelectedIndex();
1644 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1645 alignPanels.remove(panelToClose);
1646 panelToClose.closePanel();
1647 panelToClose = null;
1649 tabbedPane.removeTabAt(closedindex);
1650 tabbedPane.validate();
1652 if (index > closedindex || index == tabbedPane.getTabCount())
1654 // modify currently selected tab index if necessary.
1658 this.tabSelectionChanged(index);
1664 void updateEditMenuBar()
1667 if (viewport.getHistoryList().size() > 0)
1669 undoMenuItem.setEnabled(true);
1670 CommandI command = viewport.getHistoryList().peek();
1671 undoMenuItem.setText(MessageManager
1672 .formatMessage("label.undo_command", new Object[]
1673 { command.getDescription() }));
1677 undoMenuItem.setEnabled(false);
1678 undoMenuItem.setText(MessageManager.getString("action.undo"));
1681 if (viewport.getRedoList().size() > 0)
1683 redoMenuItem.setEnabled(true);
1685 CommandI command = viewport.getRedoList().peek();
1686 redoMenuItem.setText(MessageManager
1687 .formatMessage("label.redo_command", new Object[]
1688 { command.getDescription() }));
1692 redoMenuItem.setEnabled(false);
1693 redoMenuItem.setText(MessageManager.getString("action.redo"));
1698 public void addHistoryItem(CommandI command)
1700 if (command.getSize() > 0)
1702 viewport.addToHistoryList(command);
1703 viewport.clearRedoList();
1704 updateEditMenuBar();
1705 viewport.updateHiddenColumns();
1706 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1707 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1708 // viewport.getColumnSelection()
1709 // .getHiddenColumns().size() > 0);
1715 * @return alignment objects for all views
1717 AlignmentI[] getViewAlignments()
1719 if (alignPanels != null)
1721 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1723 for (AlignmentPanel ap : alignPanels)
1725 als[i++] = ap.av.getAlignment();
1729 if (viewport != null)
1731 return new AlignmentI[] { viewport.getAlignment() };
1743 protected void undoMenuItem_actionPerformed(ActionEvent e)
1745 if (viewport.getHistoryList().isEmpty())
1749 CommandI command = viewport.getHistoryList().pop();
1750 viewport.addToRedoList(command);
1751 command.undoCommand(getViewAlignments());
1753 AlignmentViewport originalSource = getOriginatingSource(command);
1754 updateEditMenuBar();
1756 if (originalSource != null)
1758 if (originalSource != viewport)
1761 "Implementation worry: mismatch of viewport origin for undo");
1763 originalSource.updateHiddenColumns();
1764 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1766 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1767 // viewport.getColumnSelection()
1768 // .getHiddenColumns().size() > 0);
1769 originalSource.firePropertyChange("alignment", null,
1770 originalSource.getAlignment().getSequences());
1781 protected void redoMenuItem_actionPerformed(ActionEvent e)
1783 if (viewport.getRedoList().size() < 1)
1788 CommandI command = viewport.getRedoList().pop();
1789 viewport.addToHistoryList(command);
1790 command.doCommand(getViewAlignments());
1792 AlignmentViewport originalSource = getOriginatingSource(command);
1793 updateEditMenuBar();
1795 if (originalSource != null)
1798 if (originalSource != viewport)
1801 "Implementation worry: mismatch of viewport origin for redo");
1803 originalSource.updateHiddenColumns();
1804 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1806 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1807 // viewport.getColumnSelection()
1808 // .getHiddenColumns().size() > 0);
1809 originalSource.firePropertyChange("alignment", null,
1810 originalSource.getAlignment().getSequences());
1814 AlignmentViewport getOriginatingSource(CommandI command)
1816 AlignmentViewport originalSource = null;
1817 // For sequence removal and addition, we need to fire
1818 // the property change event FROM the viewport where the
1819 // original alignment was altered
1820 AlignmentI al = null;
1821 if (command instanceof EditCommand)
1823 EditCommand editCommand = (EditCommand) command;
1824 al = editCommand.getAlignment();
1825 List<Component> comps = PaintRefresher.components
1826 .get(viewport.getSequenceSetId());
1828 for (Component comp : comps)
1830 if (comp instanceof AlignmentPanel)
1832 if (al == ((AlignmentPanel) comp).av.getAlignment())
1834 originalSource = ((AlignmentPanel) comp).av;
1841 if (originalSource == null)
1843 // The original view is closed, we must validate
1844 // the current view against the closed view first
1847 PaintRefresher.validateSequences(al, viewport.getAlignment());
1850 originalSource = viewport;
1853 return originalSource;
1857 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1858 * or the sequence under cursor in keyboard mode
1863 public void moveSelectedSequences(boolean up)
1865 SequenceGroup sg = viewport.getSelectionGroup();
1869 if (viewport.cursorMode)
1871 sg = new SequenceGroup();
1872 sg.addSequence(viewport.getAlignment().getSequenceAt(
1873 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1881 if (sg.getSize() < 1)
1886 // TODO: JAL-3733 - add an event to the undo buffer for this !
1888 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1889 viewport.getHiddenRepSequences(), up);
1890 alignPanel.paintAlignment(true, false);
1893 synchronized void slideSequences(boolean right, int size)
1895 List<SequenceI> sg = new ArrayList<>();
1896 if (viewport.cursorMode)
1898 sg.add(viewport.getAlignment()
1899 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1901 else if (viewport.getSelectionGroup() != null
1902 && viewport.getSelectionGroup().getSize() != viewport
1903 .getAlignment().getHeight())
1905 sg = viewport.getSelectionGroup()
1906 .getSequences(viewport.getHiddenRepSequences());
1914 List<SequenceI> invertGroup = new ArrayList<>();
1916 for (SequenceI seq : viewport.getAlignment().getSequences())
1918 if (!sg.contains(seq))
1920 invertGroup.add(seq);
1924 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1926 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1927 for (int i = 0; i < invertGroup.size(); i++)
1929 seqs2[i] = invertGroup.get(i);
1932 SlideSequencesCommand ssc;
1935 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1936 viewport.getGapCharacter());
1940 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1941 viewport.getGapCharacter());
1944 int groupAdjustment = 0;
1945 if (ssc.getGapsInsertedBegin() && right)
1947 if (viewport.cursorMode)
1949 alignPanel.getSeqPanel().moveCursor(size, 0);
1953 groupAdjustment = size;
1956 else if (!ssc.getGapsInsertedBegin() && !right)
1958 if (viewport.cursorMode)
1960 alignPanel.getSeqPanel().moveCursor(-size, 0);
1964 groupAdjustment = -size;
1968 if (groupAdjustment != 0)
1970 viewport.getSelectionGroup().setStartRes(
1971 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1972 viewport.getSelectionGroup().setEndRes(
1973 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1977 * just extend the last slide command if compatible; but not if in
1978 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
1980 boolean appendHistoryItem = false;
1981 Deque<CommandI> historyList = viewport.getHistoryList();
1982 boolean inSplitFrame = getSplitViewContainer() != null;
1983 if (!inSplitFrame && historyList != null && historyList.size() > 0
1984 && historyList.peek() instanceof SlideSequencesCommand)
1986 appendHistoryItem = ssc.appendSlideCommand(
1987 (SlideSequencesCommand) historyList.peek());
1990 if (!appendHistoryItem)
1992 addHistoryItem(ssc);
2005 protected void copy_actionPerformed()
2007 if (viewport.getSelectionGroup() == null)
2011 // TODO: preserve the ordering of displayed alignment annotation in any
2012 // internal paste (particularly sequence associated annotation)
2013 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2014 String[] omitHidden = null;
2016 if (viewport.hasHiddenColumns())
2018 omitHidden = viewport.getViewAsString(true);
2021 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2022 seqs, omitHidden, null);
2024 StringSelection ss = new StringSelection(output);
2028 jalview.gui.Desktop.internalCopy = true;
2029 // Its really worth setting the clipboard contents
2030 // to empty before setting the large StringSelection!!
2031 Toolkit.getDefaultToolkit().getSystemClipboard()
2032 .setContents(new StringSelection(""), null);
2034 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2036 } catch (OutOfMemoryError er)
2038 new OOMWarning("copying region", er);
2042 HiddenColumns hiddenColumns = null;
2043 if (viewport.hasHiddenColumns())
2045 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2046 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2048 // create new HiddenColumns object with copy of hidden regions
2049 // between startRes and endRes, offset by startRes
2050 hiddenColumns = new HiddenColumns(
2051 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2052 hiddenCutoff, hiddenOffset);
2055 Desktop.jalviewClipboard = new Object[] { seqs,
2056 viewport.getAlignment().getDataset(), hiddenColumns };
2057 setStatus(MessageManager.formatMessage(
2058 "label.copied_sequences_to_clipboard", new Object[]
2059 { Integer.valueOf(seqs.length).toString() }));
2069 protected void pasteNew_actionPerformed(ActionEvent e)
2081 protected void pasteThis_actionPerformed(ActionEvent e)
2087 * Paste contents of Jalview clipboard
2089 * @param newAlignment
2090 * true to paste to a new alignment, otherwise add to this.
2092 void paste(boolean newAlignment)
2094 boolean externalPaste = true;
2097 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2098 Transferable contents = c.getContents(this);
2100 if (contents == null)
2109 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2110 if (str.length() < 1)
2115 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2117 } catch (OutOfMemoryError er)
2119 new OOMWarning("Out of memory pasting sequences!!", er);
2123 SequenceI[] sequences;
2124 boolean annotationAdded = false;
2125 AlignmentI alignment = null;
2127 if (Desktop.jalviewClipboard != null)
2129 // The clipboard was filled from within Jalview, we must use the
2131 // And dataset from the copied alignment
2132 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2133 // be doubly sure that we create *new* sequence objects.
2134 sequences = new SequenceI[newseq.length];
2135 for (int i = 0; i < newseq.length; i++)
2137 sequences[i] = new Sequence(newseq[i]);
2139 alignment = new Alignment(sequences);
2140 externalPaste = false;
2144 // parse the clipboard as an alignment.
2145 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2147 sequences = alignment.getSequencesArray();
2151 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2157 if (Desktop.jalviewClipboard != null)
2159 // dataset is inherited
2160 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2164 // new dataset is constructed
2165 alignment.setDataset(null);
2167 alwidth = alignment.getWidth() + 1;
2171 AlignmentI pastedal = alignment; // preserve pasted alignment object
2172 // Add pasted sequences and dataset into existing alignment.
2173 alignment = viewport.getAlignment();
2174 alwidth = alignment.getWidth() + 1;
2175 // decide if we need to import sequences from an existing dataset
2176 boolean importDs = Desktop.jalviewClipboard != null
2177 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2178 // importDs==true instructs us to copy over new dataset sequences from
2179 // an existing alignment
2180 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2182 // minimum dataset set
2184 for (int i = 0; i < sequences.length; i++)
2188 newDs.addElement(null);
2190 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2192 if (importDs && ds != null)
2194 if (!newDs.contains(ds))
2196 newDs.setElementAt(ds, i);
2197 ds = new Sequence(ds);
2198 // update with new dataset sequence
2199 sequences[i].setDatasetSequence(ds);
2203 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2208 // copy and derive new dataset sequence
2209 sequences[i] = sequences[i].deriveSequence();
2210 alignment.getDataset()
2211 .addSequence(sequences[i].getDatasetSequence());
2212 // TODO: avoid creation of duplicate dataset sequences with a
2213 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2215 alignment.addSequence(sequences[i]); // merges dataset
2219 newDs.clear(); // tidy up
2221 if (alignment.getAlignmentAnnotation() != null)
2223 for (AlignmentAnnotation alan : alignment
2224 .getAlignmentAnnotation())
2226 if (alan.graphGroup > fgroup)
2228 fgroup = alan.graphGroup;
2232 if (pastedal.getAlignmentAnnotation() != null)
2234 // Add any annotation attached to alignment.
2235 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2236 for (int i = 0; i < alann.length; i++)
2238 annotationAdded = true;
2239 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2241 AlignmentAnnotation newann = new AlignmentAnnotation(
2243 if (newann.graphGroup > -1)
2245 if (newGraphGroups.size() <= newann.graphGroup
2246 || newGraphGroups.get(newann.graphGroup) == null)
2248 for (int q = newGraphGroups
2249 .size(); q <= newann.graphGroup; q++)
2251 newGraphGroups.add(q, null);
2253 newGraphGroups.set(newann.graphGroup,
2254 Integer.valueOf(++fgroup));
2256 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2260 newann.padAnnotation(alwidth);
2261 alignment.addAnnotation(newann);
2271 addHistoryItem(new EditCommand(
2272 MessageManager.getString("label.add_sequences"),
2273 Action.PASTE, sequences, 0, alignment.getWidth(),
2276 // Add any annotations attached to sequences
2277 for (int i = 0; i < sequences.length; i++)
2279 if (sequences[i].getAnnotation() != null)
2281 AlignmentAnnotation newann;
2282 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2284 annotationAdded = true;
2285 newann = sequences[i].getAnnotation()[a];
2286 newann.adjustForAlignment();
2287 newann.padAnnotation(alwidth);
2288 if (newann.graphGroup > -1)
2290 if (newann.graphGroup > -1)
2292 if (newGraphGroups.size() <= newann.graphGroup
2293 || newGraphGroups.get(newann.graphGroup) == null)
2295 for (int q = newGraphGroups
2296 .size(); q <= newann.graphGroup; q++)
2298 newGraphGroups.add(q, null);
2300 newGraphGroups.set(newann.graphGroup,
2301 Integer.valueOf(++fgroup));
2303 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2307 // annotation was duplicated earlier
2308 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2309 // take care of contact matrix too
2310 ContactMatrixI cm=sequences[i].getContactMatrixFor(sequences[i].getAnnotation()[a]);
2313 alignment.addContactListFor(sequences[i].getAnnotation()[a], cm);
2316 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2324 // propagate alignment changed.
2325 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2326 if (annotationAdded)
2328 // Duplicate sequence annotation in all views.
2329 AlignmentI[] alview = this.getViewAlignments();
2330 for (int i = 0; i < sequences.length; i++)
2332 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2337 for (int avnum = 0; avnum < alview.length; avnum++)
2339 if (alview[avnum] != alignment)
2341 // duplicate in a view other than the one with input focus
2342 int avwidth = alview[avnum].getWidth() + 1;
2343 // this relies on sann being preserved after we
2344 // modify the sequence's annotation array for each duplication
2345 for (int a = 0; a < sann.length; a++)
2347 AlignmentAnnotation newann = new AlignmentAnnotation(
2349 sequences[i].addAlignmentAnnotation(newann);
2350 newann.padAnnotation(avwidth);
2351 alview[avnum].addAnnotation(newann); // annotation was
2352 // duplicated earlier
2353 // TODO JAL-1145 graphGroups are not updated for sequence
2354 // annotation added to several views. This may cause
2356 alview[avnum].setAnnotationIndex(newann, a);
2361 buildSortByAnnotationScoresMenu();
2363 viewport.firePropertyChange("alignment", null,
2364 alignment.getSequences());
2365 if (alignPanels != null)
2367 for (AlignmentPanel ap : alignPanels)
2369 ap.validateAnnotationDimensions(false);
2374 alignPanel.validateAnnotationDimensions(false);
2380 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2382 String newtitle = new String("Copied sequences");
2384 if (Desktop.jalviewClipboard != null
2385 && Desktop.jalviewClipboard[2] != null)
2387 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2388 af.viewport.setHiddenColumns(hc);
2391 // >>>This is a fix for the moment, until a better solution is
2393 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2394 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2395 .getFeatureRenderer());
2397 // TODO: maintain provenance of an alignment, rather than just make the
2398 // title a concatenation of operations.
2401 if (title.startsWith("Copied sequences"))
2407 newtitle = newtitle.concat("- from " + title);
2412 newtitle = new String("Pasted sequences");
2415 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2420 } catch (Exception ex)
2422 ex.printStackTrace();
2423 System.out.println("Exception whilst pasting: " + ex);
2424 // could be anything being pasted in here
2430 protected void expand_newalign(ActionEvent e)
2434 AlignmentI alignment = AlignmentUtils
2435 .expandContext(getViewport().getAlignment(), -1);
2436 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2438 String newtitle = new String("Flanking alignment");
2440 if (Desktop.jalviewClipboard != null
2441 && Desktop.jalviewClipboard[2] != null)
2443 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2444 af.viewport.setHiddenColumns(hc);
2447 // >>>This is a fix for the moment, until a better solution is
2449 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2450 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2451 .getFeatureRenderer());
2453 // TODO: maintain provenance of an alignment, rather than just make the
2454 // title a concatenation of operations.
2456 if (title.startsWith("Copied sequences"))
2462 newtitle = newtitle.concat("- from " + title);
2466 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2468 } catch (Exception ex)
2470 ex.printStackTrace();
2471 System.out.println("Exception whilst pasting: " + ex);
2472 // could be anything being pasted in here
2473 } catch (OutOfMemoryError oom)
2475 new OOMWarning("Viewing flanking region of alignment", oom);
2480 * Action Cut (delete and copy) the selected region
2483 protected void cut_actionPerformed()
2485 copy_actionPerformed();
2486 delete_actionPerformed();
2490 * Performs menu option to Delete the currently selected region
2493 protected void delete_actionPerformed()
2496 SequenceGroup sg = viewport.getSelectionGroup();
2502 Callable okAction = () -> {
2503 SequenceI[] cut = sg.getSequences()
2504 .toArray(new SequenceI[sg.getSize()]);
2506 addHistoryItem(new EditCommand(
2507 MessageManager.getString("label.cut_sequences"), Action.CUT,
2508 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2509 viewport.getAlignment()));
2511 viewport.setSelectionGroup(null);
2512 viewport.sendSelection();
2513 viewport.getAlignment().deleteGroup(sg);
2515 viewport.firePropertyChange("alignment", null,
2516 viewport.getAlignment().getSequences());
2517 if (viewport.getAlignment().getHeight() < 1)
2521 AlignFrame.this.setClosed(true);
2522 } catch (Exception ex)
2530 * If the cut affects all sequences, prompt for confirmation
2532 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2534 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2535 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2536 if (wholeHeight && wholeWidth)
2538 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2539 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2540 Object[] options = new Object[] {
2541 MessageManager.getString("action.ok"),
2542 MessageManager.getString("action.cancel") };
2543 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2544 MessageManager.getString("label.delete_all"),
2545 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2546 options, options[0]);
2553 } catch (Exception e)
2555 e.printStackTrace();
2567 protected void deleteGroups_actionPerformed(ActionEvent e)
2569 if (avc.deleteGroups())
2571 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2572 alignPanel.updateAnnotation();
2573 alignPanel.paintAlignment(true, true);
2584 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2586 SequenceGroup sg = new SequenceGroup(
2587 viewport.getAlignment().getSequences());
2589 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2590 viewport.setSelectionGroup(sg);
2591 viewport.isSelectionGroupChanged(true);
2592 viewport.sendSelection();
2593 // JAL-2034 - should delegate to
2594 // alignPanel to decide if overview needs
2596 alignPanel.paintAlignment(false, false);
2597 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2607 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2609 if (viewport.cursorMode)
2611 alignPanel.getSeqPanel().keyboardNo1 = null;
2612 alignPanel.getSeqPanel().keyboardNo2 = null;
2614 viewport.setSelectionGroup(null);
2615 viewport.getColumnSelection().clear();
2616 viewport.setSearchResults(null);
2617 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2618 // JAL-2034 - should delegate to
2619 // alignPanel to decide if overview needs
2621 alignPanel.paintAlignment(false, false);
2622 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2623 viewport.sendSelection();
2633 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2635 SequenceGroup sg = viewport.getSelectionGroup();
2639 selectAllSequenceMenuItem_actionPerformed(null);
2644 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2646 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2648 // JAL-2034 - should delegate to
2649 // alignPanel to decide if overview needs
2652 alignPanel.paintAlignment(true, false);
2653 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2654 viewport.sendSelection();
2658 public void invertColSel_actionPerformed(ActionEvent e)
2660 viewport.invertColumnSelection();
2661 alignPanel.paintAlignment(true, false);
2662 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2663 viewport.sendSelection();
2673 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2675 trimAlignment(true);
2685 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2687 trimAlignment(false);
2690 void trimAlignment(boolean trimLeft)
2692 ColumnSelection colSel = viewport.getColumnSelection();
2695 if (!colSel.isEmpty())
2699 column = colSel.getMin();
2703 column = colSel.getMax();
2707 if (viewport.getSelectionGroup() != null)
2709 seqs = viewport.getSelectionGroup()
2710 .getSequencesAsArray(viewport.getHiddenRepSequences());
2714 seqs = viewport.getAlignment().getSequencesArray();
2717 TrimRegionCommand trimRegion;
2720 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2721 column, viewport.getAlignment());
2722 viewport.getRanges().setStartRes(0);
2726 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2727 column, viewport.getAlignment());
2730 setStatus(MessageManager.formatMessage("label.removed_columns",
2732 { Integer.valueOf(trimRegion.getSize()).toString() }));
2734 addHistoryItem(trimRegion);
2736 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2738 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2739 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2741 viewport.getAlignment().deleteGroup(sg);
2745 viewport.firePropertyChange("alignment", null,
2746 viewport.getAlignment().getSequences());
2757 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2759 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2762 if (viewport.getSelectionGroup() != null)
2764 seqs = viewport.getSelectionGroup()
2765 .getSequencesAsArray(viewport.getHiddenRepSequences());
2766 start = viewport.getSelectionGroup().getStartRes();
2767 end = viewport.getSelectionGroup().getEndRes();
2771 seqs = viewport.getAlignment().getSequencesArray();
2774 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2775 "Remove Gapped Columns", seqs, start, end,
2776 viewport.getAlignment());
2778 addHistoryItem(removeGapCols);
2780 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2782 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2784 // This is to maintain viewport position on first residue
2785 // of first sequence
2786 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2787 ViewportRanges ranges = viewport.getRanges();
2788 int startRes = seq.findPosition(ranges.getStartRes());
2789 // ShiftList shifts;
2790 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2791 // edit.alColumnChanges=shifts.getInverse();
2792 // if (viewport.hasHiddenColumns)
2793 // viewport.getColumnSelection().compensateForEdits(shifts);
2794 ranges.setStartRes(seq.findIndex(startRes) - 1);
2795 viewport.firePropertyChange("alignment", null,
2796 viewport.getAlignment().getSequences());
2807 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2809 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2812 if (viewport.getSelectionGroup() != null)
2814 seqs = viewport.getSelectionGroup()
2815 .getSequencesAsArray(viewport.getHiddenRepSequences());
2816 start = viewport.getSelectionGroup().getStartRes();
2817 end = viewport.getSelectionGroup().getEndRes();
2821 seqs = viewport.getAlignment().getSequencesArray();
2824 // This is to maintain viewport position on first residue
2825 // of first sequence
2826 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2827 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2829 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2830 viewport.getAlignment()));
2832 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2834 viewport.firePropertyChange("alignment", null,
2835 viewport.getAlignment().getSequences());
2846 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2848 viewport.setPadGaps(padGapsMenuitem.isSelected());
2849 viewport.firePropertyChange("alignment", null,
2850 viewport.getAlignment().getSequences());
2854 * Opens a Finder dialog
2859 public void findMenuItem_actionPerformed(ActionEvent e)
2861 new Finder(alignPanel, false, null);
2865 * Create a new view of the current alignment.
2868 public void newView_actionPerformed(ActionEvent e)
2870 newView(null, true);
2874 * Creates and shows a new view of the current alignment.
2877 * title of newly created view; if null, one will be generated
2878 * @param copyAnnotation
2879 * if true then duplicate all annnotation, groups and settings
2880 * @return new alignment panel, already displayed.
2882 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2885 * Create a new AlignmentPanel (with its own, new Viewport)
2887 AlignmentPanel newap = new jalview.project.Jalview2XML()
2888 .copyAlignPanel(alignPanel);
2889 if (!copyAnnotation)
2892 * remove all groups and annotation except for the automatic stuff
2894 newap.av.getAlignment().deleteAllGroups();
2895 newap.av.getAlignment().deleteAllAnnotations(false);
2898 newap.av.setGatherViewsHere(false);
2900 if (viewport.getViewName() == null)
2902 viewport.setViewName(
2903 MessageManager.getString("label.view_name_original"));
2907 * Views share the same edits undo and redo stacks
2909 newap.av.setHistoryList(viewport.getHistoryList());
2910 newap.av.setRedoList(viewport.getRedoList());
2913 * copy any visualisation settings that are not saved in the project
2915 newap.av.setColourAppliesToAllGroups(
2916 viewport.getColourAppliesToAllGroups());
2919 * Views share the same mappings; need to deregister any new mappings
2920 * created by copyAlignPanel, and register the new reference to the shared
2923 newap.av.replaceMappings(viewport.getAlignment());
2926 * start up cDNA consensus (if applicable) now mappings are in place
2928 if (newap.av.initComplementConsensus())
2930 newap.refresh(true); // adjust layout of annotations
2933 newap.av.setViewName(getNewViewName(viewTitle));
2935 addAlignmentPanel(newap, true);
2936 newap.alignmentChanged();
2938 if (alignPanels.size() == 2)
2940 viewport.setGatherViewsHere(true);
2942 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2948 * Make a new name for the view, ensuring it is unique within the current
2949 * sequenceSetId. (This used to be essential for Jalview Project archives, but
2950 * these now use viewId. Unique view names are still desirable for usability.)
2955 protected String getNewViewName(String viewTitle)
2957 int index = Desktop.getViewCount(viewport.getSequenceSetId());
2958 boolean addFirstIndex = false;
2959 if (viewTitle == null || viewTitle.trim().length() == 0)
2961 viewTitle = MessageManager.getString("action.view");
2962 addFirstIndex = true;
2966 index = 1;// we count from 1 if given a specific name
2968 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
2970 List<Component> comps = PaintRefresher.components
2971 .get(viewport.getSequenceSetId());
2973 List<String> existingNames = getExistingViewNames(comps);
2975 while (existingNames.contains(newViewName))
2977 newViewName = viewTitle + " " + (++index);
2983 * Returns a list of distinct view names found in the given list of
2984 * components. View names are held on the viewport of an AlignmentPanel.
2989 protected List<String> getExistingViewNames(List<Component> comps)
2991 List<String> existingNames = new ArrayList<>();
2992 for (Component comp : comps)
2994 if (comp instanceof AlignmentPanel)
2996 AlignmentPanel ap = (AlignmentPanel) comp;
2997 if (!existingNames.contains(ap.av.getViewName()))
2999 existingNames.add(ap.av.getViewName());
3003 return existingNames;
3007 * Explode tabbed views into separate windows.
3010 public void expandViews_actionPerformed(ActionEvent e)
3012 Desktop.explodeViews(this);
3016 * Gather views in separate windows back into a tabbed presentation.
3019 public void gatherViews_actionPerformed(ActionEvent e)
3021 Desktop.instance.gatherViews(this);
3031 public void font_actionPerformed(ActionEvent e)
3033 new FontChooser(alignPanel);
3043 protected void seqLimit_actionPerformed(ActionEvent e)
3045 viewport.setShowJVSuffix(seqLimits.isSelected());
3047 alignPanel.getIdPanel().getIdCanvas()
3048 .setPreferredSize(alignPanel.calculateIdWidth());
3049 alignPanel.paintAlignment(true, false);
3053 public void idRightAlign_actionPerformed(ActionEvent e)
3055 viewport.setRightAlignIds(idRightAlign.isSelected());
3056 alignPanel.paintAlignment(false, false);
3060 public void centreColumnLabels_actionPerformed(ActionEvent e)
3062 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3063 alignPanel.paintAlignment(false, false);
3069 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3072 protected void followHighlight_actionPerformed()
3075 * Set the 'follow' flag on the Viewport (and scroll to position if now
3078 final boolean state = this.followHighlightMenuItem.getState();
3079 viewport.setFollowHighlight(state);
3082 alignPanel.scrollToPosition(viewport.getSearchResults());
3093 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3095 viewport.setColourText(colourTextMenuItem.isSelected());
3096 alignPanel.paintAlignment(false, false);
3106 public void wrapMenuItem_actionPerformed(ActionEvent e)
3108 scaleAbove.setVisible(wrapMenuItem.isSelected());
3109 scaleLeft.setVisible(wrapMenuItem.isSelected());
3110 scaleRight.setVisible(wrapMenuItem.isSelected());
3111 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3112 alignPanel.updateLayout();
3116 public void showAllSeqs_actionPerformed(ActionEvent e)
3118 viewport.showAllHiddenSeqs();
3122 public void showAllColumns_actionPerformed(ActionEvent e)
3124 viewport.showAllHiddenColumns();
3125 alignPanel.paintAlignment(true, true);
3126 viewport.sendSelection();
3130 public void hideSelSequences_actionPerformed(ActionEvent e)
3132 viewport.hideAllSelectedSeqs();
3136 * called by key handler and the hide all/show all menu items
3141 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3144 boolean hide = false;
3145 SequenceGroup sg = viewport.getSelectionGroup();
3146 if (!toggleSeqs && !toggleCols)
3148 // Hide everything by the current selection - this is a hack - we do the
3149 // invert and then hide
3150 // first check that there will be visible columns after the invert.
3151 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3152 && sg.getStartRes() <= sg.getEndRes()))
3154 // now invert the sequence set, if required - empty selection implies
3155 // that no hiding is required.
3158 invertSequenceMenuItem_actionPerformed(null);
3159 sg = viewport.getSelectionGroup();
3163 viewport.expandColSelection(sg, true);
3164 // finally invert the column selection and get the new sequence
3166 invertColSel_actionPerformed(null);
3173 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3175 hideSelSequences_actionPerformed(null);
3178 else if (!(toggleCols && viewport.hasSelectedColumns()))
3180 showAllSeqs_actionPerformed(null);
3186 if (viewport.hasSelectedColumns())
3188 hideSelColumns_actionPerformed(null);
3191 viewport.setSelectionGroup(sg);
3196 showAllColumns_actionPerformed(null);
3205 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3206 * event.ActionEvent)
3209 public void hideAllButSelection_actionPerformed(ActionEvent e)
3211 toggleHiddenRegions(false, false);
3212 viewport.sendSelection();
3219 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3223 public void hideAllSelection_actionPerformed(ActionEvent e)
3225 SequenceGroup sg = viewport.getSelectionGroup();
3226 viewport.expandColSelection(sg, false);
3227 viewport.hideAllSelectedSeqs();
3228 viewport.hideSelectedColumns();
3229 alignPanel.updateLayout();
3230 alignPanel.paintAlignment(true, true);
3231 viewport.sendSelection();
3238 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3242 public void showAllhidden_actionPerformed(ActionEvent e)
3244 viewport.showAllHiddenColumns();
3245 viewport.showAllHiddenSeqs();
3246 alignPanel.paintAlignment(true, true);
3247 viewport.sendSelection();
3251 public void hideSelColumns_actionPerformed(ActionEvent e)
3253 viewport.hideSelectedColumns();
3254 alignPanel.updateLayout();
3255 alignPanel.paintAlignment(true, true);
3256 viewport.sendSelection();
3260 public void hiddenMarkers_actionPerformed(ActionEvent e)
3262 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3273 protected void scaleAbove_actionPerformed(ActionEvent e)
3275 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3276 alignPanel.updateLayout();
3277 alignPanel.paintAlignment(true, false);
3287 protected void scaleLeft_actionPerformed(ActionEvent e)
3289 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3290 alignPanel.updateLayout();
3291 alignPanel.paintAlignment(true, false);
3301 protected void scaleRight_actionPerformed(ActionEvent e)
3303 viewport.setScaleRightWrapped(scaleRight.isSelected());
3304 alignPanel.updateLayout();
3305 alignPanel.paintAlignment(true, false);
3315 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3317 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3318 alignPanel.paintAlignment(false, false);
3328 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3330 viewport.setShowText(viewTextMenuItem.isSelected());
3331 alignPanel.paintAlignment(false, false);
3341 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3343 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3344 alignPanel.paintAlignment(false, false);
3347 public FeatureSettings featureSettings;
3350 public FeatureSettingsControllerI getFeatureSettingsUI()
3352 return featureSettings;
3356 public void featureSettings_actionPerformed(ActionEvent e)
3358 showFeatureSettingsUI();
3362 public FeatureSettingsControllerI showFeatureSettingsUI()
3364 if (featureSettings != null)
3366 featureSettings.closeOldSettings();
3367 featureSettings = null;
3369 if (!showSeqFeatures.isSelected())
3371 // make sure features are actually displayed
3372 showSeqFeatures.setSelected(true);
3373 showSeqFeatures_actionPerformed(null);
3375 featureSettings = new FeatureSettings(this);
3376 return featureSettings;
3380 * Set or clear 'Show Sequence Features'
3386 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3388 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3389 alignPanel.paintAlignment(true, true);
3393 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3394 * the annotations panel as a whole.
3396 * The options to show/hide all annotations should be enabled when the panel
3397 * is shown, and disabled when the panel is hidden.
3402 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3404 final boolean setVisible = annotationPanelMenuItem.isSelected();
3405 viewport.setShowAnnotation(setVisible);
3406 this.showAllSeqAnnotations.setEnabled(setVisible);
3407 this.hideAllSeqAnnotations.setEnabled(setVisible);
3408 this.showAllAlAnnotations.setEnabled(setVisible);
3409 this.hideAllAlAnnotations.setEnabled(setVisible);
3410 alignPanel.updateLayout();
3414 public void alignmentProperties()
3417 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3420 String content = MessageManager.formatMessage("label.html_content",
3422 { contents.toString() });
3425 if (Platform.isJS())
3427 JLabel textLabel = new JLabel();
3428 textLabel.setText(content);
3429 textLabel.setBackground(Color.WHITE);
3431 pane = new JPanel(new BorderLayout());
3432 ((JPanel) pane).setOpaque(true);
3433 pane.setBackground(Color.WHITE);
3434 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3443 JEditorPane editPane = new JEditorPane("text/html", "");
3444 editPane.setEditable(false);
3445 editPane.setText(content);
3449 JInternalFrame frame = new JInternalFrame();
3451 frame.getContentPane().add(new JScrollPane(pane));
3453 Desktop.addInternalFrame(frame, MessageManager
3454 .formatMessage("label.alignment_properties", new Object[]
3455 { getTitle() }), 500, 400);
3459 * Opens an Overview panel for the alignment, unless one is open already
3464 public void overviewMenuItem_actionPerformed(ActionEvent e)
3466 boolean showHiddenRegions = Cache
3467 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3468 openOverviewPanel(showHiddenRegions);
3471 public OverviewPanel openOverviewPanel(boolean showHidden)
3473 if (alignPanel.overviewPanel != null)
3475 return alignPanel.overviewPanel;
3477 JInternalFrame frame = new JInternalFrame();
3478 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3480 frame.setContentPane(overview);
3481 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3482 frame.getHeight(), true, true);
3483 frame.setFrameIcon(null);
3485 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3486 final AlignmentPanel thePanel = this.alignPanel;
3487 frame.addInternalFrameListener(
3488 new javax.swing.event.InternalFrameAdapter()
3491 public void internalFrameClosed(
3492 javax.swing.event.InternalFrameEvent evt)
3495 thePanel.setOverviewPanel(null);
3498 if (getKeyListeners().length > 0)
3500 frame.addKeyListener(getKeyListeners()[0]);
3503 alignPanel.setOverviewPanel(overview);
3504 alignPanel.setOverviewTitle(this);
3510 public void textColour_actionPerformed()
3512 new TextColourChooser().chooseColour(alignPanel, null);
3516 * public void covariationColour_actionPerformed() {
3518 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3522 public void annotationColour_actionPerformed()
3524 new AnnotationColourChooser(viewport, alignPanel);
3528 public void annotationColumn_actionPerformed(ActionEvent e)
3530 new AnnotationColumnChooser(viewport, alignPanel);
3534 * Action on the user checking or unchecking the option to apply the selected
3535 * colour scheme to all groups. If unchecked, groups may have their own
3536 * independent colour schemes.
3541 public void applyToAllGroups_actionPerformed(boolean selected)
3543 viewport.setColourAppliesToAllGroups(selected);
3547 * Action on user selecting a colour from the colour menu
3550 * the name (not the menu item label!) of the colour scheme
3553 public void changeColour_actionPerformed(String name)
3556 * 'User Defined' opens a panel to configure or load a
3557 * user-defined colour scheme
3559 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3561 new UserDefinedColours(alignPanel);
3566 * otherwise set the chosen colour scheme (or null for 'None')
3568 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3569 viewport, viewport.getAlignment(),
3570 viewport.getHiddenRepSequences());
3575 * Actions on setting or changing the alignment colour scheme
3580 public void changeColour(ColourSchemeI cs)
3582 // TODO: pull up to controller method
3583 ColourMenuHelper.setColourSelected(colourMenu, cs);
3585 viewport.setGlobalColourScheme(cs);
3587 alignPanel.paintAlignment(true, true);
3591 * Show the PID threshold slider panel
3594 protected void modifyPID_actionPerformed()
3596 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3597 alignPanel.getViewName());
3598 SliderPanel.showPIDSlider();
3602 * Show the Conservation slider panel
3605 protected void modifyConservation_actionPerformed()
3607 SliderPanel.setConservationSlider(alignPanel,
3608 viewport.getResidueShading(), alignPanel.getViewName());
3609 SliderPanel.showConservationSlider();
3613 * Action on selecting or deselecting (Colour) By Conservation
3616 public void conservationMenuItem_actionPerformed(boolean selected)
3618 modifyConservation.setEnabled(selected);
3619 viewport.setConservationSelected(selected);
3620 viewport.getResidueShading().setConservationApplied(selected);
3622 changeColour(viewport.getGlobalColourScheme());
3625 modifyConservation_actionPerformed();
3629 SliderPanel.hideConservationSlider();
3634 * Action on selecting or deselecting (Colour) Above PID Threshold
3637 public void abovePIDThreshold_actionPerformed(boolean selected)
3639 modifyPID.setEnabled(selected);
3640 viewport.setAbovePIDThreshold(selected);
3643 viewport.getResidueShading().setThreshold(0,
3644 viewport.isIgnoreGapsConsensus());
3647 changeColour(viewport.getGlobalColourScheme());
3650 modifyPID_actionPerformed();
3654 SliderPanel.hidePIDSlider();
3665 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3667 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3668 AlignmentSorter.sortByPID(viewport.getAlignment(),
3669 viewport.getAlignment().getSequenceAt(0));
3670 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3671 viewport.getAlignment()));
3672 alignPanel.paintAlignment(true, false);
3682 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3684 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3685 AlignmentSorter.sortByID(viewport.getAlignment());
3687 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3688 alignPanel.paintAlignment(true, false);
3698 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3700 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3701 AlignmentSorter.sortByLength(viewport.getAlignment());
3702 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3703 viewport.getAlignment()));
3704 alignPanel.paintAlignment(true, false);
3714 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3716 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3717 AlignmentSorter.sortByGroup(viewport.getAlignment());
3718 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3719 viewport.getAlignment()));
3721 alignPanel.paintAlignment(true, false);
3731 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3733 new RedundancyPanel(alignPanel, this);
3743 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3745 if ((viewport.getSelectionGroup() == null)
3746 || (viewport.getSelectionGroup().getSize() < 2))
3748 JvOptionPane.showInternalMessageDialog(this,
3749 MessageManager.getString(
3750 "label.you_must_select_least_two_sequences"),
3751 MessageManager.getString("label.invalid_selection"),
3752 JvOptionPane.WARNING_MESSAGE);
3756 JInternalFrame frame = new JInternalFrame();
3757 frame.setContentPane(new PairwiseAlignPanel(viewport));
3758 Desktop.addInternalFrame(frame,
3759 MessageManager.getString("action.pairwise_alignment"), 600,
3765 public void autoCalculate_actionPerformed(ActionEvent e)
3767 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3768 if (viewport.autoCalculateConsensus)
3770 viewport.firePropertyChange("alignment", null,
3771 viewport.getAlignment().getSequences());
3776 public void sortByTreeOption_actionPerformed(ActionEvent e)
3778 viewport.sortByTree = sortByTree.isSelected();
3782 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3784 viewport.followSelection = listenToViewSelections.isSelected();
3788 * Constructs a tree panel and adds it to the desktop
3791 * tree type (NJ or AV)
3793 * name of score model used to compute the tree
3795 * parameters for the distance or similarity calculation
3797 void newTreePanel(String type, String modelName,
3798 SimilarityParamsI options)
3800 String frameTitle = "";
3803 boolean onSelection = false;
3804 if (viewport.getSelectionGroup() != null
3805 && viewport.getSelectionGroup().getSize() > 0)
3807 SequenceGroup sg = viewport.getSelectionGroup();
3809 /* Decide if the selection is a column region */
3810 for (SequenceI _s : sg.getSequences())
3812 if (_s.getLength() < sg.getEndRes())
3814 JvOptionPane.showMessageDialog(Desktop.desktop,
3815 MessageManager.getString(
3816 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3817 MessageManager.getString(
3818 "label.sequences_selection_not_aligned"),
3819 JvOptionPane.WARNING_MESSAGE);
3828 if (viewport.getAlignment().getHeight() < 2)
3834 tp = new TreePanel(alignPanel, type, modelName, options);
3835 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3837 frameTitle += " from ";
3839 if (viewport.getViewName() != null)
3841 frameTitle += viewport.getViewName() + " of ";
3844 frameTitle += this.title;
3846 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3857 public void addSortByOrderMenuItem(String title,
3858 final AlignmentOrder order)
3860 final JMenuItem item = new JMenuItem(MessageManager
3861 .formatMessage("action.by_title_param", new Object[]
3864 item.addActionListener(new java.awt.event.ActionListener()
3867 public void actionPerformed(ActionEvent e)
3869 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3871 // TODO: JBPNote - have to map order entries to curent SequenceI
3873 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3875 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3876 viewport.getAlignment()));
3878 alignPanel.paintAlignment(true, false);
3884 * Add a new sort by annotation score menu item
3887 * the menu to add the option to
3889 * the label used to retrieve scores for each sequence on the
3892 public void addSortByAnnotScoreMenuItem(JMenu sort,
3893 final String scoreLabel)
3895 final JMenuItem item = new JMenuItem(scoreLabel);
3897 item.addActionListener(new java.awt.event.ActionListener()
3900 public void actionPerformed(ActionEvent e)
3902 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3903 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3904 viewport.getAlignment());// ,viewport.getSelectionGroup());
3905 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3906 viewport.getAlignment()));
3907 alignPanel.paintAlignment(true, false);
3913 * last hash for alignment's annotation array - used to minimise cost of
3916 protected int _annotationScoreVectorHash;
3919 * search the alignment and rebuild the sort by annotation score submenu the
3920 * last alignment annotation vector hash is stored to minimize cost of
3921 * rebuilding in subsequence calls.
3925 public void buildSortByAnnotationScoresMenu()
3927 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3932 if (viewport.getAlignment().getAlignmentAnnotation()
3933 .hashCode() != _annotationScoreVectorHash)
3935 sortByAnnotScore.removeAll();
3936 // almost certainly a quicker way to do this - but we keep it simple
3937 Hashtable<String, String> scoreSorts = new Hashtable<>();
3938 AlignmentAnnotation aann[];
3939 for (SequenceI sqa : viewport.getAlignment().getSequences())
3941 aann = sqa.getAnnotation();
3942 for (int i = 0; aann != null && i < aann.length; i++)
3944 if (aann[i].hasScore() && aann[i].sequenceRef != null)
3946 scoreSorts.put(aann[i].label, aann[i].label);
3950 Enumeration<String> labels = scoreSorts.keys();
3951 while (labels.hasMoreElements())
3953 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
3955 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
3958 _annotationScoreVectorHash = viewport.getAlignment()
3959 .getAlignmentAnnotation().hashCode();
3964 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
3965 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
3966 * call. Listeners are added to remove the menu item when the treePanel is
3967 * closed, and adjust the tree leaf to sequence mapping when the alignment is
3971 public void buildTreeSortMenu()
3973 sortByTreeMenu.removeAll();
3975 List<Component> comps = PaintRefresher.components
3976 .get(viewport.getSequenceSetId());
3977 List<TreePanel> treePanels = new ArrayList<>();
3978 for (Component comp : comps)
3980 if (comp instanceof TreePanel)
3982 treePanels.add((TreePanel) comp);
3986 if (treePanels.size() < 1)
3988 sortByTreeMenu.setVisible(false);
3992 sortByTreeMenu.setVisible(true);
3994 for (final TreePanel tp : treePanels)
3996 final JMenuItem item = new JMenuItem(tp.getTitle());
3997 item.addActionListener(new java.awt.event.ActionListener()
4000 public void actionPerformed(ActionEvent e)
4002 tp.sortByTree_actionPerformed();
4003 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4008 sortByTreeMenu.add(item);
4012 public boolean sortBy(AlignmentOrder alorder, String undoname)
4014 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4015 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4016 if (undoname != null)
4018 addHistoryItem(new OrderCommand(undoname, oldOrder,
4019 viewport.getAlignment()));
4021 alignPanel.paintAlignment(true, false);
4026 * Work out whether the whole set of sequences or just the selected set will
4027 * be submitted for multiple alignment.
4030 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4032 // Now, check we have enough sequences
4033 AlignmentView msa = null;
4035 if ((viewport.getSelectionGroup() != null)
4036 && (viewport.getSelectionGroup().getSize() > 1))
4038 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4039 // some common interface!
4041 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4042 * SequenceI[sz = seqs.getSize(false)];
4044 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4045 * seqs.getSequenceAt(i); }
4047 msa = viewport.getAlignmentView(true);
4049 else if (viewport.getSelectionGroup() != null
4050 && viewport.getSelectionGroup().getSize() == 1)
4052 int option = JvOptionPane.showConfirmDialog(this,
4053 MessageManager.getString("warn.oneseq_msainput_selection"),
4054 MessageManager.getString("label.invalid_selection"),
4055 JvOptionPane.OK_CANCEL_OPTION);
4056 if (option == JvOptionPane.OK_OPTION)
4058 msa = viewport.getAlignmentView(false);
4063 msa = viewport.getAlignmentView(false);
4069 * Decides what is submitted to a secondary structure prediction service: the
4070 * first sequence in the alignment, or in the current selection, or, if the
4071 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4072 * region or the whole alignment. (where the first sequence in the set is the
4073 * one that the prediction will be for).
4075 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4077 AlignmentView seqs = null;
4079 if ((viewport.getSelectionGroup() != null)
4080 && (viewport.getSelectionGroup().getSize() > 0))
4082 seqs = viewport.getAlignmentView(true);
4086 seqs = viewport.getAlignmentView(false);
4088 // limit sequences - JBPNote in future - could spawn multiple prediction
4090 // TODO: viewport.getAlignment().isAligned is a global state - the local
4091 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4092 if (!viewport.getAlignment().isAligned(false))
4094 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4095 // TODO: if seqs.getSequences().length>1 then should really have warned
4109 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4111 // Pick the tree file
4112 JalviewFileChooser chooser = new JalviewFileChooser(
4113 Cache.getProperty("LAST_DIRECTORY"));
4114 chooser.setFileView(new JalviewFileView());
4115 chooser.setDialogTitle(
4116 MessageManager.getString("label.select_newick_like_tree_file"));
4117 chooser.setToolTipText(
4118 MessageManager.getString("label.load_tree_file"));
4120 chooser.setResponseHandler(0, () -> {
4121 String filePath = chooser.getSelectedFile().getPath();
4122 Cache.setProperty("LAST_DIRECTORY", filePath);
4123 NewickFile fin = null;
4126 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4127 DataSourceType.FILE));
4128 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4129 } catch (Exception ex)
4131 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4132 MessageManager.getString("label.problem_reading_tree_file"),
4133 JvOptionPane.WARNING_MESSAGE);
4134 ex.printStackTrace();
4136 if (fin != null && fin.hasWarningMessage())
4138 JvOptionPane.showMessageDialog(Desktop.desktop,
4139 fin.getWarningMessage(),
4141 .getString("label.possible_problem_with_tree_file"),
4142 JvOptionPane.WARNING_MESSAGE);
4146 chooser.showOpenDialog(this);
4149 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4151 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4154 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4155 int h, int x, int y)
4157 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4161 * Add a treeviewer for the tree extracted from a Newick file object to the
4162 * current alignment view
4169 * Associated alignment input data (or null)
4178 * @return TreePanel handle
4180 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4181 AlignmentView input, int w, int h, int x, int y)
4183 TreePanel tp = null;
4189 if (nf.getTree() != null)
4191 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4197 tp.setLocation(x, y);
4200 Desktop.addInternalFrame(tp, treeTitle, w, h);
4202 } catch (Exception ex)
4204 ex.printStackTrace();
4210 public void showContactMapTree(AlignmentAnnotation aa,
4214 int w = 400, h = 500;
4218 NewickFile fin = new NewickFile(
4219 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4220 String title = cm.getAnnotLabel() + " " + cm.getTreeMethod() + " tree"
4221 + aa.sequenceRef != null
4222 ? (" for " + aa.sequenceRef.getDisplayId(false))
4225 showColumnWiseTree(fin, aa, title, w, h, x, y);
4226 } catch (Throwable xx)
4228 Console.error("Unexpected exception showing tree for contact matrix",
4233 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4234 String treeTitle, int w, int h, int x, int y)
4239 if (nf.getTree() == null)
4243 TreePanel tp = new TreePanel(alignPanel, nf, aa, title);
4249 tp.setLocation(x, y);
4252 Desktop.addInternalFrame(tp, title, w, h);
4254 } catch (Throwable xx)
4256 Console.error("Unexpected exception showing tree for contact matrix",
4262 private boolean buildingMenu = false;
4265 * Generates menu items and listener event actions for web service clients
4268 public void BuildWebServiceMenu()
4270 while (buildingMenu)
4274 System.err.println("Waiting for building menu to finish.");
4276 } catch (Exception e)
4280 final AlignFrame me = this;
4281 buildingMenu = true;
4282 new Thread(new Runnable()
4287 final List<JMenuItem> legacyItems = new ArrayList<>();
4290 // System.err.println("Building ws menu again "
4291 // + Thread.currentThread());
4292 // TODO: add support for context dependent disabling of services based
4294 // alignment and current selection
4295 // TODO: add additional serviceHandle parameter to specify abstract
4297 // class independently of AbstractName
4298 // TODO: add in rediscovery GUI function to restart discoverer
4299 // TODO: group services by location as well as function and/or
4301 // object broker mechanism.
4302 final Vector<JMenu> wsmenu = new Vector<>();
4303 final IProgressIndicator af = me;
4306 * do not i18n these strings - they are hard-coded in class
4307 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4308 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4310 final JMenu msawsmenu = new JMenu("Alignment");
4311 final JMenu secstrmenu = new JMenu(
4312 "Secondary Structure Prediction");
4313 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4314 final JMenu analymenu = new JMenu("Analysis");
4315 final JMenu dismenu = new JMenu("Protein Disorder");
4316 // JAL-940 - only show secondary structure prediction services from
4317 // the legacy server
4318 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4320 Discoverer.services != null && (Discoverer.services.size() > 0))
4322 // TODO: refactor to allow list of AbstractName/Handler bindings to
4324 // stored or retrieved from elsewhere
4325 // No MSAWS used any more:
4326 // Vector msaws = null; // (Vector)
4327 // Discoverer.services.get("MsaWS");
4328 Vector<ServiceHandle> secstrpr = Discoverer.services
4330 if (secstrpr != null)
4332 // Add any secondary structure prediction services
4333 for (int i = 0, j = secstrpr.size(); i < j; i++)
4335 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4336 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4337 .getServiceClient(sh);
4338 int p = secstrmenu.getItemCount();
4339 impl.attachWSMenuEntry(secstrmenu, me);
4340 int q = secstrmenu.getItemCount();
4341 for (int litm = p; litm < q; litm++)
4343 legacyItems.add(secstrmenu.getItem(litm));
4349 // Add all submenus in the order they should appear on the web
4351 wsmenu.add(msawsmenu);
4352 wsmenu.add(secstrmenu);
4353 wsmenu.add(dismenu);
4354 wsmenu.add(analymenu);
4355 // No search services yet
4356 // wsmenu.add(seqsrchmenu);
4358 javax.swing.SwingUtilities.invokeLater(new Runnable()
4365 webService.removeAll();
4366 // first, add discovered services onto the webservices menu
4367 if (wsmenu.size() > 0)
4369 for (int i = 0, j = wsmenu.size(); i < j; i++)
4371 webService.add(wsmenu.get(i));
4376 webService.add(me.webServiceNoServices);
4378 // TODO: move into separate menu builder class.
4380 // logic for 2.11.1.4 is
4381 // always look to see if there is a discover. if there isn't
4382 // we can't show any Jws2 services
4383 // if there are services available, show them - regardless of
4384 // the 'show JWS2 preference'
4385 // if the discoverer is running then say so
4386 // otherwise offer to trigger discovery if 'show JWS2' is not
4388 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4389 if (jws2servs != null)
4391 if (jws2servs.hasServices())
4393 jws2servs.attachWSMenuEntry(webService, me);
4394 for (Jws2Instance sv : jws2servs.getServices())
4396 if (sv.description.toLowerCase(Locale.ROOT)
4399 for (JMenuItem jmi : legacyItems)
4401 jmi.setVisible(false);
4407 if (jws2servs.isRunning())
4409 JMenuItem tm = new JMenuItem(
4410 "Still discovering JABA Services");
4411 tm.setEnabled(false);
4414 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4416 JMenuItem enableJws2 = new JMenuItem(
4417 "Discover Web Services");
4418 enableJws2.setToolTipText(
4419 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4420 enableJws2.setEnabled(true);
4421 enableJws2.addActionListener(new ActionListener()
4425 public void actionPerformed(ActionEvent e)
4427 // start service discoverer, but ignore preference
4428 Desktop.instance.startServiceDiscovery(false,
4432 webService.add(enableJws2);
4436 build_urlServiceMenu(me.webService);
4437 build_fetchdbmenu(webService);
4438 for (JMenu item : wsmenu)
4440 if (item.getItemCount() == 0)
4442 item.setEnabled(false);
4446 item.setEnabled(true);
4449 } catch (Exception e)
4452 "Exception during web service menu building process.",
4457 } catch (Exception e)
4460 buildingMenu = false;
4467 * construct any groupURL type service menu entries.
4471 protected void build_urlServiceMenu(JMenu webService)
4473 // TODO: remove this code when 2.7 is released
4474 // DEBUG - alignmentView
4476 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4477 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4479 * @Override public void actionPerformed(ActionEvent e) {
4480 * jalview.datamodel.AlignmentView
4481 * .testSelectionViews(af.viewport.getAlignment(),
4482 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4484 * }); webService.add(testAlView);
4486 // TODO: refactor to RestClient discoverer and merge menu entries for
4487 // rest-style services with other types of analysis/calculation service
4488 // SHmmr test client - still being implemented.
4489 // DEBUG - alignmentView
4491 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4494 client.attachWSMenuEntry(
4495 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4501 * Searches the alignment sequences for xRefs and builds the Show
4502 * Cross-References menu (formerly called Show Products), with database
4503 * sources for which cross-references are found (protein sources for a
4504 * nucleotide alignment and vice versa)
4506 * @return true if Show Cross-references menu should be enabled
4508 public boolean canShowProducts()
4510 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4511 AlignmentI dataset = viewport.getAlignment().getDataset();
4513 showProducts.removeAll();
4514 final boolean dna = viewport.getAlignment().isNucleotide();
4516 if (seqs == null || seqs.length == 0)
4518 // nothing to see here.
4522 boolean showp = false;
4525 List<String> ptypes = new CrossRef(seqs, dataset)
4526 .findXrefSourcesForSequences(dna);
4528 for (final String source : ptypes)
4531 final AlignFrame af = this;
4532 JMenuItem xtype = new JMenuItem(source);
4533 xtype.addActionListener(new ActionListener()
4536 public void actionPerformed(ActionEvent e)
4538 showProductsFor(af.viewport.getSequenceSelection(), dna,
4542 showProducts.add(xtype);
4544 showProducts.setVisible(showp);
4545 showProducts.setEnabled(showp);
4546 } catch (Exception e)
4549 "canShowProducts threw an exception - please report to help@jalview.org",
4557 * Finds and displays cross-references for the selected sequences (protein
4558 * products for nucleotide sequences, dna coding sequences for peptides).
4561 * the sequences to show cross-references for
4563 * true if from a nucleotide alignment (so showing proteins)
4565 * the database to show cross-references for
4567 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4568 final String source)
4570 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4575 * Construct and display a new frame containing the translation of this
4576 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4579 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4581 AlignmentI al = null;
4584 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4586 al = dna.translateCdna(codeTable);
4587 } catch (Exception ex)
4589 Console.error("Exception during translation. Please report this !",
4591 final String msg = MessageManager.getString(
4592 "label.error_when_translating_sequences_submit_bug_report");
4593 final String errorTitle = MessageManager
4594 .getString("label.implementation_error")
4595 + MessageManager.getString("label.translation_failed");
4596 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4597 JvOptionPane.ERROR_MESSAGE);
4600 if (al == null || al.getHeight() == 0)
4602 final String msg = MessageManager.getString(
4603 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4604 final String errorTitle = MessageManager
4605 .getString("label.translation_failed");
4606 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4607 JvOptionPane.WARNING_MESSAGE);
4611 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4612 af.setFileFormat(this.currentFileFormat);
4613 final String newTitle = MessageManager
4614 .formatMessage("label.translation_of_params", new Object[]
4615 { this.getTitle(), codeTable.getId() });
4616 af.setTitle(newTitle);
4617 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4619 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4620 viewport.openSplitFrame(af, new Alignment(seqs));
4624 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4631 * Set the file format
4635 public void setFileFormat(FileFormatI format)
4637 this.currentFileFormat = format;
4641 * Try to load a features file onto the alignment.
4644 * contents or path to retrieve file or a File object
4646 * access mode of file (see jalview.io.AlignFile)
4647 * @return true if features file was parsed correctly.
4649 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4652 return avc.parseFeaturesFile(file, sourceType,
4653 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4658 public void refreshFeatureUI(boolean enableIfNecessary)
4660 // note - currently this is only still here rather than in the controller
4661 // because of the featureSettings hard reference that is yet to be
4663 if (enableIfNecessary)
4665 viewport.setShowSequenceFeatures(true);
4666 showSeqFeatures.setSelected(true);
4672 public void dragEnter(DropTargetDragEvent evt)
4677 public void dragExit(DropTargetEvent evt)
4682 public void dragOver(DropTargetDragEvent evt)
4687 public void dropActionChanged(DropTargetDragEvent evt)
4692 public void drop(DropTargetDropEvent evt)
4694 // JAL-1552 - acceptDrop required before getTransferable call for
4695 // Java's Transferable for native dnd
4696 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4697 Transferable t = evt.getTransferable();
4699 final AlignFrame thisaf = this;
4700 final List<Object> files = new ArrayList<>();
4701 List<DataSourceType> protocols = new ArrayList<>();
4705 Desktop.transferFromDropTarget(files, protocols, evt, t);
4706 } catch (Exception e)
4708 e.printStackTrace();
4712 new Thread(new Runnable()
4719 // check to see if any of these files have names matching sequences
4722 SequenceIdMatcher idm = new SequenceIdMatcher(
4723 viewport.getAlignment().getSequencesArray());
4725 * Object[] { String,SequenceI}
4727 ArrayList<Object[]> filesmatched = new ArrayList<>();
4728 ArrayList<Object> filesnotmatched = new ArrayList<>();
4729 for (int i = 0; i < files.size(); i++)
4732 Object file = files.get(i);
4733 String fileName = file.toString();
4735 DataSourceType protocol = (file instanceof File
4736 ? DataSourceType.FILE
4737 : FormatAdapter.checkProtocol(fileName));
4738 if (protocol == DataSourceType.FILE)
4741 if (file instanceof File)
4744 Platform.cacheFileData(fl);
4748 fl = new File(fileName);
4750 pdbfn = fl.getName();
4752 else if (protocol == DataSourceType.URL)
4754 URL url = new URL(fileName);
4755 pdbfn = url.getFile();
4757 if (pdbfn.length() > 0)
4759 // attempt to find a match in the alignment
4760 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4761 int l = 0, c = pdbfn.indexOf(".");
4762 while (mtch == null && c != -1)
4767 } while ((c = pdbfn.indexOf(".", l)) > l);
4770 pdbfn = pdbfn.substring(0, l);
4772 mtch = idm.findAllIdMatches(pdbfn);
4779 type = new IdentifyFile().identify(file, protocol);
4780 } catch (Exception ex)
4784 if (type != null && type.isStructureFile())
4786 filesmatched.add(new Object[] { file, protocol, mtch });
4790 // File wasn't named like one of the sequences or wasn't a PDB
4792 filesnotmatched.add(file);
4796 if (filesmatched.size() > 0)
4798 boolean autoAssociate = Cache
4799 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4802 String msg = MessageManager.formatMessage(
4803 "label.automatically_associate_structure_files_with_sequences_same_name",
4805 { Integer.valueOf(filesmatched.size())
4807 String ttl = MessageManager.getString(
4808 "label.automatically_associate_structure_files_by_name");
4809 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4810 ttl, JvOptionPane.YES_NO_OPTION);
4811 autoAssociate = choice == JvOptionPane.YES_OPTION;
4815 for (Object[] fm : filesmatched)
4817 // try and associate
4818 // TODO: may want to set a standard ID naming formalism for
4819 // associating PDB files which have no IDs.
4820 for (SequenceI toassoc : (SequenceI[]) fm[2])
4822 PDBEntry pe = new AssociatePdbFileWithSeq()
4823 .associatePdbWithSeq(fm[0].toString(),
4824 (DataSourceType) fm[1], toassoc, false,
4828 System.err.println("Associated file : "
4829 + (fm[0].toString()) + " with "
4830 + toassoc.getDisplayId(true));
4834 // TODO: do we need to update overview ? only if features are
4836 alignPanel.paintAlignment(true, false);
4842 * add declined structures as sequences
4844 for (Object[] o : filesmatched)
4846 filesnotmatched.add(o[0]);
4850 if (filesnotmatched.size() > 0)
4852 if (assocfiles > 0 && (Cache.getDefault(
4853 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4854 || JvOptionPane.showConfirmDialog(thisaf,
4855 "<html>" + MessageManager.formatMessage(
4856 "label.ignore_unmatched_dropped_files_info",
4859 filesnotmatched.size())
4862 MessageManager.getString(
4863 "label.ignore_unmatched_dropped_files"),
4864 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4868 for (Object fn : filesnotmatched)
4870 loadJalviewDataFile(fn, null, null, null);
4874 } catch (Exception ex)
4876 ex.printStackTrace();
4884 * Attempt to load a "dropped" file or URL string, by testing in turn for
4886 * <li>an Annotation file</li>
4887 * <li>a JNet file</li>
4888 * <li>a features file</li>
4889 * <li>else try to interpret as an alignment file</li>
4893 * either a filename or a URL string.
4895 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4896 FileFormatI format, SequenceI assocSeq)
4898 // BH 2018 was String file
4901 if (sourceType == null)
4903 sourceType = FormatAdapter.checkProtocol(file);
4905 // if the file isn't identified, or not positively identified as some
4906 // other filetype (PFAM is default unidentified alignment file type) then
4907 // try to parse as annotation.
4908 boolean isAnnotation = (format == null
4909 || FileFormat.Pfam.equals(format))
4910 ? new AnnotationFile().annotateAlignmentView(viewport,
4916 // first see if its a T-COFFEE score file
4917 TCoffeeScoreFile tcf = null;
4920 tcf = new TCoffeeScoreFile(file, sourceType);
4923 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4927 new TCoffeeColourScheme(viewport.getAlignment()));
4928 isAnnotation = true;
4929 setStatus(MessageManager.getString(
4930 "label.successfully_pasted_tcoffee_scores_to_alignment"));
4934 // some problem - if no warning its probable that the ID matching
4935 // process didn't work
4936 JvOptionPane.showMessageDialog(Desktop.desktop,
4937 tcf.getWarningMessage() == null
4938 ? MessageManager.getString(
4939 "label.check_file_matches_sequence_ids_alignment")
4940 : tcf.getWarningMessage(),
4941 MessageManager.getString(
4942 "label.problem_reading_tcoffee_score_file"),
4943 JvOptionPane.WARNING_MESSAGE);
4950 } catch (Exception x)
4953 "Exception when processing data source as T-COFFEE score file",
4959 // try to see if its a JNet 'concise' style annotation file *before*
4961 // try to parse it as a features file
4964 format = new IdentifyFile().identify(file, sourceType);
4966 if (FileFormat.ScoreMatrix == format)
4968 ScoreMatrixFile sm = new ScoreMatrixFile(
4969 new FileParse(file, sourceType));
4971 // todo: i18n this message
4972 setStatus(MessageManager.formatMessage(
4973 "label.successfully_loaded_matrix",
4974 sm.getMatrixName()));
4976 else if (FileFormat.Jnet.equals(format))
4978 JPredFile predictions = new JPredFile(file, sourceType);
4979 new JnetAnnotationMaker();
4980 JnetAnnotationMaker.add_annotation(predictions,
4981 viewport.getAlignment(), 0, false);
4982 viewport.getAlignment().setupJPredAlignment();
4983 isAnnotation = true;
4985 // else if (IdentifyFile.FeaturesFile.equals(format))
4986 else if (FileFormat.Features.equals(format))
4988 if (parseFeaturesFile(file, sourceType))
4990 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
4991 if (splitFrame != null)
4993 splitFrame.repaint();
4997 alignPanel.paintAlignment(true, true);
5003 new FileLoader().LoadFile(viewport, file, sourceType, format);
5010 alignPanel.adjustAnnotationHeight();
5011 viewport.updateSequenceIdColours();
5012 buildSortByAnnotationScoresMenu();
5013 alignPanel.paintAlignment(true, true);
5015 } catch (Exception ex)
5017 ex.printStackTrace();
5018 } catch (OutOfMemoryError oom)
5023 } catch (Exception x)
5028 + (sourceType != null
5029 ? (sourceType == DataSourceType.PASTE
5031 : "using " + sourceType + " from "
5035 ? "(parsing as '" + format + "' file)"
5037 oom, Desktop.desktop);
5042 * Method invoked by the ChangeListener on the tabbed pane, in other words
5043 * when a different tabbed pane is selected by the user or programmatically.
5046 public void tabSelectionChanged(int index)
5051 * update current Overview window title (if there is one)
5052 * to add view name "Original" if necessary
5054 alignPanel.setOverviewTitle(this);
5057 * switch panels and set Overview title (if there is one
5058 * because it was opened automatically)
5060 alignPanel = alignPanels.get(index);
5061 alignPanel.setOverviewTitle(this);
5063 viewport = alignPanel.av;
5064 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5065 setMenusFromViewport(viewport);
5066 if (featureSettings != null && featureSettings.isOpen()
5067 && featureSettings.fr.getViewport() != viewport)
5069 if (viewport.isShowSequenceFeatures())
5071 // refresh the featureSettings to reflect UI change
5072 showFeatureSettingsUI();
5076 // close feature settings for this view.
5077 featureSettings.close();
5084 * 'focus' any colour slider that is open to the selected viewport
5086 if (viewport.getConservationSelected())
5088 SliderPanel.setConservationSlider(alignPanel,
5089 viewport.getResidueShading(), alignPanel.getViewName());
5093 SliderPanel.hideConservationSlider();
5095 if (viewport.getAbovePIDThreshold())
5097 SliderPanel.setPIDSliderSource(alignPanel,
5098 viewport.getResidueShading(), alignPanel.getViewName());
5102 SliderPanel.hidePIDSlider();
5106 * If there is a frame linked to this one in a SplitPane, switch it to the
5107 * same view tab index. No infinite recursion of calls should happen, since
5108 * tabSelectionChanged() should not get invoked on setting the selected
5109 * index to an unchanged value. Guard against setting an invalid index
5110 * before the new view peer tab has been created.
5112 final AlignViewportI peer = viewport.getCodingComplement();
5115 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5116 .getAlignPanel().alignFrame;
5117 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5119 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5125 * On right mouse click on view tab, prompt for and set new view name.
5128 public void tabbedPane_mousePressed(MouseEvent e)
5130 if (e.isPopupTrigger())
5132 String msg = MessageManager.getString("label.enter_view_name");
5133 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5134 String reply = JvOptionPane.showInputDialog(msg, ttl);
5138 viewport.setViewName(reply);
5139 // TODO warn if reply is in getExistingViewNames()?
5140 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5145 public AlignViewport getCurrentView()
5151 * Open the dialog for regex description parsing.
5154 protected void extractScores_actionPerformed(ActionEvent e)
5156 ParseProperties pp = new jalview.analysis.ParseProperties(
5157 viewport.getAlignment());
5158 // TODO: verify regex and introduce GUI dialog for version 2.5
5159 // if (pp.getScoresFromDescription("col", "score column ",
5160 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5162 if (pp.getScoresFromDescription("description column",
5163 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5165 buildSortByAnnotationScoresMenu();
5173 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5177 protected void showDbRefs_actionPerformed(ActionEvent e)
5179 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5185 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5189 protected void showNpFeats_actionPerformed(ActionEvent e)
5191 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5195 * find the viewport amongst the tabs in this alignment frame and close that
5200 public boolean closeView(AlignViewportI av)
5204 this.closeMenuItem_actionPerformed(false);
5207 Component[] comp = tabbedPane.getComponents();
5208 for (int i = 0; comp != null && i < comp.length; i++)
5210 if (comp[i] instanceof AlignmentPanel)
5212 if (((AlignmentPanel) comp[i]).av == av)
5215 closeView((AlignmentPanel) comp[i]);
5223 protected void build_fetchdbmenu(JMenu webService)
5225 // Temporary hack - DBRef Fetcher always top level ws entry.
5226 // TODO We probably want to store a sequence database checklist in
5227 // preferences and have checkboxes.. rather than individual sources selected
5229 final JMenu rfetch = new JMenu(
5230 MessageManager.getString("action.fetch_db_references"));
5231 rfetch.setToolTipText(MessageManager.getString(
5232 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5233 webService.add(rfetch);
5235 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5236 MessageManager.getString("option.trim_retrieved_seqs"));
5237 trimrs.setToolTipText(
5238 MessageManager.getString("label.trim_retrieved_sequences"));
5240 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5241 trimrs.addActionListener(new ActionListener()
5244 public void actionPerformed(ActionEvent e)
5246 trimrs.setSelected(trimrs.isSelected());
5247 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5248 Boolean.valueOf(trimrs.isSelected()).toString());
5252 JMenuItem fetchr = new JMenuItem(
5253 MessageManager.getString("label.standard_databases"));
5254 fetchr.setToolTipText(
5255 MessageManager.getString("label.fetch_embl_uniprot"));
5256 fetchr.addActionListener(new ActionListener()
5260 public void actionPerformed(ActionEvent e)
5262 new Thread(new Runnable()
5267 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5268 .getAlignment().isNucleotide();
5269 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5270 alignPanel.av.getSequenceSelection(),
5271 alignPanel.alignFrame, null,
5272 alignPanel.alignFrame.featureSettings, isNucleotide);
5273 dbRefFetcher.addListener(new FetchFinishedListenerI()
5276 public void finished()
5279 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5280 .getFeatureSettingsModels())
5283 alignPanel.av.mergeFeaturesStyle(srcSettings);
5285 AlignFrame.this.setMenusForViewport();
5288 dbRefFetcher.fetchDBRefs(false);
5296 new Thread(new Runnable()
5301 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5302 .getSequenceFetcherSingleton();
5303 javax.swing.SwingUtilities.invokeLater(new Runnable()
5308 String[] dbclasses = sf.getNonAlignmentSources();
5309 List<DbSourceProxy> otherdb;
5310 JMenu dfetch = new JMenu();
5311 JMenu ifetch = new JMenu();
5312 JMenuItem fetchr = null;
5313 int comp = 0, icomp = 0, mcomp = 15;
5314 String mname = null;
5316 for (String dbclass : dbclasses)
5318 otherdb = sf.getSourceProxy(dbclass);
5319 // add a single entry for this class, or submenu allowing 'fetch
5321 if (otherdb == null || otherdb.size() < 1)
5327 mname = "From " + dbclass;
5329 if (otherdb.size() == 1)
5331 final DbSourceProxy[] dassource = otherdb
5332 .toArray(new DbSourceProxy[0]);
5333 DbSourceProxy src = otherdb.get(0);
5334 fetchr = new JMenuItem(src.getDbSource());
5335 fetchr.addActionListener(new ActionListener()
5339 public void actionPerformed(ActionEvent e)
5341 new Thread(new Runnable()
5347 boolean isNucleotide = alignPanel.alignFrame
5348 .getViewport().getAlignment()
5350 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5351 alignPanel.av.getSequenceSelection(),
5352 alignPanel.alignFrame, dassource,
5353 alignPanel.alignFrame.featureSettings,
5356 .addListener(new FetchFinishedListenerI()
5359 public void finished()
5361 FeatureSettingsModelI srcSettings = dassource[0]
5362 .getFeatureColourScheme();
5363 alignPanel.av.mergeFeaturesStyle(
5365 AlignFrame.this.setMenusForViewport();
5368 dbRefFetcher.fetchDBRefs(false);
5374 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5375 MessageManager.formatMessage(
5376 "label.fetch_retrieve_from", new Object[]
5377 { src.getDbName() })));
5383 final DbSourceProxy[] dassource = otherdb
5384 .toArray(new DbSourceProxy[0]);
5386 DbSourceProxy src = otherdb.get(0);
5387 fetchr = new JMenuItem(MessageManager
5388 .formatMessage("label.fetch_all_param", new Object[]
5389 { src.getDbSource() }));
5390 fetchr.addActionListener(new ActionListener()
5393 public void actionPerformed(ActionEvent e)
5395 new Thread(new Runnable()
5401 boolean isNucleotide = alignPanel.alignFrame
5402 .getViewport().getAlignment()
5404 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5405 alignPanel.av.getSequenceSelection(),
5406 alignPanel.alignFrame, dassource,
5407 alignPanel.alignFrame.featureSettings,
5410 .addListener(new FetchFinishedListenerI()
5413 public void finished()
5415 AlignFrame.this.setMenusForViewport();
5418 dbRefFetcher.fetchDBRefs(false);
5424 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5425 MessageManager.formatMessage(
5426 "label.fetch_retrieve_from_all_sources",
5428 { Integer.valueOf(otherdb.size())
5430 src.getDbSource(), src.getDbName() })));
5433 // and then build the rest of the individual menus
5434 ifetch = new JMenu(MessageManager.formatMessage(
5435 "label.source_from_db_source", new Object[]
5436 { src.getDbSource() }));
5438 String imname = null;
5440 for (DbSourceProxy sproxy : otherdb)
5442 String dbname = sproxy.getDbName();
5443 String sname = dbname.length() > 5
5444 ? dbname.substring(0, 5) + "..."
5446 String msname = dbname.length() > 10
5447 ? dbname.substring(0, 10) + "..."
5451 imname = MessageManager
5452 .formatMessage("label.from_msname", new Object[]
5455 fetchr = new JMenuItem(msname);
5456 final DbSourceProxy[] dassrc = { sproxy };
5457 fetchr.addActionListener(new ActionListener()
5461 public void actionPerformed(ActionEvent e)
5463 new Thread(new Runnable()
5469 boolean isNucleotide = alignPanel.alignFrame
5470 .getViewport().getAlignment()
5472 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5473 alignPanel.av.getSequenceSelection(),
5474 alignPanel.alignFrame, dassrc,
5475 alignPanel.alignFrame.featureSettings,
5478 .addListener(new FetchFinishedListenerI()
5481 public void finished()
5483 AlignFrame.this.setMenusForViewport();
5486 dbRefFetcher.fetchDBRefs(false);
5492 fetchr.setToolTipText(
5493 "<html>" + MessageManager.formatMessage(
5494 "label.fetch_retrieve_from", new Object[]
5498 if (++icomp >= mcomp || i == (otherdb.size()))
5500 ifetch.setText(MessageManager.formatMessage(
5501 "label.source_to_target", imname, sname));
5503 ifetch = new JMenu();
5511 if (comp >= mcomp || dbi >= (dbclasses.length))
5513 dfetch.setText(MessageManager.formatMessage(
5514 "label.source_to_target", mname, dbclass));
5516 dfetch = new JMenu();
5529 * Left justify the whole alignment.
5532 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5534 AlignmentI al = viewport.getAlignment();
5536 viewport.firePropertyChange("alignment", null, al);
5540 * Right justify the whole alignment.
5543 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5545 AlignmentI al = viewport.getAlignment();
5547 viewport.firePropertyChange("alignment", null, al);
5551 public void setShowSeqFeatures(boolean b)
5553 showSeqFeatures.setSelected(b);
5554 viewport.setShowSequenceFeatures(b);
5561 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5562 * awt.event.ActionEvent)
5565 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5567 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5568 alignPanel.paintAlignment(false, false);
5575 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5579 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5581 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5582 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5590 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5591 * .event.ActionEvent)
5594 protected void showGroupConservation_actionPerformed(ActionEvent e)
5596 viewport.setShowGroupConservation(showGroupConservation.getState());
5597 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5604 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5605 * .event.ActionEvent)
5608 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5610 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5611 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5618 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5619 * .event.ActionEvent)
5622 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5624 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5625 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5629 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5631 showSequenceLogo.setState(true);
5632 viewport.setShowSequenceLogo(true);
5633 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5634 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5638 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5640 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5647 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5648 * .event.ActionEvent)
5651 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5653 if (avc.makeGroupsFromSelection())
5655 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5656 alignPanel.updateAnnotation();
5657 alignPanel.paintAlignment(true,
5658 viewport.needToUpdateStructureViews());
5662 public void clearAlignmentSeqRep()
5664 // TODO refactor alignmentseqrep to controller
5665 if (viewport.getAlignment().hasSeqrep())
5667 viewport.getAlignment().setSeqrep(null);
5668 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5669 alignPanel.updateAnnotation();
5670 alignPanel.paintAlignment(true, true);
5675 protected void createGroup_actionPerformed(ActionEvent e)
5677 if (avc.createGroup())
5679 if (applyAutoAnnotationSettings.isSelected())
5681 alignPanel.updateAnnotation(true, false);
5683 alignPanel.alignmentChanged();
5688 protected void unGroup_actionPerformed(ActionEvent e)
5692 alignPanel.alignmentChanged();
5697 * make the given alignmentPanel the currently selected tab
5699 * @param alignmentPanel
5701 public void setDisplayedView(AlignmentPanel alignmentPanel)
5703 if (!viewport.getSequenceSetId()
5704 .equals(alignmentPanel.av.getSequenceSetId()))
5706 throw new Error(MessageManager.getString(
5707 "error.implementation_error_cannot_show_view_alignment_frame"));
5709 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5710 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5712 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5717 * Action on selection of menu options to Show or Hide annotations.
5720 * @param forSequences
5721 * update sequence-related annotations
5722 * @param forAlignment
5723 * update non-sequence-related annotations
5726 public void setAnnotationsVisibility(boolean visible,
5727 boolean forSequences, boolean forAlignment)
5729 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5730 .getAlignmentAnnotation();
5735 for (AlignmentAnnotation aa : anns)
5738 * don't display non-positional annotations on an alignment
5740 if (aa.annotations == null)
5744 boolean apply = (aa.sequenceRef == null && forAlignment)
5745 || (aa.sequenceRef != null && forSequences);
5748 aa.visible = visible;
5751 alignPanel.validateAnnotationDimensions(true);
5752 alignPanel.alignmentChanged();
5756 * Store selected annotation sort order for the view and repaint.
5759 protected void sortAnnotations_actionPerformed()
5761 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5763 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5764 alignPanel.paintAlignment(false, false);
5769 * @return alignment panels in this alignment frame
5771 public List<? extends AlignmentViewPanel> getAlignPanels()
5773 // alignPanels is never null
5774 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5779 * Open a new alignment window, with the cDNA associated with this (protein)
5780 * alignment, aligned as is the protein.
5782 protected void viewAsCdna_actionPerformed()
5784 // TODO no longer a menu action - refactor as required
5785 final AlignmentI alignment = getViewport().getAlignment();
5786 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5787 if (mappings == null)
5791 List<SequenceI> cdnaSeqs = new ArrayList<>();
5792 for (SequenceI aaSeq : alignment.getSequences())
5794 for (AlignedCodonFrame acf : mappings)
5796 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5800 * There is a cDNA mapping for this protein sequence - add to new
5801 * alignment. It will share the same dataset sequence as other mapped
5802 * cDNA (no new mappings need to be created).
5804 final Sequence newSeq = new Sequence(dnaSeq);
5805 newSeq.setDatasetSequence(dnaSeq);
5806 cdnaSeqs.add(newSeq);
5810 if (cdnaSeqs.size() == 0)
5812 // show a warning dialog no mapped cDNA
5815 AlignmentI cdna = new Alignment(
5816 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5817 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5818 AlignFrame.DEFAULT_HEIGHT);
5819 cdna.alignAs(alignment);
5820 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5822 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5823 AlignFrame.DEFAULT_HEIGHT);
5827 * Set visibility of dna/protein complement view (available when shown in a
5833 protected void showComplement_actionPerformed(boolean show)
5835 SplitContainerI sf = getSplitViewContainer();
5838 sf.setComplementVisible(this, show);
5843 * Generate the reverse (optionally complemented) of the selected sequences,
5844 * and add them to the alignment
5847 protected void showReverse_actionPerformed(boolean complement)
5849 AlignmentI al = null;
5852 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5853 al = dna.reverseCdna(complement);
5854 viewport.addAlignment(al, "");
5855 addHistoryItem(new EditCommand(
5856 MessageManager.getString("label.add_sequences"), Action.PASTE,
5857 al.getSequencesArray(), 0, al.getWidth(),
5858 viewport.getAlignment()));
5859 } catch (Exception ex)
5861 System.err.println(ex.getMessage());
5867 * Try to run a script in the Groovy console, having first ensured that this
5868 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5869 * be targeted at this alignment.
5872 protected void runGroovy_actionPerformed()
5874 Jalview.setCurrentAlignFrame(this);
5875 groovy.ui.Console console = Desktop.getGroovyConsole();
5876 if (console != null)
5880 console.runScript();
5881 } catch (Exception ex)
5883 System.err.println((ex.toString()));
5884 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5885 MessageManager.getString("label.couldnt_run_groovy_script"),
5886 MessageManager.getString("label.groovy_support_failed"),
5887 JvOptionPane.ERROR_MESSAGE);
5892 System.err.println("Can't run Groovy script as console not found");
5897 * Hides columns containing (or not containing) a specified feature, provided
5898 * that would not leave all columns hidden
5900 * @param featureType
5901 * @param columnsContaining
5904 public boolean hideFeatureColumns(String featureType,
5905 boolean columnsContaining)
5907 boolean notForHiding = avc.markColumnsContainingFeatures(
5908 columnsContaining, false, false, featureType);
5911 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5912 false, featureType))
5914 getViewport().hideSelectedColumns();
5922 protected void selectHighlightedColumns_actionPerformed(
5923 ActionEvent actionEvent)
5925 // include key modifier check in case user selects from menu
5926 avc.markHighlightedColumns(
5927 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5928 (actionEvent.getModifiers() & (ActionEvent.META_MASK
5929 | ActionEvent.CTRL_MASK)) != 0);
5933 protected void copyHighlightedColumns_actionPerformed(
5934 ActionEvent actionEvent)
5936 avc.copyHighlightedRegionsToClipboard();
5940 * Rebuilds the Colour menu, including any user-defined colours which have
5941 * been loaded either on startup or during the session
5943 public void buildColourMenu()
5945 colourMenu.removeAll();
5947 colourMenu.add(applyToAllGroups);
5948 colourMenu.add(textColour);
5949 colourMenu.addSeparator();
5951 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
5952 viewport.getAlignment(), false);
5954 colourMenu.add(annotationColour);
5955 bg.add(annotationColour);
5956 colourMenu.addSeparator();
5957 colourMenu.add(conservationMenuItem);
5958 colourMenu.add(modifyConservation);
5959 colourMenu.add(abovePIDThreshold);
5960 colourMenu.add(modifyPID);
5962 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
5963 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
5967 * Open a dialog (if not already open) that allows the user to select and
5968 * calculate PCA or Tree analysis
5970 protected void openTreePcaDialog()
5972 if (alignPanel.getCalculationDialog() == null)
5974 new CalculationChooser(AlignFrame.this);
5979 protected void loadVcf_actionPerformed()
5981 JalviewFileChooser chooser = new JalviewFileChooser(
5982 Cache.getProperty("LAST_DIRECTORY"));
5983 chooser.setFileView(new JalviewFileView());
5984 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
5985 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
5986 final AlignFrame us = this;
5987 chooser.setResponseHandler(0, () -> {
5988 String choice = chooser.getSelectedFile().getPath();
5989 Cache.setProperty("LAST_DIRECTORY", choice);
5990 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
5991 new VCFLoader(choice).loadVCF(seqs, us);
5994 chooser.showOpenDialog(null);
5998 private Rectangle lastFeatureSettingsBounds = null;
6001 public void setFeatureSettingsGeometry(Rectangle bounds)
6003 lastFeatureSettingsBounds = bounds;
6007 public Rectangle getFeatureSettingsGeometry()
6009 return lastFeatureSettingsBounds;
6014 class PrintThread extends Thread
6018 public PrintThread(AlignmentPanel ap)
6023 static PageFormat pf;
6028 PrinterJob printJob = PrinterJob.getPrinterJob();
6032 printJob.setPrintable(ap, pf);
6036 printJob.setPrintable(ap);
6039 if (printJob.printDialog())
6044 } catch (Exception PrintException)
6046 PrintException.printStackTrace();